@ngrok/mantle 0.70.1 → 0.71.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.
Files changed (161) hide show
  1. package/dist/accordion.d.ts +1 -1
  2. package/dist/alert-dialog.d.ts +341 -94
  3. package/dist/alert-dialog.js.map +1 -1
  4. package/dist/alert.d.ts +3 -3
  5. package/dist/alert.js.map +1 -1
  6. package/dist/anchor-2stEauOz.js.map +1 -1
  7. package/dist/anchor.d.ts +46 -5
  8. package/dist/{as-child-CJ2vTesV.d.ts → as-child-DQHfEmYB.d.ts} +1 -1
  9. package/dist/badge.d.ts +34 -5
  10. package/dist/badge.js.map +1 -1
  11. package/dist/{button-DDK6nEac.d.ts → button-Bq0x5Pv4.d.ts} +6 -6
  12. package/dist/button.d.ts +3 -3
  13. package/dist/card.d.ts +1 -1
  14. package/dist/checkbox.d.ts +1 -1
  15. package/dist/checkbox.js +1 -1
  16. package/dist/code-block.d.ts +3 -3
  17. package/dist/code-block.js +1 -1
  18. package/dist/code-block.js.map +1 -1
  19. package/dist/code-block_highlight-utils.d.ts +1 -1
  20. package/dist/code-block_highlight-utils.js +1 -1
  21. package/dist/code.d.ts +23 -2
  22. package/dist/code.js.map +1 -1
  23. package/dist/color.d.ts +1 -1
  24. package/dist/combobox.d.ts +12 -2
  25. package/dist/combobox.js +1 -1
  26. package/dist/combobox.js.map +1 -1
  27. package/dist/command.d.ts +3 -3
  28. package/dist/command.js +1 -1
  29. package/dist/command.js.map +1 -1
  30. package/dist/compose-refs-DZ3cPi47.js +2 -0
  31. package/dist/compose-refs-DZ3cPi47.js.map +1 -0
  32. package/dist/copy-to-clipboard-DjOD_Mwb.js +2 -0
  33. package/dist/copy-to-clipboard-DjOD_Mwb.js.map +1 -0
  34. package/dist/data-table.d.ts +530 -75
  35. package/dist/data-table.js +1 -1
  36. package/dist/data-table.js.map +1 -1
  37. package/dist/{deep-non-nullable-DwBZzk4x.d.ts → deep-non-nullable-VFm1T3JZ.d.ts} +1 -1
  38. package/dist/description-list.d.ts +1 -1
  39. package/dist/{dialog-MiS_Q-ge.js → dialog-BHzl9eye.js} +1 -1
  40. package/dist/dialog-BHzl9eye.js.map +1 -0
  41. package/dist/dialog.d.ts +8 -3
  42. package/dist/dialog.js +1 -1
  43. package/dist/{direction-ClCocWIf.js → direction-DsB-pD9V.js} +1 -1
  44. package/dist/{direction-ClCocWIf.js.map → direction-DsB-pD9V.js.map} +1 -1
  45. package/dist/{direction-Jk7BkzGo.d.ts → direction-DtBAQn7p.d.ts} +1 -1
  46. package/dist/{dropdown-menu-C9f9Y8Ov.d.ts → dropdown-menu-CzUNYIfA.d.ts} +2 -2
  47. package/dist/{dropdown-menu-Ff97BIJe.js → dropdown-menu-Ducs2SEn.js} +2 -2
  48. package/dist/{dropdown-menu-Ff97BIJe.js.map → dropdown-menu-Ducs2SEn.js.map} +1 -1
  49. package/dist/dropdown-menu.d.ts +1 -1
  50. package/dist/dropdown-menu.js +1 -1
  51. package/dist/empty.d.ts +2 -2
  52. package/dist/flag.d.ts +33 -4
  53. package/dist/flag.js.map +1 -1
  54. package/dist/hooks.d.ts +301 -77
  55. package/dist/hooks.js +1 -1
  56. package/dist/hooks.js.map +1 -1
  57. package/dist/hover-card.d.ts +15 -10
  58. package/dist/hover-card.js.map +1 -1
  59. package/dist/{icon-C0YAAaLZ.d.ts → icon-DKMJm20j.d.ts} +2 -2
  60. package/dist/{icon-button-Cl30yTfu.d.ts → icon-button-BnK4K7YK.d.ts} +3 -3
  61. package/dist/icon.d.ts +3 -3
  62. package/dist/icons.d.ts +3 -3
  63. package/dist/icons.js +1 -1
  64. package/dist/icons.js.map +1 -1
  65. package/dist/{in-view-DsiWfQpY.d.ts → in-view-Da08Bx6l.d.ts} +15 -4
  66. package/dist/{in-view-BXzPPdcl.js → in-view-pia_SVdE.js} +1 -1
  67. package/dist/{in-view-BXzPPdcl.js.map → in-view-pia_SVdE.js.map} +1 -1
  68. package/dist/{index-ddHz7L9f.d.ts → index-C91lxoX9.d.ts} +56 -13
  69. package/dist/{index-DU3SQJ46.d.ts → index-DOJUH34Z.d.ts} +4 -4
  70. package/dist/{index-B6SPk_xb.d.ts → index-DkMUaYsw.d.ts} +1 -1
  71. package/dist/{index-vOSpS5jv.d.ts → index-rtz7SwEq.d.ts} +1 -1
  72. package/dist/input.d.ts +2 -2
  73. package/dist/input.js +1 -1
  74. package/dist/input.js.map +1 -1
  75. package/dist/{is-input-Bh1rQhX3.js → is-input-CUEWaxtA.js} +1 -1
  76. package/dist/{is-input-Bh1rQhX3.js.map → is-input-CUEWaxtA.js.map} +1 -1
  77. package/dist/{kbd-B0wWeV_0.js → kbd-CAVUiqBT.js} +1 -1
  78. package/dist/kbd-CAVUiqBT.js.map +1 -0
  79. package/dist/kbd.d.ts +37 -8
  80. package/dist/kbd.js +1 -1
  81. package/dist/label.d.ts +40 -9
  82. package/dist/label.js.map +1 -1
  83. package/dist/media-object.d.ts +27 -11
  84. package/dist/media-object.js.map +1 -1
  85. package/dist/multi-select.d.ts +187 -36
  86. package/dist/multi-select.js +1 -1
  87. package/dist/multi-select.js.map +1 -1
  88. package/dist/otp-input.d.ts +167 -0
  89. package/dist/otp-input.js +2 -0
  90. package/dist/otp-input.js.map +1 -0
  91. package/dist/pagination.d.ts +3 -3
  92. package/dist/pagination.js +1 -1
  93. package/dist/pagination.js.map +1 -1
  94. package/dist/popover.d.ts +7 -5
  95. package/dist/popover.js.map +1 -1
  96. package/dist/primitive-tXm_8n_t.js.map +1 -1
  97. package/dist/{primitive-DXo0gUqw.d.ts → primitive-tyw4V7Vf.d.ts} +1 -1
  98. package/dist/progress.js.map +1 -1
  99. package/dist/radio-group.d.ts +1 -1
  100. package/dist/radio-group.js +1 -1
  101. package/dist/{resolve-pre-rendered-props-BXv6e6fc.js → resolve-pre-rendered-props-C-kiaLHj.js} +1 -1
  102. package/dist/{resolve-pre-rendered-props-BXv6e6fc.js.map → resolve-pre-rendered-props-C-kiaLHj.js.map} +1 -1
  103. package/dist/{resolve-pre-rendered-props-kcQrtWPt.d.ts → resolve-pre-rendered-props-CNUnH1fU.d.ts} +1 -1
  104. package/dist/sandboxed-on-click.d.ts +1 -1
  105. package/dist/{select-LJmfG--I.js → select-DOgdZO0Q.js} +2 -2
  106. package/dist/select-DOgdZO0Q.js.map +1 -0
  107. package/dist/{select-DNJli9JO.d.ts → select-DZutJxyr.d.ts} +11 -3
  108. package/dist/select.d.ts +1 -1
  109. package/dist/select.js +1 -1
  110. package/dist/{separator-DyOGgFCs.js → separator-DSOIrnhj.js} +1 -1
  111. package/dist/{separator-DyOGgFCs.js.map → separator-DSOIrnhj.js.map} +1 -1
  112. package/dist/separator.d.ts +1 -1
  113. package/dist/separator.js +1 -1
  114. package/dist/sheet.d.ts +7 -3
  115. package/dist/sheet.js.map +1 -1
  116. package/dist/skeleton.d.ts +32 -5
  117. package/dist/skeleton.js.map +1 -1
  118. package/dist/{sort-C_Jbs1dH.js → sort-DzCsa6Qj.js} +2 -2
  119. package/dist/{sort-C_Jbs1dH.js.map → sort-DzCsa6Qj.js.map} +1 -1
  120. package/dist/split-button.d.ts +3 -3
  121. package/dist/split-button.js +1 -1
  122. package/dist/{svg-only-BnnbLx6R.d.ts → svg-only-BtBvFy-N.d.ts} +2 -2
  123. package/dist/{table-4q1UxE7L.d.ts → table-BsNJBKiq.d.ts} +7 -3
  124. package/dist/{table-12T25gGa.js → table-Cl4nlRMR.js} +2 -2
  125. package/dist/{table-12T25gGa.js.map → table-Cl4nlRMR.js.map} +1 -1
  126. package/dist/table.d.ts +1 -1
  127. package/dist/table.js +1 -1
  128. package/dist/tabs.js +1 -1
  129. package/dist/text-area.d.ts +1 -1
  130. package/dist/text-area.js +1 -1
  131. package/dist/theme-provider-BFcnjeME.js.map +1 -1
  132. package/dist/theme.d.ts +2 -2
  133. package/dist/theme.js.map +1 -1
  134. package/dist/{themes-DXb8Tk74.d.ts → themes-DIEYkvNl.d.ts} +1 -1
  135. package/dist/toast.d.ts +3 -3
  136. package/dist/tooltip.d.ts +31 -14
  137. package/dist/tooltip.js.map +1 -1
  138. package/dist/{traffic-policy-file-ChsoQtXQ.js → traffic-policy-file-C6LHYrIU.js} +1 -1
  139. package/dist/{traffic-policy-file-ChsoQtXQ.js.map → traffic-policy-file-C6LHYrIU.js.map} +1 -1
  140. package/dist/{types-BeTbgoJd.d.ts → types-DG0WQLTL.d.ts} +1 -1
  141. package/dist/{types-DEYyl5LX.d.ts → types-DoV0R5Ja.d.ts} +1 -1
  142. package/dist/types.d.ts +5 -5
  143. package/dist/use-copy-to-clipboard-C7vsjJe-.js +2 -0
  144. package/dist/use-copy-to-clipboard-C7vsjJe-.js.map +1 -0
  145. package/dist/use-matches-media-query-CojcYxlA.js.map +1 -1
  146. package/dist/{use-prefers-reduced-motion-BcwST13S.js → use-prefers-reduced-motion-aXfsyo-k.js} +1 -1
  147. package/dist/use-prefers-reduced-motion-aXfsyo-k.js.map +1 -0
  148. package/dist/utils.d.ts +3 -3
  149. package/dist/utils.js +1 -1
  150. package/dist/utils.js.map +1 -1
  151. package/dist/{variant-props-DszdagRm.d.ts → variant-props-DUmSIQK8.d.ts} +2 -2
  152. package/dist/{with-style-props-Dlz3G1tS.d.ts → with-style-props-3iFrBR08.d.ts} +1 -1
  153. package/package.json +12 -7
  154. package/dist/compose-refs-DFIaEnQH.js +0 -2
  155. package/dist/compose-refs-DFIaEnQH.js.map +0 -1
  156. package/dist/dialog-MiS_Q-ge.js.map +0 -1
  157. package/dist/kbd-B0wWeV_0.js.map +0 -1
  158. package/dist/select-LJmfG--I.js.map +0 -1
  159. package/dist/use-copy-to-clipboard-Ds9MsSNU.js +0 -2
  160. package/dist/use-copy-to-clipboard-Ds9MsSNU.js.map +0 -1
  161. package/dist/use-prefers-reduced-motion-BcwST13S.js.map +0 -1
