@mantine/hooks 9.0.0-alpha.3 → 9.0.0-alpha.5

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 (56) hide show
  1. package/cjs/index.cjs +2 -0
  2. package/cjs/index.cjs.map +1 -1
  3. package/cjs/use-click-outside/use-click-outside.cjs +11 -11
  4. package/cjs/use-click-outside/use-click-outside.cjs.map +1 -1
  5. package/cjs/use-collapse/use-collapse.cjs +3 -2
  6. package/cjs/use-collapse/use-collapse.cjs.map +1 -1
  7. package/cjs/use-drag/use-drag.cjs +304 -0
  8. package/cjs/use-drag/use-drag.cjs.map +1 -0
  9. package/cjs/use-headroom/use-headroom.cjs +60 -42
  10. package/cjs/use-headroom/use-headroom.cjs.map +1 -1
  11. package/cjs/use-hotkeys/use-hotkeys.cjs +14 -14
  12. package/cjs/use-hotkeys/use-hotkeys.cjs.map +1 -1
  13. package/cjs/use-mask/use-mask.cjs +583 -0
  14. package/cjs/use-mask/use-mask.cjs.map +1 -0
  15. package/cjs/use-page-leave/use-page-leave.cjs +3 -2
  16. package/cjs/use-page-leave/use-page-leave.cjs.map +1 -1
  17. package/cjs/use-roving-index/use-roving-index.cjs +270 -0
  18. package/cjs/use-roving-index/use-roving-index.cjs.map +1 -0
  19. package/cjs/use-scroll-direction/use-scroll-direction.cjs +39 -0
  20. package/cjs/use-scroll-direction/use-scroll-direction.cjs.map +1 -0
  21. package/cjs/use-text-selection/use-text-selection.cjs +2 -2
  22. package/cjs/use-text-selection/use-text-selection.cjs.map +1 -1
  23. package/cjs/use-window-event/use-window-event.cjs +4 -3
  24. package/cjs/use-window-event/use-window-event.cjs.map +1 -1
  25. package/esm/index.mjs +1 -0
  26. package/esm/index.mjs.map +1 -1
  27. package/esm/use-click-outside/use-click-outside.mjs +12 -12
  28. package/esm/use-click-outside/use-click-outside.mjs.map +1 -1
  29. package/esm/use-collapse/use-collapse.mjs +4 -3
  30. package/esm/use-collapse/use-collapse.mjs.map +1 -1
  31. package/esm/use-drag/use-drag.mjs +302 -0
  32. package/esm/use-drag/use-drag.mjs.map +1 -0
  33. package/esm/use-headroom/use-headroom.mjs +60 -42
  34. package/esm/use-headroom/use-headroom.mjs.map +1 -1
  35. package/esm/use-hotkeys/use-hotkeys.mjs +15 -15
  36. package/esm/use-hotkeys/use-hotkeys.mjs.map +1 -1
  37. package/esm/use-mask/use-mask.mjs +577 -0
  38. package/esm/use-mask/use-mask.mjs.map +1 -0
  39. package/esm/use-page-leave/use-page-leave.mjs +4 -3
  40. package/esm/use-page-leave/use-page-leave.mjs.map +1 -1
  41. package/esm/use-roving-index/use-roving-index.mjs +268 -0
  42. package/esm/use-roving-index/use-roving-index.mjs.map +1 -0
  43. package/esm/use-scroll-direction/use-scroll-direction.mjs +37 -0
  44. package/esm/use-scroll-direction/use-scroll-direction.mjs.map +1 -0
  45. package/esm/use-text-selection/use-text-selection.mjs +3 -3
  46. package/esm/use-text-selection/use-text-selection.mjs.map +1 -1
  47. package/esm/use-window-event/use-window-event.mjs +5 -4
  48. package/esm/use-window-event/use-window-event.mjs.map +1 -1
  49. package/lib/index.d.mts +2 -0
  50. package/lib/index.d.ts +2 -0
  51. package/lib/use-drag/use-drag.d.ts +60 -0
  52. package/lib/use-headroom/use-headroom.d.ts +11 -2
  53. package/lib/use-mask/use-mask.d.ts +60 -0
  54. package/lib/use-roving-index/use-roving-index.d.ts +49 -0
  55. package/lib/use-scroll-direction/use-scroll-direction.d.ts +2 -0
  56. package/package.json +2 -2
@@ -1,5 +1,5 @@
1
1
  'use client';
2
- import { useEffect } from 'react';
2
+ import { useEffectEvent, useEffect } from 'react';
3
3
  import { getHotkeyMatcher } from './parse-hotkey.mjs';
4
4
  export { getHotkeyHandler } from './parse-hotkey.mjs';
5
5
 
