asma-ui-core 3.100.1 → 3.101.1

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.
@@ -170,7 +170,7 @@ var Oe = ({ onCloseText: u = "", onMinimizeText: j = "", onExpandText: C = "", o
170
170
  }), /* @__PURE__ */ t("div", {
171
171
  className: J("flex flex-col", d && !i && "h-[87dvh]"),
172
172
  children: [/* @__PURE__ */ e("div", {
173
- className: "flex-grow overflow-y-auto",
173
+ className: "flex-grow overflow-y-auto overscroll-contain",
174
174
  children: typeof x == "function" ? x({ fullScreen: d }) : x
175
175
  }), (Array.isArray(n) && n.length || typeof n == "function") && m || L ? /* @__PURE__ */ t("div", {
176
176
  className: h("flex items-center justify-between border-0 border-t-[1px] border-solid border-delta-200 bg-white p-4", P),
@@ -152,7 +152,7 @@ var ue = (g) => {
152
152
  children: o
153
153
  })]
154
154
  }), /* @__PURE__ */ e("div", {
155
- className: a(t && "hidden", "flex flex-grow flex-col overflow-y-auto"),
155
+ className: a(t && "hidden", "flex flex-grow flex-col overflow-y-auto overscroll-contain"),
156
156
  children: O
157
157
  })]
158
158
  })