package/dist/hooks.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { n as MarginType, o as useComposedRefs } from "./in-view-DsiWfQpY.js";
2
- import { RefObject, useEffect } from "react";
1
+ import { n as MarginType, o as useComposedRefs, s as copyToClipboard } from "./in-view-Da08Bx6l.js";
2
+ import { RefObject, useLayoutEffect } from "react";
3
3
 
4
4
  //#region src/hooks/use-breakpoint.d.ts
5
5
  /**
@@ -106,43 +106,119 @@ declare function useIsBelowBreakpoint(breakpoint: TailwindBreakpoint): boolean;
106
106
  //#endregion
107
107
  //#region src/hooks/use-callback-ref.d.ts
108
108
  /**
109
- * Returns a memoized callback that will always refer to the latest callback
110
- * passed to the hook.
109
+ * Returns a memoized callback that always invokes the latest version of the
110
+ * provided callback, while preserving a stable function identity across
111
+ * renders.
112
+ *
113
+ * Use this when you need to pass a callback to a child component, an event
114
+ * handler, or a hook dependency array, but the consumer should not re-run /
115
+ * re-render simply because the callback's identity changed. The returned
116
+ * function never changes reference, but internally always calls through to
117
+ * the latest `callback` passed in.
118
+ *
119
+ * Most commonly used as an internal building block for other hooks (for
120
+ * example, {@link useDebouncedCallback}). It is also re-exported publicly
121
+ * for consumers that need the same pattern.
122
+ *
123
+ * @param callback - The callback to wrap. May be `undefined`, in which case
124
+ * invoking the returned function is a no-op until a callback is provided
125
+ * on a subsequent render.
126
+ * @returns A stable function with the same signature as `callback` that
127
+ * forwards its arguments to the most recent `callback` value.
111
128
  *
112
- * This is useful when you want to pass a callback which may or may not be
113
- * memoized (have a stable identity) to a child component that will be updated
114
- * without causing the child component to re-render.
129
+ * @example
130
+ * // Pass a stable handler to a memoized child without re-rendering it
131
+ * const onSelect = useCallbackRef((id: string) => {
132
+ * // reads the latest `props.items` without being in deps
133
+ * props.onSelectItem(id, props.items);
134
+ * });
135
+ *
136
+ * return <MemoizedList onSelect={onSelect} />;
115
137
  */
