@iress-oss/ids-components 6.2.1 → 6.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.
@@ -530,6 +530,38 @@ Some use cases:
530
530
 
531
531
  [View "ValidationSummary" example in Storybook →](https://main--691abcc79dfa560a36d0a74f.chromatic.com/?path=/story/components_patterns-form--validation-summary)
532
532
 
533
+ ### Controlling screen reader announcements
534
+
535
+ By default, `IressFormValidationSummary` uses `role="alert"` (an assertive live region), which causes screen readers to interrupt the user and read out the entire error list immediately. When using `mode="onBlur"`, a new error is added every time the user leaves a field — this can be disruptive.
536
+
537
+ You have two options for a less intrusive experience:
538
+
539
+ **Option 1 — Polite announcements via `aria-live`**
540
+
541
+ Pass `aria-live="polite"` and `role="status"` to `IressFormValidationSummary` to switch to a polite live region. Screen readers will wait for a pause in user activity before announcing changes.
542
+
543
+ ```tsx
544
+ <IressForm mode="onBlur">
545
+ <IressFormValidationSummary aria-live="polite" role="status" srOnly />
546
+ {/* fields */}
547
+ </IressForm>
548
+ ```
549
+
550
+ **Option 2 — Only announce on submit via `updateErrorSummaryOnSubmit`**
551
+
552
+ Pass `updateErrorSummaryOnSubmit` to `IressForm` (or `IressHookForm`) to prevent the summary from updating while the user is still filling in the form. The summary will only be populated — and announced — when the form is submitted.
553
+
554
+ ```tsx
555
+ <IressForm mode="onBlur" updateErrorSummaryOnSubmit>
556
+ {/* fields */}
557
+ </IressForm>
558
+ ```
559
+
560
+ | Approach | When to use |
561
+ |---|---|
562
+ | `aria-live="polite"` on `IressFormValidationSummary` | Real-time feedback is still desirable but should not interrupt the user |
563
+ | `updateErrorSummaryOnSubmit` on `IressForm` | Errors should only be announced once the user tries to submit |
564
+
533
565
  ## Migration to version 5 and beyond
534
566
 
535
567
  The previous form components contained a lot of logic to translate the HTML5 validation API to a format that matched the design system’s guidelines. This allowed users to use the default props of input such as `pattern` and `required`, and be assured that the `IressField` would display errors accordingly.
@@ -0,0 +1,327 @@
1
+ import { t as e } from "./cx-QcEwjve6.js";
2
+ import { GlobalCSSClass as t } from "./enums.js";
3
+ import { idsLogger as n } from "./helpers/utility/idsLogger.js";
4
+ import { IressIcon as r } from "./components/Icon/Icon.js";
5
+ import { IressText as i } from "./components/Text/Text.js";
6
+ import { propagateTestid as a } from "./helpers/utility/propagateTestid.js";
7
+ import { IressSpinner as o } from "./components/Spinner/Spinner.js";
8
+ import { toArray as s } from "./helpers/formatting/toArray.js";
9
+ import { useControlledState as ee } from "./hooks/useControlledState.js";
10
+ import { useResponsiveProps as te } from "./hooks/useResponsiveProps.js";
11
+ import { IressPopover as ne } from "./components/Popover/Popover.js";
12
+ import { IressInputPopover as re } from "./components/Popover/InputPopover/InputPopover.js";
13
+ import { IressAlert as ie } from "./components/Alert/Alert.js";
14
+ import { autoComplete as c } from "./components/Autocomplete/Autocomplete.styles.js";
15
+ import { getFormControlValueAsStringIfDefined as ae } from "./helpers/form/getFormControlValueAsStringIfDefined.js";
16
+ import { useNoDefaultValueInForms as oe } from "./patterns/Form/hooks/useNoDefaultValueInForms.js";
17
+ import { IressReadonly as se } from "./components/Readonly/Readonly.js";
18
+ import { IressInput as l } from "./components/Input/Input.js";
19
+ import { getValueAsEvent as ce } from "./helpers/form/getValueAsEvent.js";
20
+ import { t as le } from "./useAutocompleteSearch-BYzUn7Ag.js";
21
+ import { AutocompleteInstructions as u } from "./components/Autocomplete/components/AutocompleteInstructions.js";
22
+ import { select as ue } from "./components/Select/Select.styles.js";
23
+ import { IressInline as d } from "./components/Inline/Inline.js";
24
+ import { SelectActivator as de } from "./components/Select/components/SelectActivator.js";
25
+ import { IressSelectMenu as f } from "./components/Select/SelectMenu/SelectMenu.js";
26
+ import { SelectOptions as p } from "./components/Select/components/SelectOptions.js";
27
+ import { SelectHiddenInput as fe } from "./components/Select/components/SelectHiddenInput.js";
28
+ import { NativeSelect as pe } from "./components/Select/components/NativeSelect.js";
29
+ import { useSelectState as me } from "./components/Select/hooks/useSelectState.js";
30
+ import { forwardRef as m, useCallback as he, useEffect as h, useImperativeHandle as ge, useMemo as g, useRef as _, useState as v } from "react";
31
+ import { Fragment as _e, jsx as y, jsxs as b } from "react/jsx-runtime";
32
+ //#region src/components/Select/Select.tsx
33
+ var x = (e) => typeof e == "object" && !!e && "label" in e, S = (e, t) => {
34
+ for (let n of t) if (n.children) {
35
+ let t = S(e, n.children);
36
+ if (t) return t;
37
+ } else if (n.value !== void 0 && n.value === e) return n;
38
+ }, C = (e, t) => {
39
+ if (x(e)) return e;
40
+ if (typeof t != "function") return S(e, t) ?? (typeof e == "number" ? S(String(e), t) : void 0);
41
+ }, w = (e, t) => {
42
+ if (e !== void 0) {
43
+ if (Array.isArray(e)) {
44
+ let r = e, i = r.map((e) => C(e, t)).filter((e) => e !== void 0);
45
+ return i.length < r.length && typeof t != "function" && n(`IressSelect: ${r.length - i.length} value(s) could not be resolved to matching options and were dropped.`, "warn"), i;
46
+ }
47
+ return C(e, t);
48
+ }
49
+ }, T = m(({ align: r = "bottom-start", autoHighlight: i = !0, className: a, defaultValue: o, disabled: s, errorText: ee, footer: re, header: ie, id: c, matchActivatorWidth: ae = !0, multiSelect: l, multiSelectLimit: ce, name: u, onChange: d, onBlur: f, options: m, native: S, placeholder: C, readOnly: T, renderHiddenInput: E, renderLabel: ve, renderOptions: ye, required: D, type: O, value: k, virtualFocus: A, width: j, ...M }, N) => {
50
+ oe({
51
+ component: "IressSelect",
52
+ defaultValue: o
53
+ });
54
+ let [P, F] = v(!1), I = P && !s, [L, be] = v(""), R = g(() => w(k, m), [k, m]), z = g(() => w(o, m), [o, m]);
55
+ h(() => {
56
+ k !== void 0 && !x(k) && R === void 0 && typeof m == "function" && n("IressSelect: A primitive value was passed but cannot be resolved because options are asynchronous. Pass a LabelValueMeta object instead when using async options, otherwise the component will behave as uncontrolled.", "warn");
57
+ }, [
58
+ k,
59
+ R,
60
+ m
61
+ ]);
62
+ let { value: B, setValue: V, getValuesString: H, getLabelsString: xe } = me({
63
+ component: "IressSelect",
64
+ defaultValue: z,
65
+ multiple: l,
66
+ value: R
67
+ }), U = _(null), W = _(null), G = _(null), { value: K } = te(typeof S == "string" ? {
68
+ xs: !0,
69
+ [S]: !1
70
+ } : { xs: S }, { disabled: !S }), { append: Se, container: q, debounceThreshold: Ce, initialOptions: J, loadingDelay: Y, minSearchLength: we, onActivated: Te, onDeactivated: Ee, prepend: De, selectedOptionsText: Oe, ...X } = M, { debouncedQuery: ke, error: Ae, results: je, stopSearch: Me, loading: Z, shouldShowInstructions: Ne, shouldShowNoResults: Pe } = le({
71
+ debounceThreshold: Ce,
72
+ disabled: !P || !!K,
73
+ initialOptions: J,
74
+ loadingDelay: Y,
75
+ minSearchLength: we,
76
+ options: m,
77
+ query: L
78
+ });
79
+ ge(N, () => K ? {
80
+ focus: () => W.current?.focus(),
81
+ blur: () => W.current?.blur(),
82
+ input: W.current ?? null
83
+ } : U.current ? {
84
+ ...U.current,
85
+ focus: () => U.current?.getActivator()?.focus(),
86
+ blur: () => U.current?.getActivator()?.blur(),
87
+ hiddenInput: G.current ?? void 0,
88
+ input: G.current ?? null
89
+ } : {
90
+ hiddenInput: G.current ?? void 0,
91
+ input: G.current ?? null,
92
+ focus: () => G.current?.focus(),
93
+ blur: () => G.current?.blur()
94
+ }, [K]), h(() => {
95
+ P ? Te?.() : Ee?.();
96
+ }, [
97
+ Te,
98
+ Ee,
99
+ P
100
+ ]);
101
+ let Fe = he((e) => {
102
+ if (!f) return;
103
+ let t = e.currentTarget, n = e.relatedTarget;
104
+ !P && (!n || !t.contains(n)) && f(e), e.stopPropagation();
105
+ }, [f, P]);
106
+ if (T) return /* @__PURE__ */ y(se, {
107
+ value: H(),
108
+ ref: G,
109
+ variant: T,
110
+ name: u,
111
+ disabled: s,
112
+ required: D,
113
+ children: xe(", ")
114
+ });
115
+ if (K) {
116
+ if (m instanceof Function) throw Error("[IressSelect] The native select does not support asynchronous options. Please provide options as an array.");
117
+ if (l) throw Error("[IressSelect] The native select does not support multiple selection. Please remove the multiSelect prop or use the non-native select.");
118
+ return /* @__PURE__ */ y(pe, {
119
+ className: e(a, t.Select),
120
+ "data-testid": X["data-testid"],
121
+ disabled: s,
122
+ id: c,
123
+ name: u,
124
+ onBlur: f,
125
+ onChange: (e, t) => {
126
+ d?.(e, t?.value ?? null, t), V(t);
127
+ },
128
+ options: m,
129
+ placeholder: typeof S == "string" ? C ?? "" : C,
130
+ style: X.style,
131
+ value: B,
132
+ width: j,
133
+ ref: W
134
+ });
135
+ }
136
+ let Q = typeof m == "function", Ie = A ?? !Q, Le = O ?? (Q ? void 0 : "listbox"), $ = ue({ width: j }), Re = () => {
137
+ F(!0);
138
+ }, ze = () => {
139
+ F(!1), Me();
140
+ };
141
+ return /* @__PURE__ */ b(_e, { children: [/* @__PURE__ */ y(fe, {
142
+ "data-testid": X["data-testid"],
143
+ getValuesString: H,
144
+ name: u,
145
+ renderHiddenInput: E,
146
+ required: D,
147
+ value: B,
148
+ disabled: s,
149
+ ref: G
150
+ }), /* @__PURE__ */ y(ne, {
151
+ ...X,
152
+ activator: /* @__PURE__ */ y(de, {
153
+ append: Se,
154
+ async: Q,
155
+ disabled: s,
156
+ error: Ae,
157
+ id: c,
158
+ loading: Z,
159
+ multiSelect: l,
160
+ multiSelectLimit: ce,
161
+ onChange: d,
162
+ placeholder: C,
163
+ popoverContainer: q,
164
+ prepend: De,
165
+ renderLabel: ve,
166
+ selectedOptionsText: Oe,
167
+ setValue: V,
168
+ setShow: F,
169
+ show: P,
170
+ value: B
171
+ }),
172
+ align: r,
173
+ className: e(a, $.root, t.Select),
174
+ container: q,
175
+ contentClassName: e($.popoverContent),
176
+ contentStyle: {
177
+ ...X.contentStyle,
178
+ p: "none"
179
+ },
180
+ matchActivatorWidth: ae,
181
+ onActivated: Re,
182
+ onDeactivated: ze,
183
+ ref: U,
184
+ show: I,
185
+ type: Le,
186
+ virtualFocus: Ie,
187
+ onBlur: Fe,
188
+ children: /* @__PURE__ */ b("div", {
189
+ className: $.wrapper,
190
+ children: [
191
+ ie,
192
+ /* @__PURE__ */ y(p, {
193
+ autoHighlight: i,
194
+ debouncedQuery: ke,
195
+ error: Ae,
196
+ errorText: ee,
197
+ initialOptions: J,
198
+ loading: Z,
199
+ minSearchLength: we,
200
+ multiSelect: l,
201
+ onChange: d,
202
+ options: m,
203
+ query: L,
204
+ renderOptions: ye,
205
+ results: je,
206
+ setQuery: be,
207
+ setShow: F,
208
+ setValue: V,
209
+ shouldShowInstructions: Ne,
210
+ shouldShowNoResults: Pe,
211
+ show: I,
212
+ value: B
213
+ }),
214
+ re
215
+ ]
216
+ })
217
+ })] });
218
+ });
219
+ T.displayName = "IressSelect";
220
+ //#endregion
221
+ //#region src/components/Autocomplete/Autocomplete.tsx
222
+ var E = m(({ alwaysShowOnFocus: n, append: te = /* @__PURE__ */ y(r, { name: "search" }), autoComplete: ne = "off", autoSelect: oe = !0, className: ue, clearable: de = !0, "data-testid": p, debounceThreshold: fe, defaultValue: pe, errorText: me = /* @__PURE__ */ y(ie, {
223
+ status: "danger",
224
+ mb: "none",
225
+ variant: "full-width",
226
+ children: "An unknown error occurred. Please contact support if the error persists."
227
+ }), initialOptions: m, loadingDelay: he, limitDesktop: ge = 12, limitMobile: g = 6, minSearchLength: _, noResultsText: x, onChange: S, onClear: C, onFocus: w, options: T, popoverProps: { autoHighlight: E = !1, append: ve, prepend: ye, ...D } = {}, readOnly: O, value: k, ...A }, j) => {
228
+ let [M, N] = v(!1), { value: P, setValue: F } = ee({
229
+ component: "IressAutocomplete",
230
+ defaultValue: pe,
231
+ value: k
232
+ }), [I, L] = v(!1), { clearError: be, debouncedQuery: R, error: z, loading: B, results: V, startSearch: H, stopSearch: xe, shouldShowInstructions: U, shouldShowNoResults: W } = le({
233
+ debounceThreshold: fe,
234
+ initialOptions: m,
235
+ loadingDelay: he,
236
+ minSearchLength: _,
237
+ options: T,
238
+ query: ae(P)
239
+ });
240
+ if (h(() => {
241
+ I && !M && V.length > 0 && P && N(!0);
242
+ }, [
243
+ V.length,
244
+ M,
245
+ I,
246
+ P
247
+ ]), h(() => {
248
+ B && I && N(!0);
249
+ }, [B, I]), h(() => {
250
+ z && N(!0);
251
+ }, [z]), O) return /* @__PURE__ */ y(se, {
252
+ value: P,
253
+ variant: O
254
+ });
255
+ let G = (e, t) => {
256
+ S?.(e, t), F(t), L(!!t);
257
+ }, K = (e) => {
258
+ C?.(e), F("");
259
+ }, Se = (e) => {
260
+ w?.(e), m?.length && N(!0);
261
+ }, q = (e) => {
262
+ let t = s(e)?.[0];
263
+ S?.(ce(t?.label), t?.label, t), F(t?.label), N(!1), L(!1);
264
+ }, Ce = () => {
265
+ (!n || !P) && xe(), be(), N(!1), P && L(!1);
266
+ }, J = (e) => {
267
+ A.onKeyDown?.(e), e.key === "ArrowDown" && (!M || !I) && (V.length || H(!0), L(!0), N(!0));
268
+ }, Y = c({ isEmpty: V.length === 0 && !B && !z && !U && !W });
269
+ return /* @__PURE__ */ b(re, {
270
+ ...D,
271
+ activator: /* @__PURE__ */ y(l, {
272
+ ...A,
273
+ append: te,
274
+ autoComplete: ne,
275
+ clearable: de,
276
+ "data-testid": a(p, "input"),
277
+ onChange: G,
278
+ onClear: K,
279
+ onFocus: Se,
280
+ onKeyDown: J,
281
+ value: P,
282
+ ref: j
283
+ }),
284
+ autoHighlight: E,
285
+ className: e(ue, D.className, Y.root, t.Autocomplete),
286
+ contentClassName: e(D.contentClassName, Y.popoverContent),
287
+ contentStyle: D.contentStyle,
288
+ "data-testid": p,
289
+ minLength: 0,
290
+ onActivated: () => (I || n) && N(!0),
291
+ onDeactivated: Ce,
292
+ show: M,
293
+ type: "listbox",
294
+ focusStartIndex: 0,
295
+ children: [
296
+ B && !V.length && /* @__PURE__ */ b(d, {
297
+ gap: "sm",
298
+ verticalAlign: "middle",
299
+ p: "spacing.3",
300
+ children: [/* @__PURE__ */ y(o, { color: "colour.neutral.70" }), /* @__PURE__ */ y(i, {
301
+ color: "colour.neutral.70",
302
+ children: "Loading results..."
303
+ })]
304
+ }),
305
+ V.length > 0 && /* @__PURE__ */ b(_e, { children: [
306
+ ye,
307
+ /* @__PURE__ */ y(f, {
308
+ changeOnBlur: oe,
309
+ className: e(Y.optionList),
310
+ "data-testid": a(p, "menu"),
311
+ items: V,
312
+ limitDesktop: ge,
313
+ limitMobile: g,
314
+ onChange: q,
315
+ selected: { label: R }
316
+ }),
317
+ ve
318
+ ] }),
319
+ z && me,
320
+ U && !z && /* @__PURE__ */ y(u, { minSearchLength: _ ?? 1 }),
321
+ W && !z && x
322
+ ]
323
+ });
324
+ });
325
+ E.displayName = "IressAutocomplete";
326
+ //#endregion
327
+ export { T as n, E as t };
@@ -1,2 +1,2 @@
1
- import { t as e } from "../../Autocomplete-DKufjQU5.js";
1
+ import { t as e } from "../../Autocomplete-ZqkibVwt.js";
2
2
  export { e as IressAutocomplete };
@@ -1,4 +1,4 @@
1
1
  import { autoComplete as e } from "./Autocomplete.styles.js";
2
2
  import { t } from "../../useAutocompleteSearch-BYzUn7Ag.js";
3
- import { t as n } from "../../Autocomplete-DKufjQU5.js";
3
+ import { t as n } from "../../Autocomplete-ZqkibVwt.js";
4
4
  export { n as IressAutocomplete, e as autoComplete, t as useAutocompleteSearch };
@@ -40,6 +40,12 @@ export type IressFieldProps<E extends 'div' | 'fieldset' = 'div', ELabel extends
40
40
  * Validation errors to be displayed above the field, an array of validation messages to be displayed in `IressValidationSummary`.
41
41
  */
42
42
  errorMessages?: ValidationMessageObj[];
43
+ /**
44
+ * ID for the error container element, used to associate the error message with the form control via `aria-describedby`.
45
+ * When `error` or `errorMessages` are present and `htmlFor` is set, this is automatically derived as `${htmlFor}-error`.
46
+ * Override only if you need a custom error container ID.
47
+ */
48
+ errorId?: string;
43
49
  /**
44
50
  * Renders the group in a read-only state (no asterisk symbol).
45
51
  * Use `'locked'` when the control is read-only due to permissions.
@@ -56,6 +62,6 @@ export type IressFieldProps<E extends 'div' | 'fieldset' = 'div', ELabel extends
56
62
  supplementary?: ReactNode;
57
63
  };
58
64
  export declare const IressField: {
59
- ({ children, className, "data-testid": dataTestId, error, errorMessages, hiddenLabel, hint, horizontal, label, labelWidth, required, readOnly, removeErrorMargin, supplementary, ...restProps }: IressFieldProps): import("react/jsx-runtime").JSX.Element;
65
+ ({ children, className, "data-testid": dataTestId, error, errorId, errorMessages, hiddenLabel, hint, horizontal, label, labelWidth, required, readOnly, removeErrorMargin, supplementary, ...restProps }: IressFieldProps): import("react/jsx-runtime").JSX.Element;
60
66
  displayName: string;
61
67
  };
@@ -12,57 +12,58 @@ import { FieldHint as u } from "./components/FieldHint.js";
12
12
  import { isValidElement as d } from "react";
13
13
  import { jsx as f, jsxs as p } from "react/jsx-runtime";
14
14
  //#region src/components/Field/Field.tsx
15
- var m = ({ children: m, className: h, "data-testid": g, error: _, errorMessages: v, hiddenLabel: y, hint: b, horizontal: x, label: S, labelWidth: C, required: w, readOnly: T, removeErrorMargin: E = !1, supplementary: D, ...O }) => {
16
- let { htmlFor: k } = O, A;
17
- A = k === void 0 && d(m) ? o(m)[0].props.id : k;
18
- let j = c.raw({
19
- hasError: !!_ || !!v?.length,
20
- hasHint: !!b,
21
- hiddenLabel: y,
22
- horizontal: x,
15
+ var m = ({ children: m, className: h, "data-testid": g, error: _, errorId: v, errorMessages: y, hiddenLabel: b, hint: x, horizontal: S, label: C, labelWidth: w, required: T, readOnly: E, removeErrorMargin: D = !1, supplementary: O, ...k }) => {
16
+ let { htmlFor: A } = k, j;
17
+ j = A === void 0 && d(m) ? o(m)[0].props.id : A;
18
+ let M = !!_ || !!y?.length, N = v ?? (M && j ? `${j}-error` : void 0), P = c.raw({
19
+ hasError: M,
20
+ hasHint: !!x,
21
+ hiddenLabel: b,
22
+ horizontal: S,
23
23
  multipleFields: !1,
24
- removeErrorMargin: E
25
- }), [M, N] = n(O), P = !!T, F = () => {
24
+ removeErrorMargin: D
25
+ }), [F, I] = n(k), L = !!E, R = () => {
26
26
  let t = /* @__PURE__ */ f(s, {
27
- className: e(j.label),
27
+ className: e(P.label),
28
28
  "data-testid": a(g, "label"),
29
- hiddenLabel: y,
30
- htmlFor: A,
31
- readOnly: T,
32
- required: !P && !!w,
33
- children: S
29
+ hiddenLabel: b,
30
+ htmlFor: j,
31
+ readOnly: E,
32
+ required: !L && !!T,
33
+ children: C
34
34
  });
35
- return b ? /* @__PURE__ */ f(u, {
36
- hint: b,
37
- horizontal: x,
38
- hiddenLabel: y,
35
+ return x ? /* @__PURE__ */ f(u, {
36
+ hint: x,
37
+ horizontal: S,
38
+ hiddenLabel: b,
39
39
  dataTestId: g,
40
40
  children: t
41
41
  }) : t;
42
42
  };
43
43
  return /* @__PURE__ */ p(r.div, {
44
- className: t(h, e(j.root, M), i.Field),
45
- style: { ...x && C && { gridTemplateColumns: `${C} 1fr` } },
44
+ className: t(h, e(P.root, F), i.Field),
45
+ style: { ...S && w && { gridTemplateColumns: `${w} 1fr` } },
46
46
  "data-testid": g,
47
- ...N,
47
+ ...I,
48
48
  children: [
49
49
  /* @__PURE__ */ f(r.div, {
50
- className: e(j.labelContainer),
51
- children: F()
50
+ className: e(P.labelContainer),
51
+ children: R()
52
52
  }),
53
53
  /* @__PURE__ */ f(r.div, {
54
- className: e(j.fieldContainer),
54
+ className: e(P.fieldContainer),
55
55
  children: /* @__PURE__ */ f("div", {
56
- className: e(j.element),
56
+ className: e(P.element),
57
57
  children: m
58
58
  })
59
59
  }),
60
60
  /* @__PURE__ */ f(l, {
61
- className: e(j.footer),
61
+ className: e(P.footer),
62
62
  "data-testid": a(g, "error"),
63
63
  error: _,
64
- errorMessages: v,
65
- supplementary: D
64
+ errorId: N,
65
+ errorMessages: y,
66
+ supplementary: O
66
67
  })
67
68
  ]
68
69
  });
@@ -6,6 +6,10 @@ export interface FieldFooterProps extends IressStyledProps {
6
6
  * Validation error to be displayed above the field.
7
7
  */
8
8
  error?: ReactNode;
9
+ /**
10
+ * ID for the error container element, used to associate the error message with the form control via `aria-describedby`.
11
+ */
12
+ errorId?: string;
9
13
  /**
10
14
  * Validation errors to be displayed above the field, an array of validation messages to be displayed in `IressValidationSummary`.
11
15
  */
@@ -20,6 +24,6 @@ export interface FieldFooterProps extends IressStyledProps {
20
24
  supplementary?: ReactNode;
21
25
  }
22
26
  export declare const FieldFooter: {
23
- ({ className, "data-testid": dataTestId, error, errorMessages, multipleFields, supplementary, ...restProps }: FieldFooterProps): import("react/jsx-runtime").JSX.Element | null;
27
+ ({ className, "data-testid": dataTestId, error, errorId, errorMessages, multipleFields, supplementary, ...restProps }: FieldFooterProps): import("react/jsx-runtime").JSX.Element | null;
24
28
  displayName: string;
25
29
  };
@@ -12,31 +12,32 @@ import { jsx as d, jsxs as f } from "react/jsx-runtime";
12
12
  var p = (e) => /* @__PURE__ */ d(r, {
13
13
  name: "cancel",
14
14
  ...e
15
- }), m = ({ className: r, "data-testid": m, error: h, errorMessages: g = [], multipleFields: _, supplementary: v, ...y }) => {
16
- let b = a({ multipleFields: _ }), x = u(null), S = u(null), C = l(() => !!h || g.length > 0, [h, g.length]);
15
+ }), m = ({ className: r, "data-testid": m, error: h, errorId: g, errorMessages: _ = [], multipleFields: v, supplementary: y, ...b }) => {
16
+ let x = a({ multipleFields: v }), S = u(null), C = u(null), w = l(() => !!h || _.length > 0, [h, _.length]);
17
17
  return c(() => {
18
- if (!x.current || S.current === C) {
19
- S.current = C;
18
+ if (!S.current || C.current === w) {
19
+ C.current = w;
20
20
  return;
21
21
  }
22
- x.current.classList.remove(e({ animationStyle: "field-footer" })), x.current.offsetHeight, S.current = C, x.current.classList.add(e({ animationStyle: "field-footer" }));
23
- }, [C]), !v && !C ? null : /* @__PURE__ */ f(n.div, {
24
- ...y,
25
- className: t(r, b.footer),
26
- ref: x,
27
- children: [C && /* @__PURE__ */ d(s, {
22
+ S.current.classList.remove(e({ animationStyle: "field-footer" })), S.current.offsetHeight, C.current = w, S.current.classList.add(e({ animationStyle: "field-footer" }));
23
+ }, [w]), !y && !w ? null : /* @__PURE__ */ f(n.div, {
24
+ ...b,
25
+ className: t(r, x.footer),
26
+ ref: S,
27
+ children: [w && /* @__PURE__ */ d(s, {
28
+ id: g,
28
29
  itemStyle: { textStyle: "typography.body.sm" },
29
- messages: o(g, "message"),
30
+ messages: o(_, "message"),
30
31
  "data-testid": m,
31
32
  prefix: /* @__PURE__ */ d(p, {
32
33
  "aria-label": "Error: ",
33
- className: b.footerIcon
34
+ className: x.footerIcon
34
35
  }),
35
36
  visiblePrefix: !0,
36
37
  children: h
37
- }), !C && /* @__PURE__ */ d(i, {
38
- className: b.supplementary,
39
- children: v
38
+ }), !w && /* @__PURE__ */ d(i, {
39
+ className: x.supplementary,
40
+ children: y
40
41
  })]
41
42
  });
42
43
  };
@@ -1,2 +1,2 @@
1
- import { n as e } from "../../Autocomplete-DKufjQU5.js";
1
+ import { n as e } from "../../Autocomplete-ZqkibVwt.js";
2
2
  export { e as IressSelect };
@@ -30,6 +30,6 @@ export interface IressSelectTagsProps extends Omit<IressSelectActivatorProps, 'w
30
30
  limit?: number;
31
31
  }
32
32
  export declare const IressSelectTags: {
33
- ({ append, className, "data-testid": dataTestId, id, limit, onDelete, onDeleteAll, onToggleActions, placeholder, prepend, selected, selectedOptionsText, ...restProps }: IressSelectTagsProps): import("react/jsx-runtime").JSX.Element;
33
+ ({ append, className, "data-testid": dataTestId, id, limit, onDelete, onDeleteAll, onToggleActions, placeholder, popoverContainer, prepend, selected, selectedOptionsText, ...restProps }: IressSelectTagsProps): import("react/jsx-runtime").JSX.Element;
34
34
  displayName: string;
35
35
  };
@@ -26,25 +26,25 @@ var S = (e, t) => {
26
26
  let e = r.indexOf(t.currentTarget), i = r.filter((e) => e !== t.currentTarget), a = Math.max(e - 1, 0);
27
27
  !i[a] && i[0] ? i[0].focus() : i[0] ? i[a].focus() : n?.focus();
28
28
  }
29
- }, C = ({ "data-testid": e, limit: t = 5, onDelete: i, onDeleteAll: o, onToggleActions: s, selectedArray: g, selectedOptionsText: v }) => {
30
- let [C, w] = y(!1), T = c(), E = f(), D = _((e, t) => {
31
- i?.(g.find((t) => t.label === e), t), t.stopPropagation(), S(T, t);
29
+ }, C = ({ "data-testid": e, limit: t = 5, onDelete: i, onDeleteAll: o, onToggleActions: s, popoverContainer: g, selectedArray: v, selectedOptionsText: C }) => {
30
+ let [w, T] = y(!1), E = c(), D = f(), O = _((e, t) => {
31
+ i?.(v.find((t) => t.label === e), t), t.stopPropagation(), S(E, t);
32
32
  }, [
33
33
  i,
34
- T,
35
- g
36
- ]), O = _((e) => {
37
- o?.(e), T?.getFocusableActivator()?.focus();
38
- }, [o, T]);
39
- return C && g.length || !t || g.length <= t ? g.map((t) => /* @__PURE__ */ b(p, {
40
- className: E.tag,
34
+ E,
35
+ v
36
+ ]), k = _((e) => {
37
+ o?.(e), E?.getFocusableActivator()?.focus();
38
+ }, [o, E]);
39
+ return w && v.length || !t || v.length <= t ? v.map((t) => /* @__PURE__ */ b(p, {
40
+ className: D.tag,
41
41
  "data-testid": a(e, "tag"),
42
42
  deleteButtonText: `Delete ${t.label}`,
43
- onDelete: D,
43
+ onDelete: O,
44
44
  compact: !0,
45
45
  children: t.label
46
46
  }, u(t.value) ?? t.label)) : /* @__PURE__ */ b(p, {
47
- className: E.tag,
47
+ className: D.tag,
48
48
  "data-testid": a(e, "tag"),
49
49
  deleteButton: /* @__PURE__ */ b(l, {
50
50
  activator: /* @__PURE__ */ b(r, {
@@ -56,55 +56,56 @@ var S = (e, t) => {
56
56
  }),
57
57
  onActivated: () => s?.(!0),
58
58
  onClick: (e) => {
59
- e.stopPropagation(), S(T, e);
59
+ e.stopPropagation(), S(E, e);
60
60
  },
61
61
  onDeactivated: () => s?.(!1),
62
- container: document.body,
62
+ container: g ?? document.body,
63
63
  align: "bottom-end",
64
64
  contentStyle: { p: "none" },
65
65
  virtualFocus: !0,
66
66
  children: /* @__PURE__ */ x(m, { children: [/* @__PURE__ */ b(h, {
67
- onClick: () => w(!0),
67
+ onClick: () => T(!0),
68
68
  children: "Expand all"
69
69
  }), /* @__PURE__ */ b(h, {
70
- onClick: O,
70
+ onClick: k,
71
71
  children: "Delete all"
72
72
  })] })
73
73
  }),
74
74
  compact: !0,
75
- children: d(g, v)
75
+ children: d(v, C)
76
76
  });
77
- }, w = ({ append: n = "", className: r, "data-testid": a, id: s, limit: c = 5, onDelete: l, onDeleteAll: u, onToggleActions: d, placeholder: p, prepend: m, selected: h, selectedOptionsText: _ = "{{numOptions}} selected", ...y }) => {
78
- let S = v(() => o(h), [h]), w = !S.length && p, T = !!S.length, E = f({ showDefaultChevron: n == null || n === "" || !n });
77
+ }, w = ({ append: n = "", className: r, "data-testid": a, id: s, limit: c = 5, onDelete: l, onDeleteAll: u, onToggleActions: d, placeholder: p, popoverContainer: m, prepend: h, selected: _, selectedOptionsText: y = "{{numOptions}} selected", ...S }) => {
78
+ let w = v(() => o(_), [_]), T = !w.length && p, E = !!w.length, D = f({ showDefaultChevron: n == null || n === "" || !n });
79
79
  return /* @__PURE__ */ x(i, {
80
- ...y,
80
+ ...S,
81
81
  id: s,
82
82
  tabIndex: 0,
83
- className: e(r, E.root, t.FormElementInner, t.SelectTags),
83
+ className: e(r, D.root, t.FormElementInner, t.SelectTags),
84
84
  children: [
85
- m && /* @__PURE__ */ b("span", {
86
- className: E.prepend,
87
- children: m
85
+ h && /* @__PURE__ */ b("span", {
86
+ className: D.prepend,
87
+ children: h
88
88
  }),
89
- w && /* @__PURE__ */ b(i, {
90
- className: E.placeholder,
89
+ T && /* @__PURE__ */ b(i, {
90
+ className: D.placeholder,
91
91
  children: p
92
92
  }),
93
- T && /* @__PURE__ */ b(g, {
93
+ E && /* @__PURE__ */ b(g, {
94
94
  gap: "sm",
95
- className: E.tagsList,
95
+ className: D.tagsList,
96
96
  children: /* @__PURE__ */ b(C, {
97
97
  "data-testid": a,
98
98
  limit: c,
99
99
  onDelete: l,
100
100
  onDeleteAll: u,
101
101
  onToggleActions: d,
102
- selectedArray: S,
103
- selectedOptionsText: _
102
+ popoverContainer: m,
103
+ selectedArray: w,
104
+ selectedOptionsText: y
104
105
  })
105
106
  }),
106
107
  /* @__PURE__ */ b("button", {
107
- className: E.append,
108
+ className: D.append,
108
109
  role: "combobox",
109
110
  "aria-label": "Select options",
110
111
  children: n
@@ -29,7 +29,7 @@ var f = l(({ className: l, "data-testid": f, options: p, onChange: m, placeholde
29
29
  m?.(e, t);
30
30
  },
31
31
  ref: b,
32
- value: o(_?.value ?? _?.label),
32
+ value: o(_?.value ?? _?.label) ?? "",
33
33
  children: [h !== void 0 && /* @__PURE__ */ u("option", {
34
34
  value: "",
35
35
  children: h
@@ -2,6 +2,7 @@ import { IressSelectProps, SelectLabelRenderProps } from '../Select';
2
2
  import { LabelValueMeta } from '../../../interfaces';
3
3
  import { ReactNode } from 'react';
4
4
  import { IressInputProps } from '../../Input';
5
+ import { FloatingUIContainer } from '../../../types';
5
6
  export interface IressSelectActivatorProps {
6
7
  /**
7
8
  * Append content.
@@ -12,6 +13,12 @@ export interface IressSelectActivatorProps {
12
13
  * Placeholder, shown when there is nothing selected.
13
14
  */
14
15
  placeholder?: ReactNode;
16
+ /**
17
+ * The container element to render the multiselect tags actions popover into.
18
+ * Useful when rendering inside a Shadow DOM or a custom portal root.
19
+ * Defaults to `document.body`. Pass `null` to render the popover inline.
20
+ */
21
+ popoverContainer?: FloatingUIContainer;
15
22
  /**
16
23
  * Prepend content.
17
24
  */
@@ -30,12 +37,12 @@ export interface IressSelectActivatorProps {
30
37
  */
31
38
  width?: IressInputProps['width'];
32
39
  }
33
- interface SelectActivatorProps<TMultiple extends boolean = false> extends Pick<IressSelectProps<TMultiple>, 'disabled' | 'id' | 'multiSelect' | 'multiSelectLimit' | 'onChange' | 'placeholder' | 'renderLabel' | 'append' | 'prepend' | 'selectedOptionsText'>, Omit<SelectLabelRenderProps<TMultiple>, 'close'> {
40
+ interface SelectActivatorProps<TMultiple extends boolean = false> extends Pick<IressSelectProps<TMultiple>, 'disabled' | 'id' | 'multiSelect' | 'multiSelectLimit' | 'onChange' | 'placeholder' | 'renderLabel' | 'append' | 'prepend' | 'selectedOptionsText'>, Pick<IressSelectActivatorProps, 'popoverContainer'>, Omit<SelectLabelRenderProps<TMultiple>, 'close'> {
34
41
  async?: boolean;
35
42
  setShow: (show: boolean) => void;
36
43
  }
37
44
  export declare const SelectActivator: {
38
- <TMultiple extends boolean = false>({ append, async, id, disabled, error, loading, multiSelect, multiSelectLimit, onChange, placeholder, prepend, renderLabel, selectedOptionsText, setShow, setValue, show, value, }: SelectActivatorProps<TMultiple>): import("react/jsx-runtime").JSX.Element;
45
+ <TMultiple extends boolean = false>({ append, async, id, disabled, error, loading, multiSelect, multiSelectLimit, onChange, placeholder, popoverContainer, prepend, renderLabel, selectedOptionsText, setShow, setValue, show, value, }: SelectActivatorProps<TMultiple>): import("react/jsx-runtime").JSX.Element;
39
46
  displayName: string;
40
47
  };
41
48
  export {};
@@ -5,45 +5,46 @@ import { IressSelectTags as r } from "../SelectTags/SelectTags.js";
5
5
  import { toPrimitiveValue as i } from "../helpers/toPrimitiveValue.js";
6
6
  import { jsx as a } from "react/jsx-runtime";
7
7
  //#region src/components/Select/components/SelectActivator.tsx
8
- var o = ({ append: o, async: s, id: c, disabled: l, error: u, loading: d, multiSelect: f, multiSelectLimit: p, onChange: m, placeholder: h, prepend: g, renderLabel: _, selectedOptionsText: v, setShow: y, setValue: b, show: x, value: S }) => _ ? _({
9
- close: () => y(!1),
8
+ var o = ({ append: o, async: s, id: c, disabled: l, error: u, loading: d, multiSelect: f, multiSelectLimit: p, onChange: m, placeholder: h, popoverContainer: g, prepend: _, renderLabel: v, selectedOptionsText: y, setShow: b, setValue: x, show: S, value: C }) => v ? v({
9
+ close: () => b(!1),
10
10
  disabled: l,
11
11
  error: u,
12
12
  loading: d,
13
- setValue: b,
14
- show: x,
15
- value: S
13
+ setValue: x,
14
+ show: S,
15
+ value: C
16
16
  }) : f ? /* @__PURE__ */ a(r, {
17
17
  append: o,
18
18
  id: c,
19
19
  limit: p,
20
20
  onDelete: (n) => {
21
21
  if (!n) return;
22
- let r = e(S).filter((e) => e.label !== n.label);
23
- b(r);
22
+ let r = e(C).filter((e) => e.label !== n.label);
23
+ x(r);
24
24
  let a = i(r);
25
25
  m?.(t(a), a, r);
26
26
  },
27
27
  onDeleteAll: () => {
28
28
  let e = [];
29
- b(e);
29
+ x(e);
30
30
  let n = i(e);
31
31
  m?.(t(n), n, e);
32
32
  },
33
- onToggleActions: () => y(!1),
33
+ onToggleActions: () => b(!1),
34
34
  placeholder: h,
35
- prepend: g,
36
- selected: S,
37
- selectedOptionsText: v
35
+ popoverContainer: g,
36
+ prepend: _,
37
+ selected: C,
38
+ selectedOptionsText: y
38
39
  }) : /* @__PURE__ */ a(n, {
39
40
  append: o,
40
41
  id: c,
41
42
  disabled: l,
42
43
  placeholder: h,
43
- prepend: g,
44
+ prepend: _,
44
45
  role: s ? void 0 : "combobox",
45
- selected: S,
46
- selectedOptionsText: v
46
+ selected: C,
47
+ selectedOptionsText: y
47
48
  });
48
49
  o.displayName = "SelectActivator";
49
50
  //#endregion
@@ -6,7 +6,7 @@ import { IressSelectHeading as i } from "./SelectHeading/SelectHeading.js";
6
6
  import { IressSelectMenu as a } from "./SelectMenu/SelectMenu.js";
7
7
  import { IressSelectSearchInput as o } from "./SelectSearchInput/SelectSearchInput.js";
8
8
  import { nativeSelect as s } from "./components/NativeSelect.styles.js";
9
- import { n as c } from "../../Autocomplete-DKufjQU5.js";
9
+ import { n as c } from "../../Autocomplete-ZqkibVwt.js";
10
10
  import { IressSelectBody as l } from "./SelectBody/SelectBody.js";
11
11
  import { IressSelectCreate as u } from "./SelectCreate/SelectCreate.js";
12
12
  export { c as IressSelect, l as IressSelectBody, u as IressSelectCreate, i as IressSelectHeading, t as IressSelectLabel, a as IressSelectMenu, r as IressSelectSearch, o as IressSelectSearchInput, n as IressSelectTags, s as nativeSelect, e as select };
package/dist/main.js CHANGED
@@ -66,7 +66,7 @@ import { IressSelectHeading as Ae } from "./components/Select/SelectHeading/Sele
66
66
  import { IressSelectMenu as je } from "./components/Select/SelectMenu/SelectMenu.js";
67
67
  import { IressSelectSearchInput as Me } from "./components/Select/SelectSearchInput/SelectSearchInput.js";
68
68
  import { nativeSelect as Ne } from "./components/Select/components/NativeSelect.styles.js";
69
- import { n as Pe, t as Fe } from "./Autocomplete-DKufjQU5.js";
69
+ import { n as Pe, t as Fe } from "./Autocomplete-ZqkibVwt.js";
70
70
  import { IressSelectBody as Ie } from "./components/Select/SelectBody/SelectBody.js";
71
71
  import { IressSelectCreate as Le } from "./components/Select/SelectCreate/SelectCreate.js";
72
72
  import { avatar as Re } from "./components/Avatar/Avatar.styles.js";
@@ -55,6 +55,15 @@ export interface FormFieldRenderProps<T extends FieldValues> extends ControllerR
55
55
  * ID of the field. It is automatically generated based on the name of the field and its parent form.
56
56
  */
57
57
  id: string;
58
+ /**
59
+ * References the ID of the error message container when the field has a validation error,
60
+ * so that assistive technologies can associate the error with the control.
61
+ */
62
+ 'aria-describedby'?: string;
63
+ /**
64
+ * Set to `true` when the field has a validation error, indicating an invalid state to assistive technologies.
65
+ */
66
+ 'aria-invalid'?: boolean;
58
67
  }
59
68
  /**
60
69
  * Props for the `IressFormField` `render` prop, second argument.
@@ -27,21 +27,26 @@ var f = ({ control: f, defaultValue: p, name: m, render: h, renderSupplementary:
27
27
  m,
28
28
  b
29
29
  ]);
30
- let O = {
31
- ...i(w),
32
- id: `${S.id}__${m}`
33
- }, k = {
30
+ let O = i(w), k = `${S.id}__${m}-error`, A = !!D && !b, j = {
31
+ ...O,
32
+ id: `${S.id}__${m}`,
33
+ ...A ? {
34
+ "aria-describedby": k,
35
+ "aria-invalid": !0
36
+ } : {}
37
+ }, M = {
34
38
  formState: T,
35
39
  fieldState: E
36
40
  };
37
41
  return /* @__PURE__ */ l(t, {
38
- errorMessages: D && !b ? [{ message: D }] : void 0,
42
+ errorMessages: A ? [{ message: D }] : void 0,
39
43
  htmlFor: `${S.id}__${m}`,
40
44
  readOnly: b,
41
45
  required: !!C?.required,
42
- supplementary: /* @__PURE__ */ u(c, { children: [g?.(O, k), y] }),
46
+ supplementary: /* @__PURE__ */ u(c, { children: [g?.(j, M), y] }),
43
47
  ...x,
44
- children: h(O, k)
48
+ errorId: k,
49
+ children: h(j, M)
45
50
  });
46
51
  };
47
52
  f.displayName = "IressFormField";
@@ -13,6 +13,6 @@ export type IressFormValidationSummaryProps = Omit<IressValidationSummaryProps,
13
13
  * Validation summary messages based on the form context from react-hook-form
14
14
  */
15
15
  export declare const IressFormValidationSummary: {
16
- ({ actions, children, "data-testid": testId, footer, heading, itemStyle, icon, srOnly, variant, ...restProps }: IressFormValidationSummaryProps): import("react/jsx-runtime").JSX.Element;
16
+ ({ actions, children, "data-testid": testId, footer, heading, itemStyle, icon, srOnly, variant, role, "aria-live": ariaLive, ...restProps }: IressFormValidationSummaryProps): import("react/jsx-runtime").JSX.Element;
17
17
  displayName: string;
18
18
  };
@@ -13,27 +13,31 @@ var c = e("div", { base: {
13
13
  } }, { defaultProps: {
14
14
  role: "alert",
15
15
  tabIndex: -1
16
- } }), l = ({ actions: e, children: l, "data-testid": u, footer: d, heading: f = /* @__PURE__ */ s("h3", { children: "There was a problem submitting this form" }), itemStyle: p, icon: m, srOnly: h, variant: g, ..._ }) => {
17
- let v = o(r);
18
- if (!v) throw Error("IressFormValidationSummary must be used within a IressForm");
19
- let y = Object.entries(v.errorMessages).filter(([, e]) => !!e);
20
- if (y.length === 0 || l) return /* @__PURE__ */ s(c, {
16
+ } }), l = ({ actions: e, children: l, "data-testid": u, footer: d, heading: f = /* @__PURE__ */ s("h3", { children: "There was a problem submitting this form" }), itemStyle: p, icon: m, srOnly: h, variant: g, role: _, "aria-live": v, ...y }) => {
17
+ let b = o(r);
18
+ if (!b) throw Error("IressFormValidationSummary must be used within a IressForm");
19
+ let x = Object.entries(b.errorMessages).filter(([, e]) => !!e);
20
+ if (x.length === 0 || l) return /* @__PURE__ */ s(c, {
21
21
  "data-testid": u,
22
22
  srOnly: h,
23
- ref: v.setFocusOnError,
23
+ ref: b.setFocusOnError,
24
+ ..._ !== void 0 && { role: _ },
25
+ ...v !== void 0 && { "aria-live": v },
24
26
  children: l
25
27
  });
26
- let b = y.map(([e, t]) => {
27
- let n = `${v?.id}__${e}`, r = document.getElementById(n), i = r?.labels, o = Array.from(i ?? []), s = r?.closest("fieldset")?.querySelector("legend");
28
+ let S = x.map(([e, t]) => {
29
+ let n = `${b?.id}__${e}`, r = document.getElementById(n), i = r?.labels, o = Array.from(i ?? []), s = r?.closest("fieldset")?.querySelector("legend");
28
30
  return {
29
31
  linkToTarget: n,
30
32
  message: `${`${o[0]?.dataset?.name ?? s?.dataset?.name ?? a(e)}: `}${t}`
31
33
  };
32
34
  });
33
35
  return /* @__PURE__ */ s(c, {
34
- ref: v.setFocusOnError,
36
+ ref: b.setFocusOnError,
35
37
  "data-testid": u,
36
38
  srOnly: h,
39
+ ..._ !== void 0 && { role: _ },
40
+ ...v !== void 0 && { "aria-live": v },
37
41
  children: /* @__PURE__ */ s(n, {
38
42
  actions: e,
39
43
  footer: d,
@@ -44,13 +48,13 @@ var c = e("div", { base: {
44
48
  variant: g,
45
49
  multiLine: !0,
46
50
  children: /* @__PURE__ */ s(i, {
47
- ..._,
51
+ ...y,
48
52
  "data-testid": t(u, "messages"),
49
53
  itemStyle: {
50
54
  "data-testid": t(u, "error"),
51
55
  ...p
52
56
  },
53
- messages: b
57
+ messages: S
54
58
  })
55
59
  })
56
60
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iress-oss/ids-components",
3
- "version": "6.2.1",
3
+ "version": "6.3.0",
4
4
  "description": "Iress React Component Library",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -1,324 +0,0 @@
1
- import { t as e } from "./cx-QcEwjve6.js";
2
- import { GlobalCSSClass as t } from "./enums.js";
3
- import { idsLogger as n } from "./helpers/utility/idsLogger.js";
4
- import { IressIcon as r } from "./components/Icon/Icon.js";
5
- import { IressText as i } from "./components/Text/Text.js";
6
- import { propagateTestid as a } from "./helpers/utility/propagateTestid.js";
7
- import { IressSpinner as o } from "./components/Spinner/Spinner.js";
8
- import { toArray as s } from "./helpers/formatting/toArray.js";
9
- import { useControlledState as c } from "./hooks/useControlledState.js";
10
- import { useResponsiveProps as ee } from "./hooks/useResponsiveProps.js";
11
- import { IressPopover as te } from "./components/Popover/Popover.js";
12
- import { IressInputPopover as ne } from "./components/Popover/InputPopover/InputPopover.js";
13
- import { IressAlert as re } from "./components/Alert/Alert.js";
14
- import { autoComplete as l } from "./components/Autocomplete/Autocomplete.styles.js";
15
- import { getFormControlValueAsStringIfDefined as ie } from "./helpers/form/getFormControlValueAsStringIfDefined.js";
16
- import { useNoDefaultValueInForms as ae } from "./patterns/Form/hooks/useNoDefaultValueInForms.js";
17
- import { IressReadonly as oe } from "./components/Readonly/Readonly.js";
18
- import { IressInput as u } from "./components/Input/Input.js";
19
- import { getValueAsEvent as se } from "./helpers/form/getValueAsEvent.js";
20
- import { t as ce } from "./useAutocompleteSearch-BYzUn7Ag.js";
21
- import { AutocompleteInstructions as d } from "./components/Autocomplete/components/AutocompleteInstructions.js";
22
- import { select as le } from "./components/Select/Select.styles.js";
23
- import { IressInline as f } from "./components/Inline/Inline.js";
24
- import { SelectActivator as ue } from "./components/Select/components/SelectActivator.js";
25
- import { IressSelectMenu as p } from "./components/Select/SelectMenu/SelectMenu.js";
26
- import { SelectOptions as m } from "./components/Select/components/SelectOptions.js";
27
- import { SelectHiddenInput as de } from "./components/Select/components/SelectHiddenInput.js";
28
- import { NativeSelect as fe } from "./components/Select/components/NativeSelect.js";
29
- import { useSelectState as h } from "./components/Select/hooks/useSelectState.js";
30
- import { forwardRef as g, useCallback as pe, useEffect as _, useImperativeHandle as me, useMemo as v, useRef as y, useState as b } from "react";
31
- import { Fragment as he, jsx as x, jsxs as S } from "react/jsx-runtime";
32
- //#region src/components/Select/Select.tsx
33
- var C = (e) => typeof e == "object" && !!e && "label" in e, w = (e, t) => {
34
- for (let n of t) if (n.children) {
35
- let t = w(e, n.children);
36
- if (t) return t;
37
- } else if (n.value !== void 0 && n.value === e) return n;
38
- }, T = (e, t) => {
39
- if (C(e)) return e;
40
- if (typeof t != "function") return w(e, t) ?? (typeof e == "number" ? w(String(e), t) : void 0);
41
- }, E = (e, t) => {
42
- if (e !== void 0) {
43
- if (Array.isArray(e)) {
44
- let r = e, i = r.map((e) => T(e, t)).filter((e) => e !== void 0);
45
- return i.length < r.length && typeof t != "function" && n(`IressSelect: ${r.length - i.length} value(s) could not be resolved to matching options and were dropped.`, "warn"), i;
46
- }
47
- return T(e, t);
48
- }
49
- }, D = g(({ align: r = "bottom-start", autoHighlight: i = !0, className: a, defaultValue: o, disabled: s, errorText: c, footer: ne, header: re, id: l, matchActivatorWidth: ie = !0, multiSelect: u, multiSelectLimit: se, name: d, onChange: f, onBlur: p, options: g, native: w, placeholder: T, readOnly: D, renderHiddenInput: O, renderLabel: ge, renderOptions: _e, required: k, type: A, value: j, virtualFocus: M, width: N, ...P }, F) => {
50
- ae({
51
- component: "IressSelect",
52
- defaultValue: o
53
- });
54
- let [I, L] = b(!1), R = I && !s, [z, ve] = b(""), B = v(() => E(j, g), [j, g]), V = v(() => E(o, g), [o, g]);
55
- _(() => {
56
- j !== void 0 && !C(j) && B === void 0 && typeof g == "function" && n("IressSelect: A primitive value was passed but cannot be resolved because options are asynchronous. Pass a LabelValueMeta object instead when using async options, otherwise the component will behave as uncontrolled.", "warn");
57
- }, [
58
- j,
59
- B,
60
- g
61
- ]);
62
- let { value: H, setValue: U, getValuesString: W, getLabelsString: ye } = h({
63
- component: "IressSelect",
64
- defaultValue: V,
65
- multiple: u,
66
- value: B
67
- }), G = y(null), K = y(null), q = y(null), { value: J } = ee(typeof w == "string" ? {
68
- xs: !0,
69
- [w]: !1
70
- } : { xs: w }, { disabled: !w }), { append: be, debounceThreshold: xe, initialOptions: Y, loadingDelay: Se, minSearchLength: X, onActivated: Ce, onDeactivated: we, prepend: Te, selectedOptionsText: Ee, ...Z } = P, { debouncedQuery: De, error: Oe, results: ke, stopSearch: Ae, loading: je, shouldShowInstructions: Me, shouldShowNoResults: Ne } = ce({
71
- debounceThreshold: xe,
72
- disabled: !I || !!J,
73
- initialOptions: Y,
74
- loadingDelay: Se,
75
- minSearchLength: X,
76
- options: g,
77
- query: z
78
- });
79
- me(F, () => J ? {
80
- focus: () => K.current?.focus(),
81
- blur: () => K.current?.blur(),
82
- input: K.current ?? null
83
- } : G.current ? {
84
- ...G.current,
85
- focus: () => G.current?.getActivator()?.focus(),
86
- blur: () => G.current?.getActivator()?.blur(),
87
- hiddenInput: q.current ?? void 0,
88
- input: q.current ?? null
89
- } : {
90
- hiddenInput: q.current ?? void 0,
91
- input: q.current ?? null,
92
- focus: () => q.current?.focus(),
93
- blur: () => q.current?.blur()
94
- }, [J]), _(() => {
95
- I ? Ce?.() : we?.();
96
- }, [
97
- Ce,
98
- we,
99
- I
100
- ]);
101
- let Pe = pe((e) => {
102
- if (!p) return;
103
- let t = e.currentTarget, n = e.relatedTarget;
104
- !I && (!n || !t.contains(n)) && p(e), e.stopPropagation();
105
- }, [p, I]);
106
- if (D) return /* @__PURE__ */ x(oe, {
107
- value: W(),
108
- ref: q,
109
- variant: D,
110
- name: d,
111
- disabled: s,
112
- required: k,
113
- children: ye(", ")
114
- });
115
- if (J) {
116
- if (g instanceof Function) throw Error("[IressSelect] The native select does not support asynchronous options. Please provide options as an array.");
117
- if (u) throw Error("[IressSelect] The native select does not support multiple selection. Please remove the multiSelect prop or use the non-native select.");
118
- return /* @__PURE__ */ x(fe, {
119
- className: e(a, t.Select),
120
- "data-testid": Z["data-testid"],
121
- disabled: s,
122
- id: l,
123
- name: d,
124
- onChange: (e, t) => {
125
- f?.(e, t?.value ?? null, t), U(t);
126
- },
127
- options: g,
128
- placeholder: typeof w == "string" ? T ?? "" : T,
129
- style: Z.style,
130
- value: H,
131
- width: N,
132
- ref: K
133
- });
134
- }
135
- let Q = typeof g == "function", Fe = M ?? !Q, Ie = A ?? (Q ? void 0 : "listbox"), $ = le({ width: N }), Le = () => {
136
- L(!0);
137
- }, Re = () => {
138
- L(!1), Ae();
139
- };
140
- return /* @__PURE__ */ S(he, { children: [/* @__PURE__ */ x(de, {
141
- "data-testid": Z["data-testid"],
142
- getValuesString: W,
143
- name: d,
144
- renderHiddenInput: O,
145
- required: k,
146
- value: H,
147
- disabled: s,
148
- ref: q
149
- }), /* @__PURE__ */ x(te, {
150
- ...Z,
151
- activator: /* @__PURE__ */ x(ue, {
152
- append: be,
153
- async: Q,
154
- disabled: s,
155
- error: Oe,
156
- id: l,
157
- loading: je,
158
- multiSelect: u,
159
- multiSelectLimit: se,
160
- onChange: f,
161
- placeholder: T,
162
- prepend: Te,
163
- renderLabel: ge,
164
- selectedOptionsText: Ee,
165
- setValue: U,
166
- setShow: L,
167
- show: I,
168
- value: H
169
- }),
170
- align: r,
171
- className: e(a, $.root, t.Select),
172
- contentClassName: e($.popoverContent),
173
- contentStyle: {
174
- ...Z.contentStyle,
175
- p: "none"
176
- },
177
- matchActivatorWidth: ie,
178
- onActivated: Le,
179
- onDeactivated: Re,
180
- ref: G,
181
- show: R,
182
- type: Ie,
183
- virtualFocus: Fe,
184
- onBlur: Pe,
185
- children: /* @__PURE__ */ S("div", {
186
- className: $.wrapper,
187
- children: [
188
- re,
189
- /* @__PURE__ */ x(m, {
190
- autoHighlight: i,
191
- debouncedQuery: De,
192
- error: Oe,
193
- errorText: c,
194
- initialOptions: Y,
195
- loading: je,
196
- minSearchLength: X,
197
- multiSelect: u,
198
- onChange: f,
199
- options: g,
200
- query: z,
201
- renderOptions: _e,
202
- results: ke,
203
- setQuery: ve,
204
- setShow: L,
205
- setValue: U,
206
- shouldShowInstructions: Me,
207
- shouldShowNoResults: Ne,
208
- show: R,
209
- value: H
210
- }),
211
- ne
212
- ]
213
- })
214
- })] });
215
- });
216
- D.displayName = "IressSelect";
217
- //#endregion
218
- //#region src/components/Autocomplete/Autocomplete.tsx
219
- var O = g(({ alwaysShowOnFocus: n, append: ee = /* @__PURE__ */ x(r, { name: "search" }), autoComplete: te = "off", autoSelect: ae = !0, className: le, clearable: ue = !0, "data-testid": m, debounceThreshold: de, defaultValue: fe, errorText: h = /* @__PURE__ */ x(re, {
220
- status: "danger",
221
- mb: "none",
222
- variant: "full-width",
223
- children: "An unknown error occurred. Please contact support if the error persists."
224
- }), initialOptions: g, loadingDelay: pe, limitDesktop: me = 12, limitMobile: v = 6, minSearchLength: y, noResultsText: C, onChange: w, onClear: T, onFocus: E, options: D, popoverProps: { autoHighlight: O = !1, append: ge, prepend: _e, ...k } = {}, readOnly: A, value: j, ...M }, N) => {
225
- let [P, F] = b(!1), { value: I, setValue: L } = c({
226
- component: "IressAutocomplete",
227
- defaultValue: fe,
228
- value: j
229
- }), [R, z] = b(!1), { clearError: ve, debouncedQuery: B, error: V, loading: H, results: U, startSearch: W, stopSearch: ye, shouldShowInstructions: G, shouldShowNoResults: K } = ce({
230
- debounceThreshold: de,
231
- initialOptions: g,
232
- loadingDelay: pe,
233
- minSearchLength: y,
234
- options: D,
235
- query: ie(I)
236
- });
237
- if (_(() => {
238
- R && !P && U.length > 0 && I && F(!0);
239
- }, [
240
- U.length,
241
- P,
242
- R,
243
- I
244
- ]), _(() => {
245
- H && R && F(!0);
246
- }, [H, R]), _(() => {
247
- V && F(!0);
248
- }, [V]), A) return /* @__PURE__ */ x(oe, {
249
- value: I,
250
- variant: A
251
- });
252
- let q = (e, t) => {
253
- w?.(e, t), L(t), z(!!t);
254
- }, J = (e) => {
255
- T?.(e), L("");
256
- }, be = (e) => {
257
- E?.(e), g?.length && F(!0);
258
- }, xe = (e) => {
259
- let t = s(e)?.[0];
260
- w?.(se(t?.label), t?.label, t), L(t?.label), F(!1), z(!1);
261
- }, Y = () => {
262
- (!n || !I) && ye(), ve(), F(!1), I && z(!1);
263
- }, Se = (e) => {
264
- M.onKeyDown?.(e), e.key === "ArrowDown" && (!P || !R) && (U.length || W(!0), z(!0), F(!0));
265
- }, X = l({ isEmpty: U.length === 0 && !H && !V && !G && !K });
266
- return /* @__PURE__ */ S(ne, {
267
- ...k,
268
- activator: /* @__PURE__ */ x(u, {
269
- ...M,
270
- append: ee,
271
- autoComplete: te,
272
- clearable: ue,
273
- "data-testid": a(m, "input"),
274
- onChange: q,
275
- onClear: J,
276
- onFocus: be,
277
- onKeyDown: Se,
278
- value: I,
279
- ref: N
280
- }),
281
- autoHighlight: O,
282
- className: e(le, k.className, X.root, t.Autocomplete),
283
- contentClassName: e(k.contentClassName, X.popoverContent),
284
- contentStyle: k.contentStyle,
285
- "data-testid": m,
286
- minLength: 0,
287
- onActivated: () => (R || n) && F(!0),
288
- onDeactivated: Y,
289
- show: P,
290
- type: "listbox",
291
- focusStartIndex: 0,
292
- children: [
293
- H && !U.length && /* @__PURE__ */ S(f, {
294
- gap: "sm",
295
- verticalAlign: "middle",
296
- p: "spacing.3",
297
- children: [/* @__PURE__ */ x(o, { color: "colour.neutral.70" }), /* @__PURE__ */ x(i, {
298
- color: "colour.neutral.70",
299
- children: "Loading results..."
300
- })]
301
- }),
302
- U.length > 0 && /* @__PURE__ */ S(he, { children: [
303
- _e,
304
- /* @__PURE__ */ x(p, {
305
- changeOnBlur: ae,
306
- className: e(X.optionList),
307
- "data-testid": a(m, "menu"),
308
- items: U,
309
- limitDesktop: me,
310
- limitMobile: v,
311
- onChange: xe,
312
- selected: { label: B }
313
- }),
314
- ge
315
- ] }),
316
- V && h,
317
- G && !V && /* @__PURE__ */ x(d, { minSearchLength: y ?? 1 }),
318
- K && !V && C
319
- ]
320
- });
321
- });
322
- O.displayName = "IressAutocomplete";
323
- //#endregion
324
- export { D as n, O as t };