@primereact/hooks 11.0.0-alpha.8 → 11.0.0-rc.1

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 (48) hide show
  1. package/LICENSE.md +45 -0
  2. package/README.md +34 -0
  3. package/index.d.ts +9 -0
  4. package/index.mjs +1 -1
  5. package/index.mjs.map +1 -1
  6. package/package.json +8 -12
  7. package/use-controlled-state/index.mjs +1 -1
  8. package/use-controlled-state/index.mjs.map +1 -1
  9. package/use-filter/_matchers.d.ts +23 -0
  10. package/use-filter/index.d.ts +94 -0
  11. package/use-filter/index.mjs +2 -0
  12. package/use-filter/index.mjs.map +1 -0
  13. package/use-hot-key/index.d.ts +25 -0
  14. package/use-hot-key/index.mjs +2 -0
  15. package/use-hot-key/index.mjs.map +1 -0
  16. package/use-is-mobile/index.d.ts +18 -0
  17. package/use-is-mobile/index.mjs +2 -0
  18. package/use-is-mobile/index.mjs.map +1 -0
  19. package/use-local-storage/index.d.ts +56 -0
  20. package/use-local-storage/index.mjs +2 -0
  21. package/use-local-storage/index.mjs.map +1 -0
  22. package/use-mask/index.d.ts +96 -67
  23. package/use-mask/index.mjs +1 -1
  24. package/use-mask/index.mjs.map +1 -1
  25. package/use-mounted/index.d.ts +36 -0
  26. package/use-mounted/index.mjs +2 -0
  27. package/use-mounted/index.mjs.map +1 -0
  28. package/use-number-formatter/index.d.ts +194 -0
  29. package/use-number-formatter/index.mjs +2 -0
  30. package/use-number-formatter/index.mjs.map +1 -0
  31. package/use-number-formatter/index.test.d.ts +0 -0
  32. package/use-presence/index.d.ts +1 -2
  33. package/use-presence/index.mjs +1 -1
  34. package/use-presence/index.mjs.map +1 -1
  35. package/use-props/index.d.ts +16 -11
  36. package/use-props/index.mjs +1 -1
  37. package/use-props/index.mjs.map +1 -1
  38. package/use-queue-task/index.d.ts +1 -0
  39. package/use-queue-task/index.mjs +2 -0
  40. package/use-queue-task/index.mjs.map +1 -0
  41. package/use-queue-task/index.test.d.ts +0 -0
  42. package/use-sortable-list/index.d.ts +43 -0
  43. package/use-sortable-list/index.mjs +2 -0
  44. package/use-sortable-list/index.mjs.map +1 -0
  45. package/use-tree-filter/index.d.ts +52 -0
  46. package/use-tree-filter/index.mjs +2 -0
  47. package/use-tree-filter/index.mjs.map +1 -0
  48. package/LICENSE +0 -21
package/package.json CHANGED
@@ -1,17 +1,12 @@
1
1
  {
2
2
  "name": "@primereact/hooks",
3
- "version": "11.0.0-alpha.8",
3
+ "version": "11.0.0-rc.1",
4
4
  "author": "PrimeTek Informatics",
5
- "description": "",
6
- "homepage": "https://primereact.org/",
7
- "license": "MIT",
8
- "repository": {
9
- "type": "git",
10
- "url": "git+https://github.com/primefaces/primereact.git",
11
- "directory": "packages/hooks"
12
- },
5
+ "description": "Hooks for PrimeReact components.",
6
+ "homepage": "https://primereact.dev",
7
+ "license": "SEE LICENSE IN LICENSE.md",
13
8
  "bugs": {
14
- "url": "https://github.com/primefaces/primereact/issues"
9
+ "url": "https://support.primeui.dev"
15
10
  },
16
11
  "main": "./index.mjs",
17
12
  "module": "./index.mjs",
@@ -32,6 +27,7 @@
32
27
  "access": "public"
33
28
  },
34
29
  "dependencies": {
35
- "@primeuix/utils": "^0.6.2"
36
- }
30
+ "@primeuix/utils": "^0.7.2"
31
+ },
32
+ "repository": {}
37
33
  }
