@nldd/design-system 0.8.88 → 0.8.90

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 (108) hide show
  1. package/README.md +4 -4
  2. package/custom-elements.json +303 -64
  3. package/dist/components/components.js +897 -201
  4. package/dist/components/content/image/image.d.ts +23 -3
  5. package/dist/components/content/image/image.d.ts.map +1 -1
  6. package/dist/components/content/image/image.js +74 -17
  7. package/dist/components/content/image/image.js.map +1 -1
  8. package/dist/components/content/image/image.template.js +1 -1
  9. package/dist/components/content/image/image.template.js.map +1 -1
  10. package/dist/components/{dist-LX8LuMac.js → dist-BLaE_n_F.js} +1 -1
  11. package/dist/components/{dist-CX3DK4i7.js → dist-BeymuiGt.js} +3 -3
  12. package/dist/components/{dist-CbCO0WCd.js → dist-CENYEz7C.js} +1 -1
  13. package/dist/components/{dist-B_Mnmrj4.js → dist-CYLM5ciE.js} +1 -1
  14. package/dist/components/{dist-fIxe0l7k.js → dist-DHA-0RyT.js} +91 -34
  15. package/dist/components/{dist-CgDuh26K.js → dist-D_ckX1sK.js} +1 -1
  16. package/dist/components/{dist-eVFegyjM.js → dist-Dh_b9r4M.js} +1 -1
  17. package/dist/components/{dist-DXZ-cFAl.js → dist-DkZlotgT.js} +2 -2
  18. package/dist/components/{dist-CSrO_mYe.js → dist-TCqV9dho.js} +1 -1
  19. package/dist/components/{dist-ByH8hQze.js → dist-Y54Lma86.js} +2 -2
  20. package/dist/components/{dist-CRwuSgMM.js → dist-yyE8P2O6.js} +2 -2
  21. package/dist/components/inputs/radio-button/radio-button.d.ts +58 -18
  22. package/dist/components/inputs/radio-button/radio-button.d.ts.map +1 -1
  23. package/dist/components/inputs/radio-button/radio-button.js +136 -29
  24. package/dist/components/inputs/radio-button/radio-button.js.map +1 -1
  25. package/dist/components/inputs/radio-button/radio-button.styles.d.ts.map +1 -1
  26. package/dist/components/inputs/radio-button/radio-button.styles.js +17 -23
  27. package/dist/components/inputs/radio-button/radio-button.styles.js.map +1 -1
  28. package/dist/components/inputs/radio-button/radio-button.template.d.ts.map +1 -1
  29. package/dist/components/inputs/radio-button/radio-button.template.js +13 -10
  30. package/dist/components/inputs/radio-button/radio-button.template.js.map +1 -1
  31. package/dist/components/inputs/radio-button-field/radio-button-field.d.ts +65 -18
  32. package/dist/components/inputs/radio-button-field/radio-button-field.d.ts.map +1 -1
  33. package/dist/components/inputs/radio-button-field/radio-button-field.js +151 -29
  34. package/dist/components/inputs/radio-button-field/radio-button-field.js.map +1 -1
  35. package/dist/components/inputs/radio-button-field/radio-button-field.styles.d.ts.map +1 -1
  36. package/dist/components/inputs/radio-button-field/radio-button-field.styles.js +17 -0
  37. package/dist/components/inputs/radio-button-field/radio-button-field.styles.js.map +1 -1
  38. package/dist/components/inputs/radio-button-field/radio-button-field.template.d.ts.map +1 -1
  39. package/dist/components/inputs/radio-button-field/radio-button-field.template.js +21 -12
  40. package/dist/components/inputs/radio-button-field/radio-button-field.template.js.map +1 -1
  41. package/dist/components/inputs/radio-button-group/radio-button-group.d.ts +3 -0
  42. package/dist/components/inputs/radio-button-group/radio-button-group.d.ts.map +1 -1
  43. package/dist/components/inputs/radio-button-group/radio-button-group.js +16 -4
  44. package/dist/components/inputs/radio-button-group/radio-button-group.js.map +1 -1
  45. package/dist/components/inputs/segmented-control/segmented-control.d.ts +46 -13
  46. package/dist/components/inputs/segmented-control/segmented-control.d.ts.map +1 -1
  47. package/dist/components/inputs/segmented-control/segmented-control.js +145 -16
  48. package/dist/components/inputs/segmented-control/segmented-control.js.map +1 -1
  49. package/dist/components/inputs/segmented-control/segmented-control.styles.d.ts.map +1 -1
  50. package/dist/components/inputs/segmented-control/segmented-control.styles.js +16 -0
  51. package/dist/components/inputs/segmented-control/segmented-control.styles.js.map +1 -1
  52. package/dist/components/inputs/segmented-control/segmented-control.template.d.ts.map +1 -1
  53. package/dist/components/inputs/segmented-control/segmented-control.template.js +47 -24
  54. package/dist/components/inputs/segmented-control/segmented-control.template.js.map +1 -1
  55. package/dist/components/inputs/text-editor/text-editor.cursor.d.ts.map +1 -1
  56. package/dist/components/inputs/text-editor/text-editor.cursor.js +14 -1
  57. package/dist/components/inputs/text-editor/text-editor.cursor.js.map +1 -1
  58. package/dist/components/inputs/text-editor/text-editor.mentions.d.ts.map +1 -1
  59. package/dist/components/inputs/text-editor/text-editor.mentions.js +3 -1
  60. package/dist/components/inputs/text-editor/text-editor.mentions.js.map +1 -1
  61. package/dist/components/inputs/toggle-button/toggle-button.d.ts +36 -2
  62. package/dist/components/inputs/toggle-button/toggle-button.d.ts.map +1 -1
  63. package/dist/components/inputs/toggle-button/toggle-button.js +116 -3
  64. package/dist/components/inputs/toggle-button/toggle-button.js.map +1 -1
  65. package/dist/components/inputs/toggle-button/toggle-button.styles.d.ts.map +1 -1
  66. package/dist/components/inputs/toggle-button/toggle-button.styles.js +17 -1
  67. package/dist/components/inputs/toggle-button/toggle-button.styles.js.map +1 -1
  68. package/dist/components/inputs/toggle-button/toggle-button.template.d.ts.map +1 -1
  69. package/dist/components/inputs/toggle-button/toggle-button.template.js +25 -2
  70. package/dist/components/inputs/toggle-button/toggle-button.template.js.map +1 -1
  71. package/dist/components/inputs/toggle-button-group/toggle-button-group.d.ts +4 -0
  72. package/dist/components/inputs/toggle-button-group/toggle-button-group.d.ts.map +1 -1
  73. package/dist/components/inputs/toggle-button-group/toggle-button-group.js +21 -2
  74. package/dist/components/inputs/toggle-button-group/toggle-button-group.js.map +1 -1
  75. package/dist/components/lists-and-tables/list/list.d.ts +1 -1
  76. package/dist/components/lists-and-tables/list/list.d.ts.map +1 -1
  77. package/dist/components/lists-and-tables/list/list.js +4 -3
  78. package/dist/components/lists-and-tables/list/list.js.map +1 -1
  79. package/dist/components/lists-and-tables/list/list.template.d.ts.map +1 -1
  80. package/dist/components/lists-and-tables/list/list.template.js +15 -10
  81. package/dist/components/lists-and-tables/list/list.template.js.map +1 -1
  82. package/dist/components/status-and-feedback/notification/notification-region.d.ts +4 -0
  83. package/dist/components/status-and-feedback/notification/notification-region.d.ts.map +1 -1
  84. package/dist/components/status-and-feedback/notification/notification-region.js +99 -30
  85. package/dist/components/status-and-feedback/notification/notification-region.js.map +1 -1
  86. package/dist/components/status-and-feedback/notification/notification.d.ts +7 -1
  87. package/dist/components/status-and-feedback/notification/notification.d.ts.map +1 -1
  88. package/dist/components/status-and-feedback/notification/notification.js +21 -1
  89. package/dist/components/status-and-feedback/notification/notification.js.map +1 -1
  90. package/dist/components/status-and-feedback/notification/notification.styles.d.ts.map +1 -1
  91. package/dist/components/status-and-feedback/notification/notification.styles.js +6 -0
  92. package/dist/components/status-and-feedback/notification/notification.styles.js.map +1 -1
  93. package/dist/css/variables.css +2 -2
  94. package/dist/nldd.min.js +618 -540
  95. package/dist/types/vue.d.ts +22 -18
  96. package/dist/utilities/described-by-mixin.d.ts +2 -2
  97. package/dist/utilities/described-by-mixin.d.ts.map +1 -1
  98. package/dist/utilities/described-by-mixin.js +11 -6
  99. package/dist/utilities/described-by-mixin.js.map +1 -1
  100. package/dist/utilities/radio-grouping.d.ts +66 -0
  101. package/dist/utilities/radio-grouping.d.ts.map +1 -0
  102. package/dist/utilities/radio-grouping.js +133 -0
  103. package/dist/utilities/radio-grouping.js.map +1 -0
  104. package/dist/utilities/radio-position.d.ts +20 -0
  105. package/dist/utilities/radio-position.d.ts.map +1 -0
  106. package/dist/utilities/radio-position.js +11 -0
  107. package/dist/utilities/radio-position.js.map +1 -0
  108. package/package.json +10 -10
