@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.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"hooks.js","names":[],"sources":["../src/hooks/use-breakpoint.tsx","../src/hooks/use-callback-ref.tsx","../src/hooks/use-debounced-callback.tsx","../src/hooks/use-isomorphic-layout-effect.tsx","../src/hooks/use-random-stable-id.tsx","../src/hooks/use-scroll-behavior.tsx","../src/hooks/use-in-view.tsx","../src/hooks/use-undo-redo.tsx"],"sourcesContent":["import { useSyncExternalStore } from \"react\";\n\n/**\n * Tailwind CSS breakpoints in descending order (largest → smallest).\n *\n * These correspond to Tailwind’s default `theme.screens` config and are used\n * to determine the current viewport size.\n *\n * @see https://tailwindcss.com/docs/screens\n *\n * @example\n * \"2xl\" // ≥96rem (1536px)\n * \"xl\" // ≥80rem (1280px)\n * \"lg\" // ≥64rem (1024px)\n * \"md\" // ≥48rem (768px)\n * \"sm\" // ≥40rem (640px)\n * \"xs\" // ≥30rem (480px)\n * \"2xs\" // ≥22.5rem (360px)\n */\nconst tailwindBreakpoints = [\"2xl\", \"xl\", \"lg\", \"md\", \"sm\", \"xs\", \"2xs\"] as const;\n\n/**\n * A valid Tailwind CSS breakpoint identifier.\n *\n * @example\n * const bp: TailwindBreakpoint = \"md\"; // ≥48rem (768px)\n *\n * @example\n * \"2xl\" // ≥96rem (1536px)\n * \"xl\" // ≥80rem (1280px)\n * \"lg\" // ≥64rem (1024px)\n * \"md\" // ≥48rem (768px)\n * \"sm\" // ≥40rem (640px)\n * \"xs\" // ≥30rem (480px)\n * \"2xs\" // ≥22.5rem (360px)\n */\ntype TailwindBreakpoint = (typeof tailwindBreakpoints)[number];\n\n/**\n * Mantle’s breakpoint set, extending Tailwind’s with `\"default\"`.\n *\n * `\"default\"` represents the base (0px and up) viewport,\n * useful for defining fallbacks or mobile-first styles.\n *\n * @example\n * \"default\" // ≥0rem (0px)\n * \"2xs\" // ≥22.5rem (360px)\n * \"xs\" // ≥30rem (480px)\n * \"sm\" // ≥40rem (640px)\n * \"md\" // ≥48rem (768px)\n * \"lg\" // ≥64rem (1024px)\n * \"xl\" // ≥80rem (1280px)\n * \"2xl\" // ≥96rem (1536px)\n */\nconst breakpoints = [\"default\", ...tailwindBreakpoints] as const;\n\n/**\n * A valid Mantle breakpoint identifier.\n *\n * Includes Tailwind’s standard breakpoints plus `\"default\"` for 0px+.\n *\n * @example\n * const bp: Breakpoint = \"default\"; // ≥0px\n *\n * @example\n * \"default\" // ≥0rem (0px)\n * \"2xs\" // ≥22.5rem (360px)\n * \"xs\" // ≥30rem (480px)\n * \"sm\" // ≥40rem (640px)\n * \"md\" // ≥48rem (768px)\n * \"lg\" // ≥64rem (1024px)\n * \"xl\" // ≥80rem (1280px)\n * \"2xl\" // ≥96rem (1536px)\n */\ntype Breakpoint = (typeof breakpoints)[number];\n\n/**\n * React hook that returns the current breakpoint based on the viewport width.\n *\n * Uses a singleton subscription to a set of min-width media queries and returns\n * the largest matching breakpoint. Designed for React 18+ with\n * `useSyncExternalStore`.\n *\n * @returns {Breakpoint} The current breakpoint that matches the viewport width.\n *\n * @example\n * const breakpoint = useBreakpoint();\n * if (breakpoint === \"lg\") {\n * // Do something for large screens and above\n * }\n */\nfunction useBreakpoint(): Breakpoint {\n\treturn useSyncExternalStore(\n\t\tsubscribeToBreakpointChanges,\n\t\tgetCurrentBreakpointSnapshot,\n\t\t() => \"default\", // SSR fallback\n\t);\n}\n\n/**\n * React hook that returns true if the current viewport width is below the specified breakpoint.\n *\n * This hook uses `window.matchMedia` with a max-width media query and leverages\n * `useSyncExternalStore` to stay compliant with React's concurrent rendering model.\n *\n * @param {TailwindBreakpoint} breakpoint - The breakpoint to check against (e.g., \"md\", \"lg\").\n *\n * @returns {boolean} `true` if the viewport width is below the breakpoint, otherwise `false`.\n *\n * @example\n * // Check if viewport is below medium (768px)\n * const isBelowMd = useIsBelowBreakpoint(\"md\");\n */\nfunction useIsBelowBreakpoint(breakpoint: TailwindBreakpoint): boolean {\n\treturn useSyncExternalStore(\n\t\tcreateBelowBreakpointSubscribe(breakpoint),\n\t\tcreateBelowBreakpointGetSnapshot(breakpoint),\n\t\t() => false, // SSR fallback - assume desktop\n\t);\n}\n\nexport {\n\t//,\n\tbreakpoints,\n\tuseBreakpoint,\n\tuseIsBelowBreakpoint,\n};\n\nexport type {\n\t//,\n\tBreakpoint,\n\tTailwindBreakpoint,\n};\n\n/**\n * A CSS media query string representing a minimum width in `rem` units.\n *\n * @example\n * const query: MinWidthQuery = \"(min-width: 48rem)\";\n *\n * @private\n */\ntype MinWidthQuery = `(min-width: ${number}rem)`;\n\n/**\n * A CSS media query string representing a maximum width in `rem` units.\n *\n * @example\n * const query: MaxWidthQuery = \"(max-width: 47.99rem)\";\n *\n * @private\n */\ntype MaxWidthQuery = `(max-width: ${number}rem)`;\n\n/**\n * Precomputed min-width media query strings for each Tailwind breakpoint.\n *\n * Using constants avoids template string work in hot paths and ensures type\n * safety against the `MinWidthQuery` template literal type.\n *\n * @remarks\n * These are expressed in `rem`. If your CSS breakpoints are in `px`, consider\n * aligning units to avoid JS/CSS drift when `html{font-size}` changes.\n *\n * @private\n */\nconst breakpointQueries = {\n\t\"2xl\": \"(min-width: 96rem)\" as const,\n\txl: \"(min-width: 80rem)\" as const,\n\tlg: \"(min-width: 64rem)\" as const,\n\tmd: \"(min-width: 48rem)\" as const,\n\tsm: \"(min-width: 40rem)\" as const,\n\txs: \"(min-width: 30rem)\" as const,\n\t\"2xs\": \"(min-width: 22.5rem)\" as const,\n} as const satisfies Record<TailwindBreakpoint, MinWidthQuery>;\n\n/**\n * Precomputed max-width media query strings used by `useIsBelowBreakpoint`.\n *\n * The `-0.01rem` offset avoids overlap at exact boundaries.\n *\n * @private\n */\nconst belowBreakpointQueries = {\n\t\"2xl\": \"(max-width: 95.99rem)\" as const, // 96 - 0.01\n\txl: \"(max-width: 79.99rem)\" as const, // 80 - 0.01\n\tlg: \"(max-width: 63.99rem)\" as const, // 64 - 0.01\n\tmd: \"(max-width: 47.99rem)\" as const, // 48 - 0.01\n\tsm: \"(max-width: 39.99rem)\" as const, // 40 - 0.01\n\txs: \"(max-width: 29.99rem)\" as const, // 30 - 0.01\n\t\"2xs\": \"(max-width: 22.49rem)\" as const, // 22.5 - 0.01\n} as const satisfies Record<TailwindBreakpoint, MaxWidthQuery>;\n\n/**\n * Lazily-initialized cache of `MediaQueryList` objects for min-width queries.\n *\n * Initialized on first access to remain SSR-safe (no `window` at import time).\n *\n * @private\n */\nlet minWidthMQLs: Record<TailwindBreakpoint, MediaQueryList> | null = null;\n\n/**\n * Lazily-initialized cache of `MediaQueryList` objects for max-width queries.\n *\n * Used by `useIsBelowBreakpoint`. Also SSR-safe by lazy access.\n *\n * @private\n */\nlet maxWidthMQLs: Record<TailwindBreakpoint, MediaQueryList> | null = null;\n\n/**\n * Get (and lazily create) the cached `MediaQueryList` objects for min-width queries.\n *\n * @returns A record of `MediaQueryList` keyed by Tailwind breakpoint.\n * @private\n */\nfunction getMinWidthMQLs(): Record<TailwindBreakpoint, MediaQueryList> {\n\tif (!minWidthMQLs) {\n\t\tminWidthMQLs = {\n\t\t\t\"2xl\": window.matchMedia(breakpointQueries[\"2xl\"]),\n\t\t\txl: window.matchMedia(breakpointQueries.xl),\n\t\t\tlg: window.matchMedia(breakpointQueries.lg),\n\t\t\tmd: window.matchMedia(breakpointQueries.md),\n\t\t\tsm: window.matchMedia(breakpointQueries.sm),\n\t\t\txs: window.matchMedia(breakpointQueries.xs),\n\t\t\t\"2xs\": window.matchMedia(breakpointQueries[\"2xs\"]),\n\t\t};\n\t}\n\treturn minWidthMQLs;\n}\n\n/**\n * Get (and lazily create) the cached `MediaQueryList` for a specific max-width breakpoint.\n *\n * @param breakpoint - Tailwind breakpoint identifier (e.g., \"md\").\n * @returns The corresponding `MediaQueryList`.\n * @private\n */\nfunction getMaxWidthMQL(breakpoint: TailwindBreakpoint): MediaQueryList {\n\tif (!maxWidthMQLs) {\n\t\tmaxWidthMQLs = {\n\t\t\t\"2xl\": window.matchMedia(belowBreakpointQueries[\"2xl\"]),\n\t\t\txl: window.matchMedia(belowBreakpointQueries.xl),\n\t\t\tlg: window.matchMedia(belowBreakpointQueries.lg),\n\t\t\tmd: window.matchMedia(belowBreakpointQueries.md),\n\t\t\tsm: window.matchMedia(belowBreakpointQueries.sm),\n\t\t\txs: window.matchMedia(belowBreakpointQueries.xs),\n\t\t\t\"2xs\": window.matchMedia(belowBreakpointQueries[\"2xs\"]),\n\t\t};\n\t}\n\treturn maxWidthMQLs[breakpoint];\n}\n\n/**\n * Current breakpoint value used by the singleton store backing `useBreakpoint`.\n *\n * Initialized to `\"default\"` and updated on media-query change events.\n *\n * @private\n */\nlet currentBreakpointValue: Breakpoint = \"default\";\n\n/**\n * Set of component listeners subscribed to the singleton breakpoint store.\n *\n * Each listener is invoked when the current breakpoint value changes.\n *\n * @private\n */\nconst breakpointListeners = new Set<() => void>();\n\n/**\n * Flag indicating whether global media-query listeners are currently attached.\n *\n * Prevents duplicate registrations and enables full teardown when unused.\n *\n * @private\n */\nlet breakpointSubscriptionActive = false;\n\n/**\n * Compute the current breakpoint by checking cached min-width MQLs\n * from largest to smallest.\n *\n * @returns {Breakpoint} The largest matching breakpoint, or `\"default\"`.\n * @private\n */\nfunction getCurrentBreakpoint(): Breakpoint {\n\tconst mqls = getMinWidthMQLs();\n\tfor (const breakpoint of tailwindBreakpoints) {\n\t\tif (mqls[breakpoint].matches) {\n\t\t\treturn breakpoint;\n\t\t}\n\t}\n\treturn \"default\";\n}\n\n/**\n * Update the current breakpoint value and notify all listeners.\n *\n * Uses `requestAnimationFrame` to coalesce rapid resize events and minimize\n * re-renders during active window resizing.\n *\n * @private\n */\nlet breakpointUpdatePending = false;\nfunction updateCurrentBreakpoint() {\n\tif (!breakpointUpdatePending) {\n\t\tbreakpointUpdatePending = true;\n\t\trequestAnimationFrame(() => {\n\t\t\tbreakpointUpdatePending = false;\n\t\t\tconst newBreakpoint = getCurrentBreakpoint();\n\t\t\tif (newBreakpoint !== currentBreakpointValue) {\n\t\t\t\tcurrentBreakpointValue = newBreakpoint;\n\t\t\t\tfor (const listener of breakpointListeners) {\n\t\t\t\t\tlistener();\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n}\n\n/**\n * Subscribe a component to breakpoint changes (singleton pattern).\n *\n * Ensures only one set of MQL listeners exists app-wide. Also reconciles the\n * `useSyncExternalStore` initial snapshot/subscribe race by invoking the\n * subscriber once on mount.\n *\n * @param callback - Listener invoked when the breakpoint value may have changed.\n * @returns Cleanup function to unsubscribe the listener.\n * @private\n */\nfunction subscribeToBreakpointChanges(callback: () => void) {\n\tbreakpointListeners.add(callback);\n\n\t// Attach global listeners once\n\tif (!breakpointSubscriptionActive) {\n\t\tbreakpointSubscriptionActive = true;\n\t\tconst mqls = getMinWidthMQLs();\n\n\t\t// Initialize current value synchronously\n\t\tcurrentBreakpointValue = getCurrentBreakpoint();\n\n\t\t// Attach listeners to all breakpoint MQLs\n\t\tfor (const mql of Object.values(mqls)) {\n\t\t\tmql.addEventListener(\"change\", updateCurrentBreakpoint);\n\t\t}\n\t}\n\n\t// Reconcile initial getSnapshot vs subscribe ordering\n\tcallback();\n\n\t// Cleanup\n\treturn () => {\n\t\tbreakpointListeners.delete(callback);\n\n\t\t// Tear down global listeners when no one is listening\n\t\tif (breakpointListeners.size === 0 && breakpointSubscriptionActive) {\n\t\t\tbreakpointSubscriptionActive = false;\n\t\t\tconst mqls = getMinWidthMQLs();\n\t\t\tfor (const mql of Object.values(mqls)) {\n\t\t\t\tmql.removeEventListener(\"change\", updateCurrentBreakpoint);\n\t\t\t}\n\t\t}\n\t};\n}\n\n/**\n * Return the current breakpoint value from the singleton store.\n *\n * Used as the `getSnapshot` for `useSyncExternalStore`.\n *\n * @returns {Breakpoint} The latest computed breakpoint.\n * @private\n */\nfunction getCurrentBreakpointSnapshot(): Breakpoint {\n\treturn currentBreakpointValue;\n}\n\n/**\n * Cached `subscribe` functions keyed by breakpoint.\n *\n * Without caching, `useSyncExternalStore` receives a new function reference on\n * every render, causing it to tear down and re-attach the MQL listener each\n * time — the primary source of resize sluggishness.\n *\n * @private\n */\nconst belowBreakpointSubscribeCache = new Map<\n\tTailwindBreakpoint,\n\t(callback: () => void) => () => void\n>();\n\n/**\n * Get (or create and cache) a `subscribe` function for a specific \"below\" breakpoint.\n *\n * Uses a cached `MediaQueryList` and rAF-throttled change handler to avoid\n * bursty updates during resize.\n *\n * @param breakpoint - Tailwind breakpoint identifier (e.g., \"lg\").\n * @returns A stable `subscribe` function suitable for `useSyncExternalStore`.\n * @private\n */\nfunction createBelowBreakpointSubscribe(breakpoint: TailwindBreakpoint) {\n\tlet cached = belowBreakpointSubscribeCache.get(breakpoint);\n\tif (cached) {\n\t\treturn cached;\n\t}\n\n\tcached = (callback: () => void) => {\n\t\tconst mediaQuery = getMaxWidthMQL(breakpoint);\n\n\t\t// rAF throttle the change callback during active resize\n\t\tlet pending = false;\n\t\tconst onChange = () => {\n\t\t\tif (!pending) {\n\t\t\t\tpending = true;\n\t\t\t\trequestAnimationFrame(() => {\n\t\t\t\t\tpending = false;\n\t\t\t\t\tcallback();\n\t\t\t\t});\n\t\t\t}\n\t\t};\n\n\t\tmediaQuery.addEventListener(\"change\", onChange);\n\t\treturn () => {\n\t\t\tmediaQuery.removeEventListener(\"change\", onChange);\n\t\t};\n\t};\n\n\tbelowBreakpointSubscribeCache.set(breakpoint, cached);\n\treturn cached;\n}\n\n/**\n * Cached `getSnapshot` functions keyed by breakpoint.\n *\n * Ensures `useSyncExternalStore` receives a referentially stable function,\n * preventing unnecessary subscription churn.\n *\n * @private\n */\nconst belowBreakpointSnapshotCache = new Map<TailwindBreakpoint, () => boolean>();\n\n/**\n * Get (or create and cache) a `getSnapshot` function for a specific \"below\" breakpoint.\n *\n * Uses the cached `MediaQueryList` for the target breakpoint.\n *\n * @param breakpoint - Tailwind breakpoint identifier (e.g., \"lg\").\n * @returns A stable function that returns `true` when the viewport is below the breakpoint.\n * @private\n */\nfunction createBelowBreakpointGetSnapshot(breakpoint: TailwindBreakpoint) {\n\tlet cached = belowBreakpointSnapshotCache.get(breakpoint);\n\tif (cached) {\n\t\treturn cached;\n\t}\n\n\tcached = () => {\n\t\tconst mediaQuery = getMaxWidthMQL(breakpoint);\n\t\treturn mediaQuery.matches;\n\t};\n\n\tbelowBreakpointSnapshotCache.set(breakpoint, cached);\n\treturn cached;\n}\n","import { useEffect, useMemo, useRef } from \"react\";\n\n/**\n * Returns a memoized callback that will always refer to the latest callback\n * passed to the hook.\n *\n * This is useful when you want to pass a callback which may or may not be\n * memoized (have a stable identity) to a child component that will be updated\n * without causing the child component to re-render.\n */\nfunction useCallbackRef<T extends (...args: unknown[]) => unknown>(callback: T | undefined): T {\n\tconst callbackRef = useRef(callback);\n\n\tuseEffect(() => {\n\t\tcallbackRef.current = callback;\n\t});\n\n\treturn useMemo(() => ((...args) => callbackRef.current?.(...args)) as T, []);\n}\n\nexport {\n\t//,\n\tuseCallbackRef,\n};\n","import { useCallback, useEffect, useRef } from \"react\";\nimport { useCallbackRef } from \"./use-callback-ref.js\";\n\ntype Options = {\n\t/**\n\t * The delay in milliseconds to wait before calling the callback.\n\t */\n\twaitMs: number;\n};\n\n/**\n * Create a debounced version of a callback function.\n *\n * It allows you to delay the execution of a function until a certain period of\n * inactivity has passed (the `options.waitMs`), which can be useful for limiting rapid\n * invocations of a function (like in search inputs or button clicks)\n *\n * Note: The debounced callback will always refer to the latest callback passed\n * even without memoization, so it's stable and safe to use in dependency arrays.\n */\nfunction useDebouncedCallback<T extends (...args: unknown[]) => unknown>(\n\tcallbackFn: T,\n\toptions: Options,\n) {\n\tconst stableCallbackFn = useCallbackRef(callbackFn);\n\tconst debounceTimerRef = useRef(0);\n\tuseEffect(() => () => window.clearTimeout(debounceTimerRef.current), []);\n\n\treturn useCallback(\n\t\t(...args: Parameters<T>) => {\n\t\t\twindow.clearTimeout(debounceTimerRef.current);\n\t\t\tdebounceTimerRef.current = window.setTimeout(() => stableCallbackFn(...args), options.waitMs);\n\t\t},\n\t\t[stableCallbackFn, options.waitMs],\n\t);\n}\n\nexport {\n\t//,\n\tuseDebouncedCallback,\n};\n","import { useEffect, useLayoutEffect } from \"react\";\n\n/**\n * useIsomorphicLayoutEffect is a hook that uses useLayoutEffect on the client and useEffect on the server.\n */\nexport const useIsomorphicLayoutEffect =\n\ttypeof window !== \"undefined\" ? useLayoutEffect : useEffect;\n","import { useMemo } from \"react\";\n\n/**\n * Hook to generate a random, stable id.\n * This is similar to `useId`, but generates a stable id client side which can also\n * be used for css selectors and element ids.\n */\nconst useRandomStableId = (prefix = \"mantle\") => useMemo(() => randomStableId(prefix), [prefix]);\n\nexport {\n\t//,\n\tuseRandomStableId,\n};\n\nfunction randomStableId(prefix = \"mantle\") {\n\tconst _prefix = prefix.trim() || \"mantle\";\n\treturn [_prefix, randomPostfix()].join(\"-\");\n}\n\nfunction randomPostfix() {\n\treturn Math.random().toString(36).substring(2, 9);\n}\n","import { useMemo } from \"react\";\nimport { usePrefersReducedMotion } from \"./use-prefers-reduced-motion.js\";\n\n/**\n * `scroll-behavior` values:\n *\n * - `\"auto\"` — scrolling happens instantly (no animation).\n * - `\"smooth\"` — scrolling animates smoothly using a user-agent–defined easing and duration.\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-behavior#values\n */\nexport type ScrollBehavior = \"auto\" | \"smooth\";\n\n/**\n * Returns a `ScrollBehavior` that respects the user's motion preference via `usePrefersReducedMotion`.\n *\n * - When `usePrefersReducedMotion()` is `true`, returns `\"auto\"` (no animated scroll).\n * - Otherwise returns `\"smooth\"`.\n *\n * Use this with `window.scrollTo`, `Element.scrollIntoView`, etc. It prevents\n * smooth-scrolling for users who opt out of motion and avoids SSR “first paint”\n * animations thanks to the hook’s conservative server default.\n *\n * @example\n * // Scroll to top\n * const behavior = useScrollBehavior();\n * window.scrollTo({ top: 0, behavior });\n *\n * @example\n * // Bring a section into view\n * const behavior = useScrollBehavior();\n * sectionRef.current?.scrollIntoView({ behavior, block: \"start\" });\n *\n * @see {@link usePrefersReducedMotion}\n * @see CSS `scroll-behavior` property (values: `\"auto\"`, `\"smooth\"`).\n */\nexport function useScrollBehavior(): ScrollBehavior {\n\tconst prefersReducedMotion = usePrefersReducedMotion();\n\n\treturn useMemo(() => (prefersReducedMotion ? \"auto\" : \"smooth\"), [prefersReducedMotion]);\n}\n","\"use client\";\n\nimport { type RefObject, useEffect, useState } from \"react\";\nimport type { InViewOptions, MarginType } from \"../utils/in-view.js\";\nimport { inView } from \"../utils/in-view.js\";\n\n/**\n * Options for the `useInView` hook.\n */\ntype UseInViewOptions = {\n\t/**\n\t * A ref to a scrollable container element to use as the intersection root.\n\t * Defaults to the browser viewport.\n\t */\n\troot?: RefObject<Element | null>;\n\n\t/**\n\t * Expand or contract the detected area from each side of the root's bounding box.\n\t * Uses the same syntax as the CSS `margin` shorthand (e.g. `\"10px\"`, `\"10% 20px\"`).\n\t */\n\tmargin?: MarginType;\n\n\t/**\n\t * How much of the element must be visible before it is considered in view.\n\t * - `\"some\"` (default): Any part of the element is visible.\n\t * - `\"all\"`: The entire element is visible.\n\t * - `number`: An intersection ratio between `0` and `1` (e.g. `0.5` for 50%).\n\t */\n\tamount?: \"some\" | \"all\" | number;\n\n\t/**\n\t * If `true`, stop observing once the element enters the viewport for the\n\t * first time. Useful for one-shot entrance animations.\n\t * Defaults to `false`.\n\t */\n\tonce?: boolean;\n\n\t/**\n\t * The initial visibility state returned before the observer has attached.\n\t * Defaults to `false`.\n\t */\n\tinitial?: boolean;\n};\n\n/**\n * React hook that tracks whether a DOM element is visible within the viewport\n * (or a scrollable container) using the `IntersectionObserver` API.\n *\n * @param ref - A ref attached to the element to observe.\n * @param options - Options controlling the scroll root, margin, threshold,\n * initial state, and one-time detection.\n * @returns `true` if the element is currently in view, otherwise `false`.\n *\n * @example\n * // Basic usage\n * const ref = useRef<HTMLDivElement>(null);\n * const isInView = useInView(ref);\n *\n * return <div ref={ref}>{isInView ? \"Visible!\" : \"Hidden\"}</div>;\n *\n * @example\n * // Trigger once when the element first enters the viewport\n * const ref = useRef<HTMLDivElement>(null);\n * const isInView = useInView(ref, { once: true });\n *\n * return (\n * <div\n * ref={ref}\n * style={{ opacity: isInView ? 1 : 0, transition: \"opacity 0.5s\" }}\n * />\n * );\n *\n * @example\n * // Require 50% of the element to be visible\n * const ref = useRef<HTMLDivElement>(null);\n * const isInView = useInView(ref, { amount: 0.5 });\n */\nfunction useInView(\n\tref: RefObject<Element | null>,\n\t{ root, margin, amount, once = false, initial = false }: UseInViewOptions = {},\n): boolean {\n\tconst [isInView, setInView] = useState(initial);\n\n\tuseEffect(() => {\n\t\tif (!ref.current || (once && isInView)) {\n\t\t\treturn;\n\t\t}\n\n\t\tfunction onEnter() {\n\t\t\tsetInView(true);\n\t\t\treturn once ? undefined : () => setInView(false);\n\t\t}\n\n\t\tconst options: InViewOptions = {\n\t\t\troot: (root && root.current) || undefined,\n\t\t\tmargin,\n\t\t\tamount,\n\t\t};\n\n\t\treturn inView(ref.current, onEnter, options);\n\t\t/**\n\t\t * Intentionally omit `isInView` from deps. The effect must only re-run\n\t\t * when the observation parameters change, not when visibility changes.\n\t\t * Including `isInView` would restart the observer (disconnect + reconnect)\n\t\t * on every enter/leave event, causing wasteful churn for the common\n\t\t * `once=false` case.\n\t\t */\n\t\t// oxlint-disable-next-line react-hooks/exhaustive-deps\n\t}, [root, ref, margin, once, amount]);\n\n\treturn isInView;\n}\n\nexport { useInView };\nexport type { UseInViewOptions };\n","import { useCallback, useMemo, useReducer } from \"react\";\n\ntype UndoRedoState<T> = {\n\tundoStack: T[];\n\tredoStack: T[];\n};\n\ntype UndoRedoAction<T> =\n\t| { type: \"push\"; snapshot: T }\n\t| { type: \"undo\"; current: T }\n\t| { type: \"redo\"; current: T };\n\nfunction undoRedoReducer<T>(state: UndoRedoState<T>, action: UndoRedoAction<T>): UndoRedoState<T> {\n\tswitch (action.type) {\n\t\tcase \"push\": {\n\t\t\treturn {\n\t\t\t\tundoStack: [...state.undoStack, action.snapshot],\n\t\t\t\tredoStack: [],\n\t\t\t};\n\t\t}\n\t\tcase \"undo\": {\n\t\t\tif (state.undoStack.length === 0) {\n\t\t\t\treturn state;\n\t\t\t}\n\t\t\tconst undoStack = state.undoStack.slice(0, -1);\n\t\t\tconst previous = state.undoStack[state.undoStack.length - 1];\n\t\t\tif (previous === undefined) {\n\t\t\t\treturn state;\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tundoStack,\n\t\t\t\tredoStack: [...state.redoStack, action.current],\n\t\t\t};\n\t\t}\n\t\tcase \"redo\": {\n\t\t\tif (state.redoStack.length === 0) {\n\t\t\t\treturn state;\n\t\t\t}\n\t\t\tconst redoStack = state.redoStack.slice(0, -1);\n\t\t\tconst next = state.redoStack[state.redoStack.length - 1];\n\t\t\tif (next === undefined) {\n\t\t\t\treturn state;\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tundoStack: [...state.undoStack, action.current],\n\t\t\t\tredoStack,\n\t\t\t};\n\t\t}\n\t}\n}\n\ntype UseUndoRedoReturn<T> = {\n\t/** Whether there are actions to undo. */\n\tcanUndo: boolean;\n\t/** Whether there are actions to redo. */\n\tcanRedo: boolean;\n\t/** Push a snapshot onto the undo stack. Clears the redo stack. */\n\tpush: (snapshot: T) => void;\n\t/** Pop the last snapshot from the undo stack. Returns `undefined` if empty. */\n\tundo: (current: T) => T | undefined;\n\t/** Pop the last snapshot from the redo stack. Returns `undefined` if empty. */\n\tredo: (current: T) => T | undefined;\n};\n\n/**\n * A generic undo/redo hook backed by a reducer.\n *\n * Maintains two stacks (undo and redo). Call `push` before mutating state\n * to snapshot the current value. Call `undo`/`redo` with the current value\n * to swap it with the previous/next snapshot.\n *\n * @example\n * ```tsx\n * const { push, undo, redo, canUndo, canRedo } = useUndoRedo<string[]>();\n *\n * function removeItem(item: string) {\n * push([...items]); // snapshot before mutation\n * setItems(items.filter((i) => i !== item));\n * }\n *\n * function handleKeyDown(event: KeyboardEvent) {\n * if ((event.metaKey || event.ctrlKey) && event.key === \"z\" && !event.shiftKey) {\n * const previous = undo(items);\n * if (previous) setItems(previous);\n * }\n * if ((event.metaKey || event.ctrlKey) && (event.shiftKey && event.key === \"z\" || event.key === \"y\")) {\n * const next = redo(items);\n * if (next) setItems(next);\n * }\n * }\n * ```\n */\nfunction useUndoRedo<T>(): UseUndoRedoReturn<T> {\n\tconst [state, dispatch] = useReducer(undoRedoReducer<T>, {\n\t\tundoStack: [],\n\t\tredoStack: [],\n\t});\n\n\tconst push = useCallback((snapshot: T) => {\n\t\tdispatch({ type: \"push\", snapshot });\n\t}, []);\n\n\tconst undo = useCallback(\n\t\t(current: T): T | undefined => {\n\t\t\tconst previous = state.undoStack[state.undoStack.length - 1];\n\t\t\tif (previous === undefined) {\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\tdispatch({ type: \"undo\", current });\n\t\t\treturn previous;\n\t\t},\n\t\t[state.undoStack],\n\t);\n\n\tconst redo = useCallback(\n\t\t(current: T): T | undefined => {\n\t\t\tconst next = state.redoStack[state.redoStack.length - 1];\n\t\t\tif (next === undefined) {\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\tdispatch({ type: \"redo\", current });\n\t\t\treturn next;\n\t\t},\n\t\t[state.redoStack],\n\t);\n\n\treturn useMemo(\n\t\t() => ({\n\t\t\tcanUndo: state.undoStack.length > 0,\n\t\t\tcanRedo: state.redoStack.length > 0,\n\t\t\tpush,\n\t\t\tundo,\n\t\t\tredo,\n\t\t}),\n\t\t[state.undoStack.length, state.redoStack.length, push, undo, redo],\n\t);\n}\n\nexport {\n\t//,\n\tuseUndoRedo,\n};\n\nexport type {\n\t//,\n\tUseUndoRedoReturn,\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"hooks.js","names":[],"sources":["../src/hooks/use-breakpoint.tsx","../src/hooks/use-callback-ref.tsx","../src/hooks/use-debounced-callback.tsx","../src/hooks/use-isomorphic-layout-effect.tsx","../src/hooks/use-random-stable-id.tsx","../src/hooks/use-scroll-behavior.tsx","../src/hooks/use-in-view.tsx","../src/hooks/use-undo-redo.tsx"],"sourcesContent":["import { useSyncExternalStore } from \"react\";\n\n/**\n * Tailwind CSS breakpoints in descending order (largest → smallest).\n *\n * These correspond to Tailwind’s default `theme.screens` config and are used\n * to determine the current viewport size.\n *\n * @see https://tailwindcss.com/docs/screens\n *\n * @example\n * \"2xl\" // ≥96rem (1536px)\n * \"xl\" // ≥80rem (1280px)\n * \"lg\" // ≥64rem (1024px)\n * \"md\" // ≥48rem (768px)\n * \"sm\" // ≥40rem (640px)\n * \"xs\" // ≥30rem (480px)\n * \"2xs\" // ≥22.5rem (360px)\n */\nconst tailwindBreakpoints = [\"2xl\", \"xl\", \"lg\", \"md\", \"sm\", \"xs\", \"2xs\"] as const;\n\n/**\n * A valid Tailwind CSS breakpoint identifier.\n *\n * @example\n * const bp: TailwindBreakpoint = \"md\"; // ≥48rem (768px)\n *\n * @example\n * \"2xl\" // ≥96rem (1536px)\n * \"xl\" // ≥80rem (1280px)\n * \"lg\" // ≥64rem (1024px)\n * \"md\" // ≥48rem (768px)\n * \"sm\" // ≥40rem (640px)\n * \"xs\" // ≥30rem (480px)\n * \"2xs\" // ≥22.5rem (360px)\n */\ntype TailwindBreakpoint = (typeof tailwindBreakpoints)[number];\n\n/**\n * Mantle’s breakpoint set, extending Tailwind’s with `\"default\"`.\n *\n * `\"default\"` represents the base (0px and up) viewport,\n * useful for defining fallbacks or mobile-first styles.\n *\n * @example\n * \"default\" // ≥0rem (0px)\n * \"2xs\" // ≥22.5rem (360px)\n * \"xs\" // ≥30rem (480px)\n * \"sm\" // ≥40rem (640px)\n * \"md\" // ≥48rem (768px)\n * \"lg\" // ≥64rem (1024px)\n * \"xl\" // ≥80rem (1280px)\n * \"2xl\" // ≥96rem (1536px)\n */\nconst breakpoints = [\"default\", ...tailwindBreakpoints] as const;\n\n/**\n * A valid Mantle breakpoint identifier.\n *\n * Includes Tailwind’s standard breakpoints plus `\"default\"` for 0px+.\n *\n * @example\n * const bp: Breakpoint = \"default\"; // ≥0px\n *\n * @example\n * \"default\" // ≥0rem (0px)\n * \"2xs\" // ≥22.5rem (360px)\n * \"xs\" // ≥30rem (480px)\n * \"sm\" // ≥40rem (640px)\n * \"md\" // ≥48rem (768px)\n * \"lg\" // ≥64rem (1024px)\n * \"xl\" // ≥80rem (1280px)\n * \"2xl\" // ≥96rem (1536px)\n */\ntype Breakpoint = (typeof breakpoints)[number];\n\n/**\n * React hook that returns the current breakpoint based on the viewport width.\n *\n * Uses a singleton subscription to a set of min-width media queries and returns\n * the largest matching breakpoint. Designed for React 18+ with\n * `useSyncExternalStore`.\n *\n * @returns {Breakpoint} The current breakpoint that matches the viewport width.\n *\n * @example\n * const breakpoint = useBreakpoint();\n * if (breakpoint === \"lg\") {\n * // Do something for large screens and above\n * }\n */\nfunction useBreakpoint(): Breakpoint {\n\treturn useSyncExternalStore(\n\t\tsubscribeToBreakpointChanges,\n\t\tgetCurrentBreakpointSnapshot,\n\t\t() => \"default\", // SSR fallback\n\t);\n}\n\n/**\n * React hook that returns true if the current viewport width is below the specified breakpoint.\n *\n * This hook uses `window.matchMedia` with a max-width media query and leverages\n * `useSyncExternalStore` to stay compliant with React's concurrent rendering model.\n *\n * @param {TailwindBreakpoint} breakpoint - The breakpoint to check against (e.g., \"md\", \"lg\").\n *\n * @returns {boolean} `true` if the viewport width is below the breakpoint, otherwise `false`.\n *\n * @example\n * // Check if viewport is below medium (768px)\n * const isBelowMd = useIsBelowBreakpoint(\"md\");\n */\nfunction useIsBelowBreakpoint(breakpoint: TailwindBreakpoint): boolean {\n\treturn useSyncExternalStore(\n\t\tcreateBelowBreakpointSubscribe(breakpoint),\n\t\tcreateBelowBreakpointGetSnapshot(breakpoint),\n\t\t() => false, // SSR fallback - assume desktop\n\t);\n}\n\nexport {\n\t//,\n\tbreakpoints,\n\tuseBreakpoint,\n\tuseIsBelowBreakpoint,\n};\n\nexport type {\n\t//,\n\tBreakpoint,\n\tTailwindBreakpoint,\n};\n\n/**\n * A CSS media query string representing a minimum width in `rem` units.\n *\n * @example\n * const query: MinWidthQuery = \"(min-width: 48rem)\";\n *\n * @private\n */\ntype MinWidthQuery = `(min-width: ${number}rem)`;\n\n/**\n * A CSS media query string representing a maximum width in `rem` units.\n *\n * @example\n * const query: MaxWidthQuery = \"(max-width: 47.99rem)\";\n *\n * @private\n */\ntype MaxWidthQuery = `(max-width: ${number}rem)`;\n\n/**\n * Precomputed min-width media query strings for each Tailwind breakpoint.\n *\n * Using constants avoids template string work in hot paths and ensures type\n * safety against the `MinWidthQuery` template literal type.\n *\n * @remarks\n * These are expressed in `rem`. If your CSS breakpoints are in `px`, consider\n * aligning units to avoid JS/CSS drift when `html{font-size}` changes.\n *\n * @private\n */\nconst breakpointQueries = {\n\t\"2xl\": \"(min-width: 96rem)\" as const,\n\txl: \"(min-width: 80rem)\" as const,\n\tlg: \"(min-width: 64rem)\" as const,\n\tmd: \"(min-width: 48rem)\" as const,\n\tsm: \"(min-width: 40rem)\" as const,\n\txs: \"(min-width: 30rem)\" as const,\n\t\"2xs\": \"(min-width: 22.5rem)\" as const,\n} as const satisfies Record<TailwindBreakpoint, MinWidthQuery>;\n\n/**\n * Precomputed max-width media query strings used by `useIsBelowBreakpoint`.\n *\n * The `-0.01rem` offset avoids overlap at exact boundaries.\n *\n * @private\n */\nconst belowBreakpointQueries = {\n\t\"2xl\": \"(max-width: 95.99rem)\" as const, // 96 - 0.01\n\txl: \"(max-width: 79.99rem)\" as const, // 80 - 0.01\n\tlg: \"(max-width: 63.99rem)\" as const, // 64 - 0.01\n\tmd: \"(max-width: 47.99rem)\" as const, // 48 - 0.01\n\tsm: \"(max-width: 39.99rem)\" as const, // 40 - 0.01\n\txs: \"(max-width: 29.99rem)\" as const, // 30 - 0.01\n\t\"2xs\": \"(max-width: 22.49rem)\" as const, // 22.5 - 0.01\n} as const satisfies Record<TailwindBreakpoint, MaxWidthQuery>;\n\n/**\n * Lazily-initialized cache of `MediaQueryList` objects for min-width queries.\n *\n * Initialized on first access to remain SSR-safe (no `window` at import time).\n *\n * @private\n */\nlet minWidthMQLs: Record<TailwindBreakpoint, MediaQueryList> | null = null;\n\n/**\n * Lazily-initialized cache of `MediaQueryList` objects for max-width queries.\n *\n * Used by `useIsBelowBreakpoint`. Also SSR-safe by lazy access.\n *\n * @private\n */\nlet maxWidthMQLs: Record<TailwindBreakpoint, MediaQueryList> | null = null;\n\n/**\n * Get (and lazily create) the cached `MediaQueryList` objects for min-width queries.\n *\n * @returns A record of `MediaQueryList` keyed by Tailwind breakpoint.\n * @private\n */\nfunction getMinWidthMQLs(): Record<TailwindBreakpoint, MediaQueryList> {\n\tif (!minWidthMQLs) {\n\t\tminWidthMQLs = {\n\t\t\t\"2xl\": window.matchMedia(breakpointQueries[\"2xl\"]),\n\t\t\txl: window.matchMedia(breakpointQueries.xl),\n\t\t\tlg: window.matchMedia(breakpointQueries.lg),\n\t\t\tmd: window.matchMedia(breakpointQueries.md),\n\t\t\tsm: window.matchMedia(breakpointQueries.sm),\n\t\t\txs: window.matchMedia(breakpointQueries.xs),\n\t\t\t\"2xs\": window.matchMedia(breakpointQueries[\"2xs\"]),\n\t\t};\n\t}\n\treturn minWidthMQLs;\n}\n\n/**\n * Get (and lazily create) the cached `MediaQueryList` for a specific max-width breakpoint.\n *\n * @param breakpoint - Tailwind breakpoint identifier (e.g., \"md\").\n * @returns The corresponding `MediaQueryList`.\n * @private\n */\nfunction getMaxWidthMQL(breakpoint: TailwindBreakpoint): MediaQueryList {\n\tif (!maxWidthMQLs) {\n\t\tmaxWidthMQLs = {\n\t\t\t\"2xl\": window.matchMedia(belowBreakpointQueries[\"2xl\"]),\n\t\t\txl: window.matchMedia(belowBreakpointQueries.xl),\n\t\t\tlg: window.matchMedia(belowBreakpointQueries.lg),\n\t\t\tmd: window.matchMedia(belowBreakpointQueries.md),\n\t\t\tsm: window.matchMedia(belowBreakpointQueries.sm),\n\t\t\txs: window.matchMedia(belowBreakpointQueries.xs),\n\t\t\t\"2xs\": window.matchMedia(belowBreakpointQueries[\"2xs\"]),\n\t\t};\n\t}\n\treturn maxWidthMQLs[breakpoint];\n}\n\n/**\n * Current breakpoint value used by the singleton store backing `useBreakpoint`.\n *\n * Initialized to `\"default\"` and updated on media-query change events.\n *\n * @private\n */\nlet currentBreakpointValue: Breakpoint = \"default\";\n\n/**\n * Set of component listeners subscribed to the singleton breakpoint store.\n *\n * Each listener is invoked when the current breakpoint value changes.\n *\n * @private\n */\nconst breakpointListeners = new Set<() => void>();\n\n/**\n * Flag indicating whether global media-query listeners are currently attached.\n *\n * Prevents duplicate registrations and enables full teardown when unused.\n *\n * @private\n */\nlet breakpointSubscriptionActive = false;\n\n/**\n * Compute the current breakpoint by checking cached min-width MQLs\n * from largest to smallest.\n *\n * @returns {Breakpoint} The largest matching breakpoint, or `\"default\"`.\n * @private\n */\nfunction getCurrentBreakpoint(): Breakpoint {\n\tconst mqls = getMinWidthMQLs();\n\tfor (const breakpoint of tailwindBreakpoints) {\n\t\tif (mqls[breakpoint].matches) {\n\t\t\treturn breakpoint;\n\t\t}\n\t}\n\treturn \"default\";\n}\n\n/**\n * Update the current breakpoint value and notify all listeners.\n *\n * Uses `requestAnimationFrame` to coalesce rapid resize events and minimize\n * re-renders during active window resizing.\n *\n * @private\n */\nlet breakpointUpdatePending = false;\nfunction updateCurrentBreakpoint() {\n\tif (!breakpointUpdatePending) {\n\t\tbreakpointUpdatePending = true;\n\t\trequestAnimationFrame(() => {\n\t\t\tbreakpointUpdatePending = false;\n\t\t\tconst newBreakpoint = getCurrentBreakpoint();\n\t\t\tif (newBreakpoint !== currentBreakpointValue) {\n\t\t\t\tcurrentBreakpointValue = newBreakpoint;\n\t\t\t\tfor (const listener of breakpointListeners) {\n\t\t\t\t\tlistener();\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n}\n\n/**\n * Subscribe a component to breakpoint changes (singleton pattern).\n *\n * Ensures only one set of MQL listeners exists app-wide. Also reconciles the\n * `useSyncExternalStore` initial snapshot/subscribe race by invoking the\n * subscriber once on mount.\n *\n * @param callback - Listener invoked when the breakpoint value may have changed.\n * @returns Cleanup function to unsubscribe the listener.\n * @private\n */\nfunction subscribeToBreakpointChanges(callback: () => void) {\n\tbreakpointListeners.add(callback);\n\n\t// Attach global listeners once\n\tif (!breakpointSubscriptionActive) {\n\t\tbreakpointSubscriptionActive = true;\n\t\tconst mqls = getMinWidthMQLs();\n\n\t\t// Initialize current value synchronously\n\t\tcurrentBreakpointValue = getCurrentBreakpoint();\n\n\t\t// Attach listeners to all breakpoint MQLs\n\t\tfor (const mql of Object.values(mqls)) {\n\t\t\tmql.addEventListener(\"change\", updateCurrentBreakpoint);\n\t\t}\n\t}\n\n\t// Reconcile initial getSnapshot vs subscribe ordering\n\tcallback();\n\n\t// Cleanup\n\treturn () => {\n\t\tbreakpointListeners.delete(callback);\n\n\t\t// Tear down global listeners when no one is listening\n\t\tif (breakpointListeners.size === 0 && breakpointSubscriptionActive) {\n\t\t\tbreakpointSubscriptionActive = false;\n\t\t\tconst mqls = getMinWidthMQLs();\n\t\t\tfor (const mql of Object.values(mqls)) {\n\t\t\t\tmql.removeEventListener(\"change\", updateCurrentBreakpoint);\n\t\t\t}\n\t\t}\n\t};\n}\n\n/**\n * Return the current breakpoint value from the singleton store.\n *\n * Used as the `getSnapshot` for `useSyncExternalStore`.\n *\n * @returns {Breakpoint} The latest computed breakpoint.\n * @private\n */\nfunction getCurrentBreakpointSnapshot(): Breakpoint {\n\treturn currentBreakpointValue;\n}\n\n/**\n * Cached `subscribe` functions keyed by breakpoint.\n *\n * Without caching, `useSyncExternalStore` receives a new function reference on\n * every render, causing it to tear down and re-attach the MQL listener each\n * time — the primary source of resize sluggishness.\n *\n * @private\n */\nconst belowBreakpointSubscribeCache = new Map<\n\tTailwindBreakpoint,\n\t(callback: () => void) => () => void\n>();\n\n/**\n * Get (or create and cache) a `subscribe` function for a specific \"below\" breakpoint.\n *\n * Uses a cached `MediaQueryList` and rAF-throttled change handler to avoid\n * bursty updates during resize.\n *\n * @param breakpoint - Tailwind breakpoint identifier (e.g., \"lg\").\n * @returns A stable `subscribe` function suitable for `useSyncExternalStore`.\n * @private\n */\nfunction createBelowBreakpointSubscribe(breakpoint: TailwindBreakpoint) {\n\tlet cached = belowBreakpointSubscribeCache.get(breakpoint);\n\tif (cached) {\n\t\treturn cached;\n\t}\n\n\tcached = (callback: () => void) => {\n\t\tconst mediaQuery = getMaxWidthMQL(breakpoint);\n\n\t\t// rAF throttle the change callback during active resize\n\t\tlet pending = false;\n\t\tconst onChange = () => {\n\t\t\tif (!pending) {\n\t\t\t\tpending = true;\n\t\t\t\trequestAnimationFrame(() => {\n\t\t\t\t\tpending = false;\n\t\t\t\t\tcallback();\n\t\t\t\t});\n\t\t\t}\n\t\t};\n\n\t\tmediaQuery.addEventListener(\"change\", onChange);\n\t\treturn () => {\n\t\t\tmediaQuery.removeEventListener(\"change\", onChange);\n\t\t};\n\t};\n\n\tbelowBreakpointSubscribeCache.set(breakpoint, cached);\n\treturn cached;\n}\n\n/**\n * Cached `getSnapshot` functions keyed by breakpoint.\n *\n * Ensures `useSyncExternalStore` receives a referentially stable function,\n * preventing unnecessary subscription churn.\n *\n * @private\n */\nconst belowBreakpointSnapshotCache = new Map<TailwindBreakpoint, () => boolean>();\n\n/**\n * Get (or create and cache) a `getSnapshot` function for a specific \"below\" breakpoint.\n *\n * Uses the cached `MediaQueryList` for the target breakpoint.\n *\n * @param breakpoint - Tailwind breakpoint identifier (e.g., \"lg\").\n * @returns A stable function that returns `true` when the viewport is below the breakpoint.\n * @private\n */\nfunction createBelowBreakpointGetSnapshot(breakpoint: TailwindBreakpoint) {\n\tlet cached = belowBreakpointSnapshotCache.get(breakpoint);\n\tif (cached) {\n\t\treturn cached;\n\t}\n\n\tcached = () => {\n\t\tconst mediaQuery = getMaxWidthMQL(breakpoint);\n\t\treturn mediaQuery.matches;\n\t};\n\n\tbelowBreakpointSnapshotCache.set(breakpoint, cached);\n\treturn cached;\n}\n","import { useEffect, useMemo, useRef } from \"react\";\n\n/**\n * Returns a memoized callback that always invokes the latest version of the\n * provided callback, while preserving a stable function identity across\n * renders.\n *\n * Use this when you need to pass a callback to a child component, an event\n * handler, or a hook dependency array, but the consumer should not re-run /\n * re-render simply because the callback's identity changed. The returned\n * function never changes reference, but internally always calls through to\n * the latest `callback` passed in.\n *\n * Most commonly used as an internal building block for other hooks (for\n * example, {@link useDebouncedCallback}). It is also re-exported publicly\n * for consumers that need the same pattern.\n *\n * @param callback - The callback to wrap. May be `undefined`, in which case\n * invoking the returned function is a no-op until a callback is provided\n * on a subsequent render.\n * @returns A stable function with the same signature as `callback` that\n * forwards its arguments to the most recent `callback` value.\n *\n * @example\n * // Pass a stable handler to a memoized child without re-rendering it\n * const onSelect = useCallbackRef((id: string) => {\n * // reads the latest `props.items` without being in deps\n * props.onSelectItem(id, props.items);\n * });\n *\n * return <MemoizedList onSelect={onSelect} />;\n */\nfunction useCallbackRef<T extends (...args: unknown[]) => unknown>(callback: T | undefined): T {\n\tconst callbackRef = useRef(callback);\n\n\tuseEffect(() => {\n\t\tcallbackRef.current = callback;\n\t});\n\n\treturn useMemo(() => ((...args) => callbackRef.current?.(...args)) as T, []);\n}\n\nexport {\n\t//,\n\tuseCallbackRef,\n};\n","import { useCallback, useEffect, useRef } from \"react\";\nimport { useCallbackRef } from \"./use-callback-ref.js\";\n\n/**\n * Options for {@link useDebouncedCallback}.\n */\ntype Options = {\n\t/**\n\t * The delay in milliseconds to wait between the last invocation and\n\t * actually running the callback.\n\t */\n\twaitMs: number;\n};\n\n/**\n * Returns a debounced version of the provided callback. Each call resets a\n * timer; the underlying callback only runs after `options.waitMs` of\n * inactivity has elapsed.\n *\n * Useful for limiting rapid invocations such as search-as-you-type inputs,\n * window resize handlers, or expensive button-press handlers. The pending\n * timer is automatically cleared on unmount.\n *\n * The debounced function always invokes the latest version of `callbackFn`,\n * so callers do not need to memoize it. The returned function's identity\n * only changes when `options.waitMs` changes, so it is safe to include in\n * dependency arrays.\n *\n * @param callbackFn - The function to debounce. The latest reference passed\n * on each render is always used when the timer fires.\n * @param options - Debounce options.\n * @param options.waitMs - Milliseconds of inactivity to wait before calling\n * `callbackFn`.\n * @returns A function with the same parameter list as `callbackFn` that\n * schedules (or reschedules) the underlying call.\n *\n * @example\n * // Debounce a search input by 300ms\n * const [query, setQuery] = useState(\"\");\n * const search = useDebouncedCallback((value: string) => {\n * fetchResults(value);\n * }, { waitMs: 300 });\n *\n * return (\n * <input\n * value={query}\n * onChange={(event) => {\n * setQuery(event.target.value);\n * search(event.target.value);\n * }}\n * />\n * );\n */\nfunction useDebouncedCallback<T extends (...args: unknown[]) => unknown>(\n\tcallbackFn: T,\n\toptions: Options,\n) {\n\tconst stableCallbackFn = useCallbackRef(callbackFn);\n\tconst debounceTimerRef = useRef(0);\n\tuseEffect(() => () => window.clearTimeout(debounceTimerRef.current), []);\n\n\treturn useCallback(\n\t\t(...args: Parameters<T>) => {\n\t\t\twindow.clearTimeout(debounceTimerRef.current);\n\t\t\tdebounceTimerRef.current = window.setTimeout(() => stableCallbackFn(...args), options.waitMs);\n\t\t},\n\t\t[stableCallbackFn, options.waitMs],\n\t);\n}\n\nexport {\n\t//,\n\tuseDebouncedCallback,\n};\n","import { useEffect, useLayoutEffect } from \"react\";\n\n/**\n * A drop-in replacement for `useLayoutEffect` that does not warn during\n * server-side rendering.\n *\n * Resolves to `useLayoutEffect` in the browser (where it can read layout and\n * synchronously re-render before paint) and to `useEffect` on the server\n * (where layout effects are a no-op and React would otherwise log a\n * \"useLayoutEffect does nothing on the server\" warning).\n *\n * Use this whenever you need the timing semantics of `useLayoutEffect` in\n * code that may also execute during SSR. It is most often used internally\n * by other Mantle hooks and components.\n *\n * @param effect - The imperative function that may return a cleanup\n * function — same signature as React's `useLayoutEffect` / `useEffect`.\n * @param deps - Optional dependency list, same semantics as\n * `useLayoutEffect`.\n * @returns Nothing.\n *\n * @example\n * // Measure an element synchronously after layout\n * const ref = useRef<HTMLDivElement>(null);\n * const [width, setWidth] = useState(0);\n *\n * useIsomorphicLayoutEffect(() => {\n * if (ref.current) {\n * setWidth(ref.current.getBoundingClientRect().width);\n * }\n * }, []);\n *\n * return <div ref={ref}>Width: {width}</div>;\n */\nexport const useIsomorphicLayoutEffect =\n\ttypeof window !== \"undefined\" ? useLayoutEffect : useEffect;\n","import { useMemo } from \"react\";\n\n/**\n * React hook that returns a random, stable id (e.g. `\"mantle-a3f9k7q\"`)\n * suitable for DOM `id` attributes and `aria-*` references.\n *\n * Unlike React's built-in `useId`, the generated suffix does not contain\n * special characters (`:`). The default id is safe to use directly in CSS\n * selectors and `querySelector` calls; if you provide a custom `prefix`,\n * keep it selector-safe or escape the final id with `CSS.escape()` before\n * querying. The id is generated once for the lifetime of the component and\n * is stable across re-renders, but a new value is produced when `prefix`\n * changes.\n *\n * @param prefix - Optional string prepended to the generated suffix.\n * Whitespace-only or empty values fall back to `\"mantle\"`. Use a\n * selector-safe prefix if you plan to reference the id in CSS selectors\n * without escaping. Defaults to `\"mantle\"`.\n * @returns A string of the form `\"<prefix>-<7-char-random>\"`.\n *\n * @example\n * // Associate a label with a custom input\n * const id = useRandomStableId(\"email-input\");\n *\n * return (\n * <>\n * <label htmlFor={id}>Email</label>\n * <input id={id} type=\"email\" />\n * </>\n * );\n *\n * @example\n * // Use as an aria-controls reference\n * const panelId = useRandomStableId(\"panel\");\n *\n * return (\n * <>\n * <button aria-controls={panelId}>Toggle</button>\n * <div id={panelId}>Panel contents</div>\n * </>\n * );\n */\nconst useRandomStableId = (prefix = \"mantle\") => useMemo(() => randomStableId(prefix), [prefix]);\n\nexport {\n\t//,\n\tuseRandomStableId,\n};\n\nfunction randomStableId(prefix = \"mantle\") {\n\tconst safePrefix = prefix.trim() || \"mantle\";\n\treturn [safePrefix, randomPostfix()].join(\"-\");\n}\n\nfunction randomPostfix() {\n\treturn Math.random().toString(36).substring(2, 9);\n}\n","import { useMemo } from \"react\";\nimport { usePrefersReducedMotion } from \"./use-prefers-reduced-motion.js\";\n\n/**\n * `scroll-behavior` values:\n *\n * - `\"auto\"` — scrolling happens instantly (no animation).\n * - `\"smooth\"` — scrolling animates smoothly using a user-agent–defined easing and duration.\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-behavior#values\n */\nexport type ScrollBehavior = \"auto\" | \"smooth\";\n\n/**\n * React hook that returns a {@link ScrollBehavior} value (`\"auto\"` or\n * `\"smooth\"`) that respects the user's motion preference.\n *\n * Internally calls {@link usePrefersReducedMotion}: when reduced motion is\n * preferred, this returns `\"auto\"` (no animated scroll); otherwise it\n * returns `\"smooth\"`. Pair this with `window.scrollTo`,\n * `Element.scrollIntoView`, or any other scroll API that accepts a\n * `behavior` option to avoid forcing animations on users who have opted\n * out of motion. The conservative SSR default also prevents \"first paint\"\n * scroll animations.\n *\n * @returns `\"auto\"` when the user prefers reduced motion, otherwise\n * `\"smooth\"`.\n *\n * @example\n * // Scroll to the top of the page on a button click\n * const behavior = useScrollBehavior();\n *\n * return (\n * <button onClick={() => window.scrollTo({ top: 0, behavior })}>\n * Back to top\n * </button>\n * );\n *\n * @example\n * // Bring a referenced section into view\n * const behavior = useScrollBehavior();\n * const sectionRef = useRef<HTMLElement>(null);\n *\n * function focusSection() {\n * sectionRef.current?.scrollIntoView({ behavior, block: \"start\" });\n * }\n *\n * @see {@link usePrefersReducedMotion}\n * @see CSS `scroll-behavior` property (values: `\"auto\"`, `\"smooth\"`).\n */\nexport function useScrollBehavior(): ScrollBehavior {\n\tconst prefersReducedMotion = usePrefersReducedMotion();\n\n\treturn useMemo(() => (prefersReducedMotion ? \"auto\" : \"smooth\"), [prefersReducedMotion]);\n}\n","\"use client\";\n\nimport { type RefObject, useEffect, useState } from \"react\";\nimport type { InViewOptions, MarginType } from \"../utils/in-view.js\";\nimport { inView } from \"../utils/in-view.js\";\n\n/**\n * Options for the `useInView` hook.\n */\ntype UseInViewOptions = {\n\t/**\n\t * A ref to a scrollable container element to use as the intersection root.\n\t * Defaults to the browser viewport.\n\t */\n\troot?: RefObject<Element | null>;\n\n\t/**\n\t * Expand or contract the detected area from each side of the root's bounding box.\n\t * Uses the same syntax as the CSS `margin` shorthand (e.g. `\"10px\"`, `\"10% 20px\"`).\n\t */\n\tmargin?: MarginType;\n\n\t/**\n\t * How much of the element must be visible before it is considered in view.\n\t * - `\"some\"` (default): Any part of the element is visible.\n\t * - `\"all\"`: The entire element is visible.\n\t * - `number`: An intersection ratio between `0` and `1` (e.g. `0.5` for 50%).\n\t */\n\tamount?: \"some\" | \"all\" | number;\n\n\t/**\n\t * If `true`, stop observing once the element enters the viewport for the\n\t * first time. Useful for one-shot entrance animations.\n\t * Defaults to `false`.\n\t */\n\tonce?: boolean;\n\n\t/**\n\t * The initial visibility state returned before the observer has attached.\n\t * Defaults to `false`.\n\t */\n\tinitial?: boolean;\n};\n\n/**\n * React hook that tracks whether a DOM element is visible within the viewport\n * (or a scrollable container) using the `IntersectionObserver` API.\n *\n * @param ref - A ref attached to the element to observe.\n * @param options - Options controlling the scroll root, margin, threshold,\n * initial state, and one-time detection.\n * @returns `true` if the element is currently in view, otherwise `false`.\n *\n * @example\n * // Basic usage\n * const ref = useRef<HTMLDivElement>(null);\n * const isInView = useInView(ref);\n *\n * return <div ref={ref}>{isInView ? \"Visible!\" : \"Hidden\"}</div>;\n *\n * @example\n * // Trigger once when the element first enters the viewport\n * const ref = useRef<HTMLDivElement>(null);\n * const isInView = useInView(ref, { once: true });\n *\n * return (\n * <div\n * ref={ref}\n * style={{ opacity: isInView ? 1 : 0, transition: \"opacity 0.5s\" }}\n * />\n * );\n *\n * @example\n * // Require 50% of the element to be visible\n * const ref = useRef<HTMLDivElement>(null);\n * const isInView = useInView(ref, { amount: 0.5 });\n */\nfunction useInView(\n\tref: RefObject<Element | null>,\n\t{ root, margin, amount, once = false, initial = false }: UseInViewOptions = {},\n): boolean {\n\tconst [isInView, setInView] = useState(initial);\n\n\tuseEffect(() => {\n\t\tif (!ref.current || (once && isInView)) {\n\t\t\treturn;\n\t\t}\n\n\t\tfunction onEnter() {\n\t\t\tsetInView(true);\n\t\t\treturn once ? undefined : () => setInView(false);\n\t\t}\n\n\t\tconst options: InViewOptions = {\n\t\t\troot: (root && root.current) || undefined,\n\t\t\tmargin,\n\t\t\tamount,\n\t\t};\n\n\t\treturn inView(ref.current, onEnter, options);\n\t\t/**\n\t\t * Intentionally omit `isInView` from deps. The effect must only re-run\n\t\t * when the observation parameters change, not when visibility changes.\n\t\t * Including `isInView` would restart the observer (disconnect + reconnect)\n\t\t * on every enter/leave event, causing wasteful churn for the common\n\t\t * `once=false` case.\n\t\t */\n\t\t// oxlint-disable-next-line react-hooks/exhaustive-deps\n\t}, [root, ref, margin, once, amount]);\n\n\treturn isInView;\n}\n\nexport { useInView };\nexport type { UseInViewOptions };\n","import { useCallback, useMemo, useReducer } from \"react\";\n\ntype UndoRedoState<T> = {\n\tundoStack: T[];\n\tredoStack: T[];\n};\n\ntype UndoRedoAction<T> =\n\t| { type: \"push\"; snapshot: T }\n\t| { type: \"undo\"; current: T }\n\t| { type: \"redo\"; current: T };\n\nfunction undoRedoReducer<T>(state: UndoRedoState<T>, action: UndoRedoAction<T>): UndoRedoState<T> {\n\tswitch (action.type) {\n\t\tcase \"push\": {\n\t\t\treturn {\n\t\t\t\tundoStack: [...state.undoStack, action.snapshot],\n\t\t\t\tredoStack: [],\n\t\t\t};\n\t\t}\n\t\tcase \"undo\": {\n\t\t\tif (state.undoStack.length === 0) {\n\t\t\t\treturn state;\n\t\t\t}\n\t\t\tconst undoStack = state.undoStack.slice(0, -1);\n\t\t\tconst previous = state.undoStack[state.undoStack.length - 1];\n\t\t\tif (previous === undefined) {\n\t\t\t\treturn state;\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tundoStack,\n\t\t\t\tredoStack: [...state.redoStack, action.current],\n\t\t\t};\n\t\t}\n\t\tcase \"redo\": {\n\t\t\tif (state.redoStack.length === 0) {\n\t\t\t\treturn state;\n\t\t\t}\n\t\t\tconst redoStack = state.redoStack.slice(0, -1);\n\t\t\tconst next = state.redoStack[state.redoStack.length - 1];\n\t\t\tif (next === undefined) {\n\t\t\t\treturn state;\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tundoStack: [...state.undoStack, action.current],\n\t\t\t\tredoStack,\n\t\t\t};\n\t\t}\n\t}\n}\n\ntype UseUndoRedoReturn<T> = {\n\t/** Whether there are actions to undo. */\n\tcanUndo: boolean;\n\t/** Whether there are actions to redo. */\n\tcanRedo: boolean;\n\t/** Push a snapshot onto the undo stack. Clears the redo stack. */\n\tpush: (snapshot: T) => void;\n\t/** Pop the last snapshot from the undo stack. Returns `undefined` if empty. */\n\tundo: (current: T) => T | undefined;\n\t/** Pop the last snapshot from the redo stack. Returns `undefined` if empty. */\n\tredo: (current: T) => T | undefined;\n};\n\n/**\n * Generic undo/redo hook backed by a reducer that maintains two history\n * stacks (undo and redo).\n *\n * The hook does not own your application state — instead it helps you\n * snapshot it. Call `push(snapshot)` *before* mutating state to capture\n * the current value, then call `undo(current)` or `redo(current)` to swap\n * `current` with the previous/next snapshot. Both `undo` and `redo` return\n * the snapshot to apply, or `undefined` if their stack is empty. Pushing a\n * new snapshot clears the redo stack, matching standard editor semantics.\n *\n * @typeParam T - The type of the value being snapshotted (e.g. a list of\n * items, a serialized form value, etc.).\n *\n * @returns An object with the current undo/redo capability flags and\n * actions:\n * - `canUndo`: `true` when there is at least one snapshot on the undo\n * stack.\n * - `canRedo`: `true` when there is at least one snapshot on the redo\n * stack.\n * - `push(snapshot)`: Push a snapshot onto the undo stack and clear the\n * redo stack. Call this *before* mutating state.\n * - `undo(current)`: Pop the latest undo snapshot and return it; returns\n * `undefined` when the undo stack is empty. The supplied `current` is\n * pushed onto the redo stack so you can redo back to it.\n * - `redo(current)`: Pop the latest redo snapshot and return it; returns\n * `undefined` when the redo stack is empty. The supplied `current` is\n * pushed onto the undo stack.\n *\n * @example\n * // Snapshot before mutating, then wire up keyboard shortcuts\n * const [items, setItems] = useState<string[]>([]);\n * const { push, undo, redo, canUndo, canRedo } = useUndoRedo<string[]>();\n *\n * function removeItem(item: string) {\n * push(items); // snapshot before mutation\n * setItems((prev) => prev.filter((entry) => entry !== item));\n * }\n *\n * function handleKeyDown(event: React.KeyboardEvent) {\n * const cmd = event.metaKey || event.ctrlKey;\n * if (cmd && event.key === \"z\" && !event.shiftKey) {\n * const previous = undo(items);\n * if (previous) {\n * setItems(previous);\n * }\n * }\n * if (cmd && ((event.shiftKey && event.key === \"z\") || event.key === \"y\")) {\n * const next = redo(items);\n * if (next) {\n * setItems(next);\n * }\n * }\n * }\n *\n * return (\n * <div tabIndex={0} onKeyDown={handleKeyDown}>\n * <button disabled={!canUndo} onClick={() => { const previous = undo(items); if (previous) setItems(previous); }}>Undo</button>\n * <button disabled={!canRedo} onClick={() => { const next = redo(items); if (next) setItems(next); }}>Redo</button>\n * </div>\n * );\n */\nfunction useUndoRedo<T>(): UseUndoRedoReturn<T> {\n\tconst [state, dispatch] = useReducer(undoRedoReducer<T>, {\n\t\tundoStack: [],\n\t\tredoStack: [],\n\t});\n\n\tconst push = useCallback((snapshot: T) => {\n\t\tdispatch({ type: \"push\", snapshot });\n\t}, []);\n\n\tconst undo = useCallback(\n\t\t(current: T): T | undefined => {\n\t\t\tconst previous = state.undoStack[state.undoStack.length - 1];\n\t\t\tif (previous === undefined) {\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\tdispatch({ type: \"undo\", current });\n\t\t\treturn previous;\n\t\t},\n\t\t[state.undoStack],\n\t);\n\n\tconst redo = useCallback(\n\t\t(current: T): T | undefined => {\n\t\t\tconst next = state.redoStack[state.redoStack.length - 1];\n\t\t\tif (next === undefined) {\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\tdispatch({ type: \"redo\", current });\n\t\t\treturn next;\n\t\t},\n\t\t[state.redoStack],\n\t);\n\n\treturn useMemo(\n\t\t() => ({\n\t\t\tcanUndo: state.undoStack.length > 0,\n\t\t\tcanRedo: state.redoStack.length > 0,\n\t\t\tpush,\n\t\t\tundo,\n\t\t\tredo,\n\t\t}),\n\t\t[state.undoStack.length, state.redoStack.length, push, undo, redo],\n\t);\n}\n\nexport {\n\t//,\n\tuseUndoRedo,\n};\n\nexport type {\n\t//,\n\tUseUndoRedoReturn,\n};\n"],"mappings":"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"}
@@ -7,13 +7,13 @@ import * as HoverCardPrimitive from "@radix-ui/react-hover-card";
7
7
  /**
8
8
  * A floating card that appears when a user hovers over a trigger element.
9
9
  *
10
- * `HoverCard` is intended primarily for sighted usersit is not a
11
- * reliably discoverable path for keyboard or screen reader users, since it
12
- * opens on pointer hover. Use it for supplemental previews of content that
13
- * is already available through another accessible path (typically the
14
- * underlying link). Prefer `Popover` when the floating content must be
15
- * reachable by all users, or `Tooltip` for short, non-interactive labels on
16
- * controls.
10
+ * Use `HoverCard` for non-essential preview content shown on HOVER user
11
+ * cards, repo previews, rich link previews. Because hover is not reachable
12
+ * via keyboard, all content inside a `HoverCard` must be supplemental,
13
+ * never the only path to information; the trigger is typically a link that
14
+ * already leads to the same content for keyboard and screen reader users.
15
+ * For short, non-interactive labels or hints, use `Tooltip`. For
16
+ * interactive overlays the user opens deliberately, use `Popover`.
17
17
  *
18
18
  * @see https://mantle.ngrok.com/components/hover-card
19
19
  *
@@ -89,18 +89,23 @@ declare const HoverCard: {
89
89
  readonly Content: _$react.ForwardRefExoticComponent<Omit<HoverCardPrimitive.HoverCardContentProps & _$react.RefAttributes<HTMLDivElement>, "ref"> & _$react.RefAttributes<HTMLDivElement>>;
90
90
  /**
91
91
  * The portal container for rendering hover card content outside the normal DOM tree.
92
+ * `HoverCard.Content` already renders inside this portal internally, so you typically
93
+ * do not need to use `HoverCard.Portal` directly. Use it only when you need to
94
+ * customize portal placement or wrap multiple `HoverCard.Content` instances.
92
95
  *
93
- * @see https://mantle.ngrok.com/components/hover-card#api-reference
96
+ * @see https://mantle.ngrok.com/components/hover-card#hovercardportal
94
97
  *
95
98
  * @example
96
99
  * ```tsx
97
100
  * <HoverCard.Root>
98
101
  * <HoverCard.Trigger asChild>
99
- * <Text>Hover over me</Text>
102
+ * <Button type="button" appearance="outlined">
103
+ * Hover me
104
+ * </Button>
100
105
  * </HoverCard.Trigger>
101
106
  * <HoverCard.Portal>
102
107
  * <HoverCard.Content>
103
- * <Text>This content is rendered in a portal.</Text>
108
+ * <p>This is the hover card content.</p>
104
109
  * </HoverCard.Content>
105
110
  * </HoverCard.Portal>
106
111
  * </HoverCard.Root>
@@ -1 +1 @@
1
- {"version":3,"file":"hover-card.js","names":[],"sources":["../src/components/hover-card/hover-card.tsx"],"sourcesContent":["\"use client\";\n\nimport * as HoverCardPrimitive from \"@radix-ui/react-hover-card\";\nimport { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef, ComponentRef } from \"react\";\nimport { cx } from \"../../utils/cx/cx.js\";\n\n/**\n * A floating card that appears when a user hovers over a trigger element.\n * This is the root, stateful component that manages the open/closed state of the hover card.\n *\n * @see https://mantle.ngrok.com/components/hover-card#hovercardroot\n *\n * @example\n * ```tsx\n * <HoverCard.Root>\n * <HoverCard.Trigger asChild>\n * <Button type=\"button\" appearance=\"outlined\">\n * Hover me\n * </Button>\n * </HoverCard.Trigger>\n * <HoverCard.Content>\n * <p>This is the hover card content.</p>\n * </HoverCard.Content>\n * </HoverCard.Root>\n * ```\n */\nconst Root = ({\n\tcloseDelay = 300,\n\topenDelay = 100,\n\t...props\n}: ComponentPropsWithoutRef<typeof HoverCardPrimitive.Root>) => (\n\t<HoverCardPrimitive.Root closeDelay={closeDelay} openDelay={openDelay} {...props} />\n);\nRoot.displayName = \"HoverCard\";\n\n/**\n * The trigger element that opens the hover card when hovered.\n *\n * @see https://mantle.ngrok.com/components/hover-card#hovercardtrigger\n *\n * @example\n * ```tsx\n * <HoverCard.Root>\n * <HoverCard.Trigger asChild>\n * <Button type=\"button\" appearance=\"outlined\">\n * Hover me\n * </Button>\n * </HoverCard.Trigger>\n * <HoverCard.Content>\n * <p>This is the hover card content.</p>\n * </HoverCard.Content>\n * </HoverCard.Root>\n * ```\n */\nconst Trigger = forwardRef<\n\tComponentRef<typeof HoverCardPrimitive.Trigger>,\n\tComponentPropsWithoutRef<typeof HoverCardPrimitive.Trigger>\n>((props, ref) => (\n\t<HoverCardPrimitive.Trigger ref={ref} data-slot=\"hover-card-trigger\" {...props} />\n));\nTrigger.displayName = \"HoverCardTrigger\";\n\n/**\n * The portal for a HoverCard. Should be rendered as a child of the `HoverCard` component.\n * Renders a portal that the `HoverCard.Content` is rendered into.\n *\n * You likely don't need to use this component directly, as it is used internally by the `HoverCard.Content` component.\n */\nconst Portal = HoverCardPrimitive.Portal;\nPortal.displayName = \"HoverCardPortal\";\n\n/**\n * The content to render inside the hover card.\n *\n * @see https://mantle.ngrok.com/components/hover-card#hovercardcontent\n *\n * @example\n * ```tsx\n * <HoverCard.Root>\n * <HoverCard.Trigger asChild>\n * <Button type=\"button\" appearance=\"outlined\">\n * Hover me\n * </Button>\n * </HoverCard.Trigger>\n * <HoverCard.Content>\n * <p>This is the hover card content.</p>\n * </HoverCard.Content>\n * </HoverCard.Root>\n * ```\n */\nconst Content = forwardRef<\n\tComponentRef<typeof HoverCardPrimitive.Content>,\n\tComponentPropsWithoutRef<typeof HoverCardPrimitive.Content>\n>(({ className, onClick, align = \"center\", sideOffset = 4, ...props }, ref) => (\n\t<Portal>\n\t\t<HoverCardPrimitive.Content\n\t\t\tref={ref}\n\t\t\tdata-slot=\"hover-card-content\"\n\t\t\talign={align}\n\t\t\tsideOffset={sideOffset}\n\t\t\tclassName={cx(\n\t\t\t\t\"bg-popover border-popover z-50 w-64 rounded-md border p-4 shadow-md outline-hidden\",\n\t\t\t\t\"data-state-open:animate-in data-state-closed:animate-out data-state-closed:fade-out-0 data-state-open:fade-in-0 data-state-closed:zoom-out-95 data-state-open:zoom-in-95 data-side-bottom:slide-in-from-top-2 data-side-left:slide-in-from-right-2 data-side-right:slide-in-from-left-2 data-side-top:slide-in-from-bottom-2\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\tonClick={(event) => {\n\t\t\t\t/**\n\t\t\t\t * Prevent the click event from propagating up to parent/containing elements\n\t\t\t\t */\n\t\t\t\tevent.stopPropagation();\n\t\t\t\tonClick?.(event);\n\t\t\t}}\n\t\t\t{...props}\n\t\t/>\n\t</Portal>\n));\nContent.displayName = HoverCardPrimitive.Content.displayName;\n\n/**\n * A floating card that appears when a user hovers over a trigger element.\n *\n * `HoverCard` is intended primarily for sighted usersit is not a\n * reliably discoverable path for keyboard or screen reader users, since it\n * opens on pointer hover. Use it for supplemental previews of content that\n * is already available through another accessible path (typically the\n * underlying link). Prefer `Popover` when the floating content must be\n * reachable by all users, or `Tooltip` for short, non-interactive labels on\n * controls.\n *\n * @see https://mantle.ngrok.com/components/hover-card\n *\n * @example\n * Composition:\n * ```\n * HoverCard.Root\n * ├── HoverCard.Trigger\n * └── HoverCard.Content\n * ```\n *\n * @example\n * ```tsx\n * <HoverCard.Root>\n * <HoverCard.Trigger asChild>\n * <Button type=\"button\" appearance=\"outlined\">\n * Hover me\n * </Button>\n * </HoverCard.Trigger>\n * <HoverCard.Content>\n * <p>This is the hover card content.</p>\n * </HoverCard.Content>\n * </HoverCard.Root>\n * ```\n */\nconst HoverCard = {\n\t/**\n\t * The root, stateful component that manages the open/closed state of the hover card.\n\t *\n\t * @see https://mantle.ngrok.com/components/hover-card#hovercardroot\n\t *\n\t * @example\n\t * ```tsx\n\t * <HoverCard.Root>\n\t * <HoverCard.Trigger asChild>\n\t * <Button>Hover me</Button>\n\t * </HoverCard.Trigger>\n\t * <HoverCard.Content>\n\t * <p>This is the hover card content.</p>\n\t * </HoverCard.Content>\n\t * </HoverCard.Root>\n\t * ```\n\t */\n\tRoot,\n\t/**\n\t * The content to render inside the hover card. Appears in a portal with rich styling and animations.\n\t *\n\t * @see https://mantle.ngrok.com/components/hover-card#hovercardcontent\n\t *\n\t * @example\n\t * ```tsx\n\t * <HoverCard.Root>\n\t * <HoverCard.Trigger asChild>\n\t * <Button type=\"button\" variant=\"link\">@username</Button>\n\t * </HoverCard.Trigger>\n\t * <HoverCard.Content side=\"top\">\n\t * <div className=\"space-y-2\">\n\t * <Text weight=\"strong\">User Profile</Text>\n\t * <Text>Additional information about the user.</Text>\n\t * <Button type=\"button\" size=\"sm\">Follow</Button>\n\t * </div>\n\t * </HoverCard.Content>\n\t * </HoverCard.Root>\n\t * ```\n\t */\n\tContent,\n\t/**\n\t * The portal container for rendering hover card content outside the normal DOM tree.\n\t *\n\t * @see https://mantle.ngrok.com/components/hover-card#api-reference\n\t *\n\t * @example\n\t * ```tsx\n\t * <HoverCard.Root>\n\t * <HoverCard.Trigger asChild>\n\t * <Text>Hover over me</Text>\n\t * </HoverCard.Trigger>\n\t * <HoverCard.Portal>\n\t * <HoverCard.Content>\n\t * <Text>This content is rendered in a portal.</Text>\n\t * </HoverCard.Content>\n\t * </HoverCard.Portal>\n\t * </HoverCard.Root>\n\t * ```\n\t */\n\tPortal,\n\t/**\n\t * The trigger element that opens the hover card when hovered.\n\t *\n\t * @see https://mantle.ngrok.com/components/hover-card#hovercardtrigger\n\t *\n\t * @example\n\t * ```tsx\n\t * <HoverCard.Root>\n\t * <HoverCard.Trigger asChild>\n\t * <Button type=\"button\" variant=\"ghost\">\n\t * Hover for details\n\t * </Button>\n\t * </HoverCard.Trigger>\n\t * <HoverCard.Content>\n\t * <div className=\"space-y-1\">\n\t * <Text weight=\"strong\">Quick Info</Text>\n\t * <Text>This appears when you hover over the trigger.</Text>\n\t * </div>\n\t * </HoverCard.Content>\n\t * </HoverCard.Root>\n\t * ```\n\t */\n\tTrigger,\n} as const;\n\nexport {\n\t//,\n\tHoverCard,\n};\n"],"mappings":"6JA2BA,MAAM,GAAQ,CACb,aAAa,IACb,YAAY,IACZ,GAAG,KAEH,EAAC,EAAmB,KAApB,CAAqC,aAAuB,YAAW,GAAI,EAAS,CAAA,CAErF,EAAK,YAAc,YAqBnB,MAAM,EAAU,GAGb,EAAO,IACT,EAAC,EAAmB,QAApB,CAAiC,MAAK,YAAU,qBAAqB,GAAI,EAAS,CAAA,CACjF,CACF,EAAQ,YAAc,mBAQtB,MAAM,EAAS,EAAmB,OAClC,EAAO,YAAc,kBAqBrB,MAAM,EAAU,GAGb,CAAE,YAAW,UAAS,QAAQ,SAAU,aAAa,EAAG,GAAG,GAAS,IACtE,EAAC,EAAD,CAAA,SACC,EAAC,EAAmB,QAApB,CACM,MACL,YAAU,qBACH,QACK,aACZ,UAAW,EACV,qFACA,+TACA,EACA,CACD,QAAU,GAAU,CAInB,EAAM,iBAAiB,CACvB,IAAU,EAAM,EAEjB,GAAI,EACH,CAAA,CACM,CAAA,CACR,CACF,EAAQ,YAAc,EAAmB,QAAQ,YAqCjD,MAAM,EAAY,CAkBjB,OAsBA,UAoBA,SAuBA,UACA"}
1
+ {"version":3,"file":"hover-card.js","names":[],"sources":["../src/components/hover-card/hover-card.tsx"],"sourcesContent":["\"use client\";\n\nimport * as HoverCardPrimitive from \"@radix-ui/react-hover-card\";\nimport { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef, ComponentRef } from \"react\";\nimport { cx } from \"../../utils/cx/cx.js\";\n\n/**\n * A floating card that appears when a user hovers over a trigger element.\n * This is the root, stateful component that manages the open/closed state of the hover card.\n *\n * @see https://mantle.ngrok.com/components/hover-card#hovercardroot\n *\n * @example\n * ```tsx\n * <HoverCard.Root>\n * <HoverCard.Trigger asChild>\n * <Button type=\"button\" appearance=\"outlined\">\n * Hover me\n * </Button>\n * </HoverCard.Trigger>\n * <HoverCard.Content>\n * <p>This is the hover card content.</p>\n * </HoverCard.Content>\n * </HoverCard.Root>\n * ```\n */\nconst Root = ({\n\tcloseDelay = 300,\n\topenDelay = 100,\n\t...props\n}: ComponentPropsWithoutRef<typeof HoverCardPrimitive.Root>) => (\n\t<HoverCardPrimitive.Root closeDelay={closeDelay} openDelay={openDelay} {...props} />\n);\nRoot.displayName = \"HoverCard\";\n\n/**\n * The trigger element that opens the hover card when hovered.\n *\n * @see https://mantle.ngrok.com/components/hover-card#hovercardtrigger\n *\n * @example\n * ```tsx\n * <HoverCard.Root>\n * <HoverCard.Trigger asChild>\n * <Button type=\"button\" appearance=\"outlined\">\n * Hover me\n * </Button>\n * </HoverCard.Trigger>\n * <HoverCard.Content>\n * <p>This is the hover card content.</p>\n * </HoverCard.Content>\n * </HoverCard.Root>\n * ```\n */\nconst Trigger = forwardRef<\n\tComponentRef<typeof HoverCardPrimitive.Trigger>,\n\tComponentPropsWithoutRef<typeof HoverCardPrimitive.Trigger>\n>((props, ref) => (\n\t<HoverCardPrimitive.Trigger ref={ref} data-slot=\"hover-card-trigger\" {...props} />\n));\nTrigger.displayName = \"HoverCardTrigger\";\n\n/**\n * The portal container for rendering hover card content outside the normal DOM tree.\n * `HoverCard.Content` already renders inside this portal internally, so you typically\n * do not need to use `HoverCard.Portal` directly. Use it only when you need to\n * customize portal placement (e.g., pass a `container` prop) or wrap multiple\n * `HoverCard.Content` instances in a shared portal.\n *\n * @see https://mantle.ngrok.com/components/hover-card#hovercardportal\n *\n * @example\n * ```tsx\n * <HoverCard.Root>\n * <HoverCard.Trigger asChild>\n * <Button type=\"button\" appearance=\"outlined\">\n * Hover me\n * </Button>\n * </HoverCard.Trigger>\n * <HoverCard.Portal>\n * <HoverCard.Content>\n * <p>This is the hover card content.</p>\n * </HoverCard.Content>\n * </HoverCard.Portal>\n * </HoverCard.Root>\n * ```\n */\nconst Portal = HoverCardPrimitive.Portal;\nPortal.displayName = \"HoverCardPortal\";\n\n/**\n * The content to render inside the hover card.\n *\n * @see https://mantle.ngrok.com/components/hover-card#hovercardcontent\n *\n * @example\n * ```tsx\n * <HoverCard.Root>\n * <HoverCard.Trigger asChild>\n * <Button type=\"button\" appearance=\"outlined\">\n * Hover me\n * </Button>\n * </HoverCard.Trigger>\n * <HoverCard.Content>\n * <p>This is the hover card content.</p>\n * </HoverCard.Content>\n * </HoverCard.Root>\n * ```\n */\nconst Content = forwardRef<\n\tComponentRef<typeof HoverCardPrimitive.Content>,\n\tComponentPropsWithoutRef<typeof HoverCardPrimitive.Content>\n>(({ className, onClick, align = \"center\", sideOffset = 4, ...props }, ref) => (\n\t<Portal>\n\t\t<HoverCardPrimitive.Content\n\t\t\tref={ref}\n\t\t\tdata-slot=\"hover-card-content\"\n\t\t\talign={align}\n\t\t\tsideOffset={sideOffset}\n\t\t\tclassName={cx(\n\t\t\t\t\"bg-popover border-popover z-50 w-64 rounded-md border p-4 shadow-md outline-hidden\",\n\t\t\t\t\"data-state-open:animate-in data-state-closed:animate-out data-state-closed:fade-out-0 data-state-open:fade-in-0 data-state-closed:zoom-out-95 data-state-open:zoom-in-95 data-side-bottom:slide-in-from-top-2 data-side-left:slide-in-from-right-2 data-side-right:slide-in-from-left-2 data-side-top:slide-in-from-bottom-2\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\tonClick={(event) => {\n\t\t\t\t/**\n\t\t\t\t * Prevent the click event from propagating up to parent/containing elements\n\t\t\t\t */\n\t\t\t\tevent.stopPropagation();\n\t\t\t\tonClick?.(event);\n\t\t\t}}\n\t\t\t{...props}\n\t\t/>\n\t</Portal>\n));\nContent.displayName = HoverCardPrimitive.Content.displayName;\n\n/**\n * A floating card that appears when a user hovers over a trigger element.\n *\n * Use `HoverCard` for non-essential preview content shown on HOVER user\n * cards, repo previews, rich link previews. Because hover is not reachable\n * via keyboard, all content inside a `HoverCard` must be supplemental,\n * never the only path to information; the trigger is typically a link that\n * already leads to the same content for keyboard and screen reader users.\n * For short, non-interactive labels or hints, use `Tooltip`. For\n * interactive overlays the user opens deliberately, use `Popover`.\n *\n * @see https://mantle.ngrok.com/components/hover-card\n *\n * @example\n * Composition:\n * ```\n * HoverCard.Root\n * ├── HoverCard.Trigger\n * └── HoverCard.Content\n * ```\n *\n * @example\n * ```tsx\n * <HoverCard.Root>\n * <HoverCard.Trigger asChild>\n * <Button type=\"button\" appearance=\"outlined\">\n * Hover me\n * </Button>\n * </HoverCard.Trigger>\n * <HoverCard.Content>\n * <p>This is the hover card content.</p>\n * </HoverCard.Content>\n * </HoverCard.Root>\n * ```\n */\nconst HoverCard = {\n\t/**\n\t * The root, stateful component that manages the open/closed state of the hover card.\n\t *\n\t * @see https://mantle.ngrok.com/components/hover-card#hovercardroot\n\t *\n\t * @example\n\t * ```tsx\n\t * <HoverCard.Root>\n\t * <HoverCard.Trigger asChild>\n\t * <Button>Hover me</Button>\n\t * </HoverCard.Trigger>\n\t * <HoverCard.Content>\n\t * <p>This is the hover card content.</p>\n\t * </HoverCard.Content>\n\t * </HoverCard.Root>\n\t * ```\n\t */\n\tRoot,\n\t/**\n\t * The content to render inside the hover card. Appears in a portal with rich styling and animations.\n\t *\n\t * @see https://mantle.ngrok.com/components/hover-card#hovercardcontent\n\t *\n\t * @example\n\t * ```tsx\n\t * <HoverCard.Root>\n\t * <HoverCard.Trigger asChild>\n\t * <Button type=\"button\" variant=\"link\">@username</Button>\n\t * </HoverCard.Trigger>\n\t * <HoverCard.Content side=\"top\">\n\t * <div className=\"space-y-2\">\n\t * <Text weight=\"strong\">User Profile</Text>\n\t * <Text>Additional information about the user.</Text>\n\t * <Button type=\"button\" size=\"sm\">Follow</Button>\n\t * </div>\n\t * </HoverCard.Content>\n\t * </HoverCard.Root>\n\t * ```\n\t */\n\tContent,\n\t/**\n\t * The portal container for rendering hover card content outside the normal DOM tree.\n\t * `HoverCard.Content` already renders inside this portal internally, so you typically\n\t * do not need to use `HoverCard.Portal` directly. Use it only when you need to\n\t * customize portal placement or wrap multiple `HoverCard.Content` instances.\n\t *\n\t * @see https://mantle.ngrok.com/components/hover-card#hovercardportal\n\t *\n\t * @example\n\t * ```tsx\n\t * <HoverCard.Root>\n\t * <HoverCard.Trigger asChild>\n\t * <Button type=\"button\" appearance=\"outlined\">\n\t * Hover me\n\t * </Button>\n\t * </HoverCard.Trigger>\n\t * <HoverCard.Portal>\n\t * <HoverCard.Content>\n\t * <p>This is the hover card content.</p>\n\t * </HoverCard.Content>\n\t * </HoverCard.Portal>\n\t * </HoverCard.Root>\n\t * ```\n\t */\n\tPortal,\n\t/**\n\t * The trigger element that opens the hover card when hovered.\n\t *\n\t * @see https://mantle.ngrok.com/components/hover-card#hovercardtrigger\n\t *\n\t * @example\n\t * ```tsx\n\t * <HoverCard.Root>\n\t * <HoverCard.Trigger asChild>\n\t * <Button type=\"button\" variant=\"ghost\">\n\t * Hover for details\n\t * </Button>\n\t * </HoverCard.Trigger>\n\t * <HoverCard.Content>\n\t * <div className=\"space-y-1\">\n\t * <Text weight=\"strong\">Quick Info</Text>\n\t * <Text>This appears when you hover over the trigger.</Text>\n\t * </div>\n\t * </HoverCard.Content>\n\t * </HoverCard.Root>\n\t * ```\n\t */\n\tTrigger,\n} as const;\n\nexport {\n\t//,\n\tHoverCard,\n};\n"],"mappings":"6JA2BA,MAAM,GAAQ,CACb,aAAa,IACb,YAAY,IACZ,GAAG,KAEH,EAAC,EAAmB,KAApB,CAAqC,aAAuB,YAAW,GAAI,EAAS,CAAA,CAErF,EAAK,YAAc,YAqBnB,MAAM,EAAU,GAGb,EAAO,IACT,EAAC,EAAmB,QAApB,CAAiC,MAAK,YAAU,qBAAqB,GAAI,EAAS,CAAA,CACjF,CACF,EAAQ,YAAc,mBA2BtB,MAAM,EAAS,EAAmB,OAClC,EAAO,YAAc,kBAqBrB,MAAM,EAAU,GAGb,CAAE,YAAW,UAAS,QAAQ,SAAU,aAAa,EAAG,GAAG,GAAS,IACtE,EAAC,EAAD,CAAA,SACC,EAAC,EAAmB,QAApB,CACM,MACL,YAAU,qBACH,QACK,aACZ,UAAW,EACV,qFACA,+TACA,EACA,CACD,QAAU,GAAU,CAInB,EAAM,iBAAiB,CACvB,IAAU,EAAM,EAEjB,GAAI,EACH,CAAA,CACM,CAAA,CACR,CACF,EAAQ,YAAc,EAAmB,QAAQ,YAqCjD,MAAM,EAAY,CAkBjB,OAsBA,UAyBA,SAuBA,UACA"}
@@ -1,4 +1,4 @@
1
- import { t as SvgAttributes } from "./types-DEYyl5LX.js";
1
+ import { t as SvgAttributes } from "./types-DoV0R5Ja.js";
2
2
  import * as _$react from "react";
