@j2-health/design-system 0.6.1 → 0.6.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/dist/index.cjs +7 -0
  2. package/dist/index.d.ts +3 -0
  3. package/dist/index.js +4 -1
  4. package/dist/index2.js +4 -1
  5. package/dist/src/components/bareButton/BareButton.cjs +31 -0
  6. package/dist/src/components/bareButton/BareButton.cjs.map +1 -0
  7. package/dist/src/components/bareButton/BareButton.d.ts +16 -0
  8. package/dist/src/components/bareButton/BareButton.js +29 -0
  9. package/dist/src/components/bareButton/BareButton.js.map +1 -0
  10. package/dist/src/components/bareButton/index.d.ts +1 -0
  11. package/dist/src/components/changeChip/ChangeChip.cjs +36 -30
  12. package/dist/src/components/changeChip/ChangeChip.cjs.map +1 -1
  13. package/dist/src/components/changeChip/ChangeChip.d.ts +22 -5
  14. package/dist/src/components/changeChip/ChangeChip.js +37 -31
  15. package/dist/src/components/changeChip/ChangeChip.js.map +1 -1
  16. package/dist/src/components/input/AntdInput.d.ts +10 -10
  17. package/dist/src/components/input/AntdSearchInput.d.ts +10 -10
  18. package/dist/src/components/stepDrawer/StepDrawer.cjs +89 -0
  19. package/dist/src/components/stepDrawer/StepDrawer.cjs.map +1 -0
  20. package/dist/src/components/stepDrawer/StepDrawer.d.ts +65 -0
  21. package/dist/src/components/stepDrawer/StepDrawer.js +88 -0
  22. package/dist/src/components/stepDrawer/StepDrawer.js.map +1 -0
  23. package/dist/src/components/stepDrawer/index.d.ts +1 -0
  24. package/dist/src/components/steps/Steps.cjs +4 -3
  25. package/dist/src/components/steps/Steps.cjs.map +1 -1
  26. package/dist/src/components/steps/Steps.d.ts +1 -1
  27. package/dist/src/components/steps/Steps.js +4 -3
  28. package/dist/src/components/steps/Steps.js.map +1 -1
  29. package/dist/src/components/steps/useSteps.cjs +2 -2
  30. package/dist/src/components/steps/useSteps.cjs.map +1 -1
  31. package/dist/src/components/steps/useSteps.js +2 -2
  32. package/dist/src/components/steps/useSteps.js.map +1 -1
  33. package/dist/src/components/swatch/Swatch.cjs +12 -6
  34. package/dist/src/components/swatch/Swatch.cjs.map +1 -1
  35. package/dist/src/components/swatch/Swatch.d.ts +10 -3
  36. package/dist/src/components/swatch/Swatch.js +12 -6
  37. package/dist/src/components/swatch/Swatch.js.map +1 -1
  38. package/dist/src/components/swatch/index.d.ts +1 -1
  39. package/dist/src/components/swatchStrip/SwatchStrip.cjs +67 -28
  40. package/dist/src/components/swatchStrip/SwatchStrip.cjs.map +1 -1
  41. package/dist/src/components/swatchStrip/SwatchStrip.d.ts +56 -5
  42. package/dist/src/components/swatchStrip/SwatchStrip.js +67 -28
  43. package/dist/src/components/swatchStrip/SwatchStrip.js.map +1 -1
  44. package/dist/src/components/swatchStrip/index.d.ts +1 -1
  45. package/dist/src/utils/useRender.cjs +76 -0
  46. package/dist/src/utils/useRender.cjs.map +1 -0
  47. package/dist/src/utils/useRender.d.ts +29 -0
  48. package/dist/src/utils/useRender.js +73 -0
  49. package/dist/src/utils/useRender.js.map +1 -0
  50. package/package.json +18 -19
@@ -1,45 +1,84 @@
1
1
  const require_Swatch = require("../swatch/Swatch.cjs");
2
+ const require_useRender = require("../../utils/useRender.cjs");
2
3
  const require_Tooltip = require("../tooltip/Tooltip.cjs");
3
4
  let react_jsx_runtime = require("react/jsx-runtime");
4
5
  //#region src/components/swatchStrip/SwatchStrip.tsx
6
+ var Item = ({ item, group, size, render }) => require_useRender.useRender({
7
+ render,
8
+ state: {
9
+ item,
10
+ group
11
+ },
12
+ defaultTagName: "span",
13
+ props: require_useRender.mergeProps({
14
+ className: "block",
15
+ "aria-label": item.label ?? item.tooltip,
16
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_Swatch.Swatch, {
17
+ ...item.swatch,
18
+ size
19
+ })
20
+ }, render ? void 0 : { role: "img" })
21
+ });
22
+ var Overflow = ({ render, ...state }) => require_useRender.useRender({
23
+ render,
24
+ state,
25
+ defaultTagName: "span",
26
+ props: {
27
+ className: "pl-1 text-xs tabular-nums text-j2-text-secondary",
28
+ children: `+${state.count}`
29
+ }
30
+ });
5
31
  /**
6
32
  * A compact run of swatches in groups, e.g. one square per affected item,
7
33
  * grouped by kind. Groups are separated by a thin rule rather than a wider
8
34
  * gap, so a group ending in `+N` doesn't read as farther from the next.
9
35
  */
10
- var SwatchStrip = ({ groups, max = 5, size = 12 }) => {
36
+ var SwatchStrip = ({ groups, max = 5, size = 12, groupGap = 17, rowGap = 4, renderItem, renderOverflow }) => {
11
37
  const visibleGroups = groups.filter((group) => group.items.length > 0);
12
38
  if (visibleGroups.length === 0) return null;
39
+ const inset = Math.max(0, Math.min(4, Math.floor((groupGap - 1) / 2)));
13
40
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
14
- className: "inline-flex flex-wrap items-center gap-y-1",
41
+ className: "inline-flex flex-wrap items-center overflow-clip",
42
+ style: {
43
+ columnGap: groupGap,
44
+ rowGap,
45
+ padding: inset,
46
+ margin: -inset
47
+ },
15
48
  children: visibleGroups.map((group, index) => {
16
- const shown = group.items.slice(0, max);
17
- const overflow = group.items.length - shown.length;
49
+ const shown = group.items.slice(0, group.max ?? max);
50
+ const overflow = group.overflow ?? group.items.length - shown.length;
18
51
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
19
- className: "inline-flex items-center",
20
- children: [index > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
21
- "aria-hidden": true,
22
- className: "mx-2 inline-block w-px bg-[var(--j2-color-border-secondary)]",
23
- style: { height: 12 }
24
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
25
- className: "inline-flex items-center",
26
- style: { gap: 2 },
27
- children: [shown.map((item) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_Tooltip.Tooltip, {
28
- title: item.label,
29
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
30
- className: "block",
31
- "aria-label": item.label,
32
- role: "img",
33
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_Swatch.Swatch, {
34
- ...item.swatch,
35
- size
36
- })
37
- })
38
- }, item.key)), overflow > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
39
- className: "px-1 text-xs tabular-nums text-j2-text-secondary",
40
- children: ["+", overflow]
41
- })]
42
- })]
52
+ className: "relative inline-flex items-center",
53
+ style: { gap: 2 },
54
+ children: [
55
+ index > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
56
+ "aria-hidden": true,
57
+ className: "absolute top-1/2 w-px -translate-y-1/2 bg-[var(--j2-color-border-secondary)]",
58
+ style: {
59
+ height: 12,
60
+ left: -(groupGap + 1) / 2
61
+ }
62
+ }),
63
+ shown.map((item) => {
64
+ const swatch = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Item, {
65
+ item,
66
+ group,
67
+ size,
68
+ render: renderItem
69
+ }, item.key);
70
+ const tooltip = item.tooltip ?? item.label;
71
+ return tooltip === false ? swatch : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_Tooltip.Tooltip, {
72
+ title: tooltip,
73
+ children: swatch
74
+ }, item.key);
75
+ }),
76
+ overflow > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Overflow, {
77
+ group,
78
+ count: overflow,
79
+ render: renderOverflow
80
+ })
81
+ ]
43
82
  }, group.key);
44
83
  })
45
84
  });