116
138
  declare function useCallbackRef<T extends (...args: unknown[]) => unknown>(callback: T | undefined): T;
117
139
  //#endregion
118
140
  //#region src/hooks/use-copy-to-clipboard.d.ts
119
141
  /**
120
- * A hook that allows you to copy a string to the clipboard.
142
+ * React hook that returns a stable async function for copying a string to
143
+ * the system clipboard.
121
144
  *
122
- * The returned `copyToClipboard` function is async `await` it to know
123
- * whether the write succeeded. It throws when both the Clipboard API and
124
- * the `execCommand` polyfill fail.
145
+ * The returned function uses the Clipboard API when available and falls back
146
+ * to a `document.execCommand("copy")` polyfill for older browsers. `await`
147
+ * the call (or attach a `.then()` / `.catch()`) to observe whether the copy
148
+ * succeeded — the function throws when both the Clipboard API and the
149
+ * polyfill fail, or when called outside of a DOM environment.
125
150
  *
126
151
  * Inspired by: https://usehooks.com/usecopytoclipboard
152
+ *
153
+ * @returns An async function `(value: string) => Promise<void>` that writes
154
+ * `value` to the clipboard and rejects on failure.
155
+ *
156
+ * @example
157
+ * // Copy a token on click and surface a toast on success/failure
158
+ * const copy = useCopyToClipboard();
159
+ *
160
+ * async function handleCopy() {
161
+ * try {
162
+ * await copy(token);
163
+ * toast.success("Copied!");
164
+ * } catch {
165
+ * toast.error("Could not copy to clipboard");
166
+ * }
167
+ * }
168
+ *
169
+ * return <button onClick={handleCopy}>Copy token</button>;
127
170
  */
128
- declare function useCopyToClipboard(): readonly [string, (value: string) => Promise<void>];
171
+ declare function useCopyToClipboard(): typeof copyToClipboard;
129
172
  //#endregion
130
173
  //#region src/hooks/use-debounced-callback.d.ts
174
+ /**
175
+ * Options for {@link useDebouncedCallback}.
176
+ */
131
177
  type Options = {
132
178
  /**
133
- * The delay in milliseconds to wait before calling the callback.
179
+ * The delay in milliseconds to wait between the last invocation and
180
+ * actually running the callback.
134
181
  */
135
182
  waitMs: number;
136
183
  };
137
184
  /**
138
- * Create a debounced version of a callback function.
185
+ * Returns a debounced version of the provided callback. Each call resets a
186
+ * timer; the underlying callback only runs after `options.waitMs` of
187
+ * inactivity has elapsed.
188
+ *
189
+ * Useful for limiting rapid invocations such as search-as-you-type inputs,
190
+ * window resize handlers, or expensive button-press handlers. The pending
191
+ * timer is automatically cleared on unmount.
192
+ *
193
+ * The debounced function always invokes the latest version of `callbackFn`,
194
+ * so callers do not need to memoize it. The returned function's identity
195
+ * only changes when `options.waitMs` changes, so it is safe to include in
196
+ * dependency arrays.
197
+ *
198
+ * @param callbackFn - The function to debounce. The latest reference passed
199
+ * on each render is always used when the timer fires.
200
+ * @param options - Debounce options.
201
+ * @param options.waitMs - Milliseconds of inactivity to wait before calling
202
+ * `callbackFn`.
203
+ * @returns A function with the same parameter list as `callbackFn` that
204
+ * schedules (or reschedules) the underlying call.
139
205
  *
140
- * It allows you to delay the execution of a function until a certain period of
141
- * inactivity has passed (the `options.waitMs`), which can be useful for limiting rapid
142
- * invocations of a function (like in search inputs or button clicks)
206
+ * @example
207
+ * // Debounce a search input by 300ms
208
+ * const [query, setQuery] = useState("");
209
+ * const search = useDebouncedCallback((value: string) => {
210
+ * fetchResults(value);
211
+ * }, { waitMs: 300 });
143
212
  *
144
- * Note: The debounced callback will always refer to the latest callback passed
145
- * even without memoization, so it's stable and safe to use in dependency arrays.
213
+ * return (
214
+ * <input
215
+ * value={query}
216
+ * onChange={(event) => {
217
+ * setQuery(event.target.value);
218
+ * search(event.target.value);
219
+ * }}
220
+ * />
221
+ * );
146
222
  */