3
3
  import { ReactNode } from "react";
4
4
 
@@ -24,4 +24,4 @@ type IconProps = Omit<SvgAttributes, "children"> & {
24
24
  declare const Icon: _$react.ForwardRefExoticComponent<Omit<IconProps, "ref"> & _$react.RefAttributes<SVGSVGElement>>;
25
25
  //#endregion
26
26
  export { IconProps as n, Icon as t };
27
- //# sourceMappingURL=icon-C0YAAaLZ.d.ts.map
27
+ //# sourceMappingURL=icon-DKMJm20j.d.ts.map
@@ -1,5 +1,5 @@
1
- import { t as WithAsChild } from "./as-child-CJ2vTesV.js";
2
- import { t as VariantProps } from "./variant-props-DszdagRm.js";
1
+ import { t as WithAsChild } from "./as-child-DQHfEmYB.js";
2
+ import { t as VariantProps } from "./variant-props-DUmSIQK8.js";
3
3
  import * as _$react from "react";
4
4
  import { ButtonHTMLAttributes, ReactNode } from "react";
5
5
  import * as _$class_variance_authority_types0 from "class-variance-authority/types";
@@ -95,4 +95,4 @@ type IconButtonProps = ButtonHTMLAttributes<HTMLButtonElement> & WithAsChild & I
95
95
  declare const IconButton: _$react.ForwardRefExoticComponent<IconButtonProps & _$react.RefAttributes<HTMLButtonElement>>;
96
96
  //#endregion
97
97
  export { IconButtonProps as n, IconButton as t };
98
- //# sourceMappingURL=icon-button-Cl30yTfu.d.ts.map
98
+ //# sourceMappingURL=icon-button-BnK4K7YK.d.ts.map
package/dist/icon.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { t as SvgAttributes } from "./types-DEYyl5LX.js";
2
- import { n as IconProps, t as Icon } from "./icon-C0YAAaLZ.js";
3
- import { n as SvgOnlyProps, t as SvgOnly } from "./svg-only-BnnbLx6R.js";
1
+ import { t as SvgAttributes } from "./types-DoV0R5Ja.js";
2
+ import { n as IconProps, t as Icon } from "./icon-DKMJm20j.js";
3
+ import { n as SvgOnlyProps, t as SvgOnly } from "./svg-only-BtBvFy-N.js";
4
4
  export { Icon, type IconProps, type SvgAttributes, SvgOnly, type SvgOnlyProps };
package/dist/icons.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { t as SvgAttributes } from "./types-DEYyl5LX.js";
2
- import { a as AlphanumericSortingDirection, c as TimeSortingDirection, o as SortingDirection, s as SortingMode } from "./direction-Jk7BkzGo.js";
3
- import { i as Theme } from "./themes-DXb8Tk74.js";
1
+ import { t as SvgAttributes } from "./types-DoV0R5Ja.js";
2
+ import { a as AlphanumericSortingDirection, c as TimeSortingDirection, o as SortingDirection, s as SortingMode } from "./direction-DtBAQn7p.js";
3
+ import { i as Theme } from "./themes-DIEYkvNl.js";
4
4
  import { ComponentProps } from "react";
5
5
  import * as _$react_jsx_runtime0 from "react/jsx-runtime";
6
6
 
package/dist/icons.js CHANGED
@@ -1,2 +1,2 @@
1
- import{s as e}from"./theme-provider-BFcnjeME.js";import{t}from"./traffic-policy-file-ChsoQtXQ.js";import{t as n}from"./sort-C_Jbs1dH.js";import{jsx as r}from"react/jsx-runtime";import{DesktopIcon as i}from"@phosphor-icons/react/Desktop";import{MoonIcon as a}from"@phosphor-icons/react/Moon";import{SunIcon as o}from"@phosphor-icons/react/Sun";function s(t){return r(c,{theme:e(),...t})}s.displayName=`AutoThemeIcon`;function c({theme:e,...t}){switch(e){case`system`:return r(i,{...t});case`light`:return r(o,{...t});case`dark`:return r(a,{...t});case`light-high-contrast`:return r(o,{...t,weight:`fill`});case`dark-high-contrast`:return r(a,{...t,weight:`fill`})}}c.displayName=`ThemeIcon`;function l(e){return r(`svg`,{fill:`currentColor`,height:`1em`,viewBox:`0 0 94 36`,width:`2.61em`,...e,children:r(`path`,{d:`M32.272 12.011c-1.298-1.466-2.904-2.205-4.812-2.205-1.176 0-2.26.233-3.255.7a7.995 7.995 0 0 0-2.581 1.906 9.205 9.205 0 0 0-1.715 2.853 9.773 9.773 0 0 0-.628 3.546c0 1.25.194 2.39.58 3.419.362.98.918 1.877 1.635 2.636A7.543 7.543 0 0 0 24 26.584c.965.41 2.025.617 3.176.617.522 0 1.005-.041 1.445-.116.439-.075.858-.2 1.26-.37.4-.175.79-.398 1.18-.664.385-.27.792-.612 1.21-1.018v4.353h-.005v.421h-5.33l-4.005 4.64v.798h15.037v-24.98h-5.697v1.746Zm-.014 7.979a4.25 4.25 0 0 1-.786 1.215 3.555 3.555 0 0 1-2.592 1.1 3.627 3.627 0 0 1-1.464-.292 3.508 3.508 0 0 1-1.166-.808 3.93 3.93 0 0 1-1.054-2.72c0-.519.097-1.006.298-1.457a3.77 3.77 0 0 1 .804-1.181 4.114 4.114 0 0 1 1.162-.808 3.484 3.484 0 0 1 2.817-.016c.448.19.844.463 1.181.81.336.347.6.743.804 1.194.202.452.298.95.298 1.493 0 .505-.104 1.005-.302 1.47m-16.261-7.708a6.173 6.173 0 0 0-2.06-1.602 4.875 4.875 0 0 0-.57-.22 6.383 6.383 0 0 0-.923-.216H8.383L5.697 13.39v-3.082H.002v16.61h5.695V15.712h5.35l.444-.01v11.214h5.697V16.528c0-.885-.084-1.674-.25-2.366a4.655 4.655 0 0 0-.941-1.877zm38.367-2.018h-6.213l-2.47 2.863v-2.864h-5.7v16.61h5.71l.004-11.117h4.144l4.526-5.26zm31.051 7.672 7.79-7.392v-.281H85.7l-5.975 5.991V0h-5.696v26.87h5.696v-6.766l6.262 6.763h7.663v-.316l-8.233-8.617zm-16.11-5.78a9.436 9.436 0 0 0-3.085-1.842 10.953 10.953 0 0 0-3.855-.664c-1.407 0-2.705.226-3.884.678a9.611 9.611 0 0 0-3.072 1.858 8.488 8.488 0 0 0-2.016 2.788 8.281 8.281 0 0 0-.722 3.449c0 1.362.24 2.596.722 3.707a8.52 8.52 0 0 0 2.002 2.862c.85.798 1.86 1.415 3.036 1.847 1.177.432 2.455.647 3.842.647 1.406 0 2.707-.215 3.919-.647 1.204-.431 2.24-1.04 3.098-1.833a8.583 8.583 0 0 0 2.031-2.816c.493-1.09.742-2.29.742-3.611 0-1.316-.244-2.52-.722-3.612a8.424 8.424 0 0 0-2.035-2.81Zm-3.558 7.864c-.2.461-.463.869-.786 1.215a3.573 3.573 0 0 1-2.592 1.1c-.502 0-.981-.096-1.434-.291a3.44 3.44 0 0 1-1.16-.809 4.155 4.155 0 0 1-.788-1.215 3.825 3.825 0 0 1-.297-1.537c0-.517.098-1.004.297-1.456.201-.451.46-.849.787-1.194a3.579 3.579 0 0 1 2.597-1.1c.502 0 .98.096 1.43.29.448.19.839.461 1.16.81.328.345.586.752.786 1.214.2.461.297.954.297 1.471 0 .538-.096 1.04-.297 1.502`})})}function u(e){return r(`svg`,{fill:`currentColor`,height:`1em`,viewBox:`0 0 32 32`,width:`1em`,...e,children:r(`path`,{d:`M27.2 6.18a9.47 9.47 0 0 0-3.12-2.5A9.42 9.42 0 0 0 21.82 3h-6.14l-4.06 4.9V3.1H3V29h8.62V11.53h8.09l.67-.02v17.48H29V12.8c0-1.37-.13-2.6-.38-3.68a7.35 7.35 0 0 0-1.42-2.93Z`})})}export{s as AutoThemeIcon,u as NgrokLettermarkIcon,l as NgrokWordmarkIcon,n as SortIcon,c as ThemeIcon,t as TrafficPolicyFileIcon};
1
+ import{s as e}from"./theme-provider-BFcnjeME.js";import{t}from"./traffic-policy-file-C6LHYrIU.js";import{t as n}from"./sort-DzCsa6Qj.js";import{jsx as r}from"react/jsx-runtime";import{DesktopIcon as i}from"@phosphor-icons/react/Desktop";import{MoonIcon as a}from"@phosphor-icons/react/Moon";import{SunIcon as o}from"@phosphor-icons/react/Sun";function s(t){return r(c,{theme:e(),...t})}s.displayName=`AutoThemeIcon`;function c({theme:e,...t}){switch(e){case`system`:return r(i,{...t});case`light`:return r(o,{...t});case`dark`:return r(a,{...t});case`light-high-contrast`:return r(o,{...t,weight:`fill`});case`dark-high-contrast`:return r(a,{...t,weight:`fill`})}}c.displayName=`ThemeIcon`;function l(e){return r(`svg`,{fill:`currentColor`,height:`1em`,viewBox:`0 0 94 36`,width:`2.61em`,...e,children:r(`path`,{d:`M32.272 12.011c-1.298-1.466-2.904-2.205-4.812-2.205-1.176 0-2.26.233-3.255.7a7.995 7.995 0 0 0-2.581 1.906 9.205 9.205 0 0 0-1.715 2.853 9.773 9.773 0 0 0-.628 3.546c0 1.25.194 2.39.58 3.419.362.98.918 1.877 1.635 2.636A7.543 7.543 0 0 0 24 26.584c.965.41 2.025.617 3.176.617.522 0 1.005-.041 1.445-.116.439-.075.858-.2 1.26-.37.4-.175.79-.398 1.18-.664.385-.27.792-.612 1.21-1.018v4.353h-.005v.421h-5.33l-4.005 4.64v.798h15.037v-24.98h-5.697v1.746Zm-.014 7.979a4.25 4.25 0 0 1-.786 1.215 3.555 3.555 0 0 1-2.592 1.1 3.627 3.627 0 0 1-1.464-.292 3.508 3.508 0 0 1-1.166-.808 3.93 3.93 0 0 1-1.054-2.72c0-.519.097-1.006.298-1.457a3.77 3.77 0 0 1 .804-1.181 4.114 4.114 0 0 1 1.162-.808 3.484 3.484 0 0 1 2.817-.016c.448.19.844.463 1.181.81.336.347.6.743.804 1.194.202.452.298.95.298 1.493 0 .505-.104 1.005-.302 1.47m-16.261-7.708a6.173 6.173 0 0 0-2.06-1.602 4.875 4.875 0 0 0-.57-.22 6.383 6.383 0 0 0-.923-.216H8.383L5.697 13.39v-3.082H.002v16.61h5.695V15.712h5.35l.444-.01v11.214h5.697V16.528c0-.885-.084-1.674-.25-2.366a4.655 4.655 0 0 0-.941-1.877zm38.367-2.018h-6.213l-2.47 2.863v-2.864h-5.7v16.61h5.71l.004-11.117h4.144l4.526-5.26zm31.051 7.672 7.79-7.392v-.281H85.7l-5.975 5.991V0h-5.696v26.87h5.696v-6.766l6.262 6.763h7.663v-.316l-8.233-8.617zm-16.11-5.78a9.436 9.436 0 0 0-3.085-1.842 10.953 10.953 0 0 0-3.855-.664c-1.407 0-2.705.226-3.884.678a9.611 9.611 0 0 0-3.072 1.858 8.488 8.488 0 0 0-2.016 2.788 8.281 8.281 0 0 0-.722 3.449c0 1.362.24 2.596.722 3.707a8.52 8.52 0 0 0 2.002 2.862c.85.798 1.86 1.415 3.036 1.847 1.177.432 2.455.647 3.842.647 1.406 0 2.707-.215 3.919-.647 1.204-.431 2.24-1.04 3.098-1.833a8.583 8.583 0 0 0 2.031-2.816c.493-1.09.742-2.29.742-3.611 0-1.316-.244-2.52-.722-3.612a8.424 8.424 0 0 0-2.035-2.81Zm-3.558 7.864c-.2.461-.463.869-.786 1.215a3.573 3.573 0 0 1-2.592 1.1c-.502 0-.981-.096-1.434-.291a3.44 3.44 0 0 1-1.16-.809 4.155 4.155 0 0 1-.788-1.215 3.825 3.825 0 0 1-.297-1.537c0-.517.098-1.004.297-1.456.201-.451.46-.849.787-1.194a3.579 3.579 0 0 1 2.597-1.1c.502 0 .98.096 1.43.29.448.19.839.461 1.16.81.328.345.586.752.786 1.214.2.461.297.954.297 1.471 0 .538-.096 1.04-.297 1.502`})})}function u(e){return r(`svg`,{fill:`currentColor`,height:`1em`,viewBox:`0 0 32 32`,width:`1em`,...e,children:r(`path`,{d:`M27.2 6.18a9.47 9.47 0 0 0-3.12-2.5A9.42 9.42 0 0 0 21.82 3h-6.14l-4.06 4.9V3.1H3V29h8.62V11.53h8.09l.67-.02v17.48H29V12.8c0-1.37-.13-2.6-.38-3.68a7.35 7.35 0 0 0-1.42-2.93Z`})})}export{s as AutoThemeIcon,u as NgrokLettermarkIcon,l as NgrokWordmarkIcon,n as SortIcon,c as ThemeIcon,t as TrafficPolicyFileIcon};
2
2
  //# sourceMappingURL=icons.js.map
package/dist/icons.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"icons.js","names":[],"sources":["../src/components/icons/theme.tsx","../src/components/icons/ngrok.tsx"],"sourcesContent":["import { DesktopIcon } from \"@phosphor-icons/react/Desktop\";\nimport { MoonIcon } from \"@phosphor-icons/react/Moon\";\nimport { SunIcon } from \"@phosphor-icons/react/Sun\";\nimport type { SvgAttributes } from \"../icon/types.js\";\nimport { useAppliedTheme } from \"../theme/theme-provider.js\";\nimport type { Theme } from \"../theme/themes.js\";\n\n/**\n * An icon that automatically adapts to the current applied theme.\n * - `light`: SunIcon\n * - `dark`: MoonIcon\n * - `light-high-contrast`: SunIcon (fill)\n * - `dark-high-contrast`: MoonIcon (fill)\n */\nfunction AutoThemeIcon(props: SvgAttributes) {\n\tconst appliedTheme = useAppliedTheme();\n\n\treturn <ThemeIcon theme={appliedTheme} {...props} />;\n}\nAutoThemeIcon.displayName = \"AutoThemeIcon\";\n\ntype ThemeIconProps = SvgAttributes & { theme: Theme };\n\n/**\n * An icon that adapts to a specific theme.\n * It will render a different icon based on the provided theme:\n * - `system`: DesktopIcon\n * - `light`: SunIcon\n * - `dark`: MoonIcon\n * - `light-high-contrast`: SunIcon (fill)\n * - `dark-high-contrast`: MoonIcon (fill)\n */\nfunction ThemeIcon({ theme, ...props }: ThemeIconProps) {\n\tswitch (theme) {\n\t\tcase \"system\":\n\t\t\treturn <DesktopIcon {...props} />;\n\t\tcase \"light\":\n\t\t\treturn <SunIcon {...props} />;\n\t\tcase \"dark\":\n\t\t\treturn <MoonIcon {...props} />;\n\t\tcase \"light-high-contrast\":\n\t\t\treturn <SunIcon {...props} weight=\"fill\" />;\n\t\tcase \"dark-high-contrast\":\n\t\t\treturn <MoonIcon {...props} weight=\"fill\" />;\n\t}\n}\nThemeIcon.displayName = \"ThemeIcon\";\n\nexport {\n\t//,\n\tAutoThemeIcon,\n\tThemeIcon,\n};\n","import type { InlineIconProps } from \"./types.js\";\n\n/**\n * An inline svg icon that renders the ngrok wordmark logo. Fill color is determined by the `color` CSS property.\n */\nfunction NgrokWordmarkIcon(props: Omit<InlineIconProps, \"color\">) {\n\treturn (\n\t\t<svg fill=\"currentColor\" height=\"1em\" viewBox=\"0 0 94 36\" width=\"2.61em\" {...props}>\n\t\t\t<path d=\"M32.272 12.011c-1.298-1.466-2.904-2.205-4.812-2.205-1.176 0-2.26.233-3.255.7a7.995 7.995 0 0 0-2.581 1.906 9.205 9.205 0 0 0-1.715 2.853 9.773 9.773 0 0 0-.628 3.546c0 1.25.194 2.39.58 3.419.362.98.918 1.877 1.635 2.636A7.543 7.543 0 0 0 24 26.584c.965.41 2.025.617 3.176.617.522 0 1.005-.041 1.445-.116.439-.075.858-.2 1.26-.37.4-.175.79-.398 1.18-.664.385-.27.792-.612 1.21-1.018v4.353h-.005v.421h-5.33l-4.005 4.64v.798h15.037v-24.98h-5.697v1.746Zm-.014 7.979a4.25 4.25 0 0 1-.786 1.215 3.555 3.555 0 0 1-2.592 1.1 3.627 3.627 0 0 1-1.464-.292 3.508 3.508 0 0 1-1.166-.808 3.93 3.93 0 0 1-1.054-2.72c0-.519.097-1.006.298-1.457a3.77 3.77 0 0 1 .804-1.181 4.114 4.114 0 0 1 1.162-.808 3.484 3.484 0 0 1 2.817-.016c.448.19.844.463 1.181.81.336.347.6.743.804 1.194.202.452.298.95.298 1.493 0 .505-.104 1.005-.302 1.47m-16.261-7.708a6.173 6.173 0 0 0-2.06-1.602 4.875 4.875 0 0 0-.57-.22 6.383 6.383 0 0 0-.923-.216H8.383L5.697 13.39v-3.082H.002v16.61h5.695V15.712h5.35l.444-.01v11.214h5.697V16.528c0-.885-.084-1.674-.25-2.366a4.655 4.655 0 0 0-.941-1.877zm38.367-2.018h-6.213l-2.47 2.863v-2.864h-5.7v16.61h5.71l.004-11.117h4.144l4.526-5.26zm31.051 7.672 7.79-7.392v-.281H85.7l-5.975 5.991V0h-5.696v26.87h5.696v-6.766l6.262 6.763h7.663v-.316l-8.233-8.617zm-16.11-5.78a9.436 9.436 0 0 0-3.085-1.842 10.953 10.953 0 0 0-3.855-.664c-1.407 0-2.705.226-3.884.678a9.611 9.611 0 0 0-3.072 1.858 8.488 8.488 0 0 0-2.016 2.788 8.281 8.281 0 0 0-.722 3.449c0 1.362.24 2.596.722 3.707a8.52 8.52 0 0 0 2.002 2.862c.85.798 1.86 1.415 3.036 1.847 1.177.432 2.455.647 3.842.647 1.406 0 2.707-.215 3.919-.647 1.204-.431 2.24-1.04 3.098-1.833a8.583 8.583 0 0 0 2.031-2.816c.493-1.09.742-2.29.742-3.611 0-1.316-.244-2.52-.722-3.612a8.424 8.424 0 0 0-2.035-2.81Zm-3.558 7.864c-.2.461-.463.869-.786 1.215a3.573 3.573 0 0 1-2.592 1.1c-.502 0-.981-.096-1.434-.291a3.44 3.44 0 0 1-1.16-.809 4.155 4.155 0 0 1-.788-1.215 3.825 3.825 0 0 1-.297-1.537c0-.517.098-1.004.297-1.456.201-.451.46-.849.787-1.194a3.579 3.579 0 0 1 2.597-1.1c.502 0 .98.096 1.43.29.448.19.839.461 1.16.81.328.345.586.752.786 1.214.2.461.297.954.297 1.471 0 .538-.096 1.04-.297 1.502\" />\n\t\t</svg>\n\t);\n}\n\n/**\n * An inline svg icon that renders the ngrok lettermark \"n\" logo. Fill color is determined by the `color` CSS property.\n */\nfunction NgrokLettermarkIcon(props: Omit<InlineIconProps, \"color\">) {\n\treturn (\n\t\t<svg fill=\"currentColor\" height=\"1em\" viewBox=\"0 0 32 32\" width=\"1em\" {...props}>\n\t\t\t<path d=\"M27.2 6.18a9.47 9.47 0 0 0-3.12-2.5A9.42 9.42 0 0 0 21.82 3h-6.14l-4.06 4.9V3.1H3V29h8.62V11.53h8.09l.67-.02v17.48H29V12.8c0-1.37-.13-2.6-.38-3.68a7.35 7.35 0 0 0-1.42-2.93Z\" />\n\t\t</svg>\n\t);\n}\n\nexport {\n\t//,\n\tNgrokWordmarkIcon,\n\tNgrokLettermarkIcon,\n};\n"],"mappings":"uVAcA,SAAS,EAAc,EAAsB,CAG5C,OAAO,EAAC,EAAD,CAAW,MAFG,GAAiB,CAEC,GAAI,EAAS,CAAA,CAErD,EAAc,YAAc,gBAa5B,SAAS,EAAU,CAAE,QAAO,GAAG,GAAyB,CACvD,OAAQ,EAAR,CACC,IAAK,SACJ,OAAO,EAAC,EAAD,CAAa,GAAI,EAAS,CAAA,CAClC,IAAK,QACJ,OAAO,EAAC,EAAD,CAAS,GAAI,EAAS,CAAA,CAC9B,IAAK,OACJ,OAAO,EAAC,EAAD,CAAU,GAAI,EAAS,CAAA,CAC/B,IAAK,sBACJ,OAAO,EAAC,EAAD,CAAS,GAAI,EAAO,OAAO,OAAS,CAAA,CAC5C,IAAK,qBACJ,OAAO,EAAC,EAAD,CAAU,GAAI,EAAO,OAAO,OAAS,CAAA,EAG/C,EAAU,YAAc,YCzCxB,SAAS,EAAkB,EAAuC,CACjE,OACC,EAAC,MAAD,CAAK,KAAK,eAAe,OAAO,MAAM,QAAQ,YAAY,MAAM,SAAS,GAAI,WAC5E,EAAC,OAAD,CAAM,EAAE,mlEAAqlE,CAAA,CACxlE,CAAA,CAOR,SAAS,EAAoB,EAAuC,CACnE,OACC,EAAC,MAAD,CAAK,KAAK,eAAe,OAAO,MAAM,QAAQ,YAAY,MAAM,MAAM,GAAI,WACzE,EAAC,OAAD,CAAM,EAAE,gLAAkL,CAAA,CACrL,CAAA"}
1
+ {"version":3,"file":"icons.js","names":[],"sources":["../src/components/icons/theme.tsx","../src/components/icons/ngrok.tsx"],"sourcesContent":["import { DesktopIcon } from \"@phosphor-icons/react/Desktop\";\nimport { MoonIcon } from \"@phosphor-icons/react/Moon\";\nimport { SunIcon } from \"@phosphor-icons/react/Sun\";\nimport type { SvgAttributes } from \"../icon/types.js\";\nimport { useAppliedTheme } from \"../theme/theme-provider.js\";\nimport type { Theme } from \"../theme/themes.js\";\n\n/**\n * An icon that automatically adapts to the current applied theme.\n * - `light`: SunIcon\n * - `dark`: MoonIcon\n * - `light-high-contrast`: SunIcon (fill)\n * - `dark-high-contrast`: MoonIcon (fill)\n */\nfunction AutoThemeIcon(props: SvgAttributes) {\n\tconst appliedTheme = useAppliedTheme();\n\n\treturn <ThemeIcon theme={appliedTheme} {...props} />;\n}\nAutoThemeIcon.displayName = \"AutoThemeIcon\";\n\ntype ThemeIconProps = SvgAttributes & { theme: Theme };\n\n/**\n * An icon that adapts to a specific theme.\n * It will render a different icon based on the provided theme:\n * - `system`: DesktopIcon\n * - `light`: SunIcon\n * - `dark`: MoonIcon\n * - `light-high-contrast`: SunIcon (fill)\n * - `dark-high-contrast`: MoonIcon (fill)\n */\nfunction ThemeIcon({ theme, ...props }: ThemeIconProps) {\n\tswitch (theme) {\n\t\tcase \"system\":\n\t\t\treturn <DesktopIcon {...props} />;\n\t\tcase \"light\":\n\t\t\treturn <SunIcon {...props} />;\n\t\tcase \"dark\":\n\t\t\treturn <MoonIcon {...props} />;\n\t\tcase \"light-high-contrast\":\n\t\t\treturn <SunIcon {...props} weight=\"fill\" />;\n\t\tcase \"dark-high-contrast\":\n\t\t\treturn <MoonIcon {...props} weight=\"fill\" />;\n\t}\n}\nThemeIcon.displayName = \"ThemeIcon\";\n\nexport {\n\t//,\n\tAutoThemeIcon,\n\tThemeIcon,\n};\n","import type { InlineIconProps } from \"./types.js\";\n\n/**\n * An inline svg icon that renders the ngrok wordmark logo. Fill color is determined by the `color` CSS property.\n */\nfunction NgrokWordmarkIcon(props: Omit<InlineIconProps, \"color\">) {\n\treturn (\n\t\t<svg fill=\"currentColor\" height=\"1em\" viewBox=\"0 0 94 36\" width=\"2.61em\" {...props}>\n\t\t\t<path d=\"M32.272 12.011c-1.298-1.466-2.904-2.205-4.812-2.205-1.176 0-2.26.233-3.255.7a7.995 7.995 0 0 0-2.581 1.906 9.205 9.205 0 0 0-1.715 2.853 9.773 9.773 0 0 0-.628 3.546c0 1.25.194 2.39.58 3.419.362.98.918 1.877 1.635 2.636A7.543 7.543 0 0 0 24 26.584c.965.41 2.025.617 3.176.617.522 0 1.005-.041 1.445-.116.439-.075.858-.2 1.26-.37.4-.175.79-.398 1.18-.664.385-.27.792-.612 1.21-1.018v4.353h-.005v.421h-5.33l-4.005 4.64v.798h15.037v-24.98h-5.697v1.746Zm-.014 7.979a4.25 4.25 0 0 1-.786 1.215 3.555 3.555 0 0 1-2.592 1.1 3.627 3.627 0 0 1-1.464-.292 3.508 3.508 0 0 1-1.166-.808 3.93 3.93 0 0 1-1.054-2.72c0-.519.097-1.006.298-1.457a3.77 3.77 0 0 1 .804-1.181 4.114 4.114 0 0 1 1.162-.808 3.484 3.484 0 0 1 2.817-.016c.448.19.844.463 1.181.81.336.347.6.743.804 1.194.202.452.298.95.298 1.493 0 .505-.104 1.005-.302 1.47m-16.261-7.708a6.173 6.173 0 0 0-2.06-1.602 4.875 4.875 0 0 0-.57-.22 6.383 6.383 0 0 0-.923-.216H8.383L5.697 13.39v-3.082H.002v16.61h5.695V15.712h5.35l.444-.01v11.214h5.697V16.528c0-.885-.084-1.674-.25-2.366a4.655 4.655 0 0 0-.941-1.877zm38.367-2.018h-6.213l-2.47 2.863v-2.864h-5.7v16.61h5.71l.004-11.117h4.144l4.526-5.26zm31.051 7.672 7.79-7.392v-.281H85.7l-5.975 5.991V0h-5.696v26.87h5.696v-6.766l6.262 6.763h7.663v-.316l-8.233-8.617zm-16.11-5.78a9.436 9.436 0 0 0-3.085-1.842 10.953 10.953 0 0 0-3.855-.664c-1.407 0-2.705.226-3.884.678a9.611 9.611 0 0 0-3.072 1.858 8.488 8.488 0 0 0-2.016 2.788 8.281 8.281 0 0 0-.722 3.449c0 1.362.24 2.596.722 3.707a8.52 8.52 0 0 0 2.002 2.862c.85.798 1.86 1.415 3.036 1.847 1.177.432 2.455.647 3.842.647 1.406 0 2.707-.215 3.919-.647 1.204-.431 2.24-1.04 3.098-1.833a8.583 8.583 0 0 0 2.031-2.816c.493-1.09.742-2.29.742-3.611 0-1.316-.244-2.52-.722-3.612a8.424 8.424 0 0 0-2.035-2.81Zm-3.558 7.864c-.2.461-.463.869-.786 1.215a3.573 3.573 0 0 1-2.592 1.1c-.502 0-.981-.096-1.434-.291a3.44 3.44 0 0 1-1.16-.809 4.155 4.155 0 0 1-.788-1.215 3.825 3.825 0 0 1-.297-1.537c0-.517.098-1.004.297-1.456.201-.451.46-.849.787-1.194a3.579 3.579 0 0 1 2.597-1.1c.502 0 .98.096 1.43.29.448.19.839.461 1.16.81.328.345.586.752.786 1.214.2.461.297.954.297 1.471 0 .538-.096 1.04-.297 1.502\" />\n\t\t</svg>\n\t);\n}\n\n/**\n * An inline svg icon that renders the ngrok lettermark \"n\" logo. Fill color is determined by the `color` CSS property.\n */\nfunction NgrokLettermarkIcon(props: Omit<InlineIconProps, \"color\">) {\n\treturn (\n\t\t<svg fill=\"currentColor\" height=\"1em\" viewBox=\"0 0 32 32\" width=\"1em\" {...props}>\n\t\t\t<path d=\"M27.2 6.18a9.47 9.47 0 0 0-3.12-2.5A9.42 9.42 0 0 0 21.82 3h-6.14l-4.06 4.9V3.1H3V29h8.62V11.53h8.09l.67-.02v17.48H29V12.8c0-1.37-.13-2.6-.38-3.68a7.35 7.35 0 0 0-1.42-2.93Z\" />\n\t\t</svg>\n\t);\n}\n\nexport {\n\t//,\n\tNgrokWordmarkIcon,\n\tNgrokLettermarkIcon,\n};\n"],"mappings":"uVAcA,SAAS,EAAc,EAAsB,CAG5C,OAAO,EAAC,EAAD,CAAW,MAFG,GAEgB,CAAE,GAAI,EAAS,CAAA,CAErD,EAAc,YAAc,gBAa5B,SAAS,EAAU,CAAE,QAAO,GAAG,GAAyB,CACvD,OAAQ,EAAR,CACC,IAAK,SACJ,OAAO,EAAC,EAAD,CAAa,GAAI,EAAS,CAAA,CAClC,IAAK,QACJ,OAAO,EAAC,EAAD,CAAS,GAAI,EAAS,CAAA,CAC9B,IAAK,OACJ,OAAO,EAAC,EAAD,CAAU,GAAI,EAAS,CAAA,CAC/B,IAAK,sBACJ,OAAO,EAAC,EAAD,CAAS,GAAI,EAAO,OAAO,OAAS,CAAA,CAC5C,IAAK,qBACJ,OAAO,EAAC,EAAD,CAAU,GAAI,EAAO,OAAO,OAAS,CAAA,EAG/C,EAAU,YAAc,YCzCxB,SAAS,EAAkB,EAAuC,CACjE,OACC,EAAC,MAAD,CAAK,KAAK,eAAe,OAAO,MAAM,QAAQ,YAAY,MAAM,SAAS,GAAI,WAC5E,EAAC,OAAD,CAAM,EAAE,mlEAAqlE,CAAA,CACxlE,CAAA,CAOR,SAAS,EAAoB,EAAuC,CACnE,OACC,EAAC,MAAD,CAAK,KAAK,eAAe,OAAO,MAAM,QAAQ,YAAY,MAAM,MAAM,GAAI,WACzE,EAAC,OAAD,CAAM,EAAE,gLAAkL,CAAA,CACrL,CAAA"}
@@ -1,17 +1,28 @@
1
1
  import { Ref } from "react";
