@servicetitan/anvil2-ext-common 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # @servicetitan/anvil2-ext-common
2
2
 
3
+ ## 0.3.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#2047](https://github.com/servicetitan/hammer/pull/2047) [`0df7ba2`](https://github.com/servicetitan/hammer/commit/0df7ba2e66f47059271e5ba815a9d44efcbd5842) Thanks [@copilot-swe-agent](https://github.com/apps/copilot-swe-agent)! - [useInputGuards] Add `CommitTrigger` enum and `triggers` config option to control which user actions fire a commit; remove `onClear` from returned `inputProps` (clear by setting the controlled `value` to `""`, e.g. in response to an input change that produces an empty value)
8
+
9
+ ### Patch Changes
10
+
11
+ - [#2060](https://github.com/servicetitan/hammer/pull/2060) [`8e4cea6`](https://github.com/servicetitan/hammer/commit/8e4cea6a5fdc178edae27518450f1204464831eb) Thanks [@rgdelato](https://github.com/rgdelato)! - [Illustrations] Add new `@servicetitan/anvil2-illustrations` package
12
+
13
+ - Updated dependencies [[`8e4cea6`](https://github.com/servicetitan/hammer/commit/8e4cea6a5fdc178edae27518450f1204464831eb), [`656c287`](https://github.com/servicetitan/hammer/commit/656c2870857bb4d88939308e5b567cb24ca8496b), [`8e4cea6`](https://github.com/servicetitan/hammer/commit/8e4cea6a5fdc178edae27518450f1204464831eb), [`4d21c97`](https://github.com/servicetitan/hammer/commit/4d21c97eb25b648cd14909ee3980944515739150), [`4d21c97`](https://github.com/servicetitan/hammer/commit/4d21c97eb25b648cd14909ee3980944515739150), [`f64e906`](https://github.com/servicetitan/hammer/commit/f64e906c441cb35cd37848712970e189674559b3)]:
14
+ - @servicetitan/anvil2@2.3.0
15
+
16
+ ## 0.2.1
17
+
18
+ ### Patch Changes
19
+
20
+ - Updated dependencies [[`7decf90`](https://github.com/servicetitan/hammer/commit/7decf9025a64853d5e2c56bf85ac65aae65df9a8), [`22d8c3e`](https://github.com/servicetitan/hammer/commit/22d8c3ea2f9b92beb63a99df60401c7fcdef8e6f), [`3da2bf9`](https://github.com/servicetitan/hammer/commit/3da2bf993fa62da2866a5da7976cee693e604786), [`c5dab06`](https://github.com/servicetitan/hammer/commit/c5dab06be72b5d6306b7bbac4e3b431f5f64b9b0), [`79ab1db`](https://github.com/servicetitan/hammer/commit/79ab1db3c9af5e3a6f7ad39ee999bdfbcb885f57), [`24d0da0`](https://github.com/servicetitan/hammer/commit/24d0da0d8f3fdfee60bb9315ae8c58df4270a9c4), [`e0ca085`](https://github.com/servicetitan/hammer/commit/e0ca0858a7b0b42dd4c8ffaea6a8a2da6c10467e)]:
21
+ - @servicetitan/anvil2@2.2.0
22
+
3
23
  ## 0.2.0
4
24
 
5
25
  ### Minor Changes
@@ -1 +1 @@
1
- export { useInputGuards, useInputGuards as default, type UseInputGuardsConfig, type UseInputGuardsProps, } from './useInputGuards';
1
+ export { useInputGuards, useInputGuards as default, CommitTrigger, type UseInputGuardsConfig, type UseInputGuardsProps, } from './useInputGuards';
@@ -1,29 +1,42 @@
1
1
  import { ChangeEventHandler, ClipboardEventHandler, KeyboardEventHandler } from 'react';
2
+ export declare enum CommitTrigger {
3
+ Typing = "typing",
4
+ Enter = "enter",
5
+ Paste = "paste",
6
+ Clear = "clear"
7
+ }
2
8
  export interface UseInputGuardsProps {
3
9
  value: string;
4
10
  onChange: ChangeEventHandler<HTMLInputElement>;
5
11
  onPaste: ClipboardEventHandler<HTMLInputElement>;
6
12
  onKeyDown: KeyboardEventHandler<HTMLInputElement>;
7
- onClear: () => void;
8
13
  }
9
14
  export interface UseInputGuardsConfig {
10
15
  value: string;
11
16
  delay: number;
12
17
  onCommit: (value: string) => void;
18
+ /**
19
+ * Which user actions trigger a commit. Defaults to all triggers when omitted or empty.
20
+ * Omit `CommitTrigger.Typing` to disable the debounce auto-commit after inactivity
21
+ * while still allowing Enter, paste, and clear to commit.
22
+ */
23
+ triggers?: [CommitTrigger, ...CommitTrigger[]];
13
24
  }
14
25
  /**
15
26
  * Manages a debounced text input with rate-limited commits.
16
27
  *
17
- * - Typing: visible value updates immediately; `onCommit` fires after `delay` ms of inactivity
18
- * - Paste / Enter: commits immediately via a commit guard (rate-limited to one per `delay` ms)
28
+ * - Typing: visible value updates immediately; when `CommitTrigger.Typing` is active, `onCommit` fires after `delay` ms of inactivity
29
+ * - Paste: when `CommitTrigger.Paste` is active, commits immediately via a commit guard (rate-limited to one per `delay` ms)
30
+ * - Enter: when `CommitTrigger.Enter` is active, commits immediately via a commit guard (rate-limited to one per `delay` ms)
19
31
  * - Repeated keys: held-key keydown events suppressed with `preventDefault()`
20
- * - Clear: commits `''` immediately and deactivates the guard
32
+ * - Clear: when `CommitTrigger.Clear` is active, commits `''` immediately; in all cases, clearing deactivates the guard
21
33
  * - Deduplication: consecutive identical values never committed twice
22
34
  * - External sync: when `value` changes externally, local state re-syncs and stale timers cancelled
23
35
  * - Unmount: all pending timers cancelled; no trailing commit fires
36
+ * - `triggers`: controls which user actions fire a commit (defaults to all)
24
37
  *
25
38
  * @returns An object with `inputProps` to spread onto the input element.
26
39
  */
27
- export declare function useInputGuards({ value, delay, onCommit, }: UseInputGuardsConfig): {
40
+ export declare function useInputGuards({ value, delay, onCommit, triggers, }: UseInputGuardsConfig): {
28
41
  inputProps: UseInputGuardsProps;
29
42
  };
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  export { default as ExampleComponent } from './ExampleComponent.js';
2
2
  export { u as useConfirmDialog } from './useConfirmDialog-DaQ5Golt.js';
3
- export { u as useInputGuards } from './useInputGuards-DhT8mdGl.js';
3
+ export { C as CommitTrigger, u as useInputGuards } from './useInputGuards-DkzuBQaN.js';
4
4
  export { default as ExampleProvider } from './ExampleProvider.js';
5
5
  //# sourceMappingURL=index.js.map
@@ -1,5 +1,22 @@
1
1
  import { useState, useRef, useEffect, useCallback } from 'react';
2
2
 
3
+ var CommitTrigger = /* @__PURE__ */ ((CommitTrigger2) => {
4
+ CommitTrigger2["Typing"] = "typing";
5
+ CommitTrigger2["Enter"] = "enter";
6
+ CommitTrigger2["Paste"] = "paste";
7
+ CommitTrigger2["Clear"] = "clear";
8
+ return CommitTrigger2;
9
+ })(CommitTrigger || {});
10
+ const ALL_TRIGGERS = [
11
+ "typing" /* Typing */,
12
+ "enter" /* Enter */,
13
+ "paste" /* Paste */,
14
+ "clear" /* Clear */
15
+ ];
16
+ function toTriggerSet(triggers) {
17
+ if (!triggers || triggers.length === 0) return new Set(ALL_TRIGGERS);
18
+ return new Set(triggers);
19
+ }
3
20
  function clearTypingTimer(stateRef) {
4
21
  if (stateRef.current.typingTimer !== null) {
5
22
  clearTimeout(stateRef.current.typingTimer);
@@ -23,6 +40,9 @@ function clearAllTimers(stateRef) {
23
40
  clearDeferredTimer(stateRef);
24
41
  clearGuardTimer(stateRef);
25
42
  }
43
+ function hasTrigger(stateRef, trigger) {
44
+ return stateRef.current.triggers.has(trigger);
45
+ }
26
46
  function activateGuard(stateRef) {
27
47
  stateRef.current.guardActive = true;
28
48
  clearGuardTimer(stateRef);
@@ -58,11 +78,14 @@ function handleValueChange(stateRef, setLocalValue, newValue) {
58
78
  stateRef.current.localValue = newValue;
59
79
  if (newValue === "") {
60
80
  clearAllTimers(stateRef);
61
- doCommit(stateRef, newValue);
81
+ if (hasTrigger(stateRef, "clear" /* Clear */)) {
82
+ doCommit(stateRef, newValue);
83
+ }
62
84
  deactivateGuard(stateRef);
63
85
  return;
64
86
  }
65
87
  clearTypingTimer(stateRef);
88
+ if (!hasTrigger(stateRef, "typing" /* Typing */)) return;
66
89
  stateRef.current.typingTimer = setTimeout(() => {
67
90
  stateRef.current.typingTimer = null;
68
91
  guardedCommit(stateRef, newValue);
@@ -72,12 +95,23 @@ function handlePasteValue(stateRef, setLocalValue, pastedValue) {
72
95
  setLocalValue(pastedValue);
73
96
  stateRef.current.localValue = pastedValue;
74
97
  clearTypingTimer(stateRef);
75
- guardedCommit(stateRef, pastedValue);
98
+ if (hasTrigger(stateRef, "paste" /* Paste */)) {
99
+ guardedCommit(stateRef, pastedValue);
100
+ } else {
101
+ clearDeferredTimer(stateRef);
102
+ if (hasTrigger(stateRef, "typing" /* Typing */) && pastedValue !== "") {
103
+ stateRef.current.typingTimer = setTimeout(() => {
104
+ stateRef.current.typingTimer = null;
105
+ guardedCommit(stateRef, pastedValue);
106
+ }, stateRef.current.delay);
107
+ }
108
+ }
76
109
  }
77
110
  function useInputGuards({
78
111
  value,
79
112
  delay,
80
- onCommit
113
+ onCommit,
114
+ triggers
81
115
  }) {
82
116
  const [localValue, setLocalValue] = useState(value);
83
117
  const stateRef = useRef({
@@ -88,6 +122,7 @@ function useInputGuards({
88
122
  externalValue: value,
89
123
  onCommit,
90
124
  delay,
125
+ triggers: toTriggerSet(triggers),
91
126
  typingTimer: null,
92
127
  deferredTimer: null,
93
128
  guardTimer: null
@@ -95,6 +130,7 @@ function useInputGuards({
95
130
  stateRef.current.renderedLocalValue = localValue;
96
131
  stateRef.current.onCommit = onCommit;
97
132
  stateRef.current.delay = delay;
133
+ stateRef.current.triggers = toTriggerSet(triggers);
98
134
  useEffect(() => {
99
135
  if (value === stateRef.current.externalValue) return;
100
136
  stateRef.current.externalValue = value;
@@ -144,18 +180,17 @@ function useInputGuards({
144
180
  return;
145
181
  }
146
182
  if (event.key !== "Enter") return;
147
- clearTypingTimer(stateRef);
148
- guardedCommit(stateRef, stateRef.current.localValue);
183
+ if (hasTrigger(stateRef, "enter" /* Enter */)) {
184
+ clearTypingTimer(stateRef);
185
+ guardedCommit(stateRef, stateRef.current.localValue);
186
+ }
149
187
  },
150
188
  []
151
189
  );
152
- const onClear = useCallback(() => {
153
- handleValueChange(stateRef, setLocalValue, "");
154
- }, []);
155
190
  return {
156
- inputProps: { value: localValue, onChange, onPaste, onKeyDown, onClear }
191
+ inputProps: { value: localValue, onChange, onPaste, onKeyDown }
157
192
  };
158
193
  }
159
194
 
160
- export { useInputGuards as u };
161
- //# sourceMappingURL=useInputGuards-DhT8mdGl.js.map
195
+ export { CommitTrigger as C, useInputGuards as u };
196
+ //# sourceMappingURL=useInputGuards-DkzuBQaN.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useInputGuards-DkzuBQaN.js","sources":["../src/hooks/useInputGuards/useInputGuards.ts"],"sourcesContent":["import {\n useCallback,\n useEffect,\n useRef,\n useState,\n type ChangeEventHandler,\n type ClipboardEventHandler,\n type KeyboardEventHandler,\n} from \"react\";\n\nexport enum CommitTrigger {\n Typing = \"typing\",\n Enter = \"enter\",\n Paste = \"paste\",\n Clear = \"clear\",\n}\n\nconst ALL_TRIGGERS = [\n CommitTrigger.Typing,\n CommitTrigger.Enter,\n CommitTrigger.Paste,\n CommitTrigger.Clear,\n] as const;\n\nfunction toTriggerSet(\n triggers?: CommitTrigger[],\n): ReadonlySet<CommitTrigger> {\n if (!triggers || triggers.length === 0) return new Set(ALL_TRIGGERS);\n return new Set(triggers);\n}\n\nexport interface UseInputGuardsProps {\n value: string;\n onChange: ChangeEventHandler<HTMLInputElement>;\n onPaste: ClipboardEventHandler<HTMLInputElement>;\n onKeyDown: KeyboardEventHandler<HTMLInputElement>;\n}\n\nexport interface UseInputGuardsConfig {\n value: string;\n delay: number;\n onCommit: (value: string) => void;\n /**\n * Which user actions trigger a commit. Defaults to all triggers when omitted or empty.\n * Omit `CommitTrigger.Typing` to disable the debounce auto-commit after inactivity\n * while still allowing Enter, paste, and clear to commit.\n */\n triggers?: [CommitTrigger, ...CommitTrigger[]];\n}\n\ninterface State {\n localValue: string;\n renderedLocalValue: string;\n lastCommitted: string | null;\n guardActive: boolean;\n externalValue: string;\n onCommit: (value: string) => void;\n delay: number;\n triggers: ReadonlySet<CommitTrigger>;\n typingTimer: ReturnType<typeof setTimeout> | null;\n deferredTimer: ReturnType<typeof setTimeout> | null;\n guardTimer: ReturnType<typeof setTimeout> | null;\n}\n\ninterface StateRef {\n current: State;\n}\n\nfunction clearTypingTimer(stateRef: StateRef) {\n if (stateRef.current.typingTimer !== null) {\n clearTimeout(stateRef.current.typingTimer);\n stateRef.current.typingTimer = null;\n }\n}\n\nfunction clearDeferredTimer(stateRef: StateRef) {\n if (stateRef.current.deferredTimer !== null) {\n clearTimeout(stateRef.current.deferredTimer);\n stateRef.current.deferredTimer = null;\n }\n}\n\nfunction clearGuardTimer(stateRef: StateRef) {\n if (stateRef.current.guardTimer !== null) {\n clearTimeout(stateRef.current.guardTimer);\n stateRef.current.guardTimer = null;\n }\n}\n\nfunction clearAllTimers(stateRef: StateRef) {\n clearTypingTimer(stateRef);\n clearDeferredTimer(stateRef);\n clearGuardTimer(stateRef);\n}\n\nfunction hasTrigger(stateRef: StateRef, trigger: CommitTrigger) {\n return stateRef.current.triggers.has(trigger);\n}\n\nfunction activateGuard(stateRef: StateRef) {\n stateRef.current.guardActive = true;\n clearGuardTimer(stateRef);\n\n stateRef.current.guardTimer = setTimeout(() => {\n stateRef.current.guardTimer = null;\n stateRef.current.guardActive = false;\n }, stateRef.current.delay);\n}\n\nfunction deactivateGuard(stateRef: StateRef) {\n stateRef.current.guardActive = false;\n clearGuardTimer(stateRef);\n}\n\nfunction doCommit(stateRef: StateRef, val: string) {\n if (stateRef.current.lastCommitted === val) return;\n\n stateRef.current.lastCommitted = val;\n activateGuard(stateRef);\n stateRef.current.onCommit(val);\n}\n\nfunction guardedCommit(stateRef: StateRef, val: string) {\n const wasDeferred = stateRef.current.deferredTimer !== null;\n clearDeferredTimer(stateRef);\n\n if (!wasDeferred && !stateRef.current.guardActive) {\n doCommit(stateRef, val);\n return;\n }\n\n stateRef.current.deferredTimer = setTimeout(() => {\n stateRef.current.deferredTimer = null;\n doCommit(stateRef, val);\n }, stateRef.current.delay);\n}\n\nfunction handleValueChange(\n stateRef: StateRef,\n setLocalValue: (value: string) => void,\n newValue: string,\n) {\n setLocalValue(newValue);\n stateRef.current.localValue = newValue;\n\n if (newValue === \"\") {\n clearAllTimers(stateRef);\n if (hasTrigger(stateRef, CommitTrigger.Clear)) {\n doCommit(stateRef, newValue);\n }\n deactivateGuard(stateRef);\n return;\n }\n\n clearTypingTimer(stateRef);\n if (!hasTrigger(stateRef, CommitTrigger.Typing)) return; // visible value updated above; no debounce commit\n stateRef.current.typingTimer = setTimeout(() => {\n stateRef.current.typingTimer = null;\n guardedCommit(stateRef, newValue);\n }, stateRef.current.delay);\n}\n\nfunction handlePasteValue(\n stateRef: StateRef,\n setLocalValue: (value: string) => void,\n pastedValue: string,\n) {\n setLocalValue(pastedValue);\n stateRef.current.localValue = pastedValue;\n\n clearTypingTimer(stateRef);\n if (hasTrigger(stateRef, CommitTrigger.Paste)) {\n guardedCommit(stateRef, pastedValue);\n } else {\n clearDeferredTimer(stateRef);\n if (hasTrigger(stateRef, CommitTrigger.Typing) && pastedValue !== \"\") {\n stateRef.current.typingTimer = setTimeout(() => {\n stateRef.current.typingTimer = null;\n guardedCommit(stateRef, pastedValue);\n }, stateRef.current.delay);\n }\n }\n}\n\n/**\n * Manages a debounced text input with rate-limited commits.\n *\n * - Typing: visible value updates immediately; when `CommitTrigger.Typing` is active, `onCommit` fires after `delay` ms of inactivity\n * - Paste: when `CommitTrigger.Paste` is active, commits immediately via a commit guard (rate-limited to one per `delay` ms)\n * - Enter: when `CommitTrigger.Enter` is active, commits immediately via a commit guard (rate-limited to one per `delay` ms)\n * - Repeated keys: held-key keydown events suppressed with `preventDefault()`\n * - Clear: when `CommitTrigger.Clear` is active, commits `''` immediately; in all cases, clearing deactivates the guard\n * - Deduplication: consecutive identical values never committed twice\n * - External sync: when `value` changes externally, local state re-syncs and stale timers cancelled\n * - Unmount: all pending timers cancelled; no trailing commit fires\n * - `triggers`: controls which user actions fire a commit (defaults to all)\n *\n * @returns An object with `inputProps` to spread onto the input element.\n */\nexport function useInputGuards({\n value,\n delay,\n onCommit,\n triggers,\n}: UseInputGuardsConfig): { inputProps: UseInputGuardsProps } {\n const [localValue, setLocalValue] = useState(value);\n\n const stateRef = useRef<State>({\n localValue: value,\n renderedLocalValue: value,\n lastCommitted: null,\n guardActive: false,\n externalValue: value,\n onCommit,\n delay,\n triggers: toTriggerSet(triggers),\n typingTimer: null,\n deferredTimer: null,\n guardTimer: null,\n });\n\n stateRef.current.renderedLocalValue = localValue;\n stateRef.current.onCommit = onCommit;\n stateRef.current.delay = delay;\n stateRef.current.triggers = toTriggerSet(triggers);\n\n useEffect(() => {\n if (value === stateRef.current.externalValue) return;\n\n stateRef.current.externalValue = value;\n\n if (value === stateRef.current.lastCommitted) return; // own commit bouncing back\n\n clearAllTimers(stateRef);\n deactivateGuard(stateRef);\n setLocalValue(value);\n stateRef.current.localValue = value;\n }, [value]);\n\n useEffect(() => {\n return () => {\n clearAllTimers(stateRef);\n };\n }, []);\n\n const onChange: ChangeEventHandler<HTMLInputElement> = useCallback(\n (event) => {\n const newValue = event.target.value;\n\n if (newValue === stateRef.current.localValue) return;\n if (newValue === stateRef.current.renderedLocalValue) return; // spurious post-paste event\n\n handleValueChange(stateRef, setLocalValue, newValue);\n },\n [],\n );\n\n const onPaste: ClipboardEventHandler<HTMLInputElement> = useCallback(\n (event) => {\n event.preventDefault();\n\n if (!event.clipboardData) return;\n\n const pastedText = event.clipboardData.getData(\"text\");\n const { selectionStart, selectionEnd } = event.currentTarget;\n const currentValue = stateRef.current.localValue;\n const beforeCursor = currentValue.slice(0, selectionStart ?? 0);\n const afterCursor = currentValue.slice(\n selectionEnd ?? currentValue.length,\n );\n\n handlePasteValue(\n stateRef,\n setLocalValue,\n beforeCursor + pastedText + afterCursor,\n );\n },\n [],\n );\n\n const onKeyDown: KeyboardEventHandler<HTMLInputElement> = useCallback(\n (event) => {\n if (event.repeat) {\n event.preventDefault();\n return;\n }\n if (event.key !== \"Enter\") return;\n\n if (hasTrigger(stateRef, CommitTrigger.Enter)) {\n clearTypingTimer(stateRef);\n guardedCommit(stateRef, stateRef.current.localValue);\n }\n },\n [],\n );\n\n return {\n inputProps: { value: localValue, onChange, onPaste, onKeyDown },\n };\n}\n"],"names":["CommitTrigger"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- export { u as default, u as useInputGuards } from './useInputGuards-DhT8mdGl.js';
1
+ export { C as CommitTrigger, u as default, u as useInputGuards } from './useInputGuards-DkzuBQaN.js';
2
2
  //# sourceMappingURL=useInputGuards.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@servicetitan/anvil2-ext-common",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "type": "module",
5
5
  "types": "./dist/index.d.ts",
6
6
  "main": "./dist/index.js",
@@ -31,7 +31,7 @@
31
31
  "tabbable": "^6.2.0",
32
32
  "tinycolor2": "^1.6.0",
33
33
  "uuid": "^10.0.0",
34
- "@servicetitan/anvil2": "2.1.0"
34
+ "@servicetitan/anvil2": "2.3.0"
35
35
  },
36
36
  "peerDependencies": {
37
37
  "@types/react": "^18 || ^19",
@@ -1 +0,0 @@
1
- {"version":3,"file":"useInputGuards-DhT8mdGl.js","sources":["../src/hooks/useInputGuards/useInputGuards.ts"],"sourcesContent":["import {\n useCallback,\n useEffect,\n useRef,\n useState,\n type ChangeEventHandler,\n type ClipboardEventHandler,\n type KeyboardEventHandler,\n} from \"react\";\n\nexport interface UseInputGuardsProps {\n value: string;\n onChange: ChangeEventHandler<HTMLInputElement>;\n onPaste: ClipboardEventHandler<HTMLInputElement>;\n onKeyDown: KeyboardEventHandler<HTMLInputElement>;\n onClear: () => void;\n}\n\nexport interface UseInputGuardsConfig {\n value: string;\n delay: number;\n onCommit: (value: string) => void;\n}\n\ninterface State {\n localValue: string;\n renderedLocalValue: string;\n lastCommitted: string | null;\n guardActive: boolean;\n externalValue: string;\n onCommit: (value: string) => void;\n delay: number;\n typingTimer: ReturnType<typeof setTimeout> | null;\n deferredTimer: ReturnType<typeof setTimeout> | null;\n guardTimer: ReturnType<typeof setTimeout> | null;\n}\n\ninterface StateRef {\n current: State;\n}\n\nfunction clearTypingTimer(stateRef: StateRef) {\n if (stateRef.current.typingTimer !== null) {\n clearTimeout(stateRef.current.typingTimer);\n stateRef.current.typingTimer = null;\n }\n}\n\nfunction clearDeferredTimer(stateRef: StateRef) {\n if (stateRef.current.deferredTimer !== null) {\n clearTimeout(stateRef.current.deferredTimer);\n stateRef.current.deferredTimer = null;\n }\n}\n\nfunction clearGuardTimer(stateRef: StateRef) {\n if (stateRef.current.guardTimer !== null) {\n clearTimeout(stateRef.current.guardTimer);\n stateRef.current.guardTimer = null;\n }\n}\n\nfunction clearAllTimers(stateRef: StateRef) {\n clearTypingTimer(stateRef);\n clearDeferredTimer(stateRef);\n clearGuardTimer(stateRef);\n}\n\nfunction activateGuard(stateRef: StateRef) {\n stateRef.current.guardActive = true;\n clearGuardTimer(stateRef);\n\n stateRef.current.guardTimer = setTimeout(() => {\n stateRef.current.guardTimer = null;\n stateRef.current.guardActive = false;\n }, stateRef.current.delay);\n}\n\nfunction deactivateGuard(stateRef: StateRef) {\n stateRef.current.guardActive = false;\n clearGuardTimer(stateRef);\n}\n\nfunction doCommit(stateRef: StateRef, val: string) {\n if (stateRef.current.lastCommitted === val) return;\n\n stateRef.current.lastCommitted = val;\n activateGuard(stateRef);\n stateRef.current.onCommit(val);\n}\n\nfunction guardedCommit(stateRef: StateRef, val: string) {\n const wasDeferred = stateRef.current.deferredTimer !== null;\n clearDeferredTimer(stateRef);\n\n if (!wasDeferred && !stateRef.current.guardActive) {\n doCommit(stateRef, val);\n return;\n }\n\n stateRef.current.deferredTimer = setTimeout(() => {\n stateRef.current.deferredTimer = null;\n doCommit(stateRef, val);\n }, stateRef.current.delay);\n}\n\nfunction handleValueChange(\n stateRef: StateRef,\n setLocalValue: (value: string) => void,\n newValue: string,\n) {\n setLocalValue(newValue);\n stateRef.current.localValue = newValue;\n\n if (newValue === \"\") {\n clearAllTimers(stateRef);\n doCommit(stateRef, newValue);\n deactivateGuard(stateRef);\n return;\n }\n\n clearTypingTimer(stateRef);\n stateRef.current.typingTimer = setTimeout(() => {\n stateRef.current.typingTimer = null;\n guardedCommit(stateRef, newValue);\n }, stateRef.current.delay);\n}\n\nfunction handlePasteValue(\n stateRef: StateRef,\n setLocalValue: (value: string) => void,\n pastedValue: string,\n) {\n setLocalValue(pastedValue);\n stateRef.current.localValue = pastedValue;\n\n clearTypingTimer(stateRef);\n guardedCommit(stateRef, pastedValue);\n}\n\n/**\n * Manages a debounced text input with rate-limited commits.\n *\n * - Typing: visible value updates immediately; `onCommit` fires after `delay` ms of inactivity\n * - Paste / Enter: commits immediately via a commit guard (rate-limited to one per `delay` ms)\n * - Repeated keys: held-key keydown events suppressed with `preventDefault()`\n * - Clear: commits `''` immediately and deactivates the guard\n * - Deduplication: consecutive identical values never committed twice\n * - External sync: when `value` changes externally, local state re-syncs and stale timers cancelled\n * - Unmount: all pending timers cancelled; no trailing commit fires\n *\n * @returns An object with `inputProps` to spread onto the input element.\n */\nexport function useInputGuards({\n value,\n delay,\n onCommit,\n}: UseInputGuardsConfig): { inputProps: UseInputGuardsProps } {\n const [localValue, setLocalValue] = useState(value);\n\n const stateRef = useRef<State>({\n localValue: value,\n renderedLocalValue: value,\n lastCommitted: null,\n guardActive: false,\n externalValue: value,\n onCommit,\n delay,\n typingTimer: null,\n deferredTimer: null,\n guardTimer: null,\n });\n\n stateRef.current.renderedLocalValue = localValue;\n stateRef.current.onCommit = onCommit;\n stateRef.current.delay = delay;\n\n useEffect(() => {\n if (value === stateRef.current.externalValue) return;\n\n stateRef.current.externalValue = value;\n\n if (value === stateRef.current.lastCommitted) return; // own commit bouncing back\n\n clearAllTimers(stateRef);\n deactivateGuard(stateRef);\n setLocalValue(value);\n stateRef.current.localValue = value;\n }, [value]);\n\n useEffect(() => {\n return () => {\n clearAllTimers(stateRef);\n };\n }, []);\n\n const onChange: ChangeEventHandler<HTMLInputElement> = useCallback(\n (event) => {\n const newValue = event.target.value;\n\n if (newValue === stateRef.current.localValue) return;\n if (newValue === stateRef.current.renderedLocalValue) return; // spurious post-paste event\n\n handleValueChange(stateRef, setLocalValue, newValue);\n },\n [],\n );\n\n const onPaste: ClipboardEventHandler<HTMLInputElement> = useCallback(\n (event) => {\n event.preventDefault();\n\n if (!event.clipboardData) return;\n\n const pastedText = event.clipboardData.getData(\"text\");\n const { selectionStart, selectionEnd } = event.currentTarget;\n const currentValue = stateRef.current.localValue;\n const beforeCursor = currentValue.slice(0, selectionStart ?? 0);\n const afterCursor = currentValue.slice(\n selectionEnd ?? currentValue.length,\n );\n\n handlePasteValue(\n stateRef,\n setLocalValue,\n beforeCursor + pastedText + afterCursor,\n );\n },\n [],\n );\n\n const onKeyDown: KeyboardEventHandler<HTMLInputElement> = useCallback(\n (event) => {\n if (event.repeat) {\n event.preventDefault();\n return;\n }\n if (event.key !== \"Enter\") return;\n\n clearTypingTimer(stateRef);\n guardedCommit(stateRef, stateRef.current.localValue);\n },\n [],\n );\n\n const onClear = useCallback(() => {\n handleValueChange(stateRef, setLocalValue, \"\");\n }, []);\n\n return {\n inputProps: { value: localValue, onChange, onPaste, onKeyDown, onClear },\n };\n}\n"],"names":[],"mappings":"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"}