@vellira-ui/core 2.35.1 → 2.37.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/README.md +24 -2
  2. package/dist/behavior/focus/focusUtils.d.ts +4 -0
  3. package/dist/behavior/focus/focusUtils.d.ts.map +1 -0
  4. package/dist/behavior/focus/focusUtils.js +13 -0
  5. package/dist/behavior/focus/index.d.ts +3 -0
  6. package/dist/behavior/focus/index.d.ts.map +1 -0
  7. package/dist/behavior/focus/index.js +1 -0
  8. package/dist/behavior/focus/types.d.ts +20 -0
  9. package/dist/behavior/focus/types.d.ts.map +1 -0
  10. package/dist/behavior/focus/types.js +1 -0
  11. package/dist/behavior/index.d.ts +5 -0
  12. package/dist/behavior/index.d.ts.map +1 -0
  13. package/dist/behavior/index.js +4 -0
  14. package/dist/behavior/overlay/index.d.ts +2 -0
  15. package/dist/behavior/overlay/index.d.ts.map +1 -0
  16. package/dist/behavior/overlay/index.js +1 -0
  17. package/dist/behavior/overlay/types.d.ts +23 -0
  18. package/dist/behavior/overlay/types.d.ts.map +1 -0
  19. package/dist/behavior/overlay/types.js +1 -0
  20. package/dist/behavior/portal/index.d.ts +2 -0
  21. package/dist/behavior/portal/index.d.ts.map +1 -0
  22. package/dist/behavior/portal/index.js +1 -0
  23. package/dist/behavior/portal/types.d.ts +4 -0
  24. package/dist/behavior/portal/types.d.ts.map +1 -0
  25. package/dist/behavior/portal/types.js +1 -0
  26. package/dist/behavior/utils/events.d.ts +4 -0
  27. package/dist/behavior/utils/events.d.ts.map +1 -0
  28. package/dist/behavior/utils/events.js +23 -0
  29. package/dist/behavior/utils/index.d.ts +3 -0
  30. package/dist/behavior/utils/index.d.ts.map +1 -0
  31. package/dist/behavior/utils/index.js +1 -0
  32. package/dist/behavior/utils/types.d.ts +10 -0
  33. package/dist/behavior/utils/types.d.ts.map +1 -0
  34. package/dist/behavior/utils/types.js +1 -0
  35. package/dist/index.d.ts +1 -7
  36. package/dist/index.d.ts.map +1 -1
  37. package/dist/index.js +1 -7
  38. package/package.json +1 -8
  39. package/dist/useControllableState.d.ts +0 -8
  40. package/dist/useControllableState.d.ts.map +0 -1
  41. package/dist/useControllableState.js +0 -13
  42. package/dist/useDropdown.d.ts +0 -29
  43. package/dist/useDropdown.d.ts.map +0 -1
  44. package/dist/useDropdown.js +0 -99
  45. package/dist/useKeyboardNavigation.d.ts +0 -25
  46. package/dist/useKeyboardNavigation.d.ts.map +0 -1
  47. package/dist/useKeyboardNavigation.js +0 -127
  48. package/dist/useModal.d.ts +0 -18
  49. package/dist/useModal.d.ts.map +0 -1
  50. package/dist/useModal.js +0 -16
  51. package/dist/useSelect.d.ts +0 -42
  52. package/dist/useSelect.d.ts.map +0 -1
  53. package/dist/useSelect.js +0 -131
  54. package/dist/useTabs.d.ts +0 -11
  55. package/dist/useTabs.d.ts.map +0 -1
  56. package/dist/useTabs.js +0 -12
  57. package/dist/useTabsKeyboard.d.ts +0 -22
  58. package/dist/useTabsKeyboard.d.ts.map +0 -1
  59. package/dist/useTabsKeyboard.js +0 -79
package/README.md CHANGED
@@ -9,8 +9,30 @@ This package contains hooks that can be reused by web and native packages when t
9
9
  - `useControllableState`
10
10
  - `useKeyboardNavigation`
11
11
  - `useTabsKeyboard`
12
-
13
- Internal or experimental hooks are not exported from the package root until they are part of the supported public API.
12
+ - `useOverlayStack`
13
+ - `useOverlayDismiss`
14
+ - `useScrollLock`
15
+ - `useAriaIsolation`
16
+ - `useFocusScope`
17
+ - `usePortal`
18
+
19
+ Behavior hooks live under `src/behavior` internally and are exported from the package root when they are platform-neutral.
20
+
21
+ ```text
22
+ behavior/
23
+ overlay/
24
+ useOverlayStack
25
+ useOverlayDismiss
26
+ useScrollLock
27
+ focus/
28
+ useFocusScope
29
+ useAriaIsolation
30
+ portal/
31
+ usePortal
32
+ utils/
33
+ events
34
+ focusUtils
35
+ ```
14
36
 
15
37
  ## Usage
16
38
 
