Skip to content

Commit

Permalink
main 🧊 add elemnt size, add doc for use key pressed event
Browse files Browse the repository at this point in the history
  • Loading branch information
babin committed Dec 7, 2024
1 parent 963be1b commit 3cee6ac
Show file tree
Hide file tree
Showing 12 changed files with 736 additions and 293 deletions.
10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,16 +67,16 @@
"screenfull": "^6.0.2"
},
"devDependencies": {
"@siberiacancode/builder": "^1.3.16",
"@siberiacancode/eslint": "^2.5.2",
"@siberiacancode/builder": "^1.3.17",
"@siberiacancode/eslint": "^2.6.0",
"@siberiacancode/prettier": "^1.1.1",
"@siberiacancode/vitest": "^1.2.4",
"@testing-library/dom": "^10.4.0",
"@testing-library/react": "^16.0.1",
"@types/doctrine": "^0.0.9",
"@types/node": "^22.9.1",
"@types/react": "^18.3.12",
"@types/react-dom": "^18.3.1",
"@types/react-dom": "^18.3.2",
"comment-parser": "^1.4.1",
"core-js": "^3.39.0",
"doctrine": "^3.0.0",
Expand All @@ -86,8 +86,8 @@
"react": "^18.3.1",
"react-dom": "^18.3.1",
"shx": "^0.3.4",
"typescript": "^5.6.3",
"vite": "^5.4.11",
"typescript": "^5.7.2",
"vite": "^6.0.3",
"vitepress": "^1.5.0"
},
"lint-staged": {
Expand Down
1 change: 1 addition & 0 deletions src/hooks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export * from './useDisclosure/useDisclosure';
export * from './useDocumentEvent/useDocumentEvent';
export * from './useDocumentTitle/useDocumentTitle';
export * from './useDocumentVisibility/useDocumentVisibility';
export * from './useElementSize/useElementSize';
export * from './useEvent/useEvent';
export * from './useEventListener/useEventListener';
export * from './useEyeDropper/useEyeDropper';
Expand Down
2 changes: 1 addition & 1 deletion src/hooks/useActiveElement/useActiveElement.demo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const Demo = () => {
<>
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '5px' }}>
{Array.from({ length: 6 }, (_, i) => i + 1).map((id) => (
<input key={id} data-id={String(id)} placeholder={String(id)} type='text' />
<input key={id} data-id={String(id)} type='text' placeholder={String(id)} />
))}
</div>

Expand Down
8 changes: 2 additions & 6 deletions src/hooks/useElementSize/useElementSize.demo.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
import type { CSSProperties } from 'react';

import { useRef } from 'react';

import { useElementSize } from './useElementSize';