2
2
 
3
+ //#region src/utils/copy-to-clipboard.d.ts
4
+ /**
5
+ * Copy the given string to the clipboard. Uses the Clipboard API when
6
+ * available and falls back to an `execCommand("copy")` polyfill for older
7
+ * browsers.
8
+ *
9
+ * Throws when called outside a DOM environment, or when both the Clipboard
10
+ * API and the polyfill fail — `await` the call to observe success.
11
+ */
12
+ declare function copyToClipboard(value: string): Promise<void>;
13
+ //#endregion
3
14
  //#region src/utils/compose-refs/compose-refs.d.ts
4
15
  type PossibleRef<T> = Ref<T> | undefined;
5
16
  /**
6
17
  * A utility to compose multiple refs together
7
18
  * Accepts callback refs and RefObject(s)
8
19
  */
9
- declare function composeRefs<T>(...refs: PossibleRef<T>[]): (node: T) => void;
20
+ declare function composeRefs<T>(...refs: PossibleRef<T>[]): (node: T | null) => void;
10
21
  /**
11
22
  * A custom hook that composes multiple refs
12
23
  * Accepts callback refs and RefObject(s)
13
24
  */
14
- declare function useComposedRefs<T>(...refs: PossibleRef<T>[]): () => (node: T) => void;
25
+ declare function useComposedRefs<T>(...refs: PossibleRef<T>[]): (node: T | null) => void;
15
26
  //#endregion