@@ -1 +1 @@
1
- {"version":3,"file":"SwatchStrip.cjs","names":["Tooltip","Swatch"],"sources":["../../../../src/components/swatchStrip/SwatchStrip.tsx"],"sourcesContent":["import { Tooltip } from '../tooltip'\nimport { Swatch, type SwatchProps } from '../swatch'\n\nexport type SwatchStripItem = {\n key: string\n /** Shown in a tooltip and read by assistive tech. */\n label: string\n swatch: Omit<SwatchProps, 'size'>\n}\n\nexport type SwatchStripGroup = {\n key: string\n items: SwatchStripItem[]\n}\n\nexport type SwatchStripProps = {\n /** Groups in display order; empty groups are skipped. */\n groups: SwatchStripGroup[]\n /** Swatches shown per group before a `+N` takes over. */\n max?: number\n /** Swatch side in px. */\n size?: number\n}\n\n/**\n * A compact run of swatches in groups, e.g. one square per affected item,\n * grouped by kind. Groups are separated by a thin rule rather than a wider\n * gap, so a group ending in `+N` doesn't read as farther from the next.\n */\nexport const SwatchStrip = ({\n groups,\n max = 5,\n size = 12,\n}: SwatchStripProps) => {\n const visibleGroups = groups.filter((group) => group.items.length > 0)\n if (visibleGroups.length === 0) return null\n\n return (\n <div className=\"inline-flex flex-wrap items-center gap-y-1\">\n {visibleGroups.map((group, index) => {\n const shown = group.items.slice(0, max)\n const overflow = group.items.length - shown.length\n return (\n <span key={group.key} className=\"inline-flex items-center\">\n {index > 0 && (\n <span\n aria-hidden\n className=\"mx-2 inline-block w-px bg-[var(--j2-color-border-secondary)]\"\n style={{ height: 12 }}\n />\n )}\n <span className=\"inline-flex items-center\" style={{ gap: 2 }}>\n {shown.map((item) => (\n <Tooltip key={item.key} title={item.label}>\n <span className=\"block\" aria-label={item.label} role=\"img\">\n <Swatch {...item.swatch} size={size} />\n </span>\n </Tooltip>\n ))}\n {overflow > 0 && (\n <span className=\"px-1 text-xs tabular-nums text-j2-text-secondary\">\n +{overflow}\n </span>\n )}\n </span>\n </span>\n )\n })}\n </div>\n )\n}\n"],"mappings":";;;;;;;;;AA6BA,IAAa,eAAe,EAC1B,QACA,MAAM,GACN,OAAO,SACe;CACtB,MAAM,gBAAgB,OAAO,QAAQ,UAAU,MAAM,MAAM,SAAS,CAAC;CACrE,IAAI,cAAc,WAAW,GAAG,OAAO;CAEvC,OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;EAAK,WAAU;EACZ,UAAA,cAAc,KAAK,OAAO,UAAU;GACnC,MAAM,QAAQ,MAAM,MAAM,MAAM,GAAG,GAAG;GACtC,MAAM,WAAW,MAAM,MAAM,SAAS,MAAM;GAC5C,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,QAAD;IAAsB,WAAU;IAAhC,UAAA,CACG,QAAQ,KACP,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;KACE,eAAA;KACA,WAAU;KACV,OAAO,EAAE,QAAQ,GAAG;IACrB,CAAA,GAEH,iBAAA,GAAA,kBAAA,KAAA,CAAC,QAAD;KAAM,WAAU;KAA2B,OAAO,EAAE,KAAK,EAAE;KAA3D,UAAA,CACG,MAAM,KAAK,SACV,iBAAA,GAAA,kBAAA,IAAA,CAACA,gBAAAA,SAAD;MAAwB,OAAO,KAAK;MAClC,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;OAAM,WAAU;OAAQ,cAAY,KAAK;OAAO,MAAK;OACnD,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAACC,eAAAA,QAAD;QAAQ,GAAI,KAAK;QAAc;OAAO,CAAA;MAClC,CAAA;KACC,GAJK,KAAK,GAIV,CACV,GACA,WAAW,KACV,iBAAA,GAAA,kBAAA,KAAA,CAAC,QAAD;MAAM,WAAU;MAAhB,UAAA,CAAmE,KAC/D,QACE;KAEJ,CAAA,CAAA;IACF,CAAA,CAAA;GAtBK,GAAA,MAAM,GAsBX;EAEV,CAAC;CACE,CAAA;AAET"}
1
+ {"version":3,"file":"SwatchStrip.cjs","names":["useRender","mergeProps","Swatch","Tooltip"],"sources":["../../../../src/components/swatchStrip/SwatchStrip.tsx"],"sourcesContent":["import { Tooltip } from '../tooltip'\nimport { Swatch, type SwatchVisualProps } from '../swatch'\nimport { mergeProps, useRender, type RenderProp } from '../../utils/useRender'\n\n/**\n * Every item has an accessible name: a `label`, or failing that a string\n * `tooltip`.\n */\nexport type SwatchStripItem = {\n key: string\n swatch: Omit<SwatchVisualProps, 'size'>\n} & (\n | {\n /** Read by assistive tech, and shown on hover unless `tooltip` is set. */\n label: string\n /** Shown on hover instead of `label`; `false` shows no tooltip. */\n tooltip?: React.ReactNode | false\n }\n | {\n label?: undefined\n /** Shown on hover and read by assistive tech. */\n tooltip: string\n }\n)\n\nexport type SwatchStripGroup = {\n key: string\n items: SwatchStripItem[]\n /** Overrides the strip's `max` for this group, e.g. `Infinity` to expand it. */\n max?: number\n /**\n * The count shown as `+N` after the items, in place of how many `max`\n * hides. `+N` shows whenever it's above 0, even with nothing hidden, so a\n * group showing a subset can report how many it leaves out; `0` hides it.\n */\n overflow?: number\n}\n\nexport type SwatchStripItemState = {\n item: SwatchStripItem\n group: SwatchStripGroup\n}\n\nexport type SwatchStripOverflowState = {\n group: SwatchStripGroup\n /** The group's `overflow`, or else how many of its items are hidden. */\n count: number\n}\n\nexport type SwatchStripProps = {\n /** Groups in display order; empty groups are skipped. */\n groups: SwatchStripGroup[]\n /** Swatches shown per group before a `+N` takes over. */\n max?: number\n /** Swatch side in px. */\n size?: number\n /**\n * Space in px between two groups on a line. The divider sits in the middle\n * of it.\n */\n groupGap?: number\n /** Space in px between wrapped lines. */\n rowGap?: number\n /**\n * Replaces each swatch's element, e.g. to make it a button. The props carry\n * the label and the swatch; spread them:\n * `(props, { item }) => <BareButton {...props} onClick={…} />`.\n * The default element is `role=\"img\"`; a replacement keeps its own role.\n * Clicks are not stopped, so they reach a wrapping popover trigger unless\n * the handler calls `event.stopPropagation()`.\n */\n renderItem?: RenderProp<SwatchStripItemState>\n /**\n * Replaces the `+N` element. Same contract as `renderItem`; pass children\n * to change its text. To restyle it completely, leave out `className` when\n * spreading: `({ className, ...props }) => <span {...props} className=\"…\" />`.\n */\n renderOverflow?: RenderProp<SwatchStripOverflowState>\n}\n\nconst Item = ({\n item,\n group,\n size,\n render,\n}: SwatchStripItemState & {\n size: number\n render?: RenderProp<SwatchStripItemState>\n}) =>\n useRender({\n render,\n state: { item, group },\n defaultTagName: 'span',\n props: mergeProps(\n {\n className: 'block',\n // The type guarantees a string tooltip when there's no label.\n 'aria-label': item.label ?? (item.tooltip as string),\n children: <Swatch {...item.swatch} size={size} />,\n },\n // An image only by default: a replacement element keeps its own role.\n render ? undefined : { role: 'img' }\n ),\n })\n\nconst Overflow = ({\n render,\n ...state\n}: SwatchStripOverflowState & {\n render?: RenderProp<SwatchStripOverflowState>\n}) =>\n useRender({\n render,\n state,\n defaultTagName: 'span',\n props: {\n className: 'pl-1 text-xs tabular-nums text-j2-text-secondary',\n children: `+${state.count}`,\n },\n })\n\n/**\n * A compact run of swatches in groups, e.g. one square per affected item,\n * grouped by kind. Groups are separated by a thin rule rather than a wider\n * gap, so a group ending in `+N` doesn't read as farther from the next.\n */\nexport const SwatchStrip = ({\n groups,\n max = 5,\n size = 12,\n groupGap = 17,\n rowGap = 4,\n renderItem,\n renderOverflow,\n}: SwatchStripProps) => {\n const visibleGroups = groups.filter((group) => group.items.length > 0)\n if (visibleGroups.length === 0) return null\n\n // Each divider hangs in the gap before its group. On a group that starts a\n // wrapped line, it falls left of the root and the clip hides it. The\n // padding, cancelled by the margin, keeps the clip off the focus rings of\n // items at the edges, and stays narrow enough to hide a wrapped divider.\n const inset = Math.max(0, Math.min(4, Math.floor((groupGap - 1) / 2)))\n\n return (\n <div\n className=\"inline-flex flex-wrap items-center overflow-clip\"\n style={{ columnGap: groupGap, rowGap, padding: inset, margin: -inset }}\n >\n {visibleGroups.map((group, index) => {\n const shown = group.items.slice(0, group.max ?? max)\n const overflow = group.overflow ?? group.items.length - shown.length\n return (\n <span\n key={group.key}\n className=\"relative inline-flex items-center\"\n style={{ gap: 2 }}\n >\n {index > 0 && (\n <span\n aria-hidden\n className=\"absolute top-1/2 w-px -translate-y-1/2 bg-[var(--j2-color-border-secondary)]\"\n style={{ height: 12, left: -(groupGap + 1) / 2 }}\n />\n )}\n {shown.map((item) => {\n const swatch = (\n <Item\n key={item.key}\n item={item}\n group={group}\n size={size}\n render={renderItem}\n />\n )\n const tooltip = item.tooltip ?? item.label\n return tooltip === false ? (\n swatch\n ) : (\n <Tooltip key={item.key} title={tooltip}>\n {swatch}\n </Tooltip>\n )\n })}\n {overflow > 0 && (\n <Overflow\n group={group}\n count={overflow}\n render={renderOverflow}\n />\n )}\n </span>\n )\n })}\n </div>\n )\n}\n"],"mappings":";;;;;AAgFA,IAAM,QAAQ,EACZ,MACA,OACA,MACA,aAKAA,kBAAAA,UAAU;CACR;CACA,OAAO;EAAE;EAAM;CAAM;CACrB,gBAAgB;CAChB,OAAOC,kBAAAA,WACL;EACE,WAAW;EAEX,cAAc,KAAK,SAAU,KAAK;EAClC,UAAU,iBAAA,GAAA,kBAAA,IAAA,CAACC,eAAAA,QAAD;GAAQ,GAAI,KAAK;GAAc;EAAO,CAAA;CAClD,GAEA,SAAS,KAAA,IAAY,EAAE,MAAM,MAAM,CACrC;AACF,CAAC;AAEH,IAAM,YAAY,EAChB,QACA,GAAG,YAIHF,kBAAAA,UAAU;CACR;CACA;CACA,gBAAgB;CAChB,OAAO;EACL,WAAW;EACX,UAAU,IAAI,MAAM;CACtB;AACF,CAAC;;;;;;AAOH,IAAa,eAAe,EAC1B,QACA,MAAM,GACN,OAAO,IACP,WAAW,IACX,SAAS,GACT,YACA,qBACsB;CACtB,MAAM,gBAAgB,OAAO,QAAQ,UAAU,MAAM,MAAM,SAAS,CAAC;CACrE,IAAI,cAAc,WAAW,GAAG,OAAO;CAMvC,MAAM,QAAQ,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,KAAK,OAAO,WAAW,KAAK,CAAC,CAAC,CAAC;CAErE,OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;EACE,WAAU;EACV,OAAO;GAAE,WAAW;GAAU;GAAQ,SAAS;GAAO,QAAQ,CAAC;EAAM;EAEpE,UAAA,cAAc,KAAK,OAAO,UAAU;GACnC,MAAM,QAAQ,MAAM,MAAM,MAAM,GAAG,MAAM,OAAO,GAAG;GACnD,MAAM,WAAW,MAAM,YAAY,MAAM,MAAM,SAAS,MAAM;GAC9D,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,QAAD;IAEE,WAAU;IACV,OAAO,EAAE,KAAK,EAAE;IAHlB,UAAA;KAKG,QAAQ,KACP,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;MACE,eAAA;MACA,WAAU;MACV,OAAO;OAAE,QAAQ;OAAI,MAAM,EAAE,WAAW,KAAK;MAAE;KAChD,CAAA;KAEF,MAAM,KAAK,SAAS;MACnB,MAAM,SACJ,iBAAA,GAAA,kBAAA,IAAA,CAAC,MAAD;OAEQ;OACC;OACD;OACN,QAAQ;MACT,GALM,KAAK,GAKX;MAEH,MAAM,UAAU,KAAK,WAAW,KAAK;MACrC,OAAO,YAAY,QACjB,SAEA,iBAAA,GAAA,kBAAA,IAAA,CAACG,gBAAAA,SAAD;OAAwB,OAAO;OAC5B,UAAA;MACM,GAFK,KAAK,GAEV;KAEb,CAAC;KACA,WAAW,KACV,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;MACS;MACP,OAAO;MACP,QAAQ;KACT,CAAA;IAEC;GArCC,GAAA,MAAM,GAqCP;EAEV,CAAC;CACE,CAAA;AAET"}
@@ -1,13 +1,42 @@
1
- import { SwatchProps } from '../swatch/index.js';
1
+ import { SwatchVisualProps } from '../swatch/index.js';
2
+ import { RenderProp } from '../../utils/useRender.js';
3
+ /**
4
+ * Every item has an accessible name: a `label`, or failing that a string
5
+ * `tooltip`.
6
+ */
2
7
  export type SwatchStripItem = {
3
8
  key: string;
4
- /** Shown in a tooltip and read by assistive tech. */
9
+ swatch: Omit<SwatchVisualProps, 'size'>;
10
+ } & ({
11
+ /** Read by assistive tech, and shown on hover unless `tooltip` is set. */
5
12
  label: string;
6
- swatch: Omit<SwatchProps, 'size'>;
7
- };
13
+ /** Shown on hover instead of `label`; `false` shows no tooltip. */
14
+ tooltip?: React.ReactNode | false;
15
+ } | {
16
+ label?: undefined;
17
+ /** Shown on hover and read by assistive tech. */
18
+ tooltip: string;
19
+ });
8
20
  export type SwatchStripGroup = {
9
21
  key: string;
10
22
  items: SwatchStripItem[];
23
+ /** Overrides the strip's `max` for this group, e.g. `Infinity` to expand it. */
24
+ max?: number;
25
+ /**
26
+ * The count shown as `+N` after the items, in place of how many `max`
27
+ * hides. `+N` shows whenever it's above 0, even with nothing hidden, so a
28
+ * group showing a subset can report how many it leaves out; `0` hides it.
29
+ */
30
+ overflow?: number;
31
+ };
32
+ export type SwatchStripItemState = {
33
+ item: SwatchStripItem;
34
+ group: SwatchStripGroup;
35
+ };
36
+ export type SwatchStripOverflowState = {
37
+ group: SwatchStripGroup;
38
+ /** The group's `overflow`, or else how many of its items are hidden. */
39
+ count: number;
11
40
  };