const Demo = () => {
const element = useRef<HTMLTextAreaElement>(null);

const { height, width } = useElementSize(element);
const elementSize = useElementSize<HTMLTextAreaElement>();

const containerStyle: CSSProperties = {
display: 'flex',
Expand All @@ -24,7 +20,7 @@ const Demo = () => {
return (
<div style={containerStyle}>
<span>Resize the box to see changes</span>
<textarea ref={element} style={textareaStyle} value={`width: ${width}\nheight: ${height}`} />
<textarea ref={elementSize.ref} style={textareaStyle} value={`width: ${elementSize.value.width}\nheight: ${elementSize.value.height}`} />
</div>
);
};
Expand Down
75 changes: 54 additions & 21 deletions src/hooks/useElementSize/useElementSize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,50 +2,83 @@ import type { RefObject } from 'react';

import { useEffect, useState } from 'react';

import { getElement } from '@/utils/helpers';

interface ElementSize {
height: number;
width: number;
}

type UseElementSizeTarget = RefObject<Element>;
/** The use element size target element type */
export type UseElementSizeTarget =
| (() => Element)
| Element
| RefObject<Element | null | undefined>;

export interface UseElementSizeReturn {
value: ElementSize;
}

export interface UseElementSize {
<Target extends UseElementSizeTarget>(
target: Target,
initialSize?: ElementSize
): UseElementSizeReturn;

type UseElementSizeReturn = ElementSize;
<Target extends UseElementSizeTarget>(
initialSize?: ElementSize,
target?: never
): { ref: (node: Target) => void } & UseElementSizeReturn;
}

/**
* @name useElementSize
* @description - Hook that returns the width and height of the element
* @description - Hook that observes and returns the width and height of element
* @category Elements
*
* @param {UseElementSizeTarget} target The target element to observe
* @param {ElementSize} [initialSize] The initial size of the element
* @returns {UseElementSizeReturn} An object containing the width and height of the element
* @overload
* @template Target The target element type.
* @param {UseElementSizeTarget} target The target element to observe.
* @param {ElementSize} [initialSize = { width: 0, height: 0 }]
* @returns {UseElementSizeReturn} An object containing the current width and height of the element.
*
* @example
* const { width, height } = useElementSize(elementRef);
* const { value } = useElementSize(elementRef);
*
* @overload
* @param {ElementSize} [initialSize = { width: 0, height: 0 }] The initial size of the element.
* @returns { { ref: (node: Target) => void } & UseElementSizeReturn } A reference function to attach to the element to observe size changes.
*
* @example
* const { ref, value } = useElementSize({ width: 100, height: 100 });
*/
export const useElementSize = (
target: UseElementSizeTarget,
initialSize: ElementSize = { height: 0, width: 0 }
): UseElementSizeReturn => {
const [width, setWidth] = useState(initialSize.width);
const [height, setHeight] = useState(initialSize.height);
export const useElementSize = ((...params: any[]) => {
const target = (typeof params[1] === 'undefined' ? undefined : params[0]) as
| UseElementSizeTarget
| undefined;

const initialSize = (target ? params[1] : params[0]) as ElementSize | undefined;

const [size, setSize] = useState(initialSize ?? { width: 0, height: 0 });
const [internalRef, setInternalRef] = useState<Element>();

useEffect(() => {
if (!target && !internalRef) return;
const element = (target ? getElement(target) : internalRef) as Element;

const observer = new ResizeObserver(([entry]) => {
const { inlineSize: width, blockSize: height } = entry.borderBoxSize[0];

setWidth(width);
setHeight(height);
setSize({ width, height });
});

if (target.current) {
observer.observe(target.current);
}
if (element) observer.observe(element);

return () => {
observer.disconnect();
};
}, [target]);
}, [internalRef, target]);

return { width, height };
};
if (target) return { value: size };
return { ref: setInternalRef, value: size };
}) as UseElementSize;
2 changes: 1 addition & 1 deletion src/hooks/useField/useField.demo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ const Demo = () => {

<div>
<input
placeholder='Name'
type='text'
placeholder='Name'
{...nameInput.register({
required: 'field is required',
minLength: {
Expand Down
2 changes: 1 addition & 1 deletion src/hooks/useKeyPressEvent/useKeyPressEvent.demo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const Demo = () => {
Press <code>Enter</code> key
</p>
<p>
Count of Enter key presses: <code>{counter.value}</code>
Count of key presses: <code>{counter.value}</code>
</p>
</div>
);
Expand Down
44 changes: 38 additions & 6 deletions src/hooks/useKeyPressEvent/useKeyPressEvent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,17 +39,49 @@ export interface UseKeyPressEvent {

/**
* @name useKeyPressEvent
* @description - Hook that listents for key press and execute callback function
* @description - Hook that listens for key press events on specified targets
* @category Sensors
*
* @param {UseKeyPressEventKey} key The key or array of keys to listen for
* @param {UseEventListenerTarget} [target=window] The target to attach the event listener to
* @param {(event: KeyboardEvent) => void} callback The callback function to be executed when the specified key or keys are pressed
* @param {UseEventListenerOptions} [options] The options for the event listener
* @overload
* @param {UseKeyPressEventKey} key The key or array of keys to listen for.
* @param {Window} target The window object to attach the event listener to.
* @param {(event: KeyboardEvent) => void} listener The callback function to be executed when the specified key or keys are pressed.
* @param {UseEventListenerOptions} [options] The options for the event listener.
* @returns {void}
*
* @example
* useKeyPressEvent('Enter', () => console.log('Enter key pressed'));
* useKeyPressEvent('Enter', window, () => console.log('Enter key pressed'));
*
* @overload
* @param {UseKeyPressEventKey} key The key or array of keys to listen for.
* @param {Document} target The document object to attach the event listener to.
* @param {(event: KeyboardEvent) => void} listener The callback function to be executed when the specified key or keys are pressed.
* @param {UseEventListenerOptions} [options] The options for the event listener.
* @returns {void}
*
* @example
* useKeyPressEvent('Enter', document, () => console.log('Enter key pressed'));
*
* @overload
* @template Target The target element type.
* @param {UseKeyPressEventKey} key The key or array of keys to listen for.
* @param {Target} target The target element to attach the event listener to.
* @param {(event: KeyboardEvent) => void} listener The callback function to be executed when the specified key or keys are pressed.
* @param {UseEventListenerOptions} [options] The options for the event listener.
* @returns {void}
*
* @example
* useKeyPressEvent('Enter', ref, () => console.log('Enter key pressed'));
*
* @overload
* @template Target extends Element
* @param {UseKeyPressEventKey} key The key or array of keys to listen for.
* @param {(event: KeyboardEvent) => void} listener The callback function to be executed when the specified key or keys are pressed.
* @param {UseEventListenerOptions} [options] The options for the event listener.
* @returns {void}
*
* @example
* useKeyPressEvent('Enter', (event) => console.log('Enter key pressed'));
*/
export const useKeyPressEvent = ((...params: any[]) => {
const keys = (Array.isArray(params[0]) ? params[0] : [params[0]]) as UseKeyPressEventKey;
Expand Down
2 changes: 1 addition & 1 deletion src/hooks/useLastChanged/useLastChanged.demo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ const Demo = () => {
return (
<div>
<input
placeholder='Type something...'
value={inputValue}
onChange={(event) => setInputValue(event.target.value)}
placeholder='Type something...'
/>
<p>Last changed: {value}</p>
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/hooks/useMap/useMap.demo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const Demo = () => {
<>
<div style={{ display: 'flex', gap: 8 }}>
<input placeholder='Name' {...nameInput.register()} />
<input placeholder='Age' type='number' {...ageInput.register()} />
<input type='number' placeholder='Age' {...ageInput.register()} />

<button
type='button'
Expand Down
2 changes: 1 addition & 1 deletion src/hooks/useSet/useSet.demo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ const Demo = () => {
<>
<div style={{ display: 'flex', gap: 8 }}>
<input
placeholder='Enter scope'
value={input}
onChange={(event) => setInput(event.currentTarget.value)}
placeholder='Enter scope'
/>

<button
Expand Down
Loading

0 comments on commit 3cee6ac

Please sign in to comment.