@@ -0,0 +1,4 @@
1
+ export declare const focusableSelector: string;
2
+ export declare const getFocusableElements: (content: HTMLElement) => HTMLElement[];
3
+ export declare const focusFirstElement: (content: HTMLElement) => void;
4
+ //# sourceMappingURL=focusUtils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"focusUtils.d.ts","sourceRoot":"","sources":["../../../src/behavior/focus/focusUtils.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,iBAAiB,QAOnB,CAAC;AAEZ,eAAO,MAAM,oBAAoB,GAAI,SAAS,WAAW,kBAGtD,CAAC;AAEJ,eAAO,MAAM,iBAAiB,GAAI,SAAS,WAAW,SAIrD,CAAC"}
@@ -0,0 +1,13 @@
1
+ export const focusableSelector = [
2
+ 'a[href]',
3
+ 'button:not([disabled])',
4
+ 'textarea:not([disabled])',
5
+ 'input:not([disabled])',
6
+ 'select:not([disabled])',
7
+ '[tabindex]:not([tabindex="-1"])',
8
+ ].join(',');
9
+ export const getFocusableElements = (content) => Array.from(content.querySelectorAll(focusableSelector)).filter((element) => !element.hasAttribute('disabled'));
10
+ export const focusFirstElement = (content) => {
11
+ const focusable = getFocusableElements(content);
12
+ (focusable[0] ?? content).focus();
13
+ };
@@ -0,0 +1,3 @@
1
+ export { focusableSelector, focusFirstElement, getFocusableElements, } from './focusUtils.js';
2
+ export type { AriaIsolationOptions, FocusScopeOptions, RefObjectLike, } from './types.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/behavior/focus/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,oBAAoB,GACrB,MAAM,iBAAiB,CAAC;AACzB,YAAY,EACV,oBAAoB,EACpB,iBAAiB,EACjB,aAAa,GACd,MAAM,YAAY,CAAC"}
@@ -0,0 +1 @@
1
+ export { focusableSelector, focusFirstElement, getFocusableElements, } from './focusUtils.js';
@@ -0,0 +1,20 @@
1
+ import type { OverlayAutoFocusEvent } from '../utils/types.js';
2
+ export type RefObjectLike<T> = {
3
+ current: T;
4
+ };
5
+ export type FocusScopeOptions = {
6
+ active: boolean;
7
+ contentRef: RefObjectLike<HTMLElement | null>;
8
+ enabled: boolean;
9
+ initialFocus?: RefObjectLike<HTMLElement | null>;
10
+ finalFocus?: RefObjectLike<HTMLElement | null>;
11
+ restoreFocus: boolean;
12
+ onOpenAutoFocus?: (event: OverlayAutoFocusEvent) => void;
13
+ onCloseAutoFocus?: (event: OverlayAutoFocusEvent) => void;
14
+ };
15
+ export type AriaIsolationOptions = {
16
+ active: boolean;
17
+ enabled: boolean;
18
+ content: HTMLElement | null;
19
+ };
20
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/behavior/focus/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAE/D,MAAM,MAAM,aAAa,CAAC,CAAC,IAAI;IAC7B,OAAO,EAAE,CAAC,CAAC;CACZ,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,MAAM,EAAE,OAAO,CAAC;IAChB,UAAU,EAAE,aAAa,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAC9C,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,CAAC,EAAE,aAAa,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IACjD,UAAU,CAAC,EAAE,aAAa,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAC/C,YAAY,EAAE,OAAO,CAAC;IACtB,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,qBAAqB,KAAK,IAAI,CAAC;IACzD,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,qBAAqB,KAAK,IAAI,CAAC;CAC3D,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC;CAC7B,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,5 @@
1
+ export * from './focus/index.js';
2
+ export * from './overlay/index.js';
3
+ export * from './portal/index.js';
4
+ export * from './utils/index.js';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/behavior/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AACnC,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC"}
@@ -0,0 +1,4 @@
1
+ export * from './focus/index.js';
2
+ export * from './overlay/index.js';
3
+ export * from './portal/index.js';
4
+ export * from './utils/index.js';
@@ -0,0 +1,2 @@
1
+ export type { OverlayDismissOptions, OverlayStackOptions, ScrollLockOptions, } from './types.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/behavior/overlay/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,qBAAqB,EACrB,mBAAmB,EACnB,iBAAiB,GAClB,MAAM,YAAY,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,23 @@
1
+ import type { RefObjectLike } from '../focus/types.js';
2
+ import type { OverlayOutsideEvent } from '../utils/types.js';
3
+ export type OverlayDismissOptions = {
4
+ active: boolean;
5
+ contentRef: RefObjectLike<HTMLElement | null>;
6
+ ignoreRefs?: Array<RefObjectLike<HTMLElement | null>>;
7
+ closeOnEscape: boolean;
8
+ closeOnOutsidePress: boolean;
9
+ isTopOverlay: () => boolean;
10
+ onEscapeKeyDown?: (event: KeyboardEvent) => void;
11
+ onPointerDownOutside?: (event: OverlayOutsideEvent) => void;
12
+ onInteractOutside?: (event: OverlayOutsideEvent) => void;
13
+ requestClose: () => void;
14
+ };
15
+ export type OverlayStackOptions = {
16
+ active: boolean;
17
+ id: string;
18
+ };
19
+ export type ScrollLockOptions = {
20
+ active: boolean;
21
+ enabled?: boolean;
22
+ };
23
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/behavior/overlay/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAE7D,MAAM,MAAM,qBAAqB,GAAG;IAClC,MAAM,EAAE,OAAO,CAAC;IAChB,UAAU,EAAE,aAAa,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAC9C,UAAU,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC,CAAC;IACtD,aAAa,EAAE,OAAO,CAAC;IACvB,mBAAmB,EAAE,OAAO,CAAC;IAC7B,YAAY,EAAE,MAAM,OAAO,CAAC;IAC5B,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IACjD,oBAAoB,CAAC,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI,CAAC;IAC5D,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI,CAAC;IACzD,YAAY,EAAE,MAAM,IAAI,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,MAAM,EAAE,OAAO,CAAC;IAChB,EAAE,EAAE,MAAM,CAAC;CACZ,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,2 @@
1
+ export type { PortalOptions } from './types.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/behavior/portal/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,4 @@
1
+ export type PortalOptions = {
2
+ container?: Element | DocumentFragment | null;
3
+ };
4
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/behavior/portal/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,aAAa,GAAG;IAC1B,SAAS,CAAC,EAAE,OAAO,GAAG,gBAAgB,GAAG,IAAI,CAAC;CAC/C,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,4 @@
1
+ import type { OverlayAutoFocusEvent, OverlayOutsideEvent } from './types.js';
2
+ export declare const createAutoFocusEvent: () => OverlayAutoFocusEvent;
3
+ export declare const createOutsideEvent: <TOriginalEvent>(originalEvent: TOriginalEvent) => OverlayOutsideEvent<TOriginalEvent>;
4
+ //# sourceMappingURL=events.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../../src/behavior/utils/events.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAE7E,eAAO,MAAM,oBAAoB,QAAO,qBAWvC,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,cAAc,EAC/C,eAAe,cAAc,KAC5B,mBAAmB,CAAC,cAAc,CAYpC,CAAC"}
@@ -0,0 +1,23 @@
1
+ export const createAutoFocusEvent = () => {
2
+ let defaultPrevented = false;
3
+ return {
4
+ preventDefault: () => {
5
+ defaultPrevented = true;
6
+ },
7
+ get defaultPrevented() {
8
+ return defaultPrevented;
9
+ },
10
+ };
11
+ };
12
+ export const createOutsideEvent = (originalEvent) => {
13
+ let defaultPrevented = false;
14
+ return {
15
+ originalEvent,
16
+ preventDefault: () => {
17
+ defaultPrevented = true;
18
+ },
19
+ get defaultPrevented() {
20
+ return defaultPrevented;
21
+ },
22
+ };
23
+ };
@@ -0,0 +1,3 @@
1
+ export { createAutoFocusEvent, createOutsideEvent } from './events.js';
2
+ export type { OverlayAutoFocusEvent, OverlayOutsideEvent } from './types.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/behavior/utils/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACvE,YAAY,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1 @@
1
+ export { createAutoFocusEvent, createOutsideEvent } from './events.js';
@@ -0,0 +1,10 @@
1
+ export type OverlayAutoFocusEvent = {
2
+ preventDefault: () => void;
3
+ readonly defaultPrevented: boolean;
4
+ };
5
+ export type OverlayOutsideEvent<TOriginalEvent = PointerEvent> = {
6
+ originalEvent: TOriginalEvent;
7
+ preventDefault: () => void;
8
+ readonly defaultPrevented: boolean;
9
+ };
10
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/behavior/utils/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,qBAAqB,GAAG;IAClC,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,QAAQ,CAAC,gBAAgB,EAAE,OAAO,CAAC;CACpC,CAAC;AAEF,MAAM,MAAM,mBAAmB,CAAC,cAAc,GAAG,YAAY,IAAI;IAC/D,aAAa,EAAE,cAAc,CAAC;IAC9B,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,QAAQ,CAAC,gBAAgB,EAAE,OAAO,CAAC;CACpC,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
package/dist/index.d.ts CHANGED
@@ -1,8 +1,2 @@
1
- export * from './useControllableState.js';
2
- export * from './useDropdown.js';
3
- export * from './useKeyboardNavigation.js';
4
- export * from './useModal.js';
5
- export * from './useSelect.js';
6
- export * from './useTabs.js';
7
- export * from './useTabsKeyboard.js';
1
+ export * from './behavior/index.js';
8
2
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,2BAA2B,CAAC;AAC1C,cAAc,kBAAkB,CAAC;AACjC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC"}
package/dist/index.js CHANGED
@@ -1,7 +1 @@
1
- export * from './useControllableState.js';
2
- export * from './useDropdown.js';
3
- export * from './useKeyboardNavigation.js';
4
- export * from './useModal.js';
5
- export * from './useSelect.js';
6
- export * from './useTabs.js';
7
- export * from './useTabsKeyboard.js';
1
+ export * from './behavior/index.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vellira-ui/core",
3
- "version": "2.35.1",
3
+ "version": "2.37.0",
4
4
  "description": "Shared logic and hooks for Vellira Design System",
