@ngrok/mantle 0.9.1 → 0.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/assets/mantle.css CHANGED
@@ -1618,4 +1618,21 @@
1618
1618
  100% 14px;
1619
1619
  background-attachment: local, local, scroll, scroll;
1620
1620
  }
1621
+
1622
+ .nav-scroll-shadow {
1623
+ background:
1624
+ /* Shadow Cover TOP */
1625
+ linear-gradient(hsl(var(--bg-popover)) 30%, hsl(var(--bg-popover) / 0%)) center top,
1626
+ /* Shadow Cover BOTTOM */ linear-gradient(hsl(var(--bg-popover) / 0%), hsl(var(--bg-popover)) 70%) center bottom,
1627
+ /* Shadow TOP */ radial-gradient(farthest-side at 50% 0, var(--navigation-shadow), rgb(0 0 0 / 0%)) center top,
1628
+ /* Shadow BOTTOM */ radial-gradient(farthest-side at 50% 100%, var(--navigation-shadow), rgb(0 0 0 / 0%)) center
1629
+ bottom;
1630
+ background-repeat: no-repeat;
1631
+ background-size:
1632
+ 100% 40px,
1633
+ 100% 40px,
1634
+ 100% 14px,
1635
+ 100% 14px;
1636
+ background-attachment: local, local, scroll, scroll;
1637
+ }
1621
1638
  }
package/dist/hooks.js CHANGED
@@ -1,2 +1,2 @@
1
- import{a as f}from"./chunk-D3XF6J5A.js";import{a as u}from"./chunk-ZBC4B4EM.js";import{a as n}from"./chunk-IWKI4XHM.js";import{useEffect as c,useLayoutEffect as i}from"react";var d=typeof window<"u"?i:c;import{useEffect as a,useState as m}from"react";var p="(prefers-reduced-motion: no-preference)";function y(){let[r,o]=m(!0);return a(()=>{let e=window.matchMedia(p);o(!e.matches);function t(s){o(!s.matches)}return e.addEventListener("change",t),()=>{e.removeEventListener("change",t)}},[]),r}export{n as useCopyToClipboard,d as useIsomorphicLayoutEffect,f as useMatchesMediaQuery,y as usePrefersReducedMotion,u as useRandomStableId};
1
+ import{a as u}from"./chunk-D3XF6J5A.js";import{a as s}from"./chunk-IWKI4XHM.js";import{useEffect as i,useLayoutEffect as f}from"react";var c=typeof window<"u"?f:i;import{useEffect as d,useState as m}from"react";var a="(prefers-reduced-motion: no-preference)";function p(){let[e,t]=m(!0);return d(()=>{let o=window.matchMedia(a);t(!o.matches);function r(n){t(!n.matches)}return o.addEventListener("change",r),()=>{o.removeEventListener("change",r)}},[]),e}import{useMemo as x}from"react";var M=(e="mantle")=>x(()=>h(e),[e]);function h(e="mantle"){return[e.trim()||"mantle",y()].join("-")}function y(){return Math.random().toString(36).substring(2,9)}export{s as useCopyToClipboard,c as useIsomorphicLayoutEffect,u as useMatchesMediaQuery,p as usePrefersReducedMotion,M as useRandomStableId};
2
2
  //# sourceMappingURL=hooks.js.map