147
223
  declare function useDebouncedCallback<T extends (...args: unknown[]) => unknown>(callbackFn: T, options: Options): (...args: Parameters<T>) => void;
148
224
  //#endregion
@@ -175,71 +251,171 @@ declare function useIsHydrated(): boolean;
175
251
  //#endregion
176
252
  //#region src/hooks/use-isomorphic-layout-effect.d.ts
177
253
  /**
178
- * useIsomorphicLayoutEffect is a hook that uses useLayoutEffect on the client and useEffect on the server.
254
+ * A drop-in replacement for `useLayoutEffect` that does not warn during
255
+ * server-side rendering.
256
+ *
257
+ * Resolves to `useLayoutEffect` in the browser (where it can read layout and
258
+ * synchronously re-render before paint) and to `useEffect` on the server
259
+ * (where layout effects are a no-op and React would otherwise log a
260
+ * "useLayoutEffect does nothing on the server" warning).
261
+ *
262
+ * Use this whenever you need the timing semantics of `useLayoutEffect` in
263
+ * code that may also execute during SSR. It is most often used internally
264
+ * by other Mantle hooks and components.
265
+ *
266
+ * @param effect - The imperative function that may return a cleanup
267
+ * function — same signature as React's `useLayoutEffect` / `useEffect`.
268
+ * @param deps - Optional dependency list, same semantics as
269
+ * `useLayoutEffect`.
270
+ * @returns Nothing.
271
+ *
272
+ * @example
273
+ * // Measure an element synchronously after layout
274
+ * const ref = useRef<HTMLDivElement>(null);
275
+ * const [width, setWidth] = useState(0);
276
+ *
277
+ * useIsomorphicLayoutEffect(() => {
278
+ * if (ref.current) {
279
+ * setWidth(ref.current.getBoundingClientRect().width);
280
+ * }
281
+ * }, []);
282
+ *
283
+ * return <div ref={ref}>Width: {width}</div>;
179
284
  */
180
- declare const useIsomorphicLayoutEffect: typeof useEffect;
285
+ declare const useIsomorphicLayoutEffect: typeof useLayoutEffect;
181
286
  //#endregion
182
287
  //#region src/hooks/use-matches-media-query.d.ts
183
288
  /**
184
- * React hook that subscribes to and returns the result of a CSS media query.
289
+ * React hook that subscribes to a CSS media query and returns whether it
290
+ * currently matches, re-rendering whenever the result changes.
185
291
  *
186
- * This hook uses `window.matchMedia` under the hood and leverages
187
- * `useSyncExternalStore` to stay compliant with React's concurrent rendering model.
292
+ * Uses `window.matchMedia` under the hood and `useSyncExternalStore` for
293
+ * compatibility with React's concurrent rendering model. Returns `false`
294
+ * on the server; during hydration React uses that server snapshot before
295
+ * updating to the client media-query value.
188
296
  *
189
- * @param {string} query - A valid CSS media query string (e.g., `(max-width: 768px)`).
297
+ * For common viewport breakpoint checks, prefer the more specific
298
+ * {@link useBreakpoint} or {@link useIsBelowBreakpoint} hooks.
190
299
  *
191
- * @returns {boolean} `true` if the media query currently matches, otherwise `false`.
300
+ * @param query - A valid CSS media query string
301
+ * (e.g. `"(max-width: 768px)"`, `"(prefers-color-scheme: dark)"`).
302
+ * @returns `true` if the media query currently matches, otherwise `false`.
192
303
  *
193
304
  * @example
194
- * // Detect if the user prefers a dark color scheme:
195
- * const isDarkMode = useMatchesMediaQuery("(prefers-color-scheme: dark)");
305
+ * // Detect if the user prefers a dark color scheme
306
+ * const prefersDark = useMatchesMediaQuery("(prefers-color-scheme: dark)");
196
307
  *
197
- * if (isDarkMode) {
198
- * document.body.classList.add("dark");
199
- * } else {
200
- * document.body.classList.remove("dark");
201
- * }
308
+ * return <div className={prefersDark ? "dark" : "light"}>Hello</div>;
309
+ *
310
+ * @example
311
+ * // Show a different layout on portrait orientation
312
+ * const isPortrait = useMatchesMediaQuery("(orientation: portrait)");
313
+ *
314
+ * return isPortrait ? <PortraitLayout /> : <LandscapeLayout />;
202
315
  */
203
316
  declare function useMatchesMediaQuery(query: string): boolean;
204
317
  //#endregion
205
318
  //#region src/hooks/use-prefers-reduced-motion.d.ts
