@ngrok/mantle 0.55.1 → 0.55.2

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.
@@ -1,48 +1,70 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { PropsWithChildren } from 'react';
3
+
1
4
  /**
2
- * React component that auto-scrolls to the element matching the current URL hash (e.g., `#subscription`).
5
+ * React component that auto-scrolls to the element matching the current URL hash
6
+ * (e.g., `#subscription`). It also provides a context so consumers can
7
+ * programmatically re-run the scroll after asynchronous content mounts.
8
+ *
9
+ * Behavior
10
+ * - Runs on initial mount and whenever the `location.hash` changes.
11
+ * - Schedules the scroll in `requestAnimationFrame` to ensure the target exists
12
+ * after DOM updates/paint.
13
+ * - Respects the user's motion preference via {@link useScrollBehavior}
14
+ * (i.e., `"auto"` when reduced motion is enabled; `"smooth"` otherwise).
15
+ * - Cancels a pending animation frame on unmount or dependency change.
16
+ *
17
+ * Accessibility
18
+ * - Honors reduced-motion preferences; no sudden scrolling for motion-sensitive users.
3
19
  *
4
- * Behavior:
5
- * - Runs on mount and whenever the `hash` changes.
6
- * - Schedules the scroll in `requestAnimationFrame` to ensure the target element
7
- * exists after DOM updates/paint.
8
- * - Respects the user's motion preference via `useScrollBehavior()` (i.e., `"auto"` when
9
- * reduced motion is enabled; `"smooth"` otherwise).
10
- * - Safe for SSR via `useIsomorphicLayoutEffect`.
20
+ * SSR
21
+ * - Uses {@link useIsomorphicLayoutEffect} so it is safe to include in code that may render on the server.
11
22
  *
12
23
  * @example
13
- * <AutoScrollToHash />
24
+ * ```tsx
25
+ * // App shell
26
+ * <Router>
27
+ * <AutoScrollToHash>
28
+ * <TheRestOfYourApp />
29
+ * </AutoScrollToHash>
30
+ * </Router>
31
+ * ```
14
32
  *
15
33
  * @remarks
16
34
  * If your content is loaded asynchronously and may not exist by the next animation
17
- * frame, consider enhancing the hook with a short retry loop or a `MutationObserver`.
18
- *
19
- * **Note:** This component requires `react-router` as a peer dependency.
35
+ * frame, call the public hook {@link useAutoScrollToHash} to re-run the scroll once
36
+ * the content is in the DOM.
20
37
  */
21
- declare function AutoScrollToHash(): null;
22
- type Props = {
23
- /** Disable automatic scrolling to hash targets. */
24
- disabled?: boolean;
25
- };
38
+ declare function AutoScrollToHash({ children }: PropsWithChildren): react_jsx_runtime.JSX.Element;
26
39
  /**
27
- * Hook that scrolls the element identified by `location.hash` into view.
40
+ * Public hook that returns a stable callback for programmatically re-running the
41
+ * hash-based scroll performed by {@link AutoScrollToHash}.
42
+ *
43
+ * Use this when the element for the current `location.hash` is rendered later
44
+ * (e.g., after lazy-loading a route, switching tabs, or finishing an async fetch)
45
+ * so you can bring it into view once it exists.
28
46
  *
29
- * - Exits early when `disabled` or when `hash` is empty.
30
- * - Attempts both the raw ID and a decoded ID (`decodeURIComponent`) for robustness.
31
- * - Uses `useScrollBehavior()` so motion-sensitive users get `"auto"` instead of `"smooth"`.
47
+ * The hook throws if it is used outside of an {@link AutoScrollToHash} provider.
32
48
  *
33
- * @param options.disabled When `true`, suppresses scrolling.
49
+ * @returns A stable `() => void` function that, when called, scrolls the hash target into view if present.
34
50
  *
35
51
  * @example
36
- * function Page() {
37
- * useAutoScrollToHash();
38
- * return <>{page content}</>;
39
- * }
52
+ * ```tsx
53
+ * function DetailsTab({ ready }: { ready: boolean }) {
54
+ * const reScroll = useAutoScrollToHash();
40
55
  *
41
- * @remarks
42
- * **Note:** This hook requires `react-router` as a peer dependency.
56
+ * useEffect(() => {
57
+ * if (ready) {
58
+ * reScroll();
59
+ * }
60
+ * }, [ready, reScroll]);
61
+ *
62
+ * return <div id="subscription">...</div>;
63
+ * }
64
+ * ```
43
65
  *
44
- * @see {@link useScrollBehavior} for how the scroll behavior is chosen.
66
+ * @see {@link AutoScrollToHash}
45
67
  */