@@ -13,22 +13,22 @@ function shouldFireEvent(event, tagsToIgnore, triggerOnContentEditable = false)
13
13
  return true;
14
14
  }
15
15
  function useHotkeys(hotkeys, tagsToIgnore = ["INPUT", "TEXTAREA", "SELECT"], triggerOnContentEditable = false) {
16
- useEffect(() => {
17
- const keydownListener = (event) => {
18
- hotkeys.forEach(
19
- ([hotkey, handler, options = { preventDefault: true, usePhysicalKeys: false }]) => {
20
- if (getHotkeyMatcher(hotkey, options.usePhysicalKeys)(event) && shouldFireEvent(event, tagsToIgnore, triggerOnContentEditable)) {
21
- if (options.preventDefault) {
22
- event.preventDefault();
23
- }
24
- handler(event);
16
+ const handleKeydown = useEffectEvent((event) => {
17
+ hotkeys.forEach(
18
+ ([hotkey, handler, options = { preventDefault: true, usePhysicalKeys: false }]) => {
19
+ if (getHotkeyMatcher(hotkey, options.usePhysicalKeys)(event) && shouldFireEvent(event, tagsToIgnore, triggerOnContentEditable)) {
20
+ if (options.preventDefault) {
21
+ event.preventDefault();
25
22
  }
23
+ handler(event);
26
24
  }
27
- );
28
- };
29
- document.documentElement.addEventListener("keydown", keydownListener);
30
- return () => document.documentElement.removeEventListener("keydown", keydownListener);
31
- }, [hotkeys]);
25
+ }
26
+ );
27
+ });
28
+ useEffect(() => {
29
+ document.documentElement.addEventListener("keydown", handleKeydown);
30
+ return () => document.documentElement.removeEventListener("keydown", handleKeydown);
31
+ }, []);
32
32
  }
33
33
 
34
34
  export { useHotkeys };
@@ -1 +1 @@
1
- {"version":3,"file":"use-hotkeys.mjs","sources":["../../src/use-hotkeys/use-hotkeys.ts"],"sourcesContent":["import { useEffect } from 'react';\nimport { getHotkeyHandler, getHotkeyMatcher, HotkeyItemOptions } from './parse-hotkey';\n\nexport type { HotkeyItemOptions };\nexport { getHotkeyHandler };\n\nexport type HotkeyItem = [string, (event: KeyboardEvent) => void, HotkeyItemOptions?];\n\nfunction shouldFireEvent(\n event: KeyboardEvent,\n tagsToIgnore: string[],\n triggerOnContentEditable = false\n) {\n if (event.target instanceof HTMLElement) {\n if (triggerOnContentEditable) {\n return !tagsToIgnore.includes(event.target.tagName);\n }\n\n return !event.target.isContentEditable && !tagsToIgnore.includes(event.target.tagName);\n }\n\n return true;\n}\n\nexport function useHotkeys(\n hotkeys: HotkeyItem[],\n tagsToIgnore: string[] = ['INPUT', 'TEXTAREA', 'SELECT'],\n triggerOnContentEditable = false\n) {\n useEffect(() => {\n const keydownListener = (event: KeyboardEvent) => {\n hotkeys.forEach(\n ([hotkey, handler, options = { preventDefault: true, usePhysicalKeys: false }]) => {\n if (\n getHotkeyMatcher(hotkey, options.usePhysicalKeys)(event) &&\n shouldFireEvent(event, tagsToIgnore, triggerOnContentEditable)\n ) {\n if (options.preventDefault) {\n event.preventDefault();\n }\n\n handler(event);\n }\n }\n );\n };\n\n document.documentElement.addEventListener('keydown', keydownListener);\n return () => document.documentElement.removeEventListener('keydown', keydownListener);\n }, [hotkeys]);\n}\n\nexport namespace useHotkeys {\n export type Hotkey = HotkeyItem;\n}\n"],"names":[],"mappings":";;;;;AAQA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAS,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CACP,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CACA,YAAA,CAAA,CACA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAA2B,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAC3B,CAAA;AACA,CAAA,CAAA,IAAI,CAAA,CAAA,CAAA,CAAA,CAAA,CAAM,CAAA,CAAA,CAAA,CAAA,CAAA,aAAkB,WAAA,CAAA,CAAa,CAAA;AACvC,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAI,wBAAA,CAAA,CAA0B,CAAA;AAC5B,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAO,CAAC,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAa,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAS,CAAA,CAAA,CAAA,CAAA,CAAA,CAAM,CAAA,CAAA,CAAA,CAAA,CAAA,EAAO,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAO,CAAA,CAAA;AAAA,CAAA,CAAA,CAAA,CACpD,CAAA;AAEA,CAAA,CAAA,CAAA,CAAA,OAAO,CAAC,CAAA,CAAA,CAAA,CAAA,EAAM,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAO,iBAAA,CAAA,CAAA,CAAA,CAAqB,CAAC,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAa,QAAA,CAAS,CAAA,CAAA,CAAA,CAAA,CAAA,CAAM,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAO,OAAO,CAAA,CAAA;AAAA,CAAA,CACvF,CAAA;AAEA,CAAA,CAAA,OAAO,CAAA,CAAA,CAAA,CAAA,CAAA;AACT,CAAA;AAEO,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAS,UAAA,CACd,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,GACA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,GAAyB,CAAC,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,GAAS,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,EAAY,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAQ,CAAA,EACvD,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAA2B,KAAA,CAAA,CAC3B,CAAA;AACA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAU,CAAA,CAAA,CAAA,CAAA,CAAA,CAAM,CAAA;AACd,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAM,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAkB,CAAC,KAAA,CAAA,CAAA,CAAA,CAAA,CAAyB,CAAA;AAChD,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAQ,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA;AAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CACN,CAAC,CAAC,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,EAAQ,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAS,OAAA,CAAA,CAAA,CAAU,CAAA,CAAE,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAgB,IAAA,CAAA,CAAM,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,EAAiB,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAO,CAAA,CAAA,CAAA,CAAA,CAAA,CAAM,CAAA;AACjF,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CACE,gBAAA,CAAiB,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,EAAQ,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAQ,eAAe,CAAA,CAAE,KAAK,CAAA,CAAA,CAAA,CAAA,CACvD,eAAA,CAAgB,CAAA,CAAA,CAAA,CAAA,CAAA,EAAO,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAc,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAwB,CAAA,CAAA,CAC7D,CAAA;AACA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAI,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,EAAQ,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAgB,CAAA;AAC1B,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAM,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAe,CAAA;AAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CACvB,CAAA;AAEA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAQ,CAAA,CAAA,CAAA,CAAA,CAAK,CAAA,CAAA;AAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CACf,CAAA;AAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CACF,CAAA;AAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CACF,CAAA;AAAA,CAAA,CAAA,CAAA,CACF,CAAA,CAAA;AAEA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAS,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAgB,gBAAA,CAAiB,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAW,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAe,CAAA,CAAA;AACpE,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAO,CAAA,CAAA,CAAA,CAAA,CAAA,CAAM,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAS,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAgB,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAoB,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,GAAW,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAe,CAAA,CAAA;AAAA,CAAA,CACtF,CAAA,CAAA,CAAG,CAAC,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAO,CAAC,CAAA,CAAA;AACd,CAAA;;"}
1
+ {"version":3,"file":"use-hotkeys.mjs","sources":["../../src/use-hotkeys/use-hotkeys.ts"],"sourcesContent":["import { useEffect, useEffectEvent } from 'react';\nimport { getHotkeyHandler, getHotkeyMatcher, HotkeyItemOptions } from './parse-hotkey';\n\nexport type { HotkeyItemOptions };\nexport { getHotkeyHandler };\n\nexport type HotkeyItem = [string, (event: KeyboardEvent) => void, HotkeyItemOptions?];\n\nfunction shouldFireEvent(\n event: KeyboardEvent,\n tagsToIgnore: string[],\n triggerOnContentEditable = false\n) {\n if (event.target instanceof HTMLElement) {\n if (triggerOnContentEditable) {\n return !tagsToIgnore.includes(event.target.tagName);\n }\n\n return !event.target.isContentEditable && !tagsToIgnore.includes(event.target.tagName);\n }\n\n return true;\n}\n\nexport function useHotkeys(\n hotkeys: HotkeyItem[],\n tagsToIgnore: string[] = ['INPUT', 'TEXTAREA', 'SELECT'],\n triggerOnContentEditable = false\n) {\n const handleKeydown = useEffectEvent((event: KeyboardEvent) => {\n hotkeys.forEach(\n ([hotkey, handler, options = { preventDefault: true, usePhysicalKeys: false }]) => {\n if (\n getHotkeyMatcher(hotkey, options.usePhysicalKeys)(event) &&\n shouldFireEvent(event, tagsToIgnore, triggerOnContentEditable)\n ) {\n if (options.preventDefault) {\n event.preventDefault();\n }\n\n handler(event);\n }\n }\n );\n });\n\n useEffect(() => {\n document.documentElement.addEventListener('keydown', handleKeydown);\n return () => document.documentElement.removeEventListener('keydown', handleKeydown);\n }, []);\n}\n\nexport namespace useHotkeys {\n export type Hotkey = HotkeyItem;\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,577 @@
1
+ 'use client';
2
+ import { useRef, useState, useCallback, useEffect } from 'react';
3
+
4
+ const DEFAULT_TOKENS = {
5
+ "9": /[0-9]/,
6
+ a: /[A-Za-z]/,
7
+ A: /[A-Z]/,
8
+ "*": /[A-Za-z0-9]/,
9
+ "#": /[-+0-9]/
10
+ };
11
+ function parseMask(mask, tokens) {
12
+ if (Array.isArray(mask)) {
13
+ return mask.map((item) => {
14
+ if (item instanceof RegExp) {
15
+ return { type: "token", char: "_", pattern: item };
16
+ }
17
+ return { type: "literal", char: item };
18
+ });
19
+ }
20
+ const slots = [];
21
+ let optional = false;
22
+ for (let i = 0; i < mask.length; i++) {
23
+ const char = mask[i];
24
+ if (char === "\\" && i + 1 < mask.length) {
25
+ i++;
26
+ slots.push({ type: "literal", char: mask[i] });
27
+ continue;
28
+ }
29
+ if (char === "?") {
30
+ optional = true;
31
+ continue;
32
+ }
33
+ if (tokens[char]) {
34
+ slots.push({ type: "token", char, pattern: tokens[char], optional });
35
+ } else {
36
+ slots.push({ type: "literal", char, optional });
37
+ }
38
+ }
39
+ return slots;
40
+ }
41
+ function getSlotChar(slotCharOption, index) {
42
+ if (slotCharOption === null || slotCharOption === "" || slotCharOption === void 0) {
43
+ return "";
44
+ }
45
+ if (slotCharOption.length > 1) {
46
+ return slotCharOption[index] || "_";
47
+ }
48
+ return slotCharOption;
49
+ }
50
+ function applyMaskToRaw(raw, slots, _slotCharOption, transform) {
51
+ let result = "";
52
+ let rawIndex = 0;
53
+ let slotIndex = 0;
54
+ for (slotIndex = 0; slotIndex < slots.length; slotIndex++) {
55
+ const slot = slots[slotIndex];
56
+ if (slot.type === "literal") {
57
+ result += slot.char;
58
+ } else if (rawIndex < raw.length) {
59
+ const ch = transform ? transform(raw[rawIndex]) : raw[rawIndex];
60
+ if (slot.pattern && slot.pattern.test(ch)) {
61
+ result += ch;
62
+ rawIndex++;
63
+ } else {
64
+ rawIndex++;
65
+ slotIndex--;
66
+ }
67
+ } else {
68
+ break;
69
+ }
70
+ }
71
+ return result;
72
+ }
73
+ function buildDisplayValue(value, slots, slotCharOption, showSlots) {
74
+ if (!showSlots) {
75
+ return value;
76
+ }
77
+ let display = value;
78
+ for (let i = value.length; i < slots.length; i++) {
79
+ const slot = slots[i];
80
+ if (slot.type === "literal") {
81
+ display += slot.char;
82
+ } else {
83
+ const sc = getSlotChar(slotCharOption, i);
84
+ if (!sc) {
85
+ break;
86
+ }
87
+ display += sc;
88
+ }
89
+ }
90
+ return display;
91
+ }
92
+ function extractRaw(masked, slots) {
93
+ let raw = "";
94
+ for (let i = 0; i < masked.length && i < slots.length; i++) {
95
+ if (slots[i].type === "token") {
96
+ raw += masked[i];
97
+ }
98
+ }
99
+ return raw;
100
+ }
101
+ function checkComplete(masked, slots) {
102
+ for (let i = 0; i < slots.length; i++) {
103
+ if (slots[i].type === "token" && !slots[i].optional) {
104
+ if (i >= masked.length) {
105
+ return false;
106
+ }
107
+ if (!slots[i].pattern.test(masked[i])) {
108
+ return false;
109
+ }
110
+ }
111
+ }
112
+ return true;
113
+ }
114
+ function findNextTokenIndex(slots, from) {
115
+ for (let i = from; i < slots.length; i++) {
116
+ if (slots[i].type === "token") {
117
+ return i;
118
+ }
119
+ }
120
+ return slots.length;
121
+ }
122
+ function findPrevTokenIndex(slots, from) {
123
+ for (let i = from; i >= 0; i--) {
124
+ if (slots[i].type === "token") {
125
+ return i;
126
+ }
127
+ }
128
+ return -1;
129
+ }
130
+ function processInput(inputValue, slots, _slotCharOption) {
131
+ let result = "";
132
+ let inputIndex = 0;
133
+ for (let slotIndex = 0; slotIndex < slots.length && inputIndex <= inputValue.length; slotIndex++) {
134
+ const slot = slots[slotIndex];
135
+ if (slot.type === "literal") {
136
+ result += slot.char;
137
+ if (inputIndex < inputValue.length && inputValue[inputIndex] === slot.char) {
138
+ inputIndex++;
139
+ }
140
+ continue;
141
+ }
142
+ if (inputIndex >= inputValue.length) {
143
+ break;
144
+ }
145
+ while (inputIndex < inputValue.length) {
146
+ const ch = inputValue[inputIndex];
147
+ inputIndex++;
148
+ if (slot.pattern.test(ch)) {
149
+ result += ch;
150
+ break;
151
+ }
152
+ }
153
+ if (result.length <= slotIndex) {
154
+ break;
155
+ }
156
+ }
157
+ return result;
158
+ }
159
+ function getResolvedOptions(options, rawValue) {
160
+ const tokens = { ...DEFAULT_TOKENS, ...options.tokens };
161
+ let mask = options.mask;
162
+ let slotChar = options.slotChar === void 0 ? "_" : options.slotChar;
163
+ let separate = options.separate ?? false;
164
+ if (options.modify) {
165
+ const overrides = options.modify(rawValue);
166
+ if (overrides) {
167
+ if (overrides.mask !== void 0) {
168
+ mask = overrides.mask;
169
+ }
170
+ if (overrides.tokens !== void 0) {
171
+ Object.assign(tokens, overrides.tokens);
172
+ }
173
+ if (overrides.slotChar !== void 0) {
174
+ slotChar = overrides.slotChar;
175
+ }
176
+ if (overrides.separate !== void 0) {
177
+ separate = overrides.separate;
178
+ }
179
+ }
180
+ }
181
+ const slots = parseMask(mask, tokens);
182
+ return { slots, slotChar, separate, tokens, transform: options.transform };
183
+ }
184
+ function formatMask(raw, options) {
185
+ const { slots, slotChar, transform } = getResolvedOptions(options, raw);
186
+ return applyMaskToRaw(raw, slots, slotChar, transform);
187
+ }
188
+ function unformatMask(masked, options) {
189
+ const { slots } = getResolvedOptions(options, "");
190
+ return extractRaw(masked, slots);
191
+ }
192
+ function isMaskComplete(masked, options) {
193
+ const { slots } = getResolvedOptions(options, "");
194
+ return checkComplete(masked, slots);
195
+ }
196
+ function generatePattern(mode, options) {
197
+ const { slots } = getResolvedOptions(options, "");
198
+ let pattern = "";
199
+ for (const slot of slots) {
200
+ if (slot.type === "literal") {
201
+ pattern += slot.char.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
202
+ } else {
203
+ const src = slot.pattern.source;
204
+ if (mode === "full-inexact") {
205
+ pattern += slot.optional ? `${src}?` : src;
206
+ } else {
207
+ pattern += slot.optional ? `(${src})?` : `(${src})`;
208
+ }
209
+ }
210
+ }
211
+ return pattern;
212
+ }
213
+ function useMask(options) {
214
+ const optionsRef = useRef(options);
215
+ optionsRef.current = options;
216
+ const inputRef = useRef(null);
217
+ const [maskedValue, setMaskedValue] = useState("");
218
+ const [rawValue, setRawValue] = useState("");
219
+ const processedRef = useRef("");
220
+ const wasCompleteRef = useRef(false);
221
+ const isFocusedRef = useRef(false);
222
+ const getOptions = useCallback(() => {
223
+ const opts = optionsRef.current;
224
+ return getResolvedOptions(opts, rawValue);
225
+ }, [rawValue]);
226
+ const updateValue = useCallback(
227
+ (newMasked, cursorPos) => {
228
+ const opts = optionsRef.current;
229
+ const { slots } = getResolvedOptions(
230
+ opts,
231
+ extractRaw(newMasked, getResolvedOptions(opts, "").slots)
232
+ );
233
+ const raw = extractRaw(newMasked, slots);
234
+ const { slots: resolvedSlots, slotChar } = getResolvedOptions(opts, raw);
235
+ const reprocessed = processInput(newMasked, resolvedSlots);
236
+ const newRaw = extractRaw(reprocessed, resolvedSlots);
237
+ const showSlots = opts.alwaysShowMask || isFocusedRef.current;
238
+ const showOnFocus = opts.showMaskOnFocus !== false;
239
+ const shouldShowSlots = showSlots && (showOnFocus || reprocessed.length > 0);
240
+ const displayValue = buildDisplayValue(reprocessed, resolvedSlots, slotChar, shouldShowSlots);
241
+ processedRef.current = reprocessed;
242
+ setMaskedValue(displayValue);
243
+ setRawValue(newRaw);
244
+ if (inputRef.current) {
245
+ inputRef.current.value = displayValue;
246
+ if (cursorPos !== void 0 && document.activeElement === inputRef.current) {
247
+ const pos = Math.min(cursorPos, reprocessed.length);
248
+ inputRef.current.setSelectionRange(pos, pos);
249
+ }
250
+ }
251
+ if (opts.onChangeRaw) {
252
+ opts.onChangeRaw(newRaw, displayValue);
253
+ }
254
+ const complete = checkComplete(reprocessed, resolvedSlots);
255
+ if (complete && !wasCompleteRef.current && opts.onComplete) {
256
+ opts.onComplete(displayValue, newRaw);
257
+ }
258
+ wasCompleteRef.current = complete;
259
+ return { displayValue, newRaw, reprocessed, resolvedSlots };
260
+ },
261
+ [getOptions]
262
+ );
263
+ const handleInput = useCallback(
264
+ (e) => {
265
+ const input = e.target;
266
+ const opts = optionsRef.current;
267
+ const { slots: resolvedSlots, slotChar, transform } = getResolvedOptions(opts, "");
268
+ const raw = extractRaw(input.value, resolvedSlots);
269
+ const reformatted = applyMaskToRaw(raw, resolvedSlots, slotChar, transform);
270
+ updateValue(reformatted, reformatted.length);
271
+ },
272
+ [updateValue]
273
+ );
274
+ const clampCursorToProcessed = useCallback((input) => {
275
+ const opts = optionsRef.current;
276
+ const { slots } = getResolvedOptions(opts, "");
277
+ const processed = processedRef.current;
278
+ const cursorPos = input.selectionStart ?? 0;
279
+ const maxPos = processed.length > 0 ? findNextEditablePosition(processed.length, slots, processed) : findNextTokenIndex(slots, 0);
280
+ if (cursorPos > maxPos) {
281
+ input.setSelectionRange(maxPos, maxPos);
282
+ }
283
+ }, []);
284
+ const handleFocus = useCallback(() => {
285
+ isFocusedRef.current = true;
286
+ const opts = optionsRef.current;
287
+ const input = inputRef.current;
288
+ if (!input) {
289
+ return;
290
+ }
291
+ const { slots, slotChar } = getResolvedOptions(opts, "");
292
+ const showOnFocus = opts.showMaskOnFocus !== false;
293
+ const processed = processedRef.current;
294
+ if (showOnFocus || opts.alwaysShowMask) {
295
+ const display = buildDisplayValue(processed, slots, slotChar, true);
296
+ input.value = display;
297
+ setMaskedValue(display);
298
+ }
299
+ requestAnimationFrame(() => {
300
+ if (input === document.activeElement) {
301
+ clampCursorToProcessed(input);
302
+ }
303
+ });
304
+ }, [clampCursorToProcessed]);
305
+ const handleMouseUp = useCallback(() => {
306
+ const input = inputRef.current;
307
+ if (!input || input !== document.activeElement) {
308
+ return;
309
+ }
310
+ clampCursorToProcessed(input);
311
+ }, [clampCursorToProcessed]);
312
+ const handleBlur = useCallback(() => {
313
+ isFocusedRef.current = false;
314
+ const opts = optionsRef.current;
315
+ const input = inputRef.current;
316
+ if (!input) {
317
+ return;
318
+ }
319
+ const { slots, slotChar } = getResolvedOptions(opts, rawValue);
320
+ const processed = processInput(input.value, slots);
321
+ const complete = checkComplete(processed, slots);
322
+ if (opts.autoClear && !complete && processed.length > 0) {
323
+ input.value = "";
324
+ processedRef.current = "";
325
+ setMaskedValue("");
326
+ setRawValue("");
327
+ wasCompleteRef.current = false;
328
+ if (opts.onChangeRaw) {
329
+ opts.onChangeRaw("", "");
330
+ }
331
+ if (opts.alwaysShowMask) {
332
+ const emptyDisplay = buildDisplayValue("", slots, slotChar, true);
333
+ input.value = emptyDisplay;
334
+ setMaskedValue(emptyDisplay);
335
+ }
336
+ return;
337
+ }
338
+ if (!opts.alwaysShowMask && !complete) {
339
+ const display = buildDisplayValue(processed, slots, slotChar, false);
340
+ input.value = display;
341
+ setMaskedValue(display);
342
+ }
343
+ }, [rawValue]);
344
+ const handleKeyDown = useCallback(
345
+ (e) => {
346
+ const input = e.target;
347
+ const opts = optionsRef.current;
348
+ const { slots, slotChar, transform } = getResolvedOptions(opts, rawValue);
349
+ const start = input.selectionStart ?? 0;
350
+ const end = input.selectionEnd ?? 0;
351
+ const processed = processedRef.current;
352
+ if (e.key === "Backspace") {
353
+ e.preventDefault();
354
+ if (e.metaKey || e.ctrlKey && !e.altKey) {
355
+ const clampedStart = Math.min(start, processed.length);
356
+ const afterRaw2 = extractRaw(processed.slice(clampedStart), slots.slice(clampedStart));
357
+ const newValue2 = applyMaskToRaw(afterRaw2, slots, slotChar, transform);
358
+ updateValue(newValue2, 0);
359
+ return;
360
+ }
361
+ if (start !== end) {
362
+ const clampedEnd = Math.min(end, processed.length);
363
+ const before = processed.slice(0, start);
364
+ const afterRaw2 = extractRaw(processed.slice(clampedEnd), slots.slice(clampedEnd));
365
+ const newValue2 = applyMaskToRaw(
366
+ extractRaw(before, slots) + afterRaw2,
367
+ slots,
368
+ slotChar,
369
+ transform
370
+ );
371
+ updateValue(newValue2, start);
372
+ return;
373
+ }
374
+ if (start === 0) {
375
+ return;
376
+ }
377
+ let deletePos = start - 1;
378
+ while (deletePos >= 0 && slots[deletePos] && slots[deletePos].type === "literal") {
379
+ deletePos--;
380
+ }
381
+ if (deletePos < 0) {
382
+ return;
383
+ }
384
+ const beforeRaw = extractRaw(processed.slice(0, deletePos), slots.slice(0, deletePos));
385
+ const afterRaw = extractRaw(processed.slice(deletePos + 1), slots.slice(deletePos + 1));
386
+ const newValue = applyMaskToRaw(beforeRaw + afterRaw, slots, slotChar, transform);
387
+ updateValue(newValue, deletePos);
388
+ } else if (e.key === "Delete") {
389
+ e.preventDefault();
390
+ if (start !== end) {
391
+ const clampedEnd = Math.min(end, processed.length);
392
+ const before = processed.slice(0, start);
393
+ const afterRaw2 = extractRaw(processed.slice(clampedEnd), slots.slice(clampedEnd));
394
+ const newValue2 = applyMaskToRaw(
395
+ extractRaw(before, slots) + afterRaw2,
396
+ slots,
397
+ slotChar,
398
+ transform
399
+ );
400
+ updateValue(newValue2, start);
401
+ return;
402
+ }
403
+ let deletePos = start;
404
+ while (deletePos < slots.length && slots[deletePos] && slots[deletePos].type === "literal") {
405
+ deletePos++;
406
+ }
407
+ if (deletePos >= processed.length) {
408
+ return;
409
+ }
410
+ const beforeRaw = extractRaw(processed.slice(0, start), slots.slice(0, start));
411
+ const afterRaw = extractRaw(processed.slice(deletePos + 1), slots.slice(deletePos + 1));
412
+ const newValue = applyMaskToRaw(beforeRaw + afterRaw, slots, slotChar, transform);
413
+ updateValue(newValue, start);
414
+ } else if (e.key === "ArrowRight" && !e.shiftKey) {
415
+ const nextPos = findNextEditablePosition(start + 1, slots, input.value);
416
+ if (nextPos !== start + 1) {
417
+ e.preventDefault();
418
+ input.setSelectionRange(nextPos, nextPos);
419
+ }
420
+ } else if (e.key === "ArrowLeft" && !e.shiftKey) {
421
+ if (start > 0) {
422
+ const prevToken = findPrevTokenIndex(slots, start - 1);
423
+ if (prevToken >= 0 && prevToken !== start - 1) {
424
+ e.preventDefault();
425
+ input.setSelectionRange(prevToken + 1, prevToken + 1);
426
+ }
427
+ }
428
+ } else if (e.key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey) {
429
+ e.preventDefault();
430
+ let insertPos = Math.min(start, processed.length);
431
+ while (insertPos < slots.length && slots[insertPos] && slots[insertPos].type === "literal") {
432
+ insertPos++;
433
+ }
434
+ if (insertPos >= slots.length) {
435
+ return;
436
+ }
437
+ const slot = slots[insertPos];
438
+ const ch = transform ? transform(e.key) : e.key;
439
+ if (!slot.pattern.test(ch)) {
440
+ return;
441
+ }
442
+ const beforeRaw = extractRaw(processed.slice(0, insertPos), slots.slice(0, insertPos));
443
+ const afterRaw = start < end ? extractRaw(
444
+ processed.slice(Math.min(end, processed.length)),
445
+ slots.slice(Math.min(end, processed.length))
446
+ ) : extractRaw(processed.slice(insertPos), slots.slice(insertPos));
447
+ const newValue = applyMaskToRaw(beforeRaw + ch + afterRaw, slots, slotChar, transform);
448
+ const newCursorPos = findNextEditablePosition(insertPos + 1, slots, newValue);
449
+ updateValue(newValue, newCursorPos);
450
+ }
451
+ },
452
+ [rawValue, updateValue]
453
+ );
454
+ const handlePaste = useCallback(
455
+ (e) => {
456
+ e.preventDefault();
457
+ const input = e.target;
458
+ const opts = optionsRef.current;
459
+ const pastedText = e.clipboardData?.getData("text") ?? "";
460
+ const start = input.selectionStart ?? 0;
461
+ const end = input.selectionEnd ?? 0;
462
+ const processed = processedRef.current;
463
+ const { slots, slotChar, transform } = getResolvedOptions(opts, "");
464
+ const clampedEnd = Math.min(end, processed.length);
465
+ const beforeRaw = extractRaw(processed.slice(0, start), slots.slice(0, start));
466
+ const afterRaw = extractRaw(processed.slice(clampedEnd), slots.slice(clampedEnd));
467
+ const newValue = applyMaskToRaw(
468
+ beforeRaw + pastedText + afterRaw,
469
+ slots,
470
+ slotChar,
471
+ transform
472
+ );
473
+ const { reprocessed } = updateValue(newValue);
474
+ const pasteEndPos = Math.min((reprocessed || newValue).length, slots.length);
475
+ if (input === document.activeElement) {
476
+ input.setSelectionRange(pasteEndPos, pasteEndPos);
477
+ }
478
+ },
479
+ [updateValue]
480
+ );
481
+ const setAriaAttributes = useCallback((input) => {
482
+ const opts = optionsRef.current;
483
+ if (opts.invalid) {
484
+ input.setAttribute("aria-invalid", "true");
485
+ } else {
486
+ input.removeAttribute("aria-invalid");
487
+ }
488
+ }, []);
489
+ const refCallback = useCallback(
490
+ (node) => {
491
+ const prevInput = inputRef.current;
492
+ if (prevInput) {
493
+ prevInput.removeEventListener("input", handleInput);
494
+ prevInput.removeEventListener("focus", handleFocus);
495
+ prevInput.removeEventListener("blur", handleBlur);
496
+ prevInput.removeEventListener("mouseup", handleMouseUp);
497
+ prevInput.removeEventListener("keydown", handleKeyDown);
498
+ prevInput.removeEventListener("paste", handlePaste);
499
+ }
500
+ inputRef.current = node;
501
+ if (node) {
502
+ node.addEventListener("input", handleInput);
503
+ node.addEventListener("focus", handleFocus);
504
+ node.addEventListener("blur", handleBlur);
505
+ node.addEventListener("mouseup", handleMouseUp);
506
+ node.addEventListener("keydown", handleKeyDown);
507
+ node.addEventListener("paste", handlePaste);
508
+ setAriaAttributes(node);
509
+ if (options.alwaysShowMask && !node.value) {
510
+ const { slots, slotChar } = getResolvedOptions(options, "");
511
+ const display = buildDisplayValue("", slots, slotChar, true);
512
+ node.value = display;
513
+ setMaskedValue(display);
514
+ }
515
+ }
516
+ },
517
+ [
518
+ handleInput,
519
+ handleFocus,
520
+ handleBlur,
521
+ handleMouseUp,
522
+ handleKeyDown,
523
+ handlePaste,
524
+ setAriaAttributes,
525
+ options
526
+ ]
527
+ );
528
+ useEffect(() => {
529
+ const input = inputRef.current;
530
+ if (!input) {
531
+ return;
532
+ }
533
+ setAriaAttributes(input);
534
+ }, [options.invalid, setAriaAttributes]);
535
+ const isComplete = (() => {
536
+ const { slots } = getOptions();
537
+ return checkComplete(processedRef.current, slots);
538
+ })();
539
+ const reset = useCallback(() => {
540
+ const opts = optionsRef.current;
541
+ const input = inputRef.current;
542
+ processedRef.current = "";
543
+ setMaskedValue("");
544
+ setRawValue("");
545
+ wasCompleteRef.current = false;
546
+ if (input) {
547
+ if (opts.alwaysShowMask) {
548
+ const { slots, slotChar } = getResolvedOptions(opts, "");
549
+ const display = buildDisplayValue("", slots, slotChar, true);
550
+ input.value = display;
551
+ setMaskedValue(display);
552
+ } else {
553
+ input.value = "";
554
+ }
555
+ }
556
+ if (opts.onChangeRaw) {
557
+ opts.onChangeRaw("", "");
558
+ }
559
+ }, []);
560
+ return {
561
+ ref: refCallback,
562
+ value: maskedValue,
563
+ rawValue,
564
+ isComplete,
565
+ reset
566
+ };
567
+ }
568
+ function findNextEditablePosition(from, slots, value) {
569
+ let pos = from;
570
+ while (pos < slots.length && pos < value.length && slots[pos] && slots[pos].type === "literal") {
571
+ pos++;
572
+ }
573
+ return pos;
574
+ }
575
+
576
+ export { formatMask, generatePattern, isMaskComplete, unformatMask, useMask };
577
+ //# sourceMappingURL=use-mask.mjs.map