206
319
  /**
207
- * Imperatively reads the current `prefers-reduced-motion` preference.
208
- * Useful in event handlers and plain functions where a hook cannot be called.
320
+ * Imperatively reads the current `prefers-reduced-motion` preference once at
321
+ * the time of the call.
322
+ *
323
+ * Useful in event handlers, animation entrypoints, or plain functions where
324
+ * a React hook cannot be called. Prefer {@link usePrefersReducedMotion}
325
+ * inside components — it subscribes to live changes.
209
326
  *
210
- * Returns `true` when the user has opted out of animations.
327
+ * @returns `true` when the user has opted out of animations or when called
328
+ * outside a browser environment (SSR), `false` when motion is allowed.
211
329
  *
212
330
  * @remarks
213
- * Returns `true` (reduce motion) when called outside a browser environment (SSR),
214
- * matching the conservative default of {@link usePrefersReducedMotion}.
331
+ * The conservative SSR default of `true` matches
332
+ * {@link usePrefersReducedMotion}: animations stay off until we can verify
333
+ * the user's preference on the client.
334
+ *
335
+ * @example
336
+ * // Skip a one-off entrance animation in a click handler
337
+ * function onOpen() {
338
+ * if (getPrefersReducedMotion()) {
339
+ * element.style.opacity = "1";
340
+ * return;
341
+ * }
342
+ * element.animate([{ opacity: 0 }, { opacity: 1 }], { duration: 200 });
343
+ * }
215
344
  */
216
345
  declare function getPrefersReducedMotion(): boolean;
217
346
  /**
218
- * Returns `true` when the user has opted out of animations (i.e., prefers reduced motion).
347
+ * React hook that subscribes to the user's `prefers-reduced-motion` media
348
+ * query and re-renders when it changes.
349
+ *
350
+ * Defaults to `true` (reduce motion) on the server and during the first
351
+ * client render to avoid animating before hydration. The initial client
352
+ * effect reads the *real* preference and updates state. The underlying
353
+ * media query used is `(prefers-reduced-motion: no-preference)` inverted —
354
+ * "if the system hasn't opted out, animations are allowed."
219
355
  *
220
- * Implementation notes:
221
- * - Uses the `(prefers-reduced-motion: no-preference)` media query and inverts it.
222
- * This keeps the “default” mental model explicit: if the system hasn’t opted out,
223
- * animations are allowed.
224
- * - Defaults to `true` (reduce motion) on the server/during SSR to avoid animating
225
- * before hydration. The initial client effect reads the *real* preference and updates state.
356
+ * @returns `true` when the user prefers reduced motion (animations should be
357
+ * shortened or skipped), `false` when full motion is acceptable.
358
+ *
359
+ * @remarks
360
+ * If you need to support very old browsers that lack
361
+ * `MediaQueryList.addEventListener`, consider falling back to
362
+ * `addListener` / `removeListener`.
226
363
  *
227
364
  * @example
228
365
  * // Conditionally shorten or skip transitions
229
- * const reduce = usePrefersReducedMotion();
230
- * const duration = reduce ? 0 : 200;
366
+ * const prefersReducedMotion = usePrefersReducedMotion();
367
+ * const duration = prefersReducedMotion ? 0 : 200;
231
368
  *
232
- * @remarks
233
- * If you need to support very old browsers that lack `MediaQueryList.addEventListener`,
234
- * consider falling back to `addListener/removeListener`.
369
+ * return <Modal transitionDuration={duration} />;
370
+ *
371
+ * @example
372
+ * // Disable an autoplaying carousel when motion is reduced
373
+ * const prefersReducedMotion = usePrefersReducedMotion();
374
+ *
375
+ * return <Carousel autoplay={!prefersReducedMotion} />;
235
376
  */
236
377
  declare function usePrefersReducedMotion(): boolean;
237
378
  //#endregion
238
379
  //#region src/hooks/use-random-stable-id.d.ts
239
380
  /**
240
- * Hook to generate a random, stable id.
241
- * This is similar to `useId`, but generates a stable id client side which can also
242
- * be used for css selectors and element ids.
381
+ * React hook that returns a random, stable id (e.g. `"mantle-a3f9k7q"`)
382
+ * suitable for DOM `id` attributes and `aria-*` references.
383
+ *
384
+ * Unlike React's built-in `useId`, the generated suffix does not contain
385
+ * special characters (`:`). The default id is safe to use directly in CSS
386
+ * selectors and `querySelector` calls; if you provide a custom `prefix`,
387
+ * keep it selector-safe or escape the final id with `CSS.escape()` before
388
+ * querying. The id is generated once for the lifetime of the component and
389
+ * is stable across re-renders, but a new value is produced when `prefix`
390
+ * changes.
391
+ *
392
+ * @param prefix - Optional string prepended to the generated suffix.
393
+ * Whitespace-only or empty values fall back to `"mantle"`. Use a
394
+ * selector-safe prefix if you plan to reference the id in CSS selectors
395
+ * without escaping. Defaults to `"mantle"`.
396
+ * @returns A string of the form `"<prefix>-<7-char-random>"`.
397
+ *
398
+ * @example
399
+ * // Associate a label with a custom input
400
+ * const id = useRandomStableId("email-input");
401
+ *
402
+ * return (
403
+ * <>
404
+ * <label htmlFor={id}>Email</label>
405
+ * <input id={id} type="email" />
406
+ * </>
407
+ * );
408
+ *
409
+ * @example
410
+ * // Use as an aria-controls reference
411
+ * const panelId = useRandomStableId("panel");
412
+ *
413
+ * return (
414
+ * <>
415
+ * <button aria-controls={panelId}>Toggle</button>
416
+ * <div id={panelId}>Panel contents</div>
417
+ * </>
418
+ * );
243
419
  */
244
420
  declare const useRandomStableId: (prefix?: string) => string;
245
421
  //#endregion
@@ -254,24 +430,38 @@ declare const useRandomStableId: (prefix?: string) => string;
254
430
  */
255
431
  type ScrollBehavior = "auto" | "smooth";