16
27
  //#region src/utils/in-view.d.ts
17
28
  type MarginValue = `${number}${"px" | "%"}`;
@@ -81,5 +92,5 @@ declare function inView(element: Element, onStart: (element: Element, entry: Int
81
92
  amount
82
93
  }?: InViewOptions): VoidFunction;
83
94
  //#endregion
84
- export { composeRefs as a, inView as i, MarginType as n, useComposedRefs as o, ViewChangeHandler as r, InViewOptions as t };
85
- //# sourceMappingURL=in-view-DsiWfQpY.d.ts.map
95
+ export { composeRefs as a, inView as i, MarginType as n, useComposedRefs as o, ViewChangeHandler as r, copyToClipboard as s, InViewOptions as t };
96
+ //# sourceMappingURL=in-view-Da08Bx6l.d.ts.map
@@ -1,2 +1,2 @@
1
1
  const e={some:0,all:1};function t(t,n,{root:r,margin:i,amount:a=`some`}={}){let o=new WeakMap,s=new IntersectionObserver(e=>{e.forEach(e=>{let t=o.get(e.target);if(e.isIntersecting!==!!t)if(e.isIntersecting){let t=n(e.target,e);typeof t==`function`?o.set(e.target,t):s.unobserve(e.target)}else typeof t==`function`&&(t(e),o.delete(e.target))})},{root:r,rootMargin:i,threshold:typeof a==`number`?a:e[a]});return s.observe(t),()=>{s.unobserve(t),s.disconnect()}}export{t};