@@ -1,2 +1,2 @@
1
- import{resolve as p}from"@primeuix/utils";import*as n from"react";function w({value:r,defaultValue:t,onChange:o}){let[i,u]=n.useState(t!=null?t:r),e=r!==void 0,s=e?r:i,d=n.useCallback(T=>{let[a,c]=p(T,s,e);o==null||o(c),e||u(a)},[s,e,o]);return n.useEffect(()=>{e||u(t)},[t,e]),[s,d,e]}export{w as useControlledState};
1
+ import{resolve as a}from"@primeuix/utils";import*as n from"react";function w({value:r,defaultValue:t,onChange:o}){let e=n.useRef(r!==void 0).current,[i,u]=n.useState(()=>e?void 0:t!=null?t:r),s=e?r:i,d=n.useCallback(c=>{let[l,T]=a(c,s,e);o==null||o(T),e||u(l)},[s,e,o]);return n.useEffect(()=>{e||u(t)},[t,e]),[s,d,e]}export{w as useControlledState};
2
2
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/use-controlled-state/index.ts"],"sourcesContent":["import { resolve } from '@primeuix/utils';\nimport * as React from 'react';\n\n/**\n * The options for the `useControlledState` hook.\n */\nexport interface UseControlledStateOptions<T = unknown, E = unknown> {\n /**\n * The value of the controlled state.\n */\n value?: T | undefined;\n /**\n * The default value of the uncontrolled state.\n */\n defaultValue?: T | undefined;\n /**\n * Callback function that is called when the value changes.\n */\n onChange?: (newValue: E) => void;\n}\n\n/**\n * The return type of the `useControlledState` hook.\n * A tuple containing the current value and a function to update it.\n */\nexport type UseControlledStateReturnType<T = unknown> = [T | undefined, (inValue: unknown | ((prev?: T) => unknown)) => void, boolean];\n\n/**\n * A custom hook that manages controlled and uncontrolled state.\n *\n * @param {UseControlledStateOptions} options - The options for the controlled state.\n * @returns A tuple containing the current value and a function to update it.\n *\n * @example\n * ```tsx\n * const ControlledComponent = () => {\n * const [controlledValue, setControlledValue] = React.useState('');\n *\n * const [value, setValue] = useControlledState({\n * value: controlledValue,\n * defaultValue: 'initial value',\n * onChange: (newValue) => {\n * setControlledValue(newValue);\n * }\n * });\n *\n * return <Component value={value} onChange={(e) => setValue(e.target.value)} />;\n * };\n * ```\n */\nexport function useControlledState<T = unknown, E = T>({ value, defaultValue, onChange }: UseControlledStateOptions<T, E>): UseControlledStateReturnType<T | undefined> {\n const [valueState, setValueState] = React.useState<T | undefined>(defaultValue ?? value);\n\n const isControlled = value !== undefined;\n const computedValue = isControlled ? (value as T) : valueState;\n\n const setValue = React.useCallback(\n (inValue: unknown | ((prev?: T) => unknown)) => {\n // @todo - update resolve to accept multiple parameters\n const [newValue, onChangeParam] = resolve(inValue, computedValue, isControlled) as [T, E];\n\n onChange?.(onChangeParam);\n\n if (!isControlled) {\n setValueState(newValue);\n }\n },\n [computedValue, isControlled, onChange]\n );\n\n React.useEffect(() => {\n if (!isControlled) {\n setValueState(defaultValue);\n }\n }, [defaultValue, isControlled]);\n\n return [computedValue, setValue, isControlled];\n}\n"],"mappings":"AAAA,OAAS,WAAAA,MAAe,kBACxB,UAAYC,MAAW,QAiDhB,SAASC,EAAuC,CAAE,MAAAC,EAAO,aAAAC,EAAc,SAAAC,CAAS,EAAiF,CACpK,GAAM,CAACC,EAAYC,CAAa,EAAU,WAAwBH,GAAA,KAAAA,EAAgBD,CAAK,EAEjFK,EAAeL,IAAU,OACzBM,EAAgBD,EAAgBL,EAAcG,EAE9CI,EAAiB,cAClBC,GAA+C,CAE5C,GAAM,CAACC,EAAUC,CAAa,EAAIb,EAAQW,EAASF,EAAeD,CAAY,EAE9EH,GAAA,MAAAA,EAAWQ,GAENL,GACDD,EAAcK,CAAQ,CAE9B,EACA,CAACH,EAAeD,EAAcH,CAAQ,CAC1C,EAEA,OAAM,YAAU,IAAM,CACbG,GACDD,EAAcH,CAAY,CAElC,EAAG,CAACA,EAAcI,CAAY,CAAC,EAExB,CAACC,EAAeC,EAAUF,CAAY,CACjD","names":["resolve","React","useControlledState","value","defaultValue","onChange","valueState","setValueState","isControlled","computedValue","setValue","inValue","newValue","onChangeParam"]}
1
+ {"version":3,"sources":["../../src/use-controlled-state/index.ts"],"sourcesContent":["import { resolve } from '@primeuix/utils';\nimport * as React from 'react';\n\n/**\n * The options for the `useControlledState` hook.\n */\nexport interface UseControlledStateOptions<T = unknown, E = unknown> {\n /**\n * The value of the controlled state.\n */\n value?: T | undefined;\n /**\n * The default value of the uncontrolled state.\n */\n defaultValue?: T | undefined;\n /**\n * Callback function that is called when the value changes.\n */\n onChange?: (newValue: E) => void;\n}\n\n/**\n * The return type of the `useControlledState` hook.\n * A tuple containing the current value and a function to update it.\n */\nexport type UseControlledStateReturnType<T = unknown> = [T | undefined, (inValue: unknown | ((prev?: T) => unknown)) => void, boolean];\n\n/**\n * A custom hook that manages controlled and uncontrolled state.\n *\n * @param {UseControlledStateOptions} options - The options for the controlled state.\n * @returns A tuple containing the current value and a function to update it.\n *\n * @example\n * ```tsx\n * const ControlledComponent = () => {\n * const [controlledValue, setControlledValue] = React.useState('');\n *\n * const [value, setValue] = useControlledState({\n * value: controlledValue,\n * defaultValue: 'initial value',\n * onChange: (newValue) => {\n * setControlledValue(newValue);\n * }\n * });\n *\n * return <Component value={value} onChange={(e) => setValue(e.target.value)} />;\n * };\n * ```\n */\nexport function useControlledState<T = unknown, E = T>({ value, defaultValue, onChange }: UseControlledStateOptions<T, E>): UseControlledStateReturnType<T | undefined> {\n const isControlledRef = React.useRef(value !== undefined);\n const isControlled = isControlledRef.current;\n\n const [valueState, setValueState] = React.useState<T | undefined>(() => {\n return isControlled ? undefined : (defaultValue ?? value);\n });\n\n const computedValue = isControlled ? (value as T) : valueState;\n\n const setValue = React.useCallback(\n (inValue: unknown | ((prev?: T) => unknown)) => {\n // @todo - update resolve to accept multiple parameters\n const [newValue, onChangeParam] = resolve(inValue, computedValue, isControlled) as [T, E];\n\n onChange?.(onChangeParam);\n\n if (!isControlled) {\n setValueState(newValue);\n }\n },\n [computedValue, isControlled, onChange]\n );\n\n React.useEffect(() => {\n if (!isControlled) {\n setValueState(defaultValue);\n }\n }, [defaultValue, isControlled]);\n\n return [computedValue, setValue, isControlled];\n}\n"],"mappings":"AAAA,OAAS,WAAAA,MAAe,kBACxB,UAAYC,MAAW,QAiDhB,SAASC,EAAuC,CAAE,MAAAC,EAAO,aAAAC,EAAc,SAAAC,CAAS,EAAiF,CAEpK,IAAMC,EADwB,SAAOH,IAAU,MAAS,EACnB,QAE/B,CAACI,EAAYC,CAAa,EAAU,WAAwB,IACvDF,EAAe,OAAaF,GAAA,KAAAA,EAAgBD,CACtD,EAEKM,EAAgBH,EAAgBH,EAAcI,EAE9CG,EAAiB,cAClBC,GAA+C,CAE5C,GAAM,CAACC,EAAUC,CAAa,EAAIb,EAAQW,EAASF,EAAeH,CAAY,EAE9ED,GAAA,MAAAA,EAAWQ,GAENP,GACDE,EAAcI,CAAQ,CAE9B,EACA,CAACH,EAAeH,EAAcD,CAAQ,CAC1C,EAEA,OAAM,YAAU,IAAM,CACbC,GACDE,EAAcJ,CAAY,CAElC,EAAG,CAACA,EAAcE,CAAY,CAAC,EAExB,CAACG,EAAeC,EAAUJ,CAAY,CACjD","names":["resolve","React","useControlledState","value","defaultValue","onChange","isControlled","valueState","setValueState","computedValue","setValue","inValue","newValue","onChangeParam"]}
@@ -0,0 +1,23 @@
1
+ export type FilterMatcher = (value: unknown, filter: unknown, filterLocale?: string) => boolean;
2
+ export declare const BUILT_IN_MATCHERS: {
3
+ readonly startsWith: (value: unknown, filter: unknown, locale: string | undefined) => boolean;
4
+ readonly contains: (value: unknown, filter: unknown, locale: string | undefined) => boolean;
5
+ readonly notContains: (value: unknown, filter: unknown, locale: string | undefined) => boolean;
6
+ readonly endsWith: (value: unknown, filter: unknown, locale: string | undefined) => boolean;
7
+ readonly equals: (value: unknown, filter: unknown, locale: string | undefined) => boolean;
8
+ readonly notEquals: (value: unknown, filter: unknown, locale: string | undefined) => boolean;
9
+ readonly in: (value: unknown, filter: unknown) => boolean;
10
+ readonly between: (value: unknown, filter: unknown) => boolean;
11
+ readonly lt: (value: unknown, filter: unknown) => boolean;
12
+ readonly lte: (value: unknown, filter: unknown) => boolean;
13
+ readonly gt: (value: unknown, filter: unknown) => boolean;
14
+ readonly gte: (value: unknown, filter: unknown) => boolean;
15
+ readonly dateIs: (value: unknown, filter: unknown) => boolean;
16
+ readonly dateIsNot: (value: unknown, filter: unknown) => boolean;
17
+ readonly dateBefore: (value: unknown, filter: unknown) => boolean;
18
+ readonly dateAfter: (value: unknown, filter: unknown) => boolean;
19
+ };
20
+ export type BuiltInMatchMode = keyof typeof BUILT_IN_MATCHERS;
21
+ export declare function registerMatcher(name: string, fn: FilterMatcher): void;
22
+ export declare function unregisterMatcher(name: string): void;
23
+ export declare function getGlobalMatchers(): Readonly<Record<string, FilterMatcher>>;
@@ -0,0 +1,94 @@
1
+ import { BUILT_IN_MATCHERS, getGlobalMatchers, registerMatcher, unregisterMatcher, type BuiltInMatchMode, type FilterMatcher } from './_matchers';
2
+ export { registerMatcher, unregisterMatcher, BUILT_IN_MATCHERS, getGlobalMatchers };
3
+ export type { FilterMatcher, BuiltInMatchMode };
4
+ export type FilterOperator = 'and' | 'or';
5
+ export interface FilterConstraint<TMode extends string = string> {
6
+ value: unknown;
7
+ matchMode?: TMode;
8
+ }
9
+ export interface FilterRuleSimple<TMode extends string = string> {
10
+ field: string | string[];
11
+ value: unknown;
12
+ matchMode?: TMode;
13
+ operator?: never;
14
+ constraints?: never;
15
+ }
16
+ export interface FilterRuleComposite<TMode extends string = string> {
17
+ field: string | string[];
18
+ operator?: FilterOperator;
19
+ constraints: FilterConstraint<TMode>[];
20
+ value?: never;
21
+ matchMode?: never;
22
+ }
23
+ export type FilterRule<TMode extends string = string> = FilterRuleSimple<TMode> | FilterRuleComposite<TMode>;
24
+ export interface UseFilterOptions<T, TMode extends string = BuiltInMatchMode> {
25
+ data: T[];
26
+ /** Shorthand: target field for a single-rule filter. Use `rules` / `defaultRules` for multi-rule setups. */
27
+ field?: string | string[];
28
+ /** Shorthand: value for the single-rule filter declared via `field`. */
29
+ value?: unknown;
30
+ /** Shorthand: match mode for the single-rule filter declared via `field`. Defaults to `contains`. */
31
+ matchMode?: TMode;
32
+ /** Shorthand: callback when the single-rule value changes. */
33
+ onValueChange?: (value: unknown) => void;
34
+ /** Multi-rule controlled state. Omit and use `field/value` for a single rule. */
35
+ rules?: FilterRule<TMode>[];
36
+ /** Multi-rule uncontrolled initial state. */
37
+ defaultRules?: FilterRule<TMode>[];
38
+ matchers?: Partial<Record<TMode, FilterMatcher>> & Record<string, FilterMatcher>;
39
+ filterLocale?: string;
40
+ filterDelay?: number;
41
+ /** When true, `filteredData` is returned as-is; the consumer is responsible for filtering (server-side). */
42
+ lazy?: boolean;
43
+ /** Fires after rules settle (honours `filterDelay`). The consumer is expected to fetch a new `data` slice. */
44
+ onLazyLoad?: (event: LazyFilterEvent<TMode>) => void;
45
+ onRulesChange?: (rules: FilterRule<TMode>[]) => void;
46
+ }
47
+ export interface LazyFilterEvent<TMode extends string = string> {
48
+ rules: FilterRule<TMode>[];
49
+ filterLocale?: string;
50
+ }
51
+ export interface FilterConstraintCursor<TMode extends string = string> {
52
+ value: unknown;
53
+ matchMode: TMode | undefined;
54
+ setValue: (value: unknown) => void;
55
+ setMatchMode: (matchMode: TMode) => void;
56
+ remove: () => void;
57
+ }
58
+ export interface FilterRuleCursor<TMode extends string = string> {
59
+ field: string | string[];
60
+ value: unknown;
61
+ matchMode: TMode | undefined;
62
+ operator: FilterOperator | undefined;
63
+ constraints: FilterConstraint<TMode>[] | undefined;
64
+ setValue: (value: unknown) => void;
65
+ setMatchMode: (matchMode: TMode) => void;
66
+ setOperator: (operator: FilterOperator) => void;
67
+ addConstraint: (matchMode?: TMode) => void;
68
+ constraint: (index: number) => FilterConstraintCursor<TMode> | undefined;
69
+ remove: () => void;
70
+ clear: () => void;
71
+ }
72
+ export interface UseFilterReturn<T, TMode extends string = string> {
73
+ rules: FilterRule<TMode>[];
74
+ filteredData: T[];
75
+ isFiltered: boolean;
76
+ setRules: (rules: FilterRule<TMode>[]) => void;
77
+ setValue: (ruleIndex: number, value: unknown) => void;
78
+ setMatchMode: (ruleIndex: number, matchMode: TMode) => void;
79
+ setOperator: (ruleIndex: number, operator: FilterOperator) => void;
80
+ setConstraintValue: (ruleIndex: number, constraintIndex: number, value: unknown) => void;
81
+ setConstraintMatchMode: (ruleIndex: number, constraintIndex: number, matchMode: TMode) => void;
82
+ addRule: (rule: FilterRule<TMode>) => void;
83
+ removeRule: (ruleIndex: number) => void;
84
+ clearRule: (ruleIndex: number) => void;
85
+ addConstraint: (ruleIndex: number, matchMode?: TMode) => void;
86
+ removeConstraint: (ruleIndex: number, constraintIndex: number) => void;
87
+ clearAll: () => void;
88
+ rule: (ruleKey: number | string) => FilterRuleCursor<TMode> | undefined;
89
+ match: (item: T) => boolean;
90
+ matchers: Readonly<Record<string, FilterMatcher>>;
91
+ }
92
+ export declare function matchRule<T, TMode extends string>(item: T, rule: FilterRule<TMode>, matchers: Record<string, FilterMatcher>, locale?: string): boolean;
93
+ export declare function useFilter<T, TMode extends string = BuiltInMatchMode>(options: UseFilterOptions<T, TMode>): UseFilterReturn<T, TMode>;
94
+ export declare function ruleHasValue<TMode extends string>(rule: FilterRule<TMode>): boolean;
@@ -0,0 +1,2 @@
1
+ "use client";var fe=Object.defineProperty,me=Object.defineProperties;var Me=Object.getOwnPropertyDescriptors;var $=Object.getOwnPropertySymbols;var Te=Object.prototype.hasOwnProperty,Re=Object.prototype.propertyIsEnumerable;var ee=(e,t,u)=>t in e?fe(e,t,{enumerable:!0,configurable:!0,writable:!0,value:u}):e[t]=u,f=(e,t)=>{for(var u in t||(t={}))Te.call(t,u)&&ee(e,u,t[u]);if($)for(var u of $(t))Re.call(t,u)&&ee(e,u,t[u]);return e},M=(e,t)=>me(e,Me(t));import{resolveFieldData as re}from"@primeuix/utils/object";import*as i from"react";import{equals as ge,removeAccents as he}from"@primeuix/utils/object";function m(e){return!!e&&typeof e.getTime=="function"}function g(e,t){return he(String(e)).toLocaleLowerCase(t)}var te={startsWith(e,t,u){return t==null||t===""?!0:e==null?!1:g(e,u).startsWith(g(t,u))},contains(e,t,u){return t==null||t===""?!0:e==null?!1:g(e,u).indexOf(g(t,u))!==-1},notContains(e,t,u){return t==null||t===""?!0:e==null?!1:g(e,u).indexOf(g(t,u))===-1},endsWith(e,t,u){return t==null||t===""?!0:e==null?!1:g(e,u).endsWith(g(t,u))},equals(e,t,u){return t==null||t===""?!0:e==null?!1:m(e)&&m(t)?e.getTime()===t.getTime():g(e,u)===g(t,u)},notEquals(e,t,u){return t==null||t===""?!1:e==null?!0:m(e)&&m(t)?e.getTime()!==t.getTime():g(e,u)!==g(t,u)},in(e,t){if(!Array.isArray(t)||t.length===0)return!0;for(let u of t)if(ge(e,u))return!0;return!1},between(e,t){return!Array.isArray(t)||t[0]==null||t[1]==null?!0:e==null?!1:m(e)&&m(t[0])&&m(t[1])?t[0].getTime()<=e.getTime()&&e.getTime()<=t[1].getTime():t[0]<=e&&e<=t[1]},lt(e,t){return t==null?!0:e==null?!1:m(e)&&m(t)?e.getTime()<t.getTime():e<t},lte(e,t){return t==null?!0:e==null?!1:m(e)&&m(t)?e.getTime()<=t.getTime():e<=t},gt(e,t){return t==null?!0:e==null?!1:m(e)&&m(t)?e.getTime()>t.getTime():e>t},gte(e,t){return t==null?!0:e==null?!1:m(e)&&m(t)?e.getTime()>=t.getTime():e>=t},dateIs(e,t){return t==null?!0:e==null?!1:e.toDateString()===t.toDateString()},dateIsNot(e,t){return t==null?!0:e==null?!1:e.toDateString()!==t.toDateString()},dateBefore(e,t){return t==null?!0:e==null?!1:e.getTime()<t.getTime()},dateAfter(e,t){return t==null?!0:e==null?!1:e.getTime()>t.getTime()}},J={};function be(e,t){J[e]=t}function Fe(e){delete J[e]}function ne(){return J}function B(){return"contains"}function T(e){return Array.isArray(e.constraints)}function P(e,t,u,R,p,y){let b=y[R];return b?Array.isArray(t)?u==null||u===""?!0:t.some(x=>b(re(e,x),u,p)):b(typeof e=="object"?re(e,t):e,u,p):!0}function pe(e,t,u,R){var p,y,b;if(T(t)){let x=(p=t.constraints)!=null?p:[];return x.length===0?!0:((y=t.operator)!=null?y:"and")==="and"?x.every(C=>{var a;return P(e,t.field,C.value,(a=C.matchMode)!=null?a:B(),R,u)}):x.some(C=>{var a;return P(e,t.field,C.value,(a=C.matchMode)!=null?a:B(),R,u)})}return P(e,t.field,t.value,(b=t.matchMode)!=null?b:B(),R,u)}function we(e){var Y,Z;let t=e.field,u=e.matchMode,R=t!==void 0,p=R&&e.value!==void 0,y=i.useMemo(()=>{var r;return R?[{field:t,value:(r=e.value)!=null?r:null,matchMode:u}]:[]},[R,t,u]),b=e.rules!==void 0||p,[x,Q]=i.useState((Y=e.defaultRules)!=null?Y:R?y:[]),C=i.useMemo(()=>[{field:t,value:e.value,matchMode:u}],[t,e.value,u]),a=e.rules!==void 0?e.rules:p?C:x,w=i.useRef(e.onRulesChange),D=i.useRef(e.onValueChange);w.current=e.onRulesChange,D.current=e.onValueChange;let c=i.useCallback(r=>{var n,s;if(b||Q(r),(n=w.current)==null||n.call(w,r),R){let o=r[0];o&&!("constraints"in o)&&((s=D.current)==null||s.call(D,o.value))}},[b,R]),A=e.filterLocale,L=(Z=e.filterDelay)!=null?Z:0,E=i.useMemo(()=>{var r;return f(f(f({},te),ne()),(r=e.matchers)!=null?r:{})},[e.matchers]),[ue,oe]=i.useState(a);i.useEffect(()=>{if(L<=0)return;let r=setTimeout(()=>oe(a),L);return()=>clearTimeout(r)},[a,L]);let k=L>0?ue:a,I=i.useMemo(()=>k.filter(r=>xe(r)),[k]),z=i.useCallback(r=>I.every(n=>pe(r,n,E,A)),[I,E,A]),S=!!e.lazy,ae=i.useMemo(()=>S||I.length===0?e.data:e.data.filter(z),[S,e.data,I,z]),se=I.length>0,O=i.useRef(e.onLazyLoad);O.current=e.onLazyLoad;let X=i.useRef(null);i.useEffect(()=>{var n;if(!S)return;let r=JSON.stringify(k);X.current!==r&&(X.current=r,(n=O.current)==null||n.call(O,{rules:k,filterLocale:A}))},[S,k,A]);let ie=i.useCallback(r=>c(r),[c]),_=i.useCallback((r,n)=>{let s=a.map((o,d)=>d===r?M(f({},o),{value:n}):o);c(s)},[a,c]),U=i.useCallback((r,n)=>{let s=a.map((o,d)=>d===r?M(f({},o),{matchMode:n}):o);c(s)},[a,c]),V=i.useCallback((r,n)=>{let s=a.map((o,d)=>d!==r?o:T(o)?M(f({},o),{operator:n}):{field:o.field,operator:n,constraints:[{value:o.value,matchMode:o.matchMode}]});c(s)},[a,c]),N=i.useCallback((r,n,s)=>{let o=a.map((d,l)=>{var h;if(l!==r)return d;let v=T(d)?d.constraints.map((F,K)=>K===n?M(f({},F),{value:s}):F):n===0?[{value:s,matchMode:d.matchMode}]:(h=d.constraints)!=null?h:[];return{field:d.field,operator:T(d)?d.operator:void 0,constraints:v}});c(o)},[a,c]),H=i.useCallback((r,n,s)=>{let o=a.map((d,l)=>{var h;if(l!==r)return d;let v=T(d)?d.constraints.map((F,K)=>K===n?M(f({},F),{matchMode:s}):F):n===0?[{value:d.value,matchMode:s}]:(h=d.constraints)!=null?h:[];return{field:d.field,operator:T(d)?d.operator:void 0,constraints:v}});c(o)},[a,c]),de=i.useCallback(r=>c([...a,r]),[a,c]),W=i.useCallback(r=>{let n=a.filter((s,o)=>o!==r);c(n)},[a,c]),q=i.useCallback(r=>{let n=a.map((s,o)=>o!==r?s:T(s)?M(f({},s),{constraints:s.constraints.map(d=>M(f({},d),{value:null}))}):M(f({},s),{value:null}));c(n)},[a,c]),G=i.useCallback((r,n)=>{let s=a.map((o,d)=>{if(d!==r)return o;let l=T(o)?o.constraints:[{value:o.value,matchMode:o.matchMode}];return{field:o.field,operator:T(o)?o.operator:"and",constraints:[...l,{value:null,matchMode:n!=null?n:B()}]}});c(s)},[a,c]),j=i.useCallback((r,n)=>{let s=a.map((o,d)=>{if(d!==r||!T(o))return o;let l=o.constraints.filter((v,h)=>h!==n);return l.length===0?o:M(f({},o),{constraints:l})});c(s)},[a,c]),le=i.useCallback(()=>{let r=a.map(n=>T(n)?M(f({},n),{constraints:n.constraints.map(s=>M(f({},s),{value:null}))}):M(f({},n),{value:null}));c(r)},[a,c]),ce=i.useCallback(r=>{let n=typeof r=="number"?r:a.findIndex(l=>Array.isArray(l.field)?l.field.join(",")===r:l.field===r);if(n<0||!a[n])return;let s=a[n],o=T(s),d=l=>{let v=o?s.constraints:[{value:s.value,matchMode:s.matchMode}];if(l<0||l>=v.length)return;let h=v[l];return{value:h.value,matchMode:h.matchMode,setValue:F=>N(n,l,F),setMatchMode:F=>H(n,l,F),remove:()=>j(n,l)}};return{field:s.field,value:o?void 0:s.value,matchMode:o?void 0:s.matchMode,operator:o?s.operator:void 0,constraints:o?s.constraints:void 0,setValue:l=>_(n,l),setMatchMode:l=>U(n,l),setOperator:l=>V(n,l),addConstraint:l=>G(n,l),constraint:d,remove:()=>W(n),clear:()=>q(n)}},[a,_,U,V,N,H,G,j,W,q]);return{rules:a,filteredData:ae,isFiltered:se,setRules:ie,setValue:_,setMatchMode:U,setOperator:V,setConstraintValue:N,setConstraintMatchMode:H,addRule:de,removeRule:W,clearRule:q,addConstraint:G,removeConstraint:j,clearAll:le,rule:ce,match:z,matchers:E}}function xe(e){return T(e)?e.constraints.some(t=>t.value!==null&&t.value!==void 0&&t.value!==""):e.value!==null&&e.value!==void 0&&e.value!==""}export{te as BUILT_IN_MATCHERS,ne as getGlobalMatchers,pe as matchRule,be as registerMatcher,xe as ruleHasValue,Fe as unregisterMatcher,we as useFilter};
2
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/use-filter/index.ts","../../src/use-filter/_matchers.ts"],"sourcesContent":["'use client';\nimport { resolveFieldData } from '@primeuix/utils/object';\nimport * as React from 'react';\nimport { BUILT_IN_MATCHERS, getGlobalMatchers, registerMatcher, unregisterMatcher, type BuiltInMatchMode, type FilterMatcher } from './_matchers';\n\nexport { registerMatcher, unregisterMatcher, BUILT_IN_MATCHERS, getGlobalMatchers };\nexport type { FilterMatcher, BuiltInMatchMode };\n\nexport type FilterOperator = 'and' | 'or';\n\nexport interface FilterConstraint<TMode extends string = string> {\n value: unknown;\n matchMode?: TMode;\n}\n\nexport interface FilterRuleSimple<TMode extends string = string> {\n field: string | string[];\n value: unknown;\n matchMode?: TMode;\n operator?: never;\n constraints?: never;\n}\n\nexport interface FilterRuleComposite<TMode extends string = string> {\n field: string | string[];\n operator?: FilterOperator;\n constraints: FilterConstraint<TMode>[];\n value?: never;\n matchMode?: never;\n}\n\nexport type FilterRule<TMode extends string = string> = FilterRuleSimple<TMode> | FilterRuleComposite<TMode>;\n\nexport interface UseFilterOptions<T, TMode extends string = BuiltInMatchMode> {\n data: T[];\n /** Shorthand: target field for a single-rule filter. Use `rules` / `defaultRules` for multi-rule setups. */\n field?: string | string[];\n /** Shorthand: value for the single-rule filter declared via `field`. */\n value?: unknown;\n /** Shorthand: match mode for the single-rule filter declared via `field`. Defaults to `contains`. */\n matchMode?: TMode;\n /** Shorthand: callback when the single-rule value changes. */\n onValueChange?: (value: unknown) => void;\n /** Multi-rule controlled state. Omit and use `field/value` for a single rule. */\n rules?: FilterRule<TMode>[];\n /** Multi-rule uncontrolled initial state. */\n defaultRules?: FilterRule<TMode>[];\n matchers?: Partial<Record<TMode, FilterMatcher>> & Record<string, FilterMatcher>;\n filterLocale?: string;\n filterDelay?: number;\n /** When true, `filteredData` is returned as-is; the consumer is responsible for filtering (server-side). */\n lazy?: boolean;\n /** Fires after rules settle (honours `filterDelay`). The consumer is expected to fetch a new `data` slice. */\n onLazyLoad?: (event: LazyFilterEvent<TMode>) => void;\n onRulesChange?: (rules: FilterRule<TMode>[]) => void;\n}\n\nexport interface LazyFilterEvent<TMode extends string = string> {\n rules: FilterRule<TMode>[];\n filterLocale?: string;\n}\n\nexport interface FilterConstraintCursor<TMode extends string = string> {\n value: unknown;\n matchMode: TMode | undefined;\n setValue: (value: unknown) => void;\n setMatchMode: (matchMode: TMode) => void;\n remove: () => void;\n}\n\nexport interface FilterRuleCursor<TMode extends string = string> {\n field: string | string[];\n value: unknown;\n matchMode: TMode | undefined;\n operator: FilterOperator | undefined;\n constraints: FilterConstraint<TMode>[] | undefined;\n setValue: (value: unknown) => void;\n setMatchMode: (matchMode: TMode) => void;\n setOperator: (operator: FilterOperator) => void;\n addConstraint: (matchMode?: TMode) => void;\n constraint: (index: number) => FilterConstraintCursor<TMode> | undefined;\n remove: () => void;\n clear: () => void;\n}\n\nexport interface UseFilterReturn<T, TMode extends string = string> {\n rules: FilterRule<TMode>[];\n filteredData: T[];\n isFiltered: boolean;\n\n setRules: (rules: FilterRule<TMode>[]) => void;\n setValue: (ruleIndex: number, value: unknown) => void;\n setMatchMode: (ruleIndex: number, matchMode: TMode) => void;\n setOperator: (ruleIndex: number, operator: FilterOperator) => void;\n setConstraintValue: (ruleIndex: number, constraintIndex: number, value: unknown) => void;\n setConstraintMatchMode: (ruleIndex: number, constraintIndex: number, matchMode: TMode) => void;\n addRule: (rule: FilterRule<TMode>) => void;\n removeRule: (ruleIndex: number) => void;\n clearRule: (ruleIndex: number) => void;\n addConstraint: (ruleIndex: number, matchMode?: TMode) => void;\n removeConstraint: (ruleIndex: number, constraintIndex: number) => void;\n clearAll: () => void;\n\n rule: (ruleKey: number | string) => FilterRuleCursor<TMode> | undefined;\n\n match: (item: T) => boolean;\n matchers: Readonly<Record<string, FilterMatcher>>;\n}\n\nfunction defaultMatchMode(): BuiltInMatchMode {\n return 'contains';\n}\n\nfunction ruleIsComposite<TMode extends string>(rule: FilterRule<TMode>): rule is FilterRuleComposite<TMode> {\n return Array.isArray((rule as FilterRuleComposite<TMode>).constraints);\n}\n\nfunction matchFields(item: unknown, field: string | string[], filterValue: unknown, matchMode: string, locale: string | undefined, matchers: Record<string, FilterMatcher>): boolean {\n const rule = matchers[matchMode];\n\n if (!rule) return true;\n\n if (Array.isArray(field)) {\n if (filterValue === undefined || filterValue === null || filterValue === '') return true;\n\n return field.some((f) => rule(resolveFieldData(item as Record<string, unknown>, f), filterValue, locale));\n }\n\n return rule(typeof item === 'object' ? resolveFieldData(item as Record<string, unknown>, field) : item, filterValue, locale);\n}\n\nexport function matchRule<T, TMode extends string>(item: T, rule: FilterRule<TMode>, matchers: Record<string, FilterMatcher>, locale?: string): boolean {\n if (ruleIsComposite(rule)) {\n const constraints = rule.constraints ?? [];\n\n if (constraints.length === 0) return true;\n\n const operator = rule.operator ?? 'and';\n\n if (operator === 'and') {\n return constraints.every((c) => matchFields(item, rule.field, c.value, c.matchMode ?? defaultMatchMode(), locale, matchers));\n }\n\n return constraints.some((c) => matchFields(item, rule.field, c.value, c.matchMode ?? defaultMatchMode(), locale, matchers));\n }\n\n return matchFields(item, rule.field, rule.value, rule.matchMode ?? defaultMatchMode(), locale, matchers);\n}\n\nexport function useFilter<T, TMode extends string = BuiltInMatchMode>(options: UseFilterOptions<T, TMode>): UseFilterReturn<T, TMode> {\n const shorthandField = options.field;\n const shorthandMatchMode = options.matchMode;\n const hasShorthand = shorthandField !== undefined;\n const shorthandControlled = hasShorthand && options.value !== undefined;\n\n const initialShorthandRule = React.useMemo<FilterRule<TMode>[]>(() => {\n if (!hasShorthand) return [];\n\n return [{ field: shorthandField!, value: options.value ?? null, matchMode: shorthandMatchMode } as FilterRule<TMode>];\n }, [hasShorthand, shorthandField, shorthandMatchMode]);\n\n const isControlled = options.rules !== undefined || shorthandControlled;\n const [internalRules, setInternalRules] = React.useState<FilterRule<TMode>[]>(options.defaultRules ?? (hasShorthand ? initialShorthandRule : []));\n\n const shorthandRules = React.useMemo<FilterRule<TMode>[]>(() => [{ field: shorthandField!, value: options.value, matchMode: shorthandMatchMode } as FilterRule<TMode>], [shorthandField, options.value, shorthandMatchMode]);\n\n const currentRules = options.rules !== undefined ? options.rules : shorthandControlled ? shorthandRules : internalRules;\n\n const onRulesChangeRef = React.useRef(options.onRulesChange);\n const onValueChangeRef = React.useRef(options.onValueChange);\n\n onRulesChangeRef.current = options.onRulesChange;\n onValueChangeRef.current = options.onValueChange;\n\n const commit = React.useCallback(\n (next: FilterRule<TMode>[]) => {\n if (!isControlled) setInternalRules(next);\n onRulesChangeRef.current?.(next);\n\n if (hasShorthand) {\n const first = next[0];\n\n if (first && !('constraints' in first)) onValueChangeRef.current?.(first.value);\n }\n },\n [isControlled, hasShorthand]\n );\n\n const filterLocale = options.filterLocale;\n const filterDelay = options.filterDelay ?? 0;\n\n const matchers = React.useMemo<Record<string, FilterMatcher>>(() => {\n return { ...(BUILT_IN_MATCHERS as Record<string, FilterMatcher>), ...getGlobalMatchers(), ...(options.matchers ?? {}) };\n }, [options.matchers]);\n\n const [debouncedRules, setDebouncedRules] = React.useState<FilterRule<TMode>[]>(currentRules);\n\n React.useEffect(() => {\n if (filterDelay <= 0) return;\n\n const t = setTimeout(() => setDebouncedRules(currentRules), filterDelay);\n\n return () => clearTimeout(t);\n }, [currentRules, filterDelay]);\n\n const activeRules = filterDelay > 0 ? debouncedRules : currentRules;\n\n const activeRulesNonEmpty = React.useMemo(() => activeRules.filter((r) => ruleHasValue(r)), [activeRules]);\n\n const match = React.useCallback((item: T) => activeRulesNonEmpty.every((r) => matchRule(item, r, matchers, filterLocale)), [activeRulesNonEmpty, matchers, filterLocale]);\n\n const lazy = !!options.lazy;\n\n const filteredData = React.useMemo(() => {\n if (lazy) return options.data;\n\n if (activeRulesNonEmpty.length === 0) return options.data;\n\n return options.data.filter(match);\n }, [lazy, options.data, activeRulesNonEmpty, match]);\n\n const isFiltered = activeRulesNonEmpty.length > 0;\n\n const onLazyLoadRef = React.useRef(options.onLazyLoad);\n\n onLazyLoadRef.current = options.onLazyLoad;\n\n const lastLazyKeyRef = React.useRef<string | null>(null);\n\n React.useEffect(() => {\n if (!lazy) return;\n\n const key = JSON.stringify(activeRules);\n\n if (lastLazyKeyRef.current === key) return;\n\n lastLazyKeyRef.current = key;\n onLazyLoadRef.current?.({ rules: activeRules, filterLocale });\n }, [lazy, activeRules, filterLocale]);\n\n const setRules = React.useCallback((next: FilterRule<TMode>[]) => commit(next), [commit]);\n\n const setValue = React.useCallback(\n (ruleIndex: number, value: unknown) => {\n const next = currentRules.map((r, i) => (i === ruleIndex ? { ...(r as FilterRuleSimple<TMode>), value } : r));\n\n commit(next);\n },\n [currentRules, commit]\n );\n\n const setMatchMode = React.useCallback(\n (ruleIndex: number, matchMode: TMode) => {\n const next = currentRules.map((r, i) => (i === ruleIndex ? { ...(r as FilterRuleSimple<TMode>), matchMode } : r));\n\n commit(next);\n },\n [currentRules, commit]\n );\n\n const setOperator = React.useCallback(\n (ruleIndex: number, operator: FilterOperator) => {\n const next = currentRules.map((r, i) => {\n if (i !== ruleIndex) return r;\n\n if (!ruleIsComposite(r)) {\n return { field: r.field, operator, constraints: [{ value: r.value, matchMode: r.matchMode }] } as FilterRule<TMode>;\n }\n\n return { ...r, operator };\n });\n\n commit(next);\n },\n [currentRules, commit]\n );\n\n const setConstraintValue = React.useCallback(\n (ruleIndex: number, constraintIndex: number, value: unknown) => {\n const next = currentRules.map((r, i) => {\n if (i !== ruleIndex) return r;\n\n const constraints = ruleIsComposite(r) ? r.constraints.map((c, ci) => (ci === constraintIndex ? { ...c, value } : c)) : constraintIndex === 0 ? [{ value, matchMode: r.matchMode }] : (r.constraints ?? []);\n\n return { field: r.field, operator: ruleIsComposite(r) ? r.operator : undefined, constraints } as FilterRule<TMode>;\n });\n\n commit(next);\n },\n [currentRules, commit]\n );\n\n const setConstraintMatchMode = React.useCallback(\n (ruleIndex: number, constraintIndex: number, matchMode: TMode) => {\n const next = currentRules.map((r, i) => {\n if (i !== ruleIndex) return r;\n\n const constraints = ruleIsComposite(r) ? r.constraints.map((c, ci) => (ci === constraintIndex ? { ...c, matchMode } : c)) : constraintIndex === 0 ? [{ value: r.value, matchMode }] : (r.constraints ?? []);\n\n return { field: r.field, operator: ruleIsComposite(r) ? r.operator : undefined, constraints } as FilterRule<TMode>;\n });\n\n commit(next);\n },\n [currentRules, commit]\n );\n\n const addRule = React.useCallback((rule: FilterRule<TMode>) => commit([...currentRules, rule]), [currentRules, commit]);\n\n const removeRule = React.useCallback(\n (ruleIndex: number) => {\n const next = currentRules.filter((_, i) => i !== ruleIndex);\n\n commit(next);\n },\n [currentRules, commit]\n );\n\n const clearRule = React.useCallback(\n (ruleIndex: number) => {\n const next = currentRules.map((r, i) => {\n if (i !== ruleIndex) return r;\n\n if (ruleIsComposite(r)) {\n return { ...r, constraints: r.constraints.map((c) => ({ ...c, value: null })) };\n }\n\n return { ...r, value: null };\n });\n\n commit(next);\n },\n [currentRules, commit]\n );\n\n const addConstraint = React.useCallback(\n (ruleIndex: number, matchMode?: TMode) => {\n const next = currentRules.map((r, i) => {\n if (i !== ruleIndex) return r;\n\n const base = ruleIsComposite(r) ? r.constraints : [{ value: r.value, matchMode: r.matchMode }];\n\n return {\n field: r.field,\n operator: ruleIsComposite(r) ? r.operator : 'and',\n constraints: [...base, { value: null, matchMode: matchMode ?? (defaultMatchMode() as unknown as TMode) }]\n } as FilterRule<TMode>;\n });\n\n commit(next);\n },\n [currentRules, commit]\n );\n\n const removeConstraint = React.useCallback(\n (ruleIndex: number, constraintIndex: number) => {\n const next = currentRules.map((r, i) => {\n if (i !== ruleIndex || !ruleIsComposite(r)) return r;\n\n const filtered = r.constraints.filter((_, ci) => ci !== constraintIndex);\n\n if (filtered.length === 0) return r;\n\n return { ...r, constraints: filtered };\n });\n\n commit(next);\n },\n [currentRules, commit]\n );\n\n const clearAll = React.useCallback(() => {\n const next = currentRules.map((r) => (ruleIsComposite(r) ? { ...r, constraints: r.constraints.map((c) => ({ ...c, value: null })) } : { ...r, value: null }));\n\n commit(next);\n }, [currentRules, commit]);\n\n const rule = React.useCallback(\n (key: number | string): FilterRuleCursor<TMode> | undefined => {\n const index = typeof key === 'number' ? key : currentRules.findIndex((r) => (Array.isArray(r.field) ? r.field.join(',') === key : r.field === key));\n\n if (index < 0 || !currentRules[index]) return undefined;\n\n const r = currentRules[index];\n const composite = ruleIsComposite(r);\n\n const constraintCursor = (ci: number): FilterConstraintCursor<TMode> | undefined => {\n const list = composite ? r.constraints : [{ value: r.value, matchMode: r.matchMode }];\n\n if (ci < 0 || ci >= list.length) return undefined;\n\n const c = list[ci];\n\n return {\n value: c.value,\n matchMode: c.matchMode,\n setValue: (v) => setConstraintValue(index, ci, v),\n setMatchMode: (m) => setConstraintMatchMode(index, ci, m),\n remove: () => removeConstraint(index, ci)\n };\n };\n\n return {\n field: r.field,\n value: composite ? undefined : r.value,\n matchMode: composite ? undefined : r.matchMode,\n operator: composite ? r.operator : undefined,\n constraints: composite ? r.constraints : undefined,\n setValue: (v) => setValue(index, v),\n setMatchMode: (m) => setMatchMode(index, m),\n setOperator: (op) => setOperator(index, op),\n addConstraint: (mm) => addConstraint(index, mm),\n constraint: constraintCursor,\n remove: () => removeRule(index),\n clear: () => clearRule(index)\n };\n },\n [currentRules, setValue, setMatchMode, setOperator, setConstraintValue, setConstraintMatchMode, addConstraint, removeConstraint, removeRule, clearRule]\n );\n\n return {\n rules: currentRules,\n filteredData,\n isFiltered,\n setRules,\n setValue,\n setMatchMode,\n setOperator,\n setConstraintValue,\n setConstraintMatchMode,\n addRule,\n removeRule,\n clearRule,\n addConstraint,\n removeConstraint,\n clearAll,\n rule,\n match,\n matchers\n };\n}\n\nexport function ruleHasValue<TMode extends string>(rule: FilterRule<TMode>): boolean {\n if (ruleIsComposite(rule)) {\n return rule.constraints.some((c) => c.value !== null && c.value !== undefined && c.value !== '');\n }\n\n return rule.value !== null && rule.value !== undefined && rule.value !== '';\n}\n","import { equals, removeAccents } from '@primeuix/utils/object';\n\nexport type FilterMatcher = (value: unknown, filter: unknown, filterLocale?: string) => boolean;\n\nfunction hasGetTime(x: unknown): x is { getTime: () => number } {\n return !!x && typeof (x as { getTime?: unknown }).getTime === 'function';\n}\n\nfunction norm(v: unknown, locale?: string) {\n return removeAccents(String(v)).toLocaleLowerCase(locale);\n}\n\nexport const BUILT_IN_MATCHERS = {\n startsWith(value, filter, locale) {\n if (filter === undefined || filter === null || filter === '') return true;\n if (value === undefined || value === null) return false;\n\n return norm(value, locale).startsWith(norm(filter, locale));\n },\n contains(value, filter, locale) {\n if (filter === undefined || filter === null || filter === '') return true;\n if (value === undefined || value === null) return false;\n\n return norm(value, locale).indexOf(norm(filter, locale)) !== -1;\n },\n notContains(value, filter, locale) {\n if (filter === undefined || filter === null || filter === '') return true;\n if (value === undefined || value === null) return false;\n\n return norm(value, locale).indexOf(norm(filter, locale)) === -1;\n },\n endsWith(value, filter, locale) {\n if (filter === undefined || filter === null || filter === '') return true;\n if (value === undefined || value === null) return false;\n\n return norm(value, locale).endsWith(norm(filter, locale));\n },\n equals(value, filter, locale) {\n if (filter === undefined || filter === null || filter === '') return true;\n if (value === undefined || value === null) return false;\n\n if (hasGetTime(value) && hasGetTime(filter)) return value.getTime() === filter.getTime();\n\n return norm(value, locale) === norm(filter, locale);\n },\n notEquals(value, filter, locale) {\n if (filter === undefined || filter === null || filter === '') return false;\n if (value === undefined || value === null) return true;\n\n if (hasGetTime(value) && hasGetTime(filter)) return value.getTime() !== filter.getTime();\n\n return norm(value, locale) !== norm(filter, locale);\n },\n in(value, filter) {\n if (!Array.isArray(filter) || filter.length === 0) return true;\n\n for (const f of filter) if (equals(value, f)) return true;\n\n return false;\n },\n between(value, filter) {\n if (!Array.isArray(filter) || filter[0] == null || filter[1] == null) return true;\n if (value === undefined || value === null) return false;\n\n if (hasGetTime(value) && hasGetTime(filter[0]) && hasGetTime(filter[1])) {\n return (filter[0] as { getTime: () => number }).getTime() <= value.getTime() && value.getTime() <= (filter[1] as { getTime: () => number }).getTime();\n }\n\n return (filter[0] as number) <= (value as number) && (value as number) <= (filter[1] as number);\n },\n lt(value, filter) {\n if (filter === undefined || filter === null) return true;\n if (value === undefined || value === null) return false;\n\n if (hasGetTime(value) && hasGetTime(filter)) return value.getTime() < filter.getTime();\n\n return (value as number) < (filter as number);\n },\n lte(value, filter) {\n if (filter === undefined || filter === null) return true;\n if (value === undefined || value === null) return false;\n\n if (hasGetTime(value) && hasGetTime(filter)) return value.getTime() <= filter.getTime();\n\n return (value as number) <= (filter as number);\n },\n gt(value, filter) {\n if (filter === undefined || filter === null) return true;\n if (value === undefined || value === null) return false;\n\n if (hasGetTime(value) && hasGetTime(filter)) return value.getTime() > filter.getTime();\n\n return (value as number) > (filter as number);\n },\n gte(value, filter) {\n if (filter === undefined || filter === null) return true;\n if (value === undefined || value === null) return false;\n\n if (hasGetTime(value) && hasGetTime(filter)) return value.getTime() >= filter.getTime();\n\n return (value as number) >= (filter as number);\n },\n dateIs(value, filter) {\n if (filter === undefined || filter === null) return true;\n if (value === undefined || value === null) return false;\n\n return (value as Date).toDateString() === (filter as Date).toDateString();\n },\n dateIsNot(value, filter) {\n if (filter === undefined || filter === null) return true;\n if (value === undefined || value === null) return false;\n\n return (value as Date).toDateString() !== (filter as Date).toDateString();\n },\n dateBefore(value, filter) {\n if (filter === undefined || filter === null) return true;\n if (value === undefined || value === null) return false;\n\n return (value as Date).getTime() < (filter as Date).getTime();\n },\n dateAfter(value, filter) {\n if (filter === undefined || filter === null) return true;\n if (value === undefined || value === null) return false;\n\n return (value as Date).getTime() > (filter as Date).getTime();\n }\n} as const satisfies Record<string, FilterMatcher>;\n\nexport type BuiltInMatchMode = keyof typeof BUILT_IN_MATCHERS;\n\nconst globalMatchers: Record<string, FilterMatcher> = {};\n\nexport function registerMatcher(name: string, fn: FilterMatcher): void {\n globalMatchers[name] = fn;\n}\n\nexport function unregisterMatcher(name: string): void {\n delete globalMatchers[name];\n}\n\nexport function getGlobalMatchers(): Readonly<Record<string, FilterMatcher>> {\n return globalMatchers;\n}\n"],"mappings":"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","names":["resolveFieldData","React","equals","removeAccents","hasGetTime","x","norm","v","locale","BUILT_IN_MATCHERS","value","filter","f","globalMatchers","registerMatcher","name","fn","unregisterMatcher","getGlobalMatchers","defaultMatchMode","ruleIsComposite","rule","matchFields","item","field","filterValue","matchMode","locale","matchers","f","resolveFieldData","matchRule","_a","_b","_c","constraints","c","useFilter","options","shorthandField","shorthandMatchMode","hasShorthand","shorthandControlled","initialShorthandRule","isControlled","internalRules","setInternalRules","shorthandRules","currentRules","onRulesChangeRef","onValueChangeRef","commit","next","first","filterLocale","filterDelay","__spreadValues","BUILT_IN_MATCHERS","getGlobalMatchers","debouncedRules","setDebouncedRules","t","activeRules","activeRulesNonEmpty","ruleHasValue","match","r","lazy","filteredData","isFiltered","onLazyLoadRef","lastLazyKeyRef","key","setRules","setValue","ruleIndex","value","i","__spreadProps","setMatchMode","setOperator","operator","setConstraintValue","constraintIndex","ci","setConstraintMatchMode","addRule","removeRule","_","clearRule","addConstraint","base","removeConstraint","filtered","clearAll","index","composite","constraintCursor","list","v","m","op","mm"]}
@@ -0,0 +1,25 @@
1
+ export type UseHotKeyTarget = Document | HTMLElement | null | undefined;
2
+ export interface UseHotKeyOptions {
3
+ /**
4
+ * Target to listen on. Defaults to `document` when available.
5
+ */
6
+ target?: UseHotKeyTarget;
7
+ /**
8
+ * Keyboard event type.
9
+ * @default 'keydown'
10
+ */
11
+ event?: 'keydown' | 'keyup' | 'keypress';
12
+ /**
13
+ * Enables or disables the listener.
14
+ * @default true
15
+ */
16
+ when?: boolean;
17
+ }
18
+ /**
19
+ * Runs the provided handler when any of the given keys is pressed.
20
+ *
21
+ * @param keys A single key or an array of keys to listen for (e.g. 'k' or 'ctrl+k').
22
+ * @param handler Callback fired when a matching key event occurs.
23
+ * @param options Optional configuration for target, event type, and enable flag.
24
+ */
25
+ export declare function useHotKey(keys: string | string[], handler: (event: KeyboardEvent) => void, options?: UseHotKeyOptions): void;
@@ -0,0 +1,2 @@
1
+ import*as a from"react";function k(o,u,p={}){let{target:c,event:f="keydown",when:l=!0}=p,i=a.useRef(u),y=t=>{let e=t.toLowerCase();return e==="space"||e==="spacebar"?" ":e},d=t=>{let e=t.split("+").map(s=>s.trim().toLowerCase()).filter(Boolean),r,n={ctrl:!1,meta:!1,alt:!1,shift:!1};return e.forEach(s=>{switch(s){case"ctrl":case"control":n.ctrl=!0;break;case"meta":case"cmd":case"command":n.meta=!0;break;case"alt":case"option":n.alt=!0;break;case"shift":n.shift=!0;break;default:r=y(s)}}),{key:r,required:n}},K=(t,e)=>{if(!t.key)return!1;let{required:r}=t;return r.ctrl!==e.ctrlKey||r.meta!==e.metaKey||r.alt!==e.altKey||r.shift!==e.shiftKey?!1:y(e.key)===t.key};a.useEffect(()=>{i.current=u},[u]),a.useEffect(()=>{if(!l)return;let t=c!=null?c:typeof document!="undefined"?document:null;if(!t)return;let e=(Array.isArray(o)?o:[o]).map(d),r=n=>{var m;let s=n;e.some(E=>K(E,s))&&((m=i.current)==null||m.call(i,s))};return t.addEventListener(f,r),()=>{t.removeEventListener(f,r)}},[f,o,c,l])}export{k as useHotKey};
2
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/use-hot-key/index.ts"],"sourcesContent":["import * as React from 'react';\n\nexport type UseHotKeyTarget = Document | HTMLElement | null | undefined;\n\nexport interface UseHotKeyOptions {\n /**\n * Target to listen on. Defaults to `document` when available.\n */\n target?: UseHotKeyTarget;\n /**\n * Keyboard event type.\n * @default 'keydown'\n */\n event?: 'keydown' | 'keyup' | 'keypress';\n /**\n * Enables or disables the listener.\n * @default true\n */\n when?: boolean;\n}\n\n/**\n * Runs the provided handler when any of the given keys is pressed.\n *\n * @param keys A single key or an array of keys to listen for (e.g. 'k' or 'ctrl+k').\n * @param handler Callback fired when a matching key event occurs.\n * @param options Optional configuration for target, event type, and enable flag.\n */\nexport function useHotKey(keys: string | string[], handler: (event: KeyboardEvent) => void, options: UseHotKeyOptions = {}) {\n const { target, event = 'keydown', when = true } = options;\n const handlerRef = React.useRef(handler);\n\n const normalizeKey = (key: string) => {\n const lower = key.toLowerCase();\n\n if (lower === 'space' || lower === 'spacebar') return ' ';\n\n return lower;\n };\n\n const parseKeySpec = (spec: string) => {\n const parts = spec\n .split('+')\n .map((p) => p.trim().toLowerCase())\n .filter(Boolean);\n\n let key: string | undefined;\n const required = {\n ctrl: false,\n meta: false,\n alt: false,\n shift: false\n };\n\n parts.forEach((part) => {\n switch (part) {\n case 'ctrl':\n case 'control':\n required.ctrl = true;\n break;\n case 'meta':\n case 'cmd':\n case 'command':\n required.meta = true;\n break;\n case 'alt':\n case 'option':\n required.alt = true;\n break;\n case 'shift':\n required.shift = true;\n break;\n default:\n key = normalizeKey(part);\n }\n });\n\n return { key, required };\n };\n\n const matches = (spec: ReturnType<typeof parseKeySpec>, event: KeyboardEvent) => {\n if (!spec.key) return false;\n\n const { required } = spec;\n\n if (required.ctrl !== event.ctrlKey || required.meta !== event.metaKey || required.alt !== event.altKey || required.shift !== event.shiftKey) {\n return false;\n }\n\n return normalizeKey(event.key) === spec.key;\n };\n\n React.useEffect(() => {\n handlerRef.current = handler;\n }, [handler]);\n\n React.useEffect(() => {\n if (!when) {\n return;\n }\n\n const targetElement: UseHotKeyTarget = target ?? (typeof document !== 'undefined' ? document : null);\n\n if (!targetElement) {\n return;\n }\n\n const keySpecs = (Array.isArray(keys) ? keys : [keys]).map(parseKeySpec);\n\n const listener: EventListener = (event) => {\n const keyboardEvent = event as KeyboardEvent;\n\n if (keySpecs.some((spec) => matches(spec, keyboardEvent))) {\n handlerRef.current?.(keyboardEvent);\n }\n };\n\n targetElement.addEventListener(event, listener);\n\n return () => {\n targetElement.removeEventListener(event, listener);\n };\n }, [event, keys, target, when]);\n}\n"],"mappings":"AAAA,UAAYA,MAAW,QA4BhB,SAASC,EAAUC,EAAyBC,EAAyCC,EAA4B,CAAC,EAAG,CACxH,GAAM,CAAE,OAAAC,EAAQ,MAAAC,EAAQ,UAAW,KAAAC,EAAO,EAAK,EAAIH,EAC7CI,EAAmB,SAAOL,CAAO,EAEjCM,EAAgBC,GAAgB,CAClC,IAAMC,EAAQD,EAAI,YAAY,EAE9B,OAAIC,IAAU,SAAWA,IAAU,WAAmB,IAE/CA,CACX,EAEMC,EAAgBC,GAAiB,CACnC,IAAMC,EAAQD,EACT,MAAM,GAAG,EACT,IAAKE,GAAMA,EAAE,KAAK,EAAE,YAAY,CAAC,EACjC,OAAO,OAAO,EAEfL,EACEM,EAAW,CACb,KAAM,GACN,KAAM,GACN,IAAK,GACL,MAAO,EACX,EAEA,OAAAF,EAAM,QAASG,GAAS,CACpB,OAAQA,EAAM,CACV,IAAK,OACL,IAAK,UACDD,EAAS,KAAO,GAChB,MACJ,IAAK,OACL,IAAK,MACL,IAAK,UACDA,EAAS,KAAO,GAChB,MACJ,IAAK,MACL,IAAK,SACDA,EAAS,IAAM,GACf,MACJ,IAAK,QACDA,EAAS,MAAQ,GACjB,MACJ,QACIN,EAAMD,EAAaQ,CAAI,CAC/B,CACJ,CAAC,EAEM,CAAE,IAAAP,EAAK,SAAAM,CAAS,CAC3B,EAEME,EAAU,CAACL,EAAuCP,IAAyB,CAC7E,GAAI,CAACO,EAAK,IAAK,MAAO,GAEtB,GAAM,CAAE,SAAAG,CAAS,EAAIH,EAErB,OAAIG,EAAS,OAASV,EAAM,SAAWU,EAAS,OAASV,EAAM,SAAWU,EAAS,MAAQV,EAAM,QAAUU,EAAS,QAAUV,EAAM,SACzH,GAGJG,EAAaH,EAAM,GAAG,IAAMO,EAAK,GAC5C,EAEM,YAAU,IAAM,CAClBL,EAAW,QAAUL,CACzB,EAAG,CAACA,CAAO,CAAC,EAEN,YAAU,IAAM,CAClB,GAAI,CAACI,EACD,OAGJ,IAAMY,EAAiCd,GAAA,KAAAA,EAAW,OAAO,UAAa,YAAc,SAAW,KAE/F,GAAI,CAACc,EACD,OAGJ,IAAMC,GAAY,MAAM,QAAQlB,CAAI,EAAIA,EAAO,CAACA,CAAI,GAAG,IAAIU,CAAY,EAEjES,EAA2Bf,GAAU,CA7GnD,IAAAgB,EA8GY,IAAMC,EAAgBjB,EAElBc,EAAS,KAAMP,GAASK,EAAQL,EAAMU,CAAa,CAAC,KACpDD,EAAAd,EAAW,UAAX,MAAAc,EAAA,KAAAd,EAAqBe,GAE7B,EAEA,OAAAJ,EAAc,iBAAiBb,EAAOe,CAAQ,EAEvC,IAAM,CACTF,EAAc,oBAAoBb,EAAOe,CAAQ,CACrD,CACJ,EAAG,CAACf,EAAOJ,EAAMG,EAAQE,CAAI,CAAC,CAClC","names":["React","useHotKey","keys","handler","options","target","event","when","handlerRef","normalizeKey","key","lower","parseKeySpec","spec","parts","p","required","part","matches","targetElement","keySpecs","listener","_a","keyboardEvent"]}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Detects whether the viewport matches a mobile breakpoint.
3
+ *
4
+ * @param breakpoint - Max-width in pixels to consider as mobile. Defaults to 768.
5
+ * @returns A boolean indicating whether the viewport is at or below the breakpoint.
6
+ *
7
+ * @example
8
+ * ```tsx
9
+ * const Component = () => {
10
+ * const isMobile = useIsMobile();
11
+ * return <div>{isMobile ? 'Mobile' : 'Desktop'}</div>;
12
+ * };
13
+ *
14
+ * // Custom breakpoint
15
+ * const isTablet = useIsMobile(1024);
16
+ * ```
17
+ */
18
+ export declare function useIsMobile(breakpoint?: number): boolean;
@@ -0,0 +1,2 @@
1
+ import*as t from"react";function o(a,r=!0){let[u,c]=t.useState(!1),n=t.useRef(null),s=e=>c(e.matches),i=()=>{var e;return(e=n.current)==null?void 0:e.addEventListener("change",s)},d=()=>{var e;return((e=n.current)==null?void 0:e.removeEventListener("change",s))&&(n.current=null)};return t.useEffect(()=>(r&&(n.current=window.matchMedia(a),c(n.current.matches),i()),()=>{d()}),[a,r]),u}var h=768;function M(a=h){return o(`(max-width: ${a-1}px)`)}export{M as useIsMobile};
2
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/use-match-media/index.ts","../../src/use-is-mobile/index.ts"],"sourcesContent":["import * as React from 'react';\n\n/**\n * Listens for the specified media query.\n *\n * @param query - The media query to match.\n * @param when - A boolean indicating whether the media query should be active.\n * @returns A boolean indicating whether the media query matches.\n *\n * @example\n * ```tsx\n * const Component = () => {\n * const isMobile = useMatchMedia('(max-width: 768px)');\n *\n * return <div>{isMobile ? 'Mobile' : 'Desktop'}</div>;\n * };\n */\nexport function useMatchMedia(query: string, when: boolean = true): boolean {\n const [matches, setMatches] = React.useState(false);\n const matchMedia = React.useRef<MediaQueryList | null>(null);\n\n const handleChange = (event: MediaQueryListEvent) => setMatches(event.matches);\n const bind = () => matchMedia.current?.addEventListener('change', handleChange);\n const unbind = () => matchMedia.current?.removeEventListener('change', handleChange) && (matchMedia.current = null);\n\n React.useEffect(() => {\n if (when) {\n matchMedia.current = window.matchMedia(query);\n setMatches(matchMedia.current.matches);\n\n bind();\n }\n\n return () => {\n unbind();\n };\n }, [query, when]);\n\n return matches;\n}\n","import { useMatchMedia } from '../use-match-media';\n\nconst MOBILE_BREAKPOINT = 768;\n\n/**\n * Detects whether the viewport matches a mobile breakpoint.\n *\n * @param breakpoint - Max-width in pixels to consider as mobile. Defaults to 768.\n * @returns A boolean indicating whether the viewport is at or below the breakpoint.\n *\n * @example\n * ```tsx\n * const Component = () => {\n * const isMobile = useIsMobile();\n * return <div>{isMobile ? 'Mobile' : 'Desktop'}</div>;\n * };\n *\n * // Custom breakpoint\n * const isTablet = useIsMobile(1024);\n * ```\n */\nexport function useIsMobile(breakpoint: number = MOBILE_BREAKPOINT): boolean {\n return useMatchMedia(`(max-width: ${breakpoint - 1}px)`);\n}\n"],"mappings":"AAAA,UAAYA,MAAW,QAiBhB,SAASC,EAAcC,EAAeC,EAAgB,GAAe,CACxE,GAAM,CAACC,EAASC,CAAU,EAAU,WAAS,EAAK,EAC5CC,EAAmB,SAA8B,IAAI,EAErDC,EAAgBC,GAA+BH,EAAWG,EAAM,OAAO,EACvEC,EAAO,IAAG,CAtBpB,IAAAC,EAsBuB,OAAAA,EAAAJ,EAAW,UAAX,YAAAI,EAAoB,iBAAiB,SAAUH,IAC5DI,EAAS,IAAG,CAvBtB,IAAAD,EAuByB,QAAAA,EAAAJ,EAAW,UAAX,YAAAI,EAAoB,oBAAoB,SAAUH,MAAkBD,EAAW,QAAU,OAE9G,OAAM,YAAU,KACRH,IACAG,EAAW,QAAU,OAAO,WAAWJ,CAAK,EAC5CG,EAAWC,EAAW,QAAQ,OAAO,EAErCG,EAAK,GAGF,IAAM,CACTE,EAAO,CACX,GACD,CAACT,EAAOC,CAAI,CAAC,EAETC,CACX,CCrCA,IAAMQ,EAAoB,IAmBnB,SAASC,EAAYC,EAAqBF,EAA4B,CACzE,OAAOG,EAAc,eAAeD,EAAa,CAAC,KAAK,CAC3D","names":["React","useMatchMedia","query","when","matches","setMatches","matchMedia","handleChange","event","bind","_a","unbind","MOBILE_BREAKPOINT","useIsMobile","breakpoint","useMatchMedia"]}
@@ -0,0 +1,56 @@
1
+ import * as React from 'react';
2
+ /**
3
+ * The options for the `useLocalStorage` hook.
4
+ */
5
+ export interface UseLocalStorageOptions<T = unknown> {
6
+ /**
7
+ * The key to use in localStorage.
8
+ */
9
+ key: string;
10
+ /**
11
+ * The initial value to use when no value is found in localStorage.
12
+ */
13
+ initialValue: T;
14
+ /**
15
+ * Custom serializer function. Defaults to `JSON.stringify`.
16
+ */
17
+ serializer?: (value: T) => string;
18
+ /**
19
+ * Custom deserializer function. Defaults to `JSON.parse`.
20
+ */
21
+ deserializer?: (value: string) => T;
22
+ }
23
+ /**
24
+ * The return type of the `useLocalStorage` hook.
25
+ * A tuple containing:
26
+ * 1. The current stored value.
27
+ * 2. A setter function to update the value.
28
+ * 3. A function to remove the value from localStorage.
29
+ */
30
+ export type UseLocalStorageReturnType<T = unknown> = [T, React.Dispatch<React.SetStateAction<T>>, () => void];
31
+ /**
32
+ * A custom hook that syncs state with localStorage.
33
+ * Uses initialValue for SSR and first client render to avoid hydration mismatch,
34
+ * then reads the stored value in useLayoutEffect (before paint) so no flash occurs.
35
+ *
36
+ * @param {UseLocalStorageOptions} options - The options for the local storage hook.
37
+ * @returns A tuple containing the current value, a setter function, and a remove function.
38
+ *
39
+ * @example
40
+ * ```tsx
41
+ * const MyComponent = () => {
42
+ * const [sizes, setSizes, removeSizes] = useLocalStorage({
43
+ * key: 'splitter-sizes',
44
+ * initialValue: [50, 50]
45
+ * });
46
+ *
47
+ * return (
48
+ * <Splitter.Root sizes={sizes} onResizeEnd={(e) => setSizes(e.sizes)}>
49
+ * <Splitter.Panel />
50
+ * <Splitter.Panel />
51
+ * </Splitter.Root>
52
+ * );
53
+ * };
54
+ * ```
55
+ */
56
+ export declare function useLocalStorage<T>({ key, initialValue, serializer, deserializer }: UseLocalStorageOptions<T>): UseLocalStorageReturnType<T>;
@@ -0,0 +1,2 @@
1
+ import*as t from"react";function i({key:e,initialValue:o,serializer:n=JSON.stringify,deserializer:s=JSON.parse}){let[r,c]=t.useState(o),u=t.useRef(!1);t.useLayoutEffect(()=>{try{let a=window.localStorage.getItem(e);a!==null&&c(s(a))}catch(a){}u.current=!0},[e,s]),t.useEffect(()=>{if(u.current)try{window.localStorage.setItem(e,n(r))}catch(a){}},[e,r,n]);let l=t.useCallback(()=>{try{window.localStorage.removeItem(e)}catch(a){}c(o)},[e,o]);return[r,c,l]}export{i as useLocalStorage};
2
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/use-local-storage/index.ts"],"sourcesContent":["import * as React from 'react';\n\n/**\n * The options for the `useLocalStorage` hook.\n */\nexport interface UseLocalStorageOptions<T = unknown> {\n /**\n * The key to use in localStorage.\n */\n key: string;\n /**\n * The initial value to use when no value is found in localStorage.\n */\n initialValue: T;\n /**\n * Custom serializer function. Defaults to `JSON.stringify`.\n */\n serializer?: (value: T) => string;\n /**\n * Custom deserializer function. Defaults to `JSON.parse`.\n */\n deserializer?: (value: string) => T;\n}\n\n/**\n * The return type of the `useLocalStorage` hook.\n * A tuple containing:\n * 1. The current stored value.\n * 2. A setter function to update the value.\n * 3. A function to remove the value from localStorage.\n */\nexport type UseLocalStorageReturnType<T = unknown> = [T, React.Dispatch<React.SetStateAction<T>>, () => void];\n\n/**\n * A custom hook that syncs state with localStorage.\n * Uses initialValue for SSR and first client render to avoid hydration mismatch,\n * then reads the stored value in useLayoutEffect (before paint) so no flash occurs.\n *\n * @param {UseLocalStorageOptions} options - The options for the local storage hook.\n * @returns A tuple containing the current value, a setter function, and a remove function.\n *\n * @example\n * ```tsx\n * const MyComponent = () => {\n * const [sizes, setSizes, removeSizes] = useLocalStorage({\n * key: 'splitter-sizes',\n * initialValue: [50, 50]\n * });\n *\n * return (\n * <Splitter.Root sizes={sizes} onResizeEnd={(e) => setSizes(e.sizes)}>\n * <Splitter.Panel />\n * <Splitter.Panel />\n * </Splitter.Root>\n * );\n * };\n * ```\n */\nexport function useLocalStorage<T>({ key, initialValue, serializer = JSON.stringify, deserializer = JSON.parse }: UseLocalStorageOptions<T>): UseLocalStorageReturnType<T> {\n const [storedValue, setStoredValue] = React.useState<T>(initialValue);\n const hydrated = React.useRef(false);\n\n // Read from localStorage before paint (after hydration).\n // Triggers a synchronous re-render so the user never sees the initialValue flash.\n React.useLayoutEffect(() => {\n try {\n const item = window.localStorage.getItem(key);\n\n if (item !== null) {\n setStoredValue(deserializer(item));\n }\n } catch {\n // Storage unavailable\n }\n\n hydrated.current = true;\n }, [key, deserializer]);\n\n // Write to localStorage on changes (skip until hydration is complete)\n React.useEffect(() => {\n if (!hydrated.current) return;\n\n try {\n window.localStorage.setItem(key, serializer(storedValue));\n } catch {\n // Storage full or unavailable\n }\n }, [key, storedValue, serializer]);\n\n const remove = React.useCallback(() => {\n try {\n window.localStorage.removeItem(key);\n } catch {\n // Storage unavailable\n }\n\n setStoredValue(initialValue);\n }, [key, initialValue]);\n\n return [storedValue, setStoredValue, remove];\n}\n"],"mappings":"AAAA,UAAYA,MAAW,QA0DhB,SAASC,EAAmB,CAAE,IAAAC,EAAK,aAAAC,EAAc,WAAAC,EAAa,KAAK,UAAW,aAAAC,EAAe,KAAK,KAAM,EAA4D,CACvK,GAAM,CAACC,EAAaC,CAAc,EAAU,WAAYJ,CAAY,EAC9DK,EAAiB,SAAO,EAAK,EAI7B,kBAAgB,IAAM,CACxB,GAAI,CACA,IAAMC,EAAO,OAAO,aAAa,QAAQP,CAAG,EAExCO,IAAS,MACTF,EAAeF,EAAaI,CAAI,CAAC,CAEzC,OAAQC,EAAA,CAER,CAEAF,EAAS,QAAU,EACvB,EAAG,CAACN,EAAKG,CAAY,CAAC,EAGhB,YAAU,IAAM,CAClB,GAAKG,EAAS,QAEd,GAAI,CACA,OAAO,aAAa,QAAQN,EAAKE,EAAWE,CAAW,CAAC,CAC5D,OAAQI,EAAA,CAER,CACJ,EAAG,CAACR,EAAKI,EAAaF,CAAU,CAAC,EAEjC,IAAMO,EAAe,cAAY,IAAM,CACnC,GAAI,CACA,OAAO,aAAa,WAAWT,CAAG,CACtC,OAAQQ,EAAA,CAER,CAEAH,EAAeJ,CAAY,CAC/B,EAAG,CAACD,EAAKC,CAAY,CAAC,EAEtB,MAAO,CAACG,EAAaC,EAAgBI,CAAM,CAC/C","names":["React","useLocalStorage","key","initialValue","serializer","deserializer","storedValue","setStoredValue","hydrated","item","e","remove"]}