@apipass/design-system 8.0.0 → 8.2.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,5 +1,5 @@
1
1
  import { type DateValue } from "@internationalized/date";
2
- import { type DateRangePresetKey } from "./dateRangePresets";
2
+ import { type DateRangePresetKey, type FirstDayOfWeek } from "./dateRangePresets";
3
3
  import "./daterangepicker.css";
4
4
  export interface DateRangePreset {
5
5
  id: string;
@@ -38,10 +38,11 @@ export interface DateRangePickerProps {
38
38
  minValue?: DateValue;
39
39
  maxValue?: DateValue;
40
40
  timezone?: string;
41
+ firstDayOfWeek?: FirstDayOfWeek;
41
42
  isDisabled?: boolean;
42
43
  isRequired?: boolean;
43
44
  value?: DateRangePickerValue;
44
45
  defaultValue?: DateRangePickerValue;
45
46
  onChange?: (value: DateRangePickerValue) => void;
46
47
  }
47
- export declare function DateRangePicker({ className, locale: localeProp, label, "aria-label": ariaLabel, description, errorMessage, labels, intervals: intervalsProp, presetKeys, presetLabels, hideTime, minValue, maxValue, timezone: timezoneProp, isDisabled, isRequired, value, defaultValue, onChange, }: DateRangePickerProps): import("react/jsx-runtime").JSX.Element;
48
+ export declare function DateRangePicker({ className, locale: localeProp, label, "aria-label": ariaLabel, description, errorMessage, labels, intervals: intervalsProp, presetKeys, presetLabels, hideTime, minValue, maxValue, timezone: timezoneProp, firstDayOfWeek, isDisabled, isRequired, value, defaultValue, onChange, }: DateRangePickerProps): import("react/jsx-runtime").JSX.Element;
@@ -1,10 +1,15 @@
1
1
  import type { DateRangePreset } from "./DateRangePicker";
2
2
  export type DateRangePresetKey = "last5m" | "last15m" | "last30m" | "last1h" | "last3h" | "last6h" | "last12h" | "last24h" | "today" | "yesterday" | "last7d" | "last30d" | "thisWeek" | "lastWeek" | "thisMonth" | "lastMonth" | "thisYear" | "lastYear";
3
3
  export declare const DATE_RANGE_PRESET_ORDER: DateRangePresetKey[];
4
+ export type FirstDayOfWeek = "sun" | "mon" | "tue" | "wed" | "thu" | "fri" | "sat";
5
+ export declare const DEFAULT_DATE_RANGE_PRESET_TIMEZONE: string;
6
+ export declare const DEFAULT_FIRST_DAY_OF_WEEK: FirstDayOfWeek;
4
7
  export interface CreateDateRangePresetsOptions {
5
8
  labels: Record<DateRangePresetKey, string>;
6
9
  timezone?: string;
10
+ /** @deprecated Sem efeito desde a CONSOLE-1892: o início da semana vem de `firstDayOfWeek`. */
7
11
  locale?: string;
12
+ firstDayOfWeek?: FirstDayOfWeek;
8
13
  include?: DateRangePresetKey[];
9
14
  }
10
15
  export declare function createDateRangePresets(options: CreateDateRangePresetsOptions): DateRangePreset[];
@@ -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.0.0",
3
+ "version": "8.2.0",
4
4
  "type": "module",
5
5
  "description": "APIPass React Design System",
6
6
  "sideEffects": [
@@ -58,6 +58,7 @@
58
58
  "build:lib": "tsc -p tsconfig.lib.json && vite build --config vite.lib.config.ts && node scripts/gen-embedded-styles.mjs",
59
59
  "app:dev": "vite",
60
60
  "app:build": "tsc && vite build",
61
+ "app:test": "vitest run",
61
62
  "app:lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
62
63
  "app:preview": "vite preview",
63
64
  "storybook:install": "npm ci",
@@ -134,6 +135,9 @@
134
135
  "@storybook/addon-mcp": "^0.5.0",
135
136
  "@storybook/react": "^10.3.4",
136
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",
137
141
  "@types/react": "^18.2.15",
138
142
  "@types/react-dom": "^18.2.7",
139
143
  "@types/react-grid-layout": "^1.3.6",
@@ -145,6 +149,7 @@
145
149
  "eslint-plugin-react-hooks": "^4.6.0",
146
150
  "eslint-plugin-react-refresh": "^0.4.3",
147
151
  "eslint-plugin-storybook": "^10.3.4",
152
+ "jsdom": "^26.1.0",
148
153
  "postcss": "8.5.6",
149
154
  "prettier-plugin-organize-imports": "^3.2.4",
150
155
  "react": "^18.2.0",
@@ -152,6 +157,7 @@
152
157
  "react-dom": "^18.2.0",
153
158
  "storybook": "^10.3.4",
154
159
  "typescript": "^5.0.2",
155
- "vite": "^6.3.5"
160
+ "vite": "^6.3.5",
161
+ "vitest": "^3.2.7"
156
162
  }
157
163
  }