package/dist/hooks.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/hooks/use-isomorphic-layout-effect.tsx","../src/hooks/use-prefers-reduced-motion.tsx"],"sourcesContent":["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 = typeof window !== \"undefined\" ? useLayoutEffect : useEffect;\n","import { useEffect, useState } from \"react\";\n\n/**\n * no-preference is the default value for the prefers-reduced-motion media query.\n * Users who have never fiddled with their a11y settings will still see animations\n * (no explicit opt-in required from a user's perspective)\n */\nconst query = \"(prefers-reduced-motion: no-preference)\";\n\n/**\n * usePrefersReducedMotion returns true if the user has opted out of animations\n */\nexport function usePrefersReducedMotion() {\n\t// default to no animations, since we don't know what the user's preference is on the server\n\tconst [prefersReducedMotion, setPrefersReducedMotion] = useState(true);\n\n\tuseEffect(() => {\n\t\tconst mediaQueryList = window.matchMedia(query);\n\n\t\t// set the _real_ initial value now that we're on the client\n\t\tsetPrefersReducedMotion(!mediaQueryList.matches);\n\n\t\t// register for updates\n\t\tfunction listener(event: MediaQueryListEvent) {\n\t\t\tsetPrefersReducedMotion(!event.matches);\n\t\t}\n\n\t\tmediaQueryList.addEventListener(\"change\", listener);\n\n\t\treturn () => {\n\t\t\tmediaQueryList.removeEventListener(\"change\", listener);\n\t\t};\n\t}, []);\n\n\treturn prefersReducedMotion;\n}\n"],"mappings":"wHAAA,OAAS,aAAAA,EAAW,mBAAAC,MAAuB,QAKpC,IAAMC,EAA4B,OAAO,OAAW,IAAcD,EAAkBD,ECL3F,OAAS,aAAAG,EAAW,YAAAC,MAAgB,QAOpC,IAAMC,EAAQ,0CAKP,SAASC,GAA0B,CAEzC,GAAM,CAACC,EAAsBC,CAAuB,EAAIJ,EAAS,EAAI,EAErE,OAAAD,EAAU,IAAM,CACf,IAAMM,EAAiB,OAAO,WAAWJ,CAAK,EAG9CG,EAAwB,CAACC,EAAe,OAAO,EAG/C,SAASC,EAASC,EAA4B,CAC7CH,EAAwB,CAACG,EAAM,OAAO,CACvC,CAEA,OAAAF,EAAe,iBAAiB,SAAUC,CAAQ,EAE3C,IAAM,CACZD,EAAe,oBAAoB,SAAUC,CAAQ,CACtD,CACD,EAAG,CAAC,CAAC,EAEEH,CACR","names":["useEffect","useLayoutEffect","useIsomorphicLayoutEffect","useEffect","useState","query","usePrefersReducedMotion","prefersReducedMotion","setPrefersReducedMotion","mediaQueryList","listener","event"]}
1
+ {"version":3,"sources":["../src/hooks/use-isomorphic-layout-effect.tsx","../src/hooks/use-prefers-reduced-motion.tsx","../src/hooks/use-random-stable-id.tsx"],"sourcesContent":["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 = typeof window !== \"undefined\" ? useLayoutEffect : useEffect;\n","import { useEffect, useState } from \"react\";\n\n/**\n * no-preference is the default value for the prefers-reduced-motion media query.\n * Users who have never fiddled with their a11y settings will still see animations\n * (no explicit opt-in required from a user's perspective)\n */\nconst query = \"(prefers-reduced-motion: no-preference)\";\n\n/**\n * usePrefersReducedMotion returns true if the user has opted out of animations\n */\nexport function usePrefersReducedMotion() {\n\t// default to no animations, since we don't know what the user's preference is on the server\n\tconst [prefersReducedMotion, setPrefersReducedMotion] = useState(true);\n\n\tuseEffect(() => {\n\t\tconst mediaQueryList = window.matchMedia(query);\n\n\t\t// set the _real_ initial value now that we're on the client\n\t\tsetPrefersReducedMotion(!mediaQueryList.matches);\n\n\t\t// register for updates\n\t\tfunction listener(event: MediaQueryListEvent) {\n\t\t\tsetPrefersReducedMotion(!event.matches);\n\t\t}\n\n\t\tmediaQueryList.addEventListener(\"change\", listener);\n\n\t\treturn () => {\n\t\t\tmediaQueryList.removeEventListener(\"change\", listener);\n\t\t};\n\t}, []);\n\n\treturn prefersReducedMotion;\n}\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"],"mappings":"gFAAA,OAAS,aAAAA,EAAW,mBAAAC,MAAuB,QAKpC,IAAMC,EAA4B,OAAO,OAAW,IAAcD,EAAkBD,ECL3F,OAAS,aAAAG,EAAW,YAAAC,MAAgB,QAOpC,IAAMC,EAAQ,0CAKP,SAASC,GAA0B,CAEzC,GAAM,CAACC,EAAsBC,CAAuB,EAAIJ,EAAS,EAAI,EAErE,OAAAD,EAAU,IAAM,CACf,IAAMM,EAAiB,OAAO,WAAWJ,CAAK,EAG9CG,EAAwB,CAACC,EAAe,OAAO,EAG/C,SAASC,EAASC,EAA4B,CAC7CH,EAAwB,CAACG,EAAM,OAAO,CACvC,CAEA,OAAAF,EAAe,iBAAiB,SAAUC,CAAQ,EAE3C,IAAM,CACZD,EAAe,oBAAoB,SAAUC,CAAQ,CACtD,CACD,EAAG,CAAC,CAAC,EAEEH,CACR,CCnCA,OAAS,WAAAK,MAAe,QAOxB,IAAMC,EAAoB,CAACC,EAAS,WAAaF,EAAQ,IAAMG,EAAeD,CAAM,EAAG,CAACA,CAAM,CAAC,EAO/F,SAASE,EAAeC,EAAS,SAAU,CAE1C,MAAO,CADSA,EAAO,KAAK,GAAK,SAChBC,EAAc,CAAC,EAAE,KAAK,GAAG,CAC3C,CAEA,SAASA,GAAgB,CACxB,OAAO,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,UAAU,EAAG,CAAC,CACjD","names":["useEffect","useLayoutEffect","useIsomorphicLayoutEffect","useEffect","useState","query","usePrefersReducedMotion","prefersReducedMotion","setPrefersReducedMotion","mediaQueryList","listener","event","useMemo","useRandomStableId","prefix","randomStableId","randomStableId","prefix","randomPostfix"]}
package/dist/progress.js CHANGED
@@ -1,2 +1,2 @@
1
- import{a as b}from"./chunk-ZBC4B4EM.js";import{a as c}from"./chunk-EW5CFGXT.js";import y from"clsx";import{createContext as k,useContext as N,useMemo as V}from"react";import{jsx as a,jsxs as d}from"react/jsx-runtime";var l=100,p={max:l,strokeWidth:"0.25rem",value:0},g=k(p),C=({children:e,className:t,max:r=l,strokeWidth:n=4,value:s,...u})=>{let o=M(r)?r:l,i=S(s,o)?s:s==null?0:"indeterminate",m=h(n??p.strokeWidth),f=x(i)?i:void 0,P=`calc(50% - ${m/2}px)`,v=V(()=>({max:o,strokeWidth:m,value:i}),[o,m,i]);return a(g.Provider,{value:v,children:d("svg",{"aria-valuemax":o,"aria-valuemin":0,"aria-valuenow":f,className:y(i==="indeterminate"&&"animation-duration-[15s] transform-gpu animate-spin",c("size-6 text-gray-200 dark:text-gray-300",t)),"data-max":o,"data-min":0,"data-value":f,height:"100%",role:"progressbar",width:"100%",...u,children:[a("circle",{cx:"50%",cy:"50%",fill:"transparent",r:P,stroke:"currentColor",strokeWidth:m}),e]})})},W=.6,w=({className:e,...t})=>{let r=b(),n=N(g)??p,s=(n.value=="indeterminate"?W:n.value/n.max)*100,u=h(n.strokeWidth),o=`calc(50% - ${u/2}px)`;return d("g",{className:c("text-accent-600",e),...t,children:[n.value=="indeterminate"&&a("defs",{children:d("linearGradient",{id:r,children:[a("stop",{className:"stop-opacity-100 stop-color-current",offset:"0%"}),a("stop",{className:"stop-opacity-0 stop-color-current",offset:"95%"})]})}),a("circle",{cx:"50%",cy:"50%",fill:"transparent",pathLength:100,r:o,stroke:n.value=="indeterminate"?`url(#${r})`:"currentColor",strokeDasharray:100,strokeDashoffset:100-s,strokeLinecap:"round",strokeWidth:u,"transform-origin":"center",transform:"rotate(-90)"})]})};function D(e,{min:t,max:r}){return Math.min(r,Math.max(t,e))}function h(e){let t=4;if(e==null)return t;typeof e=="number"?t=e:e.endsWith("rem")?t=Number(e.replace("rem",""))*16:t=Number(e);let r=Number.isNaN(t)?4:t;return D(r,{min:1,max:12})}function x(e){return typeof e=="number"}function S(e,t){return x(e)&&!Number.isNaN(e)&&e<=t&&e>=0}function M(e){return x(e)&&!Number.isNaN(e)&&e>0}export{C as ProgressDonut,w as ProgressDonutIndicator};
1
+ import{a as c}from"./chunk-EW5CFGXT.js";import y from"clsx";import{createContext as N,useContext as k,useId as C,useMemo as V}from"react";import{jsx as s,jsxs as d}from"react/jsx-runtime";var l=100,p={max:l,strokeWidth:"0.25rem",value:0},b=N(p),S=({children:e,className:t,max:r=l,strokeWidth:n=4,value:o,...u})=>{let a=T(r)?r:l,i=M(o,a)?o:o==null?0:"indeterminate",m=g(n??p.strokeWidth),x=f(i)?i:void 0,h=P(m),v=V(()=>({max:a,strokeWidth:m,value:i}),[a,m,i]);return s(b.Provider,{value:v,children:d("svg",{"aria-valuemax":a,"aria-valuemin":0,"aria-valuenow":x,className:y(i==="indeterminate"&&"animation-duration-[15s] transform-gpu animate-spin",c("size-6 text-gray-200 dark:text-gray-300",t)),"data-max":a,"data-min":0,"data-value":x,height:"100%",role:"progressbar",width:"100%",...u,children:[s("circle",{className:"[r:var(--radius)]",cx:"50%",cy:"50%",fill:"transparent",stroke:"currentColor",strokeWidth:m,style:{"--radius":h}}),e]})})},W=.6,w=({className:e,...t})=>{let r=C(),n=k(b)??p,o=(n.value=="indeterminate"?W:n.value/n.max)*100,u=g(n.strokeWidth),a=P(u);return d("g",{className:c("text-accent-600",e),...t,children:[n.value=="indeterminate"&&s("defs",{children:d("linearGradient",{id:r,children:[s("stop",{className:"stop-opacity-100 stop-color-current",offset:"0%"}),s("stop",{className:"stop-opacity-0 stop-color-current",offset:"95%"})]})}),s("circle",{className:"[r:var(--radius)]",cx:"50%",cy:"50%",fill:"transparent",pathLength:100,stroke:n.value=="indeterminate"?`url(#${r})`:"currentColor",strokeDasharray:100,strokeDashoffset:100-o,strokeLinecap:"round",strokeWidth:u,style:{"--radius":a},"transform-origin":"center",transform:"rotate(-90)"})]})};function D(e,{min:t,max:r}){return Math.min(r,Math.max(t,e))}function g(e){let t=4;if(e==null)return t;typeof e=="number"?t=e:e.endsWith("rem")?t=Number(e.replace("rem",""))*16:t=Number(e);let r=Number.isNaN(t)?4:t;return D(r,{min:1,max:12})}function f(e){return typeof e=="number"}function M(e,t){return f(e)&&!Number.isNaN(e)&&e<=t&&e>=0}function T(e){return f(e)&&!Number.isNaN(e)&&e>0}function P(e){return`calc(50% - ${e/2}px)`}export{S as ProgressDonut,w as ProgressDonutIndicator};
2
2
  //# sourceMappingURL=progress.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/progress/progress-donut.tsx"],"sourcesContent":["import clsx from \"clsx\";\nimport { createContext, useContext, useMemo } from \"react\";\nimport type { ComponentProps, HTMLAttributes } from \"react\";\nimport { useRandomStableId } from \"../../hooks/use-random-stable-id.js\";\nimport { cx } from \"../../utils/cx/cx.js\";\n\ntype RemValue = `${number}rem`;\ntype StrokeWidth = number | RemValue;\ntype ValueType = number | \"indeterminate\";\n\n/**\n * The default maximum value of the progress bar.\n */\nconst defaultMax = 100;\n\ntype ProgressContextValue = {\n\tmax: number;\n\tstrokeWidth: StrokeWidth;\n\tvalue: ValueType;\n};\n\nconst defaultContextValue = {\n\tmax: defaultMax,\n\tstrokeWidth: \"0.25rem\",\n\tvalue: 0,\n} as const satisfies ProgressContextValue;\n\nconst ProgressContext = createContext<ProgressContextValue>(defaultContextValue);\n\ntype SvgAttributes = Omit<\n\tHTMLAttributes<SVGElement>,\n\t\"viewBox\" | \"role\" | \"aria-valuemax\" | \"aria-valuemin\" | \"aria-valuenow\" | \"width\" | \"height\"\n>;\n\ntype Props = SvgAttributes & {\n\t/**\n\t * The maximum value of the progress bar.\n\t * This attribute describes how much work the task indicated by the progress element requires.\n\t * The max attribute, if present, must have a value greater than 0. The default value is 100.\n\t *\n\t * @default 100\n\t */\n\tmax?: number | undefined;\n\t/**\n\t * The width of the progress bar stroke.\n\t * Note, we clamp the stroke width to a minimum of 1px and max of 12px since\n\t * it is proportional to the viewbox size (0 0 32 32).\n\t *\n\t * @default 0.25rem (4px)\n\t */\n\tstrokeWidth?: StrokeWidth;\n\t/**\n\t * The current value of the progress bar.\n\t * This attribute specifies how much of the task that has been completed.\n\t * It must be a valid floating point number between 0 and max, or between 0 and 100 if max is omitted.\n\t * If set to `\"indeterminate\"`, the progress bar is considered indeterminate.\n\t *\n\t * @default 0\n\t */\n\tvalue?: ValueType | undefined;\n};\n\n/**\n * A simple circular progress bar.\n */\nconst ProgressDonut = ({\n\tchildren,\n\tclassName,\n\tmax: _max = defaultMax,\n\tstrokeWidth: _strokeWidth = 4,\n\tvalue: _value,\n\t...props\n}: Props) => {\n\tconst max = isValidMaxNumber(_max) ? _max : defaultMax;\n\tconst value = (isValidValueNumber(_value, max) ? _value : _value == null ? 0 : \"indeterminate\") satisfies ValueType;\n\tconst strokeWidthPx = deriveStrokeWidthPx(_strokeWidth ?? defaultContextValue.strokeWidth);\n\tconst valueNow = isNumber(value) ? value : undefined;\n\tconst radius = `calc(50% - ${strokeWidthPx / 2}px)` as const;\n\n\tconst ctx: ProgressContextValue = useMemo(\n\t\t() => ({\n\t\t\tmax,\n\t\t\tstrokeWidth: strokeWidthPx,\n\t\t\tvalue,\n\t\t}),\n\t\t[max, strokeWidthPx, value],\n\t);\n\n\treturn (\n\t\t<ProgressContext.Provider value={ctx}>\n\t\t\t<svg\n\t\t\t\taria-valuemax={max}\n\t\t\t\taria-valuemin={0}\n\t\t\t\taria-valuenow={valueNow}\n\t\t\t\tclassName={clsx(\n\t\t\t\t\tvalue === \"indeterminate\" && \"animation-duration-[15s] transform-gpu animate-spin\",\n\t\t\t\t\tcx(\"size-6 text-gray-200 dark:text-gray-300\", className),\n\t\t\t\t)}\n\t\t\t\tdata-max={max}\n\t\t\t\tdata-min={0}\n\t\t\t\tdata-value={valueNow}\n\t\t\t\theight=\"100%\"\n\t\t\t\trole=\"progressbar\"\n\t\t\t\twidth=\"100%\"\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t<circle cx=\"50%\" cy=\"50%\" fill=\"transparent\" r={radius} stroke=\"currentColor\" strokeWidth={strokeWidthPx} />\n\t\t\t\t{children}\n\t\t\t</svg>\n\t\t</ProgressContext.Provider>\n\t);\n};\n\n/**\n * Length (value) of the progress indicator tail when the progress bar is indeterminate.\n */\nconst indeterminateTailPercent = 0.6;\n\ntype ProgressDonutIndicatorProps = Omit<ComponentProps<\"g\">, \"children\">;\n\n/**\n * The indicator for the circular progress bar.\n */\nconst ProgressDonutIndicator = ({ className, ...props }: ProgressDonutIndicatorProps) => {\n\tconst gradientId = useRandomStableId();\n\tconst ctx = useContext(ProgressContext) ?? defaultContextValue;\n\tconst percentage = (ctx.value == \"indeterminate\" ? indeterminateTailPercent : ctx.value / ctx.max) * 100;\n\tconst strokeWidthPx = deriveStrokeWidthPx(ctx.strokeWidth);\n\tconst radius = `calc(50% - ${strokeWidthPx / 2}px)` as const;\n\n\treturn (\n\t\t<g className={cx(\"text-accent-600\", className)} {...props}>\n\t\t\t{ctx.value == \"indeterminate\" && (\n\t\t\t\t<defs>\n\t\t\t\t\t<linearGradient id={gradientId}>\n\t\t\t\t\t\t<stop className=\"stop-opacity-100 stop-color-current\" offset=\"0%\" />\n\t\t\t\t\t\t<stop className=\"stop-opacity-0 stop-color-current\" offset=\"95%\" />\n\t\t\t\t\t</linearGradient>\n\t\t\t\t</defs>\n\t\t\t)}\n\t\t\t<circle\n\t\t\t\tcx=\"50%\"\n\t\t\t\tcy=\"50%\"\n\t\t\t\tfill=\"transparent\"\n\t\t\t\tpathLength={100}\n\t\t\t\tr={radius}\n\t\t\t\tstroke={ctx.value == \"indeterminate\" ? `url(#${gradientId})` : \"currentColor\"}\n\t\t\t\tstrokeDasharray={100}\n\t\t\t\tstrokeDashoffset={100 - percentage}\n\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\tstrokeWidth={strokeWidthPx}\n\t\t\t\ttransform-origin=\"center\"\n\t\t\t\ttransform=\"rotate(-90)\" // rotate -90 degrees so it starts from the top\n\t\t\t/>\n\t\t</g>\n\t);\n};\n\nexport {\n\t//,\n\tProgressDonut,\n\tProgressDonutIndicator,\n};\n\n/**\n * Clamp a value between a minimum and maximum value.\n */\nfunction clamp(value: number, { min, max }: { min: number; max: number }): number {\n\treturn Math.min(max, Math.max(min, value));\n}\n\n/**\n * Derive the stroke width in pixels as a number value or pixels/rem from a string value.\n * Note, this function clamps the stroke width to a minimum of 1 and max of 12 since\n * it is proportional to the viewbox size (0 0 32 32).\n */\nexport function deriveStrokeWidthPx(strokeWidth: number | string | undefined): number {\n\tlet value = 4;\n\tif (strokeWidth == null) {\n\t\treturn value;\n\t}\n\n\tif (typeof strokeWidth === \"number\") {\n\t\tvalue = strokeWidth;\n\t} else if (strokeWidth.endsWith(\"rem\")) {\n\t\tvalue = Number(strokeWidth.replace(\"rem\", \"\")) * 16;\n\t} else {\n\t\tvalue = Number(strokeWidth);\n\t}\n\n\tconst stroke = Number.isNaN(value) ? 4 : value;\n\treturn clamp(stroke, { min: 1, max: 12 });\n}\n\n/**\n * Check if a value is a number.\n */\nfunction isNumber(value: unknown): value is number {\n\treturn typeof value === \"number\";\n}\n\n/**\n * Check if a value is a valid number within the range of 0 to `max`.\n */\nfunction isValidValueNumber(value: unknown, max: number): value is number {\n\treturn isNumber(value) && !Number.isNaN(value) && value <= max && value >= 0;\n}\n\n/**\n * Check if a value is a valid number greater than 0.\n */\nfunction isValidMaxNumber(value: unknown): value is number {\n\treturn isNumber(value) && !Number.isNaN(value) && value > 0;\n}\n"],"mappings":"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","names":["clsx","createContext","useContext","useMemo","jsx","jsxs","defaultMax","defaultContextValue","ProgressContext","createContext","ProgressDonut","children","className","_max","_strokeWidth","_value","props","max","isValidMaxNumber","value","isValidValueNumber","strokeWidthPx","deriveStrokeWidthPx","valueNow","isNumber","radius","ctx","useMemo","clsx","cx","indeterminateTailPercent","ProgressDonutIndicator","gradientId","useRandomStableId","useContext","percentage","clamp","value","min","max","deriveStrokeWidthPx","strokeWidth","stroke","isNumber","isValidValueNumber","isValidMaxNumber"]}