@@ -1354,7 +1354,7 @@ declare module 'vue' {
1354
1354
  type NLDDImageProps = {
1355
1355
  /** Image URL */
1356
1356
  'src'?: NLDDImage['src'];
1357
- /** Alt text. Required unless `decorative`. */
1357
+ /** Alt text for the image from `src`. Required unless `decorative`; slotted media carries its own. */
1358
1358
  'alt'?: NLDDImage['alt'];
1359
1359
  /** Responsive source set */
1360
1360
  'srcset'?: NLDDImage['srcset'];
@@ -2246,7 +2246,7 @@ declare module 'vue' {
2246
2246
  type NLDDRadioButtonProps = {
2247
2247
  /** Checked state */
2248
2248
  'checked'?: NLDDRadioButton['checked'];
2249
- /** Renders the shape without the input: no focus, no name/value, nothing announced. For a control that owns the state elsewhere, such as a list row that is itself the radio; putting a real input in there would nest a control inside a control. */
2249
+ /** Renders the shape only: no role, no focus, no name/value, nothing announced. For a control that owns the state elsewhere, such as a list row or an nldd-radio-button-field that is itself the radio; putting a second radio in there would nest a control inside a control. */
2250
2250
  'decorative'?: NLDDRadioButton['decorative'];
2251
2251
  /** Disabled state */
2252
2252
  'disabled'?: NLDDRadioButton['disabled'];
@@ -2254,15 +2254,19 @@ declare module 'vue' {
2254
2254
  'no-tab'?: NLDDRadioButton['noTab'];
2255
2255
  /** Takes the control out of the tab order (tabindex="-1"), for a control owned by a roving container (a row of an nldd-list, where the arrow keys move between rows) that manages focus itself. Still mouse- and script-focusable. */
2256
2256
  'noTab'?: NLDDRadioButton['noTab'];
2257
- /** Required state */
2257
+ /** Required state. What it asks is whether anything in the group is checked, as a native radio does. */
2258
2258
  'required'?: NLDDRadioButton['required'];
2259
+ /** Draws the focus ring around the shape. Set by nldd-radio-button-field, which is the radio itself and holds the focus. Not part of the public API. */
2260
+ 'focus-ring'?: NLDDRadioButton['focusRing'];
2261
+ /** Draws the focus ring around the shape. Set by nldd-radio-button-field, which is the radio itself and holds the focus. Not part of the public API. */
2262
+ 'focusRing'?: NLDDRadioButton['focusRing'];
2259
2263
  /** Radio group name for form submission; ties the buttons of one group together */
2260
2264
  'name'?: NLDDRadioButton['name'];
2261
2265
  /** Value submitted with the form when this radio button is checked */
2262
2266
  'value'?: NLDDRadioButton['value'];
2263
- /** Accessible label forwarded as aria-label to the native input. */
2267
+ /** Accessible label, set as aria-label on this element: it is the radio. */
2264
2268
  'accessible-label'?: NLDDRadioButton['accessibleLabel'];
2265
- /** Accessible label forwarded as aria-label to the native input. */
2269
+ /** Accessible label, set as aria-label on this element: it is the radio. */
2266
2270
  'accessibleLabel'?: NLDDRadioButton['accessibleLabel'];
2267
2271
  /** Marks the control as invalid. Announced with aria-invalid; nothing is drawn for it. Note: aria-labelledby is not supported as IDREF resolution cannot cross shadow DOM boundaries. */
2268
2272
  'invalid'?: NLDDRadioButton['invalid'];
@@ -2280,9 +2284,9 @@ declare module 'vue' {
2280
2284
  'disabled'?: NLDDRadioButtonField['disabled'];
2281
2285
  /** Value for form submission */
2282
2286
  'value'?: NLDDRadioButtonField['value'];
2283
- /** Radio group name for form submission, forwarded to the inner nldd-radio-button. Set automatically by nldd-radio-button-group. */
2287
+ /** Radio group name for form submission; ties the fields of one group together. Set automatically by nldd-radio-button-group. */
2284
2288
  'name'?: NLDDRadioButtonField['name'];
2285
- /** Required state, forwarded to the inner nldd-radio-button. Set automatically by nldd-radio-button-group. */
2289
+ /** Required state. What it asks is whether anything in the group is checked, as a native radio does. Set automatically by nldd-radio-button-group. */
2286
2290
  'required'?: NLDDRadioButtonField['required'];
2287
2291
  /** Label text for the radio button */
2288
2292
  'label'?: NLDDRadioButtonField['label'];
@@ -2386,7 +2390,7 @@ declare module 'vue' {
2386
2390
  'value'?: NLDDSegmentedControl['value'];
2387
2391
  /** Control size: 'sm' | 'md' | 'lg' (default: 'md') */
2388
2392
  'size'?: NLDDSegmentedControl['size'];
2389
- /** Input type: 'radio' | 'checkbox' (default: 'radio'). */
2393
+ /** Selection mode: 'radio' | 'checkbox' (default: 'radio'). */
2390
2394
  'type'?: NLDDSegmentedControl['type'];
2391
2395
  /** Content type for all items: 'text' | 'icon' | 'icon-and-text' (default: 'text') */
2392
2396
  'variant'?: NLDDSegmentedControl['variant'];
@@ -2394,7 +2398,7 @@ declare module 'vue' {
2394
2398
  'disabled'?: NLDDSegmentedControl['disabled'];
2395
2399
  /** Width mode: 'full' (stretches to container), 'fit-content' (per-item content size), or any CSS length (e.g. '240px') */
2396
2400
  'width'?: NLDDSegmentedControl['width'];
2397
- /** Name for form submission, forwarded to native inputs */
2401
+ /** Name for form submission */
2398
2402
  'name'?: NLDDSegmentedControl['name'];
2399
2403
  /** Accessible name for the group, set as aria-label */
2400
2404
  'accessible-label'?: NLDDSegmentedControl['accessibleLabel'];
@@ -2412,7 +2416,7 @@ declare module 'vue' {
2412
2416
  };
2413
2417
 
2414
2418
  type NLDDSegmentedControlItemProps = {
2415
- /** Required state. Set by nldd-segmented-control. */
2419
+ /** Required state of the native checkbox. In radio mode the group carries the constraint. */
2416
2420
  'required'?: NLDDSegmentedControlItem['required'];
2417
2421
  /** Value for this item */
2418
2422
  'value'?: NLDDSegmentedControlItem['value'];
@@ -2424,13 +2428,13 @@ declare module 'vue' {
2424
2428
  'size'?: NLDDSegmentedControlItem['size'];
2425
2429
  /** Content type: 'text' | 'icon' | 'icon-and-text' (default: 'text'). Set by nldd-segmented-control. */
2426
2430
  'variant'?: NLDDSegmentedControlItem['variant'];
2427
- /** Type of the native input: 'radio' | 'checkbox' (default: 'radio'). Set by nldd-segmented-control. */
2431
+ /** Selection mode: 'radio' | 'checkbox' (default: 'radio'). In radio mode the item is the radio itself, in checkbox mode it renders a native checkbox. Set by nldd-segmented-control. */
2428
2432
  'input-type'?: NLDDSegmentedControlItem['inputType'];
2429
- /** Type of the native input: 'radio' | 'checkbox' (default: 'radio'). Set by nldd-segmented-control. */
2433
+ /** Selection mode: 'radio' | 'checkbox' (default: 'radio'). In radio mode the item is the radio itself, in checkbox mode it renders a native checkbox. Set by nldd-segmented-control. */
2430
2434
  'inputType'?: NLDDSegmentedControlItem['inputType'];
2431
- /** Name of the group for form submission, put on the native input. Set by nldd-segmented-control. */
2435
+ /** Name of the group for form submission, put on the native checkbox. Set by nldd-segmented-control. */
2432
2436
  'group-name'?: NLDDSegmentedControlItem['groupName'];
2433
- /** Name of the group for form submission, put on the native input. Set by nldd-segmented-control. */
2437
+ /** Name of the group for form submission, put on the native checkbox. Set by nldd-segmented-control. */
2434
2438
  'groupName'?: NLDDSegmentedControlItem['groupName'];
2435
2439
  /** Text label (shown for variant "text" and "icon-and-text"; used as aria-label and tooltip for variant "icon") */
2436
2440
  'text'?: NLDDSegmentedControlItem['text'];
@@ -3218,7 +3222,7 @@ declare module 'vue' {
3218
3222
  type NLDDToggleButtonProps = {
3219
3223
  /** Required state. Set by nldd-toggle-button-group. */
3220
3224
  'required'?: NLDDToggleButton['required'];
3221
- /** Underlying element (default: 'button') */
3225
+ /** What the button is: a button with aria-pressed, a native checkbox, or a radio (default: 'button') */
3222
3226
  'type'?: NLDDToggleButton['type'];
3223
3227
  /** Button size (default: 'md') */
3224
3228
  'size'?: NLDDToggleButton['size'];
@@ -3747,9 +3751,9 @@ declare module 'vue' {
3747
3751
  /** Exports both NLDDProgressCircle and NLDDProgressCircleSegmentIndicator. A circular progress indicator that mirrors the API of nldd-progress-bar: single-value or multi-segment, progress or distribution mode, 24 colors, fade transitions between determinate/indeterminate, indeterminate indicator. Visual differences vs the bar: - SVG arcs instead of rectangular bars. - Label below the circle (not above). - No center text; the consumer can wrap the circle if needed. - One combined tooltip on the whole circle showing all segment info (no per-segment tooltips). - Indeterminate uses a rotating elastic arc (Material-style) instead of the bar's Knight Rider scanner. */
3748
3752
  'nldd-progress-circle': DefineComponent<NLDDProgressCircleProps>;
3749
3753
  'nldd-progress-circle-segment-indicator': DefineComponent<NLDDProgressCircleSegmentIndicatorProps>;
3750
- /** WAI-ARIA: Wrap radio buttons in a <fieldset>/<legend> or a container with role="radiogroup" and aria-labelledby for proper group semantics. <fieldset> <legend>Kies een optie</legend> <nldd-radio-button name="options" value="1">Optie 1</nldd-radio-button> <nldd-radio-button name="options" value="2">Optie 2</nldd-radio-button> </fieldset> */
3754
+ /** WAI-ARIA: put the buttons of one group in a container with role="radiogroup" and a name of its own. A screen reader counts the options from that container, so a bare <fieldset> (which is a group, not a radiogroup) leaves them uncounted. nldd-radio-button-group does this for you. Radio buttons with the same name, in the same form and the same tree, form one group the way native radios do: checking one unchecks the others, the arrow keys move between them, Tab stops at the group once, and a screen reader hears each one's place in it. The element itself is the radio, because an input per shadow root would leave every button a group of one. The shape is all this component draws. A radio with a label beside it is nldd-radio-button-field. <fieldset role="radiogroup" aria-labelledby="options-label"> <legend id="options-label">Kies een optie</legend> <nldd-radio-button name="options" value="1" accessible-label="Optie 1"></nldd-radio-button> <nldd-radio-button name="options" value="2" accessible-label="Optie 2"></nldd-radio-button> </fieldset> */
3751
3755
  'nldd-radio-button': DefineComponent<NLDDRadioButtonProps>;
3752
- /** A radio button with an inline label. Use inside nldd-radio-button-group for keyboard navigation and group semantics. The group sets the name. Form-associated: the checked field submits its `value` under `name` (the inner nldd-radio-button sits in the shadow root and never joins the consumer's form; the field submits on its behalf). Unchecking siblings is the group's job, so exactly one value per group reaches the form. */
3756
+ /** A radio button with an inline label. Use inside nldd-radio-button-group, which sets the name and labels the group. Fields that stand on their own group by name, the way native radios do: checking one unchecks the others, the arrow keys move between them and Tab stops at the group once. Put them in a container with role="radiogroup", or a screen reader has nothing to count them from. The field is the radio: it carries the role, the state, the label it is announced by and the focus, and the nldd-radio-button inside only draws the shape. A radio of its own in there would be a second control inside a control, and a group of one to count. Form-associated: the checked field submits its `value` under `name`. Unchecking siblings is the group's job, so exactly one value per group reaches the form. */
3753
3757
  'nldd-radio-button-field': DefineComponent<NLDDRadioButtonFieldProps>;
3754
3758
  /** Groups nldd-radio-button-field elements, handles keyboard navigation, and forwards name and disabled state to all child fields. Use inside nldd-form-field which provides the group label. */
3755
3759
  'nldd-radio-button-group': DefineComponent<NLDDRadioButtonGroupProps>;
@@ -3819,7 +3823,7 @@ declare module 'vue' {
3819
3823
  'nldd-title': DefineComponent<NLDDTitleProps>;
3820
3824
  /** A cell component for displaying a title with optional overline and subtitle in lists. `vertical-alignment="center"` (default) stretches the cell to fill the full row height and centers its content within that space. Use `min-height` to set a minimum centered region. For strict top alignment without a minimum height, use `vertical-alignment="top"`. Each text region (overline, title, supporting text) accepts either a string attribute or slotted DOM content. The slot is the source of truth: if the consumer provides slotted content, it replaces the attribute-based render for that region. Use slots when you need inline elements like `<nldd-tag>`, `<nldd-icon>` or other components mixed with text. Note that `query` highlighting and `**bold**` parsing only apply to the attribute path — slotted content is rendered as-is. */
3821
3825
  'nldd-title-cell': DefineComponent<NLDDTitleCellProps>;
3822
- /** A selectable button that toggles between selected and unselected. Available as a button (aria-pressed), checkbox, or radio input. */
3826
+ /** A selectable button that toggles between selected and unselected. Available as a button (aria-pressed), a checkbox, or a radio. In radio mode the button itself is the radio: it carries the role, the state and its place in the group. A native radio in a shadow root of its own would be a group of one, counted as "1 of 1" and stopped at by Tab. */
3823
3827
  'nldd-toggle-button': DefineComponent<NLDDToggleButtonProps>;
3824
3828
  /** Groups nldd-toggle-button elements and manages selection, keyboard navigation, and forwarding of type, name, size, and disabled state to all buttons. For type="radio" (single-select), arrow keys navigate between buttons and automatically select the focused one. For type="checkbox" (multi-select), multiple buttons can be selected simultaneously. */
3825
3829
  'nldd-toggle-button-group': DefineComponent<NLDDToggleButtonGroupProps>;
@@ -16,7 +16,7 @@ export interface DescribedElement {
16
16
  * `ariaDescribedByElements` takes the elements themselves and crosses the
17
17
  * boundary.
18
18
  */
19
- export declare function applyDescribedBy(target: Element | null | undefined, elements: readonly Element[]): void;
19
+ export declare function applyDescribedBy(target: Element | null | undefined, elements: readonly Element[], onSelf?: boolean): void;
20
20
  /**
21
21
  * Announces that a control is invalid, on the element assistive software meets.
22
22
  *
@@ -29,7 +29,7 @@ export declare function applyDescribedBy(target: Element | null | undefined, ele
29
29
  * A component that wraps another one hands the state on, the same way it hands
30
30
  * on the description.
31
31
  */
32
- export declare function applyInvalid(target: Element | null | undefined, invalid: boolean): void;
32
+ export declare function applyInvalid(target: Element | null | undefined, invalid: boolean, onSelf?: boolean): void;
33
33
  /**
34
34
  * Lets nldd-form-field hand a control the help and error texts that describe
35
35
  * it, wherever that control renders them.
@@ -1 +1 @@
1
- {"version":3,"file":"described-by-mixin.d.ts","sourceRoot":"","sources":["../../src/utilities/described-by-mixin.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAA2B,MAAM,KAAK,CAAC;AAI1D,KAAK,WAAW,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,QAAQ,MAAM,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;AAEnF,wEAAwE;AACxE,MAAM,WAAW,gBAAgB;IAChC,mBAAmB,EAAE,SAAS,OAAO,EAAE,CAAC;IACxC,yEAAyE;IACzE,eAAe,IAAI,OAAO,GAAG,IAAI,CAAC;CAClC;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,GAAG,SAAS,EAAE,QAAQ,EAAE,SAAS,OAAO,EAAE,GAAG,IAAI,CAavG;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,GAAG,SAAS,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAQvF;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,WAAW,CAAC,UAAU,CAAC,EAC5D,IAAI,EAAE,CAAC,GACL,CAAC,GAAG,WAAW,CAAC,gBAAgB,CAAC,CAsCnC"}
1
+ {"version":3,"file":"described-by-mixin.d.ts","sourceRoot":"","sources":["../../src/utilities/described-by-mixin.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAA2B,MAAM,KAAK,CAAC;AAI1D,KAAK,WAAW,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,QAAQ,MAAM,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;AAEnF,wEAAwE;AACxE,MAAM,WAAW,gBAAgB;IAChC,mBAAmB,EAAE,SAAS,OAAO,EAAE,CAAC;IACxC,yEAAyE;IACzE,eAAe,IAAI,OAAO,GAAG,IAAI,CAAC;CAClC;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAC/B,MAAM,EAAE,OAAO,GAAG,IAAI,GAAG,SAAS,EAClC,QAAQ,EAAE,SAAS,OAAO,EAAE,EAC5B,MAAM,UAAQ,GACZ,IAAI,CAaN;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,GAAG,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,UAAQ,GAAG,IAAI,CAQvG;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,WAAW,CAAC,UAAU,CAAC,EAC5D,IAAI,EAAE,CAAC,GACL,CAAC,GAAG,WAAW,CAAC,gBAAgB,CAAC,CA2CnC"}
@@ -15,13 +15,13 @@ import { property } from 'lit/decorators.js';
15
15
  * `ariaDescribedByElements` takes the elements themselves and crosses the
16
16
  * boundary.
17
17
  */
18
- export function applyDescribedBy(target, elements) {
18
+ export function applyDescribedBy(target, elements, onSelf = false) {
19
19
  if (!target)
20
20
  return;
21
21
  // A component that wraps another one hands the question on rather than
22
22
  // answering it. nldd-checkbox-field renders an nldd-checkbox, and only that
23
23
  // one knows which element inside itself is the control.
24
- if ('describedByElements' in target) {
24
+ if (!onSelf && 'describedByElements' in target) {
25
25
  target.describedByElements = [...elements];
26
26
  return;
27
27
  }
@@ -40,10 +40,10 @@ export function applyDescribedBy(target, elements) {
40
40
  * A component that wraps another one hands the state on, the same way it hands
41
41
  * on the description.
42
42
  */
43
- export function applyInvalid(target, invalid) {
43
+ export function applyInvalid(target, invalid, onSelf = false) {
44
44
  if (!target)
45
45
  return;
46
- if ('invalid' in target) {
46
+ if (!onSelf && 'invalid' in target) {
47
47
  target.invalid = invalid;
48
48
  return;
49
49
  }
@@ -75,12 +75,17 @@ export function DescribedBy(Base) {
75
75
  const apply = {
76
76
  hostUpdated: () => {
77
77
  const target = this.describedTarget();
78
- applyDescribedBy(target, this.describedByElements);
78
+ // A component that is the control itself, such as an
79
+ // nldd-radio-button carrying role="radio", puts the ARIA on its own
80
+ // element. Handing it on there would hand it to itself, and a
81
+ // component that does that renders forever.
82
+ const onSelf = target === this;
83
+ applyDescribedBy(target, this.describedByElements, onSelf);
79
84
  // Optional: nldd-button carries this mixin for its description and
80
85
  // has no validity of its own.
81
86
  const invalid = this.invalid;
82
87
  if (invalid !== undefined)
83
- applyInvalid(target, invalid);
88
+ applyInvalid(target, invalid, onSelf);
84
89
  },
85
90
  };
86
91
  this.addController(apply);
@@ -1 +1 @@
1
- {"version":3,"file":"described-by-mixin.js","sourceRoot":"","sources":["../../src/utilities/described-by-mixin.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAc7C;;;;;;;;;GASG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAAkC,EAAE,QAA4B;IAChG,IAAI,CAAC,MAAM;QAAE,OAAO;IAEpB,uEAAuE;IACvE,4EAA4E;IAC5E,wDAAwD;IACxD,IAAI,qBAAqB,IAAI,MAAM,EAAE,CAAC;QACpC,MAAsC,CAAC,mBAAmB,GAAG,CAAC,GAAG,QAAQ,CAAC,CAAC;QAC5E,OAAO;IACR,CAAC;IAED,MAAM,EAAE,GAAG,MAA0E,CAAC;IACtF,EAAE,CAAC,uBAAuB,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AACrE,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,YAAY,CAAC,MAAkC,EAAE,OAAgB;IAChF,IAAI,CAAC,MAAM;QAAE,OAAO;IACpB,IAAI,SAAS,IAAI,MAAM,EAAE,CAAC;QACxB,MAAyC,CAAC,OAAO,GAAG,OAAO,CAAC;QAC7D,OAAO;IACR,CAAC;IACD,IAAI,OAAO;QAAE,MAAM,CAAC,YAAY,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;;QACpD,MAAM,CAAC,eAAe,CAAC,cAAc,CAAC,CAAC;AAC7C,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,WAAW,CAC1B,IAAO;IAEP,MAAe,gBAAiB,SAAQ,IAAI;QAK3C,YAAY,GAAG,IAAW;YACzB,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC;YALhB,4DAA4D;YAE5D,wBAAmB,GAAuB,EAAE,CAAC;YAI5C,MAAM,KAAK,GAAuB;gBACjC,WAAW,EAAE,GAAG,EAAE;oBACjB,MAAM,MAAM,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC;oBACtC,gBAAgB,CAAC,MAAM,EAAE,IAAI,CAAC,mBAAmB,CAAC,CAAC;oBACnD,mEAAmE;oBACnE,8BAA8B;oBAC9B,MAAM,OAAO,GAAI,IAA8B,CAAC,OAAO,CAAC;oBACxD,IAAI,OAAO,KAAK,SAAS;wBAAE,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;gBAC1D,CAAC;aACD,CAAC;YACF,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QAC3B,CAAC;QAED;;;;;;;WAOG;QACH,eAAe;YACd,OAAO,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,yBAAyB,CAAC,IAAI,IAAI,CAAC;QAC1E,CAAC;KACD;IA5BA;QADC,QAAQ,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;iEACc;IA6B9C,2EAA2E;IAC3E,2EAA2E;IAC3E,wEAAwE;IACxE,WAAW;IACX,OAAO,gBAAgE,CAAC;AACzE,CAAC"}
1
+ {"version":3,"file":"described-by-mixin.js","sourceRoot":"","sources":["../../src/utilities/described-by-mixin.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAc7C;;;;;;;;;GASG;AACH,MAAM,UAAU,gBAAgB,CAC/B,MAAkC,EAClC,QAA4B,EAC5B,MAAM,GAAG,KAAK;IAEd,IAAI,CAAC,MAAM;QAAE,OAAO;IAEpB,uEAAuE;IACvE,4EAA4E;IAC5E,wDAAwD;IACxD,IAAI,CAAC,MAAM,IAAI,qBAAqB,IAAI,MAAM,EAAE,CAAC;QAC/C,MAAsC,CAAC,mBAAmB,GAAG,CAAC,GAAG,QAAQ,CAAC,CAAC;QAC5E,OAAO;IACR,CAAC;IAED,MAAM,EAAE,GAAG,MAA0E,CAAC;IACtF,EAAE,CAAC,uBAAuB,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AACrE,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,YAAY,CAAC,MAAkC,EAAE,OAAgB,EAAE,MAAM,GAAG,KAAK;IAChG,IAAI,CAAC,MAAM;QAAE,OAAO;IACpB,IAAI,CAAC,MAAM,IAAI,SAAS,IAAI,MAAM,EAAE,CAAC;QACnC,MAAyC,CAAC,OAAO,GAAG,OAAO,CAAC;QAC7D,OAAO;IACR,CAAC;IACD,IAAI,OAAO;QAAE,MAAM,CAAC,YAAY,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;;QACpD,MAAM,CAAC,eAAe,CAAC,cAAc,CAAC,CAAC;AAC7C,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,WAAW,CAC1B,IAAO;IAEP,MAAe,gBAAiB,SAAQ,IAAI;QAK3C,YAAY,GAAG,IAAW;YACzB,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC;YALhB,4DAA4D;YAE5D,wBAAmB,GAAuB,EAAE,CAAC;YAI5C,MAAM,KAAK,GAAuB;gBACjC,WAAW,EAAE,GAAG,EAAE;oBACjB,MAAM,MAAM,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC;oBACtC,qDAAqD;oBACrD,oEAAoE;oBACpE,8DAA8D;oBAC9D,4CAA4C;oBAC5C,MAAM,MAAM,GAAG,MAAM,KAAK,IAAI,CAAC;oBAC/B,gBAAgB,CAAC,MAAM,EAAE,IAAI,CAAC,mBAAmB,EAAE,MAAM,CAAC,CAAC;oBAC3D,mEAAmE;oBACnE,8BAA8B;oBAC9B,MAAM,OAAO,GAAI,IAA8B,CAAC,OAAO,CAAC;oBACxD,IAAI,OAAO,KAAK,SAAS;wBAAE,YAAY,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;gBAClE,CAAC;aACD,CAAC;YACF,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QAC3B,CAAC;QAED;;;;;;;WAOG;QACH,eAAe;YACd,OAAO,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,yBAAyB,CAAC,IAAI,IAAI,CAAC;QAC1E,CAAC;KACD;IAjCA;QADC,QAAQ,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;iEACc;IAkC9C,2EAA2E;IAC3E,2EAA2E;IAC3E,wEAAwE;IACxE,WAAW;IACX,OAAO,gBAAgE,CAAC;AACzE,CAAC"}
@@ -0,0 +1,66 @@
1
+ import type { ReactiveController, ReactiveControllerHost } from 'lit';
2
+ import { type RadioPosition } from './radio-position.js';
3
+ /**
4
+ * Groups a radio with the ones that share its name, the way the browser does.
5
+ *
6
+ * The platform groups native radios by name, within one tree and one form, and
7
+ * every radio of ours renders in a shadow root of its own. Left to the browser
8
+ * each of them is a group of one: checking one leaves the others checked, Tab
9
+ * stops at every option, and none of them knows its place in the set.
10
+ *
11
+ * A group component around the radios (nldd-radio-button-group) hands its
12
+ * members their position and wins where it is there. This is for the radios
13
+ * that stand on their own, in a `<fieldset role="radiogroup">` or a layout of
14
+ * the consumer's own.
15
+ */
16
+ /** What a radio has to offer to be grouped with the others of its name. */
17
+ export interface GroupedRadio extends HTMLElement {
18
+ name: string;
19
+ checked: boolean;
20
+ disabled: boolean;
21
+ readonly internals: ElementInternals;
22
+ commitFormValue(): void;
23
+ /** Checks this radio, the way a click does. */
24
+ select(): void;
25
+ }
26
+ type RadioHost = GroupedRadio & ReactiveControllerHost;
27
+ export declare class RadioGrouping implements ReactiveController {
28
+ private host;
29
+ /** Its place among the radios that share its name, or null when it has none. */
30
+ position: RadioPosition | null;
31
+ /**
32
+ * Whether anything in the group is checked, which is what `required` asks of
33
+ * a radio: one of these, not this one. A radio without a group answers for
34
+ * itself, because it is the whole group.
35
+ */
36
+ answered: boolean;
37
+ /** Where it was grouped last, so the radios it leaves behind hear of it. */
38
+ private _groupedIn;
39
+ constructor(host: RadioHost);
40
+ hostConnected(): void;
41
+ hostDisconnected(): void;
42
+ /** Reads which group this radio is in now, and recounts the one it left. */
43
+ regroup(): void;
44
+ /** Counts the group again, after this radio was checked or disabled. */
45
+ refresh(): void;
46
+ /** Unchecks the others, as checking a native radio does. */
47
+ uncheckOthers(): void;
48
+ /**
49
+ * Moves to the next radio of the group and checks it, as the arrow keys do
50
+ * for native radios. Disabled options are stepped over, and the ends wrap.
51
+ *
52
+ * @returns whether the key was handled.
53
+ */
54
+ moveWithArrow(e: KeyboardEvent): boolean;
55
+ private _key;
56
+ /** Compared by value: a recount hands out new objects for the same place, and
57
+ * asking for a render on every one of those is a render per radio per
58
+ * keystroke, each of them scheduled from inside an update that had just
59
+ * finished. */
60
+ private _apply;
61
+ private static _radiosIn;
62
+ /** A radio on its own keeps the place the browser gives it: none. */
63
+ private static _recount;
64
+ }
65
+ export {};
66
+ //# sourceMappingURL=radio-grouping.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"radio-grouping.d.ts","sourceRoot":"","sources":["../../src/utilities/radio-grouping.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,KAAK,CAAC;AACtE,OAAO,EAAkB,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzE;;;;;;;;;;;;GAYG;AAEH,2EAA2E;AAC3E,MAAM,WAAW,YAAa,SAAQ,WAAW;IAChD,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,SAAS,EAAE,gBAAgB,CAAC;IACrC,eAAe,IAAI,IAAI,CAAC;IACxB,+CAA+C;IAC/C,MAAM,IAAI,IAAI,CAAC;CACf;AAED,KAAK,SAAS,GAAG,YAAY,GAAG,sBAAsB,CAAC;AA0BvD,qBAAa,aAAc,YAAW,kBAAkB;IAe3C,OAAO,CAAC,IAAI;IAbxB,gFAAgF;IAChF,QAAQ,EAAE,aAAa,GAAG,IAAI,CAAQ;IAEtC;;;;OAIG;IACH,QAAQ,UAAS;IAEjB,4EAA4E;IAC5E,OAAO,CAAC,UAAU,CAA8B;gBAE5B,IAAI,EAAE,SAAS;IAKnC,aAAa,IAAI,IAAI;IAKrB,gBAAgB,IAAI,IAAI;IAIxB,4EAA4E;IAC5E,OAAO,IAAI,IAAI;IAUf,wEAAwE;IACxE,OAAO,IAAI,IAAI;IAKf,4DAA4D;IAC5D,aAAa,IAAI,IAAI;IAYrB;;;;;OAKG;IACH,aAAa,CAAC,CAAC,EAAE,aAAa,GAAG,OAAO;IAcxC,OAAO,CAAC,IAAI;IAKZ;;;oBAGgB;IAChB,OAAO,CAAC,MAAM;IAWd,OAAO,CAAC,MAAM,CAAC,SAAS;IAUxB,qEAAqE;IACrE,OAAO,CAAC,MAAM,CAAC,QAAQ;CAUvB"}
@@ -0,0 +1,133 @@
1
+ import { radioPositions } from './radio-position.js';
2
+ /**
3
+ * Both tags in one list, because the platform groups on the name and not on the
4
+ * element. A button and a field that share a name are one group to the browser,
5
+ * and two lists would have them counting different sets.
6
+ */
7
+ const RADIO_TAGS = 'nldd-radio-button, nldd-radio-button-field';
8
+ const ARROW_STEPS = { ArrowDown: 1, ArrowRight: 1, ArrowUp: -1, ArrowLeft: -1 };
9
+ /** The controller of each radio, so a recount can reach its siblings. */
10
+ const groupings = new WeakMap();
11
+ /** A radio that draws the shape for something else owns no state of its own. */
12
+ function isMember(radio) {
13
+ return !radio.decorative;
14
+ }
15
+ export class RadioGrouping {
16
+ constructor(host) {
17
+ this.host = host;
18
+ /** Its place among the radios that share its name, or null when it has none. */
19
+ this.position = null;
20
+ /**
21
+ * Whether anything in the group is checked, which is what `required` asks of
22
+ * a radio: one of these, not this one. A radio without a group answers for
23
+ * itself, because it is the whole group.
24
+ */
25
+ this.answered = false;
26
+ /** Where it was grouped last, so the radios it leaves behind hear of it. */
27
+ this._groupedIn = null;
28
+ groupings.set(host, this);
29
+ host.addController(this);
30
+ }
31
+ hostConnected() {
32
+ // A tick later, once the radios parsed after this one are there too.
33
+ queueMicrotask(() => this.regroup());
34
+ }
35
+ hostDisconnected() {
36
+ this.regroup();
37
+ }
38
+ /** Reads which group this radio is in now, and recounts the one it left. */
39
+ regroup() {
40
+ const was = this._groupedIn;
41
+ const now = this._key();
42
+ this._groupedIn = now;
43
+ const moved = !now || !was || was.root !== now.root || was.name !== now.name || was.form !== now.form;
44
+ if (was && moved)
45
+ RadioGrouping._recount(was);
46
+ if (now)
47
+ RadioGrouping._recount(now);
48
+ else
49
+ this._apply(null, this.host.checked);
50
+ }
51
+ /** Counts the group again, after this radio was checked or disabled. */
52
+ refresh() {
53
+ if (this._groupedIn)
54
+ RadioGrouping._recount(this._groupedIn);
55
+ else
56
+ this._apply(null, this.host.checked);
57
+ }
58
+ /** Unchecks the others, as checking a native radio does. */
59
+ uncheckOthers() {
60
+ const key = this._key();
61
+ if (!key)
62
+ return;
63
+ for (const radio of RadioGrouping._radiosIn(key)) {
64
+ if (radio === this.host || !radio.checked)
65
+ continue;
66
+ radio.checked = false;
67
+ // Synchronously: a change listener that reads the form should not find
68
+ // two values under one name.
69
+ radio.commitFormValue();
70
+ }
71
+ }
72
+ /**
73
+ * Moves to the next radio of the group and checks it, as the arrow keys do
74
+ * for native radios. Disabled options are stepped over, and the ends wrap.
75
+ *
76
+ * @returns whether the key was handled.
77
+ */
78
+ moveWithArrow(e) {
79
+ const step = ARROW_STEPS[e.key];
80
+ const key = step ? this._key() : null;
81
+ if (!key || !this.position)
82
+ return false;
83
+ const radios = RadioGrouping._radiosIn(key).filter((radio) => !radio.disabled);
84
+ const at = radios.indexOf(this.host);
85
+ if (at === -1)
86
+ return false;
87
+ e.preventDefault();
88
+ const next = radios[(at + step + radios.length) % radios.length];
89
+ next.focus();
90
+ next.select();
91
+ return true;
92
+ }
93
+ _key() {
94
+ if (!this.host.isConnected || !isMember(this.host) || !this.host.name)
95
+ return null;
96
+ return { root: this.host.getRootNode(), name: this.host.name, form: this.host.internals.form };
97
+ }
98
+ /** Compared by value: a recount hands out new objects for the same place, and
99
+ * asking for a render on every one of those is a render per radio per
100
+ * keystroke, each of them scheduled from inside an update that had just
101
+ * finished. */
102
+ _apply(position, answered) {
103
+ const same = this.answered === answered
104
+ && this.position?.posInSet === position?.posInSet
105
+ && this.position?.setSize === position?.setSize
106
+ && this.position?.tabbable === position?.tabbable;
107
+ if (same)
108
+ return;
109
+ this.position = position;
110
+ this.answered = answered;
111
+ this.host.requestUpdate();
112
+ }
113
+ static _radiosIn({ root, name, form }) {
114
+ const radios = root.querySelectorAll?.(RADIO_TAGS) ?? [];
115
+ return Array.from(radios).filter((radio) => groupings.has(radio)
116
+ && radio.isConnected
117
+ && radio.name === name
118
+ && isMember(radio)
119
+ && radio.internals.form === form);
120
+ }
121
+ /** A radio on its own keeps the place the browser gives it: none. */
122
+ static _recount(key) {
123
+ const radios = RadioGrouping._radiosIn(key);
124
+ const positions = radios.length > 1
125
+ ? radioPositions(radios, (radio) => radio.checked, (radio) => radio.disabled)
126
+ : [];
127
+ const answered = radios.some((radio) => radio.checked);
128
+ radios.forEach((radio, index) => {
129
+ groupings.get(radio)?._apply(positions[index] ?? null, answered);
130
+ });
131
+ }
132
+ }
133
+ //# sourceMappingURL=radio-grouping.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"radio-grouping.js","sourceRoot":"","sources":["../../src/utilities/radio-grouping.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Where a radio sits in its group, for a component that renders its native
3
+ * radio in a shadow root of its own.
4
+ *
5
+ * The browser groups radios by name within one tree scope. One input per
6
+ * shadow root makes every radio a group of one: a screen reader announces
7
+ * "1 of 1" for each, and each is a stop of its own for Tab. Whatever holds the
8
+ * group knows better, so it hands every radio its place, and the radio puts
9
+ * that on its input.
10
+ */
11
+ export interface RadioPosition {
12
+ posInSet: number;
13
+ setSize: number;
14
+ /** The group's one stop for Tab: the checked radio, or the first enabled
15
+ * one when none is checked, which is where the browser would land too. */
16
+ tabbable: boolean;
17
+ }
18
+ /** A position for every radio of a group, in the order given. */
19
+ export declare function radioPositions<T>(radios: readonly T[], isChecked: (radio: T) => boolean, isDisabled: (radio: T) => boolean): RadioPosition[];
20
+ //# sourceMappingURL=radio-position.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"radio-position.d.ts","sourceRoot":"","sources":["../../src/utilities/radio-position.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,MAAM,WAAW,aAAa;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB;+EAC2E;IAC3E,QAAQ,EAAE,OAAO,CAAC;CAClB;AAED,iEAAiE;AACjE,wBAAgB,cAAc,CAAC,CAAC,EAC/B,MAAM,EAAE,SAAS,CAAC,EAAE,EACpB,SAAS,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,EAChC,UAAU,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,GAC/B,aAAa,EAAE,CAQjB"}
@@ -0,0 +1,11 @@
1
+ /** A position for every radio of a group, in the order given. */
2
+ export function radioPositions(radios, isChecked, isDisabled) {
3
+ const enabled = radios.filter((radio) => !isDisabled(radio));
4
+ const stop = enabled.find(isChecked) ?? enabled[0];
5
+ return radios.map((radio, index) => ({
6
+ posInSet: index + 1,
7
+ setSize: radios.length,
8
+ tabbable: radio === stop,
9
+ }));
10
+ }
11
+ //# sourceMappingURL=radio-position.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"radio-position.js","sourceRoot":"","sources":["../../src/utilities/radio-position.ts"],"names":[],"mappings":"AAkBA,iEAAiE;AACjE,MAAM,UAAU,cAAc,CAC7B,MAAoB,EACpB,SAAgC,EAChC,UAAiC;IAEjC,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC;IAC7D,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC;IACnD,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;QACpC,QAAQ,EAAE,KAAK,GAAG,CAAC;QACnB,OAAO,EAAE,MAAM,CAAC,MAAM;QACtB,QAAQ,EAAE,KAAK,KAAK,IAAI;KACxB,CAAC,CAAC,CAAC;AACL,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nldd/design-system",
3
- "version": "0.8.88",
3
+ "version": "0.8.90",
4
4
  "description": "Design System voor Nederlandse Digitale Dienst",
5
5
  "type": "module",
6
6
  "main": "dist/components/components.js",
@@ -473,7 +473,7 @@
473
473
  ],
474
474
  "repository": {
475
475
  "type": "git",
476
- "url": "https://github.com/MinBZK/storybook.git"
476
+ "url": "https://github.com/NederlandseDigitaleDienst/design-system.git"
477
477
  },
478
478
  "publishConfig": {
479
479
  "access": "public",
@@ -533,25 +533,25 @@
533
533
  "@semantic-release/changelog": "^7.0.0",
534
534
  "@semantic-release/exec": "^7.1.0",
535
535
  "@semantic-release/git": "^11.0.1",
536
- "@storybook/addon-a11y": "^10.5.7",
537
- "@storybook/addon-docs": "^10.5.7",
538
- "@storybook/addon-themes": "^10.5.7",
539
- "@storybook/addon-vitest": "^10.5.7",
540
- "@storybook/web-components-vite": "^10.5.7",
536
+ "@storybook/addon-a11y": "^10.6.0",
537
+ "@storybook/addon-docs": "^10.6.0",
538
+ "@storybook/addon-themes": "^10.6.0",
539
+ "@storybook/addon-vitest": "^10.6.0",
540
+ "@storybook/web-components-vite": "^10.6.0",
541
541
  "@vitest/browser-playwright": "4.1.11",
542
542
  "@vitest/coverage-v8": "4.1.11",
543
543
  "conventional-changelog": "^8.1.0",
544
544
  "conventional-changelog-conventionalcommits": "10.2.1",
545
545
  "eslint": "^10.8.0",
546
546
  "eslint-plugin-lit-a11y": "^5.1.1",
547
- "eslint-plugin-storybook": "^10.5.7",
547
+ "eslint-plugin-storybook": "^10.6.0",
548
548
  "globals": "^17.8.0",
549
549
  "playwright": "^1.57.0",
550
550
  "semantic-release": "^25.0.2",
551
- "storybook": "^10.5.7",
551
+ "storybook": "^10.6.0",
552
552
  "typescript": "^5.3.0",
553
553
  "typescript-eslint": "^8.58.0",
554
- "vite": "8.2.2",
554
+ "vite": "8.3.0",
555
555
  "vitest": "4.1.11",
556
556
  "vue": "^3.5.40",
557
557
  "vue-tsc": "^3.3.7"