2
- //# sourceMappingURL=in-view-BXzPPdcl.js.map
2
+ //# sourceMappingURL=in-view-pia_SVdE.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"in-view-BXzPPdcl.js","names":[],"sources":["../src/utils/in-view.ts"],"sourcesContent":["type MarginValue = `${number}${\"px\" | \"%\"}`;\n\n/**\n * Margin string used to expand or contract the intersection root's bounding box.\n * Follows the same syntax as the CSS `margin` shorthand (1–4 values).\n *\n * @example \"10px\"\n * @example \"10% 20px\"\n * @example \"10px 20px 10px 20px\"\n */\ntype MarginType =\n\t| MarginValue\n\t| `${MarginValue} ${MarginValue}`\n\t| `${MarginValue} ${MarginValue} ${MarginValue}`\n\t| `${MarginValue} ${MarginValue} ${MarginValue} ${MarginValue}`;\n\n/**\n * Options for the `inView` helper.\n */\ntype InViewOptions = {\n\t/**\n\t * The scrollable container element (or `Document`) to use as the intersection root.\n\t * Defaults to the browser viewport.\n\t */\n\troot?: Element | Document;\n\n\t/**\n\t * Expand or contract the detected area from each side of the root's bounding box.\n\t * Uses the same syntax as the CSS `margin` shorthand (e.g. `\"10px\"`, `\"10% 20px\"`).\n\t */\n\tmargin?: MarginType;\n\n\t/**\n\t * How much of the element must be visible before it is considered in view.\n\t * - `\"some\"` (default): Any part of the element is visible.\n\t * - `\"all\"`: The entire element is visible.\n\t * - `number`: An intersection ratio between `0` and `1` (e.g. `0.5` for 50%).\n\t */\n\tamount?: \"some\" | \"all\" | number;\n};\n\n/**\n * Callback invoked when an observed element leaves the viewport.\n * Receives the `IntersectionObserverEntry` for the departing element.\n */\ntype ViewChangeHandler = (entry: IntersectionObserverEntry) => void;\n\nconst thresholds = {\n\tsome: 0,\n\tall: 1,\n};\n\n/**\n * Observe when a DOM element enters or leaves the viewport (or a scrollable\n * container) using the `IntersectionObserver` API.\n *\n * When the element enters the viewport, `onStart` is called. If `onStart`\n * returns a function, that function is called when the element leaves the\n * viewport. If `onStart` returns nothing, the element is unobserved after\n * the first entry.\n *\n * @param element - The DOM element to observe.\n * @param onStart - Called when the element enters the viewport. Optionally\n * returns a cleanup function called when the element leaves.\n * @param options - Options for the intersection root, margin, and threshold.\n * @returns A cleanup function that disconnects the observer.\n *\n * @example\n * const stop = inView(element, (el) => {\n * el.classList.add(\"visible\");\n * return () => el.classList.remove(\"visible\");\n * });\n *\n * // Later, stop observing:\n * stop();\n */\nfunction inView(\n\telement: Element,\n\tonStart: (element: Element, entry: IntersectionObserverEntry) => void | ViewChangeHandler,\n\t{ root, margin: rootMargin, amount = \"some\" }: InViewOptions = {},\n): VoidFunction {\n\tconst activeIntersections = new WeakMap<Element, ViewChangeHandler>();\n\n\tconst onIntersectionChange: IntersectionObserverCallback = (entries) => {\n\t\tentries.forEach((entry) => {\n\t\t\tconst onEnd = activeIntersections.get(entry.target);\n\n\t\t\t/**\n\t\t\t * If there's no change to the intersection, we don't need to\n\t\t\t * do anything here.\n\t\t\t */\n\t\t\tif (entry.isIntersecting === Boolean(onEnd)) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (entry.isIntersecting) {\n\t\t\t\tconst newOnEnd = onStart(entry.target, entry);\n\t\t\t\tif (typeof newOnEnd === \"function\") {\n\t\t\t\t\tactiveIntersections.set(entry.target, newOnEnd);\n\t\t\t\t} else {\n\t\t\t\t\tobserver.unobserve(entry.target);\n\t\t\t\t}\n\t\t\t} else if (typeof onEnd === \"function\") {\n\t\t\t\tonEnd(entry);\n\t\t\t\tactiveIntersections.delete(entry.target);\n\t\t\t}\n\t\t});\n\t};\n\n\tconst observer = new IntersectionObserver(onIntersectionChange, {\n\t\troot,\n\t\trootMargin,\n\t\tthreshold: typeof amount === \"number\" ? amount : thresholds[amount],\n\t});\n\n\tobserver.observe(element);\n\n\treturn () => {\n\t\tobserver.unobserve(element);\n\t\tobserver.disconnect();\n\t};\n}\n\nexport { inView };\nexport type { InViewOptions, MarginType, ViewChangeHandler };\n"],"mappings":"AA+CA,MAAM,EAAa,CAClB,KAAM,EACN,IAAK,EACL,CA0BD,SAAS,EACR,EACA,EACA,CAAE,OAAM,OAAQ,EAAY,SAAS,QAA0B,EAAE,CAClD,CACf,IAAM,EAAsB,IAAI,QA4B1B,EAAW,IAAI,qBA1BuC,GAAY,CACvE,EAAQ,QAAS,GAAU,CAC1B,IAAM,EAAQ,EAAoB,IAAI,EAAM,OAAO,CAM/C,KAAM,iBAAmB,EAAQ,EAIrC,GAAI,EAAM,eAAgB,CACzB,IAAM,EAAW,EAAQ,EAAM,OAAQ,EAAM,CACzC,OAAO,GAAa,WACvB,EAAoB,IAAI,EAAM,OAAQ,EAAS,CAE/C,EAAS,UAAU,EAAM,OAAO,MAEvB,OAAO,GAAU,aAC3B,EAAM,EAAM,CACZ,EAAoB,OAAO,EAAM,OAAO,GAExC,EAG6D,CAC/D,OACA,aACA,UAAW,OAAO,GAAW,SAAW,EAAS,EAAW,GAC5D,CAAC,CAIF,OAFA,EAAS,QAAQ,EAAQ,KAEZ,CACZ,EAAS,UAAU,EAAQ,CAC3B,EAAS,YAAY"}
1
+ {"version":3,"file":"in-view-pia_SVdE.js","names":[],"sources":["../src/utils/in-view.ts"],"sourcesContent":["type MarginValue = `${number}${\"px\" | \"%\"}`;\n\n/**\n * Margin string used to expand or contract the intersection root's bounding box.\n * Follows the same syntax as the CSS `margin` shorthand (1–4 values).\n *\n * @example \"10px\"\n * @example \"10% 20px\"\n * @example \"10px 20px 10px 20px\"\n */\ntype MarginType =\n\t| MarginValue\n\t| `${MarginValue} ${MarginValue}`\n\t| `${MarginValue} ${MarginValue} ${MarginValue}`\n\t| `${MarginValue} ${MarginValue} ${MarginValue} ${MarginValue}`;\n\n/**\n * Options for the `inView` helper.\n */\ntype InViewOptions = {\n\t/**\n\t * The scrollable container element (or `Document`) to use as the intersection root.\n\t * Defaults to the browser viewport.\n\t */\n\troot?: Element | Document;\n\n\t/**\n\t * Expand or contract the detected area from each side of the root's bounding box.\n\t * Uses the same syntax as the CSS `margin` shorthand (e.g. `\"10px\"`, `\"10% 20px\"`).\n\t */\n\tmargin?: MarginType;\n\n\t/**\n\t * How much of the element must be visible before it is considered in view.\n\t * - `\"some\"` (default): Any part of the element is visible.\n\t * - `\"all\"`: The entire element is visible.\n\t * - `number`: An intersection ratio between `0` and `1` (e.g. `0.5` for 50%).\n\t */\n\tamount?: \"some\" | \"all\" | number;\n};\n\n/**\n * Callback invoked when an observed element leaves the viewport.\n * Receives the `IntersectionObserverEntry` for the departing element.\n */\ntype ViewChangeHandler = (entry: IntersectionObserverEntry) => void;\n\nconst thresholds = {\n\tsome: 0,\n\tall: 1,\n};\n\n/**\n * Observe when a DOM element enters or leaves the viewport (or a scrollable\n * container) using the `IntersectionObserver` API.\n *\n * When the element enters the viewport, `onStart` is called. If `onStart`\n * returns a function, that function is called when the element leaves the\n * viewport. If `onStart` returns nothing, the element is unobserved after\n * the first entry.\n *\n * @param element - The DOM element to observe.\n * @param onStart - Called when the element enters the viewport. Optionally\n * returns a cleanup function called when the element leaves.\n * @param options - Options for the intersection root, margin, and threshold.\n * @returns A cleanup function that disconnects the observer.\n *\n * @example\n * const stop = inView(element, (el) => {\n * el.classList.add(\"visible\");\n * return () => el.classList.remove(\"visible\");\n * });\n *\n * // Later, stop observing:\n * stop();\n */\nfunction inView(\n\telement: Element,\n\tonStart: (element: Element, entry: IntersectionObserverEntry) => void | ViewChangeHandler,\n\t{ root, margin: rootMargin, amount = \"some\" }: InViewOptions = {},\n): VoidFunction {\n\tconst activeIntersections = new WeakMap<Element, ViewChangeHandler>();\n\n\tconst onIntersectionChange: IntersectionObserverCallback = (entries) => {\n\t\tentries.forEach((entry) => {\n\t\t\tconst onEnd = activeIntersections.get(entry.target);\n\n\t\t\t/**\n\t\t\t * If there's no change to the intersection, we don't need to\n\t\t\t * do anything here.\n\t\t\t */\n\t\t\tif (entry.isIntersecting === Boolean(onEnd)) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (entry.isIntersecting) {\n\t\t\t\tconst newOnEnd = onStart(entry.target, entry);\n\t\t\t\tif (typeof newOnEnd === \"function\") {\n\t\t\t\t\tactiveIntersections.set(entry.target, newOnEnd);\n\t\t\t\t} else {\n\t\t\t\t\tobserver.unobserve(entry.target);\n\t\t\t\t}\n\t\t\t} else if (typeof onEnd === \"function\") {\n\t\t\t\tonEnd(entry);\n\t\t\t\tactiveIntersections.delete(entry.target);\n\t\t\t}\n\t\t});\n\t};\n\n\tconst observer = new IntersectionObserver(onIntersectionChange, {\n\t\troot,\n\t\trootMargin,\n\t\tthreshold: typeof amount === \"number\" ? amount : thresholds[amount],\n\t});\n\n\tobserver.observe(element);\n\n\treturn () => {\n\t\tobserver.unobserve(element);\n\t\tobserver.disconnect();\n\t};\n}\n\nexport { inView };\nexport type { InViewOptions, MarginType, ViewChangeHandler };\n"],"mappings":"AA+CA,MAAM,EAAa,CAClB,KAAM,EACN,IAAK,EACL,CA0BD,SAAS,EACR,EACA,EACA,CAAE,OAAM,OAAQ,EAAY,SAAS,QAA0B,EAAE,CAClD,CACf,IAAM,EAAsB,IAAI,QA4B1B,EAAW,IAAI,qBA1BuC,GAAY,CACvE,EAAQ,QAAS,GAAU,CAC1B,IAAM,EAAQ,EAAoB,IAAI,EAAM,OAAO,CAM/C,KAAM,iBAAmB,EAAQ,EAIrC,GAAI,EAAM,eAAgB,CACzB,IAAM,EAAW,EAAQ,EAAM,OAAQ,EAAM,CACzC,OAAO,GAAa,WACvB,EAAoB,IAAI,EAAM,OAAQ,EAAS,CAE/C,EAAS,UAAU,EAAM,OAAO,MAEvB,OAAO,GAAU,aAC3B,EAAM,EAAM,CACZ,EAAoB,OAAO,EAAM,OAAO,GAExC,EAG6D,CAC/D,OACA,aACA,UAAW,OAAO,GAAW,SAAW,EAAS,EAAW,GAC5D,CAAC,CAIF,OAFA,EAAS,QAAQ,EAAQ,KAEZ,CACZ,EAAS,UAAU,EAAQ,CAC3B,EAAS,YAAY"}
@@ -1,4 +1,4 @@
1
- import { a as WithInputType, i as WithAutoComplete, o as WithValidation } from "./types-BeTbgoJd.js";
1
+ import { a as WithInputType, i as WithAutoComplete, o as WithValidation } from "./types-DG0WQLTL.js";
2
2
  import * as _$react from "react";
