@boxcustodia/library 2.0.0-alpha.22 → 2.0.0-alpha.23

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 (102) hide show
  1. package/dist/components/calendar/calendar.cjs.js +1 -1
  2. package/dist/components/calendar/calendar.es.js +43 -44
  3. package/dist/components/date-picker/date-input.cjs.js +1 -1
  4. package/dist/components/date-picker/date-input.es.js +160 -140
  5. package/dist/components/pagination/pagination.cjs.js +1 -1
  6. package/dist/components/pagination/pagination.es.js +37 -35
  7. package/dist/components/scroll-area/scroll-area.cjs.js +1 -1
  8. package/dist/components/scroll-area/scroll-area.es.js +4 -4
  9. package/dist/components/select/select.cjs.js +1 -1
  10. package/dist/components/select/select.es.js +94 -90
  11. package/dist/hooks/use-action/use-action.cjs.js +1 -0
  12. package/dist/hooks/use-action/use-action.es.js +41 -0
  13. package/dist/hooks/use-pagination/use-pagination.cjs.js +1 -1
  14. package/dist/hooks/use-pagination/use-pagination.es.js +77 -32
  15. package/dist/hooks/use-range-pagination/use-range-pagination.cjs.js +1 -1
  16. package/dist/hooks/use-range-pagination/use-range-pagination.es.js +8 -5
  17. package/dist/hooks/use-selection/use-selection.cjs.js +1 -1
  18. package/dist/hooks/use-selection/use-selection.es.js +95 -33
  19. package/dist/hooks/use-session-storage/use-session-storage.cjs.js +1 -0
  20. package/dist/hooks/use-session-storage/use-session-storage.es.js +57 -0
  21. package/dist/index.cjs.js +1 -1
  22. package/dist/index.es.js +61 -63
  23. package/dist/src/components/select/select.d.ts +9 -2
  24. package/dist/src/hooks/index.d.ts +2 -3
  25. package/dist/src/hooks/internal/index.d.ts +1 -0
  26. package/dist/src/hooks/internal/serializer.d.ts +4 -0
  27. package/dist/src/hooks/use-action/index.d.ts +1 -0
  28. package/dist/src/hooks/use-action/use-action.d.ts +22 -0
  29. package/dist/src/hooks/use-local-storage/use-local-storage.d.ts +2 -4
  30. package/dist/src/hooks/use-pagination/use-pagination.d.ts +47 -32
  31. package/dist/src/hooks/use-range-pagination/use-range-pagination.d.ts +16 -10
  32. package/dist/src/hooks/use-selection/use-selection.d.ts +39 -45
  33. package/dist/src/hooks/use-session-storage/index.d.ts +1 -0
  34. package/dist/src/hooks/use-session-storage/use-session-storage.d.ts +11 -0
  35. package/package.json +1 -1
  36. package/src/components/calendar/calendar.tsx +10 -8
  37. package/src/components/combobox/combobox.stories.tsx +16 -0
  38. package/src/components/date-picker/date-input.tsx +23 -2
  39. package/src/components/form/form.tsx +3 -2
  40. package/src/components/pagination/pagination.tsx +5 -3
  41. package/src/components/scroll-area/scroll-area.tsx +2 -2
  42. package/src/components/select/select.tsx +14 -3
  43. package/src/hooks/index.ts +2 -3
  44. package/src/hooks/internal/index.ts +1 -0
  45. package/src/hooks/internal/serializer.ts +4 -0
  46. package/src/hooks/use-action/index.ts +1 -0
  47. package/src/hooks/{use-mutation/use-mutation.stories.tsx → use-action/use-action.stories.tsx} +34 -34
  48. package/src/hooks/{use-mutation/use-mutation.test.ts → use-action/use-action.test.ts} +53 -53
  49. package/src/hooks/{use-mutation/use-mutation.ts → use-action/use-action.ts} +20 -20
  50. package/src/hooks/use-click-outside/use-click-outside.stories.tsx +0 -1
  51. package/src/hooks/use-clipboard/use-clipboard.stories.tsx +0 -1
  52. package/src/hooks/use-document-title/use-document-title.stories.tsx +0 -1
  53. package/src/hooks/use-is-visible/use-is-visible.test.tsx +1 -1
  54. package/src/hooks/use-local-storage/use-local-storage.stories.tsx +0 -1
  55. package/src/hooks/use-local-storage/use-local-storage.ts +2 -5
  56. package/src/hooks/use-media-query/use-media-query.stories.tsx +0 -1
  57. package/src/hooks/use-pagination/use-pagination.stories.tsx +720 -57
  58. package/src/hooks/use-pagination/use-pagination.test.tsx +560 -48
  59. package/src/hooks/use-pagination/use-pagination.ts +266 -0
  60. package/src/hooks/use-prevent-page-close/use-prevent-page-close.stories.tsx +0 -1
  61. package/src/hooks/use-range-pagination/use-range-pagination.test.tsx +2 -2
  62. package/src/hooks/use-range-pagination/use-range-pagination.tsx +24 -21
  63. package/src/hooks/use-selection/use-selection.stories.tsx +339 -84
  64. package/src/hooks/use-selection/use-selection.test.tsx +417 -2
  65. package/src/hooks/use-selection/use-selection.ts +212 -102
  66. package/src/hooks/use-session-storage/index.ts +1 -0
  67. package/src/hooks/use-session-storage/use-session-storage.stories.tsx +122 -0
  68. package/src/hooks/use-session-storage/use-session-storage.test.ts +164 -0
  69. package/src/hooks/use-session-storage/use-session-storage.ts +115 -0
  70. package/dist/hooks/use-async/use-async.cjs.js +0 -1
  71. package/dist/hooks/use-async/use-async.es.js +0 -57
  72. package/dist/hooks/use-focus-trap/scope-tab.cjs.js +0 -1
  73. package/dist/hooks/use-focus-trap/scope-tab.es.js +0 -21
  74. package/dist/hooks/use-focus-trap/tabbable.cjs.js +0 -1
  75. package/dist/hooks/use-focus-trap/tabbable.es.js +0 -38
  76. package/dist/hooks/use-focus-trap/use-focus-trap.cjs.js +0 -1
  77. package/dist/hooks/use-focus-trap/use-focus-trap.es.js +0 -34
  78. package/dist/hooks/use-mutation/use-mutation.cjs.js +0 -1
  79. package/dist/hooks/use-mutation/use-mutation.es.js +0 -41
  80. package/dist/src/hooks/use-async/index.d.ts +0 -1
  81. package/dist/src/hooks/use-async/use-async.d.ts +0 -21
  82. package/dist/src/hooks/use-focus-trap/index.d.ts +0 -1
  83. package/dist/src/hooks/use-focus-trap/scope-tab.d.ts +0 -1
  84. package/dist/src/hooks/use-focus-trap/tabbable.d.ts +0 -4
  85. package/dist/src/hooks/use-focus-trap/use-focus-trap.d.ts +0 -1
  86. package/dist/src/hooks/use-mutation/index.d.ts +0 -1
  87. package/dist/src/hooks/use-mutation/use-mutation.d.ts +0 -22
  88. package/dist/src/hooks/use-mutation/use-mutation.test.d.ts +0 -1
  89. package/src/hooks/use-async/index.ts +0 -1
  90. package/src/hooks/use-async/use-async.stories.tsx +0 -272
  91. package/src/hooks/use-async/use-async.test.ts +0 -397
  92. package/src/hooks/use-async/use-async.ts +0 -135
  93. package/src/hooks/use-focus-trap/index.ts +0 -1
  94. package/src/hooks/use-focus-trap/scope-tab.ts +0 -38
  95. package/src/hooks/use-focus-trap/tabbable.ts +0 -70
  96. package/src/hooks/use-focus-trap/use-focus-trap.stories.tsx +0 -37
  97. package/src/hooks/use-focus-trap/use-focus-trap.test.ts +0 -355
  98. package/src/hooks/use-focus-trap/use-focus-trap.ts +0 -78
  99. package/src/hooks/use-mutation/index.ts +0 -1
  100. package/src/hooks/use-pagination/use-pagination.tsx +0 -84
  101. /package/dist/src/hooks/{use-async/use-async.test.d.ts → use-action/use-action.test.d.ts} +0 -0
  102. /package/dist/src/hooks/{use-focus-trap/use-focus-trap.test.d.ts → use-session-storage/use-session-storage.test.d.ts} +0 -0