12
41
  export type SwatchStripProps = {
13
42
  /** Groups in display order; empty groups are skipped. */
@@ -16,10 +45,32 @@ export type SwatchStripProps = {
16
45
  max?: number;
17
46
  /** Swatch side in px. */
18
47
  size?: number;
48
+ /**
49
+ * Space in px between two groups on a line. The divider sits in the middle
50
+ * of it.
51
+ */
52
+ groupGap?: number;
53
+ /** Space in px between wrapped lines. */
54
+ rowGap?: number;
55
+ /**
56
+ * Replaces each swatch's element, e.g. to make it a button. The props carry
57
+ * the label and the swatch; spread them:
58
+ * `(props, { item }) => <BareButton {...props} onClick={…} />`.
59
+ * The default element is `role="img"`; a replacement keeps its own role.
60
+ * Clicks are not stopped, so they reach a wrapping popover trigger unless
61
+ * the handler calls `event.stopPropagation()`.
62
+ */
63
+ renderItem?: RenderProp<SwatchStripItemState>;
64
+ /**
65
+ * Replaces the `+N` element. Same contract as `renderItem`; pass children
66
+ * to change its text. To restyle it completely, leave out `className` when
67
+ * spreading: `({ className, ...props }) => <span {...props} className="…" />`.
68
+ */
69
+ renderOverflow?: RenderProp<SwatchStripOverflowState>;
19
70
  };
20
71
  /**
21
72
  * A compact run of swatches in groups, e.g. one square per affected item,
22
73
  * grouped by kind. Groups are separated by a thin rule rather than a wider
23
74
  * gap, so a group ending in `+N` doesn't read as farther from the next.
24
75
  */
25
- export declare const SwatchStrip: ({ groups, max, size, }: SwatchStripProps) => import('react').JSX.Element | null;
76
+ export declare const SwatchStrip: ({ groups, max, size, groupGap, rowGap, renderItem, renderOverflow, }: SwatchStripProps) => import('react').JSX.Element | null;
@@ -1,45 +1,84 @@
1
1
  import { Swatch } from "../swatch/Swatch.js";
2
+ import { mergeProps, useRender } from "../../utils/useRender.js";
2
3
  import { Tooltip } from "../tooltip/Tooltip.js";
3
4
  import { jsx, jsxs } from "react/jsx-runtime";
4
5
  //#region src/components/swatchStrip/SwatchStrip.tsx
6
+ var Item = ({ item, group, size, render }) => useRender({
7
+ render,
8
+ state: {
9
+ item,
10
+ group
11
+ },
12
+ defaultTagName: "span",
13
+ props: mergeProps({
14
+ className: "block",
15
+ "aria-label": item.label ?? item.tooltip,
16
+ children: /* @__PURE__ */ jsx(Swatch, {
17
+ ...item.swatch,
18
+ size
19
+ })
20
+ }, render ? void 0 : { role: "img" })
21
+ });
22
+ var Overflow = ({ render, ...state }) => useRender({
23
+ render,
24
+ state,
25
+ defaultTagName: "span",
26
+ props: {
27
+ className: "pl-1 text-xs tabular-nums text-j2-text-secondary",
28
+ children: `+${state.count}`
29
+ }
30
+ });
5
31
  /**
6
32
  * A compact run of swatches in groups, e.g. one square per affected item,
7
33
  * grouped by kind. Groups are separated by a thin rule rather than a wider
8
34
  * gap, so a group ending in `+N` doesn't read as farther from the next.
9
35
  */
10
- var SwatchStrip = ({ groups, max = 5, size = 12 }) => {
36
+ var SwatchStrip = ({ groups, max = 5, size = 12, groupGap = 17, rowGap = 4, renderItem, renderOverflow }) => {
11
37
  const visibleGroups = groups.filter((group) => group.items.length > 0);
12
38
  if (visibleGroups.length === 0) return null;
39
+ const inset = Math.max(0, Math.min(4, Math.floor((groupGap - 1) / 2)));
13
40
  return /* @__PURE__ */ jsx("div", {
14
- className: "inline-flex flex-wrap items-center gap-y-1",
41
+ className: "inline-flex flex-wrap items-center overflow-clip",
42
+ style: {
43
+ columnGap: groupGap,
44
+ rowGap,
45
+ padding: inset,
46
+ margin: -inset
47
+ },
15
48
  children: visibleGroups.map((group, index) => {
16
- const shown = group.items.slice(0, max);
17
- const overflow = group.items.length - shown.length;
49
+ const shown = group.items.slice(0, group.max ?? max);
50
+ const overflow = group.overflow ?? group.items.length - shown.length;
18
51
  return /* @__PURE__ */ jsxs("span", {
19
- className: "inline-flex items-center",
20
- children: [index > 0 && /* @__PURE__ */ jsx("span", {
21
- "aria-hidden": true,
22
- className: "mx-2 inline-block w-px bg-[var(--j2-color-border-secondary)]",
23
- style: { height: 12 }
24
- }), /* @__PURE__ */ jsxs("span", {
25
- className: "inline-flex items-center",
26
- style: { gap: 2 },
27
- children: [shown.map((item) => /* @__PURE__ */ jsx(Tooltip, {
28
- title: item.label,
29
- children: /* @__PURE__ */ jsx("span", {
30
- className: "block",
31
- "aria-label": item.label,
32
- role: "img",
33
- children: /* @__PURE__ */ jsx(Swatch, {
34
- ...item.swatch,
35
- size
36
- })
37
- })
38
- }, item.key)), overflow > 0 && /* @__PURE__ */ jsxs("span", {
39
- className: "px-1 text-xs tabular-nums text-j2-text-secondary",
40
- children: ["+", overflow]
41
- })]
42
- })]
52
+ className: "relative inline-flex items-center",
53
+ style: { gap: 2 },
54
+ children: [
55
+ index > 0 && /* @__PURE__ */ jsx("span", {
56
+ "aria-hidden": true,
57
+ className: "absolute top-1/2 w-px -translate-y-1/2 bg-[var(--j2-color-border-secondary)]",
58
+ style: {
59
+ height: 12,
60
+ left: -(groupGap + 1) / 2
61
+ }
62
+ }),
63
+ shown.map((item) => {
64
+ const swatch = /* @__PURE__ */ jsx(Item, {
65
+ item,
66
+ group,
67
+ size,
68
+ render: renderItem
69
+ }, item.key);
70
+ const tooltip = item.tooltip ?? item.label;
71
+ return tooltip === false ? swatch : /* @__PURE__ */ jsx(Tooltip, {
72
+ title: tooltip,
73
+ children: swatch
74
+ }, item.key);
75
+ }),
76
+ overflow > 0 && /* @__PURE__ */ jsx(Overflow, {
77
+ group,
78
+ count: overflow,
79
+ render: renderOverflow
80
+ })
81
+ ]
43
82
  }, group.key);
44
83
  })
45
84
  });
@@ -1 +1 @@
1
- {"version":3,"file":"SwatchStrip.js","names":[],"sources":["../../../../src/components/swatchStrip/SwatchStrip.tsx"],"sourcesContent":["import { Tooltip } from '../tooltip'\nimport { Swatch, type SwatchProps } from '../swatch'\n\nexport type SwatchStripItem = {\n key: string\n /** Shown in a tooltip and read by assistive tech. */\n label: string\n swatch: Omit<SwatchProps, 'size'>\n}\n\nexport type SwatchStripGroup = {\n key: string\n items: SwatchStripItem[]\n}\n\nexport type SwatchStripProps = {\n /** Groups in display order; empty groups are skipped. */\n groups: SwatchStripGroup[]\n /** Swatches shown per group before a `+N` takes over. */\n max?: number\n /** Swatch side in px. */\n size?: number\n}\n\n/**\n * A compact run of swatches in groups, e.g. one square per affected item,\n * grouped by kind. Groups are separated by a thin rule rather than a wider\n * gap, so a group ending in `+N` doesn't read as farther from the next.\n */\nexport const SwatchStrip = ({\n groups,\n max = 5,\n size = 12,\n}: SwatchStripProps) => {\n const visibleGroups = groups.filter((group) => group.items.length > 0)\n if (visibleGroups.length === 0) return null\n\n return (\n <div className=\"inline-flex flex-wrap items-center gap-y-1\">\n {visibleGroups.map((group, index) => {\n const shown = group.items.slice(0, max)\n const overflow = group.items.length - shown.length\n return (\n <span key={group.key} className=\"inline-flex items-center\">\n {index > 0 && (\n <span\n aria-hidden\n className=\"mx-2 inline-block w-px bg-[var(--j2-color-border-secondary)]\"\n style={{ height: 12 }}\n />\n )}\n <span className=\"inline-flex items-center\" style={{ gap: 2 }}>\n {shown.map((item) => (\n <Tooltip key={item.key} title={item.label}>\n <span className=\"block\" aria-label={item.label} role=\"img\">\n <Swatch {...item.swatch} size={size} />\n </span>\n </Tooltip>\n ))}\n {overflow > 0 && (\n <span className=\"px-1 text-xs tabular-nums text-j2-text-secondary\">\n +{overflow}\n </span>\n )}\n </span>\n </span>\n )\n })}\n </div>\n )\n}\n"],"mappings":";;;;;;;;;AA6BA,IAAa,eAAe,EAC1B,QACA,MAAM,GACN,OAAO,SACe;CACtB,MAAM,gBAAgB,OAAO,QAAQ,UAAU,MAAM,MAAM,SAAS,CAAC;CACrE,IAAI,cAAc,WAAW,GAAG,OAAO;CAEvC,OACE,oBAAC,OAAD;EAAK,WAAU;EACZ,UAAA,cAAc,KAAK,OAAO,UAAU;GACnC,MAAM,QAAQ,MAAM,MAAM,MAAM,GAAG,GAAG;GACtC,MAAM,WAAW,MAAM,MAAM,SAAS,MAAM;GAC5C,OACE,qBAAC,QAAD;IAAsB,WAAU;IAAhC,UAAA,CACG,QAAQ,KACP,oBAAC,QAAD;KACE,eAAA;KACA,WAAU;KACV,OAAO,EAAE,QAAQ,GAAG;IACrB,CAAA,GAEH,qBAAC,QAAD;KAAM,WAAU;KAA2B,OAAO,EAAE,KAAK,EAAE;KAA3D,UAAA,CACG,MAAM,KAAK,SACV,oBAAC,SAAD;MAAwB,OAAO,KAAK;MAClC,UAAA,oBAAC,QAAD;OAAM,WAAU;OAAQ,cAAY,KAAK;OAAO,MAAK;OACnD,UAAA,oBAAC,QAAD;QAAQ,GAAI,KAAK;QAAc;OAAO,CAAA;MAClC,CAAA;KACC,GAJK,KAAK,GAIV,CACV,GACA,WAAW,KACV,qBAAC,QAAD;MAAM,WAAU;MAAhB,UAAA,CAAmE,KAC/D,QACE;KAEJ,CAAA,CAAA;IACF,CAAA,CAAA;GAtBK,GAAA,MAAM,GAsBX;EAEV,CAAC;CACE,CAAA;AAET"}
1
+ {"version":3,"file":"SwatchStrip.js","names":[],"sources":["../../../../src/components/swatchStrip/SwatchStrip.tsx"],"sourcesContent":["import { Tooltip } from '../tooltip'\nimport { Swatch, type SwatchVisualProps } from '../swatch'\nimport { mergeProps, useRender, type RenderProp } from '../../utils/useRender'\n\n/**\n * Every item has an accessible name: a `label`, or failing that a string\n * `tooltip`.\n */\nexport type SwatchStripItem = {\n key: string\n swatch: Omit<SwatchVisualProps, 'size'>\n} & (\n | {\n /** Read by assistive tech, and shown on hover unless `tooltip` is set. */\n label: string\n /** Shown on hover instead of `label`; `false` shows no tooltip. */\n tooltip?: React.ReactNode | false\n }\n | {\n label?: undefined\n /** Shown on hover and read by assistive tech. */\n tooltip: string\n }\n)\n\nexport type SwatchStripGroup = {\n key: string\n items: SwatchStripItem[]\n /** Overrides the strip's `max` for this group, e.g. `Infinity` to expand it. */\n max?: number\n /**\n * The count shown as `+N` after the items, in place of how many `max`\n * hides. `+N` shows whenever it's above 0, even with nothing hidden, so a\n * group showing a subset can report how many it leaves out; `0` hides it.\n */\n overflow?: number\n}\n\nexport type SwatchStripItemState = {\n item: SwatchStripItem\n group: SwatchStripGroup\n}\n\nexport type SwatchStripOverflowState = {\n group: SwatchStripGroup\n /** The group's `overflow`, or else how many of its items are hidden. */\n count: number\n}\n\nexport type SwatchStripProps = {\n /** Groups in display order; empty groups are skipped. */\n groups: SwatchStripGroup[]\n /** Swatches shown per group before a `+N` takes over. */\n max?: number\n /** Swatch side in px. */\n size?: number\n /**\n * Space in px between two groups on a line. The divider sits in the middle\n * of it.\n */\n groupGap?: number\n /** Space in px between wrapped lines. */\n rowGap?: number\n /**\n * Replaces each swatch's element, e.g. to make it a button. The props carry\n * the label and the swatch; spread them:\n * `(props, { item }) => <BareButton {...props} onClick={…} />`.\n * The default element is `role=\"img\"`; a replacement keeps its own role.\n * Clicks are not stopped, so they reach a wrapping popover trigger unless\n * the handler calls `event.stopPropagation()`.\n */\n renderItem?: RenderProp<SwatchStripItemState>\n /**\n * Replaces the `+N` element. Same contract as `renderItem`; pass children\n * to change its text. To restyle it completely, leave out `className` when\n * spreading: `({ className, ...props }) => <span {...props} className=\"…\" />`.\n */\n renderOverflow?: RenderProp<SwatchStripOverflowState>\n}\n\nconst Item = ({\n item,\n group,\n size,\n render,\n}: SwatchStripItemState & {\n size: number\n render?: RenderProp<SwatchStripItemState>\n}) =>\n useRender({\n render,\n state: { item, group },\n defaultTagName: 'span',\n props: mergeProps(\n {\n className: 'block',\n // The type guarantees a string tooltip when there's no label.\n 'aria-label': item.label ?? (item.tooltip as string),\n children: <Swatch {...item.swatch} size={size} />,\n },\n // An image only by default: a replacement element keeps its own role.\n render ? undefined : { role: 'img' }\n ),\n })\n\nconst Overflow = ({\n render,\n ...state\n}: SwatchStripOverflowState & {\n render?: RenderProp<SwatchStripOverflowState>\n}) =>\n useRender({\n render,\n state,\n defaultTagName: 'span',\n props: {\n className: 'pl-1 text-xs tabular-nums text-j2-text-secondary',\n children: `+${state.count}`,\n },\n })\n\n/**\n * A compact run of swatches in groups, e.g. one square per affected item,\n * grouped by kind. Groups are separated by a thin rule rather than a wider\n * gap, so a group ending in `+N` doesn't read as farther from the next.\n */\nexport const SwatchStrip = ({\n groups,\n max = 5,\n size = 12,\n groupGap = 17,\n rowGap = 4,\n renderItem,\n renderOverflow,\n}: SwatchStripProps) => {\n const visibleGroups = groups.filter((group) => group.items.length > 0)\n if (visibleGroups.length === 0) return null\n\n // Each divider hangs in the gap before its group. On a group that starts a\n // wrapped line, it falls left of the root and the clip hides it. The\n // padding, cancelled by the margin, keeps the clip off the focus rings of\n // items at the edges, and stays narrow enough to hide a wrapped divider.\n const inset = Math.max(0, Math.min(4, Math.floor((groupGap - 1) / 2)))\n\n return (\n <div\n className=\"inline-flex flex-wrap items-center overflow-clip\"\n style={{ columnGap: groupGap, rowGap, padding: inset, margin: -inset }}\n >\n {visibleGroups.map((group, index) => {\n const shown = group.items.slice(0, group.max ?? max)\n const overflow = group.overflow ?? group.items.length - shown.length\n return (\n <span\n key={group.key}\n className=\"relative inline-flex items-center\"\n style={{ gap: 2 }}\n >\n {index > 0 && (\n <span\n aria-hidden\n className=\"absolute top-1/2 w-px -translate-y-1/2 bg-[var(--j2-color-border-secondary)]\"\n style={{ height: 12, left: -(groupGap + 1) / 2 }}\n />\n )}\n {shown.map((item) => {\n const swatch = (\n <Item\n key={item.key}\n item={item}\n group={group}\n size={size}\n render={renderItem}\n />\n )\n const tooltip = item.tooltip ?? item.label\n return tooltip === false ? (\n swatch\n ) : (\n <Tooltip key={item.key} title={tooltip}>\n {swatch}\n </Tooltip>\n )\n })}\n {overflow > 0 && (\n <Overflow\n group={group}\n count={overflow}\n render={renderOverflow}\n />\n )}\n </span>\n )\n })}\n </div>\n )\n}\n"],"mappings":";;;;;AAgFA,IAAM,QAAQ,EACZ,MACA,OACA,MACA,aAKA,UAAU;CACR;CACA,OAAO;EAAE;EAAM;CAAM;CACrB,gBAAgB;CAChB,OAAO,WACL;EACE,WAAW;EAEX,cAAc,KAAK,SAAU,KAAK;EAClC,UAAU,oBAAC,QAAD;GAAQ,GAAI,KAAK;GAAc;EAAO,CAAA;CAClD,GAEA,SAAS,KAAA,IAAY,EAAE,MAAM,MAAM,CACrC;AACF,CAAC;AAEH,IAAM,YAAY,EAChB,QACA,GAAG,YAIH,UAAU;CACR;CACA;CACA,gBAAgB;CAChB,OAAO;EACL,WAAW;EACX,UAAU,IAAI,MAAM;CACtB;AACF,CAAC;;;;;;AAOH,IAAa,eAAe,EAC1B,QACA,MAAM,GACN,OAAO,IACP,WAAW,IACX,SAAS,GACT,YACA,qBACsB;CACtB,MAAM,gBAAgB,OAAO,QAAQ,UAAU,MAAM,MAAM,SAAS,CAAC;CACrE,IAAI,cAAc,WAAW,GAAG,OAAO;CAMvC,MAAM,QAAQ,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,KAAK,OAAO,WAAW,KAAK,CAAC,CAAC,CAAC;CAErE,OACE,oBAAC,OAAD;EACE,WAAU;EACV,OAAO;GAAE,WAAW;GAAU;GAAQ,SAAS;GAAO,QAAQ,CAAC;EAAM;EAEpE,UAAA,cAAc,KAAK,OAAO,UAAU;GACnC,MAAM,QAAQ,MAAM,MAAM,MAAM,GAAG,MAAM,OAAO,GAAG;GACnD,MAAM,WAAW,MAAM,YAAY,MAAM,MAAM,SAAS,MAAM;GAC9D,OACE,qBAAC,QAAD;IAEE,WAAU;IACV,OAAO,EAAE,KAAK,EAAE;IAHlB,UAAA;KAKG,QAAQ,KACP,oBAAC,QAAD;MACE,eAAA;MACA,WAAU;MACV,OAAO;OAAE,QAAQ;OAAI,MAAM,EAAE,WAAW,KAAK;MAAE;KAChD,CAAA;KAEF,MAAM,KAAK,SAAS;MACnB,MAAM,SACJ,oBAAC,MAAD;OAEQ;OACC;OACD;OACN,QAAQ;MACT,GALM,KAAK,GAKX;MAEH,MAAM,UAAU,KAAK,WAAW,KAAK;MACrC,OAAO,YAAY,QACjB,SAEA,oBAAC,SAAD;OAAwB,OAAO;OAC5B,UAAA;MACM,GAFK,KAAK,GAEV;KAEb,CAAC;KACA,WAAW,KACV,oBAAC,UAAD;MACS;MACP,OAAO;MACP,QAAQ;KACT,CAAA;IAEC;GArCC,GAAA,MAAM,GAqCP;EAEV,CAAC;CACE,CAAA;AAET"}
@@ -1 +1 @@
1
- export { SwatchStrip, type SwatchStripGroup, type SwatchStripItem, type SwatchStripProps, } from './SwatchStrip.js';
1
+ export { SwatchStrip, type SwatchStripGroup, type SwatchStripItem, type SwatchStripItemState, type SwatchStripOverflowState, type SwatchStripProps, } from './SwatchStrip.js';
@@ -0,0 +1,76 @@
1
+ const require_runtime = require("../../_virtual/_rolldown/runtime.cjs");
2
+ let react = require("react");
3
+ let classnames = require("classnames");
4
+ classnames = require_runtime.__toESM(classnames, 1);
5
+ //#region src/utils/useRender.ts
6
+ /** Sets one ref. Returns a callback ref's cleanup, if it gave one. */
7
+ var setRef = (ref, value) => {
8
+ if (typeof ref === "function") return ref(value);
9
+ if (ref) ref.current = value;
10
+ };
11
+ /**
12
+ * One callback ref that feeds every ref given to it. When a callback ref
13
+ * returns a cleanup (React 19), detaching runs it instead of passing null.
14
+ */
15
+ var composeRefs = (...refs) => (value) => {
16
+ const cleanups = refs.map((ref) => setRef(ref, value));
17
+ if (!cleanups.some((cleanup) => typeof cleanup === "function")) return;
18
+ return () => cleanups.forEach((cleanup, index) => typeof cleanup === "function" ? cleanup() : setRef(refs[index], null));
19
+ };
20
+ /** `composeRefs`, kept stable while the refs are. */
21
+ var useMergedRefs = (...refs) => (0, react.useCallback)((value) => composeRefs(...refs)(value), refs);
22
+ /**
23
+ * Merges prop objects left to right. Later props win, except that event
24
+ * handlers all run (last first), classNames join, styles combine and refs
25
+ * all receive the element. An `undefined` handler or ref leaves an earlier
26
+ * one in place. The merged ref is a new function on every call, so React
27
+ * reattaches it on each render, as with any inline callback ref.
28
+ */
29
+ var mergeProps = (...sources) => {
30
+ const merged = {};
31
+ for (const source of sources) {
32
+ if (!source) continue;
33
+ for (const [key, value] of Object.entries(source)) {
34
+ const existing = merged[key];
35
+ if ((key === "ref" || /^on[A-Z]/.test(key)) && value === void 0) continue;
36
+ else if (key === "ref" && existing) merged.ref = composeRefs(existing, value);
37
+ else if (/^on[A-Z]/.test(key) && typeof existing === "function" && typeof value === "function") merged[key] = (...args) => {
38
+ value(...args);
39
+ existing(...args);
40
+ };
41
+ else if (key === "className") merged.className = (0, classnames.default)(existing, value);
42
+ else if (key === "style") merged.style = {
43
+ ...existing,
44
+ ...value
45
+ };
46
+ else merged[key] = value;
47
+ }
48
+ }
49
+ return merged;
50
+ };
51
+ var isReact19 = Number(react.version.split(".")[0]) >= 19;
52
+ /**
53
+ * The ref an element was created with: a prop in React 19, a field in 18.
54
+ * Reading the field in 19 logs a deprecation warning, so branch on version.
55
+ */
56
+ var elementRef = (element) => isReact19 ? element.props.ref : element.ref;
57
+ var useRender = ({ render, props, ref, state, defaultTagName = "div" }) => {
58
+ const element = (0, react.isValidElement)(render) ? render : void 0;
59
+ const mergedRef = useMergedRefs(ref, element && elementRef(element));
60
+ const rendered = typeof render === "function" ? render({
61
+ ...props,
62
+ ref: mergedRef
63
+ }, state) : element ? (0, react.cloneElement)(element, {
64
+ ...mergeProps(props, element.props),
65
+ ref: mergedRef
66
+ }) : (0, react.createElement)(defaultTagName, {
67
+ ...props,
68
+ ref: mergedRef
69
+ });
70
+ return rendered.type === "button" && rendered.props.type === void 0 ? (0, react.cloneElement)(rendered, { type: "button" }) : rendered;
71
+ };
72
+ //#endregion
73
+ exports.mergeProps = mergeProps;
74
+ exports.useRender = useRender;
75
+
76
+ //# sourceMappingURL=useRender.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useRender.cjs","names":["useCallback","cx","version","isValidElement","cloneElement","createElement"],"sources":["../../../src/utils/useRender.ts"],"sourcesContent":["// A port of Base UI's `render` prop: its `useRender` hook and `mergeProps`\n// utility (https://base-ui.com/react/utils/use-render), adapted without the\n// dependency and cut down to what this library uses. Base UI also maps state\n// to data-* attributes and takes arrays of refs; neither is needed here.\n//\n// A component keeps its own element and props, and lets the app swap the\n// element: pass an element to merge onto, or a function that receives the\n// props (and the component's state) and returns the element. Unlike Base UI,\n// a <button> that ends up with no `type` gets `type=\"button\"`, so swapping\n// an element in never makes a form submit button by accident.\n//\n// Base UI is distributed under the MIT License:\n//\n// Copyright (c) 2019 Material-UI SAS\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to\n// deal in the Software without restriction, including without limitation the\n// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n// sell copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n// IN THE SOFTWARE.\nimport {\n cloneElement,\n createElement,\n isValidElement,\n useCallback,\n version,\n type HTMLAttributes,\n type JSX,\n type ReactElement,\n type Ref,\n type RefCallback,\n} from 'react'\nimport cx from 'classnames'\n\nexport type RenderProps = HTMLAttributes<HTMLElement> & {\n [key: string]: unknown\n}\n\n/**\n * Replaces a component's element. Pass an element to merge the component's\n * props onto, e.g. `<button />`, or a function that spreads them:\n * `(props, state) => <button {...props} onClick={…} />`.\n */\nexport type RenderProp<State> =\n | ReactElement\n | ((\n props: RenderProps & { ref: RefCallback<HTMLElement> },\n state: State\n ) => ReactElement)\n\n/** Sets one ref. Returns a callback ref's cleanup, if it gave one. */\nconst setRef = <T>(ref: Ref<T> | undefined, value: T | null) => {\n if (typeof ref === 'function') return ref(value)\n if (ref) (ref as { current: T | null }).current = value\n}\n\n/**\n * One callback ref that feeds every ref given to it. When a callback ref\n * returns a cleanup (React 19), detaching runs it instead of passing null.\n */\nconst composeRefs =\n <T>(...refs: (Ref<T> | undefined)[]): RefCallback<T> =>\n (value: T | null) => {\n const cleanups = refs.map((ref) => setRef(ref, value))\n if (!cleanups.some((cleanup) => typeof cleanup === 'function')) return\n return () =>\n cleanups.forEach((cleanup, index) =>\n typeof cleanup === 'function' ? cleanup() : setRef(refs[index], null)\n )\n }\n\n/** `composeRefs`, kept stable while the refs are. */\nconst useMergedRefs = <T>(...refs: (Ref<T> | undefined)[]): RefCallback<T> =>\n useCallback((value: T | null) => composeRefs(...refs)(value), refs)\n\n/**\n * Merges prop objects left to right. Later props win, except that event\n * handlers all run (last first), classNames join, styles combine and refs\n * all receive the element. An `undefined` handler or ref leaves an earlier\n * one in place. The merged ref is a new function on every call, so React\n * reattaches it on each render, as with any inline callback ref.\n */\nexport const mergeProps = (\n ...sources: (RenderProps | undefined)[]\n): RenderProps => {\n const merged: RenderProps = {}\n for (const source of sources) {\n if (!source) continue\n for (const [key, value] of Object.entries(source)) {\n const existing = merged[key]\n if ((key === 'ref' || /^on[A-Z]/.test(key)) && value === undefined) {\n continue\n } else if (key === 'ref' && existing) {\n merged.ref = composeRefs(\n existing as Ref<unknown>,\n value as Ref<unknown>\n )\n } else if (\n /^on[A-Z]/.test(key) &&\n typeof existing === 'function' &&\n typeof value === 'function'\n ) {\n merged[key] = (...args: unknown[]) => {\n value(...args)\n existing(...args)\n }\n } else if (key === 'className') {\n merged.className = cx(existing as string, value as string)\n } else if (key === 'style') {\n merged.style = { ...(existing as object), ...(value as object) }\n } else {\n merged[key] = value\n }\n }\n }\n return merged\n}\n\nconst isReact19 = Number(version.split('.')[0]) >= 19\n\n/**\n * The ref an element was created with: a prop in React 19, a field in 18.\n * Reading the field in 19 logs a deprecation warning, so branch on version.\n */\nconst elementRef = (element: ReactElement): Ref<HTMLElement> | undefined =>\n isReact19\n ? (element.props as { ref?: Ref<HTMLElement> }).ref\n : (element as unknown as { ref?: Ref<HTMLElement> }).ref\n\nexport const useRender = <State>({\n render,\n props,\n ref,\n state,\n defaultTagName = 'div',\n}: {\n render?: RenderProp<State>\n /** The component's own props, already merged with what it was given. */\n props: RenderProps\n ref?: Ref<HTMLElement>\n /** Passed to a `render` function as its second argument. */\n state: State\n defaultTagName?: keyof JSX.IntrinsicElements\n}): ReactElement => {\n const element = isValidElement(render) ? render : undefined\n const mergedRef = useMergedRefs(ref, element && elementRef(element))\n\n const rendered =\n typeof render === 'function'\n ? render({ ...props, ref: mergedRef }, state)\n : element\n ? cloneElement(element, {\n ...mergeProps(props, element.props as RenderProps),\n ref: mergedRef,\n } as RenderProps)\n : createElement(defaultTagName, { ...props, ref: mergedRef })\n return rendered.type === 'button' &&\n (rendered.props as RenderProps).type === undefined\n ? cloneElement(rendered, { type: 'button' } as RenderProps)\n : rendered\n}\n"],"mappings":";;;;;;AA+DA,IAAM,UAAa,KAAyB,UAAoB;CAC9D,IAAI,OAAO,QAAQ,YAAY,OAAO,IAAI,KAAK;CAC/C,IAAI,KAAK,IAA+B,UAAU;AACpD;;;;;AAMA,IAAM,eACA,GAAG,UACN,UAAoB;CACnB,MAAM,WAAW,KAAK,KAAK,QAAQ,OAAO,KAAK,KAAK,CAAC;CACrD,IAAI,CAAC,SAAS,MAAM,YAAY,OAAO,YAAY,UAAU,GAAG;CAChE,aACE,SAAS,SAAS,SAAS,UACzB,OAAO,YAAY,aAAa,QAAQ,IAAI,OAAO,KAAK,QAAQ,IAAI,CACtE;AACJ;;AAGF,IAAM,iBAAoB,GAAG,UAAA,GAC3BA,MAAAA,YAAAA,EAAa,UAAoB,YAAY,GAAG,IAAI,CAAC,CAAC,KAAK,GAAG,IAAI;;;;;;;;AASpE,IAAa,cACX,GAAG,YACa;CAChB,MAAM,SAAsB,CAAC;CAC7B,KAAK,MAAM,UAAU,SAAS;EAC5B,IAAI,CAAC,QAAQ;EACb,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,MAAM,GAAG;GACjD,MAAM,WAAW,OAAO;GACxB,KAAK,QAAQ,SAAS,WAAW,KAAK,GAAG,MAAM,UAAU,KAAA,GACvD;QACK,IAAI,QAAQ,SAAS,UAC1B,OAAO,MAAM,YACX,UACA,KACF;QACK,IACL,WAAW,KAAK,GAAG,KACnB,OAAO,aAAa,cACpB,OAAO,UAAU,YAEjB,OAAO,QAAQ,GAAG,SAAoB;IACpC,MAAM,GAAG,IAAI;IACb,SAAS,GAAG,IAAI;GAClB;QACK,IAAI,QAAQ,aACjB,OAAO,aAAA,GAAYC,WAAAA,QAAAA,CAAG,UAAoB,KAAe;QACpD,IAAI,QAAQ,SACjB,OAAO,QAAQ;IAAE,GAAI;IAAqB,GAAI;GAAiB;QAE/D,OAAO,OAAO;EAElB;CACF;CACA,OAAO;AACT;AAEA,IAAM,YAAY,OAAOC,MAAAA,QAAQ,MAAM,GAAG,CAAC,CAAC,EAAE,KAAK;;;;;AAMnD,IAAM,cAAc,YAClB,YACK,QAAQ,MAAqC,MAC7C,QAAkD;AAEzD,IAAa,aAAoB,EAC/B,QACA,OACA,KACA,OACA,iBAAiB,YASC;CAClB,MAAM,WAAA,GAAUC,MAAAA,eAAAA,CAAe,MAAM,IAAI,SAAS,KAAA;CAClD,MAAM,YAAY,cAAc,KAAK,WAAW,WAAW,OAAO,CAAC;CAEnE,MAAM,WACJ,OAAO,WAAW,aACd,OAAO;EAAE,GAAG;EAAO,KAAK;CAAU,GAAG,KAAK,IAC1C,WAAA,GACEC,MAAAA,aAAAA,CAAa,SAAS;EACpB,GAAG,WAAW,OAAO,QAAQ,KAAoB;EACjD,KAAK;CACP,CAAgB,KAAA,GAChBC,MAAAA,cAAAA,CAAc,gBAAgB;EAAE,GAAG;EAAO,KAAK;CAAU,CAAC;CAClE,OAAO,SAAS,SAAS,YACtB,SAAS,MAAsB,SAAS,KAAA,KAAA,GACvCD,MAAAA,aAAAA,CAAa,UAAU,EAAE,MAAM,SAAS,CAAgB,IACxD;AACN"}
@@ -0,0 +1,29 @@
1
+ import { HTMLAttributes, JSX, ReactElement, Ref, RefCallback } from 'react';
2
+ export type RenderProps = HTMLAttributes<HTMLElement> & {
3
+ [key: string]: unknown;
4
+ };
5
+ /**
6
+ * Replaces a component's element. Pass an element to merge the component's
7
+ * props onto, e.g. `<button />`, or a function that spreads them:
8
+ * `(props, state) => <button {...props} onClick={…} />`.
9
+ */
10
+ export type RenderProp<State> = ReactElement | ((props: RenderProps & {
11
+ ref: RefCallback<HTMLElement>;
12
+ }, state: State) => ReactElement);
13
+ /**
14
+ * Merges prop objects left to right. Later props win, except that event
15
+ * handlers all run (last first), classNames join, styles combine and refs
16
+ * all receive the element. An `undefined` handler or ref leaves an earlier
17
+ * one in place. The merged ref is a new function on every call, so React
18
+ * reattaches it on each render, as with any inline callback ref.
19
+ */
20
+ export declare const mergeProps: (...sources: (RenderProps | undefined)[]) => RenderProps;
21
+ export declare const useRender: <State>({ render, props, ref, state, defaultTagName, }: {
22
+ render?: RenderProp<State>;
23
+ /** The component's own props, already merged with what it was given. */
24
+ props: RenderProps;
25
+ ref?: Ref<HTMLElement>;
26
+ /** Passed to a `render` function as its second argument. */
27
+ state: State;
28
+ defaultTagName?: keyof JSX.IntrinsicElements;
29
+ }) => ReactElement;
@@ -0,0 +1,73 @@
1
+ import { cloneElement, createElement, isValidElement, useCallback, version } from "react";
2
+ import cx from "classnames";
3
+ //#region src/utils/useRender.ts
4
+ /** Sets one ref. Returns a callback ref's cleanup, if it gave one. */
5
+ var setRef = (ref, value) => {
6
+ if (typeof ref === "function") return ref(value);
7
+ if (ref) ref.current = value;
8
+ };
9
+ /**
10
+ * One callback ref that feeds every ref given to it. When a callback ref
11
+ * returns a cleanup (React 19), detaching runs it instead of passing null.
12
+ */
13
+ var composeRefs = (...refs) => (value) => {
14
+ const cleanups = refs.map((ref) => setRef(ref, value));
15
+ if (!cleanups.some((cleanup) => typeof cleanup === "function")) return;
16
+ return () => cleanups.forEach((cleanup, index) => typeof cleanup === "function" ? cleanup() : setRef(refs[index], null));
17
+ };
18
+ /** `composeRefs`, kept stable while the refs are. */
19
+ var useMergedRefs = (...refs) => useCallback((value) => composeRefs(...refs)(value), refs);
20
+ /**
21
+ * Merges prop objects left to right. Later props win, except that event
22
+ * handlers all run (last first), classNames join, styles combine and refs
23
+ * all receive the element. An `undefined` handler or ref leaves an earlier
24
+ * one in place. The merged ref is a new function on every call, so React
25
+ * reattaches it on each render, as with any inline callback ref.
26
+ */
27
+ var mergeProps = (...sources) => {
28
+ const merged = {};
29
+ for (const source of sources) {
30
+ if (!source) continue;
31
+ for (const [key, value] of Object.entries(source)) {
32
+ const existing = merged[key];
33
+ if ((key === "ref" || /^on[A-Z]/.test(key)) && value === void 0) continue;
34
+ else if (key === "ref" && existing) merged.ref = composeRefs(existing, value);
35
+ else if (/^on[A-Z]/.test(key) && typeof existing === "function" && typeof value === "function") merged[key] = (...args) => {
36
+ value(...args);
37
+ existing(...args);
38
+ };
39
+ else if (key === "className") merged.className = cx(existing, value);
40
+ else if (key === "style") merged.style = {
41
+ ...existing,
42
+ ...value
43
+ };
44
+ else merged[key] = value;
45
+ }
46
+ }
47
+ return merged;
48
+ };
49
+ var isReact19 = Number(version.split(".")[0]) >= 19;
50
+ /**
51
+ * The ref an element was created with: a prop in React 19, a field in 18.
52
+ * Reading the field in 19 logs a deprecation warning, so branch on version.
53
+ */
54
+ var elementRef = (element) => isReact19 ? element.props.ref : element.ref;
55
+ var useRender = ({ render, props, ref, state, defaultTagName = "div" }) => {
56
+ const element = isValidElement(render) ? render : void 0;
57
+ const mergedRef = useMergedRefs(ref, element && elementRef(element));
58
+ const rendered = typeof render === "function" ? render({
59
+ ...props,
60
+ ref: mergedRef
61
+ }, state) : element ? cloneElement(element, {
62
+ ...mergeProps(props, element.props),
63
+ ref: mergedRef
64
+ }) : createElement(defaultTagName, {
65
+ ...props,
66
+ ref: mergedRef
67
+ });
68
+ return rendered.type === "button" && rendered.props.type === void 0 ? cloneElement(rendered, { type: "button" }) : rendered;
69
+ };
70
+ //#endregion
71
+ export { mergeProps, useRender };
72
+
73
+ //# sourceMappingURL=useRender.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useRender.js","names":[],"sources":["../../../src/utils/useRender.ts"],"sourcesContent":["// A port of Base UI's `render` prop: its `useRender` hook and `mergeProps`\n// utility (https://base-ui.com/react/utils/use-render), adapted without the\n// dependency and cut down to what this library uses. Base UI also maps state\n// to data-* attributes and takes arrays of refs; neither is needed here.\n//\n// A component keeps its own element and props, and lets the app swap the\n// element: pass an element to merge onto, or a function that receives the\n// props (and the component's state) and returns the element. Unlike Base UI,\n// a <button> that ends up with no `type` gets `type=\"button\"`, so swapping\n// an element in never makes a form submit button by accident.\n//\n// Base UI is distributed under the MIT License:\n//\n// Copyright (c) 2019 Material-UI SAS\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to\n// deal in the Software without restriction, including without limitation the\n// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n// sell copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n// IN THE SOFTWARE.\nimport {\n cloneElement,\n createElement,\n isValidElement,\n useCallback,\n version,\n type HTMLAttributes,\n type JSX,\n type ReactElement,\n type Ref,\n type RefCallback,\n} from 'react'\nimport cx from 'classnames'\n\nexport type RenderProps = HTMLAttributes<HTMLElement> & {\n [key: string]: unknown\n}\n\n/**\n * Replaces a component's element. Pass an element to merge the component's\n * props onto, e.g. `<button />`, or a function that spreads them:\n * `(props, state) => <button {...props} onClick={…} />`.\n */\nexport type RenderProp<State> =\n | ReactElement\n | ((\n props: RenderProps & { ref: RefCallback<HTMLElement> },\n state: State\n ) => ReactElement)\n\n/** Sets one ref. Returns a callback ref's cleanup, if it gave one. */\nconst setRef = <T>(ref: Ref<T> | undefined, value: T | null) => {\n if (typeof ref === 'function') return ref(value)\n if (ref) (ref as { current: T | null }).current = value\n}\n\n/**\n * One callback ref that feeds every ref given to it. When a callback ref\n * returns a cleanup (React 19), detaching runs it instead of passing null.\n */\nconst composeRefs =\n <T>(...refs: (Ref<T> | undefined)[]): RefCallback<T> =>\n (value: T | null) => {\n const cleanups = refs.map((ref) => setRef(ref, value))\n if (!cleanups.some((cleanup) => typeof cleanup === 'function')) return\n return () =>\n cleanups.forEach((cleanup, index) =>\n typeof cleanup === 'function' ? cleanup() : setRef(refs[index], null)\n )\n }\n\n/** `composeRefs`, kept stable while the refs are. */\nconst useMergedRefs = <T>(...refs: (Ref<T> | undefined)[]): RefCallback<T> =>\n useCallback((value: T | null) => composeRefs(...refs)(value), refs)\n\n/**\n * Merges prop objects left to right. Later props win, except that event\n * handlers all run (last first), classNames join, styles combine and refs\n * all receive the element. An `undefined` handler or ref leaves an earlier\n * one in place. The merged ref is a new function on every call, so React\n * reattaches it on each render, as with any inline callback ref.\n */\nexport const mergeProps = (\n ...sources: (RenderProps | undefined)[]\n): RenderProps => {\n const merged: RenderProps = {}\n for (const source of sources) {\n if (!source) continue\n for (const [key, value] of Object.entries(source)) {\n const existing = merged[key]\n if ((key === 'ref' || /^on[A-Z]/.test(key)) && value === undefined) {\n continue\n } else if (key === 'ref' && existing) {\n merged.ref = composeRefs(\n existing as Ref<unknown>,\n value as Ref<unknown>\n )\n } else if (\n /^on[A-Z]/.test(key) &&\n typeof existing === 'function' &&\n typeof value === 'function'\n ) {\n merged[key] = (...args: unknown[]) => {\n value(...args)\n existing(...args)\n }\n } else if (key === 'className') {\n merged.className = cx(existing as string, value as string)\n } else if (key === 'style') {\n merged.style = { ...(existing as object), ...(value as object) }\n } else {\n merged[key] = value\n }\n }\n }\n return merged\n}\n\nconst isReact19 = Number(version.split('.')[0]) >= 19\n\n/**\n * The ref an element was created with: a prop in React 19, a field in 18.\n * Reading the field in 19 logs a deprecation warning, so branch on version.\n */\nconst elementRef = (element: ReactElement): Ref<HTMLElement> | undefined =>\n isReact19\n ? (element.props as { ref?: Ref<HTMLElement> }).ref\n : (element as unknown as { ref?: Ref<HTMLElement> }).ref\n\nexport const useRender = <State>({\n render,\n props,\n ref,\n state,\n defaultTagName = 'div',\n}: {\n render?: RenderProp<State>\n /** The component's own props, already merged with what it was given. */\n props: RenderProps\n ref?: Ref<HTMLElement>\n /** Passed to a `render` function as its second argument. */\n state: State\n defaultTagName?: keyof JSX.IntrinsicElements\n}): ReactElement => {\n const element = isValidElement(render) ? render : undefined\n const mergedRef = useMergedRefs(ref, element && elementRef(element))\n\n const rendered =\n typeof render === 'function'\n ? render({ ...props, ref: mergedRef }, state)\n : element\n ? cloneElement(element, {\n ...mergeProps(props, element.props as RenderProps),\n ref: mergedRef,\n } as RenderProps)\n : createElement(defaultTagName, { ...props, ref: mergedRef })\n return rendered.type === 'button' &&\n (rendered.props as RenderProps).type === undefined\n ? cloneElement(rendered, { type: 'button' } as RenderProps)\n : rendered\n}\n"],"mappings":";;;;AA+DA,IAAM,UAAa,KAAyB,UAAoB;CAC9D,IAAI,OAAO,QAAQ,YAAY,OAAO,IAAI,KAAK;CAC/C,IAAI,KAAK,IAA+B,UAAU;AACpD;;;;;AAMA,IAAM,eACA,GAAG,UACN,UAAoB;CACnB,MAAM,WAAW,KAAK,KAAK,QAAQ,OAAO,KAAK,KAAK,CAAC;CACrD,IAAI,CAAC,SAAS,MAAM,YAAY,OAAO,YAAY,UAAU,GAAG;CAChE,aACE,SAAS,SAAS,SAAS,UACzB,OAAO,YAAY,aAAa,QAAQ,IAAI,OAAO,KAAK,QAAQ,IAAI,CACtE;AACJ;;AAGF,IAAM,iBAAoB,GAAG,SAC3B,aAAa,UAAoB,YAAY,GAAG,IAAI,CAAC,CAAC,KAAK,GAAG,IAAI;;;;;;;;AASpE,IAAa,cACX,GAAG,YACa;CAChB,MAAM,SAAsB,CAAC;CAC7B,KAAK,MAAM,UAAU,SAAS;EAC5B,IAAI,CAAC,QAAQ;EACb,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,MAAM,GAAG;GACjD,MAAM,WAAW,OAAO;GACxB,KAAK,QAAQ,SAAS,WAAW,KAAK,GAAG,MAAM,UAAU,KAAA,GACvD;QACK,IAAI,QAAQ,SAAS,UAC1B,OAAO,MAAM,YACX,UACA,KACF;QACK,IACL,WAAW,KAAK,GAAG,KACnB,OAAO,aAAa,cACpB,OAAO,UAAU,YAEjB,OAAO,QAAQ,GAAG,SAAoB;IACpC,MAAM,GAAG,IAAI;IACb,SAAS,GAAG,IAAI;GAClB;QACK,IAAI,QAAQ,aACjB,OAAO,YAAY,GAAG,UAAoB,KAAe;QACpD,IAAI,QAAQ,SACjB,OAAO,QAAQ;IAAE,GAAI;IAAqB,GAAI;GAAiB;QAE/D,OAAO,OAAO;EAElB;CACF;CACA,OAAO;AACT;AAEA,IAAM,YAAY,OAAO,QAAQ,MAAM,GAAG,CAAC,CAAC,EAAE,KAAK;;;;;AAMnD,IAAM,cAAc,YAClB,YACK,QAAQ,MAAqC,MAC7C,QAAkD;AAEzD,IAAa,aAAoB,EAC/B,QACA,OACA,KACA,OACA,iBAAiB,YASC;CAClB,MAAM,UAAU,eAAe,MAAM,IAAI,SAAS,KAAA;CAClD,MAAM,YAAY,cAAc,KAAK,WAAW,WAAW,OAAO,CAAC;CAEnE,MAAM,WACJ,OAAO,WAAW,aACd,OAAO;EAAE,GAAG;EAAO,KAAK;CAAU,GAAG,KAAK,IAC1C,UACE,aAAa,SAAS;EACpB,GAAG,WAAW,OAAO,QAAQ,KAAoB;EACjD,KAAK;CACP,CAAgB,IAChB,cAAc,gBAAgB;EAAE,GAAG;EAAO,KAAK;CAAU,CAAC;CAClE,OAAO,SAAS,SAAS,YACtB,SAAS,MAAsB,SAAS,KAAA,IACvC,aAAa,UAAU,EAAE,MAAM,SAAS,CAAgB,IACxD;AACN"}