3
3
  import { InputHTMLAttributes, PropsWithChildren } from "react";
4
4
 
@@ -23,7 +23,7 @@ type InputProps = Omit<InputHTMLAttributes<HTMLInputElement>, "autoComplete" | "
23
23
  * />
24
24
  * ```
25
25
  */
26
- declare const Input: _$react.ForwardRefExoticComponent<Omit<InputHTMLAttributes<HTMLInputElement>, "autoComplete" | "type"> & WithAutoComplete & WithInputType & WithValidation & {
26
+ declare const Input: _$react.ForwardRefExoticComponent<Omit<InputHTMLAttributes<HTMLInputElement>, "type" | "autoComplete"> & WithAutoComplete & WithInputType & WithValidation & {
27
27
  children?: _$react.ReactNode | undefined;
28
28
  } & _$react.RefAttributes<HTMLInputElement>>;
29
29
  type InputCaptureProps = Omit<InputHTMLAttributes<HTMLInputElement>, "autoComplete" | "type"> & BaseProps;
@@ -41,7 +41,7 @@ type InputCaptureProps = Omit<InputHTMLAttributes<HTMLInputElement>, "autoComple
41
41
  * </Input>
42
42
  * ```
43
43
  */
44
- declare const InputCapture: _$react.ForwardRefExoticComponent<Omit<InputHTMLAttributes<HTMLInputElement>, "autoComplete" | "type"> & WithAutoComplete & WithInputType & WithValidation & _$react.RefAttributes<HTMLInputElement>>;
44
+ declare const InputCapture: _$react.ForwardRefExoticComponent<Omit<InputHTMLAttributes<HTMLInputElement>, "type" | "autoComplete"> & WithAutoComplete & WithInputType & WithValidation & _$react.RefAttributes<HTMLInputElement>>;
45
45
  //#endregion
