@apipass/design-system 8.1.0 → 8.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.
@@ -1,113 +1,183 @@
1
- import { jsx as n, jsxs as d } from "react/jsx-runtime";
2
- import { clsx as N } from "../../../vendor/clsx/dist/clsx.js";
3
- import h, { useRef as R, useState as F, useCallback as I, useLayoutEffect as j } from "react";
4
- import { MenuTrigger as B, Button as L, Popover as M } from "react-aria-components";
1
+ import { jsx as n, jsxs as S } from "react/jsx-runtime";
2
+ import { clsx as D } from "../../../vendor/clsx/dist/clsx.js";
3
+ import x, { useRef as N, useState as F, useCallback as k, useLayoutEffect as L } from "react";
4
+ import { MenuTrigger as M, Button as O, Popover as V, useFilter as j, TextField as A } from "react-aria-components";
5
5
  /* empty css */
6
- import { IconChevronDown as O } from "../../icons/IconChevronDown.js";
7
- import { useOverlayPortalContainer as W } from "../../hooks/useOverlayPortal.js";
8
- import { Field as k, Label as z, Description as D, FieldError as P } from "../Fieldset/Fieldset.js";
9
- import { ListBox as V } from "../ListBox/ListBox.js";
10
- function g(t) {
11
- const { id: e } = t.props;
12
- return String(e ?? t.key ?? "");
6
+ import { IconChevronDown as W } from "../../icons/IconChevronDown.js";
7
+ import { useOverlayPortalContainer as z } from "../../hooks/useOverlayPortal.js";
8
+ import { Field as K, Label as q, Description as H, FieldError as P } from "../Fieldset/Fieldset.js";
9
+ import { ListBox as E } from "../ListBox/ListBox.js";
10
+ import { Input as U } from "../Input/Input.js";
11
+ function w(r) {
12
+ const { id: e } = r.props;
13
+ return e ?? r.key ?? "";
13
14
  }
14
- function A(t) {
15
- const { textValue: e, children: r } = t.props;
16
- return e !== void 0 ? e : typeof r == "string" ? r : "";
15
+ function I(r) {
16
+ const { textValue: e, children: t } = r.props;
17
+ return e !== void 0 ? e : typeof t == "string" ? t : "";
17
18
  }
18
- function v(t, e) {
19
- h.Children.forEach(t, (r) => {
20
- h.isValidElement(r) && e(r);
19
+ function R(r, e) {
20
+ x.Children.forEach(r, (t) => {
21
+ x.isValidElement(t) && e(t);
21
22
  });
22
23
  }
23
- function K(t) {
24
+ function _(r) {
24
25
  const e = /* @__PURE__ */ new Set();
25
- return v(t, (r) => e.add(g(r))), e;
26
+ return R(r, (t) => e.add(w(t))), e;
26
27
  }
27
- function U(t, e) {
28
- const r = new Set([...e].map(String)), i = [];
29
- return v(t, (s) => {
30
- r.has(g(s)) && i.push(A(s));
28
+ function $(r, e, t) {
29
+ return x.Children.toArray(r).filter(
30
+ (i) => x.isValidElement(i) && t(I(i), e)
31
+ );
32
+ }
33
+ function G(r, e, t) {
34
+ const i = new Set(e.map(String)), o = (c) => i.has(String(c)), s = [...r].filter((c) => !o(c)), a = t === "all" ? e : [...t].filter(o);
35
+ return /* @__PURE__ */ new Set([...s, ...a]);
36
+ }
37
+ function J(r, e) {
38
+ const t = new Set([...e].map(String)), i = [];
39
+ return R(r, (o) => {
40
+ t.has(String(w(o))) && i.push(I(o));
31
41
  }), i.join(", ");
32
42
  }
33
- function Z({
34
- className: t,
43
+ function Q({
44
+ children: r,
45
+ selectedKeys: e,
46
+ onSelectionChange: t,
47
+ disallowEmptySelection: i,
48
+ listLabel: o,
49
+ searchPlaceholder: s,
50
+ emptyStateText: a
51
+ }) {
52
+ const { contains: c } = j({ sensitivity: "base" }), [h, y] = F(""), m = N(null), l = $(r, h, c), f = l.map(w);
53
+ function b(d) {
54
+ var u, g;
55
+ d.key !== "ArrowDown" || l.length === 0 || (d.preventDefault(), (g = (u = m.current) == null ? void 0 : u.querySelector('[role="listbox"]')) == null || g.focus());
56
+ }
57
+ return /* @__PURE__ */ S("div", { ref: m, className: "select-search-panel", children: [
58
+ /* @__PURE__ */ n(
59
+ A,
60
+ {
61
+ "aria-label": s,
62
+ value: h,
63
+ onChange: y,
64
+ autoFocus: !0,
65
+ children: /* @__PURE__ */ n(
66
+ U,
67
+ {
68
+ className: "select-search-input",
69
+ placeholder: s,
70
+ onKeyDown: b
71
+ }
72
+ )
73
+ }
74
+ ),
75
+ /* @__PURE__ */ n(
76
+ E,
77
+ {
78
+ "aria-label": o,
79
+ selectionMode: "multiple",
80
+ escapeKeyBehavior: "none",
81
+ disallowEmptySelection: i,
82
+ selectedKeys: e,
83
+ onSelectionChange: (d) => t(G(e, f, d)),
84
+ renderEmptyState: () => /* @__PURE__ */ n("span", { className: "select-empty-state", children: a }),
85
+ children: l
86
+ }
87
+ )
88
+ ] });
89
+ }
90
+ function ce({
91
+ className: r,
35
92
  label: e,
36
- description: r,
93
+ description: t,
37
94
  errorMessage: i,
38
- placeholder: s,
39
- children: a,
40
- selectedKeys: f,
41
- onSelectionChange: x,
42
- isDisabled: S,
95
+ placeholder: o,
96
+ children: s,
97
+ selectedKeys: a,
98
+ onSelectionChange: c,
99
+ isDisabled: h,
43
100
  isInvalid: y,
44
- disallowEmptySelection: C,
45
- "aria-label": m
101
+ disallowEmptySelection: m,
102
+ "aria-label": l,
103
+ ...f
46
104
  }) {
47
- const T = N(t, "select-container"), b = W(), c = R(null), [w, E] = F(), u = I(() => {
48
- c.current && E(`${c.current.offsetWidth}px`);
105
+ const b = D(r, "select-container"), d = z(), u = N(null), [g, B] = F(), T = k(() => {
106
+ u.current && B(`${u.current.offsetWidth}px`);
49
107
  }, []);
50
- j(() => {
51
- u();
52
- const o = c.current;
53
- if (!o || typeof ResizeObserver > "u") return;
54
- const p = new ResizeObserver(u);
55
- return p.observe(o), () => p.disconnect();
56
- }, [u]);
57
- const l = U(a, f);
58
- return /* @__PURE__ */ n("div", { className: T, children: /* @__PURE__ */ d(k, { children: [
59
- e && /* @__PURE__ */ n(z, { children: e }),
60
- /* @__PURE__ */ d(B, { children: [
61
- /* @__PURE__ */ d(
62
- L,
108
+ L(() => {
109
+ T();
110
+ const p = u.current;
111
+ if (!p || typeof ResizeObserver > "u") return;
112
+ const C = new ResizeObserver(T);
113
+ return C.observe(p), () => C.disconnect();
114
+ }, [T]);
115
+ const v = J(s, a);
116
+ return /* @__PURE__ */ n("div", { className: b, children: /* @__PURE__ */ S(K, { children: [
117
+ e && /* @__PURE__ */ n(q, { children: e }),
118
+ /* @__PURE__ */ S(M, { children: [
119
+ /* @__PURE__ */ S(
120
+ O,
63
121
  {
64
- ref: c,
122
+ ref: u,
65
123
  className: "select",
66
- "aria-label": m,
67
- isDisabled: S,
124
+ "aria-label": l,
125
+ isDisabled: h,
68
126
  "data-invalid": y || void 0,
69
127
  children: [
70
128
  /* @__PURE__ */ n(
71
129
  "span",
72
130
  {
73
131
  className: "select-value",
74
- "data-placeholder": l === "" || void 0,
75
- title: l || void 0,
76
- children: l === "" ? s : l
132
+ "data-placeholder": v === "" || void 0,
133
+ title: v || void 0,
134
+ children: v === "" ? o : v
77
135
  }
78
136
  ),
79
- /* @__PURE__ */ n(O, { "aria-hidden": "true" })
137
+ /* @__PURE__ */ n(W, { "aria-hidden": "true" })
80
138
  ]
81
139
  }
82
140
  ),
83
141
  /* @__PURE__ */ n(
84
- M,
142
+ V,
85
143
  {
86
144
  className: "select-popover",
87
- style: { "--trigger-width": w },
88
- UNSTABLE_portalContainer: b,
89
- children: /* @__PURE__ */ n(
90
- V,
145
+ style: { "--trigger-width": g },
146
+ UNSTABLE_portalContainer: d,
147
+ children: f.isSearchable ? /* @__PURE__ */ n(
148
+ Q,
149
+ {
150
+ listLabel: e ?? l,
151
+ selectedKeys: a,
152
+ onSelectionChange: c,
153
+ disallowEmptySelection: m,
154
+ searchPlaceholder: f.searchPlaceholder,
155
+ emptyStateText: f.emptyStateText,
156
+ children: s
157
+ }
158
+ ) : /* @__PURE__ */ n(
159
+ E,
91
160
  {
92
- "aria-label": e ?? m,
161
+ "aria-label": e ?? l,
93
162
  autoFocus: !0,
94
163
  selectionMode: "multiple",
95
- disallowEmptySelection: C,
96
- selectedKeys: f,
97
- onSelectionChange: (o) => x(
98
- o === "all" ? K(a) : new Set(o)
164
+ escapeKeyBehavior: "none",
165
+ disallowEmptySelection: m,
166
+ selectedKeys: a,
167
+ onSelectionChange: (p) => c(
168
+ p === "all" ? _(s) : new Set(p)
99
169
  ),
100
- children: a
170
+ children: s
101
171
  }
102
172
  )
103
173
  }
104
174
  )
105
175
  ] }),
106
- r && /* @__PURE__ */ n(D, { children: r }),
176
+ t && /* @__PURE__ */ n(H, { children: t }),
107
177
  /* @__PURE__ */ n(P, { children: i })
108
178
  ] }) });
109
179
  }
110
180
  export {
111
- Z as MultiSelectField
181
+ ce as MultiSelectField
112
182
  };
113
183
  //# sourceMappingURL=MultiSelect.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"MultiSelect.js","sources":["../../../../../src/ui/primitives/Select/MultiSelect.tsx"],"sourcesContent":["import { clsx } from \"clsx\";\nimport { useOverlayPortalContainer } from \"hooks\";\nimport { IconChevronDown } from \"icons\";\nimport {\n Description,\n Field,\n FieldError,\n Label,\n ListBox,\n SharedFieldProps,\n} from \"primitives\";\nimport React, { useCallback, useLayoutEffect, useRef, useState } from \"react\";\nimport {\n Button as RACButton,\n MenuTrigger as RACMenuTrigger,\n Popover as RACPopover,\n type Key as RACKey,\n type Selection as RACSelection,\n} from \"react-aria-components\";\nimport \"./select.css\";\n\nfunction itemKey(item: React.ReactElement): string {\n const { id } = item.props as { id?: RACKey };\n return String(id ?? item.key ?? \"\");\n}\n\nfunction itemText(item: React.ReactElement): string {\n const { textValue, children } = item.props as {\n textValue?: string;\n children?: React.ReactNode;\n };\n if (textValue !== undefined) return textValue;\n return typeof children === \"string\" ? children : \"\";\n}\n\nfunction forEachItem(\n children: React.ReactNode,\n visit: (item: React.ReactElement) => void,\n) {\n React.Children.forEach(children, (child) => {\n if (React.isValidElement(child)) visit(child);\n });\n}\n\nfunction allItemKeys(children: React.ReactNode): Set<RACKey> {\n const keys = new Set<RACKey>();\n forEachItem(children, (item) => keys.add(itemKey(item)));\n return keys;\n}\n\nfunction selectedItemsText(\n children: React.ReactNode,\n selectedKeys: Iterable<RACKey>,\n): string {\n const selected = new Set([...selectedKeys].map(String));\n const texts: string[] = [];\n forEachItem(children, (item) => {\n if (selected.has(itemKey(item))) texts.push(itemText(item));\n });\n return texts.join(\", \");\n}\n\nexport interface MultiSelectFieldProps extends SharedFieldProps {\n children: React.ReactNode;\n selectedKeys: Iterable<RACKey>;\n onSelectionChange: (keys: Set<RACKey>) => void;\n className?: string;\n isDisabled?: boolean;\n isInvalid?: boolean;\n disallowEmptySelection?: boolean;\n \"aria-label\"?: string;\n}\n\nexport function MultiSelectField({\n className,\n label,\n description,\n errorMessage,\n placeholder,\n children,\n selectedKeys,\n onSelectionChange,\n isDisabled,\n isInvalid,\n disallowEmptySelection,\n \"aria-label\": ariaLabel,\n}: MultiSelectFieldProps) {\n const classNames = clsx(className, \"select-container\");\n const portalContainer = useOverlayPortalContainer();\n const triggerRef = useRef<HTMLButtonElement>(null);\n const [triggerWidth, setTriggerWidth] = useState<string>();\n\n const measureTrigger = useCallback(() => {\n if (triggerRef.current) {\n setTriggerWidth(`${triggerRef.current.offsetWidth}px`);\n }\n }, []);\n\n useLayoutEffect(() => {\n measureTrigger();\n const trigger = triggerRef.current;\n if (!trigger || typeof ResizeObserver === \"undefined\") return;\n const observer = new ResizeObserver(measureTrigger);\n observer.observe(trigger);\n return () => observer.disconnect();\n }, [measureTrigger]);\n\n const chosenText = selectedItemsText(children, selectedKeys);\n\n return (\n <div className={classNames}>\n <Field>\n {label && <Label>{label}</Label>}\n <RACMenuTrigger>\n <RACButton\n ref={triggerRef}\n className=\"select\"\n aria-label={ariaLabel}\n isDisabled={isDisabled}\n data-invalid={isInvalid || undefined}\n >\n <span\n className=\"select-value\"\n data-placeholder={chosenText === \"\" || undefined}\n title={chosenText || undefined}\n >\n {chosenText === \"\" ? placeholder : chosenText}\n </span>\n <IconChevronDown aria-hidden=\"true\" />\n </RACButton>\n <RACPopover\n className=\"select-popover\"\n style={{ \"--trigger-width\": triggerWidth } as React.CSSProperties}\n UNSTABLE_portalContainer={portalContainer}\n >\n <ListBox\n aria-label={label ?? ariaLabel}\n autoFocus\n selectionMode=\"multiple\"\n disallowEmptySelection={disallowEmptySelection}\n selectedKeys={selectedKeys}\n onSelectionChange={(keys: RACSelection) =>\n onSelectionChange(\n keys === \"all\" ? allItemKeys(children) : new Set(keys),\n )\n }\n >\n {children}\n </ListBox>\n </RACPopover>\n </RACMenuTrigger>\n {description && <Description>{description}</Description>}\n <FieldError>{errorMessage}</FieldError>\n </Field>\n </div>\n );\n}\n"],"names":["itemKey","item","id","itemText","textValue","children","forEachItem","visit","React","child","allItemKeys","keys","selectedItemsText","selectedKeys","selected","texts","MultiSelectField","className","label","description","errorMessage","placeholder","onSelectionChange","isDisabled","isInvalid","disallowEmptySelection","ariaLabel","classNames","clsx","portalContainer","useOverlayPortalContainer","triggerRef","useRef","triggerWidth","setTriggerWidth","useState","measureTrigger","useCallback","useLayoutEffect","trigger","observer","chosenText","jsx","Field","Label","RACMenuTrigger","jsxs","RACButton","IconChevronDown","RACPopover","ListBox","Description","FieldError"],"mappings":"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"}
1
+ {"version":3,"file":"MultiSelect.js","sources":["../../../../../src/ui/primitives/Select/MultiSelect.tsx"],"sourcesContent":["import { clsx } from \"clsx\";\nimport { useOverlayPortalContainer } from \"hooks\";\nimport { IconChevronDown } from \"icons\";\nimport {\n Description,\n Field,\n FieldError,\n Input,\n Label,\n ListBox,\n SharedFieldProps,\n} from \"primitives\";\nimport React, { useCallback, useLayoutEffect, useRef, useState } from \"react\";\nimport {\n Button as RACButton,\n MenuTrigger as RACMenuTrigger,\n Popover as RACPopover,\n TextField as RACTextField,\n useFilter,\n type Key as RACKey,\n type Selection as RACSelection,\n} from \"react-aria-components\";\nimport \"./select.css\";\n\nfunction itemKey(item: React.ReactElement): RACKey {\n const { id } = item.props as { id?: RACKey };\n return id ?? item.key ?? \"\";\n}\n\nfunction itemText(item: React.ReactElement): string {\n const { textValue, children } = item.props as {\n textValue?: string;\n children?: React.ReactNode;\n };\n if (textValue !== undefined) return textValue;\n return typeof children === \"string\" ? children : \"\";\n}\n\nfunction forEachItem(\n children: React.ReactNode,\n visit: (item: React.ReactElement) => void,\n) {\n React.Children.forEach(children, (child) => {\n if (React.isValidElement(child)) visit(child);\n });\n}\n\nfunction allItemKeys(children: React.ReactNode): Set<RACKey> {\n const keys = new Set<RACKey>();\n forEachItem(children, (item) => keys.add(itemKey(item)));\n return keys;\n}\n\ntype TextMatcher = (text: string, searchText: string) => boolean;\n\nfunction matchingItems(\n children: React.ReactNode,\n searchText: string,\n matches: TextMatcher,\n): React.ReactElement[] {\n return React.Children.toArray(children).filter(\n (child): child is React.ReactElement =>\n React.isValidElement(child) && matches(itemText(child), searchText),\n );\n}\n\nfunction keepHiddenSelection(\n previousKeys: Iterable<RACKey>,\n visibleKeys: RACKey[],\n visibleSelection: RACSelection,\n): Set<RACKey> {\n const visible = new Set(visibleKeys.map(String));\n const isVisible = (key: RACKey) => visible.has(String(key));\n const hiddenSelected = [...previousKeys].filter((key) => !isVisible(key));\n const visibleSelected =\n visibleSelection === \"all\"\n ? visibleKeys\n : [...visibleSelection].filter(isVisible);\n return new Set([...hiddenSelected, ...visibleSelected]);\n}\n\nfunction selectedItemsText(\n children: React.ReactNode,\n selectedKeys: Iterable<RACKey>,\n): string {\n const selected = new Set([...selectedKeys].map(String));\n const texts: string[] = [];\n forEachItem(children, (item) => {\n if (selected.has(String(itemKey(item)))) texts.push(itemText(item));\n });\n return texts.join(\", \");\n}\n\ninterface MultiSelectOptionsProps {\n children: React.ReactNode;\n selectedKeys: Iterable<RACKey>;\n onSelectionChange: (keys: Set<RACKey>) => void;\n disallowEmptySelection?: boolean;\n}\n\ninterface MultiSelectFieldBaseProps\n extends SharedFieldProps,\n MultiSelectOptionsProps {\n className?: string;\n isDisabled?: boolean;\n isInvalid?: boolean;\n \"aria-label\"?: string;\n}\n\nexport interface MultiSelectSearchProps {\n isSearchable: true;\n searchPlaceholder: string;\n emptyStateText: string;\n}\n\ninterface MultiSelectWithoutSearchProps {\n isSearchable?: false;\n searchPlaceholder?: never;\n emptyStateText?: never;\n}\n\nexport type MultiSelectFieldProps = MultiSelectFieldBaseProps &\n (MultiSelectSearchProps | MultiSelectWithoutSearchProps);\n\nfunction SearchableOptions({\n children,\n selectedKeys,\n onSelectionChange,\n disallowEmptySelection,\n listLabel,\n searchPlaceholder,\n emptyStateText,\n}: MultiSelectOptionsProps &\n Omit<MultiSelectSearchProps, \"isSearchable\"> & { listLabel?: string }) {\n const { contains } = useFilter({ sensitivity: \"base\" });\n const [searchText, setSearchText] = useState(\"\");\n const panelRef = useRef<HTMLDivElement>(null);\n const visibleItems = matchingItems(children, searchText, contains);\n const visibleKeys = visibleItems.map(itemKey);\n\n function moveFocusToList(event: React.KeyboardEvent<HTMLInputElement>) {\n if (event.key !== \"ArrowDown\" || visibleItems.length === 0) return;\n event.preventDefault();\n panelRef.current?.querySelector<HTMLElement>('[role=\"listbox\"]')?.focus();\n }\n\n return (\n <div ref={panelRef} className=\"select-search-panel\">\n <RACTextField\n aria-label={searchPlaceholder}\n value={searchText}\n onChange={setSearchText}\n autoFocus\n >\n <Input\n className=\"select-search-input\"\n placeholder={searchPlaceholder}\n onKeyDown={moveFocusToList}\n />\n </RACTextField>\n <ListBox\n aria-label={listLabel}\n selectionMode=\"multiple\"\n escapeKeyBehavior=\"none\"\n disallowEmptySelection={disallowEmptySelection}\n selectedKeys={selectedKeys}\n onSelectionChange={(keys: RACSelection) =>\n onSelectionChange(keepHiddenSelection(selectedKeys, visibleKeys, keys))\n }\n renderEmptyState={() => (\n <span className=\"select-empty-state\">{emptyStateText}</span>\n )}\n >\n {visibleItems}\n </ListBox>\n </div>\n );\n}\n\nexport function MultiSelectField({\n className,\n label,\n description,\n errorMessage,\n placeholder,\n children,\n selectedKeys,\n onSelectionChange,\n isDisabled,\n isInvalid,\n disallowEmptySelection,\n \"aria-label\": ariaLabel,\n ...searchProps\n}: MultiSelectFieldProps) {\n const classNames = clsx(className, \"select-container\");\n const portalContainer = useOverlayPortalContainer();\n const triggerRef = useRef<HTMLButtonElement>(null);\n const [triggerWidth, setTriggerWidth] = useState<string>();\n\n const measureTrigger = useCallback(() => {\n if (triggerRef.current) {\n setTriggerWidth(`${triggerRef.current.offsetWidth}px`);\n }\n }, []);\n\n useLayoutEffect(() => {\n measureTrigger();\n const trigger = triggerRef.current;\n if (!trigger || typeof ResizeObserver === \"undefined\") return;\n const observer = new ResizeObserver(measureTrigger);\n observer.observe(trigger);\n return () => observer.disconnect();\n }, [measureTrigger]);\n\n const chosenText = selectedItemsText(children, selectedKeys);\n\n return (\n <div className={classNames}>\n <Field>\n {label && <Label>{label}</Label>}\n <RACMenuTrigger>\n <RACButton\n ref={triggerRef}\n className=\"select\"\n aria-label={ariaLabel}\n isDisabled={isDisabled}\n data-invalid={isInvalid || undefined}\n >\n <span\n className=\"select-value\"\n data-placeholder={chosenText === \"\" || undefined}\n title={chosenText || undefined}\n >\n {chosenText === \"\" ? placeholder : chosenText}\n </span>\n <IconChevronDown aria-hidden=\"true\" />\n </RACButton>\n <RACPopover\n className=\"select-popover\"\n style={{ \"--trigger-width\": triggerWidth } as React.CSSProperties}\n UNSTABLE_portalContainer={portalContainer}\n >\n {searchProps.isSearchable ? (\n <SearchableOptions\n listLabel={label ?? ariaLabel}\n selectedKeys={selectedKeys}\n onSelectionChange={onSelectionChange}\n disallowEmptySelection={disallowEmptySelection}\n searchPlaceholder={searchProps.searchPlaceholder}\n emptyStateText={searchProps.emptyStateText}\n >\n {children}\n </SearchableOptions>\n ) : (\n <ListBox\n aria-label={label ?? ariaLabel}\n autoFocus\n selectionMode=\"multiple\"\n escapeKeyBehavior=\"none\"\n disallowEmptySelection={disallowEmptySelection}\n selectedKeys={selectedKeys}\n onSelectionChange={(keys: RACSelection) =>\n onSelectionChange(\n keys === \"all\" ? allItemKeys(children) : new Set(keys),\n )\n }\n >\n {children}\n </ListBox>\n )}\n </RACPopover>\n </RACMenuTrigger>\n {description && <Description>{description}</Description>}\n <FieldError>{errorMessage}</FieldError>\n </Field>\n </div>\n );\n}\n"],"names":["itemKey","item","id","itemText","textValue","children","forEachItem","visit","React","child","allItemKeys","keys","matchingItems","searchText","matches","keepHiddenSelection","previousKeys","visibleKeys","visibleSelection","visible","isVisible","key","hiddenSelected","visibleSelected","selectedItemsText","selectedKeys","selected","texts","SearchableOptions","onSelectionChange","disallowEmptySelection","listLabel","searchPlaceholder","emptyStateText","contains","useFilter","setSearchText","useState","panelRef","useRef","visibleItems","moveFocusToList","event","_b","_a","jsxs","jsx","RACTextField","Input","ListBox","MultiSelectField","className","label","description","errorMessage","placeholder","isDisabled","isInvalid","ariaLabel","searchProps","classNames","clsx","portalContainer","useOverlayPortalContainer","triggerRef","triggerWidth","setTriggerWidth","measureTrigger","useCallback","useLayoutEffect","trigger","observer","chosenText","Field","Label","RACMenuTrigger","RACButton","IconChevronDown","RACPopover","Description","FieldError"],"mappings":"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"}
@@ -1,13 +1,14 @@
1
1
  import { type ComponentPropsWithoutRef } from "react";
2
2
  import { type ChartLegendLabels } from "../ChartLegend/ChartLegend";
3
- import { type TimeSeriesData, type TimeSeriesDisplayType, type TimeSeriesLegendMode, type TimeSeriesLineOptions, type TimeSeriesYAxisOptions } from "./time-series-option";
3
+ import { type TimeSeriesData, type TimeSeriesDisplayType, type TimeSeriesLegendMode, type TimeSeriesLineOptions, type TimeSeriesXAxisOptions, type TimeSeriesYAxisOptions } from "./time-series-option";
4
4
  import "./time-series-chart.css";
5
- export type { TimeSeriesData, TimeSeriesDisplayType, TimeSeriesLegendMode, TimeSeriesLineOptions, TimeSeriesLineStyle, TimeSeriesLineWidth, TimeSeriesPoint, TimeSeriesYAxisOptions, } from "./time-series-option";
5
+ export type { TimeSeriesData, TimeSeriesDisplayType, TimeSeriesLegendMode, TimeSeriesLineOptions, TimeSeriesLineStyle, TimeSeriesLineWidth, TimeSeriesPoint, TimeSeriesXAxisOptions, TimeSeriesYAxisOptions, } from "./time-series-option";
6
6
  export type TimeSeriesChartProps = Omit<ComponentPropsWithoutRef<"div">, "children"> & {
7
7
  series: TimeSeriesData[];
8
8
  displayType?: TimeSeriesDisplayType;
9
9
  legend?: TimeSeriesLegendMode;
10
10
  line?: TimeSeriesLineOptions;
11
+ xAxis?: TimeSeriesXAxisOptions;
11
12
  yAxis?: TimeSeriesYAxisOptions;
12
13
  showSymbols?: boolean;
13
14
  showValueLabels?: boolean;
@@ -15,4 +16,4 @@ export type TimeSeriesChartProps = Omit<ComponentPropsWithoutRef<"div">, "childr
15
16
  onSeriesColorChange?: (seriesId: string, colorToken: string | null) => void;
16
17
  legendLabels?: Partial<ChartLegendLabels>;
17
18
  };
18
- export declare function TimeSeriesChart({ series, displayType, legend, line, yAxis, showSymbols, showValueLabels, valueFormatter, onSeriesColorChange, legendLabels, className, ...props }: TimeSeriesChartProps): import("react/jsx-runtime").JSX.Element;
19
+ export declare function TimeSeriesChart({ series, displayType, legend, line, xAxis, yAxis, showSymbols, showValueLabels, valueFormatter, onSeriesColorChange, legendLabels, className, ...props }: TimeSeriesChartProps): import("react/jsx-runtime").JSX.Element;
@@ -24,10 +24,15 @@ export interface TimeSeriesYAxisOptions {
24
24
  max?: number;
25
25
  includeZero?: boolean;
26
26
  }
27
+ export interface TimeSeriesXAxisOptions {
28
+ min?: number;
29
+ max?: number;
30
+ }
27
31
  export interface TimeSeriesOptionInput {
28
32
  series: TimeSeriesData[];
29
33
  displayType: TimeSeriesDisplayType;
30
34
  line: TimeSeriesLineOptions;
35
+ xAxis: TimeSeriesXAxisOptions;
31
36
  yAxis: TimeSeriesYAxisOptions;
32
37
  theme: ChartTheme;
33
38
  showSymbols: boolean;
@@ -2,14 +2,28 @@ import { SharedFieldProps } from "primitives";
2
2
  import React from "react";
3
3
  import { type Key as RACKey } from "react-aria-components";
4
4
  import "./select.css";
5
- export interface MultiSelectFieldProps extends SharedFieldProps {
5
+ interface MultiSelectOptionsProps {
6
6
  children: React.ReactNode;
7
7
  selectedKeys: Iterable<RACKey>;
8
8
  onSelectionChange: (keys: Set<RACKey>) => void;
9
+ disallowEmptySelection?: boolean;
10
+ }
11
+ interface MultiSelectFieldBaseProps extends SharedFieldProps, MultiSelectOptionsProps {
9
12
  className?: string;
10
13
  isDisabled?: boolean;
11
14
  isInvalid?: boolean;
12
- disallowEmptySelection?: boolean;
13
15
  "aria-label"?: string;
14
16
  }
15
- export declare function MultiSelectField({ className, label, description, errorMessage, placeholder, children, selectedKeys, onSelectionChange, isDisabled, isInvalid, disallowEmptySelection, "aria-label": ariaLabel, }: MultiSelectFieldProps): import("react/jsx-runtime").JSX.Element;
17
+ export interface MultiSelectSearchProps {
18
+ isSearchable: true;
19
+ searchPlaceholder: string;
20
+ emptyStateText: string;
21
+ }
22
+ interface MultiSelectWithoutSearchProps {
23
+ isSearchable?: false;
24
+ searchPlaceholder?: never;
25
+ emptyStateText?: never;
26
+ }
27
+ export type MultiSelectFieldProps = MultiSelectFieldBaseProps & (MultiSelectSearchProps | MultiSelectWithoutSearchProps);
28
+ export declare function MultiSelectField({ className, label, description, errorMessage, placeholder, children, selectedKeys, onSelectionChange, isDisabled, isInvalid, disallowEmptySelection, "aria-label": ariaLabel, ...searchProps }: MultiSelectFieldProps): import("react/jsx-runtime").JSX.Element;
29
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@apipass/design-system",
3
- "version": "8.1.0",
3
+ "version": "8.3.0",
4
4
  "type": "module",
5
5
  "description": "APIPass React Design System",
6
6
  "sideEffects": [
@@ -135,6 +135,9 @@
135
135
  "@storybook/addon-mcp": "^0.5.0",
136
136
  "@storybook/react": "^10.3.4",
137
137
  "@storybook/react-vite": "^10.3.4",
138
+ "@testing-library/dom": "^10.4.0",
139
+ "@testing-library/react": "^16.3.0",
140
+ "@testing-library/user-event": "^14.6.1",
138
141
  "@types/react": "^18.2.15",
139
142
  "@types/react-dom": "^18.2.7",
140
143
  "@types/react-grid-layout": "^1.3.6",
@@ -146,6 +149,7 @@
146
149
  "eslint-plugin-react-hooks": "^4.6.0",
147
150
  "eslint-plugin-react-refresh": "^0.4.3",
148
151
  "eslint-plugin-storybook": "^10.3.4",
152
+ "jsdom": "^26.1.0",
149
153
  "postcss": "8.5.6",
150
154
  "prettier-plugin-organize-imports": "^3.2.4",
151
155
  "react": "^18.2.0",