@smwb/ui-react 2.1.3 → 2.3.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/dist/assets/styles/less/components/appBar/appBar.entry.css +1 -1
- package/dist/assets/styles/less/components/assetGrid/assetGrid.entry.css +1 -0
- package/dist/assets/styles/less/components/chipGroup/chipGroup.entry.css +1 -0
- package/dist/assets/styles/less/components/lazyImage/lazyImage.entry.css +1 -0
- package/dist/assets/styles/less/components/overflowMenu/overflowMenu.entry.css +1 -0
- package/dist/assets/styles/less/components/saveAssetDialog/saveAssetDialog.entry.css +1 -0
- package/dist/assets/styles/less/components/sheet/sheet.entry.css +1 -1
- package/dist/assets/styles/less/components/thumbCard/thumbCard.entry.css +1 -0
- package/dist/assets/styles/less/components/valueSlider/valueSlider.entry.css +1 -0
- package/dist/components/dataDisplay/assetGrid/assetGrid.d.ts +30 -0
- package/dist/components/dataDisplay/assetGrid/assetGrid.js +68 -0
- package/dist/components/dataDisplay/assetGrid/assetGrid.js.map +1 -0
- package/dist/components/dataDisplay/assetGrid/index.d.ts +2 -0
- package/dist/components/dataDisplay/chat/useChatStickToBottom.js +8 -7
- package/dist/components/dataDisplay/chat/useChatStickToBottom.js.map +1 -1
- package/dist/components/dataDisplay/chipGroup/chipGroup.d.ts +27 -0
- package/dist/components/dataDisplay/chipGroup/chipGroup.js +42 -0
- package/dist/components/dataDisplay/chipGroup/chipGroup.js.map +1 -0
- package/dist/components/dataDisplay/chipGroup/index.d.ts +2 -0
- package/dist/components/dataDisplay/lazyImage/index.d.ts +2 -0
- package/dist/components/dataDisplay/lazyImage/lazyImage.d.ts +22 -0
- package/dist/components/dataDisplay/lazyImage/lazyImage.js +52 -0
- package/dist/components/dataDisplay/lazyImage/lazyImage.js.map +1 -0
- package/dist/components/dataDisplay/thumbCard/index.d.ts +2 -0
- package/dist/components/dataDisplay/thumbCard/thumbCard.d.ts +29 -0
- package/dist/components/dataDisplay/thumbCard/thumbCard.js +82 -0
- package/dist/components/dataDisplay/thumbCard/thumbCard.js.map +1 -0
- package/dist/components/feedBack/saveAssetDialog/index.d.ts +2 -0
- package/dist/components/feedBack/saveAssetDialog/saveAssetDialog.d.ts +30 -0
- package/dist/components/feedBack/saveAssetDialog/saveAssetDialog.js +60 -0
- package/dist/components/feedBack/saveAssetDialog/saveAssetDialog.js.map +1 -0
- package/dist/components/inputs/valueSlider/index.d.ts +2 -0
- package/dist/components/inputs/valueSlider/valueSlider.d.ts +23 -0
- package/dist/components/inputs/valueSlider/valueSlider.js +55 -0
- package/dist/components/inputs/valueSlider/valueSlider.js.map +1 -0
- package/dist/components/navigation/overflowMenu/index.d.ts +2 -0
- package/dist/components/navigation/overflowMenu/overflowMenu.d.ts +27 -0
- package/dist/components/navigation/overflowMenu/overflowMenu.js +54 -0
- package/dist/components/navigation/overflowMenu/overflowMenu.js.map +1 -0
- package/dist/headless/components/dataDisplay/assetGrid/assetGrid.js +67 -0
- package/dist/headless/components/dataDisplay/assetGrid/assetGrid.js.map +1 -0
- package/dist/headless/components/dataDisplay/chat/useChatStickToBottom.js +8 -7
- package/dist/headless/components/dataDisplay/chat/useChatStickToBottom.js.map +1 -1
- package/dist/headless/components/dataDisplay/chipGroup/chipGroup.js +41 -0
- package/dist/headless/components/dataDisplay/chipGroup/chipGroup.js.map +1 -0
- package/dist/headless/components/dataDisplay/lazyImage/lazyImage.js +51 -0
- package/dist/headless/components/dataDisplay/lazyImage/lazyImage.js.map +1 -0
- package/dist/headless/components/dataDisplay/thumbCard/thumbCard.js +81 -0
- package/dist/headless/components/dataDisplay/thumbCard/thumbCard.js.map +1 -0
- package/dist/headless/components/feedBack/saveAssetDialog/saveAssetDialog.js +59 -0
- package/dist/headless/components/feedBack/saveAssetDialog/saveAssetDialog.js.map +1 -0
- package/dist/headless/components/inputs/valueSlider/valueSlider.js +54 -0
- package/dist/headless/components/inputs/valueSlider/valueSlider.js.map +1 -0
- package/dist/headless/components/navigation/overflowMenu/overflowMenu.js +53 -0
- package/dist/headless/components/navigation/overflowMenu/overflowMenu.js.map +1 -0
- package/dist/headless/hooks/useEventCallback.js +8 -7
- package/dist/headless/hooks/useEventCallback.js.map +1 -1
- package/dist/headless/hooks/useTheme.js +16 -15
- package/dist/headless/hooks/useTheme.js.map +1 -1
- package/dist/headless/index.js +240 -226
- package/dist/headless/index.js.map +1 -1
- package/dist/hooks/useEventCallback.js +8 -7
- package/dist/hooks/useEventCallback.js.map +1 -1
- package/dist/hooks/useTheme.js +16 -15
- package/dist/hooks/useTheme.js.map +1 -1
- package/dist/index.cjs +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +14 -0
- package/dist/index.js +240 -226
- package/dist/index.js.map +1 -1
- package/package.json +6 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"thumbCard.js","sources":["../../../../../src/components/dataDisplay/thumbCard/thumbCard.tsx"],"sourcesContent":["import React, { forwardRef, useEffect, useRef, useState } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport cn from \"clsx\";\nimport { LazyImage } from \"../lazyImage\";\nimport { useForkRef } from \"../../../hooks/useForkRef\";\n\nexport interface ThumbCardProps extends Omit<React.HTMLAttributes<HTMLDivElement>, \"onSelect\"> {\n /** Thumbnail URL; falls back to `fallback` when missing / failed. */\n src?: string;\n caption?: React.ReactNode;\n selected?: boolean;\n /** Makes the card a selectable button (keyboard + `aria-pressed`). */\n onSelect?: () => void;\n /** Shown in place of the image when `src` is missing / fails. */\n fallback?: React.ReactNode;\n /** A larger preview shown in a floating popup after a hover delay. */\n hoverPreview?: React.ReactNode | string;\n /** Top-left overlay slot (e.g. a favourite star). */\n topStart?: React.ReactNode;\n /** Top-right overlay slot (e.g. a kebab menu). */\n topEnd?: React.ReactNode;\n lazy?: boolean;\n disabled?: boolean;\n /** Delay (ms) before the hover preview appears. Default 350. */\n hoverDelay?: number;\n}\n\n/**\n * A selectable gallery card: image with an `onError` fallback + optional lazy\n * load, keyboard/`aria-pressed` selection, corner action slots, and a delayed\n * floating hover-preview. The generic gallery-card behaviour every app rebuilds\n * on top of the primitives. SSR-safe — the hover preview is client-only.\n */\nexport const ThumbCard = forwardRef<HTMLDivElement, ThumbCardProps>(function ThumbCard(\n {\n src,\n caption,\n selected,\n onSelect,\n fallback,\n hoverPreview,\n topStart,\n topEnd,\n lazy = true,\n disabled,\n hoverDelay = 350,\n className,\n ...rest\n },\n ref\n) {\n const cardRef = useRef<HTMLDivElement | null>(null);\n const setRefs = useForkRef(ref, cardRef);\n const [preview, setPreview] = useState<{ top: number; left: number } | null>(null);\n const timer = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const clearTimer = (): void => {\n if (timer.current) {\n clearTimeout(timer.current);\n timer.current = null;\n }\n };\n const onEnter = (): void => {\n if (hoverPreview == null || disabled) return;\n clearTimer();\n timer.current = setTimeout(() => {\n const rect = cardRef.current?.getBoundingClientRect();\n if (rect) setPreview({ top: rect.top, left: rect.right + 8 });\n }, hoverDelay);\n };\n const onLeave = (): void => {\n clearTimer();\n setPreview(null);\n };\n useEffect(() => clearTimer, []);\n\n const interactive = !!onSelect && !disabled;\n const onKeyDown = (event: React.KeyboardEvent<HTMLDivElement>): void => {\n if (interactive && (event.key === \"Enter\" || event.key === \" \")) {\n event.preventDefault();\n onSelect?.();\n }\n };\n\n return (\n <div\n {...rest}\n ref={setRefs}\n className={cn(\"smwb-thumb-card\", className, {\n \"smwb-thumb-card--selected\": selected,\n \"smwb-thumb-card--disabled\": disabled,\n \"smwb-thumb-card--interactive\": interactive,\n })}\n role={interactive ? \"button\" : undefined}\n tabIndex={interactive ? 0 : undefined}\n aria-pressed={onSelect ? (selected ?? false) : undefined}\n aria-disabled={disabled || undefined}\n onClick={interactive ? () => onSelect?.() : undefined}\n onKeyDown={onKeyDown}\n onMouseEnter={onEnter}\n onMouseLeave={onLeave}\n >\n <div className=\"smwb-thumb-card__media\">\n <LazyImage src={src} lazy={lazy} fallback={fallback} />\n {topStart ? <div className=\"smwb-thumb-card__slot smwb-thumb-card__slot--start\">{topStart}</div> : null}\n {topEnd ? <div className=\"smwb-thumb-card__slot smwb-thumb-card__slot--end\">{topEnd}</div> : null}\n </div>\n {caption ? <div className=\"smwb-thumb-card__caption\">{caption}</div> : null}\n {preview && typeof document !== \"undefined\"\n ? createPortal(\n <div\n className=\"smwb-thumb-card__preview\"\n style={{ position: \"fixed\", top: preview.top, left: preview.left }}\n >\n {typeof hoverPreview === \"string\" ? <img src={hoverPreview} alt=\"\" /> : hoverPreview}\n </div>,\n document.body\n )\n : null}\n </div>\n );\n});\n\nexport default ThumbCard;\n"],"names":["ThumbCard","forwardRef","src","caption","selected","onSelect","fallback","hoverPreview","topStart","topEnd","lazy","disabled","hoverDelay","className","rest","ref","cardRef","useRef","setRefs","useForkRef","preview","setPreview","useState","timer","clearTimer","onEnter","rect","_a","onLeave","useEffect","interactive","onKeyDown","event","jsxs","cn","jsx","LazyImage","createPortal"],"mappings":"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"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { jsxs as w, jsx as i } from "react/jsx-runtime";
|
|
2
|
+
import c from "clsx";
|
|
3
|
+
import { Modal as r } from "../modal/modal.js";
|
|
4
|
+
import { TextField as e } from "../../inputs/textField/textField.js";
|
|
5
|
+
import { Button as _ } from "../../inputs/button/button.js";
|
|
6
|
+
function D({
|
|
7
|
+
open: p,
|
|
8
|
+
title: o,
|
|
9
|
+
nameLabel: t,
|
|
10
|
+
name: d,
|
|
11
|
+
onNameChange: s,
|
|
12
|
+
previewSrc: f,
|
|
13
|
+
onCapture: h,
|
|
14
|
+
captureLabel: v,
|
|
15
|
+
busy: l,
|
|
16
|
+
confirmLabel: x,
|
|
17
|
+
cancelLabel: u,
|
|
18
|
+
onConfirm: F,
|
|
19
|
+
onClose: k,
|
|
20
|
+
children: j,
|
|
21
|
+
className: z
|
|
22
|
+
}) {
|
|
23
|
+
const S = s !== void 0 || d !== void 0;
|
|
24
|
+
return /* @__PURE__ */ w(r, { open: p, onClose: k, size: "small", children: [
|
|
25
|
+
/* @__PURE__ */ i(r.Header, { children: o != null ? o : "Save" }),
|
|
26
|
+
/* @__PURE__ */ i(r.Content, { children: /* @__PURE__ */ w("div", { className: c("smwb-save-asset-dialog__body", z), children: [
|
|
27
|
+
S ? /* @__PURE__ */ i(
|
|
28
|
+
e,
|
|
29
|
+
{
|
|
30
|
+
label: t != null ? t : "Name",
|
|
31
|
+
value: d != null ? d : "",
|
|
32
|
+
disabled: !!l,
|
|
33
|
+
onChange: (T) => s == null ? void 0 : s(T.currentTarget.value)
|
|
34
|
+
}
|
|
35
|
+
) : null,
|
|
36
|
+
f ? /* @__PURE__ */ i("div", { className: "smwb-save-asset-dialog__preview", children: /* @__PURE__ */ i("img", { src: f, alt: "" }) }) : null,
|
|
37
|
+
h ? /* @__PURE__ */ i(
|
|
38
|
+
_,
|
|
39
|
+
{
|
|
40
|
+
variant: "outlined",
|
|
41
|
+
size: "small",
|
|
42
|
+
disabled: !!l,
|
|
43
|
+
onClick: () => h(),
|
|
44
|
+
label: v != null ? v : "Capture preview"
|
|
45
|
+
}
|
|
46
|
+
) : null,
|
|
47
|
+
j
|
|
48
|
+
] }) }),
|
|
49
|
+
/* @__PURE__ */ w(r.Footer, { children: [
|
|
50
|
+
/* @__PURE__ */ i(_, { variant: "text", disabled: !!l, onClick: () => k(), label: u != null ? u : "Cancel" }),
|
|
51
|
+
/* @__PURE__ */ i(_, { variant: "contained", disabled: !!l, onClick: () => F(), label: x != null ? x : "Save" })
|
|
52
|
+
] })
|
|
53
|
+
] });
|
|
54
|
+
}
|
|
55
|
+
export {
|
|
56
|
+
D as SaveAssetDialog,
|
|
57
|
+
D as default
|
|
58
|
+
};
|
|
59
|
+
//# sourceMappingURL=saveAssetDialog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"saveAssetDialog.js","sources":["../../../../../src/components/feedBack/saveAssetDialog/saveAssetDialog.tsx"],"sourcesContent":["import React from \"react\";\nimport cn from \"clsx\";\nimport { Modal } from \"../modal\";\nimport { Button } from \"../../inputs/button\";\nimport { TextField } from \"../../inputs/textField\";\n\nexport interface SaveAssetDialogProps {\n open: boolean;\n title?: string;\n /** Label for the name field. Omit `onNameChange` AND `name` to hide the field. */\n nameLabel?: string;\n name?: string;\n onNameChange?: (name: string) => void;\n /** Preview image URL (e.g. a freshly captured thumbnail). */\n previewSrc?: string;\n /** Shows a Capture button when provided. */\n onCapture?: () => void;\n captureLabel?: string;\n /** Disables the actions + name field while a save/capture is in flight. */\n busy?: boolean;\n confirmLabel?: string;\n cancelLabel?: string;\n onConfirm: () => void;\n onClose: () => void;\n /** Extra content between the name field/preview and the actions. */\n children?: React.ReactNode;\n className?: string;\n}\n\n/**\n * A \"name it / preview a thumbnail / confirm-cancel\" dialog on `Modal` — the\n * save/capture flow apps hand-build for every asset. Pairs with srv-solid's\n * asset store: `onConfirm` uploads the captured `previewSrc`.\n */\nexport function SaveAssetDialog({\n open,\n title,\n nameLabel,\n name,\n onNameChange,\n previewSrc,\n onCapture,\n captureLabel,\n busy,\n confirmLabel,\n cancelLabel,\n onConfirm,\n onClose,\n children,\n className,\n}: SaveAssetDialogProps): React.ReactElement {\n const showNameField = onNameChange !== undefined || name !== undefined;\n\n return (\n <Modal open={open} onClose={onClose} size=\"small\">\n <Modal.Header>{title ?? \"Save\"}</Modal.Header>\n <Modal.Content>\n <div className={cn(\"smwb-save-asset-dialog__body\", className)}>\n {showNameField ? (\n <TextField\n label={nameLabel ?? \"Name\"}\n value={name ?? \"\"}\n disabled={!!busy}\n onChange={(event) => onNameChange?.(event.currentTarget.value)}\n />\n ) : null}\n {previewSrc ? (\n <div className=\"smwb-save-asset-dialog__preview\">\n <img src={previewSrc} alt=\"\" />\n </div>\n ) : null}\n {onCapture ? (\n <Button\n variant=\"outlined\"\n size=\"small\"\n disabled={!!busy}\n onClick={() => onCapture()}\n label={captureLabel ?? \"Capture preview\"}\n />\n ) : null}\n {children}\n </div>\n </Modal.Content>\n <Modal.Footer>\n <Button variant=\"text\" disabled={!!busy} onClick={() => onClose()} label={cancelLabel ?? \"Cancel\"} />\n <Button variant=\"contained\" disabled={!!busy} onClick={() => onConfirm()} label={confirmLabel ?? \"Save\"} />\n </Modal.Footer>\n </Modal>\n );\n}\n\nexport default SaveAssetDialog;\n"],"names":["SaveAssetDialog","open","title","nameLabel","name","onNameChange","previewSrc","onCapture","captureLabel","busy","confirmLabel","cancelLabel","onConfirm","onClose","children","className","showNameField","jsxs","Modal","jsx","cn","TextField","event","Button"],"mappings":";;;;;AAkCO,SAASA,EAAgB;AAAA,EAC9B,MAAAC;AAAA,EACA,OAAAC;AAAA,EACA,WAAAC;AAAA,EACA,MAAAC;AAAA,EACA,cAAAC;AAAA,EACA,YAAAC;AAAA,EACA,WAAAC;AAAA,EACA,cAAAC;AAAA,EACA,MAAAC;AAAA,EACA,cAAAC;AAAA,EACA,aAAAC;AAAA,EACA,WAAAC;AAAA,EACA,SAAAC;AAAA,EACA,UAAAC;AAAA,EACA,WAAAC;AACF,GAA6C;AAC3C,QAAMC,IAAgBX,MAAiB,UAAaD,MAAS;AAE7D,SACE,gBAAAa,EAACC,GAAA,EAAM,MAAAjB,GAAY,SAAAY,GAAkB,MAAK,SACxC,UAAA;AAAA,IAAA,gBAAAM,EAACD,EAAM,QAAN,EAAc,UAAAhB,KAAA,OAAAA,IAAS,QAAO;AAAA,IAC/B,gBAAAiB,EAACD,EAAM,SAAN,EACC,UAAA,gBAAAD,EAAC,SAAI,WAAWG,EAAG,gCAAgCL,CAAS,GACzD,UAAA;AAAA,MAAAC,IACC,gBAAAG;AAAA,QAACE;AAAA,QAAA;AAAA,UACC,OAAOlB,KAAA,OAAAA,IAAa;AAAA,UACpB,OAAOC,KAAA,OAAAA,IAAQ;AAAA,UACf,UAAU,CAAC,CAACK;AAAA,UACZ,UAAU,CAACa,MAAUjB,KAAA,gBAAAA,EAAeiB,EAAM,cAAc;AAAA,QAAK;AAAA,MAAA,IAE7D;AAAA,MACHhB,IACC,gBAAAa,EAAC,OAAA,EAAI,WAAU,mCACb,UAAA,gBAAAA,EAAC,OAAA,EAAI,KAAKb,GAAY,KAAI,GAAA,CAAG,EAAA,CAC/B,IACE;AAAA,MACHC,IACC,gBAAAY;AAAA,QAACI;AAAA,QAAA;AAAA,UACC,SAAQ;AAAA,UACR,MAAK;AAAA,UACL,UAAU,CAAC,CAACd;AAAA,UACZ,SAAS,MAAMF,EAAA;AAAA,UACf,OAAOC,KAAA,OAAAA,IAAgB;AAAA,QAAA;AAAA,MAAA,IAEvB;AAAA,MACHM;AAAA,IAAA,EAAA,CACH,EAAA,CACF;AAAA,IACA,gBAAAG,EAACC,EAAM,QAAN,EACC,UAAA;AAAA,MAAA,gBAAAC,EAACI,GAAA,EAAO,SAAQ,QAAO,UAAU,CAAC,CAACd,GAAM,SAAS,MAAMI,EAAA,GAAW,OAAOF,KAAA,OAAAA,IAAe,SAAA,CAAU;AAAA,MACnG,gBAAAQ,EAACI,GAAA,EAAO,SAAQ,aAAY,UAAU,CAAC,CAACd,GAAM,SAAS,MAAMG,EAAA,GAAa,OAAOF,KAAA,OAAAA,IAAgB,OAAA,CAAQ;AAAA,IAAA,EAAA,CAC3G;AAAA,EAAA,GACF;AAEJ;"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { jsxs as t, jsx as n } from "react/jsx-runtime";
|
|
2
|
+
import c from "clsx";
|
|
3
|
+
import { Slider as m } from "../slider/slider.js";
|
|
4
|
+
function h(r, l) {
|
|
5
|
+
return typeof r == "function" ? r(l) : Array.isArray(l) ? `${l[0]} – ${l[1]}` : l == null ? "" : String(l);
|
|
6
|
+
}
|
|
7
|
+
function w({
|
|
8
|
+
readout: r,
|
|
9
|
+
endAdornment: l,
|
|
10
|
+
onReset: i,
|
|
11
|
+
resetLabel: s,
|
|
12
|
+
label: e,
|
|
13
|
+
className: u,
|
|
14
|
+
...a
|
|
15
|
+
}) {
|
|
16
|
+
const d = r !== void 0 && r !== !1, o = e != null || d || l != null || i != null;
|
|
17
|
+
return /* @__PURE__ */ t("div", { className: c("smwb-value-slider", u), children: [
|
|
18
|
+
o ? /* @__PURE__ */ t("div", { className: "smwb-value-slider__header", children: [
|
|
19
|
+
e != null ? /* @__PURE__ */ n("span", { className: "smwb-value-slider__label", children: e }) : null,
|
|
20
|
+
/* @__PURE__ */ n("span", { className: "smwb-value-slider__spacer" }),
|
|
21
|
+
d ? /* @__PURE__ */ n("span", { className: "smwb-value-slider__readout", children: h(r, a.value) }) : null,
|
|
22
|
+
l,
|
|
23
|
+
i != null ? /* @__PURE__ */ n(
|
|
24
|
+
"button",
|
|
25
|
+
{
|
|
26
|
+
type: "button",
|
|
27
|
+
className: "smwb-value-slider__reset",
|
|
28
|
+
"aria-label": s != null ? s : "Reset",
|
|
29
|
+
disabled: !!a.disabled,
|
|
30
|
+
onClick: () => i(),
|
|
31
|
+
children: /* @__PURE__ */ n(
|
|
32
|
+
"svg",
|
|
33
|
+
{
|
|
34
|
+
viewBox: "0 0 24 24",
|
|
35
|
+
width: "16",
|
|
36
|
+
height: "16",
|
|
37
|
+
"aria-hidden": "true",
|
|
38
|
+
fill: "none",
|
|
39
|
+
stroke: "currentColor",
|
|
40
|
+
strokeWidth: "2",
|
|
41
|
+
children: /* @__PURE__ */ n("path", { d: "M3 12a9 9 0 1 0 3-6.7M3 4v4h4", strokeLinecap: "round", strokeLinejoin: "round" })
|
|
42
|
+
}
|
|
43
|
+
)
|
|
44
|
+
}
|
|
45
|
+
) : null
|
|
46
|
+
] }) : null,
|
|
47
|
+
/* @__PURE__ */ n(m, { ...a })
|
|
48
|
+
] });
|
|
49
|
+
}
|
|
50
|
+
export {
|
|
51
|
+
w as ValueSlider,
|
|
52
|
+
w as default
|
|
53
|
+
};
|
|
54
|
+
//# sourceMappingURL=valueSlider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"valueSlider.js","sources":["../../../../../src/components/inputs/valueSlider/valueSlider.tsx"],"sourcesContent":["import React from \"react\";\nimport cn from \"clsx\";\nimport { Slider, type SliderProps, type SliderValue } from \"../slider\";\n\nexport interface ValueSliderProps extends SliderProps {\n /**\n * Read-only value readout beside the label. `true` shows the raw value; pass a\n * formatter for units/precision (e.g. `(v) => `${v}%``). Reflects `value`.\n */\n readout?: boolean | ((value: SliderValue | undefined) => string);\n /** Content at the end of the header row — a reset button, a favourite star, etc. */\n endAdornment?: React.ReactNode;\n /** Renders a built-in reset control in the header; called on click. */\n onReset?: () => void;\n /** Accessible label for the reset control. */\n resetLabel?: string;\n}\n\nfunction formatReadout(readout: ValueSliderProps[\"readout\"], value: SliderValue | undefined): string {\n if (typeof readout === \"function\") return readout(value);\n if (Array.isArray(value)) return `${value[0]} – ${value[1]}`;\n return value == null ? \"\" : String(value);\n}\n\n/**\n * `Slider` plus the value-readout + adornment header row every app rebuilds: a\n * read-only formatted value next to the label, an optional reset \"eraser\", and an\n * `endAdornment` slot. A drop-in preset — all `Slider` props pass through; the\n * label is rendered in the header instead of inside Slider.\n */\nexport function ValueSlider({\n readout,\n endAdornment,\n onReset,\n resetLabel,\n label,\n className,\n ...sliderProps\n}: ValueSliderProps): React.ReactElement {\n const hasReadout = readout !== undefined && readout !== false;\n const showHeader = label != null || hasReadout || endAdornment != null || onReset != null;\n\n return (\n <div className={cn(\"smwb-value-slider\", className)}>\n {showHeader ? (\n <div className=\"smwb-value-slider__header\">\n {label != null ? <span className=\"smwb-value-slider__label\">{label}</span> : null}\n <span className=\"smwb-value-slider__spacer\" />\n {hasReadout ? (\n <span className=\"smwb-value-slider__readout\">{formatReadout(readout, sliderProps.value)}</span>\n ) : null}\n {endAdornment}\n {onReset != null ? (\n <button\n type=\"button\"\n className=\"smwb-value-slider__reset\"\n aria-label={resetLabel ?? \"Reset\"}\n disabled={!!sliderProps.disabled}\n onClick={() => onReset()}\n >\n <svg\n viewBox=\"0 0 24 24\"\n width=\"16\"\n height=\"16\"\n aria-hidden=\"true\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n >\n <path d=\"M3 12a9 9 0 1 0 3-6.7M3 4v4h4\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n </button>\n ) : null}\n </div>\n ) : null}\n <Slider {...sliderProps} />\n </div>\n );\n}\n\nexport default ValueSlider;\n"],"names":["formatReadout","readout","value","ValueSlider","endAdornment","onReset","resetLabel","label","className","sliderProps","hasReadout","showHeader","cn","jsxs","jsx","Slider"],"mappings":";;;AAkBA,SAASA,EAAcC,GAAsCC,GAAwC;AACnG,SAAI,OAAOD,KAAY,aAAmBA,EAAQC,CAAK,IACnD,MAAM,QAAQA,CAAK,IAAU,GAAGA,EAAM,CAAC,CAAC,MAAMA,EAAM,CAAC,CAAC,KACnDA,KAAS,OAAO,KAAK,OAAOA,CAAK;AAC1C;AAQO,SAASC,EAAY;AAAA,EAC1B,SAAAF;AAAA,EACA,cAAAG;AAAA,EACA,SAAAC;AAAA,EACA,YAAAC;AAAA,EACA,OAAAC;AAAA,EACA,WAAAC;AAAA,EACA,GAAGC;AACL,GAAyC;AACvC,QAAMC,IAAaT,MAAY,UAAaA,MAAY,IAClDU,IAAaJ,KAAS,QAAQG,KAAcN,KAAgB,QAAQC,KAAW;AAErF,2BACG,OAAA,EAAI,WAAWO,EAAG,qBAAqBJ,CAAS,GAC9C,UAAA;AAAA,IAAAG,IACC,gBAAAE,EAAC,OAAA,EAAI,WAAU,6BACZ,UAAA;AAAA,MAAAN,KAAS,OAAO,gBAAAO,EAAC,QAAA,EAAK,WAAU,4BAA4B,aAAM,IAAU;AAAA,MAC7E,gBAAAA,EAAC,QAAA,EAAK,WAAU,4BAAA,CAA4B;AAAA,MAC3CJ,IACC,gBAAAI,EAAC,QAAA,EAAK,WAAU,8BAA8B,YAAcb,GAASQ,EAAY,KAAK,EAAA,CAAE,IACtF;AAAA,MACHL;AAAA,MACAC,KAAW,OACV,gBAAAS;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,MAAK;AAAA,UACL,WAAU;AAAA,UACV,cAAYR,KAAA,OAAAA,IAAc;AAAA,UAC1B,UAAU,CAAC,CAACG,EAAY;AAAA,UACxB,SAAS,MAAMJ,EAAA;AAAA,UAEf,UAAA,gBAAAS;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,SAAQ;AAAA,cACR,OAAM;AAAA,cACN,QAAO;AAAA,cACP,eAAY;AAAA,cACZ,MAAK;AAAA,cACL,QAAO;AAAA,cACP,aAAY;AAAA,cAEZ,4BAAC,QAAA,EAAK,GAAE,iCAAgC,eAAc,SAAQ,gBAAe,QAAA,CAAQ;AAAA,YAAA;AAAA,UAAA;AAAA,QACvF;AAAA,MAAA,IAEA;AAAA,IAAA,EAAA,CACN,IACE;AAAA,IACJ,gBAAAA,EAACC,GAAA,EAAQ,GAAGN,EAAA,CAAa;AAAA,EAAA,GAC3B;AAEJ;"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { jsxs as f, jsx as e } from "react/jsx-runtime";
|
|
2
|
+
import { useRef as h, useState as b } from "react";
|
|
3
|
+
import t from "clsx";
|
|
4
|
+
import { Button as v } from "../../inputs/button/button.js";
|
|
5
|
+
import { Menu as w } from "../menu/menu.js";
|
|
6
|
+
import { MenuItem as x } from "../menu/menuItem.js";
|
|
7
|
+
import { Icon as M } from "../../base/icon/icon.js";
|
|
8
|
+
function N({
|
|
9
|
+
items: u,
|
|
10
|
+
icon: p = "more_vert",
|
|
11
|
+
placement: r,
|
|
12
|
+
"aria-label": n,
|
|
13
|
+
disabled: d,
|
|
14
|
+
className: i
|
|
15
|
+
}) {
|
|
16
|
+
const s = h(null), [m, l] = b(!1), c = () => l(!1);
|
|
17
|
+
return /* @__PURE__ */ f("span", { className: t("smwb-overflow-menu", i), children: [
|
|
18
|
+
/* @__PURE__ */ e(
|
|
19
|
+
v,
|
|
20
|
+
{
|
|
21
|
+
ref: s,
|
|
22
|
+
variant: "text",
|
|
23
|
+
size: "small",
|
|
24
|
+
icon: p,
|
|
25
|
+
"aria-label": n != null ? n : "More actions",
|
|
26
|
+
"aria-haspopup": "menu",
|
|
27
|
+
disabled: !!d,
|
|
28
|
+
onClick: () => l((o) => !o)
|
|
29
|
+
}
|
|
30
|
+
),
|
|
31
|
+
/* @__PURE__ */ e(w, { isOpen: m, onClose: c, anchorElement: s.current, ...r ? { placement: r } : {}, children: u.map((o) => /* @__PURE__ */ f(
|
|
32
|
+
x,
|
|
33
|
+
{
|
|
34
|
+
className: t({ "smwb-overflow-menu__item--danger": o.danger }),
|
|
35
|
+
disabled: o.disabled,
|
|
36
|
+
onClick: () => {
|
|
37
|
+
var a;
|
|
38
|
+
o.disabled || ((a = o.onSelect) == null || a.call(o), c());
|
|
39
|
+
},
|
|
40
|
+
children: [
|
|
41
|
+
o.icon ? typeof o.icon == "string" ? /* @__PURE__ */ e(M, { name: o.icon }) : o.icon : null,
|
|
42
|
+
o.label
|
|
43
|
+
]
|
|
44
|
+
},
|
|
45
|
+
o.id
|
|
46
|
+
)) })
|
|
47
|
+
] });
|
|
48
|
+
}
|
|
49
|
+
export {
|
|
50
|
+
N as OverflowMenu,
|
|
51
|
+
N as default
|
|
52
|
+
};
|
|
53
|
+
//# sourceMappingURL=overflowMenu.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"overflowMenu.js","sources":["../../../../../src/components/navigation/overflowMenu/overflowMenu.tsx"],"sourcesContent":["import React, { useRef, useState } from \"react\";\nimport type { Placement } from \"@floating-ui/react\";\nimport cn from \"clsx\";\nimport { Button } from \"../../inputs/button\";\nimport { Icon } from \"../../base/icon\";\nimport { Menu, MenuItem } from \"../menu\";\n\nexport interface OverflowMenuItem {\n id: string;\n label: string;\n icon?: React.ReactNode | string;\n danger?: boolean;\n disabled?: boolean;\n onSelect?: () => void;\n}\n\nexport interface OverflowMenuProps {\n items: OverflowMenuItem[];\n /** Trigger icon name (default `more_vert`). */\n icon?: string;\n placement?: Placement;\n \"aria-label\"?: string;\n disabled?: boolean;\n className?: string;\n}\n\n/**\n * A one-shot kebab / overflow menu: a trigger icon button wired to a floating\n * `Menu` over an `items` array, with open/close state baked in. The card 3-dot\n * menu every app hand-builds (button + surface + open state) collapses to\n * passing an items list.\n */\nexport function OverflowMenu({\n items,\n icon = \"more_vert\",\n placement,\n \"aria-label\": ariaLabel,\n disabled,\n className,\n}: OverflowMenuProps): React.ReactElement {\n const anchorRef = useRef<HTMLButtonElement | HTMLAnchorElement | null>(null);\n const [open, setOpen] = useState(false);\n const close = (): void => setOpen(false);\n\n return (\n <span className={cn(\"smwb-overflow-menu\", className)}>\n <Button\n ref={anchorRef}\n variant=\"text\"\n size=\"small\"\n icon={icon}\n aria-label={ariaLabel ?? \"More actions\"}\n aria-haspopup=\"menu\"\n disabled={!!disabled}\n onClick={() => setOpen((value) => !value)}\n />\n <Menu isOpen={open} onClose={close} anchorElement={anchorRef.current} {...(placement ? { placement } : {})}>\n {items.map((item) => (\n <MenuItem\n key={item.id}\n className={cn({ \"smwb-overflow-menu__item--danger\": item.danger })}\n disabled={item.disabled}\n onClick={() => {\n if (item.disabled) return;\n item.onSelect?.();\n close();\n }}\n >\n {item.icon ? typeof item.icon === \"string\" ? <Icon name={item.icon} /> : item.icon : null}\n {item.label}\n </MenuItem>\n ))}\n </Menu>\n </span>\n );\n}\n\nexport default OverflowMenu;\n"],"names":["OverflowMenu","items","icon","placement","ariaLabel","disabled","className","anchorRef","useRef","open","setOpen","useState","close","cn","jsx","Button","value","Menu","item","jsxs","MenuItem","_a","Icon"],"mappings":";;;;;;;AAgCO,SAASA,EAAa;AAAA,EAC3B,OAAAC;AAAA,EACA,MAAAC,IAAO;AAAA,EACP,WAAAC;AAAA,EACA,cAAcC;AAAA,EACd,UAAAC;AAAA,EACA,WAAAC;AACF,GAA0C;AACxC,QAAMC,IAAYC,EAAqD,IAAI,GACrE,CAACC,GAAMC,CAAO,IAAIC,EAAS,EAAK,GAChCC,IAAQ,MAAYF,EAAQ,EAAK;AAEvC,2BACG,QAAA,EAAK,WAAWG,EAAG,sBAAsBP,CAAS,GACjD,UAAA;AAAA,IAAA,gBAAAQ;AAAA,MAACC;AAAA,MAAA;AAAA,QACC,KAAKR;AAAA,QACL,SAAQ;AAAA,QACR,MAAK;AAAA,QACL,MAAAL;AAAA,QACA,cAAYE,KAAA,OAAAA,IAAa;AAAA,QACzB,iBAAc;AAAA,QACd,UAAU,CAAC,CAACC;AAAA,QACZ,SAAS,MAAMK,EAAQ,CAACM,MAAU,CAACA,CAAK;AAAA,MAAA;AAAA,IAAA;AAAA,sBAEzCC,GAAA,EAAK,QAAQR,GAAM,SAASG,GAAO,eAAeL,EAAU,SAAU,GAAIJ,IAAY,EAAE,WAAAA,MAAc,CAAA,GACpG,UAAAF,EAAM,IAAI,CAACiB,MACV,gBAAAC;AAAA,MAACC;AAAA,MAAA;AAAA,QAEC,WAAWP,EAAG,EAAE,oCAAoCK,EAAK,QAAQ;AAAA,QACjE,UAAUA,EAAK;AAAA,QACf,SAAS,MAAM;;AACb,UAAIA,EAAK,cACTG,IAAAH,EAAK,aAAL,QAAAG,EAAA,KAAAH,IACAN,EAAA;AAAA,QACF;AAAA,QAEC,UAAA;AAAA,UAAAM,EAAK,OAAO,OAAOA,EAAK,QAAS,WAAW,gBAAAJ,EAACQ,GAAA,EAAK,MAAMJ,EAAK,KAAA,CAAM,IAAKA,EAAK,OAAO;AAAA,UACpFA,EAAK;AAAA,QAAA;AAAA,MAAA;AAAA,MAVDA,EAAK;AAAA,IAAA,CAYb,EAAA,CACH;AAAA,EAAA,GACF;AAEJ;"}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import t from "react";
|
|
2
|
+
import { useSafeLayoutEffect as c } from "./useSafeLayoutEffect.js";
|
|
3
|
+
function f(e) {
|
|
4
|
+
const r = t.useRef(e);
|
|
5
|
+
return c(() => {
|
|
6
|
+
r.current = e;
|
|
7
|
+
}), t.useCallback((...u) => (0, r.current)(...u), []);
|
|
7
8
|
}
|
|
8
9
|
export {
|
|
9
|
-
|
|
10
|
+
f as useEventCallback
|
|
10
11
|
};
|
|
11
12
|
//# sourceMappingURL=useEventCallback.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useEventCallback.js","sources":["../../../src/hooks/useEventCallback.ts"],"sourcesContent":["import React from \"react\";\n\n/**\n * https://github.com/facebook/react/issues/14099#issuecomment-440013892\n */\nexport function useEventCallback<Args extends unknown[], Return>(\n fn: (...args: Args) => Return\n): (...args: Args) => Return {\n const ref = React.useRef(fn);\n\n React
|
|
1
|
+
{"version":3,"file":"useEventCallback.js","sources":["../../../src/hooks/useEventCallback.ts"],"sourcesContent":["import React from \"react\";\nimport { useSafeLayoutEffect } from \"./useSafeLayoutEffect\";\n\n/**\n * https://github.com/facebook/react/issues/14099#issuecomment-440013892\n */\nexport function useEventCallback<Args extends unknown[], Return>(\n fn: (...args: Args) => Return\n): (...args: Args) => Return {\n const ref = React.useRef(fn);\n\n // useSafeLayoutEffect falls back to useEffect on the server so this hook does\n // not emit React's \"useLayoutEffect does nothing on the server\" SSR warning.\n useSafeLayoutEffect(() => {\n ref.current = fn;\n });\n\n return React.useCallback((...args: Args) => (0, ref.current)(...args), []);\n}\n"],"names":["useEventCallback","fn","ref","React","useSafeLayoutEffect","args"],"mappings":";;AAMO,SAASA,EACdC,GAC2B;AAC3B,QAAMC,IAAMC,EAAM,OAAOF,CAAE;AAI3B,SAAAG,EAAoB,MAAM;AACxB,IAAAF,EAAI,UAAUD;AAAA,EAChB,CAAC,GAEME,EAAM,YAAY,IAAIE,UAAmBH,EAAI,SAAS,GAAGG,CAAI,GAAG,EAAE;AAC3E;"}
|
|
@@ -1,37 +1,38 @@
|
|
|
1
|
-
import { useRef as n,
|
|
2
|
-
import { Observable as
|
|
3
|
-
import { useObservable as
|
|
1
|
+
import { useRef as n, useEffect as c } from "react";
|
|
2
|
+
import { Observable as l } from "../utils/observable.js";
|
|
3
|
+
import { useObservable as d } from "./useObservable.js";
|
|
4
|
+
import { useSafeLayoutEffect as u } from "./useSafeLayoutEffect.js";
|
|
4
5
|
var i = /* @__PURE__ */ ((t) => (t.dark = "dark", t.light = "light", t))(i || {});
|
|
5
|
-
const
|
|
6
|
+
const r = "smui-theme", a = new l(
|
|
6
7
|
"light"
|
|
7
8
|
/* light */
|
|
8
|
-
),
|
|
9
|
-
const t =
|
|
10
|
-
|
|
11
|
-
const e = localStorage.getItem(
|
|
12
|
-
if (
|
|
13
|
-
if (
|
|
9
|
+
), b = () => {
|
|
10
|
+
const t = d(a), s = n(!0);
|
|
11
|
+
u(() => {
|
|
12
|
+
const e = localStorage.getItem(r);
|
|
13
|
+
if (s.current)
|
|
14
|
+
if (s.current = !1, e)
|
|
14
15
|
a.setValue(e), document.documentElement.dataset.theme = e;
|
|
15
16
|
else {
|
|
16
17
|
const o = window.matchMedia("(prefers-color-scheme: light)").matches ? "light" : "dark";
|
|
17
|
-
e !== t && a.setValue(o), localStorage.setItem(
|
|
18
|
+
e !== t && a.setValue(o), localStorage.setItem(r, o), document.documentElement.dataset.theme = o;
|
|
18
19
|
}
|
|
19
20
|
}, [t]);
|
|
20
21
|
const m = function(e) {
|
|
21
22
|
if (e.storageArea === localStorage) {
|
|
22
|
-
const o = localStorage.getItem(
|
|
23
|
+
const o = localStorage.getItem(r);
|
|
23
24
|
document.documentElement.dataset.theme = o, a.setValue(o);
|
|
24
25
|
}
|
|
25
26
|
};
|
|
26
|
-
return
|
|
27
|
+
return c(() => (window.addEventListener("storage", m), () => window.removeEventListener("storage", m)), []), {
|
|
27
28
|
theme: t,
|
|
28
29
|
setTheme: (e) => {
|
|
29
|
-
localStorage.setItem(
|
|
30
|
+
localStorage.setItem(r, e), a.setValue.bind(a)(e), document.documentElement.dataset.theme = e;
|
|
30
31
|
}
|
|
31
32
|
};
|
|
32
33
|
};
|
|
33
34
|
export {
|
|
34
35
|
i as Theme,
|
|
35
|
-
|
|
36
|
+
b as default
|
|
36
37
|
};
|
|
37
38
|
//# sourceMappingURL=useTheme.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useTheme.js","sources":["../../../src/hooks/useTheme.ts"],"sourcesContent":["import { useEffect,
|
|
1
|
+
{"version":3,"file":"useTheme.js","sources":["../../../src/hooks/useTheme.ts"],"sourcesContent":["import { useEffect, useRef } from \"react\";\nimport { Observable } from \"../utils/observable\";\nimport { useObservable } from \"./useObservable\";\nimport { useSafeLayoutEffect } from \"./useSafeLayoutEffect\";\n\nexport enum Theme {\n dark = \"dark\",\n light = \"light\",\n}\n\nconst themeStorageKey = \"smui-theme\";\n\nconst themeObservable = new Observable<Theme>(Theme.light);\n\nconst useTheme = () => {\n const theme = useObservable(themeObservable);\n // Начальная инициализация\n const firstUpdate = useRef(true);\n useSafeLayoutEffect(() => {\n const savedTheme = localStorage.getItem(themeStorageKey) as Theme;\n if (firstUpdate.current) {\n firstUpdate.current = false;\n if (savedTheme) {\n themeObservable.setValue(savedTheme);\n document.documentElement.dataset.theme = savedTheme;\n } else {\n const defaultTheme: Theme = window.matchMedia(\"(prefers-color-scheme: light)\").matches\n ? Theme.light\n : Theme.dark;\n if (savedTheme !== theme) {\n themeObservable.setValue(defaultTheme);\n }\n localStorage.setItem(themeStorageKey, defaultTheme);\n document.documentElement.dataset.theme = defaultTheme;\n }\n }\n }, [theme]);\n\n const themeListener = function (event: StorageEvent) {\n if (event.storageArea === localStorage) {\n const savedTheme = localStorage.getItem(themeStorageKey) as Theme;\n document.documentElement.dataset.theme = savedTheme;\n themeObservable.setValue(savedTheme);\n }\n };\n\n useEffect(() => {\n window.addEventListener(\"storage\", themeListener);\n return () => window.removeEventListener(\"storage\", themeListener);\n }, []);\n\n return {\n theme,\n setTheme: (value: Theme) => {\n localStorage.setItem(themeStorageKey, value);\n themeObservable.setValue.bind(themeObservable)(value);\n document.documentElement.dataset.theme = value;\n },\n };\n};\n\nexport default useTheme;\n"],"names":["Theme","themeStorageKey","themeObservable","Observable","useTheme","theme","useObservable","firstUpdate","useRef","useSafeLayoutEffect","savedTheme","defaultTheme","themeListener","event","useEffect","value"],"mappings":";;;;AAKO,IAAKA,sBAAAA,OACVA,EAAA,OAAO,QACPA,EAAA,QAAQ,SAFEA,IAAAA,KAAA,CAAA,CAAA;AAKZ,MAAMC,IAAkB,cAElBC,IAAkB,IAAIC;AAAA,EAAkB;AAAA;AAAA,GAExCC,IAAW,MAAM;AACrB,QAAMC,IAAQC,EAAcJ,CAAe,GAErCK,IAAcC,EAAO,EAAI;AAC/B,EAAAC,EAAoB,MAAM;AACxB,UAAMC,IAAa,aAAa,QAAQT,CAAe;AACvD,QAAIM,EAAY;AAEd,UADAA,EAAY,UAAU,IAClBG;AACF,QAAAR,EAAgB,SAASQ,CAAU,GACnC,SAAS,gBAAgB,QAAQ,QAAQA;AAAA,WACpC;AACL,cAAMC,IAAsB,OAAO,WAAW,+BAA+B,EAAE,UAC3E,UACA;AACJ,QAAID,MAAeL,KACjBH,EAAgB,SAASS,CAAY,GAEvC,aAAa,QAAQV,GAAiBU,CAAY,GAClD,SAAS,gBAAgB,QAAQ,QAAQA;AAAA,MAC3C;AAAA,EAEJ,GAAG,CAACN,CAAK,CAAC;AAEV,QAAMO,IAAgB,SAAUC,GAAqB;AACnD,QAAIA,EAAM,gBAAgB,cAAc;AACtC,YAAMH,IAAa,aAAa,QAAQT,CAAe;AACvD,eAAS,gBAAgB,QAAQ,QAAQS,GACzCR,EAAgB,SAASQ,CAAU;AAAA,IACrC;AAAA,EACF;AAEA,SAAAI,EAAU,OACR,OAAO,iBAAiB,WAAWF,CAAa,GACzC,MAAM,OAAO,oBAAoB,WAAWA,CAAa,IAC/D,CAAA,CAAE,GAEE;AAAA,IACL,OAAAP;AAAA,IACA,UAAU,CAACU,MAAiB;AAC1B,mBAAa,QAAQd,GAAiBc,CAAK,GAC3Cb,EAAgB,SAAS,KAAKA,CAAe,EAAEa,CAAK,GACpD,SAAS,gBAAgB,QAAQ,QAAQA;AAAA,IAC3C;AAAA,EAAA;AAEJ;"}
|