46
46
  //#region src/components/input/password-input.d.ts
47
47
  type PasswordInputProps = Omit<InputHTMLAttributes<HTMLInputElement>, "autoComplete" | "type"> & WithValidation & WithAutoComplete & {
@@ -56,21 +56,64 @@ type PasswordInputProps = Omit<InputHTMLAttributes<HTMLInputElement>, "autoCompl
56
56
  showValue?: boolean;
57
57
  };
58
58
  /**
59
- * A specialized input component for password entry with a toggle button to show/hide the password value.
60
- * Provides enhanced security UX by allowing users to verify their input while maintaining privacy.
59
+ * An input optimized for password and other sensitive-value entry. Renders a
60
+ * native `<input type="password">` with a built-in trailing button that
61
+ * toggles between hidden (`••••`) and revealed (`text`) display.
61
62
  *
62
- * @see https://mantle.ngrok.com/components/input
63
+ * **When to use**
64
+ * - Password fields on login, signup, and reset flows.
65
+ * - One-time tokens, recovery codes, or secrets the user needs to type
66
+ * accurately and may want to verify visually before submitting.
67
+ *
68
+ * **When not to use**
69
+ * - For values that are never sensitive — use a plain {@link https://mantle.ngrok.com/components/input Input}.
70
+ * - For controls where the toggle would be confusing (e.g. masked input
71
+ * formatting like phone numbers).
72
+ *
73
+ * **Visibility state.** The toggle is uncontrolled by default. Pass
74
+ * `showValue` to control the visibility from the outside (useful when one
75
+ * UI control toggles multiple password fields), and `onValueVisibilityChange`
76
+ * to be notified when the user toggles via the built-in button.
77
+ *
78
+ * **Accessibility.** Always pair with a {@link https://mantle.ngrok.com/components/label Label}.
79
+ * The toggle button has its own accessible name announcing the current
80
+ * state. The input keeps `autocomplete="current-password"` /
81
+ * `"new-password"` semantics — set `autoComplete` explicitly per flow.
82
+ *
83
+ * **Browser password managers.** When revealed, the input switches to
84
+ * `type="text"` — some password managers may pause autofill in this state,
85
+ * which is the intended security tradeoff.
86
+ *
87
+ * @see https://mantle.ngrok.com/components/password-input
63
88
  *
64
89
  * @example
65
90
  * ```tsx
66
- * <PasswordInput
67
- * placeholder="Enter your password"
68
- * showValue={false}
69
- * onValueVisibilityChange={(visible) => console.log('Password visible:', visible)}
70
- * />
91
+ * import { PasswordInput } from "@ngrok/mantle/input";
92
+ * import { Label } from "@ngrok/mantle/label";
93
+ * import { useState } from "react";
94
+ *
95
+ * // Basic — uncontrolled visibility.
96
+ * <Label className="grid gap-1">
97
+ * <span>Password</span>
98
+ * <PasswordInput name="password" autoComplete="current-password" />
99
+ * </Label>
100
+ *
101
+ * // Validation state.
102
+ * <PasswordInput validation="error" />
103
+ *
104
+ * // Controlled visibility — one toggle reveals multiple fields.
105
+ * function PasswordPair() {
106
+ * const [show, setShow] = useState(false);
107
+ * return (
108
+ * <>
109
+ * <PasswordInput showValue={show} onValueVisibilityChange={setShow} />
110
+ * <PasswordInput showValue={show} onValueVisibilityChange={setShow} />
111
+ * </>
112
+ * );
113
+ * }
71
114
  * ```
72
115
  */