256
432
  /**
257
- * Returns a `ScrollBehavior` that respects the user's motion preference via `usePrefersReducedMotion`.
433
+ * React hook that returns a {@link ScrollBehavior} value (`"auto"` or
434
+ * `"smooth"`) that respects the user's motion preference.
258
435
  *
259
- * - When `usePrefersReducedMotion()` is `true`, returns `"auto"` (no animated scroll).
260
- * - Otherwise returns `"smooth"`.
436
+ * Internally calls {@link usePrefersReducedMotion}: when reduced motion is
437
+ * preferred, this returns `"auto"` (no animated scroll); otherwise it
438
+ * returns `"smooth"`. Pair this with `window.scrollTo`,
439
+ * `Element.scrollIntoView`, or any other scroll API that accepts a
440
+ * `behavior` option to avoid forcing animations on users who have opted
441
+ * out of motion. The conservative SSR default also prevents "first paint"
442
+ * scroll animations.
261
443
  *
262
- * Use this with `window.scrollTo`, `Element.scrollIntoView`, etc. It prevents
263
- * smooth-scrolling for users who opt out of motion and avoids SSR “first paint”
264
- * animations thanks to the hook’s conservative server default.
444
+ * @returns `"auto"` when the user prefers reduced motion, otherwise
445
+ * `"smooth"`.
265
446
  *
266
447
  * @example
267
- * // Scroll to top
448
+ * // Scroll to the top of the page on a button click
268
449
  * const behavior = useScrollBehavior();
269
- * window.scrollTo({ top: 0, behavior });
450
+ *
451
+ * return (
452
+ * <button onClick={() => window.scrollTo({ top: 0, behavior })}>
453
+ * Back to top
454
+ * </button>
455
+ * );
270
456
  *
271
457
  * @example
272
- * // Bring a section into view
458
+ * // Bring a referenced section into view
273
459
  * const behavior = useScrollBehavior();
274
- * sectionRef.current?.scrollIntoView({ behavior, block: "start" });
460
+ * const sectionRef = useRef<HTMLElement>(null);
461
+ *
462
+ * function focusSection() {
463
+ * sectionRef.current?.scrollIntoView({ behavior, block: "start" });
464
+ * }
275
465
  *
276
466
  * @see {@link usePrefersReducedMotion}
277
467
  * @see CSS `scroll-behavior` property (values: `"auto"`, `"smooth"`).
@@ -362,32 +552,66 @@ type UseUndoRedoReturn<T> = {
362
552
  redo: (current: T) => T | undefined;
363
553
  };
364
554
  /**
365
- * A generic undo/redo hook backed by a reducer.
366
- *
367
- * Maintains two stacks (undo and redo). Call `push` before mutating state
368
- * to snapshot the current value. Call `undo`/`redo` with the current value
369
- * to swap it with the previous/next snapshot.
555
+ * Generic undo/redo hook backed by a reducer that maintains two history
556
+ * stacks (undo and redo).
557
+ *
558
+ * The hook does not own your application state instead it helps you
559
+ * snapshot it. Call `push(snapshot)` *before* mutating state to capture
560
+ * the current value, then call `undo(current)` or `redo(current)` to swap
561
+ * `current` with the previous/next snapshot. Both `undo` and `redo` return
562
+ * the snapshot to apply, or `undefined` if their stack is empty. Pushing a
563
+ * new snapshot clears the redo stack, matching standard editor semantics.
564
+ *
565
+ * @typeParam T - The type of the value being snapshotted (e.g. a list of
566
+ * items, a serialized form value, etc.).
567
+ *
568
+ * @returns An object with the current undo/redo capability flags and
569
+ * actions:
570
+ * - `canUndo`: `true` when there is at least one snapshot on the undo
571
+ * stack.
572
+ * - `canRedo`: `true` when there is at least one snapshot on the redo
573
+ * stack.
574
+ * - `push(snapshot)`: Push a snapshot onto the undo stack and clear the
575
+ * redo stack. Call this *before* mutating state.
576
+ * - `undo(current)`: Pop the latest undo snapshot and return it; returns
577
+ * `undefined` when the undo stack is empty. The supplied `current` is
578
+ * pushed onto the redo stack so you can redo back to it.
579
+ * - `redo(current)`: Pop the latest redo snapshot and return it; returns
580
+ * `undefined` when the redo stack is empty. The supplied `current` is
581
+ * pushed onto the undo stack.
370
582
  *
371
583
  * @example
372
- * ```tsx
584
+ * // Snapshot before mutating, then wire up keyboard shortcuts
585
+ * const [items, setItems] = useState<string[]>([]);
373
586
  * const { push, undo, redo, canUndo, canRedo } = useUndoRedo<string[]>();
374
587
  *
375
588
  * function removeItem(item: string) {
376
- * push([...items]); // snapshot before mutation
377
- * setItems(items.filter((i) => i !== item));
589
+ * push(items); // snapshot before mutation
590
+ * setItems((prev) => prev.filter((entry) => entry !== item));
378
591
  * }
379
592
  *
380
- * function handleKeyDown(event: KeyboardEvent) {
381
- * if ((event.metaKey || event.ctrlKey) && event.key === "z" && !event.shiftKey) {
593
+ * function handleKeyDown(event: React.KeyboardEvent) {
594
+ * const cmd = event.metaKey || event.ctrlKey;
595
+ * if (cmd && event.key === "z" && !event.shiftKey) {
382
596
  * const previous = undo(items);
383
- * if (previous) setItems(previous);
597
+ * if (previous) {
598
+ * setItems(previous);
599
+ * }
384
600
  * }
385
- * if ((event.metaKey || event.ctrlKey) && (event.shiftKey && event.key === "z" || event.key === "y")) {
601
+ * if (cmd && ((event.shiftKey && event.key === "z") || event.key === "y")) {
386
602
  * const next = redo(items);
387
- * if (next) setItems(next);
603
+ * if (next) {
604
+ * setItems(next);
605
+ * }
388
606
  * }
389
607
  * }
390
- * ```
608
+ *
609
+ * return (
610
+ * <div tabIndex={0} onKeyDown={handleKeyDown}>
611
+ * <button disabled={!canUndo} onClick={() => { const previous = undo(items); if (previous) setItems(previous); }}>Undo</button>
612
+ * <button disabled={!canRedo} onClick={() => { const next = redo(items); if (next) setItems(next); }}>Redo</button>
613
+ * </div>
614
+ * );
391
615
  */
392
616
  declare function useUndoRedo<T>(): UseUndoRedoReturn<T>;
393
617
  //#endregion