package/dist/index.es.js CHANGED
@@ -68,8 +68,8 @@ import { Tooltip as Mp, TooltipArrow as hp, TooltipPopup as Lp, TooltipProvider
68
68
  import { Tooltip as Hp } from "@base-ui/react/tooltip";
69
69
  import { TreeDragLine as Vp, TreeItem as Bp, TreeItemLabel as Op, TreeRoot as zp } from "./components/tree/tree.es.js";
70
70
  import { useControllableState as Kp } from "@radix-ui/react-use-controllable-state";
71
- import { useArray as Zp } from "./hooks/use-array/use-array.es.js";
72
- import { useAsync as qp } from "./hooks/use-async/use-async.es.js";
71
+ import { useAction as Zp } from "./hooks/use-action/use-action.es.js";
72
+ import { useArray as qp } from "./hooks/use-array/use-array.es.js";
73
73
  import { useBoolean as Up } from "./hooks/use-boolean/use-boolean.es.js";
74
74
  import { useClickOutside as Xp } from "./hooks/use-click-outside/use-click-outside.es.js";
75
75
  import { useClipboard as $p } from "./hooks/use-clipboard/use-clipboard.es.js";
@@ -78,32 +78,31 @@ import { useDebouncedValue as ta } from "./hooks/use-debounce-value/use-debounce
78
78
  import { useDisclosure as pa } from "./hooks/use-disclosure/use-disclosure.es.js";
79
79
  import { useDocumentTitle as ma } from "./hooks/use-document-title/use-document-title.es.js";
80
80
  import { useEventListener as na } from "./hooks/use-event-listener/use-event-listener.es.js";
81
- import { useFocusTrap as ua } from "./hooks/use-focus-trap/use-focus-trap.es.js";
82
- import { getHotkeyHandler as ba, useHotkey as ca } from "./hooks/use-hotkey/use-hotkey.es.js";
83
- import { useHover as ga } from "./hooks/use-hover/use-hover.es.js";
84
- import { useIsVisible as Pa } from "./hooks/use-is-visible/use-is-visible.es.js";
85
- import { useLocalStorage as da } from "./hooks/use-local-storage/use-local-storage.es.js";
86
- import { useMediaQuery as Aa } from "./hooks/use-media-query/use-media-query.es.js";
87
- import { useMemoizedFn as Da } from "./hooks/use-memoized-fn/use-memoized-fn.es.js";
88
- import { useMutation as Fa } from "./hooks/use-mutation/use-mutation.es.js";
89
- import { useObject as ka } from "./hooks/use-object/use-object.es.js";
90
- import { useOnMount as ha } from "./hooks/use-on-mount/use-on-mount.es.js";
91
- import { usePagination as ya } from "./hooks/use-pagination/use-pagination.es.js";
92
- import { usePortal as Na } from "./hooks/use-portal/use-portal.es.js";
93
- import { usePreventPageClose as Ha } from "./hooks/use-prevent-page-close/use-prevent-page-close.es.js";
94
- import { DOTS as Va, useRangePagination as Ba } from "./hooks/use-range-pagination/use-range-pagination.es.js";
95
- import { useSelection as za } from "./hooks/use-selection/use-selection.es.js";
96
- import { useStep as Ka } from "./hooks/use-step/use-step.es.js";
97
- import { cn as Za, twMerge as _a } from "./lib/cn.es.js";
98
- import { LibraryProvider as Ja } from "./providers/library-provider.es.js";
99
- import { ThemeProvider as Wa, useTheme as Xa } from "./providers/theme/ThemeProvider.es.js";
100
- import { useThemeProps as $a } from "./providers/theme/useThemeProps.es.js";
101
- import { HookField as em, HookForm as rm, parseFormValues as tm, useHookForm as im } from "./utils/form.es.js";
102
- import { createSafeContext as am } from "./utils/functions/createSafeContext.es.js";
103
- import { ensureReactElement as lm } from "./utils/functions/ensureReactElement.es.js";
104
- import { getFormData as sm } from "./utils/functions/getFormData.es.js";
105
- import { mergeRefs as xm } from "./utils/functions/mergeRefs.es.js";
106
- import { extractInitials as cm } from "./utils/strings/extractInitials.utility.es.js";
81
+ import { getHotkeyHandler as ua, useHotkey as xa } from "./hooks/use-hotkey/use-hotkey.es.js";
82
+ import { useHover as ca } from "./hooks/use-hover/use-hover.es.js";
83
+ import { useIsVisible as ga } from "./hooks/use-is-visible/use-is-visible.es.js";
84
+ import { useLocalStorage as Pa } from "./hooks/use-local-storage/use-local-storage.es.js";
85
+ import { useMediaQuery as da } from "./hooks/use-media-query/use-media-query.es.js";
86
+ import { useMemoizedFn as Aa } from "./hooks/use-memoized-fn/use-memoized-fn.es.js";
87
+ import { useObject as Da } from "./hooks/use-object/use-object.es.js";
88
+ import { useOnMount as Fa } from "./hooks/use-on-mount/use-on-mount.es.js";
89
+ import { usePagination as ka } from "./hooks/use-pagination/use-pagination.es.js";
90
+ import { usePortal as ha } from "./hooks/use-portal/use-portal.es.js";
91
+ import { usePreventPageClose as ya } from "./hooks/use-prevent-page-close/use-prevent-page-close.es.js";
92
+ import { DOTS as Na, useRangePagination as Ea } from "./hooks/use-range-pagination/use-range-pagination.es.js";
93
+ import { useSelection as wa } from "./hooks/use-selection/use-selection.es.js";
94
+ import { useSessionStorage as Ba } from "./hooks/use-session-storage/use-session-storage.es.js";
95
+ import { useStep as za } from "./hooks/use-step/use-step.es.js";
96
+ import { cn as Ka, twMerge as Qa } from "./lib/cn.es.js";
97
+ import { LibraryProvider as _a } from "./providers/library-provider.es.js";
98
+ import { ThemeProvider as Ja, useTheme as Ua } from "./providers/theme/ThemeProvider.es.js";
99
+ import { useThemeProps as Xa } from "./providers/theme/useThemeProps.es.js";
100
+ import { HookField as $a, HookForm as om, parseFormValues as em, useHookForm as rm } from "./utils/form.es.js";
101
+ import { createSafeContext as im } from "./utils/functions/createSafeContext.es.js";
102
+ import { ensureReactElement as am } from "./utils/functions/ensureReactElement.es.js";
103
+ import { getFormData as lm } from "./utils/functions/getFormData.es.js";
104
+ import { mergeRefs as sm } from "./utils/functions/mergeRefs.es.js";
105
+ import { extractInitials as xm } from "./utils/strings/extractInitials.utility.es.js";
107
106
  export {
108
107
  r as Accordion,
109
108
  t as AccordionContent,
@@ -196,7 +195,7 @@ export {
196
195
  ee as ComboboxStatus,
197
196
  re as ComboboxTrigger,
198
197
  te as ComboboxValue,
199
- Va as DOTS,
198
+ Na as DOTS,
200
199
  le as DateInput,
201
200
  se as DatePicker,
202
201
  xe as Dialog,
@@ -242,14 +241,14 @@ export {
242
241
  Be as FileTypeGroups,
243
242
  br as Form,
244
243
  fr as FormPrimitive,
245
- em as HookField,
246
- rm as HookForm,
244
+ $a as HookField,
245
+ om as HookForm,
247
246
  Tr as Input,
248
247
  dr as InputPrimitive,
249
248
  Ar as Kbd,
250
249
  vr as KbdGroup,
251
250
  Ir as Label,
252
- Ja as LibraryProvider,
251
+ _a as LibraryProvider,
253
252
  Rr as Loader,
254
253
  Mr as Menu,
255
254
  Lr as MenuCheckboxItem,
@@ -366,7 +365,7 @@ export {
366
365
  rp as TabsTrigger,
367
366
  ap as Tag,
368
367
  np as Textarea,
369
- Wa as ThemeProvider,
368
+ Ja as ThemeProvider,
370
369
  up as Timeline,
371
370
  xp as TimelineContent,
372
371
  bp as TimelineDate,
@@ -390,25 +389,25 @@ export {
390
389
  Op as TreeItemLabel,
391
390
  zp as TreeRoot,
392
391
  mo as buttonVariants,
393
- Za as cn,
394
- am as createSafeContext,
392
+ Ka as cn,
393
+ im as createSafeContext,
395
394
  Ap as createToastManager,
396
- lm as ensureReactElement,
397
- cm as extractInitials,
398
- sm as getFormData,
399
- ba as getHotkeyHandler,
395
+ am as ensureReactElement,
396
+ xm as extractInitials,
397
+ lm as getFormData,
398
+ ua as getHotkeyHandler,
400
399
  Pr as inputBaseClasses,
401
- xm as mergeRefs,
400
+ sm as mergeRefs,
402
401
  pr as normalizeError,
403
- tm as parseFormValues,
402
+ em as parseFormValues,
404
403
  bi as selectTriggerClasses,
405
404
  ci as selectTriggerIconClassName,
406
405
  mp as tagVariants,
407
406
  vp as toast,
408
407
  Dp as toastVariants,
409
- _a as twMerge,
410
- Zp as useArray,
411
- qp as useAsync,
408
+ Qa as twMerge,
409
+ Zp as useAction,
410
+ qp as useArray,
412
411
  _ as useAutocompleteFilter,
413
412
  Up as useBoolean,
414
413
  Xp as useClickOutside,
@@ -421,27 +420,26 @@ export {
421
420
  ma as useDocumentTitle,
422
421
  na as useEventListener,
423
422
  ar as useFieldName,
424
- ua as useFocusTrap,
425
- im as useHookForm,
426
- ca as useHotkey,
427
- ga as useHover,
423
+ rm as useHookForm,
424
+ xa as useHotkey,
425
+ ca as useHover,
428
426
  mr as useIsInsideFieldRoot,
429
- Pa as useIsVisible,
430
- da as useLocalStorage,
431
- Aa as useMediaQuery,
432
- Da as useMemoizedFn,
433
- Fa as useMutation,
434
- ka as useObject,
435
- ha as useOnMount,
436
- ya as usePagination,
437
- Na as usePortal,
438
- Ha as usePreventPageClose,
439
- Ba as useRangePagination,
440
- za as useSelection,
441
- Ka as useStep,
427
+ ga as useIsVisible,
428
+ Pa as useLocalStorage,
429
+ da as useMediaQuery,
430
+ Aa as useMemoizedFn,
431
+ Da as useObject,
432
+ Fa as useOnMount,
433
+ ka as usePagination,
434
+ ha as usePortal,
435
+ ya as usePreventPageClose,
436
+ Ea as useRangePagination,
437
+ wa as useSelection,
438
+ Ba as useSessionStorage,
439
+ za as useStep,
442
440
  Gi as useStepItem,
443
441
  Ni as useStepper,
444
- Xa as useTheme,
445
- $a as useThemeProps,
442
+ Ua as useTheme,
443
+ Xa as useThemeProps,
446
444
  Ip as useToastManager
447
445
  };
@@ -4,11 +4,16 @@ import * as React from "react";
4
4
  export declare const selectTriggerClasses: string;
5
5
  export declare const selectTriggerIconClassName = "-me-1 size-4.5 opacity-80 sm:size-4";
6
6
  export declare function SelectRoot<Value = string, Multiple extends boolean | undefined = false>({ ...props }: SelectPrimitive.Root.Props<Value, Multiple>): React.ReactElement;
7
- export declare function SelectTrigger({ className, children, ...props }: SelectPrimitive.Trigger.Props): React.ReactElement;
7
+ export declare function SelectTrigger({ className, children, icon, ...props }: SelectPrimitive.Trigger.Props & {
8
+ /** Icon rendered inside the trigger. Defaults to a chevrons-up-down glyph. */
9
+ icon?: React.ReactNode;
10
+ }): React.ReactElement;
8
11
  export type SelectButtonProps = useRender.ComponentProps<"button"> & {
9
12
  ref?: React.Ref<HTMLButtonElement>;
13
+ /** Icon rendered inside the button. Defaults to a chevrons-up-down glyph. */
14
+ icon?: React.ReactNode;
10
15
  };
11
- export declare function SelectButton({ className, render, children, ...props }: SelectButtonProps): React.ReactElement;
16
+ export declare function SelectButton({ className, render, children, icon, ...props }: SelectButtonProps): React.ReactElement;
12
17
  export declare function SelectValue({ className, ...props }: SelectPrimitive.Value.Props): React.ReactElement;
13
18
  export declare function SelectPopup({ className, children, side, sideOffset, align, alignOffset, alignItemWithTrigger, anchor, portalProps, ...props }: SelectPrimitive.Popup.Props & {
14
19
  portalProps?: SelectPrimitive.Portal.Props;
@@ -35,6 +40,8 @@ type SelectBaseProps<TItem = unknown> = Omit<SelectPrimitive.Root.Props<string,
35
40
  renderItem?: (item: TItem) => React.ReactNode;
36
41
  placeholder?: string;
37
42
  className?: string;
43
+ /** Icon rendered inside the trigger. Defaults to a chevrons-up-down glyph. */
44
+ icon?: React.ReactNode;
38
45
  /** Styles applied to each internal slot. */
39
46
  classNames?: {
40
47
  /** Popup panel containing the item list. */
@@ -1,6 +1,6 @@
1
1
  export { useControllableState } from '@radix-ui/react-use-controllable-state';
2
+ export * from './use-action';
2
3
  export * from './use-array';
3
- export * from './use-async';
4
4
  export * from './use-boolean';
5
5
  export * from './use-click-outside';
6
6
  export * from './use-clipboard';
@@ -9,14 +9,12 @@ export * from './use-debounce-value';
9
9
  export * from './use-disclosure';
10
10
  export * from './use-document-title';
11
11
  export * from './use-event-listener';
12
- export * from './use-focus-trap';
13
12
  export * from './use-hotkey';
14
13
  export * from './use-hover';
15
14
  export * from './use-is-visible';
16
15
  export * from './use-local-storage';
17
16
  export * from './use-media-query';
18
17
  export * from './use-memoized-fn';
19
- export * from './use-mutation';
20
18
  export * from './use-object';
21
19
  export * from './use-on-mount';
22
20
  export * from './use-pagination';
@@ -24,4 +22,5 @@ export * from './use-portal';
24
22
  export * from './use-prevent-page-close';
25
23
  export * from './use-range-pagination';
26
24
  export * from './use-selection';
25
+ export * from './use-session-storage';
27
26
  export * from './use-step';
@@ -1,4 +1,5 @@
1
1
  export { isAppleDevice } from './is-apple-device';
2
2
  export { isBrowser } from './is-browser';
3
+ export type { Serializer } from './serializer';
3
4
  export { useIsomorphicLayoutEffect } from './use-isomorphic-layout-effect';
4
5
  export { useLatestRef } from './use-latest-ref';
@@ -0,0 +1,4 @@
1
+ export interface Serializer<T> {
2
+ read: (raw: string) => T;
3
+ write: (value: T) => string;
4
+ }
@@ -0,0 +1 @@
1
+ export * from './use-action';
@@ -0,0 +1,22 @@
1
+ type ActionStatus = "idle" | "pending" | "success" | "error";
2
+ export interface UseActionOptions<TVariables = void, TData = unknown> {
3
+ fn: (variables: TVariables) => Promise<TData>;
4
+ onExecute?: (variables: TVariables) => void;
5
+ onSuccess?: (data: TData, variables: TVariables) => void;
6
+ onError?: (error: Error, variables: TVariables) => void;
7
+ onSettled?: (data: TData | null, error: Error | null, variables: TVariables) => void;
8
+ }
9
+ export interface UseActionReturn<TVariables = void, TData = unknown> {
10
+ execute: (variables: TVariables) => void;
11
+ executeAsync: (variables: TVariables) => Promise<TData>;
12
+ reset: () => void;
13
+ data: TData | null;
14
+ error: Error | null;
15
+ status: ActionStatus;
16
+ isIdle: boolean;
17
+ isPending: boolean;
18
+ isSuccess: boolean;
19
+ isError: boolean;
20
+ }
21
+ export declare const useAction: <TVariables = void, TData = unknown>(options: UseActionOptions<TVariables, TData>) => UseActionReturn<TVariables, TData>;
22
+ export {};
@@ -1,7 +1,5 @@
1
- export interface Serializer<T> {
2
- read: (raw: string) => T;
3
- write: (value: T) => string;
4
- }
1
+ import { Serializer } from '../internal';
2
+ export type { Serializer };
5
3
  export interface UseLocalStorageOptions<T> {
6
4
  serializer?: Serializer<T>;
7
5
  }
@@ -1,46 +1,61 @@
1
- export type usePaginationProps = {
2
- /**
3
- * Cantidad total de elementos
4
- */
1
+ export interface UsePaginationProps {
2
+ /** Total number of items. Required. */
5
3
  totalItems: number;
4
+ /** Controlled page size. Pair with defaultPageSize / onPageSizeChange. */
5
+ pageSize?: number;
6
+ /** Initial page size (uncontrolled). @default 10 */
7
+ defaultPageSize?: number;
8
+ /** Fired when page size changes. Stable via useLatestRef. */
9
+ onPageSizeChange?: (size: number) => void;
10
+ /** Controlled current page. */
11
+ page?: number;
12
+ /** Initial page (uncontrolled). @default 1 */
13
+ defaultPage?: number;
14
+ /** Fired when page changes. Stable via useLatestRef. */
15
+ onPageChange?: (page: number) => void;
6
16
  /**
7
- * Cantidad de elementos por página
8
- */
9
- pageSize: number;
10
- /**
11
- * Página controlada
12
- */
13
- currentPage?: number;
14
- /**
15
- * Página inicial (uncontrolled)
17
+ * Fired once with BOTH resolved values whenever page or pageSize changes.
18
+ * Ideal as a single data-fetching trigger — no need to wire a `useEffect` on
19
+ * both `page` and `pageSize`. NOT called on mount. Stable via useLatestRef.
16
20
  */
17
- defaultCurrentPage?: number;
18
- /**
19
- * Callback cuando cambia la página
20
- */
21
- onCurrentPageChange?: (page: number) => void;
22
- /**
23
- * @deprecated Usá `defaultCurrentPage`
24
- */
25
- initialCurrentPage?: number;
26
- /**
27
- * @deprecated Usá `onCurrentPageChange`
28
- */
29
- onChange?: (value: {
30
- currentPage: number;
21
+ onPaginationChange?: (state: {
22
+ page: number;
31
23
  pageSize: number;
32
24
  }) => void;
33
- };
34
- export declare function usePagination({ totalItems, pageSize, currentPage: currentPageProp, defaultCurrentPage, onCurrentPageChange, initialCurrentPage, onChange, }: usePaginationProps): {
25
+ }
26
+ export interface UsePaginationActions {
27
+ /** Go to the next page. No-op on last page. Stable reference. */
35
28
  next: () => void;
29
+ /** Go to the previous page. No-op on first page. Stable reference. */
36
30
  prev: () => void;
31
+ /** Jump to the first page. Stable reference. */
32
+ firstPage: () => void;
33
+ /** Jump to the last page. Stable reference. */
34
+ lastPage: () => void;
35
+ /** Jump to a specific page, clamped to [1, pageCount]. Stable reference. */
37
36
  goTo: (page: number) => void;
38
- currentPage: number;
39
- maxPage: number;
37
+ /** Change the page size. Resets to page 1. Stable reference. */
38
+ setPageSize: (size: number) => void;
39
+ }
40
+ export interface UsePaginationReturn extends UsePaginationActions {
41
+ /** Current active page (1-indexed). */
42
+ page: number;
43
+ /** Current page size. */
44
+ pageSize: number;
45
+ /** Total number of pages. 0 when there are no items. */
46
+ pageCount: number;
47
+ /** Whether the current page is the first. */
40
48
  isFirstPage: boolean;
49
+ /** Whether the current page is the last. */
41
50
  isLastPage: boolean;
51
+ /** Whether there is a previous page. */
52
+ hasPrevPage: boolean;
53
+ /** Whether there is a next page. */
54
+ hasNextPage: boolean;
55
+ /** 1-based item range for the current page. */
42
56
  range: {
43
57
  start: number;
44
58
  end: number;
45
59
  };
46
- };
60
+ }
61
+ export declare function usePagination({ totalItems, pageSize: pageSizeProp, defaultPageSize, onPageSizeChange, page: pageProp, defaultPage, onPageChange, onPaginationChange, }: UsePaginationProps): UsePaginationReturn;
@@ -1,22 +1,28 @@
1
- import { usePaginationProps } from '../../hooks';
1
+ import { UsePaginationProps } from '../../hooks';
2
2
  export declare const DOTS = "...";
3
- export type useRangePaginationProps = {
3
+ export type UseRangePaginationProps = {
4
4
  /**
5
- * Cantidad de elementos visibles al lado de la pagina actual
5
+ * Visible siblings on each side of the current page.
6
6
  */
7
7
  siblingCount?: number;
8
- } & usePaginationProps;
9
- export declare const useRangePagination: ({ siblingCount, ...paginationProps }: useRangePaginationProps) => {
8
+ } & UsePaginationProps;
9
+ export declare const useRangePagination: ({ siblingCount, ...paginationProps }: UseRangePaginationProps) => {
10
10
  paginationRange: (string | number)[];
11
- next: () => void;
12
- prev: () => void;
13
- goTo: (page: number) => void;
14
- currentPage: number;
15
- maxPage: number;
11
+ page: number;
12
+ pageSize: number;
13
+ pageCount: number;
16
14
  isFirstPage: boolean;
17
15
  isLastPage: boolean;
16
+ hasPrevPage: boolean;
17
+ hasNextPage: boolean;
18
18
  range: {
19
19
  start: number;
20
20
  end: number;
21
21
  };
22
+ next: () => void;
23
+ prev: () => void;
24
+ firstPage: () => void;
25
+ lastPage: () => void;
26
+ goTo: (page: number) => void;
27
+ setPageSize: (size: number) => void;
22
28
  };
@@ -1,54 +1,48 @@
1
- type Return<T> = {
2
- /**
3
- * Indica si todos los elementos están seleccionados.
4
- */
1
+ /** Stable identity projected from an item. */
2
+ export type Key = string | number | symbol;
3
+ export interface UseSelectionOptions<T> {
4
+ /**
5
+ * Projects a stable key from an item. Frozen on mount.
6
+ * When omitted, the item itself is used as its key (reference identity for
7
+ * objects, value identity for primitives). Pass this for object lists that
8
+ * are re-created across renders (e.g. after a fetch) so selection survives.
9
+ */
10
+ keyFn?: (item: T) => Key;
11
+ /** Initial selection. Frozen on mount — never re-applied on re-render. */
12
+ defaultSelected?: T[];
13
+ /** Called after every selection change. NOT called on initial mount. */
14
+ onChange?: (selected: T[]) => void;
15
+ }
16
+ export interface UseSelectionReturn<T> {
17
+ /** Currently-selected items present in `items`. Stable reference. */
18
+ selected: T[];
19
+ /** All selected keys, including keys whose item is absent (sticky). */
20
+ selectedKeys: ReadonlySet<Key>;
21
+ /** True when every item in `items` is selected (false when empty). */
5
22
  isAllSelected: boolean;
6
- /**
7
- * Indica si algunos elementos están seleccionados.
8
- */
23
+ /** True when at least one — but not all — items are selected. */
9
24
  isSomeSelected: boolean;
10
- /**
11
- * Indica si ningun elemento está seleccionado.
12
- */
25
+ /** True when nothing is selected. */
13
26
  isNoneSelected: boolean;
14
- /**
15
- * Función que devuelve true si el elemento dado está seleccionado, false de lo contrario.
16
- * @param item El elemento a verificar.
17
- * @returns true si el elemento está seleccionado, false de lo contrario.
18
- */
27
+ /** Stable fn ref: true if `item` is selected. */
19
28
  isSelected: (item: T) => boolean;
20
- /**
21
- * Array de elementos seleccionados.
22
- */
23
- selected: T[];
24
- /**
25
- * Establece los elementos seleccionados.
26
- * @param items Los elementos seleccionados.
27
- */
28
- setSelected: (items: T[]) => void;
29
- /**
30
- * Selecciona un elemento.
31
- * @param item El elemento a seleccionar.
32
- */
29
+ /** Selects one item. No-op if already selected. */
33
30
  select: (item: T) => void;
34
- /**
35
- * Deselecciona un elemento.
36
- * @param item El elemento a deseleccionar.
37
- */
31
+ /** Unselects one item. No-op if not selected. */
38
32
  unselect: (item: T) => void;
39
- /**
40
- * Alterna la selección de un elemento (si está seleccionado, lo deselecciona y viceversa).
41
- * @param item El elemento cuya selección se alternará.
42
- */
33
+ /** Toggles one item's selection. */
43
34
  toggle: (item: T) => void;
44
- /**
45
- * Alterna la selección de todos los elementos (si todos están seleccionados, los deselecciona; de lo contrario, los selecciona).
46
- */
35
+ /** Replaces the entire selection with `items`. */
36
+ setSelected: (items: T[]) => void;
37
+ /** Selects every item currently in `items` (additive). */
38
+ selectAll: () => void;
39
+ /** Selects all if not all selected, otherwise clears. */
47
40
  toggleAll: () => void;
48
- /**
49
- * Deselecciona todos los elementos.
50
- */
41
+ /** Clears the entire selection (including sticky orphaned keys). */
51
42
  clear: () => void;
52
- };
53
- export declare function useSelection<T>(items: T[]): Return<T>;
54
- export {};
43
+ /** Inverts selection relative to current `items`. */
44
+ invert: () => void;
45
+ /** Selects items in the inclusive index range [from, to] of `items` (additive). */
46
+ selectRange: (from: number, to: number) => void;
47
+ }
48
+ export declare function useSelection<T>(items: T[], options?: UseSelectionOptions<T>): UseSelectionReturn<T>;
@@ -0,0 +1 @@
1
+ export * from './use-session-storage';
@@ -0,0 +1,11 @@
1
+ import { Serializer } from '../internal';
2
+ export type { Serializer };
3
+ export interface UseSessionStorageOptions<T> {
4
+ serializer?: Serializer<T>;
5
+ }
6
+ export declare function useSessionStorage<T>(key: string): [
7
+ T | undefined,
8
+ (value: T | ((prev: T | undefined) => T)) => void,
9
+ () => void
10
+ ];
11
+ export declare function useSessionStorage<T>(key: string, initialValue: T, options?: UseSessionStorageOptions<T>): [T, (value: T | ((prev: T) => T)) => void, () => void];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@boxcustodia/library",
3
- "version": "2.0.0-alpha.22",
3
+ "version": "2.0.0-alpha.23",
4
4
  "type": "module",
5
5
  "main": "dist/index.cjs.js",
6
6
  "module": "dist/index.es.js",
@@ -2,15 +2,15 @@
2
2
 
3
3
  import { es } from "date-fns/locale";
4
4
  import {
5
+ ChevronDownIcon,
5
6
  ChevronLeftIcon,
6
7
  ChevronRightIcon,
7
- ChevronsUpDownIcon,
8
8
  } from "lucide-react";
9
9
  import type * as React from "react";
10
10
  import type { DropdownProps } from "react-day-picker";
11
11
  import { DayPicker } from "react-day-picker";
12
12
  import { cn } from "@/lib";
13
- import { Select } from "../select/select";
13
+ import { Select, selectTriggerIconClassName } from "../select/select";
14
14
 
15
15
  const _year = new Date().getFullYear();
16
16
  const DEFAULT_START_MONTH = new Date(_year - 100, 0);
@@ -33,11 +33,12 @@ function CalendarDropdown({
33
33
  <Select
34
34
  items={items}
35
35
  value={selected}
36
+ icon={<ChevronDownIcon className={selectTriggerIconClassName} />}
36
37
  // Month/year dropdowns are calendar navigation, not form fields. Force
37
38
  // off the invalid state so a surrounding invalid Field never paints them
38
39
  // with the error border.
39
40
  aria-invalid={false}
40
- className="py-1 h-7"
41
+ className="py-1 h-7 border-none font-medium! w-fit! [&>span]:capitalize"
41
42
  getLabel={(o) => o.label}
42
43
  getId={(o) => String(o.value)}
43
44
  onValueChange={(item) => {
@@ -145,11 +146,7 @@ export function Calendar({
145
146
  }
146
147
 
147
148
  return (
148
- <ChevronsUpDownIcon
149
- className={className}
150
- {...props}
151
- aria-hidden="true"
152
- />
149
+ <ChevronDownIcon className={className} {...props} aria-hidden="true" />
153
150
  );
154
151
  },
155
152
  };
@@ -162,6 +159,11 @@ export function Calendar({
162
159
  const dayPickerProps = {
163
160
  className: cn(
164
161
  "w-fit [--cell-size:--spacing(10)] sm:[--cell-size:--spacing(9)]",
162
+ // Standalone container surface. Inside a popover (DatePicker) the
163
+ // popup already paints border + background + padding, so strip ours
164
+ // to avoid a double border.
165
+ "rounded-xl border bg-background p-3",
166
+ "in-data-[slot=popover-popup]:rounded-none in-data-[slot=popover-popup]:border-0 in-data-[slot=popover-popup]:bg-transparent in-data-[slot=popover-popup]:p-0",
165
167
  className,
166
168
  ),
167
169
  classNames: mergedClassNames,
@@ -219,6 +219,22 @@ export const StringItems: Story = {
219
219
  ),
220
220
  };
221
221
 
222
+ /**
223
+ * The popup caps its height at `min(--available-height, 23rem)` and the list
224
+ * scrolls natively — no extra props needed. With a long list the dropdown stays
225
+ * anchored and scrollable instead of overflowing the viewport. Typing filters
226
+ * the list, so the scroll only appears while many items still match.
227
+ */
228
+ export const ManyItems: Story = {
229
+ render: () => {
230
+ const manyItems: Item[] = Array.from({ length: 50 }, (_, index) => ({
231
+ label: `Item ${index + 1}`,
232
+ value: `item-${index + 1}`,
233
+ }));
234
+ return <Combobox<Item> items={manyItems} placeholder="Select an item…" />;
235
+ },
236
+ };
237
+
222
238
  export const LibraryForm: Story = {
223
239
  name: "Form",
224
240
  render: () => {