73
- declare const PasswordInput: _$react.ForwardRefExoticComponent<Omit<InputHTMLAttributes<HTMLInputElement>, "autoComplete" | "type"> & WithValidation & WithAutoComplete & {
116
+ declare const PasswordInput: _$react.ForwardRefExoticComponent<Omit<InputHTMLAttributes<HTMLInputElement>, "type" | "autoComplete"> & WithValidation & WithAutoComplete & {
74
117
  /**
75
118
  * Callback for when the visibility of the password value changes.
76
119
  */
@@ -100,4 +143,4 @@ declare const PasswordInput: _$react.ForwardRefExoticComponent<Omit<InputHTMLAtt
100
143
  declare function isInput(value: unknown): value is HTMLInputElement;
101
144
  //#endregion
102
145
  export { InputCapture as a, Input as i, PasswordInput as n, InputCaptureProps as o, PasswordInputProps as r, InputProps as s, isInput as t };
103
- //# sourceMappingURL=index-ddHz7L9f.d.ts.map
146
+ //# sourceMappingURL=index-C91lxoX9.d.ts.map
@@ -1,12 +1,12 @@
1
- import { t as WithAsChild } from "./as-child-CJ2vTesV.js";
2
- import { t as VariantProps } from "./variant-props-DszdagRm.js";
1
+ import { t as WithAsChild } from "./as-child-DQHfEmYB.js";
2
+ import { t as VariantProps } from "./variant-props-DUmSIQK8.js";
3
3
  import * as _$react from "react";
4
4
  import { ComponentProps } from "react";
5
5
  import * as _$class_variance_authority_types0 from "class-variance-authority/types";
6
6
 
7
7
  //#region src/components/button/button-group.d.ts
8
8
  declare const buttonGroupVariants: (props?: ({
9
- appearance?: "panel" | "ghost" | "outlined" | null | undefined;
9
+ appearance?: "ghost" | "outlined" | "panel" | null | undefined;
10
10
  } & _$class_variance_authority_types0.ClassProp) | undefined) => string;
11
11
  type ButtonGroupVariants = VariantProps<typeof buttonGroupVariants>;
12
12
  type ButtonGroupProps = ComponentProps<"div"> & ButtonGroupVariants & WithAsChild;
@@ -27,4 +27,4 @@ type ButtonGroupProps = ComponentProps<"div"> & ButtonGroupVariants & WithAsChil
27
27
  declare const ButtonGroup: _$react.ForwardRefExoticComponent<Omit<ButtonGroupProps, "ref"> & _$react.RefAttributes<HTMLDivElement>>;
28
28
  //#endregion
29
29
  export { ButtonGroupProps as n, ButtonGroup as t };
30
- //# sourceMappingURL=index-DU3SQJ46.d.ts.map
30
+ //# sourceMappingURL=index-DOJUH34Z.d.ts.map
@@ -37,4 +37,4 @@ type Color = (typeof colors)[number];
37
37
  declare const isColor: (value: unknown) => value is Color;
38
38
  //#endregion
39
39
  export { functionalColors as a, isNamedColor as c, colors as i, namedColors as l, FunctionalColor as n, isColor as o, NamedColor as r, isFunctionalColor as s, Color as t };
40
- //# sourceMappingURL=index-B6SPk_xb.d.ts.map
40
+ //# sourceMappingURL=index-DkMUaYsw.d.ts.map
@@ -44,4 +44,4 @@ type CssProperties = CSSProperties & Record<CssVariableName, string | number>;
44
44
  declare const $cssProperties: <T extends CssProperties = CssProperties>(input: T) => CSSProperties;
45
45
  //#endregion
46
46
  export { parseBooleanish as i, CssProperties as n, Booleanish as r, $cssProperties as t };
47
- //# sourceMappingURL=index-vOSpS5jv.d.ts.map
47
+ //# sourceMappingURL=index-rtz7SwEq.d.ts.map