1
+ {"version":3,"sources":["../src/components/progress/progress-donut.tsx"],"sourcesContent":["import clsx from \"clsx\";\nimport { createContext, useContext, useId, useMemo } from \"react\";\nimport type { ComponentProps, CSSProperties, HTMLAttributes } from \"react\";\nimport { cx } from \"../../utils/cx/cx.js\";\n\ntype RemValue = `${number}rem`;\ntype StrokeWidth = number | RemValue;\ntype ValueType = number | \"indeterminate\";\n\n/**\n * The default maximum value of the progress bar.\n */\nconst defaultMax = 100;\n\ntype ProgressContextValue = {\n\tmax: number;\n\tstrokeWidth: StrokeWidth;\n\tvalue: ValueType;\n};\n\nconst defaultContextValue = {\n\tmax: defaultMax,\n\tstrokeWidth: \"0.25rem\",\n\tvalue: 0,\n} as const satisfies ProgressContextValue;\n\nconst ProgressContext = createContext<ProgressContextValue>(defaultContextValue);\n\ntype SvgAttributes = Omit<\n\tHTMLAttributes<SVGElement>,\n\t\"viewBox\" | \"role\" | \"aria-valuemax\" | \"aria-valuemin\" | \"aria-valuenow\" | \"width\" | \"height\"\n>;\n\ntype Props = SvgAttributes & {\n\t/**\n\t * The maximum value of the progress bar.\n\t * This attribute describes how much work the task indicated by the progress element requires.\n\t * The max attribute, if present, must have a value greater than 0. The default value is 100.\n\t *\n\t * @default 100\n\t */\n\tmax?: number | undefined;\n\t/**\n\t * The width of the progress bar stroke.\n\t * Note, we clamp the stroke width to a minimum of 1px and max of 12px since\n\t * it is proportional to the viewbox size (0 0 32 32).\n\t *\n\t * @default 0.25rem (4px)\n\t */\n\tstrokeWidth?: StrokeWidth;\n\t/**\n\t * The current value of the progress bar.\n\t * This attribute specifies how much of the task that has been completed.\n\t * It must be a valid floating point number between 0 and max, or between 0 and 100 if max is omitted.\n\t * If set to `\"indeterminate\"`, the progress bar is considered indeterminate.\n\t *\n\t * @default 0\n\t */\n\tvalue?: ValueType | undefined;\n};\n\n/**\n * A simple circular progress bar.\n */\nconst ProgressDonut = ({\n\tchildren,\n\tclassName,\n\tmax: _max = defaultMax,\n\tstrokeWidth: _strokeWidth = 4,\n\tvalue: _value,\n\t...props\n}: Props) => {\n\tconst max = isValidMaxNumber(_max) ? _max : defaultMax;\n\tconst value = (isValidValueNumber(_value, max) ? _value : _value == null ? 0 : \"indeterminate\") satisfies ValueType;\n\tconst strokeWidthPx = deriveStrokeWidthPx(_strokeWidth ?? defaultContextValue.strokeWidth);\n\tconst valueNow = isNumber(value) ? value : undefined;\n\tconst radius = calcRadius(strokeWidthPx);\n\n\tconst ctx: ProgressContextValue = useMemo(\n\t\t() => ({\n\t\t\tmax,\n\t\t\tstrokeWidth: strokeWidthPx,\n\t\t\tvalue,\n\t\t}),\n\t\t[max, strokeWidthPx, value],\n\t);\n\n\treturn (\n\t\t<ProgressContext.Provider value={ctx}>\n\t\t\t<svg\n\t\t\t\taria-valuemax={max}\n\t\t\t\taria-valuemin={0}\n\t\t\t\taria-valuenow={valueNow}\n\t\t\t\tclassName={clsx(\n\t\t\t\t\tvalue === \"indeterminate\" && \"animation-duration-[15s] transform-gpu animate-spin\",\n\t\t\t\t\tcx(\"size-6 text-gray-200 dark:text-gray-300\", className),\n\t\t\t\t)}\n\t\t\t\tdata-max={max}\n\t\t\t\tdata-min={0}\n\t\t\t\tdata-value={valueNow}\n\t\t\t\theight=\"100%\"\n\t\t\t\trole=\"progressbar\"\n\t\t\t\twidth=\"100%\"\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t<circle\n\t\t\t\t\tclassName=\"[r:var(--radius)]\"\n\t\t\t\t\tcx=\"50%\"\n\t\t\t\t\tcy=\"50%\"\n\t\t\t\t\tfill=\"transparent\"\n\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\tstrokeWidth={strokeWidthPx}\n\t\t\t\t\tstyle={{ \"--radius\": radius } as CSSProperties}\n\t\t\t\t/>\n\t\t\t\t{children}\n\t\t\t</svg>\n\t\t</ProgressContext.Provider>\n\t);\n};\n\n/**\n * Length (value) of the progress indicator tail when the progress bar is indeterminate.\n */\nconst indeterminateTailPercent = 0.6;\n\ntype ProgressDonutIndicatorProps = Omit<ComponentProps<\"g\">, \"children\">;\n\n/**\n * The indicator for the circular progress bar.\n */\nconst ProgressDonutIndicator = ({ className, ...props }: ProgressDonutIndicatorProps) => {\n\tconst gradientId = useId();\n\tconst ctx = useContext(ProgressContext) ?? defaultContextValue;\n\tconst percentage = (ctx.value == \"indeterminate\" ? indeterminateTailPercent : ctx.value / ctx.max) * 100;\n\tconst strokeWidthPx = deriveStrokeWidthPx(ctx.strokeWidth);\n\tconst radius = calcRadius(strokeWidthPx);\n\n\treturn (\n\t\t<g className={cx(\"text-accent-600\", className)} {...props}>\n\t\t\t{ctx.value == \"indeterminate\" && (\n\t\t\t\t<defs>\n\t\t\t\t\t<linearGradient id={gradientId}>\n\t\t\t\t\t\t<stop className=\"stop-opacity-100 stop-color-current\" offset=\"0%\" />\n\t\t\t\t\t\t<stop className=\"stop-opacity-0 stop-color-current\" offset=\"95%\" />\n\t\t\t\t\t</linearGradient>\n\t\t\t\t</defs>\n\t\t\t)}\n\t\t\t<circle\n\t\t\t\tclassName=\"[r:var(--radius)]\"\n\t\t\t\tcx=\"50%\"\n\t\t\t\tcy=\"50%\"\n\t\t\t\tfill=\"transparent\"\n\t\t\t\tpathLength={100}\n\t\t\t\tstroke={ctx.value == \"indeterminate\" ? `url(#${gradientId})` : \"currentColor\"}\n\t\t\t\tstrokeDasharray={100}\n\t\t\t\tstrokeDashoffset={100 - percentage}\n\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\tstrokeWidth={strokeWidthPx}\n\t\t\t\tstyle={{ \"--radius\": radius } as CSSProperties}\n\t\t\t\ttransform-origin=\"center\"\n\t\t\t\ttransform=\"rotate(-90)\" // rotate -90 degrees so it starts from the top\n\t\t\t/>\n\t\t</g>\n\t);\n};\n\nexport {\n\t//,\n\tProgressDonut,\n\tProgressDonutIndicator,\n};\n\n/**\n * Clamp a value between a minimum and maximum value.\n */\nfunction clamp(value: number, { min, max }: { min: number; max: number }): number {\n\treturn Math.min(max, Math.max(min, value));\n}\n\n/**\n * Derive the stroke width in pixels as a number value or pixels/rem from a string value.\n * Note, this function clamps the stroke width to a minimum of 1 and max of 12 since\n * it is proportional to the viewbox size (0 0 32 32).\n */\nexport function deriveStrokeWidthPx(strokeWidth: number | string | undefined): number {\n\tlet value = 4;\n\tif (strokeWidth == null) {\n\t\treturn value;\n\t}\n\n\tif (typeof strokeWidth === \"number\") {\n\t\tvalue = strokeWidth;\n\t} else if (strokeWidth.endsWith(\"rem\")) {\n\t\tvalue = Number(strokeWidth.replace(\"rem\", \"\")) * 16;\n\t} else {\n\t\tvalue = Number(strokeWidth);\n\t}\n\n\tconst stroke = Number.isNaN(value) ? 4 : value;\n\treturn clamp(stroke, { min: 1, max: 12 });\n}\n\n/**\n * Check if a value is a number.\n */\nfunction isNumber(value: unknown): value is number {\n\treturn typeof value === \"number\";\n}\n\n/**\n * Check if a value is a valid number within the range of 0 to `max`.\n */\nfunction isValidValueNumber(value: unknown, max: number): value is number {\n\treturn isNumber(value) && !Number.isNaN(value) && value <= max && value >= 0;\n}\n\n/**\n * Check if a value is a valid number greater than 0.\n */\nfunction isValidMaxNumber(value: unknown): value is number {\n\treturn isNumber(value) && !Number.isNaN(value) && value > 0;\n}\n\n/**\n * Calculate the radius of the progress donut and indicator based on the stroke\n * width in pixels.\n */\nfunction calcRadius(strokeWidthPx: number) {\n\treturn `calc(50% - ${strokeWidthPx / 2}px)` as const;\n}\n"],"mappings":"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","names":["clsx","createContext","useContext","useId","useMemo","jsx","jsxs","defaultMax","defaultContextValue","ProgressContext","createContext","ProgressDonut","children","className","_max","_strokeWidth","_value","props","max","isValidMaxNumber","value","isValidValueNumber","strokeWidthPx","deriveStrokeWidthPx","valueNow","isNumber","radius","calcRadius","ctx","useMemo","clsx","cx","indeterminateTailPercent","ProgressDonutIndicator","gradientId","useId","useContext","percentage","clamp","value","min","max","deriveStrokeWidthPx","strokeWidth","stroke","isNumber","isValidValueNumber","isValidMaxNumber","calcRadius","strokeWidthPx"]}
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.9.1",
6
+ "version": "0.10.1",
7
7
  "homepage": "https://mantle.ngrok.com",
8
8
  "repository": {
9
9
  "type": "git",
@@ -1,2 +0,0 @@
1
- import{useMemo as n}from"react";var a=(t="mantle")=>n(()=>o(t),[t]);function o(t="mantle"){return[t.trim()||"mantle",r()].join("-")}function r(){return Math.random().toString(36).substring(2,9)}export{a};
2
- //# sourceMappingURL=chunk-ZBC4B4EM.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/hooks/use-random-stable-id.tsx"],"sourcesContent":["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"],"mappings":"AAAA,OAAS,WAAAA,MAAe,QAOxB,IAAMC,EAAoB,CAACC,EAAS,WAAaF,EAAQ,IAAMG,EAAeD,CAAM,EAAG,CAACA,CAAM,CAAC,EAO/F,SAASE,EAAeC,EAAS,SAAU,CAE1C,MAAO,CADSA,EAAO,KAAK,GAAK,SAChBC,EAAc,CAAC,EAAE,KAAK,GAAG,CAC3C,CAEA,SAASA,GAAgB,CACxB,OAAO,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,UAAU,EAAG,CAAC,CACjD","names":["useMemo","useRandomStableId","prefix","randomStableId","randomStableId","prefix","randomPostfix"]}