@primereact/hooks 11.0.0-alpha.1 → 11.0.0-alpha.10

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 (44) hide show
  1. package/index.d.ts +12 -0
  2. package/index.mjs +1 -1
  3. package/index.mjs.map +1 -1
  4. package/package.json +3 -3
  5. package/use-controlled-state/index.mjs +1 -1
  6. package/use-controlled-state/index.mjs.map +1 -1
  7. package/use-hot-key/index.d.ts +25 -0
  8. package/use-hot-key/index.mjs +2 -0
  9. package/use-hot-key/index.mjs.map +1 -0
  10. package/use-intersection-observer/index.d.ts +58 -0
  11. package/use-intersection-observer/index.mjs +2 -0
  12. package/use-intersection-observer/index.mjs.map +1 -0
  13. package/use-intersection-observer/index.test.d.ts +0 -0
  14. package/use-key-filter/index.d.ts +42 -0
  15. package/use-key-filter/index.mjs +2 -0
  16. package/use-key-filter/index.mjs.map +1 -0
  17. package/use-key-filter/index.test.d.ts +0 -0
  18. package/use-mask/index.d.ts +109 -0
  19. package/use-mask/index.mjs +2 -0
  20. package/use-mask/index.mjs.map +1 -0
  21. package/use-mask/index.test.d.ts +0 -0
  22. package/use-number-formatter/index.d.ts +194 -0
  23. package/use-number-formatter/index.mjs +2 -0
  24. package/use-number-formatter/index.mjs.map +1 -0
  25. package/use-number-formatter/index.test.d.ts +0 -0
  26. package/use-presence/index.d.ts +21 -0
  27. package/use-presence/index.mjs +2 -0
  28. package/use-presence/index.mjs.map +1 -0
  29. package/use-presence/index.test.d.ts +0 -0
  30. package/use-props/index.d.ts +11 -11
  31. package/use-props/index.mjs +1 -1
  32. package/use-props/index.mjs.map +1 -1
  33. package/use-queue-task/index.d.ts +1 -0
  34. package/use-queue-task/index.mjs +2 -0
  35. package/use-queue-task/index.mjs.map +1 -0
  36. package/use-queue-task/index.test.d.ts +0 -0
  37. package/use-scrolltop/index.d.ts +59 -0
  38. package/use-scrolltop/index.mjs +2 -0
  39. package/use-scrolltop/index.mjs.map +1 -0
  40. package/use-scrolltop/index.test.d.ts +0 -0
  41. package/use-visibility-change/index.d.ts +14 -0
  42. package/use-visibility-change/index.mjs +2 -0
  43. package/use-visibility-change/index.mjs.map +1 -0
  44. package/use-visibility-change/index.test.d.ts +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/use-key-filter/index.ts"],"sourcesContent":["import { isAndroid } from '@primeuix/utils';\n\n/**\n * The options for the `useKeyFilter` hook.\n */\nexport interface UseKeyFilterOptions {\n /**\n * Sets the pattern for key filtering.\n * @default /./\n */\n pattern?: 'pint' | 'int' | 'pnum' | 'money' | 'num' | 'hex' | 'email' | 'alpha' | 'alphanum' | RegExp;\n /**\n * When enabled, instead of blocking keys, input is validated internally to test against the regular expression.\n * @default false\n */\n validateOnly?: boolean;\n}\n\nexport interface UseKeyFilterExposes {\n /**\n * Handles input events for key filter.\n * Processes character input and composition events while applying the filter pattern.\n * @param event - The form or composition event from the input element\n */\n onBeforeInput: (event: React.CompositionEvent<HTMLInputElement>) => void;\n /**\n * Handles keypress events for character input validation.\n * Validates and places characters according to the filter pattern.\n * @param event - The keyboard event from the input element\n */\n onKeyPress: (event: React.KeyboardEvent<HTMLInputElement>) => void;\n /**\n * Handles paste events for clipboard content insertion.\n * Processes pasted content according to the mask pattern.\n * @param event - The clipboard event from the input element\n */\n onPaste: (event: React.ClipboardEvent<HTMLInputElement>) => void;\n /**\n * Validates the current input value against the filter pattern.\n * @param event - The form event from the input element\n * @returns true if the value matches the pattern, false otherwise\n */\n validate: (event: React.FormEvent<HTMLInputElement>) => boolean;\n}\n\nexport function useKeyFilter(options: UseKeyFilterOptions): UseKeyFilterExposes {\n const { pattern = /./, validateOnly = false } = options;\n\n const DEFAULT_MASKS = {\n pint: /[\\d]/,\n int: /[\\d-]/,\n pnum: /[\\d.]/,\n money: /[\\d.\\s,]/,\n num: /[\\d-.]/,\n hex: /[0-9a-f]/i,\n email: /[a-z0-9_.-@]/i,\n alpha: /[a-z_]/i,\n alphanum: /[a-z0-9_]/\n };\n\n const getRegex = (): RegExp => {\n return typeof pattern === 'string' ? DEFAULT_MASKS[pattern] : pattern;\n };\n\n const onBeforeInput = (event: React.CompositionEvent<HTMLInputElement>) => {\n // android devices must use beforeinput https://stackoverflow.com/questions/36753548/keycode-on-android-is-always-229\n if (validateOnly || !isAndroid()) {\n return;\n }\n\n validateKey(event, event.data);\n };\n\n const onKeyPress = (event: React.KeyboardEvent<HTMLInputElement>) => {\n // non android devices use keydown\n if (validateOnly || isAndroid()) {\n return;\n }\n\n if (event.ctrlKey || event.altKey || event.metaKey) {\n return;\n }\n\n validateKey(event, event.key);\n };\n\n const onPaste = (event: React.ClipboardEvent<HTMLInputElement>) => {\n if (validateOnly) {\n return;\n }\n\n const regex = getRegex();\n const clipboard = event.clipboardData.getData('text');\n\n // loop over each letter pasted and if any fail prevent the paste\n [...clipboard].forEach((c) => {\n if (!regex.test(c)) {\n event.preventDefault();\n\n return false;\n }\n });\n };\n\n const validateKey = (event: React.CompositionEvent<HTMLInputElement> | React.KeyboardEvent<HTMLInputElement>, key: string) => {\n if (key === null || key === undefined) {\n return;\n }\n\n // some AZERTY keys come in with 2 chars like ´ç if Dead key is pressed first\n const isPrintableKey = key.length <= 2;\n\n if (!isPrintableKey) {\n return;\n }\n\n const regex = getRegex();\n\n if (!regex.test(key)) {\n event.preventDefault();\n }\n };\n\n const validate = (event: React.FormEvent<HTMLInputElement>) => {\n const value = (event.target as HTMLInputElement).value;\n let validatePattern = true;\n\n const regex = getRegex();\n\n if (value && !regex.test(value)) {\n validatePattern = false;\n }\n\n return validatePattern;\n };\n\n return {\n onBeforeInput,\n onKeyPress,\n onPaste,\n validate\n };\n}\n"],"mappings":"AAAA,OAAS,aAAAA,MAAiB,kBA6CnB,SAASC,EAAaC,EAAmD,CAC5E,GAAM,CAAE,QAAAC,EAAU,IAAK,aAAAC,EAAe,EAAM,EAAIF,EAE1CG,EAAgB,CAClB,KAAM,OACN,IAAK,QACL,KAAM,QACN,MAAO,WACP,IAAK,SACL,IAAK,YACL,MAAO,gBACP,MAAO,UACP,SAAU,WACd,EAEMC,EAAW,IACN,OAAOH,GAAY,SAAWE,EAAcF,CAAO,EAAIA,EAG5DI,EAAiBC,GAAoD,CAEnEJ,GAAgB,CAACJ,EAAU,GAI/BS,EAAYD,EAAOA,EAAM,IAAI,CACjC,EAEME,EAAcF,GAAiD,CAE7DJ,GAAgBJ,EAAU,GAI1BQ,EAAM,SAAWA,EAAM,QAAUA,EAAM,SAI3CC,EAAYD,EAAOA,EAAM,GAAG,CAChC,EAEMG,EAAWH,GAAkD,CAC/D,GAAIJ,EACA,OAGJ,IAAMQ,EAAQN,EAAS,EAIvB,CAAC,GAHiBE,EAAM,cAAc,QAAQ,MAAM,CAGvC,EAAE,QAASK,GAAM,CAC1B,GAAI,CAACD,EAAM,KAAKC,CAAC,EACb,OAAAL,EAAM,eAAe,EAEd,EAEf,CAAC,CACL,EAEMC,EAAc,CAACD,EAAyFM,IAAgB,CAQ1H,GAPIA,GAAQ,MAOR,EAFmBA,EAAI,QAAU,GAGjC,OAGUR,EAAS,EAEZ,KAAKQ,CAAG,GACfN,EAAM,eAAe,CAE7B,EAeA,MAAO,CACH,cAAAD,EACA,WAAAG,EACA,QAAAC,EACA,SAjBcH,GAA6C,CAC3D,IAAMO,EAASP,EAAM,OAA4B,MAC7CQ,EAAkB,GAEhBJ,EAAQN,EAAS,EAEvB,OAAIS,GAAS,CAACH,EAAM,KAAKG,CAAK,IAC1BC,EAAkB,IAGfA,CACX,CAOA,CACJ","names":["isAndroid","useKeyFilter","options","pattern","validateOnly","DEFAULT_MASKS","getRegex","onBeforeInput","event","validateKey","onKeyPress","onPaste","regex","c","key","value","validatePattern"]}
File without changes
@@ -0,0 +1,109 @@
1
+ import * as React from 'react';
2
+ /**
3
+ * Event fired when the component's state changes.
4
+ */
5
+ export interface UseMaskChangeEvent {
6
+ /**
7
+ * The value of the component.
8
+ */
9
+ value: string | undefined;
10
+ }
11
+ /**
12
+ * The options for the `useMask` hook.
13
+ */
14
+ export interface UseMaskOptions {
15
+ /**
16
+ * Mask pattern.
17
+ */
18
+ mask: string;
19
+ /**
20
+ * Defines if model sets the raw unmasked value to bound value or the formatted mask value.
21
+ * @default false
22
+ */
23
+ unmask?: string;
24
+ /**
25
+ * Placeholder character in mask, default is underscore.
26
+ * @default _
27
+ */
28
+ slotChar?: string;
29
+ /**
30
+ * Clears the incomplete value on blur.
31
+ * @default true
32
+ */
33
+ autoClear?: boolean;
34
+ /**
35
+ * Whether the components are clickable or not.
36
+ * @default false
37
+ */
38
+ readOnly?: boolean;
39
+ /**
40
+ * Callback function that is called when the value is changed.
41
+ * @param event The event that triggered the change.
42
+ * @param event.value The value of the component.
43
+ * @returns void
44
+ */
45
+ onMaskChange?: (event: UseMaskChangeEvent) => void;
46
+ /**
47
+ * Reference to the mask element.
48
+ */
49
+ target: HTMLInputElement;
50
+ }
51
+ export interface UseMaskExposes {
52
+ /**
53
+ * Handles input events for the masked input field.
54
+ * Processes character input and composition events while applying the mask pattern.
55
+ * @param event - The form or composition event from the input element
56
+ */
57
+ onMaskInput: (event: React.FormEvent<HTMLInputElement> | React.CompositionEvent<HTMLInputElement>) => void;
58
+ /**
59
+ * Handles keydown events for special key operations.
60
+ * Manages backspace, delete, escape, and enter key behaviors.
61
+ * @param event - The keyboard event from the input element
62
+ */
63
+ onMaskKeyDown: (event: React.KeyboardEvent<HTMLInputElement>) => void;
64
+ /**
65
+ * Handles keypress events for character input validation.
66
+ * Validates and places characters according to the mask pattern.
67
+ * @param event - The keyboard event from the input element
68
+ */
69
+ onMaskKeyPress: (event: React.KeyboardEvent<HTMLInputElement>) => void;
70
+ /**
71
+ * Handles focus events when the input gains focus.
72
+ * Initializes the mask display and sets the cursor position.
73
+ * @param event - The focus event from the input element
74
+ */
75
+ onMaskFocus: (event: React.FocusEvent<HTMLInputElement>) => void;
76
+ /**
77
+ * Handles blur events when the input loses focus.
78
+ * Validates the final value and triggers change events if needed.
79
+ * @param event - The focus event from the input element
80
+ */
81
+ onMaskBlur: (event: React.FocusEvent<HTMLInputElement>) => void;
82
+ /**
83
+ * Handles paste events for clipboard content insertion.
84
+ * Processes pasted content according to the mask pattern.
85
+ * @param event - The clipboard event from the input element
86
+ */
87
+ onMaskPaste: (event: React.ClipboardEvent<HTMLInputElement>) => void;
88
+ }
89
+ /**
90
+ * useMask hook is used to enter input in a certain format such as numeric, date, currency, email and phone.
91
+ *
92
+ * @param {UseMaskOptions} options - The options for the mask.
93
+ * @returns {UseMaskExposes} - The exposed methods for the mask.
94
+ *
95
+ * @example
96
+ * ```tsx
97
+ * const { onMaskInput, onMaskKeyDown, onMaskKeyPress, onMaskFocus, onMaskBlur, onMaskPaste } = useMask({
98
+ * mask: '99/99/9999',
99
+ * onMaskChange: (event: UseMaskChangeEvent) => setValue(event.value ?? ''),
100
+ * target: ref
101
+ * });
102
+ *
103
+ * return (
104
+ * <div className="card flex justify-center">
105
+ * <InputText ref={ref} value={value} placeholder="99/99/9999" onInput={onMaskInput} onKeyDown={onMaskKeyDown} onKeyPress={onMaskKeyPress} onFocus={onMaskFocus} onBlur={onMaskBlur} onPaste={onMaskPaste} />
106
+ * </div>
107
+ * );
108
+ */
109
+ export declare function useMask(options: UseMaskOptions): UseMaskExposes;
@@ -0,0 +1,2 @@
1
+ import{useMountEffect as te}from"@primereact/hooks";import{getUserAgent as x}from"@primeuix/utils";import*as i from"react";function ue(j){let{mask:m,unmask:N,slotChar:L="_",autoClear:O=!0,readOnly:v=!1,onMaskChange:K,target:s}=j,o=i.useRef(0),a=i.useRef([]),l=i.useRef([]),k=i.useRef(null),h=i.useRef(0),w=i.useRef(!1),P=i.useRef(!1),T=i.useRef(null),M=i.useRef(null),S=i.useRef(0),H=i.useRef(null),I=i.useRef(null),A=i.useRef(null),q=e=>{"isComposing"in e&&e.isComposing||(w.current?X():D(e))},z=e=>{var b;if(v)return;let t=e.code,r,n,u,c=/iphone/i.test(x());if(I.current=s==null?void 0:s.value,t==="Backspace"||t==="Delete"||c&&t==="Escape"){if(r=f(),!r)return;n=r.begin,u=r.end,u-n===0&&(n=t!=="Delete"?Q(n):u=d(n-1),u=t==="Delete"?d(u):u),y(n,u),F(n,u-1),g(e.target.value),e.preventDefault()}else t==="Enter"?(s.blur(),g(e.target.value)):t==="Escape"&&(s&&(s.value=(b=T.current)!=null?b:""),f(0,p()),g(e.target.value),e.preventDefault())},J=e=>{var b;if(v)return;let t=e.code,r=f(),n,u,c;r&&(e.ctrlKey||e.altKey||e.metaKey||e.shiftKey||e.key==="CapsLock"||e.key==="Escape"||e.key==="Tab"||(t&&t!=="Enter"&&(r.end-r.begin!==0&&(y(r.begin,r.end),F(r.begin,r.end-1)),n=d(r.begin-1),n<o.current&&(u=e.key,(b=a.current[n])!=null&&b.test(u)&&(W(n),l.current[n]=u,E(),c=d(n),/android/i.test(x())?setTimeout(()=>{f(c)},0):f(c))),e.preventDefault()),g(e.target.value)))},Z=()=>{if(!v)if(H.current&&clearTimeout(H.current),P.current=!0,T.current=s.value,!s.value||s.value===k.current)requestAnimationFrame(()=>{s===document.activeElement&&f(0,0)});else{let e=p();H.current=setTimeout(()=>{s===document.activeElement&&(E(),e===(m==null?void 0:m.replace("?","").length)?f(0,e):f(e))},10)}},_=e=>{if(P.current=!1,p(),g(e.target.value),s.value!==T.current){let t=new Event("change",{bubbles:!0,cancelable:!1});s.dispatchEvent(t)}},G=e=>{D(e)},f=(e,t)=>{var u,c;let r=0,n=0;return typeof e=="number"?(r=e,n=typeof t=="number"?t:r,s.setSelectionRange(r,n)):s&&(r=(u=s.selectionStart)!=null?u:0,n=(c=s.selectionEnd)!=null?c:0),{begin:r,end:n}},R=e=>e<L.length?L.charAt(e):L.charAt(0),d=e=>{for(;++e<o.current&&!a.current[e];);return e},Q=e=>{for(;--e>=0&&!a.current[e];);return e},F=(e,t)=>{var u,c;let r,n;if(!(e<0)){for(r=e,n=d(t);r<o.current;r++)if(a.current[r]){if(n<o.current&&((u=a.current[r])!=null&&u.test(l.current[n])))l.current[r]=l.current[n],l.current[n]=R(n);else break;n=d(n)}E(),f(Math.max((c=M.current)!=null?c:0,e))}},W=e=>{var c;let t,r,n,u;for(t=e,r=R(e);t<o.current;t++)if(a.current[t])if(n=d(t),u=l.current[t],l.current[t]=r,n<o.current&&((c=a.current[n])!=null&&c.test(u)))r=u;else break},X=()=>{var r;let e=s.value,t=f();if(t)if(I.current&&I.current.length&&I.current.length>e.length){for(p(!0);t.begin>0&&!a.current[t.begin-1];)t.begin--;if(t.begin===0)for(;t.begin<((r=M.current)!=null?r:0)&&!a.current[t.begin];)t.begin++;f(t.begin,t.begin)}else{for(p(!0);t.begin<o.current&&!a.current[t.begin];)t.begin++;f(t.begin,t.begin)}},y=(e,t)=>{let r;for(r=e;r<t&&r<o.current;r++)a.current[r]&&(l.current[r]=R(r))},E=()=>{s&&(s.value=l.current.join(""))},p=(e=!1)=>{var b,C,V,B;let t=s.value,r=-1,n,u,c;for(n=0,c=0;n<o.current;n++){let U=a.current[n];if(U!==null){for(l.current[n]=R(n);c++<((b=t==null?void 0:t.length)!=null?b:0);)if(u=(C=t==null?void 0:t.charAt(c-1))!=null?C:"",U.test(u)){l.current[n]=u,r=n;break}if(c>((V=t==null?void 0:t.length)!=null?V:0)){y(n+1,o.current);break}}else l.current[n]===(t==null?void 0:t.charAt(c))&&c++,n<h.current&&(r=n)}return e?E():r+1<h.current?O||l.current.join("")===k.current?(s.value&&(s.value=""),y(0,o.current)):E():(E(),s&&(s.value=s.value.substring(0,r+1))),h.current?n:(B=M.current)!=null?B:0},D=e=>{let t=e.type==="paste";if(v||t)return;let r=p(!0);f(r),g(e.target.value)},Y=e=>{let t=[],r=e.split("");for(let n=0;n<r.length;n++){let u=r[n];a.current[n]&&u!==R(n)&&t.push(u)}return t.join("")},g=e=>{if(A.current===e)return;let t=N?Y(e):e,r=k.current!==t?t:"";A.current=e,s&&(s.value=r),K&&K({value:r})},$=(e=!0)=>{s&&(s.value==null?(s.value="",e&&g("")):(p(),setTimeout(()=>{s&&(E(),p(),e&&g(s.value))},10)),T.current=s.value)},ee=()=>{a.current=[],h.current=m?m.length:0,o.current=m?m.length:0,M.current=null;let e={9:"[0-9]",a:"[A-Za-z]","*":"[A-Za-z0-9]"},t=x();w.current=/chrome/i.test(t)&&/android/i.test(t);let r=m?m.split(""):"";for(let n=0;n<r.length;n++){let u=r[n];u==="?"?(o.current--,h.current=n):e[u]?(a.current.push(new RegExp(e[u])),M.current===null&&(M.current=a.current.length-1),n<h.current&&(S.current=a.current.length-1)):a.current.push(null)}l.current=[];for(let n=0;n<r.length;n++){let u=r[n];u!=="?"&&(e[u]?l.current.push(R(n)):l.current.push(u))}k.current=l.current.join(""),$(!1)};return te(()=>{ee()}),{onMaskInput:q,onMaskKeyDown:z,onMaskKeyPress:J,onMaskFocus:Z,onMaskBlur:_,onMaskPaste:G}}export{ue as useMask};
2
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/use-mask/index.ts"],"sourcesContent":["import { useMountEffect } from '@primereact/hooks';\nimport { getUserAgent } from '@primeuix/utils';\nimport * as React from 'react';\n\n/**\n * Event fired when the component's state changes.\n */\nexport interface UseMaskChangeEvent {\n /**\n * The value of the component.\n */\n value: string | undefined;\n}\n\n/**\n * The options for the `useMask` hook.\n */\nexport interface UseMaskOptions {\n /**\n * Mask pattern.\n */\n mask: string;\n /**\n * Defines if model sets the raw unmasked value to bound value or the formatted mask value.\n * @default false\n */\n unmask?: string;\n /**\n * Placeholder character in mask, default is underscore.\n * @default _\n */\n slotChar?: string;\n /**\n * Clears the incomplete value on blur.\n * @default true\n */\n autoClear?: boolean;\n /**\n * Whether the components are clickable or not.\n * @default false\n */\n readOnly?: boolean;\n /**\n * Callback function that is called when the value is changed.\n * @param event The event that triggered the change.\n * @param event.value The value of the component.\n * @returns void\n */\n onMaskChange?: (event: UseMaskChangeEvent) => void;\n /**\n * Reference to the mask element.\n */\n target: HTMLInputElement;\n}\n\nexport interface UseMaskExposes {\n /**\n * Handles input events for the masked input field.\n * Processes character input and composition events while applying the mask pattern.\n * @param event - The form or composition event from the input element\n */\n onMaskInput: (event: React.FormEvent<HTMLInputElement> | React.CompositionEvent<HTMLInputElement>) => void;\n /**\n * Handles keydown events for special key operations.\n * Manages backspace, delete, escape, and enter key behaviors.\n * @param event - The keyboard event from the input element\n */\n onMaskKeyDown: (event: React.KeyboardEvent<HTMLInputElement>) => void;\n /**\n * Handles keypress events for character input validation.\n * Validates and places characters according to the mask pattern.\n * @param event - The keyboard event from the input element\n */\n onMaskKeyPress: (event: React.KeyboardEvent<HTMLInputElement>) => void;\n /**\n * Handles focus events when the input gains focus.\n * Initializes the mask display and sets the cursor position.\n * @param event - The focus event from the input element\n */\n onMaskFocus: (event: React.FocusEvent<HTMLInputElement>) => void;\n /**\n * Handles blur events when the input loses focus.\n * Validates the final value and triggers change events if needed.\n * @param event - The focus event from the input element\n */\n onMaskBlur: (event: React.FocusEvent<HTMLInputElement>) => void;\n /**\n * Handles paste events for clipboard content insertion.\n * Processes pasted content according to the mask pattern.\n * @param event - The clipboard event from the input element\n */\n onMaskPaste: (event: React.ClipboardEvent<HTMLInputElement>) => void;\n}\n\n/**\n * useMask hook is used to enter input in a certain format such as numeric, date, currency, email and phone.\n *\n * @param {UseMaskOptions} options - The options for the mask.\n * @returns {UseMaskExposes} - The exposed methods for the mask.\n *\n * @example\n * ```tsx\n * const { onMaskInput, onMaskKeyDown, onMaskKeyPress, onMaskFocus, onMaskBlur, onMaskPaste } = useMask({\n * mask: '99/99/9999',\n * onMaskChange: (event: UseMaskChangeEvent) => setValue(event.value ?? ''),\n * target: ref\n * });\n *\n * return (\n * <div className=\"card flex justify-center\">\n * <InputText ref={ref} value={value} placeholder=\"99/99/9999\" onInput={onMaskInput} onKeyDown={onMaskKeyDown} onKeyPress={onMaskKeyPress} onFocus={onMaskFocus} onBlur={onMaskBlur} onPaste={onMaskPaste} />\n * </div>\n * );\n */\nexport function useMask(options: UseMaskOptions): UseMaskExposes {\n const { mask, unmask, slotChar = '_', autoClear = true, readOnly = false, onMaskChange, target } = options;\n\n const len = React.useRef(0);\n const tests = React.useRef<Array<RegExp | null>>([]);\n const buffer = React.useRef<string[]>([]);\n const defaultBuffer = React.useRef<string | null>(null);\n const partialPosition = React.useRef<number>(0);\n const androidChrome = React.useRef(false);\n const focus = React.useRef(false);\n const focusText = React.useRef<string | null>(null);\n const firstNonMaskPos = React.useRef<number | null>(null);\n const lastRequiredNonMaskPos = React.useRef<number>(0);\n const caretTimeoutId = React.useRef<NodeJS.Timeout | null>(null);\n const oldVal = React.useRef<string | null>(null);\n const currentVal = React.useRef<string | null>(null);\n\n const onMaskInput = (event: React.FormEvent<HTMLInputElement> | React.CompositionEvent<HTMLInputElement>) => {\n // Check if the event is part of a text composition process (e.g., for Asian languages).\n // If event.isComposing is true, it means the user is still composing text and the input is not finalized.\n if ('isComposing' in event && event.isComposing) {\n return;\n }\n\n if (androidChrome.current) handleAndroidInput();\n else handleInputChange(event);\n };\n\n const onMaskKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {\n if (readOnly) {\n return;\n }\n\n const k = event.code;\n let pos, begin, end;\n const iPhone = /iphone/i.test(getUserAgent());\n\n oldVal.current = target?.value as string;\n\n //backspace, delete, and escape get special treatment\n if (k === 'Backspace' || k === 'Delete' || (iPhone && k === 'Escape')) {\n pos = caret();\n\n if (!pos) {\n return;\n }\n\n begin = pos.begin;\n end = pos.end;\n\n if (end - begin === 0) {\n begin = k !== 'Delete' ? seekPrev(begin) : (end = seekNext(begin - 1));\n end = k === 'Delete' ? seekNext(end) : end;\n }\n\n clearBuffer(begin, end);\n shiftL(begin, end - 1);\n updateModelValue((event.target as HTMLInputElement).value);\n\n event.preventDefault();\n } else if (k === 'Enter') {\n // enter\n target.blur();\n updateModelValue((event.target as HTMLInputElement).value);\n } else if (k === 'Escape') {\n // escape\n if (target) {\n target.value = focusText.current ?? '';\n }\n\n caret(0, checkVal());\n updateModelValue((event.target as HTMLInputElement).value);\n event.preventDefault();\n }\n };\n\n const onMaskKeyPress = (event: React.KeyboardEvent<HTMLInputElement>) => {\n if (readOnly) {\n return;\n }\n\n const k = event.code,\n pos = caret();\n let p: number, c: string, next: number;\n\n if (!pos) {\n return;\n }\n\n if (event.ctrlKey || event.altKey || event.metaKey || event.shiftKey || event.key === 'CapsLock' || event.key === 'Escape' || event.key === 'Tab') {\n //Ignore\n return;\n } else if (k && k !== 'Enter') {\n if (pos.end - pos.begin !== 0) {\n clearBuffer(pos.begin, pos.end);\n shiftL(pos.begin, pos.end - 1);\n }\n\n p = seekNext(pos.begin - 1);\n\n if (p < len.current) {\n c = event.key;\n\n if (tests.current[p]?.test(c)) {\n shiftR(p);\n\n buffer.current[p] = c;\n writeBuffer();\n next = seekNext(p);\n\n if (/android/i.test(getUserAgent())) {\n //Path for CSP Violation on FireFox OS 1.1\n const proxy = () => {\n caret(next);\n };\n\n setTimeout(proxy, 0);\n } else {\n caret(next);\n }\n }\n }\n\n event.preventDefault();\n }\n\n updateModelValue((event.target as HTMLInputElement).value);\n };\n\n const onMaskFocus = () => {\n if (readOnly) {\n return;\n }\n\n if (caretTimeoutId.current) {\n clearTimeout(caretTimeoutId.current as NodeJS.Timeout);\n }\n\n focus.current = true;\n focusText.current = target.value as string;\n\n if (!target.value || target.value === defaultBuffer.current) {\n requestAnimationFrame(() => {\n if (target === document.activeElement) {\n caret(0, 0);\n }\n });\n } else {\n const pos = checkVal();\n\n caretTimeoutId.current = setTimeout(() => {\n if (target !== document.activeElement) {\n return;\n }\n\n writeBuffer();\n\n if (pos === mask?.replace('?', '').length) {\n caret(0, pos);\n } else {\n caret(pos);\n }\n }, 10);\n }\n };\n\n const onMaskBlur = (event: React.FocusEvent<HTMLInputElement>) => {\n focus.current = false;\n checkVal();\n updateModelValue(event.target.value);\n\n if (target.value !== focusText.current) {\n const e = new Event('change', { bubbles: true, cancelable: false });\n\n target.dispatchEvent(e);\n }\n };\n\n const onMaskPaste = (event: React.ClipboardEvent<HTMLInputElement>) => {\n handleInputChange(event);\n };\n\n const caret = (first?: number, last?: number): { begin: number; end: number } | undefined => {\n let begin = 0,\n end = 0;\n\n if (typeof first === 'number') {\n begin = first;\n end = typeof last === 'number' ? last : begin;\n\n target.setSelectionRange(begin, end);\n } else {\n if (target) {\n begin = target.selectionStart ?? 0;\n end = target.selectionEnd ?? 0;\n }\n }\n\n return { begin, end };\n };\n\n const getPlaceholder = (i: number) => {\n if (i < slotChar.length) {\n return slotChar.charAt(i);\n }\n\n return slotChar.charAt(0);\n };\n\n const seekNext = (pos: number) => {\n while (++pos < len.current && !tests.current[pos]);\n\n return pos;\n };\n\n const seekPrev = (pos: number) => {\n while (--pos >= 0 && !tests.current[pos]);\n\n return pos;\n };\n\n const shiftL = (begin: number, end: number) => {\n let i, j;\n\n if (begin < 0) {\n return;\n }\n\n for (i = begin, j = seekNext(end); i < len.current; i++) {\n if (tests.current[i]) {\n if (j < len.current && tests.current[i]?.test(buffer.current[j])) {\n buffer.current[i] = buffer.current[j];\n buffer.current[j] = getPlaceholder(j);\n } else {\n break;\n }\n\n j = seekNext(j);\n }\n }\n\n writeBuffer();\n caret(Math.max(firstNonMaskPos.current ?? 0, begin));\n };\n\n const shiftR = (pos: number) => {\n let i, c, j, t;\n\n for (i = pos, c = getPlaceholder(pos); i < len.current; i++) {\n if (tests.current[i]) {\n j = seekNext(i);\n t = buffer.current[i];\n buffer.current[i] = c;\n\n if (j < len.current && tests.current[j]?.test(t)) {\n c = t;\n } else {\n break;\n }\n }\n }\n };\n\n const handleAndroidInput = () => {\n const curVal = target.value as string;\n const pos = caret();\n\n if (!pos) {\n return;\n }\n\n if (oldVal.current && oldVal.current.length && oldVal.current.length > curVal.length) {\n // a deletion or backspace happened\n checkVal(true);\n while (pos.begin > 0 && !tests.current[pos.begin - 1]) pos.begin--;\n\n if (pos.begin === 0) {\n while (pos.begin < (firstNonMaskPos.current ?? 0) && !tests.current[pos.begin]) pos.begin++;\n }\n\n caret(pos.begin, pos.begin);\n } else {\n checkVal(true);\n while (pos.begin < len.current && !tests.current[pos.begin]) pos.begin++;\n\n caret(pos.begin, pos.begin);\n }\n };\n\n const clearBuffer = (start: number, end: number) => {\n let i;\n\n for (i = start; i < end && i < len.current; i++) {\n if (tests.current[i]) {\n buffer.current[i] = getPlaceholder(i);\n }\n }\n };\n\n const writeBuffer = () => {\n if (target) {\n target.value = buffer.current.join('');\n }\n };\n\n const checkVal = (allow = false): number => {\n //try to place characters where they belong\n const test = target.value;\n let lastMatch = -1,\n i,\n c,\n pos;\n\n for (i = 0, pos = 0; i < len.current; i++) {\n const currentTest = tests.current[i];\n\n if (currentTest !== null) {\n buffer.current[i] = getPlaceholder(i);\n\n while (pos++ < (test?.length ?? 0)) {\n c = test?.charAt(pos - 1) ?? '';\n\n if (currentTest.test(c)) {\n buffer.current[i] = c;\n lastMatch = i;\n break;\n }\n }\n\n if (pos > (test?.length ?? 0)) {\n clearBuffer(i + 1, len.current);\n break;\n }\n } else {\n if (buffer.current[i] === test?.charAt(pos)) {\n pos++;\n }\n\n if (i < partialPosition.current) {\n lastMatch = i;\n }\n }\n }\n\n if (allow) {\n writeBuffer();\n } else if (lastMatch + 1 < partialPosition.current) {\n if (autoClear || buffer.current.join('') === defaultBuffer.current) {\n // Invalid value. Remove it and replace it with the\n // mask, which is the default behavior.\n if (target.value) {\n target.value = '';\n }\n\n clearBuffer(0, len.current);\n } else {\n // Invalid value, but we opt to show the value to the\n // user and allow them to correct their mistake.\n writeBuffer();\n }\n } else {\n writeBuffer();\n\n if (target) {\n target.value = target.value.substring(0, lastMatch + 1);\n }\n }\n\n return partialPosition.current ? i : (firstNonMaskPos.current ?? 0);\n };\n\n const handleInputChange = (event: React.FormEvent<HTMLInputElement> | React.ClipboardEvent<HTMLInputElement>) => {\n const isPasteEvent = event.type === 'paste';\n\n if (readOnly || isPasteEvent) {\n return;\n }\n\n const pos = checkVal(true);\n\n caret(pos);\n updateModelValue((event.target as HTMLInputElement).value);\n };\n\n const unmaskValue = (value: string) => {\n const unmaskedBuffer = [];\n const thisbuffer = value.split('');\n\n for (let i = 0; i < thisbuffer.length; i++) {\n const c = thisbuffer[i];\n\n if (tests.current[i] && c !== getPlaceholder(i)) {\n unmaskedBuffer.push(c);\n }\n }\n\n return unmaskedBuffer.join('');\n };\n\n const updateModelValue = (value: string) => {\n if (currentVal.current === value) return;\n\n const val = unmask ? unmaskValue(value) : value;\n const finalValue = defaultBuffer.current !== val ? val : '';\n\n currentVal.current = value;\n\n if (target) {\n target.value = finalValue;\n }\n\n // Call the onMaskChange callback to update React state\n if (onMaskChange) {\n onMaskChange({ value: finalValue });\n }\n };\n\n const updateValue = (updateModel = true) => {\n if (target) {\n if (target.value == null) {\n target.value = '';\n\n if (updateModel) {\n updateModelValue('');\n }\n } else {\n checkVal();\n\n setTimeout(() => {\n if (target) {\n writeBuffer();\n checkVal();\n\n if (updateModel) updateModelValue(target.value);\n }\n }, 10);\n }\n\n focusText.current = target.value;\n }\n };\n\n const initMask = () => {\n tests.current = [];\n partialPosition.current = mask ? mask.length : 0;\n len.current = mask ? mask.length : 0;\n firstNonMaskPos.current = null;\n const defs = {\n 9: '[0-9]',\n a: '[A-Za-z]',\n '*': '[A-Za-z0-9]'\n } as Record<string, string>;\n\n const ua = getUserAgent();\n\n androidChrome.current = /chrome/i.test(ua) && /android/i.test(ua);\n\n const maskTokens = mask ? mask.split('') : '';\n\n for (let i = 0; i < maskTokens.length; i++) {\n const c = maskTokens[i];\n\n if (c === '?') {\n len.current--;\n partialPosition.current = i;\n } else if (defs[c]) {\n tests.current.push(new RegExp(defs[c]));\n\n if (firstNonMaskPos.current === null) {\n firstNonMaskPos.current = tests.current.length - 1;\n }\n\n if (i < partialPosition.current) {\n lastRequiredNonMaskPos.current = tests.current.length - 1;\n }\n } else {\n tests.current.push(null);\n }\n }\n\n buffer.current = [];\n\n for (let i = 0; i < maskTokens.length; i++) {\n const c = maskTokens[i];\n\n if (c !== '?') {\n if (defs[c]) buffer.current.push(getPlaceholder(i));\n else buffer.current.push(c);\n }\n }\n\n defaultBuffer.current = buffer.current.join('');\n\n updateValue(false);\n };\n\n useMountEffect(() => {\n initMask();\n });\n\n return {\n onMaskInput,\n onMaskKeyDown,\n onMaskKeyPress,\n onMaskFocus,\n onMaskBlur,\n onMaskPaste\n };\n}\n"],"mappings":"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","names":["useMountEffect","getUserAgent","React","useMask","options","mask","unmask","slotChar","autoClear","readOnly","onMaskChange","target","len","tests","buffer","defaultBuffer","partialPosition","androidChrome","focus","focusText","firstNonMaskPos","lastRequiredNonMaskPos","caretTimeoutId","oldVal","currentVal","onMaskInput","event","handleAndroidInput","handleInputChange","onMaskKeyDown","_a","k","pos","begin","end","iPhone","caret","seekPrev","seekNext","clearBuffer","shiftL","updateModelValue","checkVal","onMaskKeyPress","p","c","next","shiftR","writeBuffer","onMaskFocus","onMaskBlur","e","onMaskPaste","first","last","_b","getPlaceholder","i","j","t","curVal","start","allow","_c","_d","test","lastMatch","currentTest","isPasteEvent","unmaskValue","value","unmaskedBuffer","thisbuffer","val","finalValue","updateValue","updateModel","initMask","defs","ua","maskTokens"]}
File without changes
@@ -0,0 +1,194 @@
1
+ /**
2
+ * The options for the `useNumberFormatter` hook.
3
+ */
4
+ export interface UseNumberFormatterOptions {
5
+ /**
6
+ * The numeric value to be formatted.
7
+ */
8
+ value?: number | string | null | undefined;
9
+ /**
10
+ * Locale to be used in formatting.
11
+ */
12
+ locale?: string;
13
+ /**
14
+ * The locale matching algorithm to use. Possible values are 'lookup' and 'best fit'.
15
+ * @default 'best fit'
16
+ */
17
+ localeMatcher?: 'lookup' | 'best fit';
18
+ /**
19
+ * Defines the behavior of the component.
20
+ * @default 'decimal'
21
+ */
22
+ mode?: 'decimal' | 'currency';
23
+ /**
24
+ * The currency to use in currency formatting (ISO 4217 currency codes).
25
+ */
26
+ currency?: string;
27
+ /**
28
+ * How to display the currency in currency formatting.
29
+ */
30
+ currencyDisplay?: 'symbol' | 'narrowSymbol' | 'code' | 'name';
31
+ /**
32
+ * Whether to use grouping separators, such as thousands separators.
33
+ * @default true
34
+ */
35
+ useGrouping?: boolean;
36
+ /**
37
+ * The minimum number of fraction digits to use.
38
+ */
39
+ minFractionDigits?: number;
40
+ /**
41
+ * The maximum number of fraction digits to use.
42
+ */
43
+ maxFractionDigits?: number;
44
+ /**
45
+ * How decimals should be rounded.
46
+ */
47
+ roundingMode?: 'ceil' | 'floor' | 'expand' | 'trunc' | 'halfCeil' | 'halfFloor' | 'halfExpand' | 'halfTrunc' | 'halfEven';
48
+ /**
49
+ * Text to display before the value.
50
+ */
51
+ prefix?: string;
52
+ /**
53
+ * Text to display after the value.
54
+ */
55
+ suffix?: string;
56
+ /**
57
+ * Minimum boundary value (used to determine if minus sign is allowed).
58
+ */
59
+ min?: number;
60
+ /**
61
+ * Whether to format the value.
62
+ * @default true
63
+ */
64
+ format?: boolean;
65
+ }
66
+ /**
67
+ * The exposes for the `useNumberFormatter` hook.
68
+ */
69
+ export interface UseNumberFormatterExposes {
70
+ /**
71
+ * The formatted value based on the provided value and options.
72
+ */
73
+ formattedValue: string;
74
+ /**
75
+ * Formats a numeric value to a localized string.
76
+ * @param value - The value to format
77
+ * @returns The formatted string
78
+ */
79
+ formatValue: (value: number | string | null | undefined) => string;
80
+ /**
81
+ * Parses a formatted string back to a numeric value.
82
+ * @param text - The text to parse
83
+ * @returns The parsed number, '-' for minus sign only, or null if invalid
84
+ */
85
+ parseValue: (text: string) => number | string | null;
86
+ /**
87
+ * Adds two numbers with floating-point precision handling.
88
+ * @param base - The base number
89
+ * @param increment - The increment to add
90
+ * @returns The sum with proper precision
91
+ */
92
+ addWithPrecision: (base: number, increment: number) => number;
93
+ /**
94
+ * Checks if the mode is decimal.
95
+ * @returns True if mode is 'decimal'
96
+ */
97
+ isDecimalMode: () => boolean;
98
+ /**
99
+ * Checks if a character is a numeral character (digit, decimal, group separator, or minus sign).
100
+ * @param char - The character to check
101
+ * @returns True if the character is a numeral character
102
+ */
103
+ isNumeralChar: (char: string) => boolean;
104
+ /**
105
+ * Checks if a character is a minus sign.
106
+ * @param char - The character to check
107
+ * @returns True if the character is a minus sign
108
+ */
109
+ isMinusSign: (char: string) => boolean;
110
+ /**
111
+ * Checks if a character is a decimal sign.
112
+ * @param char - The character to check
113
+ * @returns True if the character is a decimal sign
114
+ */
115
+ isDecimalSign: (char: string) => boolean;
116
+ /**
117
+ * Checks if minus sign is allowed based on min value.
118
+ * @returns True if minus sign is allowed
119
+ */
120
+ allowMinusSign: () => boolean;
121
+ /**
122
+ * Gets the decimal character indexes in a value string.
123
+ * @param val - The value string to analyze
124
+ * @returns Object with decimalCharIndex and decimalCharIndexWithoutPrefix
125
+ */
126
+ getDecimalCharIndexes: (val: string) => {
127
+ decimalCharIndex: number;
128
+ decimalCharIndexWithoutPrefix: number;
129
+ };
130
+ /**
131
+ * Gets various character indexes (decimal, minus, suffix, currency) in a value string.
132
+ * @param val - The value string to analyze
133
+ * @returns Object with character indexes
134
+ */
135
+ getCharIndexes: (val: string) => {
136
+ decimalCharIndex: number;
137
+ minusCharIndex: number;
138
+ suffixCharIndex: number;
139
+ currencyCharIndex: number;
140
+ };
141
+ /**
142
+ * Gets the length of decimal part in a formatted value.
143
+ * @param value - The formatted value string
144
+ * @returns The decimal length
145
+ */
146
+ getDecimalLength: (value: string) => number;
147
+ /**
148
+ * Concatenates two value strings, handling decimal positions.
149
+ * @param val1 - The first value
150
+ * @param val2 - The second value
151
+ * @returns The concatenated result
152
+ */
153
+ concatValues: (val1: string, val2: string) => string;
154
+ /**
155
+ * The group character used for thousands separator.
156
+ */
157
+ groupChar: string | null;
158
+ /**
159
+ * The prefix character/string.
160
+ */
161
+ prefixChar: string | null;
162
+ /**
163
+ * The suffix character/string.
164
+ */
165
+ suffixChar: string | null;
166
+ /**
167
+ * The resolved Intl.NumberFormat options.
168
+ */
169
+ resolvedOptions: () => Intl.ResolvedNumberFormatOptions | undefined;
170
+ /**
171
+ * Reinitializes the parser (call when options change).
172
+ */
173
+ constructParser: () => void;
174
+ }
175
+ /**
176
+ * useNumberFormatter hook is used to format and parse numbers using Intl.NumberFormat.
177
+ *
178
+ * @param {UseNumberFormatterOptions} options - The options for the number formatter.
179
+ * @returns {UseNumberFormatterExposes} - The exposed methods for the number formatter.
180
+ *
181
+ * @example
182
+ * ```tsx
183
+ * const formatter = useNumberFormatter({
184
+ * value: 1234.56,
185
+ * locale: 'en-US',
186
+ * mode: 'currency',
187
+ * currency: 'USD'
188
+ * });
189
+ *
190
+ * const formatted = formatter.formatValue(1234.56); // "$1,234.56"
191
+ * const parsed = formatter.parseValue("$1,234.56"); // 1234.56
192
+ * ```
193
+ */
194
+ export declare function useNumberFormatter(options?: UseNumberFormatterOptions): UseNumberFormatterExposes;
@@ -0,0 +1,2 @@
1
+ var ar=Object.defineProperty,lr=Object.defineProperties;var or=Object.getOwnPropertyDescriptors;var L=Object.getOwnPropertySymbols;var mr=Object.prototype.hasOwnProperty,fr=Object.prototype.propertyIsEnumerable;var T=(o,a,t)=>a in o?ar(o,a,{enumerable:!0,configurable:!0,writable:!0,value:t}):o[a]=t,k=(o,a)=>{for(var t in a||(a={}))mr.call(a,t)&&T(o,t,a[t]);if(L)for(var t of L(a))fr.call(a,t)&&T(o,t,a[t]);return o},A=(o,a)=>lr(o,or(a));import*as i from"react";function pr(o={}){let{value:a,locale:t,localeMatcher:G,mode:x="decimal",currency:g,currencyDisplay:h,useGrouping:_=!0,minFractionDigits:C,maxFractionDigits:E,roundingMode:F,prefix:b,suffix:R,min:S,format:q=!0}=o,O=i.useRef(null),V=i.useRef(null),w=i.useRef(null),I=i.useRef(null),l=i.useRef(null),p=i.useRef(null),s=i.useRef(null),d=i.useRef(null),c=i.useRef(null),m=i.useRef(null),y=i.useRef(null),D=i.useRef(null),P=()=>({localeMatcher:G,style:x,currency:g,currencyDisplay:h,useGrouping:_,minimumFractionDigits:C!=null?C:void 0,maximumFractionDigits:E!=null?E:void 0,roundingMode:F}),N=r=>r.replace(/[-[\]{}()*+?.,\\^$|#\s]/g,"\\$&"),z=()=>{var e,n;let r=new Intl.NumberFormat(t,A(k({},P()),{useGrouping:!1}));return new RegExp(`[${r.format(1.1).replace((e=d.current)!=null?e:"","").trim().replace((n=l.current)!=null?n:"","")}]`,"g")},B=()=>{var e;let r=new Intl.NumberFormat(t,{useGrouping:!0});return V.current=r.format(1e6).trim().replace((e=l.current)!=null?e:"","").charAt(0),new RegExp(`[${V.current}]`,"g")},H=()=>{var e;let r=new Intl.NumberFormat(t,{useGrouping:!1});return new RegExp(`[${r.format(-1).trim().replace((e=l.current)!=null?e:"","")}]`,"g")},J=()=>{var r,e;if(g){let n=new Intl.NumberFormat(t,{style:"currency",currency:g,currencyDisplay:h,minimumFractionDigits:0,maximumFractionDigits:0,roundingMode:F});return new RegExp(`[${n.format(1).replace(/\s/g,"").replace((r=l.current)!=null?r:"","").replace((e=p.current)!=null?e:"","")}]`,"g")}return new RegExp("[]","g")},K=()=>{if(b)y.current=new RegExp(N(b),"g");else{let e=new Intl.NumberFormat(t,{style:x,currency:g,currencyDisplay:h}).format(1).split("1")[0];y.current=new RegExp(N(e),"g")}return y.current},Q=()=>{if(R)m.current=new RegExp(N(R),"g");else{let e=new Intl.NumberFormat(t,{style:x,currency:g,currencyDisplay:h,minimumFractionDigits:0,maximumFractionDigits:0,roundingMode:F}).format(1).split("1")[1];m.current=new RegExp(N(e),"g")}return m.current},U=()=>{O.current=new Intl.NumberFormat(t,P());let r=[...new Intl.NumberFormat(t,{useGrouping:!1}).format(9876543210)].reverse(),e=new Map(r.map((n,u)=>[n,u]));if(l.current=new RegExp(`[${r.join("")}]`,"g"),p.current=B(),s.current=H(),d.current=J(),c.current=z(),m.current=Q(),y.current=K(),D.current=n=>e.get(n),b)w.current=b;else{let n=new Intl.NumberFormat(t,{style:x,currency:g,currencyDisplay:h});w.current=n.format(1).split("1")[0]}if(R)I.current=R;else{let n=new Intl.NumberFormat(t,{style:x,currency:g,currencyDisplay:h,minimumFractionDigits:0,maximumFractionDigits:0,roundingMode:F});I.current=n.format(1).split("1")[1]}},W=r=>{if(r!=null){if(typeof r=="string"&&r==="-")return r;if(q){let e=new Intl.NumberFormat(t,P()),n=typeof r=="string"?Number(r):r,u=e.format(n);return b&&(u=b+u),R&&(u=u+R),u}return r.toString()}return""},X=r=>{var n;let e=r.replace(m.current||"","").replace(y.current||"","").trim().replace(/\s/g,"").replace(d.current||"","");if(c.current&&s.current&&l.current){let u=new RegExp(`[${[...new Intl.NumberFormat(t,{useGrouping:!1}).format(9876543210)].reverse().join("")}${new Intl.NumberFormat(t).format(1.1).replace(/[0-9]/g,"")}${new Intl.NumberFormat(t).format(-1).replace(/[0-9]/g,"")}]`,"g");e=((n=e.match(u))==null?void 0:n.join(""))||""}if(p.current&&(e=e.replace(p.current,"")),s.current&&(e=e.replace(s.current,"-")),c.current&&(e=e.replace(c.current,".")),l.current&&D.current&&(e=e.replace(l.current,u=>{let f=D.current?D.current(u):void 0;return f!==void 0?f.toString():""})),e){if(e==="-")return e;let u=+e;return isNaN(u)?null:u}return null},Y=(r,e)=>{let n=r.toString(),u=e.toString(),f=n.includes(".")?n.split(".")[1].length:0,$=u.includes(".")?u.split(".")[1].length:0,M=Math.max(f,$),j=Math.pow(10,M);return Math.round((r+e)*j)/j},Z=()=>x==="decimal",v=()=>{l.current&&(l.current.lastIndex=0),c.current&&(c.current.lastIndex=0),p.current&&(p.current.lastIndex=0),s.current&&(s.current.lastIndex=0)},rr=r=>r.length===1&&(l.current&&l.current.test(r)||c.current&&c.current.test(r)||p.current&&p.current.test(r)||s.current&&s.current.test(r))?(v(),!0):!1,er=r=>s.current&&s.current.test(r)||r==="-"?(s.current&&(s.current.lastIndex=0),!0):!1,nr=r=>t!=null&&t.includes("fr")&&[".",","].includes(r)||c.current&&c.current.test(r)?(c.current&&(c.current.lastIndex=0),!0):!1,tr=()=>S==null||S<0,ur=r=>{let e=c.current?r.search(c.current):-1;c.current&&(c.current.lastIndex=0);let n=r.replace(y.current||"","").trim().replace(/\s/g,"").replace(d.current||"",""),u=c.current?n.search(c.current):-1;return c.current&&(c.current.lastIndex=0),{decimalCharIndex:e,decimalCharIndexWithoutPrefix:u}},cr=r=>{let e=M=>{M&&(M.lastIndex=0)},n=c.current?r.search(c.current):-1;e(c.current);let u=s.current?r.search(s.current):-1;e(s.current);let f=m.current?r.search(m.current):-1;e(m.current);let $=d.current?r.search(d.current):-1;return e(d.current),{decimalCharIndex:n,minusCharIndex:u,suffixCharIndex:f,currencyCharIndex:$}},sr=r=>{var e,n,u;if(r){let f=r.split((e=c.current)!=null?e:"");if(f.length===2)return f[1].replace((n=m.current)!=null?n:"","").trim().replace(/\s/g,"").replace((u=d.current)!=null?u:"","").length}return 0},ir=(r,e)=>{if(r&&e){let n=c.current,u=n?e.search(n):-1;if(n&&(n.lastIndex=0),I.current)return u!==-1?r.replace(I.current,"").split(n!=null?n:"")[0]+e.replace(I.current,"").slice(u)+I.current:r;if(w.current)return u!==-1?r.split(n!=null?n:"")[0]+e.slice(u):r}return r};return i.useEffect(()=>{U()},[t,G,x,g,h,_,C,E,F,b,R]),{formattedValue:W(a),formatValue:W,parseValue:X,addWithPrecision:Y,isDecimalMode:Z,isNumeralChar:rr,isMinusSign:er,isDecimalSign:nr,allowMinusSign:tr,getDecimalCharIndexes:ur,getCharIndexes:cr,getDecimalLength:sr,concatValues:ir,groupChar:V.current,prefixChar:w.current,suffixChar:I.current,resolvedOptions:()=>{var r;return(r=O.current)==null?void 0:r.resolvedOptions()},constructParser:U}}export{pr as useNumberFormatter};
2
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/use-number-formatter/index.ts"],"sourcesContent":["import * as React from 'react';\n\n/**\n * The options for the `useNumberFormatter` hook.\n */\nexport interface UseNumberFormatterOptions {\n /**\n * The numeric value to be formatted.\n */\n value?: number | string | null | undefined;\n /**\n * Locale to be used in formatting.\n */\n locale?: string;\n /**\n * The locale matching algorithm to use. Possible values are 'lookup' and 'best fit'.\n * @default 'best fit'\n */\n localeMatcher?: 'lookup' | 'best fit';\n /**\n * Defines the behavior of the component.\n * @default 'decimal'\n */\n mode?: 'decimal' | 'currency';\n /**\n * The currency to use in currency formatting (ISO 4217 currency codes).\n */\n currency?: string;\n /**\n * How to display the currency in currency formatting.\n */\n currencyDisplay?: 'symbol' | 'narrowSymbol' | 'code' | 'name';\n /**\n * Whether to use grouping separators, such as thousands separators.\n * @default true\n */\n useGrouping?: boolean;\n /**\n * The minimum number of fraction digits to use.\n */\n minFractionDigits?: number;\n /**\n * The maximum number of fraction digits to use.\n */\n maxFractionDigits?: number;\n /**\n * How decimals should be rounded.\n */\n roundingMode?: 'ceil' | 'floor' | 'expand' | 'trunc' | 'halfCeil' | 'halfFloor' | 'halfExpand' | 'halfTrunc' | 'halfEven';\n /**\n * Text to display before the value.\n */\n prefix?: string;\n /**\n * Text to display after the value.\n */\n suffix?: string;\n /**\n * Minimum boundary value (used to determine if minus sign is allowed).\n */\n min?: number;\n /**\n * Whether to format the value.\n * @default true\n */\n format?: boolean;\n}\n\n/**\n * The exposes for the `useNumberFormatter` hook.\n */\nexport interface UseNumberFormatterExposes {\n /**\n * The formatted value based on the provided value and options.\n */\n formattedValue: string;\n /**\n * Formats a numeric value to a localized string.\n * @param value - The value to format\n * @returns The formatted string\n */\n formatValue: (value: number | string | null | undefined) => string;\n /**\n * Parses a formatted string back to a numeric value.\n * @param text - The text to parse\n * @returns The parsed number, '-' for minus sign only, or null if invalid\n */\n parseValue: (text: string) => number | string | null;\n /**\n * Adds two numbers with floating-point precision handling.\n * @param base - The base number\n * @param increment - The increment to add\n * @returns The sum with proper precision\n */\n addWithPrecision: (base: number, increment: number) => number;\n /**\n * Checks if the mode is decimal.\n * @returns True if mode is 'decimal'\n */\n isDecimalMode: () => boolean;\n /**\n * Checks if a character is a numeral character (digit, decimal, group separator, or minus sign).\n * @param char - The character to check\n * @returns True if the character is a numeral character\n */\n isNumeralChar: (char: string) => boolean;\n /**\n * Checks if a character is a minus sign.\n * @param char - The character to check\n * @returns True if the character is a minus sign\n */\n isMinusSign: (char: string) => boolean;\n /**\n * Checks if a character is a decimal sign.\n * @param char - The character to check\n * @returns True if the character is a decimal sign\n */\n isDecimalSign: (char: string) => boolean;\n /**\n * Checks if minus sign is allowed based on min value.\n * @returns True if minus sign is allowed\n */\n allowMinusSign: () => boolean;\n /**\n * Gets the decimal character indexes in a value string.\n * @param val - The value string to analyze\n * @returns Object with decimalCharIndex and decimalCharIndexWithoutPrefix\n */\n getDecimalCharIndexes: (val: string) => { decimalCharIndex: number; decimalCharIndexWithoutPrefix: number };\n /**\n * Gets various character indexes (decimal, minus, suffix, currency) in a value string.\n * @param val - The value string to analyze\n * @returns Object with character indexes\n */\n getCharIndexes: (val: string) => { decimalCharIndex: number; minusCharIndex: number; suffixCharIndex: number; currencyCharIndex: number };\n /**\n * Gets the length of decimal part in a formatted value.\n * @param value - The formatted value string\n * @returns The decimal length\n */\n getDecimalLength: (value: string) => number;\n /**\n * Concatenates two value strings, handling decimal positions.\n * @param val1 - The first value\n * @param val2 - The second value\n * @returns The concatenated result\n */\n concatValues: (val1: string, val2: string) => string;\n /**\n * The group character used for thousands separator.\n */\n groupChar: string | null;\n /**\n * The prefix character/string.\n */\n prefixChar: string | null;\n /**\n * The suffix character/string.\n */\n suffixChar: string | null;\n /**\n * The resolved Intl.NumberFormat options.\n */\n resolvedOptions: () => Intl.ResolvedNumberFormatOptions | undefined;\n /**\n * Reinitializes the parser (call when options change).\n */\n constructParser: () => void;\n}\n\n/**\n * useNumberFormatter hook is used to format and parse numbers using Intl.NumberFormat.\n *\n * @param {UseNumberFormatterOptions} options - The options for the number formatter.\n * @returns {UseNumberFormatterExposes} - The exposed methods for the number formatter.\n *\n * @example\n * ```tsx\n * const formatter = useNumberFormatter({\n * value: 1234.56,\n * locale: 'en-US',\n * mode: 'currency',\n * currency: 'USD'\n * });\n *\n * const formatted = formatter.formatValue(1234.56); // \"$1,234.56\"\n * const parsed = formatter.parseValue(\"$1,234.56\"); // 1234.56\n * ```\n */\nexport function useNumberFormatter(options: UseNumberFormatterOptions = {}): UseNumberFormatterExposes {\n const { value, locale, localeMatcher, mode = 'decimal', currency, currencyDisplay, useGrouping = true, minFractionDigits, maxFractionDigits, roundingMode, prefix, suffix, min, format = true } = options;\n\n // Internal refs for regex patterns\n const numberFormat = React.useRef<Intl.NumberFormat | null>(null);\n const groupCharRef = React.useRef<string | null>(null);\n const prefixCharRef = React.useRef<string | null>(null);\n const suffixCharRef = React.useRef<string | null>(null);\n const _numeral = React.useRef<RegExp | null>(null);\n const _group = React.useRef<RegExp | null>(null);\n const _minusSign = React.useRef<RegExp | null>(null);\n const _currency = React.useRef<RegExp | null>(null);\n const _decimal = React.useRef<RegExp | null>(null);\n const _suffix = React.useRef<RegExp | null>(null);\n const _prefix = React.useRef<RegExp | null>(null);\n const _index = React.useRef<((d: string) => number | undefined) | null>(null);\n\n const getOptions = () => {\n return {\n localeMatcher: localeMatcher,\n style: mode,\n currency: currency,\n currencyDisplay: currencyDisplay,\n useGrouping: useGrouping,\n minimumFractionDigits: minFractionDigits ?? undefined,\n maximumFractionDigits: maxFractionDigits ?? undefined,\n roundingMode: roundingMode\n };\n };\n\n const escapeRegExp = (text: string) => {\n return text.replace(/[-[\\]{}()*+?.,\\\\^$|#\\s]/g, '\\\\$&');\n };\n\n const getDecimalExpression = () => {\n const formatter = new Intl.NumberFormat(locale, { ...getOptions(), useGrouping: false });\n\n return new RegExp(\n `[${formatter\n .format(1.1)\n .replace(_currency.current ?? '', '')\n .trim()\n .replace(_numeral.current ?? '', '')}]`,\n 'g'\n );\n };\n\n const getGroupingExpression = () => {\n const formatter = new Intl.NumberFormat(locale, { useGrouping: true });\n\n groupCharRef.current = formatter\n .format(1000000)\n .trim()\n .replace(_numeral.current ?? '', '')\n .charAt(0);\n\n return new RegExp(`[${groupCharRef.current}]`, 'g');\n };\n\n const getMinusSignExpression = () => {\n const formatter = new Intl.NumberFormat(locale, { useGrouping: false });\n\n return new RegExp(\n `[${formatter\n .format(-1)\n .trim()\n .replace(_numeral.current ?? '', '')}]`,\n 'g'\n );\n };\n\n const getCurrencyExpression = () => {\n if (currency) {\n const formatter = new Intl.NumberFormat(locale, { style: 'currency', currency: currency, currencyDisplay: currencyDisplay, minimumFractionDigits: 0, maximumFractionDigits: 0, roundingMode: roundingMode });\n\n return new RegExp(\n `[${formatter\n .format(1)\n .replace(/\\s/g, '')\n .replace(_numeral.current ?? '', '')\n .replace(_group.current ?? '', '')}]`,\n 'g'\n );\n }\n\n return new RegExp(`[]`, 'g');\n };\n\n const getPrefixExpression = () => {\n if (prefix) {\n _prefix.current = new RegExp(escapeRegExp(prefix), 'g');\n } else {\n const formatter = new Intl.NumberFormat(locale, { style: mode, currency: currency, currencyDisplay: currencyDisplay });\n\n const prefixStr = formatter.format(1).split('1')[0];\n\n _prefix.current = new RegExp(escapeRegExp(prefixStr), 'g');\n }\n\n return _prefix.current;\n };\n\n const getSuffixExpression = () => {\n if (suffix) {\n _suffix.current = new RegExp(escapeRegExp(suffix), 'g');\n } else {\n const formatter = new Intl.NumberFormat(locale, { style: mode, currency: currency, currencyDisplay: currencyDisplay, minimumFractionDigits: 0, maximumFractionDigits: 0, roundingMode: roundingMode });\n\n const suffixStr = formatter.format(1).split('1')[1];\n\n _suffix.current = new RegExp(escapeRegExp(suffixStr), 'g');\n }\n\n return _suffix.current;\n };\n\n const constructParser = () => {\n numberFormat.current = new Intl.NumberFormat(locale, getOptions());\n const numerals = [...new Intl.NumberFormat(locale, { useGrouping: false }).format(9876543210)].reverse();\n const index = new Map(numerals.map((d, i) => [d, i]));\n\n _numeral.current = new RegExp(`[${numerals.join('')}]`, 'g');\n _group.current = getGroupingExpression();\n _minusSign.current = getMinusSignExpression();\n _currency.current = getCurrencyExpression();\n _decimal.current = getDecimalExpression();\n _suffix.current = getSuffixExpression();\n _prefix.current = getPrefixExpression();\n _index.current = (d) => index.get(d);\n\n // Set prefix and suffix chars\n if (prefix) {\n prefixCharRef.current = prefix;\n } else {\n const formatter = new Intl.NumberFormat(locale, { style: mode, currency: currency, currencyDisplay: currencyDisplay });\n\n prefixCharRef.current = formatter.format(1).split('1')[0];\n }\n\n if (suffix) {\n suffixCharRef.current = suffix;\n } else {\n const formatter = new Intl.NumberFormat(locale, { style: mode, currency: currency, currencyDisplay: currencyDisplay, minimumFractionDigits: 0, maximumFractionDigits: 0, roundingMode: roundingMode });\n\n suffixCharRef.current = formatter.format(1).split('1')[1];\n }\n };\n\n const formatValue = (value: number | string | null | undefined) => {\n if (value != null) {\n if (typeof value === 'string' && value === '-') {\n // Minus sign\n return value;\n }\n\n if (format) {\n const formatter = new Intl.NumberFormat(locale, getOptions());\n const numericValue = typeof value === 'string' ? Number(value) : value;\n let formattedValue = formatter.format(numericValue);\n\n if (prefix) {\n formattedValue = prefix + formattedValue;\n }\n\n if (suffix) {\n formattedValue = formattedValue + suffix;\n }\n\n return formattedValue;\n }\n\n return value.toString();\n }\n\n return '';\n };\n\n const parseValue = (text: string) => {\n let cleanText = text\n .replace(_suffix.current || '', '')\n .replace(_prefix.current || '', '')\n .trim()\n .replace(/\\s/g, '')\n .replace(_currency.current || '', '');\n\n if (_decimal.current && _minusSign.current && _numeral.current) {\n const validChars = new RegExp(\n `[${[...new Intl.NumberFormat(locale, { useGrouping: false }).format(9876543210)].reverse().join('')}${new Intl.NumberFormat(locale).format(1.1).replace(/[0-9]/g, '')}${new Intl.NumberFormat(locale)\n .format(-1)\n .replace(/[0-9]/g, '')}]`,\n 'g'\n );\n\n cleanText = cleanText.match(validChars)?.join('') || '';\n }\n\n if (_group.current) {\n cleanText = cleanText.replace(_group.current, '');\n }\n\n if (_minusSign.current) {\n cleanText = cleanText.replace(_minusSign.current, '-');\n }\n\n if (_decimal.current) {\n cleanText = cleanText.replace(_decimal.current, '.');\n }\n\n if (_numeral.current && _index.current) {\n cleanText = cleanText.replace(_numeral.current, (d) => {\n const res = _index.current ? _index.current(d) : undefined;\n\n return res !== undefined ? res.toString() : '';\n });\n }\n\n if (cleanText) {\n if (cleanText === '-') return cleanText;\n\n const parsedValue = +cleanText;\n\n return isNaN(parsedValue) ? null : parsedValue;\n }\n\n return null;\n };\n\n const addWithPrecision = (base: number, increment: number) => {\n const baseStr = base.toString();\n const stepStr = increment.toString();\n\n const baseDecimalPlaces = baseStr.includes('.') ? baseStr.split('.')[1].length : 0;\n const stepDecimalPlaces = stepStr.includes('.') ? stepStr.split('.')[1].length : 0;\n\n const maxDecimalPlaces = Math.max(baseDecimalPlaces, stepDecimalPlaces);\n const precision = Math.pow(10, maxDecimalPlaces);\n\n return Math.round((base + increment) * precision) / precision;\n };\n\n const isDecimalMode = () => {\n return mode === 'decimal';\n };\n\n const resetRegex = () => {\n if (_numeral.current) _numeral.current.lastIndex = 0;\n\n if (_decimal.current) _decimal.current.lastIndex = 0;\n\n if (_group.current) _group.current.lastIndex = 0;\n\n if (_minusSign.current) _minusSign.current.lastIndex = 0;\n };\n\n const isNumeralChar = (char: string) => {\n if (char.length === 1 && ((_numeral.current && _numeral.current.test(char)) || (_decimal.current && _decimal.current.test(char)) || (_group.current && _group.current.test(char)) || (_minusSign.current && _minusSign.current.test(char)))) {\n resetRegex();\n\n return true;\n }\n\n return false;\n };\n\n const isMinusSignFn = (char: string) => {\n if ((_minusSign.current && _minusSign.current.test(char)) || char === '-') {\n if (_minusSign.current) {\n _minusSign.current.lastIndex = 0;\n }\n\n return true;\n }\n\n return false;\n };\n\n const isDecimalSignFn = (char: string) => {\n if ((locale?.includes('fr') && ['.', ','].includes(char)) || (_decimal.current && _decimal.current.test(char))) {\n if (_decimal.current) {\n _decimal.current.lastIndex = 0;\n }\n\n return true;\n }\n\n return false;\n };\n\n const allowMinusSign = () => {\n return min === undefined || min === null || min < 0;\n };\n\n const getDecimalCharIndexes = (val: string) => {\n const decimalCharIndex = _decimal.current ? val.search(_decimal.current) : -1;\n\n if (_decimal.current) {\n _decimal.current.lastIndex = 0;\n }\n\n const filteredVal = val\n .replace(_prefix.current || '', '')\n .trim()\n .replace(/\\s/g, '')\n .replace(_currency.current || '', '');\n const decimalCharIndexWithoutPrefix = _decimal.current ? filteredVal.search(_decimal.current) : -1;\n\n if (_decimal.current) {\n _decimal.current.lastIndex = 0;\n }\n\n return { decimalCharIndex, decimalCharIndexWithoutPrefix };\n };\n\n const getCharIndexes = (val: string) => {\n const resetRegexLastIndex = (regex: RegExp | null) => {\n if (regex) {\n regex.lastIndex = 0;\n }\n };\n\n const decimalCharIndex = _decimal.current ? val.search(_decimal.current) : -1;\n\n resetRegexLastIndex(_decimal.current);\n\n const minusCharIndex = _minusSign.current ? val.search(_minusSign.current) : -1;\n\n resetRegexLastIndex(_minusSign.current);\n\n const suffixCharIndex = _suffix.current ? val.search(_suffix.current) : -1;\n\n resetRegexLastIndex(_suffix.current);\n\n const currencyCharIndex = _currency.current ? val.search(_currency.current) : -1;\n\n resetRegexLastIndex(_currency.current);\n\n return { decimalCharIndex, minusCharIndex, suffixCharIndex, currencyCharIndex };\n };\n\n const getDecimalLength = (value: string) => {\n if (value) {\n const valueSplit = value.split(_decimal.current ?? '');\n\n if (valueSplit.length === 2) {\n return valueSplit[1]\n .replace(_suffix.current ?? '', '')\n .trim()\n .replace(/\\s/g, '')\n .replace(_currency.current ?? '', '').length;\n }\n }\n\n return 0;\n };\n\n const concatValues = (val1: string, val2: string) => {\n if (val1 && val2) {\n const decimalRegex = _decimal.current;\n const decimalCharIndex = decimalRegex ? val2.search(decimalRegex) : -1;\n\n if (decimalRegex) {\n decimalRegex.lastIndex = 0;\n }\n\n if (suffixCharRef.current) {\n return decimalCharIndex !== -1 ? val1.replace(suffixCharRef.current, '').split(decimalRegex ?? '')[0] + val2.replace(suffixCharRef.current, '').slice(decimalCharIndex) + suffixCharRef.current : val1;\n } else if (prefixCharRef.current) {\n return decimalCharIndex !== -1 ? val1.split(decimalRegex ?? '')[0] + val2.slice(decimalCharIndex) : val1;\n }\n }\n\n return val1;\n };\n\n React.useEffect(() => {\n constructParser();\n }, [locale, localeMatcher, mode, currency, currencyDisplay, useGrouping, minFractionDigits, maxFractionDigits, roundingMode, prefix, suffix]);\n\n return {\n formattedValue: formatValue(value),\n formatValue,\n parseValue,\n addWithPrecision,\n isDecimalMode,\n isNumeralChar,\n isMinusSign: isMinusSignFn,\n isDecimalSign: isDecimalSignFn,\n allowMinusSign,\n getDecimalCharIndexes,\n getCharIndexes,\n getDecimalLength,\n concatValues,\n groupChar: groupCharRef.current,\n prefixChar: prefixCharRef.current,\n suffixChar: suffixCharRef.current,\n resolvedOptions: () => numberFormat.current?.resolvedOptions(),\n constructParser\n };\n}\n"],"mappings":"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","names":["React","useNumberFormatter","options","value","locale","localeMatcher","mode","currency","currencyDisplay","useGrouping","minFractionDigits","maxFractionDigits","roundingMode","prefix","suffix","min","format","numberFormat","groupCharRef","prefixCharRef","suffixCharRef","_numeral","_group","_minusSign","_currency","_decimal","_suffix","_prefix","_index","getOptions","escapeRegExp","text","getDecimalExpression","_a","_b","formatter","__spreadProps","__spreadValues","getGroupingExpression","getMinusSignExpression","getCurrencyExpression","getPrefixExpression","prefixStr","getSuffixExpression","suffixStr","constructParser","numerals","index","d","i","formatValue","numericValue","formattedValue","parseValue","cleanText","validChars","res","parsedValue","addWithPrecision","base","increment","baseStr","stepStr","baseDecimalPlaces","stepDecimalPlaces","maxDecimalPlaces","precision","isDecimalMode","resetRegex","isNumeralChar","char","isMinusSignFn","isDecimalSignFn","allowMinusSign","getDecimalCharIndexes","val","decimalCharIndex","filteredVal","decimalCharIndexWithoutPrefix","getCharIndexes","resetRegexLastIndex","regex","minusCharIndex","suffixCharIndex","currencyCharIndex","getDecimalLength","_c","valueSplit","concatValues","val1","val2","decimalRegex"]}
File without changes
@@ -0,0 +1,21 @@
1
+ import * as React from 'react';
2
+ /**
3
+ * usePresence hook is used to manage the presence of a component.
4
+ *
5
+ * @param open - The open state.
6
+ * @returns An object containing the present, exiting, mounted, and ref states.
7
+ *
8
+ * @example
9
+ * ```tsx
10
+ * const { present, exiting, mounted, ref } = usePresence(true);
11
+ *
12
+ * return present && (
13
+ * <div className="card flex justify-center"></div>
14
+ * );
15
+ */
16
+ export declare function usePresence(open: boolean, fallbackMs?: number): {
17
+ present: boolean;
18
+ exiting: boolean;
19
+ mounted: boolean;
20
+ ref: React.RefObject<HTMLElement | null>;
21
+ };
@@ -0,0 +1,2 @@
1
+ import*as t from"react";function R(i,o=500){let[m,c]=t.useState(i),[d,a]=t.useState(!1),[v,l]=t.useState(!1),f=t.useRef(null),n=t.useRef(null),r=t.useRef(null);return t.useEffect(()=>{if(n.current&&(n.current(),n.current=null),r.current&&(r.current(),r.current=null),i){c(!0),a(!1);let e=[];e.push(requestAnimationFrame(()=>{e.push(requestAnimationFrame(()=>{e.push(requestAnimationFrame(()=>l(!0)))}))})),r.current=()=>{e.forEach(u=>cancelAnimationFrame(u)),e.length=0}}else if(f.current){a(!0),l(!1);let e=f.current,u=!1,s=()=>{u||(u=!0,c(!1),a(!1),e.removeEventListener("transitionend",s),e.removeEventListener("animationend",s),n.current=null)};e.addEventListener("transitionend",s,{passive:!0}),e.addEventListener("animationend",s,{passive:!0}),n.current=()=>{u||(e.removeEventListener("transitionend",s),e.removeEventListener("animationend",s))}}else l(!1),c(!1),a(!1)},[i,o]),t.useEffect(()=>()=>{n.current&&n.current(),r.current&&r.current()},[]),{present:m,exiting:d,mounted:v,ref:f}}export{R as usePresence};
2
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/use-presence/index.ts"],"sourcesContent":["import * as React from 'react';\n\n/**\n * usePresence hook is used to manage the presence of a component.\n *\n * @param open - The open state.\n * @returns An object containing the present, exiting, mounted, and ref states.\n *\n * @example\n * ```tsx\n * const { present, exiting, mounted, ref } = usePresence(true);\n *\n * return present && (\n * <div className=\"card flex justify-center\"></div>\n * );\n */\n\nexport function usePresence(open: boolean, fallbackMs: number = 500) {\n const [present, setPresent] = React.useState(open);\n const [exiting, setExiting] = React.useState(false);\n const [mounted, setMounted] = React.useState(false);\n const ref = React.useRef<HTMLElement>(null);\n const cleanupRef = React.useRef<(() => void) | null>(null);\n const rafCleanupRef = React.useRef<(() => void) | null>(null);\n\n React.useEffect(() => {\n if (cleanupRef.current) {\n cleanupRef.current();\n cleanupRef.current = null;\n }\n\n if (rafCleanupRef.current) {\n rafCleanupRef.current();\n rafCleanupRef.current = null;\n }\n\n if (open) {\n setPresent(true);\n setExiting(false);\n\n const rafs: number[] = [];\n\n rafs.push(\n requestAnimationFrame(() => {\n rafs.push(\n requestAnimationFrame(() => {\n rafs.push(requestAnimationFrame(() => setMounted(true)));\n })\n );\n })\n );\n\n rafCleanupRef.current = () => {\n rafs.forEach((raf) => cancelAnimationFrame(raf));\n rafs.length = 0;\n };\n } else if (ref.current) {\n setExiting(true);\n setMounted(false);\n const node = ref.current;\n let isHandled = false;\n\n const handleEnd = () => {\n if (isHandled) return;\n\n isHandled = true;\n\n setPresent(false);\n setExiting(false);\n\n node.removeEventListener('transitionend', handleEnd);\n node.removeEventListener('animationend', handleEnd);\n\n cleanupRef.current = null;\n };\n\n node.addEventListener('transitionend', handleEnd, { passive: true });\n node.addEventListener('animationend', handleEnd, { passive: true });\n\n // const fallbackTimeout = setTimeout(() => {\n // if (!isHandled) {\n // handleEnd();\n // }\n // }, fallbackMs);\n\n cleanupRef.current = () => {\n // clearTimeout(fallbackTimeout);\n\n if (!isHandled) {\n node.removeEventListener('transitionend', handleEnd);\n node.removeEventListener('animationend', handleEnd);\n }\n };\n } else {\n setMounted(false);\n setPresent(false);\n setExiting(false);\n }\n }, [open, fallbackMs]);\n\n React.useEffect(() => {\n return () => {\n if (cleanupRef.current) {\n cleanupRef.current();\n }\n\n if (rafCleanupRef.current) {\n rafCleanupRef.current();\n }\n };\n }, []);\n\n return { present, exiting, mounted, ref };\n}\n"],"mappings":"AAAA,UAAYA,MAAW,QAiBhB,SAASC,EAAYC,EAAeC,EAAqB,IAAK,CACjE,GAAM,CAACC,EAASC,CAAU,EAAU,WAASH,CAAI,EAC3C,CAACI,EAASC,CAAU,EAAU,WAAS,EAAK,EAC5C,CAACC,EAASC,CAAU,EAAU,WAAS,EAAK,EAC5CC,EAAY,SAAoB,IAAI,EACpCC,EAAmB,SAA4B,IAAI,EACnDC,EAAsB,SAA4B,IAAI,EAE5D,OAAM,YAAU,IAAM,CAWlB,GAVID,EAAW,UACXA,EAAW,QAAQ,EACnBA,EAAW,QAAU,MAGrBC,EAAc,UACdA,EAAc,QAAQ,EACtBA,EAAc,QAAU,MAGxBV,EAAM,CACNG,EAAW,EAAI,EACfE,EAAW,EAAK,EAEhB,IAAMM,EAAiB,CAAC,EAExBA,EAAK,KACD,sBAAsB,IAAM,CACxBA,EAAK,KACD,sBAAsB,IAAM,CACxBA,EAAK,KAAK,sBAAsB,IAAMJ,EAAW,EAAI,CAAC,CAAC,CAC3D,CAAC,CACL,CACJ,CAAC,CACL,EAEAG,EAAc,QAAU,IAAM,CAC1BC,EAAK,QAASC,GAAQ,qBAAqBA,CAAG,CAAC,EAC/CD,EAAK,OAAS,CAClB,CACJ,SAAWH,EAAI,QAAS,CACpBH,EAAW,EAAI,EACfE,EAAW,EAAK,EAChB,IAAMM,EAAOL,EAAI,QACbM,EAAY,GAEVC,EAAY,IAAM,CAChBD,IAEJA,EAAY,GAEZX,EAAW,EAAK,EAChBE,EAAW,EAAK,EAEhBQ,EAAK,oBAAoB,gBAAiBE,CAAS,EACnDF,EAAK,oBAAoB,eAAgBE,CAAS,EAElDN,EAAW,QAAU,KACzB,EAEAI,EAAK,iBAAiB,gBAAiBE,EAAW,CAAE,QAAS,EAAK,CAAC,EACnEF,EAAK,iBAAiB,eAAgBE,EAAW,CAAE,QAAS,EAAK,CAAC,EAQlEN,EAAW,QAAU,IAAM,CAGlBK,IACDD,EAAK,oBAAoB,gBAAiBE,CAAS,EACnDF,EAAK,oBAAoB,eAAgBE,CAAS,EAE1D,CACJ,MACIR,EAAW,EAAK,EAChBJ,EAAW,EAAK,EAChBE,EAAW,EAAK,CAExB,EAAG,CAACL,EAAMC,CAAU,CAAC,EAEf,YAAU,IACL,IAAM,CACLQ,EAAW,SACXA,EAAW,QAAQ,EAGnBC,EAAc,SACdA,EAAc,QAAQ,CAE9B,EACD,CAAC,CAAC,EAEE,CAAE,QAAAR,EAAS,QAAAE,EAAS,QAAAE,EAAS,IAAAE,CAAI,CAC5C","names":["React","usePresence","open","fallbackMs","present","setPresent","exiting","setExiting","mounted","setMounted","ref","cleanupRef","rafCleanupRef","rafs","raf","node","isHandled","handleEnd"]}
File without changes
@@ -1,26 +1,26 @@
1
1
  /**
2
2
  * Used to merge and differentiate incoming props with the default props.
3
- * - Keys that exist in both `props1` and `props2` are placed in `props`, with values from `props1`.
4
- * - Keys that exist in `props1` but not in `props2` are placed in `attrs`.
3
+ * - Keys that exist in both `props1` and `props2` are placed in `props`, with values from `props2`.
4
+ * - Keys that exist in `props2` but not in `props1` are placed in `attrs`.
5
5
  *
6
- * @template P1 The type of the incoming set of props.
7
- * @template P2 The type of the default set of props.
6
+ * @template P1 The type of the default set of props.
7
+ * @template P2 The type of the incoming set of props.
8
8
  *
9
- * @param props1 The incoming set of props (e.g., user-defined or dynamic props).
10
- * @param props2 The default set of props (e.g., default props).
9
+ * @param props1 The default set of props (e.g., default props).
10
+ * @param props2 The incoming set of props (e.g., user-defined or dynamic props).
11
11
  * @returns An object containing:
12
- * - `props`: A new object containing keys that exist in both `props1` and `props2`, using values from `props1`.
13
- * - `attrs`: A new object containing keys that exist only in `props1`, excluding any keys from `props2`.
12
+ * - `props`: A new object containing keys that exist in both `props1` and `props2`, using values from `props2`.
13
+ * - `attrs`: A new object containing keys that exist only in `props2`, excluding any keys from `props1`.
14
14
  *
15
15
  * @example
16
16
  * ```ts
17
- * const { props, attrs } = useProps({ id: 'foo', className: 'bar' }, { className: 'baz' });
17
+ * const { props, attrs } = useProps({ className: 'baz' }, { id: 'foo', className: 'bar' });
18
18
  *
19
19
  * console.log(props); // { className: 'bar' }
20
20
  * console.log(attrs); // { id: 'foo' }
21
21
  * ```
22
22
  */
23
23
  export declare function useProps<P1, P2>(props1?: P1, props2?: P2): {
24
- props: Pick<P1 & P2, keyof P2>;
25
- attrs: Omit<P1, keyof P2>;
24
+ props: Pick<P1 & P2, keyof P1>;
25
+ attrs: Omit<P2, keyof P1>;
26
26
  };
@@ -1,2 +1,2 @@
1
- var i=Object.defineProperty;var o=Object.getOwnPropertySymbols;var u=Object.prototype.hasOwnProperty,p=Object.prototype.propertyIsEnumerable;var P=(r,t,s)=>t in r?i(r,t,{enumerable:!0,configurable:!0,writable:!0,value:s}):r[t]=s,a=(r,t)=>{for(var s in t||(t={}))u.call(t,s)&&P(r,s,t[s]);if(o)for(var s of o(t))p.call(t,s)&&P(r,s,t[s]);return r};import*as c from"react";function f(r={},t={}){return c.useMemo(()=>{let s={props:a({},t),attrs:{}};return Object.entries(r).forEach(([n,e])=>{n in t?s.props[n]=e:s.attrs[n]=e}),s},[r,t])}export{f as useProps};
1
+ var i=Object.defineProperty;var o=Object.getOwnPropertySymbols;var u=Object.prototype.hasOwnProperty,p=Object.prototype.propertyIsEnumerable;var P=(r,s,t)=>s in r?i(r,s,{enumerable:!0,configurable:!0,writable:!0,value:t}):r[s]=t,a=(r,s)=>{for(var t in s||(s={}))u.call(s,t)&&P(r,t,s[t]);if(o)for(var t of o(s))p.call(s,t)&&P(r,t,s[t]);return r};import*as c from"react";function f(r={},s={}){return c.useMemo(()=>{let t={props:a({},r),attrs:{}};return Object.entries(s).forEach(([n,e])=>{n in r?t.props[n]=e:t.attrs[n]=e}),t},[r,s])}export{f as useProps};
2
2
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/use-props/index.ts"],"sourcesContent":["import * as React from 'react';\n\n/**\n * Used to merge and differentiate incoming props with the default props.\n * - Keys that exist in both `props1` and `props2` are placed in `props`, with values from `props1`.\n * - Keys that exist in `props1` but not in `props2` are placed in `attrs`.\n *\n * @template P1 The type of the incoming set of props.\n * @template P2 The type of the default set of props.\n *\n * @param props1 The incoming set of props (e.g., user-defined or dynamic props).\n * @param props2 The default set of props (e.g., default props).\n * @returns An object containing:\n * - `props`: A new object containing keys that exist in both `props1` and `props2`, using values from `props1`.\n * - `attrs`: A new object containing keys that exist only in `props1`, excluding any keys from `props2`.\n *\n * @example\n * ```ts\n * const { props, attrs } = useProps({ id: 'foo', className: 'bar' }, { className: 'baz' });\n *\n * console.log(props); // { className: 'bar' }\n * console.log(attrs); // { id: 'foo' }\n * ```\n */\nexport function useProps<P1, P2>(props1: P1 = {} as P1, props2: P2 = {} as P2) {\n type Props = Pick<P1 & P2, keyof P2>;\n type Attrs = Omit<P1, keyof P2>;\n type Result = { props: Props; attrs: Attrs };\n\n return React.useMemo(() => {\n const result: Result = { props: { ...props2 } as Props, attrs: {} as Attrs };\n\n Object.entries(props1 as Record<string, unknown>).forEach(([key, value]) => {\n if (key in (props2 as Record<string, unknown>)) {\n (result.props as Record<string, unknown>)[key] = value;\n } else {\n (result.attrs as Record<string, unknown>)[key] = value;\n }\n });\n\n return result;\n }, [props1, props2]);\n}\n"],"mappings":"yVAAA,UAAYA,MAAW,QAwBhB,SAASC,EAAiBC,EAAa,CAAC,EAASC,EAAa,CAAC,EAAS,CAK3E,OAAa,UAAQ,IAAM,CACvB,IAAMC,EAAiB,CAAE,MAAOC,EAAA,GAAKF,GAAmB,MAAO,CAAC,CAAW,EAE3E,cAAO,QAAQD,CAAiC,EAAE,QAAQ,CAAC,CAACI,EAAKC,CAAK,IAAM,CACpED,KAAQH,EACPC,EAAO,MAAkCE,CAAG,EAAIC,EAEhDH,EAAO,MAAkCE,CAAG,EAAIC,CAEzD,CAAC,EAEMH,CACX,EAAG,CAACF,EAAQC,CAAM,CAAC,CACvB","names":["React","useProps","props1","props2","result","__spreadValues","key","value"]}
1
+ {"version":3,"sources":["../../src/use-props/index.ts"],"sourcesContent":["import * as React from 'react';\n\n/**\n * Used to merge and differentiate incoming props with the default props.\n * - Keys that exist in both `props1` and `props2` are placed in `props`, with values from `props2`.\n * - Keys that exist in `props2` but not in `props1` are placed in `attrs`.\n *\n * @template P1 The type of the default set of props.\n * @template P2 The type of the incoming set of props.\n *\n * @param props1 The default set of props (e.g., default props).\n * @param props2 The incoming set of props (e.g., user-defined or dynamic props).\n * @returns An object containing:\n * - `props`: A new object containing keys that exist in both `props1` and `props2`, using values from `props2`.\n * - `attrs`: A new object containing keys that exist only in `props2`, excluding any keys from `props1`.\n *\n * @example\n * ```ts\n * const { props, attrs } = useProps({ className: 'baz' }, { id: 'foo', className: 'bar' });\n *\n * console.log(props); // { className: 'bar' }\n * console.log(attrs); // { id: 'foo' }\n * ```\n */\nexport function useProps<P1, P2>(props1: P1 = {} as P1, props2: P2 = {} as P2) {\n type Props = Pick<P1 & P2, keyof P1>;\n type Attrs = Omit<P2, keyof P1>;\n type Result = { props: Props; attrs: Attrs };\n\n return React.useMemo(() => {\n const result: Result = { props: { ...props1 } as Props, attrs: {} as Attrs };\n\n Object.entries(props2 as Record<string, unknown>).forEach(([key, value]) => {\n if (key in (props1 as Record<string, unknown>)) {\n (result.props as Record<string, unknown>)[key] = value;\n } else {\n (result.attrs as Record<string, unknown>)[key] = value;\n }\n });\n\n return result;\n }, [props1, props2]);\n}\n"],"mappings":"yVAAA,UAAYA,MAAW,QAwBhB,SAASC,EAAiBC,EAAa,CAAC,EAASC,EAAa,CAAC,EAAS,CAK3E,OAAa,UAAQ,IAAM,CACvB,IAAMC,EAAiB,CAAE,MAAOC,EAAA,GAAKH,GAAmB,MAAO,CAAC,CAAW,EAE3E,cAAO,QAAQC,CAAiC,EAAE,QAAQ,CAAC,CAACG,EAAKC,CAAK,IAAM,CACpED,KAAQJ,EACPE,EAAO,MAAkCE,CAAG,EAAIC,EAEhDH,EAAO,MAAkCE,CAAG,EAAIC,CAEzD,CAAC,EAEMH,CACX,EAAG,CAACF,EAAQC,CAAM,CAAC,CACvB","names":["React","useProps","props1","props2","result","__spreadValues","key","value"]}
@@ -0,0 +1 @@
1
+ export declare const useQueueTask: () => (id: string | number, task: () => void) => void;
@@ -0,0 +1,2 @@
1
+ import*as e from"react";var a=()=>{let t=e.useRef(new Map),r=e.useRef(!1),u=e.useCallback(()=>{r.current=!1;let s=t.current;t.current=new Map,s.forEach(c=>c())},[]);return e.useCallback((s,c)=>{t.current.set(s,c),r.current||(r.current=!0,queueMicrotask(u))},[u])};export{a as useQueueTask};
2
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/use-queue-task/index.ts"],"sourcesContent":["import * as React from 'react';\n\nexport const useQueueTask = () => {\n const tasksRef = React.useRef(new Map<string | number, () => void>());\n const scheduledRef = React.useRef(false);\n\n const flush = React.useCallback(() => {\n scheduledRef.current = false;\n const tasks = tasksRef.current;\n\n tasksRef.current = new Map();\n tasks.forEach((task) => task());\n }, []);\n\n return React.useCallback(\n (id: string | number, task: () => void) => {\n tasksRef.current.set(id, task);\n\n if (!scheduledRef.current) {\n scheduledRef.current = true;\n queueMicrotask(flush);\n }\n },\n [flush]\n );\n};\n"],"mappings":"AAAA,UAAYA,MAAW,QAEhB,IAAMC,EAAe,IAAM,CAC9B,IAAMC,EAAiB,SAAO,IAAI,GAAkC,EAC9DC,EAAqB,SAAO,EAAK,EAEjCC,EAAc,cAAY,IAAM,CAClCD,EAAa,QAAU,GACvB,IAAME,EAAQH,EAAS,QAEvBA,EAAS,QAAU,IAAI,IACvBG,EAAM,QAASC,GAASA,EAAK,CAAC,CAClC,EAAG,CAAC,CAAC,EAEL,OAAa,cACT,CAACC,EAAqBD,IAAqB,CACvCJ,EAAS,QAAQ,IAAIK,EAAID,CAAI,EAExBH,EAAa,UACdA,EAAa,QAAU,GACvB,eAAeC,CAAK,EAE5B,EACA,CAACA,CAAK,CACV,CACJ","names":["React","useQueueTask","tasksRef","scheduledRef","flush","tasks","task","id"]}