5
5
  "author": "Roman Bakurov",
6
6
  "license": "MIT",
@@ -30,13 +30,6 @@
30
30
  "build": "pnpm run clean && tsc -p tsconfig.build.json",
31
31
  "typecheck": "tsc -p tsconfig.json --noEmit"
32
32
  },
33
- "peerDependencies": {
34
- "react": ">=18"
35
- },
36
- "devDependencies": {
37
- "@types/react": "^19.2.3",
38
- "react": "19.2.7"
39
- },
40
33
  "publishConfig": {
41
34
  "access": "public"
42
35
  }
@@ -1,8 +0,0 @@
1
- interface UseControllableStateProps<T> {
2
- value?: T;
3
- defaultValue: T;
4
- onChange?: (value: T) => void;
5
- }
6
- export declare const useControllableState: <T>({ value, defaultValue, onChange, }: UseControllableStateProps<T>) => readonly [T, (next: T) => void];
7
- export {};
8
- //# sourceMappingURL=useControllableState.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"useControllableState.d.ts","sourceRoot":"","sources":["../src/useControllableState.ts"],"names":[],"mappings":"AAKA,UAAU,yBAAyB,CAAC,CAAC;IACnC,KAAK,CAAC,EAAE,CAAC,CAAC;IACV,YAAY,EAAE,CAAC,CAAC;IAChB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,CAAC;CAC/B;AAED,eAAO,MAAM,oBAAoB,GAAI,CAAC,EAAE,oCAIrC,yBAAyB,CAAC,CAAC,CAAC,yBAQpB,CAAC,UAUX,CAAC"}
@@ -1,13 +0,0 @@
1
- import { useCallback, useState } from 'react';
2
- export const useControllableState = ({ value, defaultValue, onChange, }) => {
3
- const [internalValue, setInternalValue] = useState(defaultValue);
4
- const isControlled = value !== undefined;
5
- const currentValue = isControlled ? value : internalValue;
6
- const setValue = useCallback((next) => {
7
- if (!isControlled) {
8
- setInternalValue(next);
9
- }
10
- onChange?.(next);
11
- }, [isControlled, onChange]);
12
- return [currentValue, setValue];
13
- };
@@ -1,29 +0,0 @@
1
- import { type KeyboardNavigationEvent, type NavigableItem } from './useKeyboardNavigation.js';
2
- export interface UseDropdownParams<TItem extends NavigableItem> {
3
- items: TItem[];
4
- open?: boolean;
5
- defaultOpen?: boolean;
6
- disabled?: boolean;
7
- onOpenChange?: (open: boolean) => void;
8
- onSelect?: (value: string) => void;
9
- getItemValue: (item: TItem, index: number) => string;
10
- getItemText?: (item: TItem) => string;
11
- loop?: boolean;
12
- }
13
- export declare const useDropdown: <TItem extends NavigableItem>({ items, open, defaultOpen, disabled, onOpenChange, onSelect, getItemValue, getItemText, loop, }: UseDropdownParams<TItem>) => {
14
- activeIndex: number;
15
- setActiveIndex: import("react").Dispatch<import("react").SetStateAction<number>>;
16
- isOpen: boolean;
17
- open: boolean;
18
- setOpen: (nextOpen: boolean, initialIndex?: number) => void;
19
- openDropdown: (initialIndex?: number) => void;
20
- closeDropdown: () => void;
21
- toggleDropdown: () => void;
22
- selectItem: (item: TItem) => void;
23
- select: (item: TItem) => void;
24
- selectActiveItem: () => void;
25
- onKeyDown: (event: KeyboardNavigationEvent) => void;
26
- getFirstEnabledIndex: () => number;
27
- getLastEnabledIndex: () => number;
28
- };
29
- //# sourceMappingURL=useDropdown.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"useDropdown.d.ts","sourceRoot":"","sources":["../src/useDropdown.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,uBAAuB,EAC5B,KAAK,aAAa,EAEnB,MAAM,4BAA4B,CAAC;AAEpC,MAAM,WAAW,iBAAiB,CAAC,KAAK,SAAS,aAAa;IAC5D,KAAK,EAAE,KAAK,EAAE,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,YAAY,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IACrD,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,MAAM,CAAC;IACtC,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,eAAO,MAAM,WAAW,GAAI,KAAK,SAAS,aAAa,EAAE,kGAUtD,iBAAiB,CAAC,KAAK,CAAC;;;;;wBA6CZ,OAAO,iBAAiB,MAAM;;;;uBAsClC,KAAK;mBAAL,KAAK;;;;;CAgDf,CAAC"}
@@ -1,99 +0,0 @@
1
- import { useCallback, useEffect, useState } from 'react';
2
- import { useKeyboardNavigation, } from './useKeyboardNavigation.js';
3
- export const useDropdown = ({ items, open, defaultOpen = false, disabled = false, onOpenChange, onSelect, getItemValue, getItemText, loop = true, }) => {
4
- const [uncontrolledOpen, setUncontrolledOpen] = useState(defaultOpen);
5
- const [activeIndex, setActiveIndex] = useState(-1);
6
- const isControlled = open !== undefined;
7
- const isOpen = open ?? uncontrolledOpen;
8
- const getFirstEnabledIndex = useCallback(() => items.findIndex((item) => !item.disabled), [items]);
9
- const getLastEnabledIndex = useCallback(() => {
10
- for (let index = items.length - 1; index >= 0; index--) {
11
- if (!items[index]?.disabled) {
12
- return index;
13
- }
14
- }
15
- return -1;
16
- }, [items]);
17
- const syncActiveIndex = useCallback((nextOpen, initialIndex) => {
18
- if (nextOpen) {
19
- setActiveIndex((currentIndex) => {
20
- if (currentIndex >= 0 && !items[currentIndex]?.disabled) {
21
- return currentIndex;
22
- }
23
- return initialIndex ?? getFirstEnabledIndex();
24
- });
25
- return;
26
- }
27
- setActiveIndex(-1);
28
- }, [getFirstEnabledIndex, items]);
29
- useEffect(() => {
30
- syncActiveIndex(isOpen);
31
- }, [isOpen, syncActiveIndex]);
32
- const setOpen = useCallback((nextOpen, initialIndex) => {
33
- if (!isControlled) {
34
- setUncontrolledOpen(nextOpen);
35
- }
36
- onOpenChange?.(nextOpen);
37
- syncActiveIndex(nextOpen, initialIndex);
38
- }, [isControlled, onOpenChange, syncActiveIndex]);
39
- const openDropdown = useCallback((initialIndex = getFirstEnabledIndex()) => {
40
- if (disabled)
41
- return;
42
- setOpen(true, initialIndex);
43
- }, [disabled, getFirstEnabledIndex, setOpen]);
44
- const closeDropdown = useCallback(() => {
45
- if (!isOpen)
46
- return;
47
- setOpen(false);
48
- }, [isOpen, setOpen]);
49
- const toggleDropdown = useCallback(() => {
50
- if (disabled)
51
- return;
52
- if (isOpen) {
53
- setOpen(false);
54
- return;
55
- }
56
- openDropdown();
57
- }, [disabled, isOpen, openDropdown, setOpen]);
58
- const selectItem = useCallback((item) => {
59
- if (item.disabled)
60
- return;
61
- onSelect?.(getItemValue(item, items.indexOf(item)));
62
- closeDropdown();
63
- }, [closeDropdown, getItemValue, items, onSelect]);
64
- const selectActiveItem = useCallback(() => {
65
- const item = items[activeIndex];
66
- if (!item)
67
- return;
68
- selectItem(item);
69
- }, [activeIndex, items, selectItem]);
70
- const { onKeyDown } = useKeyboardNavigation({
71
- activeIndex,
72
- setActiveIndex,
73
- items,
74
- isOpen,
75
- onOpen: (event) => {
76
- openDropdown(event.key === 'ArrowUp' ? getLastEnabledIndex() : getFirstEnabledIndex());
77
- },
78
- onSelect: selectActiveItem,
79
- onClose: closeDropdown,
80
- getItemText,
81
- loop,
82
- });
83
- return {
84
- activeIndex,
85
- setActiveIndex,
86
- isOpen,
87
- open: isOpen,
88
- setOpen,
89
- openDropdown,
90
- closeDropdown,
91
- toggleDropdown,
92
- selectItem,
93
- select: selectItem,
94
- selectActiveItem,
95
- onKeyDown,
96
- getFirstEnabledIndex,
97
- getLastEnabledIndex,
98
- };
99
- };
@@ -1,25 +0,0 @@
1
- export interface NavigableItem {
2
- disabled?: boolean;
3
- }
4
- export interface KeyboardNavigationEvent {
5
- key: string;
6
- altKey?: boolean;
7
- ctrlKey?: boolean;
8
- metaKey?: boolean;
9
- preventDefault: () => void;
10
- }
11
- export interface UseKeyboardNavigationParams<TItem extends NavigableItem> {
12
- activeIndex: number;
13
- setActiveIndex: (index: number) => void;
14
- items: TItem[];
15
- isOpen: boolean;
16
- onOpen: (event: KeyboardNavigationEvent) => void;
17
- onSelect?: () => void;
18
- onClose?: () => void;
19
- getItemText?: (item: TItem) => string;
20
- loop?: boolean;
21
- }
22
- export declare const useKeyboardNavigation: <TItem extends NavigableItem>({ activeIndex, setActiveIndex, items, isOpen, onOpen, onSelect, onClose, getItemText, loop, }: UseKeyboardNavigationParams<TItem>) => {
23
- onKeyDown: (event: KeyboardNavigationEvent) => void;
24
- };
25
- //# sourceMappingURL=useKeyboardNavigation.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"useKeyboardNavigation.d.ts","sourceRoot":"","sources":["../src/useKeyboardNavigation.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,uBAAuB;IACtC,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,cAAc,EAAE,MAAM,IAAI,CAAC;CAC5B;AAED,MAAM,WAAW,2BAA2B,CAAC,KAAK,SAAS,aAAa;IACtE,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,KAAK,EAAE,KAAK,EAAE,CAAC;IACf,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,CAAC,KAAK,EAAE,uBAAuB,KAAK,IAAI,CAAC;IACjD,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,MAAM,CAAC;IACtC,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,eAAO,MAAM,qBAAqB,GAAI,KAAK,SAAS,aAAa,EAAE,+FAUhE,2BAA2B,CAAC,KAAK,CAAC;uBAiFzB,uBAAuB;CA6FlC,CAAC"}
@@ -1,127 +0,0 @@
1
- import { useCallback, useEffect, useRef } from 'react';
2
- export const useKeyboardNavigation = ({ activeIndex, setActiveIndex, items, isOpen, onOpen, onSelect, onClose, getItemText, loop = true, }) => {
3
- const searchRef = useRef({
4
- value: '',
5
- timeoutId: undefined,
6
- });
7
- useEffect(() => () => {
8
- if (searchRef.current.timeoutId) {
9
- clearTimeout(searchRef.current.timeoutId);
10
- }
11
- }, []);
12
- const getNextEnabledIndex = useCallback((current, direction) => {
13
- if (!items.length)
14
- return current;
15
- let index = current;
16
- for (let i = 0; i < items.length; i++) {
17
- const nextIndex = index + direction;
18
- if (!loop && (nextIndex < 0 || nextIndex >= items.length)) {
19
- return current;
20
- }
21
- index = (nextIndex + items.length) % items.length;
22
- if (!items[index]?.disabled) {
23
- return index;
24
- }
25
- }
26
- return current;
27
- }, [items, loop]);
28
- const getFirstEnabledIndex = useCallback(() => items.findIndex((item) => !item.disabled), [items]);
29
- const getLastEnabledIndex = useCallback(() => {
30
- for (let i = items.length - 1; i >= 0; i--) {
31
- if (!items[i].disabled) {
32
- return i;
33
- }
34
- }
35
- return -1;
36
- }, [items]);
37
- const getTypeaheadIndex = useCallback((query) => {
38
- if (!getItemText || !query)
39
- return -1;
40
- const normalizedQuery = query.toLocaleLowerCase();
41
- const startIndex = activeIndex >= 0 ? activeIndex + 1 : 0;
42
- for (let offset = 0; offset < items.length; offset++) {
43
- const index = (startIndex + offset) % items.length;
44
- const item = items[index];
45
- if (item &&
46
- !item.disabled &&
47
- getItemText(item).toLocaleLowerCase().startsWith(normalizedQuery)) {
48
- return index;
49
- }
50
- }
51
- return -1;
52
- }, [activeIndex, getItemText, items]);
53
- const onKeyDown = useCallback((event) => {
54
- if (!isOpen) {
55
- if (event.key === ' ' ||
56
- event.key === 'Enter' ||
57
- event.key === 'ArrowDown' ||
58
- event.key === 'ArrowUp') {
59
- event.preventDefault();
60
- onOpen(event);
61
- }
62
- return;
63
- }
64
- switch (event.key) {
65
- case 'ArrowDown':
66
- event.preventDefault();
67
- setActiveIndex(getNextEnabledIndex(activeIndex, 1));
68
- break;
69
- case 'ArrowUp':
70
- event.preventDefault();
71
- setActiveIndex(getNextEnabledIndex(activeIndex, -1));
72
- break;
73
- case 'Enter':
74
- case ' ':
75
- event.preventDefault();
76
- onSelect?.();
77
- break;
78
- case 'Escape':
79
- event.preventDefault();
80
- onClose?.();
81
- break;
82
- case 'Home':
83
- event.preventDefault();
84
- setActiveIndex(getFirstEnabledIndex());
85
- break;
86
- case 'End':
87
- event.preventDefault();
88
- setActiveIndex(getLastEnabledIndex());
89
- break;
90
- case 'Tab':
91
- onClose?.();
92
- break;
93
- default:
94
- if (event.key.length === 1 &&
95
- !event.altKey &&
96
- !event.ctrlKey &&
97
- !event.metaKey) {
98
- event.preventDefault();
99
- if (searchRef.current.timeoutId) {
100
- clearTimeout(searchRef.current.timeoutId);
101
- }
102
- searchRef.current.value += event.key;
103
- searchRef.current.timeoutId = setTimeout(() => {
104
- searchRef.current.value = '';
105
- searchRef.current.timeoutId = undefined;
106
- }, 700);
107
- const nextIndex = getTypeaheadIndex(searchRef.current.value);
108
- if (nextIndex >= 0) {
109
- setActiveIndex(nextIndex);
110
- }
111
- }
112
- break;
113
- }
114
- }, [
115
- activeIndex,
116
- isOpen,
117
- onOpen,
118
- onSelect,
119
- onClose,
120
- setActiveIndex,
121
- getNextEnabledIndex,
122
- getFirstEnabledIndex,
123
- getLastEnabledIndex,
124
- getTypeaheadIndex,
125
- ]);
126
- return { onKeyDown };
127
- };
@@ -1,18 +0,0 @@
1
- export interface UseModalParams {
2
- isOpen: boolean;
3
- onClose: () => void;
4
- closeOnBackdrop?: boolean;
5
- closeOnClick?: boolean;
6
- closeOnEsc?: boolean;
7
- }
8
- export declare const useModal: ({ isOpen, onClose, closeOnBackdrop, closeOnClick, closeOnEsc, }: UseModalParams) => {
9
- isOpen: boolean;
10
- open: boolean;
11
- shouldRender: boolean;
12
- onClose: () => void;
13
- closeOnBackdrop: boolean | undefined;
14
- closeOnEsc: boolean;
15
- titleId: string;
16
- descriptionId: string;
17
- };
18
- //# sourceMappingURL=useModal.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"useModal.d.ts","sourceRoot":"","sources":["../src/useModal.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,eAAO,MAAM,QAAQ,GAAI,iEAMtB,cAAc;;;;mBAZA,IAAI;;;;;CA2BpB,CAAC"}
package/dist/useModal.js DELETED
@@ -1,16 +0,0 @@
1
- import { useId } from 'react';
2
- export const useModal = ({ isOpen, onClose, closeOnBackdrop, closeOnClick, closeOnEsc = true, }) => {
3
- const titleId = useId();
4
- const descriptionId = useId();
5
- const resolvedCloseOnBackdrop = closeOnBackdrop ?? closeOnClick;
6
- return {
7
- isOpen,
8
- open: isOpen,
9
- shouldRender: isOpen,
10
- onClose,
11
- closeOnBackdrop: resolvedCloseOnBackdrop,
12
- closeOnEsc,
13
- titleId,
14
- descriptionId,
15
- };
16
- };
@@ -1,42 +0,0 @@
1
- import { type NavigableItem } from './useKeyboardNavigation.js';
2
- export interface SelectOptionLike extends NavigableItem {
3
- label: string;
4
- value: string;
5
- }
6
- export type SelectStateValue = string | string[];
7
- export interface UseSelectParams<TOption extends SelectOptionLike> {
8
- value?: SelectStateValue;
9
- defaultValue?: SelectStateValue;
10
- onValueChange?: (value: SelectStateValue) => void;
11
- /** @deprecated Use onValueChange. */
12
- onChange?: (value: SelectStateValue) => void;
13
- options: TOption[];
14
- multiple?: boolean;
15
- maxSelected?: number;
16
- closeOnSelect?: boolean;
17
- disabled?: boolean;
18
- open?: boolean;
19
- defaultOpen?: boolean;
20
- onOpenChange?: (open: boolean) => void;
21
- }
22
- export declare const useSelect: <TOption extends SelectOptionLike>({ value, defaultValue, onValueChange, onChange, options, multiple, maxSelected, closeOnSelect, disabled, open, defaultOpen, onOpenChange, }: UseSelectParams<TOption>) => {
23
- selectedValue: SelectStateValue;
24
- selectedValues: string[];
25
- setSelectedValue: (next: SelectStateValue) => void;
26
- selectedOption: TOption | undefined;
27
- selectedOptions: TOption[];
28
- isOpen: boolean;
29
- open: boolean;
30
- setIsOpen: (next: boolean) => void;
31
- activeIndex: number;
32
- setActiveIndex: import("react").Dispatch<import("react").SetStateAction<number>>;
33
- getInitialActiveIndex: () => number;
34
- openDropdown: () => void;
35
- closeDropdown: () => void;
36
- toggleDropdown: () => void;
37
- selectValue: (nextValue: string) => void;
38
- select: (nextValue: string) => void;
39
- selectActiveOption: () => void;
40
- onKeyDown: (event: import("./useKeyboardNavigation.js").KeyboardNavigationEvent) => void;
41
- };
42
- //# sourceMappingURL=useSelect.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"useSelect.d.ts","sourceRoot":"","sources":["../src/useSelect.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,KAAK,aAAa,EAEnB,MAAM,4BAA4B,CAAC;AAEpC,MAAM,WAAW,gBAAiB,SAAQ,aAAa;IACrD,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,MAAM,EAAE,CAAC;AAEjD,MAAM,WAAW,eAAe,CAAC,OAAO,SAAS,gBAAgB;IAC/D,KAAK,CAAC,EAAE,gBAAgB,CAAC;IACzB,YAAY,CAAC,EAAE,gBAAgB,CAAC;IAChC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAClD,qCAAqC;IACrC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAC7C,OAAO,EAAE,OAAO,EAAE,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;CACxC;AAED,eAAO,MAAM,SAAS,GAAI,OAAO,SAAS,gBAAgB,EAAE,6IAazD,eAAe,CAAC,OAAO,CAAC;;;;;;;;;;;;;;;6BAiFX,MAAM;wBAAN,MAAM;;;CAuFrB,CAAC"}
package/dist/useSelect.js DELETED
@@ -1,131 +0,0 @@
1
- import { useCallback, useEffect, useMemo, useState } from 'react';
2
- import { useControllableState } from './useControllableState.js';
3
- import { useKeyboardNavigation, } from './useKeyboardNavigation.js';
4
- export const useSelect = ({ value, defaultValue, onValueChange, onChange, options, multiple = false, maxSelected, closeOnSelect = !multiple, disabled = false, open, defaultOpen = false, onOpenChange, }) => {
5
- const [selectedValue, setSelectedValue] = useControllableState({
6
- value,
7
- defaultValue: defaultValue ?? (multiple ? [] : ''),
8
- onChange: onValueChange ?? onChange,
9
- });
10
- const [isOpen, setIsOpen] = useControllableState({
11
- value: open,
12
- defaultValue: defaultOpen,
13
- onChange: onOpenChange,
14
- });
15
- const [activeIndex, setActiveIndex] = useState(-1);
16
- const selectedValues = useMemo(() => Array.isArray(selectedValue)
17
- ? selectedValue
18
- : selectedValue
19
- ? [selectedValue]
20
- : [], [selectedValue]);
21
- const selectedOption = useMemo(() => options.find((option) => selectedValues.includes(option.value)), [options, selectedValues]);
22
- const selectedOptions = useMemo(() => options.filter((option) => selectedValues.includes(option.value)), [options, selectedValues]);
23
- const getInitialActiveIndex = useCallback(() => {
24
- const selectedIndex = options.findIndex((option) => selectedValues.includes(option.value) && !option.disabled);
25
- if (selectedIndex >= 0)
26
- return selectedIndex;
27
- return options.findIndex((option) => !option.disabled);
28
- }, [options, selectedValues]);
29
- const openDropdown = useCallback(() => {
30
- if (disabled)
31
- return;
32
- setActiveIndex(getInitialActiveIndex());
33
- setIsOpen(true);
34
- }, [disabled, getInitialActiveIndex, setIsOpen]);
35
- const closeDropdown = useCallback(() => {
36
- setIsOpen(false);
37
- }, [setIsOpen]);
38
- const toggleDropdown = useCallback(() => {
39
- if (disabled)
40
- return;
41
- if (isOpen) {
42
- closeDropdown();
43
- return;
44
- }
45
- openDropdown();
46
- }, [closeDropdown, disabled, isOpen, openDropdown]);
47
- useEffect(() => {
48
- if (!isOpen)
49
- return;
50
- setActiveIndex((currentIndex) => {
51
- const currentOption = options[currentIndex];
52
- if (currentOption && !currentOption.disabled) {
53
- return currentIndex;
54
- }
55
- return getInitialActiveIndex();
56
- });
57
- }, [getInitialActiveIndex, isOpen, options]);
58
- const selectValue = useCallback((nextValue) => {
59
- if (nextValue === '') {
60
- setSelectedValue(multiple ? [] : '');
61
- closeDropdown();
62
- return;
63
- }
64
- const nextOption = options.find((option) => option.value === nextValue);
65
- if (!nextOption || nextOption.disabled)
66
- return;
67
- if (multiple) {
68
- const isSelected = selectedValues.includes(nextValue);
69
- if (!isSelected &&
70
- typeof maxSelected === 'number' &&
71
- selectedValues.length >= maxSelected) {
72
- return;
73
- }
74
- const nextValues = selectedValues.includes(nextValue)
75
- ? selectedValues.filter((value) => value !== nextValue)
76
- : [...selectedValues, nextValue];
77
- setSelectedValue(nextValues);
78
- if (closeOnSelect) {
79
- closeDropdown();
80
- }
81
- return;
82
- }
83
- setSelectedValue(nextValue);
84
- setActiveIndex(options.indexOf(nextOption));
85
- closeDropdown();
86
- }, [
87
- closeDropdown,
88
- closeOnSelect,
89
- maxSelected,
90
- multiple,
91
- options,
92
- selectedValues,
93
- setSelectedValue,
94
- ]);
95
- const selectActiveOption = useCallback(() => {
96
- const activeOption = options[activeIndex];
97
- if (!activeOption)
98
- return;
99
- selectValue(activeOption.value);
100
- }, [activeIndex, options, selectValue]);
101
- const { onKeyDown } = useKeyboardNavigation({
102
- activeIndex,
103
- setActiveIndex,
104
- items: options,
105
- isOpen,
106
- onOpen: openDropdown,
107
- onClose: closeDropdown,
108
- onSelect: selectActiveOption,
109
- getItemText: (option) => option.label,
110
- });
111
- return {
112
- selectedValue,
113
- selectedValues,
114
- setSelectedValue,
115
- selectedOption,
116
- selectedOptions,
117
- isOpen,
118
- open: isOpen,
119
- setIsOpen,
120
- activeIndex,
121
- setActiveIndex,
122
- getInitialActiveIndex,
123
- openDropdown,
124
- closeDropdown,
125
- toggleDropdown,
126
- selectValue,
127
- select: selectValue,
128
- selectActiveOption,
129
- onKeyDown,
130
- };
131
- };
package/dist/useTabs.d.ts DELETED
@@ -1,11 +0,0 @@
1
- export interface UseTabsParams {
2
- activeIndex?: number;
3
- defaultActiveIndex?: number;
4
- onChange?: (index: number) => void;
5
- orientation?: 'horizontal' | 'vertical';
6
- }
7
- export declare const useTabs: ({ activeIndex: controlledActiveIndex, defaultActiveIndex, onChange, }: UseTabsParams) => {
8
- activeIndex: number;
9
- setActiveIndex: (next: number) => void;
10
- };
11
- //# sourceMappingURL=useTabs.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"useTabs.d.ts","sourceRoot":"","sources":["../src/useTabs.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,aAAa;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,WAAW,CAAC,EAAE,YAAY,GAAG,UAAU,CAAC;CACzC;AAED,eAAO,MAAM,OAAO,GAAI,uEAIrB,aAAa;;;CAWf,CAAC"}
package/dist/useTabs.js DELETED
@@ -1,12 +0,0 @@
1
- import { useControllableState } from './useControllableState.js';
2
- export const useTabs = ({ activeIndex: controlledActiveIndex, defaultActiveIndex = 0, onChange, }) => {
3
- const [activeIndex, setActiveIndex] = useControllableState({
4
- value: controlledActiveIndex,
5
- defaultValue: defaultActiveIndex,
6
- onChange,
7
- });
8
- return {
9
- activeIndex,
10
- setActiveIndex,
11
- };
12
- };
@@ -1,22 +0,0 @@
1
- import type { MutableRefObject } from 'react';
2
- export interface TabsKeyboardEvent {
3
- key: string;
4
- preventDefault: () => void;
5
- }
6
- export interface TabKeyboardItem {
7
- disabled?: boolean;
8
- props?: {
9
- disabled?: boolean;
10
- };
11
- }
12
- export interface UseTabsKeyboardParams<TItem extends TabKeyboardItem> {
13
- activeIndex: number;
14
- setActiveIndex: (index: number) => void;
15
- tabRefs: MutableRefObject<(TItem | null)[]>;
16
- orientation: 'horizontal' | 'vertical';
17
- onNavigate?: (index: number) => void;
18
- }
19
- export declare const useTabsKeyboard: <TItem extends TabKeyboardItem>({ activeIndex, setActiveIndex, tabRefs, orientation, onNavigate, }: UseTabsKeyboardParams<TItem>) => {
20
- onKeyDown: (event: TabsKeyboardEvent) => void;
21
- };
22
- //# sourceMappingURL=useTabsKeyboard.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"useTabsKeyboard.d.ts","sourceRoot":"","sources":["../src/useTabsKeyboard.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,OAAO,CAAC;AAE9C,MAAM,WAAW,iBAAiB;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,cAAc,EAAE,MAAM,IAAI,CAAC;CAC5B;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE;QACN,QAAQ,CAAC,EAAE,OAAO,CAAC;KACpB,CAAC;CACH;AAED,MAAM,WAAW,qBAAqB,CAAC,KAAK,SAAS,eAAe;IAClE,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,OAAO,EAAE,gBAAgB,CAAC,CAAC,KAAK,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC;IAC5C,WAAW,EAAE,YAAY,GAAG,UAAU,CAAC;IACvC,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACtC;AAED,eAAO,MAAM,eAAe,GAAI,KAAK,SAAS,eAAe,EAAE,oEAM5D,qBAAqB,CAAC,KAAK,CAAC;uBAEnB,iBAAiB;CAiG5B,CAAC"}
@@ -1,79 +0,0 @@
1
- import { useCallback } from 'react';
2
- export const useTabsKeyboard = ({ activeIndex, setActiveIndex, tabRefs, orientation = 'horizontal', onNavigate, }) => {
3
- const onKeyDown = useCallback((event) => {
4
- const isTabDisabled = (tab) => {
5
- return Boolean(tab?.disabled || tab?.props?.disabled);
6
- };
7
- const getNextEnabledIndex = (current, direction) => {
8
- const total = tabRefs.current.length;
9
- if (!total)
10
- return current;
11
- let index = current;
12
- for (let i = 0; i < total; i++) {
13
- index = (index + direction + total) % total;
14
- const tab = tabRefs.current[index];
15
- if (tab && !isTabDisabled(tab)) {
16
- return index;
17
- }
18
- }
19
- return current;
20
- };
21
- const getFirstEnabledIndex = () => {
22
- return tabRefs.current.findIndex((tab) => tab && !isTabDisabled(tab));
23
- };
24
- const getLastEnabledIndex = () => {
25
- for (let i = tabRefs.current.length - 1; i >= 0; i--) {
26
- const tab = tabRefs.current[i];
27
- if (tab && !isTabDisabled(tab)) {
28
- return i;
29
- }
30
- }
31
- return activeIndex;
32
- };
33
- let nextIndex = activeIndex;
34
- switch (event.key) {
35
- case 'ArrowLeft':
36
- if (orientation === 'horizontal') {
37
- event.preventDefault();
38
- nextIndex = getNextEnabledIndex(activeIndex, -1);
39
- }
40
- break;
41
- case 'ArrowRight':
42
- if (orientation === 'horizontal') {
43
- event.preventDefault();
44
- nextIndex = getNextEnabledIndex(activeIndex, 1);
45
- }
46
- break;
47
- case 'ArrowUp':
48
- if (orientation === 'vertical') {
49
- event.preventDefault();
50
- nextIndex = getNextEnabledIndex(activeIndex, -1);
51
- }
52
- break;
53
- case 'ArrowDown':
54
- if (orientation === 'vertical') {
55
- event.preventDefault();
56
- nextIndex = getNextEnabledIndex(activeIndex, 1);
57
- }
58
- break;
59
- case 'Home': {
60
- event.preventDefault();
61
- const firstEnabledIndex = getFirstEnabledIndex();
62
- nextIndex =
63
- firstEnabledIndex === -1 ? activeIndex : firstEnabledIndex;
64
- break;
65
- }
66
- case 'End':
67
- event.preventDefault();
68
- nextIndex = getLastEnabledIndex();
69
- break;
70
- default:
71
- return;
72
- }
73
- if (nextIndex !== activeIndex) {
74
- setActiveIndex(nextIndex);
75
- onNavigate?.(nextIndex);
76
- }
77
- }, [activeIndex, onNavigate, orientation, setActiveIndex, tabRefs]);
78
- return { onKeyDown };
79
- };