package/dist/hooks.js CHANGED
@@ -1,2 +1,2 @@
1
- import{t as e}from"./use-matches-media-query-CojcYxlA.js";import{r as t}from"./browser-only-QPyyfLaB.js";import{n}from"./compose-refs-DFIaEnQH.js";import{t as r}from"./use-copy-to-clipboard-Ds9MsSNU.js";import{n as i,t as a}from"./use-prefers-reduced-motion-BcwST13S.js";import{t as o}from"./in-view-BXzPPdcl.js";import{useCallback as s,useEffect as c,useLayoutEffect as l,useMemo as u,useReducer as d,useRef as f,useState as p,useSyncExternalStore as m}from"react";const h=[`2xl`,`xl`,`lg`,`md`,`sm`,`xs`,`2xs`],g=[`default`,...h];function _(){return m(j,M,()=>`default`)}function v(e){return m(P(e),I(e),()=>!1)}const y={"2xl":`(min-width: 96rem)`,xl:`(min-width: 80rem)`,lg:`(min-width: 64rem)`,md:`(min-width: 48rem)`,sm:`(min-width: 40rem)`,xs:`(min-width: 30rem)`,"2xs":`(min-width: 22.5rem)`},b={"2xl":`(max-width: 95.99rem)`,xl:`(max-width: 79.99rem)`,lg:`(max-width: 63.99rem)`,md:`(max-width: 47.99rem)`,sm:`(max-width: 39.99rem)`,xs:`(max-width: 29.99rem)`,"2xs":`(max-width: 22.49rem)`};let x=null,S=null;function C(){return x||={"2xl":window.matchMedia(y[`2xl`]),xl:window.matchMedia(y.xl),lg:window.matchMedia(y.lg),md:window.matchMedia(y.md),sm:window.matchMedia(y.sm),xs:window.matchMedia(y.xs),"2xs":window.matchMedia(y[`2xs`])},x}function w(e){return S||={"2xl":window.matchMedia(b[`2xl`]),xl:window.matchMedia(b.xl),lg:window.matchMedia(b.lg),md:window.matchMedia(b.md),sm:window.matchMedia(b.sm),xs:window.matchMedia(b.xs),"2xs":window.matchMedia(b[`2xs`])},S[e]}let T=`default`;const E=new Set;let D=!1;function O(){let e=C();for(let t of h)if(e[t].matches)return t;return`default`}let k=!1;function A(){k||(k=!0,requestAnimationFrame(()=>{k=!1;let e=O();if(e!==T){T=e;for(let e of E)e()}}))}function j(e){if(E.add(e),!D){D=!0;let e=C();T=O();for(let t of Object.values(e))t.addEventListener(`change`,A)}return e(),()=>{if(E.delete(e),E.size===0&&D){D=!1;let e=C();for(let t of Object.values(e))t.removeEventListener(`change`,A)}}}function M(){return T}const N=new Map;function P(e){let t=N.get(e);return t||(t=t=>{let n=w(e),r=!1,i=()=>{r||(r=!0,requestAnimationFrame(()=>{r=!1,t()}))};return n.addEventListener(`change`,i),()=>{n.removeEventListener(`change`,i)}},N.set(e,t),t)}const F=new Map;function I(e){let t=F.get(e);return t||(t=()=>w(e).matches,F.set(e,t),t)}function L(e){let t=f(e);return c(()=>{t.current=e}),u(()=>((...e)=>t.current?.(...e)),[])}function R(e,t){let n=L(e),r=f(0);return c(()=>()=>window.clearTimeout(r.current),[]),s((...e)=>{window.clearTimeout(r.current),r.current=window.setTimeout(()=>n(...e),t.waitMs)},[n,t.waitMs])}const z=typeof window<`u`?l:c,B=(e=`mantle`)=>u(()=>V(e),[e]);function V(e=`mantle`){return[e.trim()||`mantle`,H()].join(`-`)}function H(){return Math.random().toString(36).substring(2,9)}function U(){let e=i();return u(()=>e?`auto`:`smooth`,[e])}function W(e,{root:t,margin:n,amount:r,once:i=!1,initial:a=!1}={}){let[s,l]=p(a);return c(()=>{if(!e.current||i&&s)return;function a(){return l(!0),i?void 0:()=>l(!1)}let c={root:t&&t.current||void 0,margin:n,amount:r};return o(e.current,a,c)},[t,e,n,i,r]),s}function G(e,t){switch(t.type){case`push`:return{undoStack:[...e.undoStack,t.snapshot],redoStack:[]};case`undo`:{if(e.undoStack.length===0)return e;let n=e.undoStack.slice(0,-1);return e.undoStack[e.undoStack.length-1]===void 0?e:{undoStack:n,redoStack:[...e.redoStack,t.current]}}case`redo`:{if(e.redoStack.length===0)return e;let n=e.redoStack.slice(0,-1);return e.redoStack[e.redoStack.length-1]===void 0?e:{undoStack:[...e.undoStack,t.current],redoStack:n}}}}function K(){let[e,t]=d(G,{undoStack:[],redoStack:[]}),n=s(e=>{t({type:`push`,snapshot:e})},[]),r=s(n=>{let r=e.undoStack[e.undoStack.length-1];if(r!==void 0)return t({type:`undo`,current:n}),r},[e.undoStack]),i=s(n=>{let r=e.redoStack[e.redoStack.length-1];if(r!==void 0)return t({type:`redo`,current:n}),r},[e.redoStack]);return u(()=>({canUndo:e.undoStack.length>0,canRedo:e.redoStack.length>0,push:n,undo:r,redo:i}),[e.undoStack.length,e.redoStack.length,n,r,i])}export{g as breakpoints,a as getPrefersReducedMotion,_ as useBreakpoint,L as useCallbackRef,n as useComposedRefs,r as useCopyToClipboard,R as useDebouncedCallback,W as useInView,v as useIsBelowBreakpoint,t as useIsHydrated,z as useIsomorphicLayoutEffect,e as useMatchesMediaQuery,i as usePrefersReducedMotion,B as useRandomStableId,U as useScrollBehavior,K as useUndoRedo};
1
+ import{t as e}from"./use-matches-media-query-CojcYxlA.js";import{r as t}from"./browser-only-QPyyfLaB.js";import{n}from"./compose-refs-DZ3cPi47.js";import{t as r}from"./use-copy-to-clipboard-C7vsjJe-.js";import{n as i,t as a}from"./use-prefers-reduced-motion-aXfsyo-k.js";import{t as o}from"./in-view-pia_SVdE.js";import{useCallback as s,useEffect as c,useLayoutEffect as l,useMemo as u,useReducer as d,useRef as f,useState as p,useSyncExternalStore as m}from"react";const h=[`2xl`,`xl`,`lg`,`md`,`sm`,`xs`,`2xs`],g=[`default`,...h];function _(){return m(j,M,()=>`default`)}function v(e){return m(P(e),I(e),()=>!1)}const y={"2xl":`(min-width: 96rem)`,xl:`(min-width: 80rem)`,lg:`(min-width: 64rem)`,md:`(min-width: 48rem)`,sm:`(min-width: 40rem)`,xs:`(min-width: 30rem)`,"2xs":`(min-width: 22.5rem)`},b={"2xl":`(max-width: 95.99rem)`,xl:`(max-width: 79.99rem)`,lg:`(max-width: 63.99rem)`,md:`(max-width: 47.99rem)`,sm:`(max-width: 39.99rem)`,xs:`(max-width: 29.99rem)`,"2xs":`(max-width: 22.49rem)`};let x=null,S=null;function C(){return x||={"2xl":window.matchMedia(y[`2xl`]),xl:window.matchMedia(y.xl),lg:window.matchMedia(y.lg),md:window.matchMedia(y.md),sm:window.matchMedia(y.sm),xs:window.matchMedia(y.xs),"2xs":window.matchMedia(y[`2xs`])},x}function w(e){return S||={"2xl":window.matchMedia(b[`2xl`]),xl:window.matchMedia(b.xl),lg:window.matchMedia(b.lg),md:window.matchMedia(b.md),sm:window.matchMedia(b.sm),xs:window.matchMedia(b.xs),"2xs":window.matchMedia(b[`2xs`])},S[e]}let T=`default`;const E=new Set;let D=!1;function O(){let e=C();for(let t of h)if(e[t].matches)return t;return`default`}let k=!1;function A(){k||(k=!0,requestAnimationFrame(()=>{k=!1;let e=O();if(e!==T){T=e;for(let e of E)e()}}))}function j(e){if(E.add(e),!D){D=!0;let e=C();T=O();for(let t of Object.values(e))t.addEventListener(`change`,A)}return e(),()=>{if(E.delete(e),E.size===0&&D){D=!1;let e=C();for(let t of Object.values(e))t.removeEventListener(`change`,A)}}}function M(){return T}const N=new Map;function P(e){let t=N.get(e);return t||(t=t=>{let n=w(e),r=!1,i=()=>{r||(r=!0,requestAnimationFrame(()=>{r=!1,t()}))};return n.addEventListener(`change`,i),()=>{n.removeEventListener(`change`,i)}},N.set(e,t),t)}const F=new Map;function I(e){let t=F.get(e);return t||(t=()=>w(e).matches,F.set(e,t),t)}function L(e){let t=f(e);return c(()=>{t.current=e}),u(()=>((...e)=>t.current?.(...e)),[])}function R(e,t){let n=L(e),r=f(0);return c(()=>()=>window.clearTimeout(r.current),[]),s((...e)=>{window.clearTimeout(r.current),r.current=window.setTimeout(()=>n(...e),t.waitMs)},[n,t.waitMs])}const z=typeof window<`u`?l:c,B=(e=`mantle`)=>u(()=>V(e),[e]);function V(e=`mantle`){return[e.trim()||`mantle`,H()].join(`-`)}function H(){return Math.random().toString(36).substring(2,9)}function U(){let e=i();return u(()=>e?`auto`:`smooth`,[e])}function W(e,{root:t,margin:n,amount:r,once:i=!1,initial:a=!1}={}){let[s,l]=p(a);return c(()=>{if(!e.current||i&&s)return;function a(){return l(!0),i?void 0:()=>l(!1)}let c={root:t&&t.current||void 0,margin:n,amount:r};return o(e.current,a,c)},[t,e,n,i,r]),s}function G(e,t){switch(t.type){case`push`:return{undoStack:[...e.undoStack,t.snapshot],redoStack:[]};case`undo`:{if(e.undoStack.length===0)return e;let n=e.undoStack.slice(0,-1);return e.undoStack[e.undoStack.length-1]===void 0?e:{undoStack:n,redoStack:[...e.redoStack,t.current]}}case`redo`:{if(e.redoStack.length===0)return e;let n=e.redoStack.slice(0,-1);return e.redoStack[e.redoStack.length-1]===void 0?e:{undoStack:[...e.undoStack,t.current],redoStack:n}}}}function K(){let[e,t]=d(G,{undoStack:[],redoStack:[]}),n=s(e=>{t({type:`push`,snapshot:e})},[]),r=s(n=>{let r=e.undoStack[e.undoStack.length-1];if(r!==void 0)return t({type:`undo`,current:n}),r},[e.undoStack]),i=s(n=>{let r=e.redoStack[e.redoStack.length-1];if(r!==void 0)return t({type:`redo`,current:n}),r},[e.redoStack]);return u(()=>({canUndo:e.undoStack.length>0,canRedo:e.redoStack.length>0,push:n,undo:r,redo:i}),[e.undoStack.length,e.redoStack.length,n,r,i])}export{g as breakpoints,a as getPrefersReducedMotion,_ as useBreakpoint,L as useCallbackRef,n as useComposedRefs,r as useCopyToClipboard,R as useDebouncedCallback,W as useInView,v as useIsBelowBreakpoint,t as useIsHydrated,z as useIsomorphicLayoutEffect,e as useMatchesMediaQuery,i as usePrefersReducedMotion,B as useRandomStableId,U as useScrollBehavior,K as useUndoRedo};
2
2
  //# sourceMappingURL=hooks.js.map