@dbcdk/react-components 0.0.202 → 0.0.204

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. package/dist/components/chip/Chip.d.ts +2 -1
  2. package/dist/components/chip/Chip.module.css +13 -0
  3. package/dist/components/forms/checkbox/Checkbox.cjs +11 -6
  4. package/dist/components/forms/checkbox/Checkbox.d.ts +5 -1
  5. package/dist/components/forms/checkbox/Checkbox.js +11 -6
  6. package/dist/components/forms/checkbox/Checkbox.module.css +6 -7
  7. package/dist/components/forms/form-select/FormSelect.cjs +61 -63
  8. package/dist/components/forms/form-select/FormSelect.d.ts +1 -1
  9. package/dist/components/forms/form-select/FormSelect.js +62 -64
  10. package/dist/components/forms/form-select/FormSelect.module.css +10 -0
  11. package/dist/components/forms/input/Input.cjs +10 -1
  12. package/dist/components/forms/input/Input.js +10 -1
  13. package/dist/components/forms/input/Input.module.css +11 -130
  14. package/dist/components/forms/input-container/InputContainer.cjs +28 -10
  15. package/dist/components/forms/input-container/InputContainer.d.ts +4 -1
  16. package/dist/components/forms/input-container/InputContainer.js +29 -11
  17. package/dist/components/forms/input-container/InputContainer.module.css +33 -3
  18. package/dist/components/forms/input-container/messageIds.cjs +15 -0
  19. package/dist/components/forms/input-container/messageIds.d.ts +13 -0
  20. package/dist/components/forms/input-container/messageIds.js +12 -0
  21. package/dist/components/forms/select/Select.cjs +111 -113
  22. package/dist/components/forms/select/Select.d.ts +1 -1
  23. package/dist/components/forms/select/Select.js +112 -114
  24. package/dist/components/forms/select/Select.module.css +11 -33
  25. package/dist/components/forms/text-area/Textarea.cjs +5 -9
  26. package/dist/components/forms/text-area/Textarea.js +5 -9
  27. package/dist/components/forms/text-area/Textarea.module.css +11 -32
  28. package/package.json +1 -1
@@ -6,6 +6,7 @@ import { ClearButton } from '../../../components/clear-button/ClearButton';
6
6
  import { useTooltipTrigger } from '../../../components/overlay/tooltip/useTooltipTrigger';
7
7
  import styles from '../input/Input.module.css';
8
8
  import { InputContainer } from '../input-container/InputContainer';
9
+ import { getDescribedBy } from '../input-container/messageIds';
9
10
 