@@ -1,17 +1,18 @@
1
- import { DynamicInteractiveChipGroup as m } from "./components/DynamicInteractiveChipGroup.js";
2
- import { DynamicSelectAutocomplete as i } from "./components/DynamicSelectAutocomplete.js";
3
- import { forwardRef as n } from "react";
4
- import { jsx as o } from "react/jsx-runtime";
5
- var p = n((t, r) => {
6
- const { options: e } = t;
7
- return e.length > 0 && e.length <= 5 ? /* @__PURE__ */ o(m, {
1
+ import { DynamicInteractiveChipGroup as i } from "./components/DynamicInteractiveChipGroup.js";
2
+ import { DynamicSelectAutocomplete as n } from "./components/DynamicSelectAutocomplete.js";
3
+ import { DynamicSelectReadOnlyValue as o } from "./components/DynamicSelectReadOnlyValue.js";
4
+ import { forwardRef as l } from "react";
5
+ import { jsx as e } from "react/jsx-runtime";
6
+ var d = l((t, r) => {
7
+ const { options: m } = t;
8
+ return t.readOnly && !t.multiple ? /* @__PURE__ */ e(o, { ...t }) : m.length > 0 && m.length <= 5 ? /* @__PURE__ */ e(i, {
8
9
  ...t,
9
10
  ref: r
10
- }) : /* @__PURE__ */ o(i, {
11
+ }) : /* @__PURE__ */ e(n, {
11
12
  ...t,
12
13
  ref: r
13
14
  });
14
15
  });
15
16
  export {
16
- p as StyledDynamicSelect
17
+ d as StyledDynamicSelect
17
18
  };
@@ -0,0 +1,19 @@
1
+ import { jsx as d, jsxs as u } from "react/jsx-runtime";
2
+ var m = ({ dataTest: a, options: c, value: t, title: n, valueKey: i = "value", labelKey: o = "label", renderLabel: r }) => {
3
+ const s = (e) => typeof e == "object" ? e?.[i] : e, f = (e) => typeof e == "object" ? e?.[o]?.toString() ?? "" : e?.toString() ?? "", l = t == null ? null : c.find((e) => s(e) === s(t)) ?? t;
4
+ return /* @__PURE__ */ u("div", {
5
+ "data-testid": `${a}-read-only`,
6
+ className: "flex flex-col gap-y-1",
7
+ children: [n && /* @__PURE__ */ d("span", {
8
+ className: "text-base font-semibold text-delta-800",
9
+ children: n
10
+ }), /* @__PURE__ */ d("div", {
11
+ "data-testid": `${a}-read-only-value`,
12
+ className: "text-base/6 text-delta-700",
13
+ children: l === null ? "-" : r ? r(l) : f(l)
14
+ })]
15
+ });
16
+ };
17
+ export {
18
+ m as DynamicSelectReadOnlyValue
19
+ };
@@ -1,66 +1,72 @@
1
- import { cn as re } from "../../../helpers/cn.js";
2
- import { firstTabbable as ne } from "../../../helpers/focusable.js";
3
- import { TOP_LAYER_PROPS as ie, TOP_LAYER_RESET_STYLE as se, getOpenModalDialogAncestor as ae, shouldUsePopoverTopLayer as le, useTopLayerRef as ce } from "../../../hooks/useTopLayer.hook.js";
4
- import { StyledButton as ue } from "../../inputs/button/StyledButton.js";
5
- import { useMobileMediaQuery as de } from "../../../hooks/useMediaQuery.hook.js";
6
- import { useDebouncedValue as fe } from "../../../hooks/useDebouncedValue.hook.js";
7
- import { useFocusTrap as pe } from "../../../hooks/useFocusTrap.hook.js";
8
- import { formatResultsLabel as me } from "../bottom-sheet/formatResultsLabel.js";
9
- import { StyledBottomSheet as ge } from "../bottom-sheet/StyledBottomSheet.js";
10
- import { PopoverAnatomy as ve } from "./PopoverAnatomy.js";
11
- import { useCallback as v, useEffect as y, useId as he, useRef as T, useState as h } from "react";
12
- import { Fragment as N, jsx as l, jsxs as W } from "react/jsx-runtime";
13
- import { FloatingPortal as xe, autoUpdate as _e, flip as Pe, offset as be, shift as Re, size as ye, useDismiss as Te, useFloating as Ee, useInteractions as Me, useMergeRefs as Se } from "@floating-ui/react";
14
- var we = 240, Ae = {
1
+ import { cn as ie } from "../../../helpers/cn.js";
2
+ import { firstTabbable as se } from "../../../helpers/focusable.js";
3
+ import { TOP_LAYER_PROPS as ae, TOP_LAYER_RESET_STYLE as le, getOpenModalDialogAncestor as ce, shouldUsePopoverTopLayer as de, useTopLayerRef as ue } from "../../../hooks/useTopLayer.hook.js";
4
+ import { StyledButton as fe } from "../../inputs/button/StyledButton.js";
5
+ import { useMobileMediaQuery as pe } from "../../../hooks/useMediaQuery.hook.js";
6
+ import { useDebouncedValue as me } from "../../../hooks/useDebouncedValue.hook.js";
7
+ import { useFocusTrap as ge } from "../../../hooks/useFocusTrap.hook.js";
8
+ import { formatResultsLabel as he } from "../bottom-sheet/formatResultsLabel.js";
9
+ import { StyledBottomSheet as ve } from "../bottom-sheet/StyledBottomSheet.js";
10
+ import { PopoverAnatomy as xe } from "./PopoverAnatomy.js";
11
+ import { useCallback as v, useEffect as R, useId as _e, useRef as T, useState as l } from "react";
12
+ import { Fragment as N, jsx as c, jsxs as B } from "react/jsx-runtime";
13
+ import { FloatingPortal as be, autoUpdate as Pe, flip as ye, offset as Re, shift as Te, size as Ee, useDismiss as Me, useFloating as Se, useInteractions as we, useMergeRefs as Ae } from "@floating-ui/react";
14
+ var Oe = 240, Fe = {
15
15
  info: 472,
16
16
  action: 472
17
- }, Fe = 0.6, B = "calc(100vw - 32px)", Ie = (n, c, u) => _e(n, c, u, { elementResize: !1 }), qe = ({ dataTest: n, renderTrigger: c, variant: u = "info", title: d, children: E, viewResultsAction: M, resetAction: S, footerActions: w, resultCount: x, closeLabel: A = "Lukk", ariaLabel: F, onOpenChange: I, className: O }) => {
18
- const a = he(), L = `${a}-title`, [o, X] = h(!1), [H, z] = h(), [U, Y] = h(), f = de(), t = u === "action", $ = f && !t, k = f && t, p = v((e) => {
19
- X(e), I?.(e);
20
- }, [I]), { refs: _, floatingStyles: j, context: q } = Ee({
17
+ }, Ie = 0.6, X = "calc(100vw - 32px)", Le = (n, d, u) => Pe(n, d, u, { elementResize: !1 }), Ve = ({ dataTest: n, renderTrigger: d, variant: u = "info", title: f, children: E, viewResultsAction: M, resetAction: S, footerActions: w, resultCount: x, closeLabel: A = "Lukk", ariaLabel: O, onOpenChange: F, className: I }) => {
18
+ const a = _e(), L = `${a}-title`, [o, z] = l(!1), [H, K] = l(), [U, Y] = l(), p = pe(), t = u === "action", $ = p && !t, k = p && t, m = v((e) => {
19
+ z(e), F?.(e);
20
+ }, [F]), { refs: _, floatingStyles: j, context: q } = Se({
21
21
  open: o,
22
- onOpenChange: p,
22
+ onOpenChange: m,
23
23
  placement: "bottom-start",
24
24
  strategy: "fixed",
25
- whileElementsMounted: Ie,
25
+ whileElementsMounted: Le,
26
26
  middleware: [
27
- be(8),
28
- ...$ ? [] : [Pe({ padding: 8 })],
29
- Re({ padding: 8 }),
30
- ye({
27
+ Re(8),
28
+ ...$ ? [] : [ye({ padding: 8 })],
29
+ Te({ padding: 8 }),
30
+ Ee({
31
31
  padding: 8,
32
32
  apply({ availableHeight: e }) {
33
- Y(Math.min(e, Math.round(window.innerHeight * Fe)));
33
+ Y(Math.min(e, Math.round(window.innerHeight * Ie)));
34
34
  }
35
35
  })
36
36
  ]
37
- }), { getFloatingProps: V } = Me([Te(q, {
37
+ }), { getFloatingProps: V } = we([Me(q, {
38
38
  enabled: !k,
39
39
  escapeKey: !0,
40
40
  outsidePress: (e) => {
41
- const s = m.current;
41
+ const s = g.current;
42
42
  return !(s && e.target instanceof Node && s.contains(e.target));
43
43
  }
44
- })]), P = le(H), C = T(null), [r, G] = h(null), K = v((e) => {
44
+ })]), b = de(H), C = T(null), [r, G] = l(null), Q = v((e) => {
45
45
  C.current = e, G(e);
46
- }, []), Q = Se([ce(_.setFloating, P), K]), m = T(null), J = v((e) => {
47
- m.current = e, _.setReference(e);
46
+ }, []), J = Ae([ue(_.setFloating, b), Q]), g = T(null), Z = v((e) => {
47
+ g.current = e, _.setReference(e);
48
48
  }, [_]), i = v(() => {
49
- p(!1);
50
- }, [p]);
51
- pe(o && t && r !== null, C), y(() => {
52
- if (!r) return;
49
+ m(!1);
50
+ }, [m]);
51
+ ge(o && t && r !== null, C);
52
+ const [W, ee] = l(!1);
53
+ R(() => {
54
+ if (!r || t && !W) return;
53
55
  const e = requestAnimationFrame(() => {
54
- (t ? ne(r) : r)?.focus({ preventScroll: !0 });
56
+ (t ? se(r) : r)?.focus({ preventScroll: !0 });
55
57
  });
56
58
  return () => {
57
59
  cancelAnimationFrame(e);
58
60
  };
59
- }, [r, t]), y(() => {
61
+ }, [
62
+ r,
63
+ t,
64
+ W
65
+ ]), R(() => {
60
66
  if (!r || t) return;
61
67
  const e = (s) => {
62
- const R = s.relatedTarget;
63
- R instanceof Node && (r.contains(R) || m.current?.contains(R)) || i();
68
+ const y = s.relatedTarget;
69
+ y instanceof Node && (r.contains(y) || g.current?.contains(y)) || i();
64
70
  };
65
71
  return r.addEventListener("focusout", e), () => {
66
72
  r.removeEventListener("focusout", e);
@@ -70,15 +76,15 @@ var we = 240, Ae = {
70
76
  t,
71
77
  i
72
78
  ]);
73
- const b = T(!1);
74
- y(() => {
79
+ const P = T(!1);
80
+ R(() => {
75
81
  if (o) {
76
- b.current = !0;
82
+ P.current = !0;
77
83
  return;
78
84
  }
79
- if (!b.current) return;
80
- b.current = !1;
81
- const e = m.current;
85
+ if (!P.current) return;
86
+ P.current = !1;
87
+ const e = g.current;
82
88
  if (!e) return;
83
89
  const s = requestAnimationFrame(() => {
84
90
  document.activeElement === document.body && e.focus();
@@ -88,7 +94,7 @@ var we = 240, Ae = {
88
94
  };
89
95
  }, [o]);
90
96
  const D = {
91
- ref: J,
97
+ ref: Z,
92
98
  isOpen: o,
93
99
  triggerProps: {
94
100
  onClick: (e) => {
@@ -96,70 +102,70 @@ var we = 240, Ae = {
96
102
  i();
97
103
  return;
98
104
  }
99
- z(ae(e.currentTarget)), p(!0);
105
+ K(ce(e.currentTarget)), ee(e.detail === 0), m(!0);
100
106
  },
101
107
  "aria-expanded": o,
102
108
  "aria-controls": o ? a : void 0,
103
109
  "aria-haspopup": t ? "dialog" : void 0,
104
110
  "aria-describedby": !t && o ? a : void 0
105
111
  }
106
- }, g = (e) => typeof e == "function" ? e({ close: i }) : e, Z = fe(x, 500), ee = M ?? (x === void 0 ? void 0 : /* @__PURE__ */ l(ue, {
112
+ }, h = (e) => typeof e == "function" ? e({ close: i }) : e, te = me(x, 500), oe = M ?? (x === void 0 ? void 0 : /* @__PURE__ */ c(fe, {
107
113
  dataTest: `${n}-view-results`,
108
114
  type: "button",
109
115
  variant: "text",
110
116
  onClick: i,
111
- children: me(Z)
112
- })), te = f ? B : Ae[u], oe = f ? B : void 0;
113
- return k ? /* @__PURE__ */ W(N, { children: [c(D), /* @__PURE__ */ l(ge, {
117
+ children: he(te)
118
+ })), re = p ? X : Fe[u], ne = p ? X : void 0;
119
+ return k ? /* @__PURE__ */ B(N, { children: [d(D), /* @__PURE__ */ c(ve, {
114
120
  id: a,
115
121
  dataTest: n,
116
122
  open: o,
117
123
  onClose: i,
118
- title: d,
119
- ariaLabel: F,
124
+ title: f,
125
+ ariaLabel: O,
120
126
  viewResultsAction: M,
121
127
  resetAction: S,
122
128
  footerActions: w,
123
129
  resultCount: x,
124
130
  closeLabel: A,
125
- className: O,
131
+ className: I,
126
132
  children: E
127
- })] }) : /* @__PURE__ */ W(N, { children: [c(D), o && /* @__PURE__ */ l(xe, {
133
+ })] }) : /* @__PURE__ */ B(N, { children: [d(D), o && /* @__PURE__ */ c(be, {
128
134
  root: H,
129
- children: /* @__PURE__ */ l("div", {
135
+ children: /* @__PURE__ */ c("div", {
130
136
  ...V(),
131
- ref: Q,
137
+ ref: J,
132
138
  id: a,
133
139
  "data-test": n,
134
140
  "data-testid": n,
135
141
  role: t ? "dialog" : void 0,
136
- "aria-labelledby": t && d ? L : void 0,
137
- "aria-label": t && !d ? F : void 0,
142
+ "aria-labelledby": t && f ? L : void 0,
143
+ "aria-label": t && !f ? O : void 0,
138
144
  tabIndex: t ? void 0 : -1,
139
- ...P ? ie : {},
145
+ ...b ? ae : {},
140
146
  style: {
141
- ...P ? se : {},
147
+ ...b ? le : {},
142
148
  ...j,
143
- minWidth: we,
144
- width: oe,
145
- maxWidth: te,
149
+ minWidth: Oe,
150
+ width: ne,
151
+ maxWidth: re,
146
152
  maxHeight: U
147
153
  },
148
- className: re("z-[1300]", "box-border flex flex-col overflow-hidden rounded-lg bg-white text-delta-700 outline-none shadow-[inset_0_0_0_1px_var(--colors-delta-300),0px_4px_40px_0px_#22213366]", O),
149
- children: /* @__PURE__ */ l(ve, {
154
+ className: ie("z-[1300]", "box-border flex flex-col overflow-hidden rounded-lg bg-white text-delta-700 outline-none shadow-[inset_0_0_0_1px_var(--colors-delta-300),0px_4px_40px_0px_#22213366]", I),
155
+ children: /* @__PURE__ */ c(xe, {
150
156
  dataTest: n,
151
- title: d,
157
+ title: f,
152
158
  titleId: L,
153
- viewResultsAction: g(ee),
154
- resetAction: g(S),
155
- footerActions: g(w),
159
+ viewResultsAction: h(oe),
160
+ resetAction: h(S),
161
+ footerActions: h(w),
156
162
  closeLabel: A,
157
163
  onClose: i,
158
- children: g(E)
164
+ children: h(E)
159
165
  })
160
166
  })
161
167
  })] });
162
168
  };
163
169
  export {
164
- qe as PopoverSheet
170
+ Ve as PopoverSheet
165
171
  };
@@ -19,6 +19,9 @@ import { StyledDynamicSelectComponent } from './types';
19
19
  * are behavioral / MUI `Autocomplete` API-parity.
20
20
  *
21
21
  * **Rendering strategy:**
22
+ * - `readOnly` + single (not `multiple`) → plain text (`DynamicSelectReadOnlyValue`), whatever the
23
+ * option count: the title, then the selected label (or `-`). No chip, no input, no helper row.
24
+ * `readOnly` + `multiple` is unaffected and follows the rules below.
22
25
  * - `1–5 options` → renders as an interactive chip group (`DynamicInteractiveChipGroup`).
23
26
  * Chips behave as radio buttons (single) or checkboxes (multiple).
24
27
  * Long labels automatically switch to a vertical stacked layout.
@@ -96,7 +99,8 @@ import { StyledDynamicSelectComponent } from './types';
96
99
  * ---
97
100
  *
98
101
  * @example
99
- * // 4. Read-only display – only selected options are shown
102
+ * // 4. Read-only display – single: the selected label as plain text; multiple: only the selected
103
+ * // options, as chips
100
104
  * <StyledDynamicSelect
101
105
  * dataTest="status-readonly"
102
106
  * options={statuses}
@@ -0,0 +1,15 @@
1
+ import { DynamicSelectOption, StyledDynamicSelectProps } from '../types';
2
+ type DynamicSelectReadOnlyValueProps<TOption extends DynamicSelectOption> = Pick<StyledDynamicSelectProps<TOption>, 'dataTest' | 'options' | 'title' | 'valueKey' | 'labelKey' | 'renderLabel'> & {
3
+ value: TOption | null;
4
+ };
5
+ /**
6
+ * Read-only **single** select: the selected option as plain text under the title — no chip, no
7
+ * input field, no helper/error row (there is nothing to validate). Applies whatever the option
8
+ * count, so the ≤5 chip variant and the 6+ autocomplete variant read the same.
9
+ *
10
+ * Text = Body Base 16/24 `text-icon/body` (delta-700) at every `size`: `size` scales chips and
11
+ * buttons, and read-only draws neither. No value → `-`, the same placeholder the chip variant shows.
12
+ * Multiple selects never reach this component.
13
+ */
14
+ export declare const DynamicSelectReadOnlyValue: <TOption extends DynamicSelectOption>({ dataTest, options, value, title, valueKey, labelKey, renderLabel, }: DynamicSelectReadOnlyValueProps<TOption>) => JSX.Element;
15
+ export {};
@@ -26,7 +26,11 @@ interface DynamicSelectCommonProps<TOption extends DynamicSelectOption> {
26
26
  dataTest: string;
27
27
  /** @figmaProp option-count column — 1–5 → Chips select, 6–10 → Select (dropdown), 11+ → Autocomplete. */
28
28
  options: TOption[];
29
- /** @figmaProp State = true→"Read-only" (non-interactive; selected value(s) shown as plain chips). */
29
+ /**
30
+ * @figmaProp State = true→"Read-only" (non-interactive). Single: the selected label as plain text
31
+ * (`-` when empty), no chip, input or helper row, at any option count. Multiple: the selected
32
+ * values as plain chips.
33
+ */
30
34
  readOnly?: boolean;
31
35
  /** Prevents the built-in clear button from appearing even when a value is set. Applies to autocomplete only. */
32
36
  disableClearable?: boolean;
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "3.100.1",
6
+ "version": "3.101.1",
7
7
  "type": "module",
8
8
  "sideEffects": [
9
9
  "**/*.css",
@@ -75,6 +75,7 @@
75
75
  "vrt:report": "playwright show-report",
76
76
  "test-storybook": "npx vitest --project=storybook",
77
77
  "test:interaction": "vitest --project=interaction --run",
78
+ "test:flaky": "tsx scripts/detect-flaky.ts",
78
79
  "changeset:pre-beta": "changeset pre enter beta",
79
80
  "changeset:pre-exit": "changeset pre exit",
80
81
  "changeset:version": "changeset version",