46
- declare function useAutoScrollToHash({ disabled }?: Props): void;
68
+ declare function useAutoScrollToHash(): () => void;
47
69
 
48
70
  export { AutoScrollToHash, useAutoScrollToHash };
@@ -1,2 +1,2 @@
1
- import{a as s,c as l}from"./chunk-V4TWM6RF.js";import{useLocation as u}from"react-router";function m(){return i(),null}function i({disabled:n=!1}={}){let{hash:e}=u(),c=l();s(()=>{if(n||!e)return;let t=e.replace(/^#/,""),r=[t];try{let o=window.decodeURIComponent(t);o&&o!==t&&r.push(o)}catch{}let a=0;return a=window.requestAnimationFrame(()=>{(document.getElementById(r[0]??"")??document.getElementById(r[1]??""))?.scrollIntoView({behavior:c})}),()=>{window.cancelAnimationFrame(a)}},[e,n,c])}export{m as AutoScrollToHash,i as useAutoScrollToHash};
1
+ import{a as s,c as a}from"./chunk-V4TWM6RF.js";import{createContext as i,useCallback as m,useContext as d,useRef as h}from"react";import{useLocation as f}from"react-router";import p from"tiny-invariant";import{jsx as S}from"react/jsx-runtime";var u=i(()=>{});function T({children:o}){let t=H();return S(u.Provider,{value:t,children:o})}function A(){let o=d(u);return p(o,"useAutoScrollToHash must be used within an AutoScrollToHash provider"),o}function H(){let{hash:o}=f(),t=a(),c=h(0),l=m(()=>{if(!o)return;let r=o.replace(/^#/,""),n=[r];try{let e=window.decodeURIComponent(r);e&&e!==r&&n.push(e)}catch{}c.current=window.requestAnimationFrame(()=>{(document.getElementById(n[0]??"")??document.getElementById(n[1]??""))?.scrollIntoView({behavior:t})})},[o,t]);return s(()=>(l(),()=>{window.cancelAnimationFrame(c.current)}),[o,t]),l}export{T as AutoScrollToHash,A as useAutoScrollToHash};
2
2
  //# sourceMappingURL=auto-scroll-to-hash.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/auto-scroll-to-hash/auto-scroll-to-hash.tsx"],"sourcesContent":["import { useLocation } from \"react-router\";\nimport { useIsomorphicLayoutEffect } from \"../../hooks/use-isomorphic-layout-effect.js\";\nimport { useScrollBehavior } from \"../../hooks/use-scroll-behavior.js\";\n\n/**\n * React component that auto-scrolls to the element matching the current URL hash (e.g., `#subscription`).\n *\n * Behavior:\n * - Runs on mount and whenever the `hash` changes.\n * - Schedules the scroll in `requestAnimationFrame` to ensure the target element\n * exists after DOM updates/paint.\n * - Respects the user's motion preference via `useScrollBehavior()` (i.e., `\"auto\"` when\n * reduced motion is enabled; `\"smooth\"` otherwise).\n * - Safe for SSR via `useIsomorphicLayoutEffect`.\n *\n * @example\n * <AutoScrollToHash />\n *\n * @remarks\n * If your content is loaded asynchronously and may not exist by the next animation\n * frame, consider enhancing the hook with a short retry loop or a `MutationObserver`.\n *\n * **Note:** This component requires `react-router` as a peer dependency.\n */\nfunction AutoScrollToHash() {\n\tuseAutoScrollToHash();\n\n\treturn null;\n}\n\ntype Props = {\n\t/** Disable automatic scrolling to hash targets. */\n\tdisabled?: boolean;\n};\n\n/**\n * Hook that scrolls the element identified by `location.hash` into view.\n *\n * - Exits early when `disabled` or when `hash` is empty.\n * - Attempts both the raw ID and a decoded ID (`decodeURIComponent`) for robustness.\n * - Uses `useScrollBehavior()` so motion-sensitive users get `\"auto\"` instead of `\"smooth\"`.\n *\n * @param options.disabled When `true`, suppresses scrolling.\n *\n * @example\n * function Page() {\n * useAutoScrollToHash();\n * return <>{page content}</>;\n * }\n *\n * @remarks\n * **Note:** This hook requires `react-router` as a peer dependency.\n *\n * @see {@link useScrollBehavior} for how the scroll behavior is chosen.\n */\nfunction useAutoScrollToHash({ disabled = false }: Props = {}) {\n\tconst { hash } = useLocation();\n\tconst scrollBehavior = useScrollBehavior();\n\n\tuseIsomorphicLayoutEffect(() => {\n\t\tif (disabled || !hash) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Strip leading '#' and consider both raw and decoded forms.\n\t\tconst rawId = hash.replace(/^#/, \"\");\n\t\tconst candidates = [rawId];\n\t\ttry {\n\t\t\tconst decoded = window.decodeURIComponent(rawId);\n\t\t\tif (decoded && decoded !== rawId) {\n\t\t\t\tcandidates.push(decoded);\n\t\t\t}\n\t\t} catch {\n\t\t\t// ignore malformed encodings and fall back to raw\n\t\t}\n\n\t\tlet handle = 0;\n\t\thandle = window.requestAnimationFrame(() => {\n\t\t\t// Resolve the first element that exists among our candidates.\n\t\t\tconst target =\n\t\t\t\tdocument.getElementById(candidates[0] ?? \"\") ??\n\t\t\t\tdocument.getElementById(candidates[1] ?? \"\");\n\n\t\t\ttarget?.scrollIntoView({ behavior: scrollBehavior });\n\t\t});\n\n\t\treturn () => {\n\t\t\twindow.cancelAnimationFrame(handle);\n\t\t};\n\t}, [hash, disabled, scrollBehavior]);\n}\n\nexport {\n\t//,\n\tAutoScrollToHash,\n\tuseAutoScrollToHash,\n};\n"],"mappings":"+CAAA,OAAS,eAAAA,MAAmB,eAwB5B,SAASC,GAAmB,CAC3B,OAAAC,EAAoB,EAEb,IACR,CA2BA,SAASA,EAAoB,CAAE,SAAAC,EAAW,EAAM,EAAW,CAAC,EAAG,CAC9D,GAAM,CAAE,KAAAC,CAAK,EAAIC,EAAY,EACvBC,EAAiBC,EAAkB,EAEzCC,EAA0B,IAAM,CAC/B,GAAIL,GAAY,CAACC,EAChB,OAID,IAAMK,EAAQL,EAAK,QAAQ,KAAM,EAAE,EAC7BM,EAAa,CAACD,CAAK,EACzB,GAAI,CACH,IAAME,EAAU,OAAO,mBAAmBF,CAAK,EAC3CE,GAAWA,IAAYF,GAC1BC,EAAW,KAAKC,CAAO,CAEzB,MAAQ,CAER,CAEA,IAAIC,EAAS,EACb,OAAAA,EAAS,OAAO,sBAAsB,IAAM,EAG1C,SAAS,eAAeF,EAAW,CAAC,GAAK,EAAE,GAC3C,SAAS,eAAeA,EAAW,CAAC,GAAK,EAAE,IAEpC,eAAe,CAAE,SAAUJ,CAAe,CAAC,CACpD,CAAC,EAEM,IAAM,CACZ,OAAO,qBAAqBM,CAAM,CACnC,CACD,EAAG,CAACR,EAAMD,EAAUG,CAAc,CAAC,CACpC","names":["useLocation","AutoScrollToHash","useAutoScrollToHash","disabled","hash","useLocation","scrollBehavior","useScrollBehavior","useIsomorphicLayoutEffect","rawId","candidates","decoded","handle"]}
1
+ {"version":3,"sources":["../src/components/auto-scroll-to-hash/auto-scroll-to-hash.tsx"],"sourcesContent":["import {\n\ttype PropsWithChildren,\n\tcreateContext,\n\tuseCallback,\n\tuseContext,\n\tuseRef,\n} from \"react\";\nimport { useLocation } from \"react-router\";\nimport invariant from \"tiny-invariant\";\nimport { useIsomorphicLayoutEffect } from \"../../hooks/use-isomorphic-layout-effect.js\";\nimport { useScrollBehavior } from \"../../hooks/use-scroll-behavior.js\";\n\nconst AutoScrollToHashContext = createContext<() => void>(() => {});\n\n/**\n * React component that auto-scrolls to the element matching the current URL hash\n * (e.g., `#subscription`). It also provides a context so consumers can\n * programmatically re-run the scroll after asynchronous content mounts.\n *\n * Behavior\n * - Runs on initial mount and whenever the `location.hash` changes.\n * - Schedules the scroll in `requestAnimationFrame` to ensure the target exists\n * after DOM updates/paint.\n * - Respects the user's motion preference via {@link useScrollBehavior}\n * (i.e., `\"auto\"` when reduced motion is enabled; `\"smooth\"` otherwise).\n * - Cancels a pending animation frame on unmount or dependency change.\n *\n * Accessibility\n * - Honors reduced-motion preferences; no sudden scrolling for motion-sensitive users.\n *\n * SSR\n * - Uses {@link useIsomorphicLayoutEffect} so it is safe to include in code that may render on the server.\n *\n * @example\n * ```tsx\n * // App shell\n * <Router>\n * <AutoScrollToHash>\n * <TheRestOfYourApp />\n * </AutoScrollToHash>\n * </Router>\n * ```\n *\n * @remarks\n * If your content is loaded asynchronously and may not exist by the next animation\n * frame, call the public hook {@link useAutoScrollToHash} to re-run the scroll once\n * the content is in the DOM.\n */\nfunction AutoScrollToHash({ children }: PropsWithChildren) {\n\tconst scrollToElement = useInternalAutoScrollToHash();\n\n\treturn (\n\t\t<AutoScrollToHashContext.Provider value={scrollToElement}>\n\t\t\t{children}\n\t\t</AutoScrollToHashContext.Provider>\n\t);\n}\n\n/**\n * Public hook that returns a stable callback for programmatically re-running the\n * hash-based scroll performed by {@link AutoScrollToHash}.\n *\n * Use this when the element for the current `location.hash` is rendered later\n * (e.g., after lazy-loading a route, switching tabs, or finishing an async fetch)\n * so you can bring it into view once it exists.\n *\n * The hook throws if it is used outside of an {@link AutoScrollToHash} provider.\n *\n * @returns A stable `() => void` function that, when called, scrolls the hash target into view if present.\n *\n * @example\n * ```tsx\n * function DetailsTab({ ready }: { ready: boolean }) {\n * const reScroll = useAutoScrollToHash();\n *\n * useEffect(() => {\n * if (ready) {\n * reScroll();\n * }\n * }, [ready, reScroll]);\n *\n * return <div id=\"subscription\">...</div>;\n * }\n * ```\n *\n * @see {@link AutoScrollToHash}\n */\nfunction useAutoScrollToHash() {\n\tconst scrollToElement = useContext(AutoScrollToHashContext);\n\tinvariant(\n\t\tscrollToElement,\n\t\t\"useAutoScrollToHash must be used within an AutoScrollToHash provider\",\n\t);\n\treturn scrollToElement;\n}\n\nexport {\n\t//,\n\tAutoScrollToHash,\n\tuseAutoScrollToHash,\n};\n\n/**\n * Internal hook that scrolls the element identified by `location.hash` into view\n * and returns a function you can call to trigger the same behavior manually.\n *\n * Implementation notes\n * - Exits early when `hash` is empty.\n * - Attempts both the raw ID and a decoded ID (`decodeURIComponent`) for robustness.\n * - Uses {@link useScrollBehavior} so motion-sensitive users get `\"auto\"` instead of `\"smooth\"`.\n * - Schedules the scroll in `requestAnimationFrame` to avoid racing DOM paint.\n * - Cancels any pending frame on cleanup.\n *\n * @returns A stable `() => void` that attempts to scroll the hash target into view.\n *\n * @internal\n */\nfunction useInternalAutoScrollToHash() {\n\tconst { hash } = useLocation();\n\tconst scrollBehavior = useScrollBehavior();\n\tconst rafHandle = useRef(0);\n\n\tconst scrollToElement = useCallback(() => {\n\t\tif (!hash) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Strip leading '#' and consider both raw and decoded forms.\n\t\tconst rawId = hash.replace(/^#/, \"\");\n\t\tconst candidates = [rawId];\n\t\ttry {\n\t\t\tconst decoded = window.decodeURIComponent(rawId);\n\t\t\tif (decoded && decoded !== rawId) {\n\t\t\t\tcandidates.push(decoded);\n\t\t\t}\n\t\t} catch {\n\t\t\t// ignore malformed encodings and fall back to raw\n\t\t}\n\n\t\trafHandle.current = window.requestAnimationFrame(() => {\n\t\t\t// Resolve the first element that exists among our candidates.\n\t\t\tconst target =\n\t\t\t\tdocument.getElementById(candidates[0] ?? \"\") ??\n\t\t\t\tdocument.getElementById(candidates[1] ?? \"\");\n\n\t\t\ttarget?.scrollIntoView({ behavior: scrollBehavior });\n\t\t});\n\t}, [hash, scrollBehavior]);\n\n\tuseIsomorphicLayoutEffect(() => {\n\t\tscrollToElement();\n\n\t\treturn () => {\n\t\t\twindow.cancelAnimationFrame(rafHandle.current);\n\t\t};\n\t}, [hash, scrollBehavior]);\n\n\treturn scrollToElement;\n}\n"],"mappings":"+CAAA,OAEC,iBAAAA,EACA,eAAAC,EACA,cAAAC,EACA,UAAAC,MACM,QACP,OAAS,eAAAC,MAAmB,eAC5B,OAAOC,MAAe,iBA4CpB,cAAAC,MAAA,oBAxCF,IAAMC,EAA0BC,EAA0B,IAAM,CAAC,CAAC,EAoClE,SAASC,EAAiB,CAAE,SAAAC,CAAS,EAAsB,CAC1D,IAAMC,EAAkBC,EAA4B,EAEpD,OACCN,EAACC,EAAwB,SAAxB,CAAiC,MAAOI,EACvC,SAAAD,EACF,CAEF,CA+BA,SAASG,GAAsB,CAC9B,IAAMF,EAAkBG,EAAWP,CAAuB,EAC1D,OAAAQ,EACCJ,EACA,sEACD,EACOA,CACR,CAuBA,SAASK,GAA8B,CACtC,GAAM,CAAE,KAAAC,CAAK,EAAIC,EAAY,EACvBC,EAAiBC,EAAkB,EACnCC,EAAYC,EAAO,CAAC,EAEpBC,EAAkBC,EAAY,IAAM,CACzC,GAAI,CAACP,EACJ,OAID,IAAMQ,EAAQR,EAAK,QAAQ,KAAM,EAAE,EAC7BS,EAAa,CAACD,CAAK,EACzB,GAAI,CACH,IAAME,EAAU,OAAO,mBAAmBF,CAAK,EAC3CE,GAAWA,IAAYF,GAC1BC,EAAW,KAAKC,CAAO,CAEzB,MAAQ,CAER,CAEAN,EAAU,QAAU,OAAO,sBAAsB,IAAM,EAGrD,SAAS,eAAeK,EAAW,CAAC,GAAK,EAAE,GAC3C,SAAS,eAAeA,EAAW,CAAC,GAAK,EAAE,IAEpC,eAAe,CAAE,SAAUP,CAAe,CAAC,CACpD,CAAC,CACF,EAAG,CAACF,EAAME,CAAc,CAAC,EAEzB,OAAAS,EAA0B,KACzBL,EAAgB,EAET,IAAM,CACZ,OAAO,qBAAqBF,EAAU,OAAO,CAC9C,GACE,CAACJ,EAAME,CAAc,CAAC,EAElBI,CACR","names":["createContext","useCallback","useContext","useRef","useLocation","invariant","jsx","AutoScrollToHashContext","createContext","AutoScrollToHash","children","scrollToElement","useInternalAutoScrollToHash","useAutoScrollToHash","useContext","invariant","useInternalAutoScrollToHash","hash","useLocation","scrollBehavior","useScrollBehavior","rafHandle","useRef","scrollToElement","useCallback","rawId","candidates","decoded","useIsomorphicLayoutEffect"]}
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "description": "mantle is ngrok's UI library and design system.",
4
4
  "author": "ngrok",
5
5
  "license": "MIT",
6
- "version": "0.55.1",
6
+ "version": "0.55.2",
7
7
  "homepage": "https://mantle.ngrok.com",
8
8
  "repository": {
9
9
  "type": "git",