10
11
  function mergeRefs(...refs) {
11
12
  return (node) => {
@@ -21,6 +22,7 @@ const Input = forwardRef(function Input2({
21
22
  labelAction,
22
23
  error,
23
24
  helpText,
25
+ helpTextAddition,
24
26
  orientation = "vertical",
25
27
  labelWidth = "160px",
26
28
  fullWidth = false,
@@ -91,6 +93,7 @@ const Input = forwardRef(function Input2({
91
93
  fullWidth,
92
94
  error,
93
95
  helpText,
96
+ helpTextAddition,
94
97
  orientation,
95
98
  labelWidth,
96
99
  required,
@@ -117,7 +120,7 @@ const Input = forwardRef(function Input2({
117
120
  styles[variant],
118
121
  icon ? styles.fieldWithIcon : "",
119
122
  inputSize ? styles[inputSize] : "",
120
- modified ? styles.modified : "",
123
+ error ? styles.invalid : "",
121
124
  fieldClassName != null ? fieldClassName : ""
122
125
  ].filter(Boolean).join(" "),
123
126
  "data-forminput": "field",
@@ -132,6 +135,12 @@ const Input = forwardRef(function Input2({
132
135
  {
133
136
  ...inputProps,
134
137
  id: inputId,
138
+ "aria-invalid": error ? true : inputProps["aria-invalid"],
139
+ "aria-describedby": getDescribedBy(
140
+ inputId,
141
+ { error, helpText },
142
+ inputProps["aria-describedby"]
143
+ ),
135
144
  ref: mergeRefs(inputRef, ref),
136
145
  className: [styles.input, inputSize ? styles[inputSize] : "", inputClassName != null ? inputClassName : ""].filter(Boolean).join(" ")
137
146
  }
@@ -140,14 +140,6 @@
140
140
  --input-autofill-ring: var(--color-navbar-fg);
141
141
  }
142
142
 
143
- .modified {
144
- --input-autofill-ring: color-mix(
145
- in srgb,
146
- var(--color-status-warning-border) 55%,
147
- var(--color-border-default)
148
- );
149
- }
150
-
151
143
  .embedded:has(.input:-webkit-autofill)::after {
152
144
  content: none;
153
145
  }
@@ -309,128 +301,6 @@
309
301
  color: var(--color-navbar-fg);
310
302
  }
311
303
 
312
- /* =========================
313
- Modified state
314
- ========================= */
315
-
316
- .modified {
317
- background-color: color-mix(in srgb, var(--color-status-warning-bg) 22%, var(--color-bg-surface));
318
- border-color: color-mix(
319
- in srgb,
320
- var(--color-status-warning-border) 45%,
321
- var(--color-border-default)
322
- );
323
- border-left-color: var(--color-status-warning-border);
324
- border-left-width: 4px;
325
- }
326
-
327
- /* Hover should stay warm, not switch back to the normal border */
328
- .modified:hover:not([aria-disabled='true']) {
329
- background-color: color-mix(in srgb, var(--color-status-warning-bg) 28%, var(--color-bg-surface));
330
- border-color: color-mix(
331
- in srgb,
332
- var(--color-status-warning-border) 60%,
333
- var(--color-border-default)
334
- );
335
- border-left-color: var(--color-status-warning-border);
336
- }
337
-
338
- /* Focus should also stay warm and readable */
339
- .modified:focus-within:not([aria-disabled='true']) {
340
- background-color: color-mix(in srgb, var(--color-status-warning-bg) 28%, var(--color-bg-surface));
341
- border-color: color-mix(
342
- in srgb,
343
- var(--color-status-warning-border) 75%,
344
- var(--color-border-default)
345
- );
346
- border-left-color: var(--color-status-warning-border);
347
- box-shadow: inset 0 0 0 1px
348
- color-mix(in srgb, var(--color-status-warning-border) 55%, var(--color-border-default));
349
- }
350
-
351
- /* Variant-specific tweaks when modified */
352
- .surface.modified {
353
- box-shadow: 0 1px 2px rgba(0, 0, 0, 0.03);
354
- }
355
-
356
- .surface.modified:hover:not([aria-disabled='true']) {
357
- box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
358
- }
359
-
360
- .surface.modified:focus-within:not([aria-disabled='true']) {
361
- box-shadow: inset 0 0 0 1px
362
- color-mix(in srgb, var(--color-status-warning-border) 55%, var(--color-border-default));
363
- }
364
-
365
- .subtle.modified {
366
- background-color: color-mix(in srgb, var(--color-status-warning-bg) 30%, var(--color-bg-toolbar));
367
- border-color: transparent;
368
- border-left-color: var(--color-status-warning-border);
369
- border-left-width: 4px;
370
- box-shadow: none;
371
- }
372
-
373
- .subtle.modified:hover:not([aria-disabled='true']) {
374
- background-color: color-mix(
375
- in srgb,
376
- var(--color-status-warning-bg) 36%,
377
- var(--color-bg-toolbar-hover)
378
- );
379
- }
380
-
381
- .subtle.modified:focus-within:not([aria-disabled='true']) {
382
- border-color: color-mix(
383
- in srgb,
384
- var(--color-status-warning-border) 75%,
385
- var(--color-border-default)
386
- );
387
- border-left-color: var(--color-status-warning-border);
388
- box-shadow: inset 0 0 0 1px
389
- color-mix(in srgb, var(--color-status-warning-border) 55%, var(--color-border-default));
390
- }
391
-
392
- .standalone.modified {
393
- box-shadow: var(--shadow-xs), var(--shadow-md);
394
- }
395
-
396
- .standalone.modified:hover:not([aria-disabled='true']) {
397
- box-shadow: var(--shadow-sm), var(--shadow-md);
398
- }
399
-
400
- .standalone.modified:focus-within:not([aria-disabled='true']) {
401
- box-shadow:
402
- var(--shadow-xs),
403
- var(--shadow-md),
404
- inset 0 0 0 1px
405
- color-mix(in srgb, var(--color-status-warning-border) 55%, var(--color-border-default));
406
- }
407
-
408
- /* Embedded should stay visually light, but can still get the marker */
409
- .embedded.modified {
410
- background-color: color-mix(in srgb, var(--color-status-warning-bg) 18%, transparent);
411
- border-color: transparent;
412
- border-left-color: var(--color-status-warning-border);
413
- border-left-width: 3px;
414
- box-shadow: none;
415
- }
416
-
417
- .embedded.modified:hover:not([aria-disabled='true']),
418
- .embedded.modified:focus-within:not([aria-disabled='true']) {
419
- background-color: color-mix(in srgb, var(--color-status-warning-bg) 22%, transparent);
420
- border-color: transparent;
421
- border-left-color: var(--color-status-warning-border);
422
- box-shadow: none;
423
- }
424
-
425
- /* Disabled modified state */
426
- .modified[aria-disabled='true'] {
427
- background-color: var(--color-disabled-bg);
428
- border-color: var(--color-disabled-border);
429
- border-left-color: var(--color-disabled-border);
430
- border-left-width: var(--border-width-thin);
431
- box-shadow: none;
432
- }
433
-
434
304
  /* Sizes */
435
305
  .xs {
436
306
  block-size: var(--component-size-xs);
@@ -602,3 +472,14 @@
602
472
  opacity: 1;
603
473
  pointer-events: auto;
604
474
  }
475
+
476
+ /* Error: wins over variant and modified styles */
477
+ .field.invalid,
478
+ .field.invalid:hover:not([aria-disabled='true']) {
479
+ border-color: var(--color-status-error);
480
+ }
481
+
482
+ .field.invalid:focus-within:not([aria-disabled='true']) {
483
+ border-color: var(--color-status-error);
484
+ box-shadow: inset 0 0 0 1px var(--color-status-error);
485
+ }
@@ -1,8 +1,10 @@
1
1
  'use strict';
2
2
 
3
3
  var jsxRuntime = require('react/jsx-runtime');
4
+ var lucideReact = require('lucide-react');
4
5
  var styles = require('./InputContainer.module.css');
5
- var InlineStatus = require('../../inline-status/InlineStatus');
6
+ var messageIds = require('./messageIds');
7
+ var Circle = require('../../circle/Circle');
6
8
 
7
9
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
8
10
 
@@ -22,19 +24,33 @@ function InputContainer({
22
24
  size = "md",
23
25
  labelWidth = "160px",
24
26
  labelAlignment = "center",
25
- modified = false
27
+ modified = false,
28
+ modifiedLabel = "\xC6ndret"
26
29
  }) {
27
- const renderLabelRow = (label || labelAction) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${styles__default.default.labelRow} dbc-flex dbc-items-center dbc-gap-xs`, children: [
30
+ const modifiedTag = modified && label ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.modifiedTag, children: /* @__PURE__ */ jsxRuntime.jsx(Circle.Circle, { size: "2xs", severity: "info", children: modifiedLabel }) }) : null;
31
+ const labelRow = (withModifiedTag) => (label || labelAction) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${styles__default.default.labelRow} dbc-flex dbc-items-center dbc-gap-xs`, children: [
28
32
  label && /* @__PURE__ */ jsxRuntime.jsxs("label", { className: styles__default.default.label, htmlFor, children: [
29
33
  label,
30
34
  required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.required, children: " *" })
31
35
  ] }),
36
+ withModifiedTag && modifiedTag,
32
37
  labelAction && /* @__PURE__ */ jsxRuntime.jsx("span", { "data-input-container-label-action": "true", children: labelAction })
33
38
  ] });
34
- const renderMessageRow = (error || helpText || helpTextAddition) && /* @__PURE__ */ jsxRuntime.jsx("div", { className: `${error ? styles__default.default.errorText : styles__default.default.helpText} ${styles__default.default.messageRow}`, children: error ? /* @__PURE__ */ jsxRuntime.jsx(InlineStatus.InlineStatus, { severity: "error", disableIcon: true, children: error }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
35
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: helpText }),
36
- helpTextAddition && /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.helpTextAddition, children: helpTextAddition })
37
- ] }) });
39
+ const renderLabelRow = orientation === "vertical" ? labelRow(true) : modifiedTag ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles__default.default.horizontalLabel, children: [
40
+ labelRow(false),
41
+ modifiedTag
42
+ ] }) : labelRow(false);
43
+ const messageIds$1 = htmlFor ? messageIds.getMessageIds(htmlFor) : void 0;
44
+ const renderMessageRow = (error || helpText || helpTextAddition) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "dbc-flex dbc-flex-column dbc-gap-xxs", children: [
45
+ error && /* @__PURE__ */ jsxRuntime.jsxs("div", { id: messageIds$1 == null ? void 0 : messageIds$1.errorId, className: `${styles__default.default.errorText} ${styles__default.default.messageRow}`, children: [
46
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CircleAlert, { className: styles__default.default.errorIcon, "aria-hidden": "true" }),
47
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: error })
48
+ ] }),
49
+ (helpText || helpTextAddition) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${styles__default.default.helpText} ${styles__default.default.messageRow}`, children: [
50
+ /* @__PURE__ */ jsxRuntime.jsx("span", { id: messageIds$1 == null ? void 0 : messageIds$1.helpTextId, children: helpText }),
51
+ helpTextAddition && /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.helpTextAddition, children: helpTextAddition })
52
+ ] })
53
+ ] });
38
54
  if (orientation === "vertical") {
39
55
  return /* @__PURE__ */ jsxRuntime.jsxs(
40
56
  "div",
@@ -44,8 +60,10 @@ function InputContainer({
44
60
  style: { width: fullWidth ? "100%" : void 0 },
45
61
  children: [
46
62
  renderLabelRow,
47
- children,
48
- renderMessageRow
63
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "dbc-flex dbc-flex-column dbc-gap-xxs", children: [
64
+ children,
65
+ renderMessageRow
66
+ ] })
49
67
  ]
50
68
  }
51
69
  );
@@ -59,7 +77,7 @@ function InputContainer({
59
77
  "--label-width": labelWidth,
60
78
  width: fullWidth ? "100%" : void 0
61
79
  },
62
- children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${styles__default.default.horizontal} dbc-flex dbc-flex-column dbc-gap-xs`, "data-size": size, children: [
80
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${styles__default.default.horizontal} dbc-flex dbc-flex-column dbc-gap-xxs`, "data-size": size, children: [
63
81
  /* @__PURE__ */ jsxRuntime.jsxs(
64
82
  "div",
65
83
  {
@@ -13,6 +13,9 @@ export interface InputContainerProps {
13
13
  size?: 'sm' | 'md' | 'lg';
14
14
  labelWidth?: string;
15
15
  labelAlignment?: 'top' | 'center';
16
+ /** Marks the field as changed since it was last saved. */
16
17
  modified?: boolean;
18
+ /** Text shown for a modified field. */
19
+ modifiedLabel?: string;
17
20
  }
18
- export declare function InputContainer({ label, labelAction, htmlFor, error, helpText, helpTextAddition, fullWidth, required, children, orientation, size, labelWidth, labelAlignment, modified, }: InputContainerProps): React.ReactElement;
21
+ export declare function InputContainer({ label, labelAction, htmlFor, error, helpText, helpTextAddition, fullWidth, required, children, orientation, size, labelWidth, labelAlignment, modified, modifiedLabel, }: InputContainerProps): React.ReactElement;
@@ -1,6 +1,8 @@
1
- import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
+ import { CircleAlert } from 'lucide-react';
2
3
  import styles from './InputContainer.module.css';
3
- import { InlineStatus } from '../../inline-status/InlineStatus';
4
+ import { getMessageIds } from './messageIds';
5
+ import { Circle } from '../../circle/Circle';
4
6
 
5
7
  function InputContainer({
6
8
  label,
@@ -16,19 +18,33 @@ function InputContainer({
16
18
  size = "md",
17
19
  labelWidth = "160px",
18
20
  labelAlignment = "center",
19
- modified = false
21
+ modified = false,
22
+ modifiedLabel = "\xC6ndret"
20
23
  }) {
21
- const renderLabelRow = (label || labelAction) && /* @__PURE__ */ jsxs("div", { className: `${styles.labelRow} dbc-flex dbc-items-center dbc-gap-xs`, children: [
24
+ const modifiedTag = modified && label ? /* @__PURE__ */ jsx("span", { className: styles.modifiedTag, children: /* @__PURE__ */ jsx(Circle, { size: "2xs", severity: "info", children: modifiedLabel }) }) : null;
25
+ const labelRow = (withModifiedTag) => (label || labelAction) && /* @__PURE__ */ jsxs("div", { className: `${styles.labelRow} dbc-flex dbc-items-center dbc-gap-xs`, children: [
22
26
  label && /* @__PURE__ */ jsxs("label", { className: styles.label, htmlFor, children: [
23
27
  label,
24
28
  required && /* @__PURE__ */ jsx("span", { className: styles.required, children: " *" })
25
29
  ] }),
30
+ withModifiedTag && modifiedTag,
26
31
  labelAction && /* @__PURE__ */ jsx("span", { "data-input-container-label-action": "true", children: labelAction })
27
32
  ] });
28
- const renderMessageRow = (error || helpText || helpTextAddition) && /* @__PURE__ */ jsx("div", { className: `${error ? styles.errorText : styles.helpText} ${styles.messageRow}`, children: error ? /* @__PURE__ */ jsx(InlineStatus, { severity: "error", disableIcon: true, children: error }) : /* @__PURE__ */ jsxs(Fragment, { children: [
29
- /* @__PURE__ */ jsx("span", { children: helpText }),
30
- helpTextAddition && /* @__PURE__ */ jsx("span", { className: styles.helpTextAddition, children: helpTextAddition })
31
- ] }) });
33
+ const renderLabelRow = orientation === "vertical" ? labelRow(true) : modifiedTag ? /* @__PURE__ */ jsxs("div", { className: styles.horizontalLabel, children: [
34
+ labelRow(false),
35
+ modifiedTag
36
+ ] }) : labelRow(false);
37
+ const messageIds = htmlFor ? getMessageIds(htmlFor) : void 0;
38
+ const renderMessageRow = (error || helpText || helpTextAddition) && /* @__PURE__ */ jsxs("div", { className: "dbc-flex dbc-flex-column dbc-gap-xxs", children: [
39
+ error && /* @__PURE__ */ jsxs("div", { id: messageIds == null ? void 0 : messageIds.errorId, className: `${styles.errorText} ${styles.messageRow}`, children: [
40
+ /* @__PURE__ */ jsx(CircleAlert, { className: styles.errorIcon, "aria-hidden": "true" }),
41
+ /* @__PURE__ */ jsx("span", { children: error })
42
+ ] }),
43
+ (helpText || helpTextAddition) && /* @__PURE__ */ jsxs("div", { className: `${styles.helpText} ${styles.messageRow}`, children: [
44
+ /* @__PURE__ */ jsx("span", { id: messageIds == null ? void 0 : messageIds.helpTextId, children: helpText }),
45
+ helpTextAddition && /* @__PURE__ */ jsx("span", { className: styles.helpTextAddition, children: helpTextAddition })
46
+ ] })
47
+ ] });
32
48
  if (orientation === "vertical") {
33
49
  return /* @__PURE__ */ jsxs(
34
50
  "div",
@@ -38,8 +54,10 @@ function InputContainer({
38
54
  style: { width: fullWidth ? "100%" : void 0 },
39
55
  children: [
40
56
  renderLabelRow,
41
- children,
42
- renderMessageRow
57
+ /* @__PURE__ */ jsxs("div", { className: "dbc-flex dbc-flex-column dbc-gap-xxs", children: [
58
+ children,
59
+ renderMessageRow
60
+ ] })
43
61
  ]
44
62
  }
45
63
  );
@@ -53,7 +71,7 @@ function InputContainer({
53
71
  "--label-width": labelWidth,
54
72
  width: fullWidth ? "100%" : void 0
55
73
  },
56
- children: /* @__PURE__ */ jsxs("div", { className: `${styles.horizontal} dbc-flex dbc-flex-column dbc-gap-xs`, "data-size": size, children: [
74
+ children: /* @__PURE__ */ jsxs("div", { className: `${styles.horizontal} dbc-flex dbc-flex-column dbc-gap-xxs`, "data-size": size, children: [
57
75
  /* @__PURE__ */ jsxs(
58
76
  "div",
59
77
  {
@@ -23,14 +23,19 @@
23
23
 
24
24
  .helpText {
25
25
  color: var(--color-fg-subtle);
26
- font-size: var(--font-size-sm);
26
+ font-size: var(--font-size-xs);
27
27
  display: flex;
28
- align-items: center;
28
+ /* Line the addition up with the first line of text, also when it wraps */
29
+ align-items: baseline;
29
30
  justify-content: space-between;
31
+ gap: var(--spacing-sm);
30
32
  }
31
33
 
32
34
  .helpTextAddition {
33
35
  color: var(--color-fg-subtle);
36
+ /* Never squeezed or wrapped by a long help text */
37
+ flex-shrink: 0;
38
+ white-space: nowrap;
34
39
  }
35
40
 
36
41
  .horizontal label {
@@ -38,8 +43,19 @@
38
43
  }
39
44
 
40
45
  .errorText {
46
+ display: flex;
47
+ align-items: flex-start;
48
+ gap: var(--spacing-xxs);
41
49
  color: var(--color-status-error);
42
- font-size: var(--font-size-sm);
50
+ font-size: var(--font-size-xs);
51
+ }
52
+
53
+ /* Centred on the first line of the error text */
54
+ .errorIcon {
55
+ flex-shrink: 0;
56
+ inline-size: var(--icon-size-xs);
57
+ block-size: var(--icon-size-xs);
58
+ margin-block: calc((1lh - var(--icon-size-xs)) / 2);
43
59
  }
44
60
 
45
61
  .required {
@@ -50,3 +66,17 @@
50
66
  .messageRow {
51
67
  min-height: 1lh;
52
68
  }
69
+
70
+ /* Modified: a status dot with text next to the label, not a style on the field */
71
+ .modifiedTag {
72
+ display: inline-flex;
73
+ flex-shrink: 0;
74
+ color: var(--color-fg-subtle);
75
+ }
76
+
77
+ .horizontalLabel {
78
+ display: flex;
79
+ flex-direction: column;
80
+ align-items: flex-start;
81
+ flex-shrink: 0;
82
+ }
@@ -0,0 +1,15 @@
1
+ 'use strict';
2
+
3
+ function getMessageIds(controlId) {
4
+ return { errorId: `${controlId}-error`, helpTextId: `${controlId}-help` };
5
+ }
6
+ function getDescribedBy(controlId, { error, helpText }, ...extraIds) {
7
+ const { errorId, helpTextId } = getMessageIds(controlId);
8
+ const ids = [error ? errorId : void 0, helpText ? helpTextId : void 0, ...extraIds].filter(
9
+ Boolean
10
+ );
11
+ return ids.length ? ids.join(" ") : void 0;
12
+ }
13
+
14
+ exports.getDescribedBy = getDescribedBy;
15
+ exports.getMessageIds = getMessageIds;
@@ -0,0 +1,13 @@
1
+ /** Ids of the error and help text that InputContainer renders for a control with id `controlId`. */
2
+ export declare function getMessageIds(controlId: string): {
3
+ errorId: string;
4
+ helpTextId: string;
5
+ };
6
+ /**
7
+ * aria-describedby value for a control inside InputContainer: the rendered error and help text,
8
+ * followed by any extra ids (e.g. a tooltip or the consumer's own aria-describedby).
9
+ */
10
+ export declare function getDescribedBy(controlId: string, { error, helpText }: {
11
+ error?: unknown;
12
+ helpText?: unknown;
13
+ }, ...extraIds: Array<string | undefined | null | false>): string | undefined;
@@ -0,0 +1,12 @@
1
+ function getMessageIds(controlId) {
2
+ return { errorId: `${controlId}-error`, helpTextId: `${controlId}-help` };
3
+ }
4
+ function getDescribedBy(controlId, { error, helpText }, ...extraIds) {
5
+ const { errorId, helpTextId } = getMessageIds(controlId);
6
+ const ids = [error ? errorId : void 0, helpText ? helpTextId : void 0, ...extraIds].filter(
7
+ Boolean
8
+ );
9
+ return ids.length ? ids.join(" ") : void 0;
10
+ }
11
+
12
+ export { getDescribedBy, getMessageIds };