@salt-ds/core 1.65.0 → 1.66.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +36 -0
- package/css/salt-core.css +154 -3
- package/dist-cjs/index.js +22 -0
- package/dist-cjs/index.js.map +1 -1
- package/dist-cjs/mega-menu/MegaMenu.js +81 -0
- package/dist-cjs/mega-menu/MegaMenu.js.map +1 -0
- package/dist-cjs/mega-menu/MegaMenuActions.css.js +6 -0
- package/dist-cjs/mega-menu/MegaMenuActions.css.js.map +1 -0
- package/dist-cjs/mega-menu/MegaMenuActions.js +37 -0
- package/dist-cjs/mega-menu/MegaMenuActions.js.map +1 -0
- package/dist-cjs/mega-menu/MegaMenuAside.css.js +6 -0
- package/dist-cjs/mega-menu/MegaMenuAside.css.js.map +1 -0
- package/dist-cjs/mega-menu/MegaMenuAside.js +37 -0
- package/dist-cjs/mega-menu/MegaMenuAside.js.map +1 -0
- package/dist-cjs/mega-menu/MegaMenuContent.css.js +6 -0
- package/dist-cjs/mega-menu/MegaMenuContent.css.js.map +1 -0
- package/dist-cjs/mega-menu/MegaMenuContent.js +29 -0
- package/dist-cjs/mega-menu/MegaMenuContent.js.map +1 -0
- package/dist-cjs/mega-menu/MegaMenuContext.js +18 -0
- package/dist-cjs/mega-menu/MegaMenuContext.js.map +1 -0
- package/dist-cjs/mega-menu/MegaMenuGroup.css.js +6 -0
- package/dist-cjs/mega-menu/MegaMenuGroup.css.js.map +1 -0
- package/dist-cjs/mega-menu/MegaMenuGroup.js +44 -0
- package/dist-cjs/mega-menu/MegaMenuGroup.js.map +1 -0
- package/dist-cjs/mega-menu/MegaMenuGroupContext.js +23 -0
- package/dist-cjs/mega-menu/MegaMenuGroupContext.js.map +1 -0
- package/dist-cjs/mega-menu/MegaMenuGroupHeading.css.js +6 -0
- package/dist-cjs/mega-menu/MegaMenuGroupHeading.css.js.map +1 -0
- package/dist-cjs/mega-menu/MegaMenuGroupHeading.js +44 -0
- package/dist-cjs/mega-menu/MegaMenuGroupHeading.js.map +1 -0
- package/dist-cjs/mega-menu/MegaMenuGroups.css.js +6 -0
- package/dist-cjs/mega-menu/MegaMenuGroups.css.js.map +1 -0
- package/dist-cjs/mega-menu/MegaMenuGroups.js +29 -0
- package/dist-cjs/mega-menu/MegaMenuGroups.js.map +1 -0
- package/dist-cjs/mega-menu/MegaMenuList.css.js +6 -0
- package/dist-cjs/mega-menu/MegaMenuList.css.js.map +1 -0
- package/dist-cjs/mega-menu/MegaMenuList.js +47 -0
- package/dist-cjs/mega-menu/MegaMenuList.js.map +1 -0
- package/dist-cjs/mega-menu/MegaMenuListItem.css.js +6 -0
- package/dist-cjs/mega-menu/MegaMenuListItem.css.js.map +1 -0
- package/dist-cjs/mega-menu/MegaMenuListItem.js +50 -0
- package/dist-cjs/mega-menu/MegaMenuListItem.js.map +1 -0
- package/dist-cjs/mega-menu/MegaMenuPanel.css.js +6 -0
- package/dist-cjs/mega-menu/MegaMenuPanel.css.js.map +1 -0
- package/dist-cjs/mega-menu/MegaMenuPanel.js +94 -0
- package/dist-cjs/mega-menu/MegaMenuPanel.js.map +1 -0
- package/dist-cjs/mega-menu/MegaMenuTrigger.js +97 -0
- package/dist-cjs/mega-menu/MegaMenuTrigger.js.map +1 -0
- package/dist-cjs/mega-menu/useMegaMenu.js +15 -0
- package/dist-cjs/mega-menu/useMegaMenu.js.map +1 -0
- package/dist-cjs/mega-menu/useMegaMenuNavigation.js +282 -0
- package/dist-cjs/mega-menu/useMegaMenuNavigation.js.map +1 -0
- package/dist-cjs/mega-menu/usePageMargin.js +28 -0
- package/dist-cjs/mega-menu/usePageMargin.js.map +1 -0
- package/dist-cjs/spinner/Spinner.css.js +1 -1
- package/dist-cjs/spinner/Spinner.js +4 -5
- package/dist-cjs/spinner/Spinner.js.map +1 -1
- package/dist-cjs/spinner/svgSpinners/SpinnerSVG.js +32 -50
- package/dist-cjs/spinner/svgSpinners/SpinnerSVG.js.map +1 -1
- package/dist-es/index.js +11 -0
- package/dist-es/index.js.map +1 -1
- package/dist-es/mega-menu/MegaMenu.js +79 -0
- package/dist-es/mega-menu/MegaMenu.js.map +1 -0
- package/dist-es/mega-menu/MegaMenuActions.css.js +4 -0
- package/dist-es/mega-menu/MegaMenuActions.css.js.map +1 -0
- package/dist-es/mega-menu/MegaMenuActions.js +35 -0
- package/dist-es/mega-menu/MegaMenuActions.js.map +1 -0
- package/dist-es/mega-menu/MegaMenuAside.css.js +4 -0
- package/dist-es/mega-menu/MegaMenuAside.css.js.map +1 -0
- package/dist-es/mega-menu/MegaMenuAside.js +35 -0
- package/dist-es/mega-menu/MegaMenuAside.js.map +1 -0
- package/dist-es/mega-menu/MegaMenuContent.css.js +4 -0
- package/dist-es/mega-menu/MegaMenuContent.css.js.map +1 -0
- package/dist-es/mega-menu/MegaMenuContent.js +27 -0
- package/dist-es/mega-menu/MegaMenuContent.js.map +1 -0
- package/dist-es/mega-menu/MegaMenuContext.js +16 -0
- package/dist-es/mega-menu/MegaMenuContext.js.map +1 -0
- package/dist-es/mega-menu/MegaMenuGroup.css.js +4 -0
- package/dist-es/mega-menu/MegaMenuGroup.css.js.map +1 -0
- package/dist-es/mega-menu/MegaMenuGroup.js +42 -0
- package/dist-es/mega-menu/MegaMenuGroup.js.map +1 -0
- package/dist-es/mega-menu/MegaMenuGroupContext.js +20 -0
- package/dist-es/mega-menu/MegaMenuGroupContext.js.map +1 -0
- package/dist-es/mega-menu/MegaMenuGroupHeading.css.js +4 -0
- package/dist-es/mega-menu/MegaMenuGroupHeading.css.js.map +1 -0
- package/dist-es/mega-menu/MegaMenuGroupHeading.js +42 -0
- package/dist-es/mega-menu/MegaMenuGroupHeading.js.map +1 -0
- package/dist-es/mega-menu/MegaMenuGroups.css.js +4 -0
- package/dist-es/mega-menu/MegaMenuGroups.css.js.map +1 -0
- package/dist-es/mega-menu/MegaMenuGroups.js +27 -0
- package/dist-es/mega-menu/MegaMenuGroups.js.map +1 -0
- package/dist-es/mega-menu/MegaMenuList.css.js +4 -0
- package/dist-es/mega-menu/MegaMenuList.css.js.map +1 -0
- package/dist-es/mega-menu/MegaMenuList.js +45 -0
- package/dist-es/mega-menu/MegaMenuList.js.map +1 -0
- package/dist-es/mega-menu/MegaMenuListItem.css.js +4 -0
- package/dist-es/mega-menu/MegaMenuListItem.css.js.map +1 -0
- package/dist-es/mega-menu/MegaMenuListItem.js +48 -0
- package/dist-es/mega-menu/MegaMenuListItem.js.map +1 -0
- package/dist-es/mega-menu/MegaMenuPanel.css.js +4 -0
- package/dist-es/mega-menu/MegaMenuPanel.css.js.map +1 -0
- package/dist-es/mega-menu/MegaMenuPanel.js +92 -0
- package/dist-es/mega-menu/MegaMenuPanel.js.map +1 -0
- package/dist-es/mega-menu/MegaMenuTrigger.js +95 -0
- package/dist-es/mega-menu/MegaMenuTrigger.js.map +1 -0
- package/dist-es/mega-menu/useMegaMenu.js +13 -0
- package/dist-es/mega-menu/useMegaMenu.js.map +1 -0
- package/dist-es/mega-menu/useMegaMenuNavigation.js +278 -0
- package/dist-es/mega-menu/useMegaMenuNavigation.js.map +1 -0
- package/dist-es/mega-menu/usePageMargin.js +26 -0
- package/dist-es/mega-menu/usePageMargin.js.map +1 -0
- package/dist-es/spinner/Spinner.css.js +1 -1
- package/dist-es/spinner/Spinner.js +4 -5
- package/dist-es/spinner/Spinner.js.map +1 -1
- package/dist-es/spinner/svgSpinners/SpinnerSVG.js +32 -50
- package/dist-es/spinner/svgSpinners/SpinnerSVG.js.map +1 -1
- package/dist-types/index.d.ts +1 -0
- package/dist-types/mega-menu/MegaMenu.d.ts +36 -0
- package/dist-types/mega-menu/MegaMenuActions.d.ts +10 -0
- package/dist-types/mega-menu/MegaMenuAside.d.ts +9 -0
- package/dist-types/mega-menu/MegaMenuContent.d.ts +9 -0
- package/dist-types/mega-menu/MegaMenuContext.d.ts +28 -0
- package/dist-types/mega-menu/MegaMenuGroup.d.ts +9 -0
- package/dist-types/mega-menu/MegaMenuGroupContext.d.ts +12 -0
- package/dist-types/mega-menu/MegaMenuGroupHeading.d.ts +13 -0
- package/dist-types/mega-menu/MegaMenuGroups.d.ts +8 -0
- package/dist-types/mega-menu/MegaMenuList.d.ts +16 -0
- package/dist-types/mega-menu/MegaMenuListItem.d.ts +25 -0
- package/dist-types/mega-menu/MegaMenuPanel.d.ts +8 -0
- package/dist-types/mega-menu/MegaMenuTrigger.d.ts +9 -0
- package/dist-types/mega-menu/index.d.ts +11 -0
- package/dist-types/mega-menu/useMegaMenu.d.ts +6 -0
- package/dist-types/mega-menu/useMegaMenuNavigation.d.ts +16 -0
- package/dist-types/mega-menu/usePageMargin.d.ts +6 -0
- package/dist-types/spinner/svgSpinners/SpinnerSVG.d.ts +10 -10
- package/package.json +2 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Spinner.js","sources":["../src/spinner/Spinner.tsx"],"sourcesContent":["import { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { clsx } from \"clsx\";\nimport { forwardRef, type HTMLAttributes, useEffect } from \"react\";\nimport { useAriaAnnouncer } from \"../aria-announcer\";\nimport {
|
|
1
|
+
{"version":3,"file":"Spinner.js","sources":["../src/spinner/Spinner.tsx"],"sourcesContent":["import { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { clsx } from \"clsx\";\nimport { forwardRef, type HTMLAttributes, useEffect } from \"react\";\nimport { useAriaAnnouncer } from \"../aria-announcer\";\nimport { makePrefixer, useId } from \"../utils\";\nimport spinnerCss from \"./Spinner.css\";\nimport { SpinnerSVG } from \"./svgSpinners/SpinnerSVG\";\n\n/**\n * Spinner component, provides an indeterminate loading indicator\n *\n * @example\n * <Spinner size=\"small\" | \"medium\" | \"large\" />\n */\n\nexport const SpinnerSizeValues = [\n \"default\",\n \"large\",\n \"small\",\n \"medium\",\n] as const;\n\ntype SpinnerSize = (typeof SpinnerSizeValues)[number];\n\nexport type SpinnerSVGSize = Exclude<SpinnerSize, \"default\">;\n\nconst handleSize = (size: SpinnerSize): SpinnerSVGSize =>\n size === \"default\" ? \"medium\" : size;\n\nconst withBaseName = makePrefixer(\"saltSpinner\");\n\nexport interface SpinnerProps extends HTMLAttributes<HTMLDivElement> {\n /**\n * Determines the interval on which the component will continue to announce the aria-label. Defaults to 5000ms (5s)\n */\n announcerInterval?: number;\n /**\n * * Determines the interval after which the component will stop announcing the aria-label. Defaults to 20000ms (20s)\n */\n announcerTimeout?: number;\n /**\n * The className(s) of the component\n */\n className?: string;\n /**\n * Determines the message to be announced by the component when it unmounts. Set to null if not needed.\n */\n completionAnnouncement?: string | null;\n /**\n * If true, built in aria announcer will be inactive\n */\n disableAnnouncer?: boolean;\n /**\n * The prop for the role attribute of the component\n */\n role?: string;\n /**\n * Determines the size of the spinner. Must be one of: 'default', 'large', 'small', 'medium'.\n */\n size?: SpinnerSize;\n /**\n * The ids of the SvgSpinner components\n */\n id?: string;\n}\n\nexport const Spinner = forwardRef<HTMLDivElement, SpinnerProps>(\n function Spinner(\n {\n \"aria-label\": ariaLabel = \"loading\",\n announcerInterval = 5000,\n announcerTimeout = 20000,\n completionAnnouncement = `finished ${ariaLabel}`,\n disableAnnouncer,\n className,\n size: sizeProp = \"medium\",\n id: idProp,\n ...rest\n },\n ref,\n ) {\n const id = useId(idProp);\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"salt-spinner\",\n css: spinnerCss,\n window: targetWindow,\n });\n\n const { announce } = useAriaAnnouncer();\n\n const size = handleSize(sizeProp);\n\n useEffect(() => {\n if (disableAnnouncer) return;\n\n announce(ariaLabel);\n\n const startTime = Date.now();\n\n const interval =\n announcerInterval > 0 &&\n setInterval(() => {\n if (Date.now() - startTime > announcerTimeout) {\n // The announcer will stop after `announcerTimeout` time\n announce(\n `${ariaLabel} is still in progress, but will no longer announce.`,\n );\n interval && clearInterval(interval);\n return;\n }\n announce(ariaLabel);\n }, announcerInterval);\n\n return () => {\n if (disableAnnouncer) return;\n\n interval && clearInterval(interval);\n if (completionAnnouncement) {\n announce(completionAnnouncement);\n }\n };\n }, [\n announce,\n announcerInterval,\n announcerTimeout,\n ariaLabel,\n completionAnnouncement,\n disableAnnouncer,\n ]);\n\n return (\n <div\n aria-label={ariaLabel}\n className={clsx(withBaseName(), withBaseName(size), className)}\n ref={ref}\n role=\"img\"\n {...rest}\n >\n <SpinnerSVG id={id} />\n </div>\n );\n },\n);\n"],"names":["Spinner","spinnerCss"],"mappings":";;;;;;;;;;;;;;;;AAgBO,MAAM,iBAAA,GAAoB;AAAA,EAC/B,SAAA;AAAA,EACA,OAAA;AAAA,EACA,OAAA;AAAA,EACA;AACF;AAMA,MAAM,UAAA,GAAa,CAAC,IAAA,KAClB,IAAA,KAAS,YAAY,QAAA,GAAW,IAAA;AAElC,MAAM,YAAA,GAAe,aAAa,aAAa,CAAA;AAqCxC,MAAM,OAAA,GAAU,UAAA;AAAA,EACrB,SAASA,QAAAA,CACP;AAAA,IACE,cAAc,SAAA,GAAY,SAAA;AAAA,IAC1B,iBAAA,GAAoB,GAAA;AAAA,IACpB,gBAAA,GAAmB,GAAA;AAAA,IACnB,sBAAA,GAAyB,YAAY,SAAS,CAAA,CAAA;AAAA,IAC9C,gBAAA;AAAA,IACA,SAAA;AAAA,IACA,MAAM,QAAA,GAAW,QAAA;AAAA,IACjB,EAAA,EAAI,MAAA;AAAA,IACJ,GAAG;AAAA,KAEL,GAAA,EACA;AACA,IAAA,MAAM,EAAA,GAAK,MAAM,MAAM,CAAA;AACvB,IAAA,MAAM,eAAe,SAAA,EAAU;AAC/B,IAAA,wBAAA,CAAyB;AAAA,MACvB,MAAA,EAAQ,cAAA;AAAA,MACR,GAAA,EAAKC,QAAA;AAAA,MACL,MAAA,EAAQ;AAAA,KACT,CAAA;AAED,IAAA,MAAM,EAAE,QAAA,EAAS,GAAI,gBAAA,EAAiB;AAEtC,IAAA,MAAM,IAAA,GAAO,WAAW,QAAQ,CAAA;AAEhC,IAAA,SAAA,CAAU,MAAM;AACd,MAAA,IAAI,gBAAA,EAAkB;AAEtB,MAAA,QAAA,CAAS,SAAS,CAAA;AAElB,MAAA,MAAM,SAAA,GAAY,KAAK,GAAA,EAAI;AAE3B,MAAA,MAAM,QAAA,GACJ,iBAAA,GAAoB,CAAA,IACpB,WAAA,CAAY,MAAM;AAChB,QAAA,IAAI,IAAA,CAAK,GAAA,EAAI,GAAI,SAAA,GAAY,gBAAA,EAAkB;AAE7C,UAAA,QAAA;AAAA,YACE,GAAG,SAAS,CAAA,mDAAA;AAAA,WACd;AACA,UAAA,QAAA,IAAY,cAAc,QAAQ,CAAA;AAClC,UAAA;AAAA,QACF;AACA,QAAA,QAAA,CAAS,SAAS,CAAA;AAAA,MACpB,GAAG,iBAAiB,CAAA;AAEtB,MAAA,OAAO,MAAM;AACX,QAAA,IAAI,gBAAA,EAAkB;AAEtB,QAAA,QAAA,IAAY,cAAc,QAAQ,CAAA;AAClC,QAAA,IAAI,sBAAA,EAAwB;AAC1B,UAAA,QAAA,CAAS,sBAAsB,CAAA;AAAA,QACjC;AAAA,MACF,CAAA;AAAA,IACF,CAAA,EAAG;AAAA,MACD,QAAA;AAAA,MACA,iBAAA;AAAA,MACA,gBAAA;AAAA,MACA,SAAA;AAAA,MACA,sBAAA;AAAA,MACA;AAAA,KACD,CAAA;AAED,IAAA,uBACE,GAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,YAAA,EAAY,SAAA;AAAA,QACZ,WAAW,IAAA,CAAK,YAAA,IAAgB,YAAA,CAAa,IAAI,GAAG,SAAS,CAAA;AAAA,QAC7D,GAAA;AAAA,QACA,IAAA,EAAK,KAAA;AAAA,QACJ,GAAG,IAAA;AAAA,QAEJ,QAAA,kBAAA,GAAA,CAAC,cAAW,EAAA,EAAQ;AAAA;AAAA,KACtB;AAAA,EAEJ;AACF;;;;"}
|
|
@@ -8,46 +8,20 @@ import '../../salt-provider/SaltProvider.js';
|
|
|
8
8
|
import '../../viewport/ViewportProvider.js';
|
|
9
9
|
|
|
10
10
|
const withBaseName = makePrefixer("saltSpinner");
|
|
11
|
-
const sizeAndStrokeWidthMapping = {
|
|
12
|
-
small: {
|
|
13
|
-
high: { width: 12, strokeWidth: 2 },
|
|
14
|
-
medium: { width: 12, strokeWidth: 2 },
|
|
15
|
-
low: { width: 14, strokeWidth: 2 },
|
|
16
|
-
touch: { width: 16, strokeWidth: 2 },
|
|
17
|
-
mobile: { width: 16, strokeWidth: 2 }
|
|
18
|
-
},
|
|
19
|
-
medium: {
|
|
20
|
-
high: { width: 20, strokeWidth: 2 },
|
|
21
|
-
medium: { width: 28, strokeWidth: 4 },
|
|
22
|
-
low: { width: 36, strokeWidth: 6 },
|
|
23
|
-
touch: { width: 44, strokeWidth: 8 },
|
|
24
|
-
mobile: { width: 44, strokeWidth: 8 }
|
|
25
|
-
},
|
|
26
|
-
large: {
|
|
27
|
-
high: { width: 40, strokeWidth: 2 },
|
|
28
|
-
medium: { width: 56, strokeWidth: 4 },
|
|
29
|
-
low: { width: 72, strokeWidth: 6 },
|
|
30
|
-
touch: { width: 88, strokeWidth: 8 },
|
|
31
|
-
mobile: { width: 88, strokeWidth: 8 }
|
|
32
|
-
}
|
|
33
|
-
};
|
|
34
11
|
const SpinnerSVG = ({
|
|
35
12
|
id = "svg-spinner",
|
|
36
|
-
rest
|
|
37
|
-
size,
|
|
38
|
-
density
|
|
13
|
+
...rest
|
|
39
14
|
}) => {
|
|
40
|
-
const
|
|
41
|
-
const radius = (width - strokeWidth) / 2;
|
|
15
|
+
const gradientId = `${id}-1`;
|
|
42
16
|
return /* @__PURE__ */ jsxs(
|
|
43
17
|
"svg",
|
|
44
18
|
{
|
|
45
19
|
className: withBaseName("spinner"),
|
|
46
|
-
|
|
20
|
+
preserveAspectRatio: "xMidYMid meet",
|
|
47
21
|
id,
|
|
48
22
|
...rest,
|
|
49
23
|
children: [
|
|
50
|
-
/* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsxs("linearGradient", { id:
|
|
24
|
+
/* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsxs("linearGradient", { id: gradientId, x1: "0", y1: "0", x2: "50%", y2: "0", children: [
|
|
51
25
|
/* @__PURE__ */ jsx(
|
|
52
26
|
"stop",
|
|
53
27
|
{
|
|
@@ -65,26 +39,34 @@ const SpinnerSVG = ({
|
|
|
65
39
|
}
|
|
66
40
|
)
|
|
67
41
|
] }) }),
|
|
68
|
-
/* @__PURE__ */
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
"
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
42
|
+
/* @__PURE__ */ jsx(
|
|
43
|
+
"circle",
|
|
44
|
+
{
|
|
45
|
+
className: withBaseName("arc"),
|
|
46
|
+
cx: "50%",
|
|
47
|
+
cy: "50%",
|
|
48
|
+
fill: "none",
|
|
49
|
+
stroke: "var(--saltSpinner-gradient-color, var(--salt-sentiment-accent-background))",
|
|
50
|
+
strokeWidth: "var(--spinner-strokeWidth)",
|
|
51
|
+
pathLength: "100",
|
|
52
|
+
strokeDasharray: "50 50",
|
|
53
|
+
strokeDashoffset: "50"
|
|
54
|
+
}
|
|
55
|
+
),
|
|
56
|
+
/* @__PURE__ */ jsx(
|
|
57
|
+
"circle",
|
|
58
|
+
{
|
|
59
|
+
className: withBaseName("arc"),
|
|
60
|
+
cx: "50%",
|
|
61
|
+
cy: "50%",
|
|
62
|
+
fill: "none",
|
|
63
|
+
stroke: `url(#${gradientId})`,
|
|
64
|
+
strokeWidth: "var(--spinner-strokeWidth)",
|
|
65
|
+
pathLength: "100",
|
|
66
|
+
strokeDasharray: "50 50",
|
|
67
|
+
strokeDashoffset: "75"
|
|
68
|
+
}
|
|
69
|
+
)
|
|
88
70
|
]
|
|
89
71
|
}
|
|
90
72
|
);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SpinnerSVG.js","sources":["../src/spinner/svgSpinners/SpinnerSVG.tsx"],"sourcesContent":["import type {
|
|
1
|
+
{"version":3,"file":"SpinnerSVG.js","sources":["../src/spinner/svgSpinners/SpinnerSVG.tsx"],"sourcesContent":["import type { ComponentPropsWithoutRef } from \"react\";\nimport { makePrefixer } from \"../../utils\";\n\nconst withBaseName = makePrefixer(\"saltSpinner\");\n\ntype SpinnerSVGProps = ComponentPropsWithoutRef<\"svg\">;\n\n/**\n * Draws the spinner as two overlapping circles. Each circle is half-stroked\n * (`stroke-dasharray=\"50 50\"` against a normalised `pathLength` of 100) and\n * rotated via `stroke-dashoffset`: the first draws the top half, the second\n * draws the left half with a fading gradient. Radius and stroke width come\n * from CSS custom properties set by the parent `.saltSpinner-*` size class.\n */\nexport const SpinnerSVG = ({\n id = \"svg-spinner\",\n ...rest\n}: SpinnerSVGProps) => {\n const gradientId = `${id}-1`;\n\n return (\n <svg\n className={withBaseName(\"spinner\")}\n preserveAspectRatio=\"xMidYMid meet\"\n id={id}\n {...rest}\n >\n <defs>\n <linearGradient id={gradientId} x1=\"0\" y1=\"0\" x2=\"50%\" y2=\"0\">\n <stop\n className={withBaseName(\"gradientStop\")}\n offset=\"15%\"\n stopOpacity=\"1\"\n />\n <stop\n className={withBaseName(\"gradientStop\")}\n offset=\"100%\"\n stopOpacity=\"0\"\n />\n </linearGradient>\n </defs>\n <circle\n className={withBaseName(\"arc\")}\n cx=\"50%\"\n cy=\"50%\"\n fill=\"none\"\n stroke=\"var(--saltSpinner-gradient-color, var(--salt-sentiment-accent-background))\"\n strokeWidth=\"var(--spinner-strokeWidth)\"\n pathLength=\"100\"\n strokeDasharray=\"50 50\"\n strokeDashoffset=\"50\"\n />\n <circle\n className={withBaseName(\"arc\")}\n cx=\"50%\"\n cy=\"50%\"\n fill=\"none\"\n stroke={`url(#${gradientId})`}\n strokeWidth=\"var(--spinner-strokeWidth)\"\n pathLength=\"100\"\n strokeDasharray=\"50 50\"\n strokeDashoffset=\"75\"\n />\n </svg>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;AAGA,MAAM,YAAA,GAAe,aAAa,aAAa,CAAA;AAWxC,MAAM,aAAa,CAAC;AAAA,EACzB,EAAA,GAAK,aAAA;AAAA,EACL,GAAG;AACL,CAAA,KAAuB;AACrB,EAAA,MAAM,UAAA,GAAa,GAAG,EAAE,CAAA,EAAA,CAAA;AAExB,EAAA,uBACE,IAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAW,aAAa,SAAS,CAAA;AAAA,MACjC,mBAAA,EAAoB,eAAA;AAAA,MACpB,EAAA;AAAA,MACC,GAAG,IAAA;AAAA,MAEJ,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,MAAA,EAAA,EACC,QAAA,kBAAA,IAAA,CAAC,gBAAA,EAAA,EAAe,EAAA,EAAI,UAAA,EAAY,EAAA,EAAG,GAAA,EAAI,EAAA,EAAG,GAAA,EAAI,EAAA,EAAG,KAAA,EAAM,EAAA,EAAG,GAAA,EACxD,QAAA,EAAA;AAAA,0BAAA,GAAA;AAAA,YAAC,MAAA;AAAA,YAAA;AAAA,cACC,SAAA,EAAW,aAAa,cAAc,CAAA;AAAA,cACtC,MAAA,EAAO,KAAA;AAAA,cACP,WAAA,EAAY;AAAA;AAAA,WACd;AAAA,0BACA,GAAA;AAAA,YAAC,MAAA;AAAA,YAAA;AAAA,cACC,SAAA,EAAW,aAAa,cAAc,CAAA;AAAA,cACtC,MAAA,EAAO,MAAA;AAAA,cACP,WAAA,EAAY;AAAA;AAAA;AACd,SAAA,EACF,CAAA,EACF,CAAA;AAAA,wBACA,GAAA;AAAA,UAAC,QAAA;AAAA,UAAA;AAAA,YACC,SAAA,EAAW,aAAa,KAAK,CAAA;AAAA,YAC7B,EAAA,EAAG,KAAA;AAAA,YACH,EAAA,EAAG,KAAA;AAAA,YACH,IAAA,EAAK,MAAA;AAAA,YACL,MAAA,EAAO,4EAAA;AAAA,YACP,WAAA,EAAY,4BAAA;AAAA,YACZ,UAAA,EAAW,KAAA;AAAA,YACX,eAAA,EAAgB,OAAA;AAAA,YAChB,gBAAA,EAAiB;AAAA;AAAA,SACnB;AAAA,wBACA,GAAA;AAAA,UAAC,QAAA;AAAA,UAAA;AAAA,YACC,SAAA,EAAW,aAAa,KAAK,CAAA;AAAA,YAC7B,EAAA,EAAG,KAAA;AAAA,YACH,EAAA,EAAG,KAAA;AAAA,YACH,IAAA,EAAK,MAAA;AAAA,YACL,MAAA,EAAQ,QAAQ,UAAU,CAAA,CAAA,CAAA;AAAA,YAC1B,WAAA,EAAY,4BAAA;AAAA,YACZ,UAAA,EAAW,KAAA;AAAA,YACX,eAAA,EAAgB,OAAA;AAAA,YAChB,gBAAA,EAAiB;AAAA;AAAA;AACnB;AAAA;AAAA,GACF;AAEJ;;;;"}
|
package/dist-types/index.d.ts
CHANGED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Supported placements for the mega menu panel.
|
|
4
|
+
*/
|
|
5
|
+
export type MegaMenuPlacement = "bottom" | "bottom-start" | "bottom-end";
|
|
6
|
+
export interface MegaMenuProps {
|
|
7
|
+
/**
|
|
8
|
+
* The content of the mega menu, typically `MegaMenuTrigger` and `MegaMenuPanel`.
|
|
9
|
+
*/
|
|
10
|
+
children?: ReactNode;
|
|
11
|
+
/**
|
|
12
|
+
* Whether the mega menu is open. Use for controlled mode.
|
|
13
|
+
*/
|
|
14
|
+
open?: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Whether the mega menu is initially open. Use for uncontrolled mode.
|
|
17
|
+
* @default false
|
|
18
|
+
*/
|
|
19
|
+
defaultOpen?: boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Callback fired when the open state changes.
|
|
22
|
+
*/
|
|
23
|
+
onOpenChange?: (open: boolean) => void;
|
|
24
|
+
/**
|
|
25
|
+
* The placement of the mega menu panel relative to the trigger.
|
|
26
|
+
* @default "bottom"
|
|
27
|
+
*/
|
|
28
|
+
placement?: MegaMenuPlacement;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Root of a mega menu, coordinating its trigger and panel.
|
|
32
|
+
*
|
|
33
|
+
* Not intended to be nested inside another floating overlay (e.g. a dialog or
|
|
34
|
+
* popover): the mega menu does not participate in floating-ui's `FloatingTree`
|
|
35
|
+
*/
|
|
36
|
+
export declare function MegaMenu({ children, open, defaultOpen, onOpenChange, placement, }: MegaMenuProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type ComponentPropsWithoutRef, type ReactNode } from "react";
|
|
2
|
+
export interface MegaMenuActionsProps extends ComponentPropsWithoutRef<"div"> {
|
|
3
|
+
/**
|
|
4
|
+
* The content of the actions. Place `MegaMenuActions` inside
|
|
5
|
+
* `MegaMenuContent`, after `MegaMenuGroups`; it renders as a band beneath the
|
|
6
|
+
* groups, spanning their width.
|
|
7
|
+
*/
|
|
8
|
+
children?: ReactNode;
|
|
9
|
+
}
|
|
10
|
+
export declare const MegaMenuActions: import("react").ForwardRefExoticComponent<MegaMenuActionsProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type ComponentPropsWithoutRef, type ReactNode } from "react";
|
|
2
|
+
export interface MegaMenuAsideProps extends ComponentPropsWithoutRef<"aside"> {
|
|
3
|
+
/**
|
|
4
|
+
* The content. Renders to the left of `MegaMenuContent` when placed before
|
|
5
|
+
* it, and to the right when placed after.
|
|
6
|
+
*/
|
|
7
|
+
children?: ReactNode;
|
|
8
|
+
}
|
|
9
|
+
export declare const MegaMenuAside: import("react").ForwardRefExoticComponent<MegaMenuAsideProps & import("react").RefAttributes<HTMLElement>>;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type ComponentPropsWithoutRef, type ReactNode } from "react";
|
|
2
|
+
export interface MegaMenuContentProps extends ComponentPropsWithoutRef<"div"> {
|
|
3
|
+
/**
|
|
4
|
+
* The content of the mega menu navigation area, typically a `MegaMenuGroups`
|
|
5
|
+
* and an optional `MegaMenuActions`.
|
|
6
|
+
*/
|
|
7
|
+
children?: ReactNode;
|
|
8
|
+
}
|
|
9
|
+
export declare const MegaMenuContent: import("react").ForwardRefExoticComponent<MegaMenuContentProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { FloatingRootContext } from "@floating-ui/react";
|
|
2
|
+
import type { Dispatch, HTMLProps, MutableRefObject, SetStateAction } from "react";
|
|
3
|
+
import type { MegaMenuPlacement } from "./MegaMenu";
|
|
4
|
+
export interface MegaMenuContextValue {
|
|
5
|
+
/** Whether the mega menu is currently open. */
|
|
6
|
+
openState: boolean;
|
|
7
|
+
/** Toggle or set the open state of the mega menu. */
|
|
8
|
+
setOpen: (open: boolean) => void;
|
|
9
|
+
/** The floating-ui root context for coordinating interactions. */
|
|
10
|
+
floatingRootContext: FloatingRootContext;
|
|
11
|
+
/** The placement of the mega menu panel relative to the trigger. */
|
|
12
|
+
placement: MegaMenuPlacement;
|
|
13
|
+
/** Props getter for the trigger (reference) element. Merges floating-ui interaction props with user props. */
|
|
14
|
+
getReferenceProps: (userProps?: HTMLProps<Element> | undefined) => Record<string, unknown>;
|
|
15
|
+
/** Props getter for the floating panel element. Merges floating-ui interaction props with user props. */
|
|
16
|
+
getFloatingProps: (userProps?: HTMLProps<HTMLElement> | undefined) => Record<string, unknown>;
|
|
17
|
+
/** Ref setter for the floating panel element. */
|
|
18
|
+
setFloating: Dispatch<SetStateAction<HTMLElement | null>>;
|
|
19
|
+
/** Ref setter for the trigger (reference) element. */
|
|
20
|
+
setReference: Dispatch<SetStateAction<HTMLElement | null>>;
|
|
21
|
+
/** Whether the first item should receive focus when the panel opens. */
|
|
22
|
+
focusFirstItemOnOpenRef: MutableRefObject<boolean>;
|
|
23
|
+
/** The id of the mega menu panel, used for aria-controls on the trigger. */
|
|
24
|
+
panelId: string | undefined;
|
|
25
|
+
/** Registers the panel's id so the trigger's aria-controls stays in sync. */
|
|
26
|
+
setPanelId: Dispatch<SetStateAction<string | undefined>>;
|
|
27
|
+
}
|
|
28
|
+
export declare const MegaMenuContext: import("react").Context<MegaMenuContextValue | undefined>;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type ComponentPropsWithoutRef, type ReactNode } from "react";
|
|
2
|
+
export interface MegaMenuGroupProps extends ComponentPropsWithoutRef<"div"> {
|
|
3
|
+
/**
|
|
4
|
+
* The content of the mega menu group: a `MegaMenuGroupHeading` and a
|
|
5
|
+
* `MegaMenuList` of `MegaMenuListItem`s.
|
|
6
|
+
*/
|
|
7
|
+
children?: ReactNode;
|
|
8
|
+
}
|
|
9
|
+
export declare const MegaMenuGroup: import("react").ForwardRefExoticComponent<MegaMenuGroupProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface MegaMenuGroupContextValue {
|
|
2
|
+
/**
|
|
3
|
+
* The rendered heading's id, used to label the item list via `aria-labelledby`.
|
|
4
|
+
* `undefined` when the group has no `MegaMenuGroupHeading`.
|
|
5
|
+
*/
|
|
6
|
+
headingId: string | undefined;
|
|
7
|
+
/** Register (or clear, with `undefined`) the heading's id. */
|
|
8
|
+
setHeadingId: (id: string | undefined) => void;
|
|
9
|
+
}
|
|
10
|
+
export declare const MegaMenuGroupContext: import("react").Context<MegaMenuGroupContextValue>;
|
|
11
|
+
/** Access the nearest `MegaMenuGroup` context. */
|
|
12
|
+
export declare function useMegaMenuGroup(): MegaMenuGroupContextValue;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type ComponentPropsWithoutRef, type ReactNode } from "react";
|
|
2
|
+
export interface MegaMenuGroupHeadingProps extends ComponentPropsWithoutRef<"h2"> {
|
|
3
|
+
/**
|
|
4
|
+
* The content of the mega menu group heading.
|
|
5
|
+
*/
|
|
6
|
+
children?: ReactNode;
|
|
7
|
+
/**
|
|
8
|
+
* The heading element to render.
|
|
9
|
+
* @default "h3"
|
|
10
|
+
*/
|
|
11
|
+
as?: "h1" | "h2" | "h3" | "h4" | "h5" | "h6";
|
|
12
|
+
}
|
|
13
|
+
export declare const MegaMenuGroupHeading: import("react").ForwardRefExoticComponent<MegaMenuGroupHeadingProps & import("react").RefAttributes<HTMLHeadingElement>>;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type ComponentPropsWithoutRef, type ReactNode } from "react";
|
|
2
|
+
export interface MegaMenuGroupsProps extends ComponentPropsWithoutRef<"div"> {
|
|
3
|
+
/**
|
|
4
|
+
* The `MegaMenuGroup` columns of the mega menu.
|
|
5
|
+
*/
|
|
6
|
+
children?: ReactNode;
|
|
7
|
+
}
|
|
8
|
+
export declare const MegaMenuGroups: import("react").ForwardRefExoticComponent<MegaMenuGroupsProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type ElementType, type FunctionComponent, type ReactNode } from "react";
|
|
2
|
+
import { type PolymorphicComponentPropWithRef } from "../utils";
|
|
3
|
+
export type MegaMenuListProps<T extends ElementType = "ul"> = PolymorphicComponentPropWithRef<T, {
|
|
4
|
+
/**
|
|
5
|
+
* The items of the group, typically `MegaMenuListItem` components. Each
|
|
6
|
+
* `MegaMenuListItem` renders its own `<li>`.
|
|
7
|
+
*/
|
|
8
|
+
children?: ReactNode;
|
|
9
|
+
}>;
|
|
10
|
+
type MegaMenuListComponent = <T extends ElementType = "ul">(props: MegaMenuListProps<T>) => ReturnType<FunctionComponent>;
|
|
11
|
+
/**
|
|
12
|
+
* The list of a group's `MegaMenuListItem`s. Renders a `<ul>` by default; pass
|
|
13
|
+
* `as="ol"` for an ordered list.
|
|
14
|
+
*/
|
|
15
|
+
export declare const MegaMenuList: MegaMenuListComponent;
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type ComponentPropsWithoutRef, type MouseEventHandler, type ReactNode } from "react";
|
|
2
|
+
import { type RenderPropsType } from "../utils";
|
|
3
|
+
export interface MegaMenuListItemProps extends Omit<ComponentPropsWithoutRef<"li">, "onClick"> {
|
|
4
|
+
/**
|
|
5
|
+
* The content of the mega menu item.
|
|
6
|
+
*/
|
|
7
|
+
children?: ReactNode;
|
|
8
|
+
/**
|
|
9
|
+
* Whether the item is the current page. Sets `aria-current="page"`
|
|
10
|
+
*/
|
|
11
|
+
current?: boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Href passed to the link action element.
|
|
14
|
+
*/
|
|
15
|
+
href?: string;
|
|
16
|
+
/**
|
|
17
|
+
* Called when the item's action is activated, before the menu closes.
|
|
18
|
+
*/
|
|
19
|
+
onClick?: MouseEventHandler<HTMLAnchorElement>;
|
|
20
|
+
/**
|
|
21
|
+
* Render prop to enable customization of the underlying action element (e.g. a router `Link`).
|
|
22
|
+
*/
|
|
23
|
+
render?: RenderPropsType["render"];
|
|
24
|
+
}
|
|
25
|
+
export declare const MegaMenuListItem: import("react").ForwardRefExoticComponent<MegaMenuListItemProps & import("react").RefAttributes<HTMLLIElement>>;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type ComponentPropsWithoutRef, type ReactNode } from "react";
|
|
2
|
+
export interface MegaMenuPanelProps extends ComponentPropsWithoutRef<"div"> {
|
|
3
|
+
/**
|
|
4
|
+
* The content of the mega menu panel.
|
|
5
|
+
*/
|
|
6
|
+
children?: ReactNode;
|
|
7
|
+
}
|
|
8
|
+
export declare const MegaMenuPanel: import("react").ForwardRefExoticComponent<MegaMenuPanelProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
export interface MegaMenuTriggerProps {
|
|
3
|
+
/**
|
|
4
|
+
* The trigger element for the mega menu, typically a `NavigationItem` or `Button`.
|
|
5
|
+
* Wrap each mega menu in its own `<li>` — arrow-key navigation between triggers depends on it.
|
|
6
|
+
*/
|
|
7
|
+
children?: ReactNode;
|
|
8
|
+
}
|
|
9
|
+
export declare const MegaMenuTrigger: import("react").ForwardRefExoticComponent<MegaMenuTriggerProps & import("react").RefAttributes<HTMLElement>>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export * from "./MegaMenu";
|
|
2
|
+
export * from "./MegaMenuActions";
|
|
3
|
+
export * from "./MegaMenuAside";
|
|
4
|
+
export * from "./MegaMenuContent";
|
|
5
|
+
export * from "./MegaMenuGroup";
|
|
6
|
+
export * from "./MegaMenuGroupHeading";
|
|
7
|
+
export * from "./MegaMenuGroups";
|
|
8
|
+
export * from "./MegaMenuList";
|
|
9
|
+
export * from "./MegaMenuListItem";
|
|
10
|
+
export * from "./MegaMenuPanel";
|
|
11
|
+
export * from "./MegaMenuTrigger";
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { ElementProps, FloatingRootContext } from "@floating-ui/react";
|
|
2
|
+
export declare const FOCUSABLE_SELECTOR = "a[href], button:not([disabled]), [tabindex]:not([tabindex=\"-1\"])";
|
|
3
|
+
export interface UseMegaMenuNavigationProps {
|
|
4
|
+
/**
|
|
5
|
+
* Whether the interaction is enabled.
|
|
6
|
+
* @default true
|
|
7
|
+
*/
|
|
8
|
+
enabled?: boolean;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Floating-ui interaction hook for mega menu keyboard navigation. Handles keys
|
|
12
|
+
* on the panel only; the trigger keys are owned by `MegaMenuTrigger`.
|
|
13
|
+
*/
|
|
14
|
+
export declare function useMegaMenuNavigation(context: FloatingRootContext, props?: UseMegaMenuNavigationProps): ElementProps;
|
|
15
|
+
/** Focus the first navigable item inside a mega menu panel, retrying until rendered. */
|
|
16
|
+
export declare function focusFirstItem(panel: HTMLElement, attempt?: number): void;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolves the panel's page-margin token to pixels for floating-ui padding, to
|
|
3
|
+
* handle token (`--saltMegaMenuPanel-pageMargin`) override by consumers
|
|
4
|
+
* (edge to edge example).
|
|
5
|
+
*/
|
|
6
|
+
export declare function usePageMargin(referenceEl: HTMLElement | null | undefined): number;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
export declare const SpinnerSVG: ({ id, rest
|
|
1
|
+
import type { ComponentPropsWithoutRef } from "react";
|
|
2
|
+
type SpinnerSVGProps = ComponentPropsWithoutRef<"svg">;
|
|
3
|
+
/**
|
|
4
|
+
* Draws the spinner as two overlapping circles. Each circle is half-stroked
|
|
5
|
+
* (`stroke-dasharray="50 50"` against a normalised `pathLength` of 100) and
|
|
6
|
+
* rotated via `stroke-dashoffset`: the first draws the top half, the second
|
|
7
|
+
* draws the left half with a fading gradient. Radius and stroke width come
|
|
8
|
+
* from CSS custom properties set by the parent `.saltSpinner-*` size class.
|
|
9
|
+
*/
|
|
10
|
+
export declare const SpinnerSVG: ({ id, ...rest }: SpinnerSVGProps) => import("react/jsx-runtime").JSX.Element;
|
|
11
11
|
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@salt-ds/core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.66.0",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
"@salt-ds/styles": "0.3.0",
|
|
23
23
|
"@salt-ds/window": "0.1.1",
|
|
24
24
|
"clsx": "^2.0.0",
|
|
25
|
+
"compute-scroll-into-view": "^3.0.0",
|
|
25
26
|
"dom-accessibility-api": "^0.7.1",
|
|
26
27
|
"tabbable": "^6.0.0",
|
|
27
28
|
"use-sync-external-store": "^1.5.0"
|