@nldd/design-system 0.8.80 → 0.8.83
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.
- package/custom-elements.json +1138 -71
- package/dist/components/actions/button/button.d.ts +5 -0
- package/dist/components/actions/button/button.d.ts.map +1 -1
- package/dist/components/actions/button/button.js +8 -0
- package/dist/components/actions/button/button.js.map +1 -1
- package/dist/components/actions/button/button.template.d.ts.map +1 -1
- package/dist/components/actions/button/button.template.js +2 -0
- package/dist/components/actions/button/button.template.js.map +1 -1
- package/dist/components/actions/icon-button/icon-button.d.ts +1 -1
- package/dist/components/actions/icon-button/icon-button.js +1 -1
- package/dist/components/actions/menu/menu.d.ts +25 -2
- package/dist/components/actions/menu/menu.d.ts.map +1 -1
- package/dist/components/actions/menu/menu.js +31 -8
- package/dist/components/actions/menu/menu.js.map +1 -1
- package/dist/components/actions/menu/menu.template.d.ts +1 -1
- package/dist/components/actions/menu/menu.template.d.ts.map +1 -1
- package/dist/components/actions/menu/menu.template.js +7 -3
- package/dist/components/actions/menu/menu.template.js.map +1 -1
- package/dist/components/actions/toolbar/toolbar.d.ts +20 -0
- package/dist/components/actions/toolbar/toolbar.d.ts.map +1 -1
- package/dist/components/actions/toolbar/toolbar.js +54 -0
- package/dist/components/actions/toolbar/toolbar.js.map +1 -1
- package/dist/components/breakpoints-CkxsiRgH.js +10 -0
- package/dist/components/components.js +52643 -117
- package/dist/components/content/avatar/avatar.styles.d.ts.map +1 -1
- package/dist/components/content/avatar/avatar.styles.js +5 -1
- package/dist/components/content/avatar/avatar.styles.js.map +1 -1
- package/dist/components/content/icon/icon-aliases.d.ts.map +1 -1
- package/dist/components/content/icon/icon-aliases.js +78 -6
- package/dist/components/content/icon/icon-aliases.js.map +1 -1
- package/dist/components/content/icon/icon-gallery-status.d.ts.map +1 -1
- package/dist/components/content/icon/icon-gallery-status.js +63 -92
- package/dist/components/content/icon/icon-gallery-status.js.map +1 -1
- package/dist/components/content/icon/icon-registry.d.ts.map +1 -1
- package/dist/components/content/icon/icon-registry.js +44 -6
- package/dist/components/content/icon/icon-registry.js.map +1 -1
- package/dist/components/content/icon/icon.d.ts +8 -2
- package/dist/components/content/icon/icon.d.ts.map +1 -1
- package/dist/components/content/icon/icon.js +17 -2
- package/dist/components/content/icon/icon.js.map +1 -1
- package/dist/components/content/icon/icon.styles.d.ts.map +1 -1
- package/dist/components/content/icon/icon.styles.js +8 -0
- package/dist/components/content/icon/icon.styles.js.map +1 -1
- package/dist/components/content/text/text.d.ts +50 -0
- package/dist/components/content/text/text.d.ts.map +1 -0
- package/dist/components/content/text/text.js +81 -0
- package/dist/components/content/text/text.js.map +1 -0
- package/dist/components/content/text/text.styles.d.ts +2 -0
- package/dist/components/content/text/text.styles.d.ts.map +1 -0
- package/dist/components/content/text/text.styles.js +116 -0
- package/dist/components/content/text/text.styles.js.map +1 -0
- package/dist/components/content/text/text.template.d.ts +3 -0
- package/dist/components/content/text/text.template.d.ts.map +1 -0
- package/dist/components/content/text/text.template.js +7 -0
- package/dist/components/content/text/text.template.js.map +1 -0
- package/dist/components/content/title/title.styles.d.ts.map +1 -1
- package/dist/components/content/title/title.styles.js +9 -13
- package/dist/components/content/title/title.styles.js.map +1 -1
- package/dist/components/decorate-BKn10QQi.js +9 -0
- package/dist/components/dist-BYVOPNHp.js +381 -0
- package/dist/components/dist-Bq4xc7Bm.js +624 -0
- package/dist/components/dist-C0PiB1dr.js +870 -0
- package/dist/components/dist-C400RcFU.js +1498 -0
- package/dist/components/dist-CCg5Mso_.js +390 -0
- package/dist/components/dist-CJR_Rwhh.js +464 -0
- package/dist/components/dist-Ccw7ZfsU.js +18481 -0
- package/dist/components/dist-OBifyiJS.js +887 -0
- package/dist/components/dist-TpIL8G4G.js +1480 -0
- package/dist/components/dist-afrAoubg.js +1181 -0
- package/dist/components/dist-bO14jlsr.js +78 -0
- package/dist/components/forms/form-field/form-field.d.ts +59 -2
- package/dist/components/forms/form-field/form-field.d.ts.map +1 -1
- package/dist/components/forms/form-field/form-field.js +120 -35
- package/dist/components/forms/form-field/form-field.js.map +1 -1
- package/dist/components/gherkin-uCVRxsGf.js +108 -0
- package/dist/components/icon-C1Kikpol.js +841 -0
- package/dist/components/icon-button-BYy6hnAY.js +1676 -0
- package/dist/components/index.d.ts +2 -1
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +2 -1
- package/dist/components/index.js.map +1 -1
- package/dist/components/input-modality-DhTeUxKi.js +43 -0
- package/dist/components/inputs/checkbox/checkbox.d.ts +8 -0
- package/dist/components/inputs/checkbox/checkbox.d.ts.map +1 -1
- package/dist/components/inputs/checkbox/checkbox.js +10 -0
- package/dist/components/inputs/checkbox/checkbox.js.map +1 -1
- package/dist/components/inputs/checkbox-field/checkbox-field.d.ts +9 -0
- package/dist/components/inputs/checkbox-field/checkbox-field.d.ts.map +1 -1
- package/dist/components/inputs/checkbox-field/checkbox-field.js +11 -0
- package/dist/components/inputs/checkbox-field/checkbox-field.js.map +1 -1
- package/dist/components/inputs/code-editor/code-editor.d.ts +3 -0
- package/dist/components/inputs/code-editor/code-editor.d.ts.map +1 -1
- package/dist/components/inputs/code-editor/code-editor.js +3 -0
- package/dist/components/inputs/code-editor/code-editor.js.map +1 -1
- package/dist/components/inputs/combo-box/combo-box.d.ts +8 -0
- package/dist/components/inputs/combo-box/combo-box.d.ts.map +1 -1
- package/dist/components/inputs/combo-box/combo-box.js +36 -0
- package/dist/components/inputs/combo-box/combo-box.js.map +1 -1
- package/dist/components/inputs/combo-box/combo-box.styles.d.ts.map +1 -1
- package/dist/components/inputs/combo-box/combo-box.styles.js +5 -0
- package/dist/components/inputs/combo-box/combo-box.styles.js.map +1 -1
- package/dist/components/inputs/combo-box/combo-box.template.d.ts.map +1 -1
- package/dist/components/inputs/combo-box/combo-box.template.js +23 -20
- package/dist/components/inputs/combo-box/combo-box.template.js.map +1 -1
- package/dist/components/inputs/date-field/date-field.d.ts +6 -0
- package/dist/components/inputs/date-field/date-field.d.ts.map +1 -1
- package/dist/components/inputs/date-field/date-field.js +11 -0
- package/dist/components/inputs/date-field/date-field.js.map +1 -1
- package/dist/components/inputs/date-field/date-field.template.d.ts.map +1 -1
- package/dist/components/inputs/date-field/date-field.template.js +7 -1
- package/dist/components/inputs/date-field/date-field.template.js.map +1 -1
- package/dist/components/inputs/date-picker/date-picker.d.ts +3 -0
- package/dist/components/inputs/date-picker/date-picker.d.ts.map +1 -1
- package/dist/components/inputs/date-picker/date-picker.js +4 -1
- package/dist/components/inputs/date-picker/date-picker.js.map +1 -1
- package/dist/components/inputs/dropdown/dropdown.d.ts +29 -0
- package/dist/components/inputs/dropdown/dropdown.d.ts.map +1 -1
- package/dist/components/inputs/dropdown/dropdown.js +44 -1
- package/dist/components/inputs/dropdown/dropdown.js.map +1 -1
- package/dist/components/inputs/file-field/file-field.d.ts +3 -0
- package/dist/components/inputs/file-field/file-field.d.ts.map +1 -1
- package/dist/components/inputs/file-field/file-field.js +3 -0
- package/dist/components/inputs/file-field/file-field.js.map +1 -1
- package/dist/components/inputs/multi-line-text-field/multi-line-text-field.d.ts +11 -1
- package/dist/components/inputs/multi-line-text-field/multi-line-text-field.d.ts.map +1 -1
- package/dist/components/inputs/multi-line-text-field/multi-line-text-field.js +11 -0
- package/dist/components/inputs/multi-line-text-field/multi-line-text-field.js.map +1 -1
- package/dist/components/inputs/multi-line-text-field/multi-line-text-field.template.d.ts.map +1 -1
- package/dist/components/inputs/multi-line-text-field/multi-line-text-field.template.js +2 -0
- package/dist/components/inputs/multi-line-text-field/multi-line-text-field.template.js.map +1 -1
- package/dist/components/inputs/number-field/number-field.d.ts +9 -0
- package/dist/components/inputs/number-field/number-field.d.ts.map +1 -1
- package/dist/components/inputs/number-field/number-field.js +12 -0
- package/dist/components/inputs/number-field/number-field.js.map +1 -1
- package/dist/components/inputs/number-field/number-field.template.d.ts.map +1 -1
- package/dist/components/inputs/number-field/number-field.template.js +1 -0
- package/dist/components/inputs/number-field/number-field.template.js.map +1 -1
- package/dist/components/inputs/password-field/password-field.d.ts +9 -0
- package/dist/components/inputs/password-field/password-field.d.ts.map +1 -1
- package/dist/components/inputs/password-field/password-field.js +12 -0
- package/dist/components/inputs/password-field/password-field.js.map +1 -1
- package/dist/components/inputs/password-field/password-field.template.d.ts.map +1 -1
- package/dist/components/inputs/password-field/password-field.template.js +1 -0
- package/dist/components/inputs/password-field/password-field.template.js.map +1 -1
- package/dist/components/inputs/radio-button/radio-button.d.ts +8 -0
- package/dist/components/inputs/radio-button/radio-button.d.ts.map +1 -1
- package/dist/components/inputs/radio-button/radio-button.js +10 -0
- package/dist/components/inputs/radio-button/radio-button.js.map +1 -1
- package/dist/components/inputs/radio-button-field/radio-button-field.d.ts +9 -0
- package/dist/components/inputs/radio-button-field/radio-button-field.d.ts.map +1 -1
- package/dist/components/inputs/radio-button-field/radio-button-field.js +11 -0
- package/dist/components/inputs/radio-button-field/radio-button-field.js.map +1 -1
- package/dist/components/inputs/radio-button-group/radio-button-group.d.ts +16 -0
- package/dist/components/inputs/radio-button-group/radio-button-group.d.ts.map +1 -1
- package/dist/components/inputs/radio-button-group/radio-button-group.js +33 -0
- package/dist/components/inputs/radio-button-group/radio-button-group.js.map +1 -1
- package/dist/components/inputs/search-field/search-field.d.ts +6 -0
- package/dist/components/inputs/search-field/search-field.d.ts.map +1 -1
- package/dist/components/inputs/search-field/search-field.js +6 -0
- package/dist/components/inputs/search-field/search-field.js.map +1 -1
- package/dist/components/inputs/segmented-control/segmented-control.d.ts +16 -0
- package/dist/components/inputs/segmented-control/segmented-control.d.ts.map +1 -1
- package/dist/components/inputs/segmented-control/segmented-control.js +26 -7
- package/dist/components/inputs/segmented-control/segmented-control.js.map +1 -1
- package/dist/components/inputs/stepper/stepper.d.ts +17 -0
- package/dist/components/inputs/stepper/stepper.d.ts.map +1 -1
- package/dist/components/inputs/stepper/stepper.js +22 -0
- package/dist/components/inputs/stepper/stepper.js.map +1 -1
- package/dist/components/inputs/stepper/stepper.template.js +1 -1
- package/dist/components/inputs/stepper/stepper.template.js.map +1 -1
- package/dist/components/inputs/switch/switch.d.ts +3 -0
- package/dist/components/inputs/switch/switch.d.ts.map +1 -1
- package/dist/components/inputs/switch/switch.js +3 -0
- package/dist/components/inputs/switch/switch.js.map +1 -1
- package/dist/components/inputs/switch-field/switch-field.d.ts +3 -0
- package/dist/components/inputs/switch-field/switch-field.d.ts.map +1 -1
- package/dist/components/inputs/switch-field/switch-field.js +3 -0
- package/dist/components/inputs/switch-field/switch-field.js.map +1 -1
- package/dist/components/inputs/text-editor/text-editor.d.ts +3 -0
- package/dist/components/inputs/text-editor/text-editor.d.ts.map +1 -1
- package/dist/components/inputs/text-editor/text-editor.js +4 -1
- package/dist/components/inputs/text-editor/text-editor.js.map +1 -1
- package/dist/components/inputs/text-field/text-field.d.ts +30 -0
- package/dist/components/inputs/text-field/text-field.d.ts.map +1 -1
- package/dist/components/inputs/text-field/text-field.js +60 -0
- package/dist/components/inputs/text-field/text-field.js.map +1 -1
- package/dist/components/inputs/text-field/text-field.template.d.ts.map +1 -1
- package/dist/components/inputs/text-field/text-field.template.js +3 -0
- package/dist/components/inputs/text-field/text-field.template.js.map +1 -1
- package/dist/components/inputs/time-field/time-field.d.ts +6 -0
- package/dist/components/inputs/time-field/time-field.d.ts.map +1 -1
- package/dist/components/inputs/time-field/time-field.js +11 -0
- package/dist/components/inputs/time-field/time-field.js.map +1 -1
- package/dist/components/inputs/time-field/time-field.template.d.ts.map +1 -1
- package/dist/components/inputs/time-field/time-field.template.js +7 -1
- package/dist/components/inputs/time-field/time-field.template.js.map +1 -1
- package/dist/components/inputs/time-picker/time-picker.d.ts +3 -0
- package/dist/components/inputs/time-picker/time-picker.d.ts.map +1 -1
- package/dist/components/inputs/time-picker/time-picker.js +4 -1
- package/dist/components/inputs/time-picker/time-picker.js.map +1 -1
- package/dist/components/inputs/toggle-button/toggle-button.d.ts +10 -0
- package/dist/components/inputs/toggle-button/toggle-button.d.ts.map +1 -1
- package/dist/components/inputs/toggle-button/toggle-button.js +14 -0
- package/dist/components/inputs/toggle-button/toggle-button.js.map +1 -1
- package/dist/components/inputs/toggle-button-group/toggle-button-group.d.ts +11 -0
- package/dist/components/inputs/toggle-button-group/toggle-button-group.d.ts.map +1 -1
- package/dist/components/inputs/toggle-button-group/toggle-button-group.js +16 -6
- package/dist/components/inputs/toggle-button-group/toggle-button-group.js.map +1 -1
- package/dist/components/inputs/token-field/token-field.d.ts +6 -0
- package/dist/components/inputs/token-field/token-field.d.ts.map +1 -1
- package/dist/components/inputs/token-field/token-field.js +13 -0
- package/dist/components/inputs/token-field/token-field.js.map +1 -1
- package/dist/components/layout/box/box.d.ts +3 -3
- package/dist/components/layout/box/box.d.ts.map +1 -1
- package/dist/components/layout/box/box.js +3 -3
- package/dist/components/layout/box/box.js.map +1 -1
- package/dist/components/layout/box/box.styles.d.ts.map +1 -1
- package/dist/components/layout/box/box.styles.js +3 -6
- package/dist/components/layout/box/box.styles.js.map +1 -1
- package/dist/components/layout/sheet/sheet.styles.d.ts.map +1 -1
- package/dist/components/layout/sheet/sheet.styles.js +10 -3
- package/dist/components/layout/sheet/sheet.styles.js.map +1 -1
- package/dist/components/lists-and-tables/list/list.d.ts +60 -45
- package/dist/components/lists-and-tables/list/list.d.ts.map +1 -1
- package/dist/components/lists-and-tables/list/list.js +94 -80
- package/dist/components/lists-and-tables/list/list.js.map +1 -1
- package/dist/components/lists-and-tables/list-item/list-item.d.ts +94 -21
- package/dist/components/lists-and-tables/list-item/list-item.d.ts.map +1 -1
- package/dist/components/lists-and-tables/list-item/list-item.js +275 -48
- package/dist/components/lists-and-tables/list-item/list-item.js.map +1 -1
- package/dist/components/lists-and-tables/list-item/list-item.styles.d.ts.map +1 -1
- package/dist/components/lists-and-tables/list-item/list-item.styles.js +116 -34
- package/dist/components/lists-and-tables/list-item/list-item.styles.js.map +1 -1
- package/dist/components/lists-and-tables/list-item/list-item.template.d.ts +1 -1
- package/dist/components/lists-and-tables/list-item/list-item.template.d.ts.map +1 -1
- package/dist/components/lists-and-tables/list-item/list-item.template.js +5 -2
- package/dist/components/lists-and-tables/list-item/list-item.template.js.map +1 -1
- package/dist/components/lists-and-tables/list-item-segment/list-item-segment.d.ts +116 -0
- package/dist/components/lists-and-tables/list-item-segment/list-item-segment.d.ts.map +1 -0
- package/dist/components/lists-and-tables/{list-item-action/list-item-action.js → list-item-segment/list-item-segment.js} +77 -52
- package/dist/components/lists-and-tables/list-item-segment/list-item-segment.js.map +1 -0
- package/dist/components/lists-and-tables/list-item-segment/list-item-segment.styles.d.ts +2 -0
- package/dist/components/lists-and-tables/list-item-segment/list-item-segment.styles.d.ts.map +1 -0
- package/dist/components/lists-and-tables/list-item-segment/list-item-segment.styles.js +179 -0
- package/dist/components/lists-and-tables/list-item-segment/list-item-segment.styles.js.map +1 -0
- package/dist/components/lists-and-tables/list-item-segment/list-item-segment.template.d.ts +3 -0
- package/dist/components/lists-and-tables/list-item-segment/list-item-segment.template.d.ts.map +1 -0
- package/dist/components/lists-and-tables/{list-item-action/list-item-action.template.js → list-item-segment/list-item-segment.template.js} +5 -4
- package/dist/components/lists-and-tables/list-item-segment/list-item-segment.template.js.map +1 -0
- package/dist/components/reflect-non-default-OLaK60rT.js +37 -0
- package/dist/components/rolldown-runtime-D7D4PA-g.js +13 -0
- package/dist/components/shadow-resets-aG-rgyNQ.js +61 -0
- package/dist/components/shell-C61GCsJA.js +223 -0
- package/dist/components/status-and-feedback/badge/badge.d.ts +8 -2
- package/dist/components/status-and-feedback/badge/badge.d.ts.map +1 -1
- package/dist/components/status-and-feedback/badge/badge.js +17 -1
- package/dist/components/status-and-feedback/badge/badge.js.map +1 -1
- package/dist/components/status-and-feedback/badge/badge.styles.d.ts.map +1 -1
- package/dist/components/status-and-feedback/badge/badge.styles.js +35 -6
- package/dist/components/status-and-feedback/badge/badge.styles.js.map +1 -1
- package/dist/components/status-and-feedback/modal-dialog/modal-dialog.styles.d.ts.map +1 -1
- package/dist/components/status-and-feedback/modal-dialog/modal-dialog.styles.js +7 -0
- package/dist/components/status-and-feedback/modal-dialog/modal-dialog.styles.js.map +1 -1
- package/dist/components/toml-C2HBbPgG.js +59 -0
- package/dist/components/visibility-mixin-GxbwkBb1.js +104 -0
- package/dist/components/with-translations-DzAdFTK8.js +48 -0
- package/dist/css/variables.css +25 -1
- package/dist/nldd.min.js +2797 -2355
- package/dist/types/vue.d.ts +106 -48
- package/dist/utilities/implicit-submission.d.ts +31 -0
- package/dist/utilities/implicit-submission.d.ts.map +1 -0
- package/dist/utilities/implicit-submission.js +65 -0
- package/dist/utilities/implicit-submission.js.map +1 -0
- package/dist/utilities/owned-attribute.d.ts +19 -0
- package/dist/utilities/owned-attribute.d.ts.map +1 -0
- package/dist/utilities/owned-attribute.js +32 -0
- package/dist/utilities/owned-attribute.js.map +1 -0
- package/dist/utilities/scroll-mode-controller.d.ts +9 -1
- package/dist/utilities/scroll-mode-controller.d.ts.map +1 -1
- package/dist/utilities/scroll-mode-controller.js +10 -2
- package/dist/utilities/scroll-mode-controller.js.map +1 -1
- package/package.json +10 -6
- package/dist/components/gherkin-DhZlEZiy.js +0 -115
- package/dist/components/index-8pDDdMeW.js +0 -384
- package/dist/components/index-C7QocEcT.js +0 -81
- package/dist/components/index-CDz7-C9c.js +0 -177
- package/dist/components/index-CWQunWUb.js +0 -75039
- package/dist/components/index-CoY3JfIy.js +0 -688
- package/dist/components/index-DP9dl7P7.js +0 -703
- package/dist/components/index-DV_2YpaH.js +0 -405
- package/dist/components/lists-and-tables/list-item-action/list-item-action.d.ts +0 -108
- package/dist/components/lists-and-tables/list-item-action/list-item-action.d.ts.map +0 -1
- package/dist/components/lists-and-tables/list-item-action/list-item-action.js.map +0 -1
- package/dist/components/lists-and-tables/list-item-action/list-item-action.styles.d.ts +0 -2
- package/dist/components/lists-and-tables/list-item-action/list-item-action.styles.d.ts.map +0 -1
- package/dist/components/lists-and-tables/list-item-action/list-item-action.styles.js +0 -145
- package/dist/components/lists-and-tables/list-item-action/list-item-action.styles.js.map +0 -1
- package/dist/components/lists-and-tables/list-item-action/list-item-action.template.d.ts +0 -3
- package/dist/components/lists-and-tables/list-item-action/list-item-action.template.d.ts.map +0 -1
- package/dist/components/lists-and-tables/list-item-action/list-item-action.template.js.map +0 -1
- package/dist/components/shell-BlsXDxCn.js +0 -222
- package/dist/components/toml-BOuWGMcf.js +0 -76
|
@@ -13,10 +13,62 @@ import { template } from './list-item.template.js';
|
|
|
13
13
|
import { isPointerMode } from '../../../utilities/input-modality.js';
|
|
14
14
|
import { withTranslations } from '../../../utilities/with-translations.js';
|
|
15
15
|
import { nlddListItemTranslations } from './list-item.i18n.js';
|
|
16
|
+
/** Anything in a row's light DOM that is a tab stop of its own. `[tabindex]`
|
|
17
|
+
* counts because an authored one makes any element focusable; the value itself
|
|
18
|
+
* is read per element, and put back when the row becomes the current one. */
|
|
19
|
+
const OWN_TAB_STOP = 'a[href], button, input, select, textarea, [contenteditable]:not([contenteditable="false"]), [tabindex]';
|
|
20
|
+
/** Keyed on the element, so a row that is re-rendered around the same control
|
|
21
|
+
* still knows what the consumer authored. */
|
|
22
|
+
const authoredTabState = new WeakMap();
|
|
23
|
+
function authoredStateOf(el) {
|
|
24
|
+
let authored = authoredTabState.get(el);
|
|
25
|
+
if (!authored) {
|
|
26
|
+
authored = { noTab: 'noTab' in el ? el.noTab : undefined, tabindex: el.getAttribute('tabindex') };
|
|
27
|
+
authoredTabState.set(el, authored);
|
|
28
|
+
}
|
|
29
|
+
return authored;
|
|
30
|
+
}
|
|
31
|
+
function applyAuthoredTabState(el, authored) {
|
|
32
|
+
if (authored.noTab !== undefined) {
|
|
33
|
+
el.noTab = authored.noTab;
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
if (authored.tabindex === null)
|
|
37
|
+
el.removeAttribute('tabindex');
|
|
38
|
+
else
|
|
39
|
+
el.setAttribute('tabindex', authored.tabindex);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Puts one control in or out of the tab order on behalf of the row it sits in.
|
|
43
|
+
*
|
|
44
|
+
* A design-system control keeps its tab stop inside its own shadow root, where
|
|
45
|
+
* a tabindex on the host cannot reach it, so it carries `no-tab` for exactly
|
|
46
|
+
* this. Everything else is native and takes the tabindex directly. A consumer
|
|
47
|
+
* who set either themselves keeps it: their `no-tab` or `tabindex="-1"` is a
|
|
48
|
+
* decision, not a leftover.
|
|
49
|
+
*/
|
|
50
|
+
function setTabbable(el, tabbable) {
|
|
51
|
+
const authored = authoredStateOf(el);
|
|
52
|
+
if (authored.noTab !== undefined) {
|
|
53
|
+
el.noTab = authored.noTab || !tabbable;
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
if (tabbable)
|
|
57
|
+
applyAuthoredTabState(el, authored);
|
|
58
|
+
else
|
|
59
|
+
el.setAttribute('tabindex', '-1');
|
|
60
|
+
}
|
|
61
|
+
function releaseTabbable(el) {
|
|
62
|
+
const authored = authoredTabState.get(el);
|
|
63
|
+
if (!authored)
|
|
64
|
+
return;
|
|
65
|
+
applyAuthoredTabState(el, authored);
|
|
66
|
+
authoredTabState.delete(el);
|
|
67
|
+
}
|
|
16
68
|
/**
|
|
17
69
|
* A row within an `nldd-list`. Renders as a link when `href` is set, as a
|
|
18
70
|
* checkbox when `checkbox` is set, as a button when `button` is set, or as a
|
|
19
|
-
* plain container otherwise. All cells and
|
|
71
|
+
* plain container otherwise. All cells and segments share one flat
|
|
20
72
|
* slot, in source order.
|
|
21
73
|
*
|
|
22
74
|
* ## Geometry
|
|
@@ -30,7 +82,7 @@ import { nlddListItemTranslations } from './list-item.i18n.js';
|
|
|
30
82
|
* itself outward (`is-interactive` host class → negative inline margin)
|
|
31
83
|
* and pads the row block back by the same amount, so content stays on the
|
|
32
84
|
* grid. A row-wide action owns that padding itself, making the whole
|
|
33
|
-
* widened box one hit area; slotted
|
|
85
|
+
* widened box one hit area; slotted segments stay in the grid, so their
|
|
34
86
|
* footprint is position-independent and tree columns line up at any depth.
|
|
35
87
|
*
|
|
36
88
|
* ## Divider
|
|
@@ -39,7 +91,7 @@ import { nlddListItemTranslations } from './list-item.i18n.js';
|
|
|
39
91
|
* an avatar, a checkbox, or the spacers a tree indents with. Rows of different
|
|
40
92
|
* shapes then still line their dividers up with each other, and a tree's
|
|
41
93
|
* dividers step inward with its indentation. Text inside an
|
|
42
|
-
* `nldd-list-item-
|
|
94
|
+
* `nldd-list-item-segment` counts as the row's content, and the marker is that
|
|
43
95
|
* text cell rather than the action: the action carries its own inline padding,
|
|
44
96
|
* so its edge sits before the words. A row with no text or title cell keeps the
|
|
45
97
|
* full content width. Mark a cell with `divider-start` and/or `divider-end` to
|
|
@@ -51,7 +103,7 @@ import { nlddListItemTranslations } from './list-item.i18n.js';
|
|
|
51
103
|
*
|
|
52
104
|
* ## Disclosure
|
|
53
105
|
* A branch row can disclose its children in two ways: a dedicated
|
|
54
|
-
* `nldd-list-item-
|
|
106
|
+
* `nldd-list-item-segment[disclosure]` segment (only the chevron is clickable),
|
|
55
107
|
* or the row itself as the control (`button` + `expanded`, the whole row
|
|
56
108
|
* toggles). In the second case, mark the chevron's `nldd-icon-cell` with
|
|
57
109
|
* `disclosure` and the row turns it with `expanded` — the same affordance,
|
|
@@ -84,17 +136,19 @@ import { nlddListItemTranslations } from './list-item.i18n.js';
|
|
|
84
136
|
* @element nldd-list-item
|
|
85
137
|
*
|
|
86
138
|
* @attr {'sm'|'md'} size - Row size (default: 'md'). Pushed onto the cells whose `size` means the same scale (nldd-text-cell, nldd-drag-handle-cell), so it is written once per row instead of once per cell. A size set on the cell itself wins. Cells where `size` means something else — pixels on nldd-icon-cell / nldd-spacer-cell, a heading scale on nldd-title-cell — are left alone.
|
|
87
|
-
* @attr {boolean} selected - Marks the item as selected. Selection is consumer-managed; the list never sets it. In a `navigation` parent it puts `aria-current="page"` on the inner action, in a `listbox` parent it drives `aria-selected`.
|
|
88
|
-
* @attr {boolean}
|
|
89
|
-
* @attr {boolean}
|
|
139
|
+
* @attr {boolean} selected - Marks the item as selected: it is one of the rows you picked. Selection is consumer-managed; the list never sets it. In a `navigation` parent it puts `aria-current="page"` on the inner action, in a `listbox` parent it drives `aria-selected`.
|
|
140
|
+
* @attr {boolean} current - Marks the item as the one you are on: the page a menu row points at, the record a list has open. Exactly one row in a list carries it, where `selected` may be on many. It paints like `selected` at rest, and takes the highlighted fill while focus is anywhere in the row — including inside a nested `nldd-list-item-segment`, which is what a segmented row needs: the focus never reaches the row's own control, because there is none. In a `navigation` parent it puts `aria-current="page"` on the inner action. On a segmented row set it on the segment that holds the link instead: the row reads `current` off its own segments and paints itself, so it is written once, where `aria-current` belongs.
|
|
141
|
+
* @attr {boolean} button - Renders the item as a `<button>`. Last of the three: `href` and `checkbox` both win over it.
|
|
142
|
+
* @attr {boolean} checkbox - Makes the whole row a `role="checkbox"` control. Wins over `button`, loses to `href`.
|
|
90
143
|
* @attr {boolean} checked - Checked state of a `checkbox` row; the item toggles it on activation
|
|
91
|
-
* @attr {boolean}
|
|
92
|
-
* @attr {
|
|
144
|
+
* @attr {boolean} disabled - Switches the row's own control off: a `button` or `checkbox` row stops responding and dims, a `href` row gets `aria-disabled` and its click is blocked (a link cannot be disabled natively). A row without a control of its own has nothing to switch off, and segments carry their own `disabled`. The arrow keys skip a disabled row.
|
|
145
|
+
* @attr {boolean} expanded - Disclosure state. Drives the `children` group's visibility AND supplies `aria-expanded` — to the row's own control when the row is interactive, or to the segment marked `disclosure`. Written once either way; the item DEV-warns when there is nowhere for it to live.
|
|
146
|
+
* @attr {string} href - Renders the item as an `<a>` with this URL. Wins over `checkbox` and `button`; without any of the three the item is a plain container with no action.
|
|
93
147
|
* @attr {string} target - Link target forwarded to the `<a>` (e.g. '_blank'); only applies with `href`. With '_blank' a visually hidden "opens in new tab" announcement is added for assistive technology.
|
|
94
148
|
* @attr {string} rel - Link rel forwarded to the `<a>` (e.g. 'noopener noreferrer'); only applies with `href`
|
|
95
149
|
* @attr {boolean} reorderable - Set by the parent `nldd-list` when its own `reorderable` is on (with `type="list"`); consumers do not set this. Serves as a CSS hook for drag handle visibility.
|
|
96
150
|
*
|
|
97
|
-
* @slot - Cells and
|
|
151
|
+
* @slot - Cells and segments, in source order
|
|
98
152
|
* @slot children - Child rows of a branch in an `nldd-list type="tree"`. Rendered as a `role="group"` below the row, hidden while `expanded` is false. The nesting IS the hierarchy, so aria-level / -posinset / -setsize are derived, not authored. The group has no styling of its own: repeat a spacer-cell per level to indent, or show depth some other way.
|
|
99
153
|
*
|
|
100
154
|
* @fires change - On a `checkbox` row after it toggles; detail: { checked: boolean }
|
|
@@ -104,20 +158,39 @@ let NLDDListItem = NLDDListItem_1 = class NLDDListItem extends withTranslations(
|
|
|
104
158
|
super(...arguments);
|
|
105
159
|
this.size = 'md';
|
|
106
160
|
this.selected = false;
|
|
161
|
+
/**
|
|
162
|
+
* The row you are on, as opposed to the rows you picked (`selected`).
|
|
163
|
+
*
|
|
164
|
+
* Kept apart because the two say different things and a list can show both:
|
|
165
|
+
* a checkbox list where three rows are ticked and one is open. At rest they
|
|
166
|
+
* paint the same, so a menu reads the same as it always did; the difference
|
|
167
|
+
* shows when focus is in the row.
|
|
168
|
+
*/
|
|
169
|
+
this.current = false;
|
|
107
170
|
/** When set, renders the item as a button; ignored when href is set. */
|
|
108
171
|
this.button = false;
|
|
109
172
|
/** When set, the whole row is the checkbox control. Ignored when href is set. */
|
|
110
173
|
this.checkbox = false;
|
|
111
174
|
/** Checked state of a `checkbox` row. Toggled by the item on activation. */
|
|
112
175
|
this.checked = false;
|
|
176
|
+
/**
|
|
177
|
+
* Switches off the row's own control.
|
|
178
|
+
*
|
|
179
|
+
* Only the row's own: a row built out of segments has no control here, and
|
|
180
|
+
* each segment carries its own `disabled`. A link cannot be disabled the way
|
|
181
|
+
* a button can, so there it is `aria-disabled` plus a blocked click, the
|
|
182
|
+
* same trade `nldd-button` makes.
|
|
183
|
+
*/
|
|
184
|
+
this.disabled = false;
|
|
113
185
|
/** Set by the parent nldd-list when reorderable is enabled. Used as a CSS hook for drag handle visibility. */
|
|
114
186
|
this.reorderable = false;
|
|
115
187
|
this._showChildren = false;
|
|
116
188
|
this._parentType = 'list';
|
|
117
|
-
/** Set by the parent nldd-list when
|
|
189
|
+
/** Set by the parent nldd-list when it runs the roving tabindex (everywhere
|
|
190
|
+
* except a listbox and a reorderable list).
|
|
118
191
|
* Switches the inner action from a normal tab stop to a roving one. */
|
|
119
192
|
this._arrowNavigation = false;
|
|
120
|
-
/** Set by the parent nldd-list:
|
|
193
|
+
/** Set by the parent nldd-list: while the roving runs, exactly one item
|
|
121
194
|
* is the roving entry point (tabindex 0); the rest are tabindex -1. */
|
|
122
195
|
this._rovingActive = false;
|
|
123
196
|
/** Set by the parent nldd-list in `type="listbox"`: marks this option as
|
|
@@ -129,6 +202,10 @@ let NLDDListItem = NLDDListItem_1 = class NLDDListItem extends withTranslations(
|
|
|
129
202
|
this._isBoxed = false;
|
|
130
203
|
this._hasCheckedSegment = false;
|
|
131
204
|
this._lightDomObserver = null;
|
|
205
|
+
/** The controls in this row the roving takes in and out of the tab order.
|
|
206
|
+
* Rebuilt when the row's light DOM changes, so a keypress does not walk
|
|
207
|
+
* every cell of every row again. */
|
|
208
|
+
this._rovingControlsCache = null;
|
|
132
209
|
/** Watches the row and its divider-marker cells for size changes; marker
|
|
133
210
|
* insets are measured, so any reflow can move them. */
|
|
134
211
|
this._dividerMarkerObserver = null;
|
|
@@ -137,6 +214,13 @@ let NLDDListItem = NLDDListItem_1 = class NLDDListItem extends withTranslations(
|
|
|
137
214
|
/** Remembers the size a cell was authored with, so a later push can restore it. */
|
|
138
215
|
this._ownCellSize = new WeakMap();
|
|
139
216
|
this._handleClick = (e) => {
|
|
217
|
+
// A disabled <button> never gets here, but a link does: there is no such
|
|
218
|
+
// thing as a disabled <a>, so the row stops the navigation itself.
|
|
219
|
+
if (this.disabled) {
|
|
220
|
+
e.preventDefault();
|
|
221
|
+
e.stopPropagation();
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
140
224
|
// Safari and Firefox on Mac don't focus buttons on click. Force focus
|
|
141
225
|
// so :has(.list-item__action:focus) and :focus-within CSS work reliably.
|
|
142
226
|
this._action?.focus();
|
|
@@ -160,7 +244,24 @@ let NLDDListItem = NLDDListItem_1 = class NLDDListItem extends withTranslations(
|
|
|
160
244
|
this._handleFocusOut = () => {
|
|
161
245
|
this._action?.classList.remove('is-pointer-focus');
|
|
162
246
|
};
|
|
247
|
+
/**
|
|
248
|
+
* See the same handler in nldd-list-item-segment: Safari hands focus to the
|
|
249
|
+
* body while the mouse is down, which drops a row out of its lit state until
|
|
250
|
+
* you let go. Left alone on a reorderable row and on a row whose press came
|
|
251
|
+
* from a nested one, where the default is doing real work (dragging).
|
|
252
|
+
*/
|
|
253
|
+
this._onMouseDown = (e) => {
|
|
254
|
+
if (e.button > 0 || this.reorderable)
|
|
255
|
+
return;
|
|
256
|
+
if (this._isFromNestedRow(e))
|
|
257
|
+
return;
|
|
258
|
+
if (!this._action)
|
|
259
|
+
return;
|
|
260
|
+
e.preventDefault();
|
|
261
|
+
};
|
|
163
262
|
this._onPointerDown = (e) => {
|
|
263
|
+
if (this.disabled)
|
|
264
|
+
return;
|
|
164
265
|
// Primary button / touch / pen only (mouse right-click has button > 0).
|
|
165
266
|
if (e.button > 0)
|
|
166
267
|
return;
|
|
@@ -170,6 +271,11 @@ let NLDDListItem = NLDDListItem_1 = class NLDDListItem extends withTranslations(
|
|
|
170
271
|
if (this._isFromNestedRow(e))
|
|
171
272
|
return;
|
|
172
273
|
this._action?.classList.add('is-pressed');
|
|
274
|
+
// Safari does not focus a <button> on click, so a row whose paint follows
|
|
275
|
+
// the focus in it would stay unlit there while the other browsers light
|
|
276
|
+
// up. Focusing on the press makes the three agree; the ring stays hidden
|
|
277
|
+
// because is-pointer-focus already marks a pointer focus.
|
|
278
|
+
this._action?.focus({ preventScroll: true });
|
|
173
279
|
};
|
|
174
280
|
this._clearPressed = () => {
|
|
175
281
|
this._action?.classList.remove('is-pressed');
|
|
@@ -193,10 +299,11 @@ let NLDDListItem = NLDDListItem_1 = class NLDDListItem extends withTranslations(
|
|
|
193
299
|
// turns into a scroll (the browser fires pointercancel for that pointer),
|
|
194
300
|
// so `active` never sticks while the user scrolls the list.
|
|
195
301
|
this.addEventListener('pointerdown', this._onPointerDown);
|
|
302
|
+
this.addEventListener('mousedown', this._onMouseDown);
|
|
196
303
|
this.addEventListener('pointerup', this._clearPressed);
|
|
197
304
|
this.addEventListener('pointercancel', this._clearPressed);
|
|
198
305
|
// Light-DOM state the row derives styling from: a checked checkbox-
|
|
199
|
-
// segment (row-wide selected fill), which
|
|
306
|
+
// segment (row-wide selected fill), which segments own a row edge, and
|
|
200
307
|
// the divider markers. Attribute observation, not events: consumers
|
|
201
308
|
// also set these programmatically via setAttribute.
|
|
202
309
|
this._lightDomObserver = new MutationObserver(() => this._onLightDomChange());
|
|
@@ -204,7 +311,7 @@ let NLDDListItem = NLDDListItem_1 = class NLDDListItem extends withTranslations(
|
|
|
204
311
|
subtree: true,
|
|
205
312
|
childList: true,
|
|
206
313
|
attributes: true,
|
|
207
|
-
attributeFilter: ['checked', 'divider-start', 'divider-end'],
|
|
314
|
+
attributeFilter: ['checked', 'current', 'divider-start', 'divider-end'],
|
|
208
315
|
});
|
|
209
316
|
this._onLightDomChange();
|
|
210
317
|
}
|
|
@@ -214,6 +321,7 @@ let NLDDListItem = NLDDListItem_1 = class NLDDListItem extends withTranslations(
|
|
|
214
321
|
this.removeEventListener('focusout', this._handleFocusOut);
|
|
215
322
|
this.removeEventListener('click', this._handleClick);
|
|
216
323
|
this.removeEventListener('pointerdown', this._onPointerDown);
|
|
324
|
+
this.removeEventListener('mousedown', this._onMouseDown);
|
|
217
325
|
this.removeEventListener('pointerup', this._clearPressed);
|
|
218
326
|
this.removeEventListener('pointercancel', this._clearPressed);
|
|
219
327
|
this._lightDomObserver?.disconnect();
|
|
@@ -223,38 +331,118 @@ let NLDDListItem = NLDDListItem_1 = class NLDDListItem extends withTranslations(
|
|
|
223
331
|
}
|
|
224
332
|
_onLightDomChange() {
|
|
225
333
|
this._updateCheckedSegment();
|
|
334
|
+
this._updateCurrentSegment();
|
|
226
335
|
this._updateInteractive();
|
|
227
336
|
this._measureDividerMarkers();
|
|
337
|
+
this._rovingControlsCache = null;
|
|
338
|
+
// A framework can fill a row in a later pass than the one that put the row
|
|
339
|
+
// in the list, so both have to run again: the tab stops inside this row,
|
|
340
|
+
// and the list's choice of which rows the arrows stop at — a row that just
|
|
341
|
+
// gained its only control was not a stop when that choice was made.
|
|
342
|
+
if (this._arrowNavigation) {
|
|
343
|
+
this._syncRovingTabStops();
|
|
344
|
+
this._parentList?._updateRoving();
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
get _parentList() {
|
|
348
|
+
return this.closest('nldd-list');
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* The controls in this row that own a tab stop: a design-system control that
|
|
352
|
+
* carries `no-tab`, or anything natively focusable. Segments are left
|
|
353
|
+
* out — they have their own channel (`_tabbable`) — but a control slotted
|
|
354
|
+
* inside one is not, so it is managed here.
|
|
355
|
+
*
|
|
356
|
+
* Custom elements that have not upgraded yet cannot answer whether they carry
|
|
357
|
+
* `no-tab`, so the cache is dropped and the row re-syncs once they do.
|
|
358
|
+
*/
|
|
359
|
+
_rovingControls() {
|
|
360
|
+
if (this._rovingControlsCache)
|
|
361
|
+
return this._rovingControlsCache;
|
|
362
|
+
const pending = new Set();
|
|
363
|
+
const controls = this._ownDescendants('*').filter((el) => {
|
|
364
|
+
const tag = el.tagName.toLowerCase();
|
|
365
|
+
if (tag === 'nldd-list-item-segment')
|
|
366
|
+
return false;
|
|
367
|
+
if (tag.includes('-') && !customElements.get(tag)) {
|
|
368
|
+
pending.add(tag);
|
|
369
|
+
return false;
|
|
370
|
+
}
|
|
371
|
+
return 'noTab' in el || el.matches(OWN_TAB_STOP);
|
|
372
|
+
});
|
|
373
|
+
this._rovingControlsCache = controls;
|
|
374
|
+
pending.forEach((tag) => {
|
|
375
|
+
customElements.whenDefined(tag).then(() => {
|
|
376
|
+
this._rovingControlsCache = null;
|
|
377
|
+
if (this._arrowNavigation)
|
|
378
|
+
this._syncRovingTabStops();
|
|
379
|
+
});
|
|
380
|
+
});
|
|
381
|
+
return controls;
|
|
382
|
+
}
|
|
383
|
+
/**
|
|
384
|
+
* Whether the arrow keys stop at this row.
|
|
385
|
+
*
|
|
386
|
+
* Anything you can operate makes a row a stop: its own link, button or
|
|
387
|
+
* checkbox, a segment, or a control sitting in one of its cells. A
|
|
388
|
+
* row of nothing but text is skipped, because focus that leads nowhere is a
|
|
389
|
+
* dead end for a keyboard.
|
|
390
|
+
*
|
|
391
|
+
* @internal Read by the parent nldd-list.
|
|
392
|
+
*/
|
|
393
|
+
get _isRovingStop() {
|
|
394
|
+
// Nothing to land on: a disabled control is not focusable, so a stop there
|
|
395
|
+
// would swallow the arrow key and leave focus where it was.
|
|
396
|
+
if (this.disabled)
|
|
397
|
+
return false;
|
|
398
|
+
if (this.href || this.button || this.checkbox)
|
|
399
|
+
return true;
|
|
400
|
+
if (this._ownDescendants('nldd-list-item-segment:not([disabled])').length > 0)
|
|
401
|
+
return true;
|
|
402
|
+
return this._rovingControls().some((control) => !control.hasAttribute('disabled'));
|
|
403
|
+
}
|
|
404
|
+
/**
|
|
405
|
+
* A segment marked `current` makes the whole row the current one.
|
|
406
|
+
*
|
|
407
|
+
* A row cut into segments has no control of its own, so `aria-current="page"`
|
|
408
|
+
* belongs on the segment that holds the link. Written there, the row would
|
|
409
|
+
* stay unpainted and the consumer had to set `current` twice, once for the
|
|
410
|
+
* semantics and once for the colour, with nothing to catch the two drifting
|
|
411
|
+
* apart. The row reads it off its own segments instead — reading, not
|
|
412
|
+
* writing: the attributes stay the consumer's.
|
|
413
|
+
*/
|
|
414
|
+
_updateCurrentSegment() {
|
|
415
|
+
this.toggleAttribute('data-current', this._ownDescendants('nldd-list-item-segment[current]').length > 0);
|
|
228
416
|
}
|
|
229
417
|
/** A checked checkbox-segment reads as "this row is selected", so the fill
|
|
230
418
|
* covers the whole row — including a disclosure segment — instead of
|
|
231
|
-
* stopping at the
|
|
419
|
+
* stopping at the segment boundary. Scoped to own descendants: a checked
|
|
232
420
|
* row in a nested branch must not light up its ancestors. */
|
|
233
421
|
_updateCheckedSegment() {
|
|
234
422
|
this._hasCheckedSegment =
|
|
235
|
-
this._ownDescendants('nldd-list-item-
|
|
423
|
+
this._ownDescendants('nldd-list-item-segment[checkbox][checked]').length > 0;
|
|
236
424
|
}
|
|
237
425
|
/** A row with any action — its own href/button/checkbox or a slotted
|
|
238
426
|
* segment — carries the widened geometry: negative host margin plus the
|
|
239
427
|
* compensating row padding (see the geometry rules in the class doc).
|
|
240
428
|
*
|
|
241
|
-
* An
|
|
242
|
-
* so the row drops its own there and the
|
|
429
|
+
* An segment at a row edge owns the padding for that side itself,
|
|
430
|
+
* so the row drops its own there and the segment lands on the row's edge.
|
|
243
431
|
* Stamped as classes because the CSS cannot ask: `:has()` is not allowed
|
|
244
432
|
* inside `:host()`, and the row's own padding is what has to change — a
|
|
245
|
-
* `::slotted()` rule could only reach the
|
|
433
|
+
* `::slotted()` rule could only reach the segment. */
|
|
246
434
|
_updateInteractive() {
|
|
247
435
|
const interactive = !!this.href || this.button || this.checkbox ||
|
|
248
|
-
this._ownDescendants('nldd-list-item-
|
|
436
|
+
this._ownDescendants('nldd-list-item-segment').length > 0;
|
|
249
437
|
this.classList.toggle('is-interactive', interactive);
|
|
250
438
|
// The row's own children, not the branch's child rows: those go to the
|
|
251
439
|
// `children` slot and render BELOW the row, so on a branch row the last
|
|
252
440
|
// element child is a nested row rather than the row's trailing segment.
|
|
253
441
|
const ownChildren = Array.from(this.children)
|
|
254
442
|
.filter(el => el.getAttribute('slot') !== 'children');
|
|
255
|
-
const isSegment = (el) => el?.tagName.toLowerCase() === 'nldd-list-item-
|
|
256
|
-
this.classList.toggle('has-leading-
|
|
257
|
-
this.classList.toggle('has-trailing-
|
|
443
|
+
const isSegment = (el) => el?.tagName.toLowerCase() === 'nldd-list-item-segment';
|
|
444
|
+
this.classList.toggle('has-leading-segment', isSegment(ownChildren[0]));
|
|
445
|
+
this.classList.toggle('has-trailing-segment', isSegment(ownChildren[ownChildren.length - 1]));
|
|
258
446
|
}
|
|
259
447
|
firstUpdated() {
|
|
260
448
|
// Clones are visual-only copies inside nldd-list's shadow root: their
|
|
@@ -271,12 +459,12 @@ let NLDDListItem = NLDDListItem_1 = class NLDDListItem extends withTranslations(
|
|
|
271
459
|
}
|
|
272
460
|
/**
|
|
273
461
|
* The row's own descendants for `selector` — everything down to and inside
|
|
274
|
-
* its
|
|
462
|
+
* its segments, but NOT inside a nested row. In a tree the child rows
|
|
275
463
|
* are DOM children of this row, so a plain querySelectorAll would push this
|
|
276
464
|
* row's state into theirs (a parent's `expanded` turning every nested
|
|
277
465
|
* chevron, its `size` overwriting theirs). A `:scope >` child selector is
|
|
278
466
|
* too strict the other way: cells legitimately sit one level deeper, inside
|
|
279
|
-
* an nldd-list-item-
|
|
467
|
+
* an nldd-list-item-segment.
|
|
280
468
|
*/
|
|
281
469
|
_ownDescendants(selector) {
|
|
282
470
|
return Array.from(this.querySelectorAll(selector))
|
|
@@ -311,7 +499,7 @@ let NLDDListItem = NLDDListItem_1 = class NLDDListItem extends withTranslations(
|
|
|
311
499
|
});
|
|
312
500
|
}
|
|
313
501
|
updated(changed) {
|
|
314
|
-
if (changed.has('selected') || changed.has('button') || changed.has('checkbox') || changed.has('href') || changed.has('_parentType')) {
|
|
502
|
+
if (changed.has('selected') || changed.has('current') || changed.has('button') || changed.has('checkbox') || changed.has('href') || changed.has('_parentType')) {
|
|
315
503
|
this._updateAriaState();
|
|
316
504
|
}
|
|
317
505
|
if (changed.has('button') || changed.has('checkbox') || changed.has('href')) {
|
|
@@ -324,6 +512,14 @@ let NLDDListItem = NLDDListItem_1 = class NLDDListItem extends withTranslations(
|
|
|
324
512
|
if (changed.has('_arrowNavigation') || changed.has('_rovingActive')) {
|
|
325
513
|
this._syncRovingTabStops();
|
|
326
514
|
}
|
|
515
|
+
// A row that switches off mid-flight stops being a stop, but the tab stop it
|
|
516
|
+
// already holds does not move by itself: a disabled anchor keeps its
|
|
517
|
+
// tabindex, so Tab would land on a row that answers to nothing until some
|
|
518
|
+
// unrelated change happened to re-run the roving.
|
|
519
|
+
if (changed.has('disabled')) {
|
|
520
|
+
this._syncRovingTabStops();
|
|
521
|
+
this._parentList?._updateRoving();
|
|
522
|
+
}
|
|
327
523
|
this._propagateSize();
|
|
328
524
|
}
|
|
329
525
|
/**
|
|
@@ -342,8 +538,8 @@ let NLDDListItem = NLDDListItem_1 = class NLDDListItem extends withTranslations(
|
|
|
342
538
|
/** Segments marked `disclosure` announce the row's expanded state, so the
|
|
343
539
|
* consumer writes it once — here, where it also drives the children group. */
|
|
344
540
|
_relayExpanded() {
|
|
345
|
-
this._ownDescendants('nldd-list-item-
|
|
346
|
-
.forEach(
|
|
541
|
+
this._ownDescendants('nldd-list-item-segment[disclosure]')
|
|
542
|
+
.forEach(segment => { segment._rowExpanded = this._resolvedExpanded; });
|
|
347
543
|
}
|
|
348
544
|
/** `expanded` needs a control to sit on; a plain container has none. */
|
|
349
545
|
_warnOnStrayExpanded() {
|
|
@@ -353,9 +549,9 @@ let NLDDListItem = NLDDListItem_1 = class NLDDListItem extends withTranslations(
|
|
|
353
549
|
return;
|
|
354
550
|
if (this.href || this.button || this.checkbox)
|
|
355
551
|
return;
|
|
356
|
-
if (this._ownDescendants('nldd-list-item-
|
|
552
|
+
if (this._ownDescendants('nldd-list-item-segment[disclosure]').length > 0)
|
|
357
553
|
return;
|
|
358
|
-
console.warn('nldd-list-item: `expanded` needs somewhere to live — make the row interactive (href, button or checkbox), or mark the
|
|
554
|
+
console.warn('nldd-list-item: `expanded` needs somewhere to live — make the row interactive (href, button or checkbox), or mark the segment that does the disclosing with `disclosure`.');
|
|
359
555
|
}
|
|
360
556
|
/** True when the item is an option in a `type="listbox"` parent. */
|
|
361
557
|
get _isListboxOption() {
|
|
@@ -388,11 +584,11 @@ let NLDDListItem = NLDDListItem_1 = class NLDDListItem extends withTranslations(
|
|
|
388
584
|
_applyParentType(type) {
|
|
389
585
|
this._parentType = type;
|
|
390
586
|
this._relayToChildren(item => item._applyParentType(type));
|
|
391
|
-
//
|
|
587
|
+
// Segments need the list type too: in a listbox they degrade to a
|
|
392
588
|
// plain container, since an `option` may not hold interactive descendants.
|
|
393
|
-
// Own
|
|
394
|
-
this._ownDescendants('nldd-list-item-
|
|
395
|
-
.forEach(
|
|
589
|
+
// Own segments only — nested rows get the relay above and push their own.
|
|
590
|
+
this._ownDescendants('nldd-list-item-segment')
|
|
591
|
+
.forEach(segment => segment._applyParentType?.(type));
|
|
396
592
|
}
|
|
397
593
|
/** Nested rows sit in this item's `children` slot, not the list's, so a plain
|
|
398
594
|
* `querySelector` from the list walks past them. */
|
|
@@ -423,7 +619,7 @@ let NLDDListItem = NLDDListItem_1 = class NLDDListItem extends withTranslations(
|
|
|
423
619
|
}
|
|
424
620
|
// aria-current on the inner action (link/button) — navigation only
|
|
425
621
|
const action = this._action;
|
|
426
|
-
if (this._parentType === 'navigation' && this.selected && action) {
|
|
622
|
+
if (this._parentType === 'navigation' && (this.current || this.selected) && action) {
|
|
427
623
|
action.setAttribute('aria-current', 'page');
|
|
428
624
|
}
|
|
429
625
|
else {
|
|
@@ -447,7 +643,7 @@ let NLDDListItem = NLDDListItem_1 = class NLDDListItem extends withTranslations(
|
|
|
447
643
|
* full-width line back.
|
|
448
644
|
*/
|
|
449
645
|
_implicitDividerStart() {
|
|
450
|
-
// The marker is the CELL, never a
|
|
646
|
+
// The marker is the CELL, never a segment around it: the action
|
|
451
647
|
// carries its own inline padding, so its edge sits before the text. Own
|
|
452
648
|
// descendants, so a text inside a segment counts as this row's content
|
|
453
649
|
// while a nested row's text does not.
|
|
@@ -577,7 +773,7 @@ let NLDDListItem = NLDDListItem_1 = class NLDDListItem extends withTranslations(
|
|
|
577
773
|
* so consumers can call `listItemEl.focus()` without reaching into shadow DOM.
|
|
578
774
|
*/
|
|
579
775
|
focus(options) {
|
|
580
|
-
// A tree row without a control of its own (only
|
|
776
|
+
// A tree row without a control of its own (only segments, or
|
|
581
777
|
// none at all) takes focus on the host: that is where role="treeitem"
|
|
582
778
|
// sits, so assistive technology announces the row rather than a button
|
|
583
779
|
// inside it. _syncRovingTabStops gives the host the tabindex for it.
|
|
@@ -590,8 +786,9 @@ let NLDDListItem = NLDDListItem_1 = class NLDDListItem extends withTranslations(
|
|
|
590
786
|
/**
|
|
591
787
|
* The roving tab stop, spread over the row and the controls inside it: the
|
|
592
788
|
* current row is reachable with Tab, everything else only with the arrow
|
|
593
|
-
* keys. Within the current row Tab then walks its
|
|
594
|
-
* that holds a checkbox and a chevron
|
|
789
|
+
* keys. Within the current row Tab then walks its segments and any
|
|
790
|
+
* control in its cells, so a row that holds a checkbox and a chevron, or a
|
|
791
|
+
* menu button at its end, stays fully operable.
|
|
595
792
|
*
|
|
596
793
|
* A row that is not the current one carries NO tabindex at all rather than
|
|
597
794
|
* -1. A shadow host with a tabindex is a focus scope of its own, and Chromium
|
|
@@ -603,11 +800,12 @@ let NLDDListItem = NLDDListItem_1 = class NLDDListItem extends withTranslations(
|
|
|
603
800
|
* tab stop is in the DOM before focus is handed over.
|
|
604
801
|
*/
|
|
605
802
|
_syncRovingTabStops() {
|
|
606
|
-
const
|
|
607
|
-
&& el.tagName.toLowerCase() === 'nldd-list-item-
|
|
803
|
+
const ownSegments = Array.from(this.children).filter((el) => el.getAttribute('slot') !== 'children'
|
|
804
|
+
&& el.tagName.toLowerCase() === 'nldd-list-item-segment');
|
|
608
805
|
if (!this._arrowNavigation) {
|
|
609
806
|
this.removeAttribute('tabindex');
|
|
610
|
-
|
|
807
|
+
ownSegments.forEach((segment) => { segment._tabbable = undefined; });
|
|
808
|
+
this._rovingControls().forEach(releaseTabbable);
|
|
611
809
|
return;
|
|
612
810
|
}
|
|
613
811
|
// Only a row without its own control needs the host as focus target; with
|
|
@@ -618,14 +816,15 @@ let NLDDListItem = NLDDListItem_1 = class NLDDListItem extends withTranslations(
|
|
|
618
816
|
else {
|
|
619
817
|
this.setAttribute('tabindex', '0');
|
|
620
818
|
}
|
|
621
|
-
|
|
819
|
+
ownSegments.forEach((segment) => { segment._tabbable = this._rovingActive; });
|
|
820
|
+
this._rovingControls().forEach((control) => { setTabbable(control, this._rovingActive); });
|
|
622
821
|
}
|
|
623
|
-
/** The control that opens and closes this row: the
|
|
822
|
+
/** The control that opens and closes this row: the segment marked
|
|
624
823
|
* `disclosure`, or the row itself when it is a button. Never a link — Left
|
|
625
824
|
* and Right may not navigate away. */
|
|
626
825
|
get _disclosureControl() {
|
|
627
826
|
const action = Array.from(this.children).find((el) => el.getAttribute('slot') !== 'children'
|
|
628
|
-
&& el.tagName.toLowerCase() === 'nldd-list-item-
|
|
827
|
+
&& el.tagName.toLowerCase() === 'nldd-list-item-segment'
|
|
629
828
|
&& el.hasAttribute('disclosure'));
|
|
630
829
|
if (action)
|
|
631
830
|
return action;
|
|
@@ -640,7 +839,7 @@ let NLDDListItem = NLDDListItem_1 = class NLDDListItem extends withTranslations(
|
|
|
640
839
|
const control = this._disclosureControl;
|
|
641
840
|
if (!control)
|
|
642
841
|
return false;
|
|
643
|
-
// The click lands on a
|
|
842
|
+
// The click lands on a segment, and that segment pulls focus into
|
|
644
843
|
// its own control — with the pointer-focus flag set, since a click is what
|
|
645
844
|
// it sees. Focus belongs to the row: that is the roving tab stop, and the
|
|
646
845
|
// keyboard user has to keep seeing where they are.
|
|
@@ -650,6 +849,28 @@ let NLDDListItem = NLDDListItem_1 = class NLDDListItem extends withTranslations(
|
|
|
650
849
|
this.focus();
|
|
651
850
|
return true;
|
|
652
851
|
}
|
|
852
|
+
/**
|
|
853
|
+
* Activates what this row is FOR, as opposed to what folds it: the first
|
|
854
|
+
* segment that is not the disclosure. A row that is its own control
|
|
855
|
+
* needs none of this, because the key reaches that control by itself.
|
|
856
|
+
* Returns false when there is nothing but a chevron.
|
|
857
|
+
*/
|
|
858
|
+
_activatePrimary() {
|
|
859
|
+
const segments = [...this.querySelectorAll(':scope > nldd-list-item-segment')];
|
|
860
|
+
const primary = segments.find((segment) => !segment.hasAttribute('disclosure'));
|
|
861
|
+
if (!primary)
|
|
862
|
+
return false;
|
|
863
|
+
const control = primary.shadowRoot?.querySelector('a, button');
|
|
864
|
+
if (!control)
|
|
865
|
+
return false;
|
|
866
|
+
// Same trade as _activateDisclosure: the click pulls focus into the
|
|
867
|
+
// segment, and the row has to keep it, because the row is the tab stop.
|
|
868
|
+
const hadFocus = this.matches(':focus-within');
|
|
869
|
+
control.click();
|
|
870
|
+
if (hadFocus)
|
|
871
|
+
this.focus();
|
|
872
|
+
return true;
|
|
873
|
+
}
|
|
653
874
|
/** The branch this row hangs under, or undefined for a top-level row. */
|
|
654
875
|
get parentRow() {
|
|
655
876
|
const parent = this.parentElement;
|
|
@@ -665,7 +886,7 @@ let NLDDListItem = NLDDListItem_1 = class NLDDListItem extends withTranslations(
|
|
|
665
886
|
// search input is in the tab order, and active moves via
|
|
666
887
|
// aria-activedescendant. Roving tabindex (arrow-navigation) supersedes
|
|
667
888
|
// nothing here: the two modes are mutually exclusive on the parent list.
|
|
668
|
-
// Otherwise, roving tabindex:
|
|
889
|
+
// Otherwise, roving tabindex: while the list runs the roving,
|
|
669
890
|
// exactly one item is the tab stop (0) and the rest are reachable only
|
|
670
891
|
// via the arrow keys (-1). Off → undefined leaves the native
|
|
671
892
|
// button/link as a normal tab stop.
|
|
@@ -674,7 +895,7 @@ let NLDDListItem = NLDDListItem_1 = class NLDDListItem extends withTranslations(
|
|
|
674
895
|
: this._arrowNavigation
|
|
675
896
|
? (this._rovingActive ? '0' : '-1')
|
|
676
897
|
: undefined;
|
|
677
|
-
return template(this.button, this.href, this.target, this.rel, opensInNewTabLabel, actionTabindex, this._highlighted, this.checkbox, this.checked, this._resolvedExpanded, this._showChildren, this._hasCheckedSegment);
|
|
898
|
+
return template(this.button, this.href, this.target, this.rel, opensInNewTabLabel, actionTabindex, this._highlighted, this.checkbox, this.checked, this._resolvedExpanded, this._showChildren, this._hasCheckedSegment, this.disabled);
|
|
678
899
|
}
|
|
679
900
|
};
|
|
680
901
|
NLDDListItem.styles = [listItemStyles];
|
|
@@ -690,6 +911,9 @@ __decorate([
|
|
|
690
911
|
__decorate([
|
|
691
912
|
property({ type: Boolean, reflect: true })
|
|
692
913
|
], NLDDListItem.prototype, "selected", void 0);
|
|
914
|
+
__decorate([
|
|
915
|
+
property({ type: Boolean, reflect: true })
|
|
916
|
+
], NLDDListItem.prototype, "current", void 0);
|
|
693
917
|
__decorate([
|
|
694
918
|
property({ type: Boolean, reflect: true })
|
|
695
919
|
], NLDDListItem.prototype, "button", void 0);
|
|
@@ -699,6 +923,9 @@ __decorate([
|
|
|
699
923
|
__decorate([
|
|
700
924
|
property({ type: Boolean, reflect: true })
|
|
701
925
|
], NLDDListItem.prototype, "checked", void 0);
|
|
926
|
+
__decorate([
|
|
927
|
+
property({ type: Boolean, reflect: true })
|
|
928
|
+
], NLDDListItem.prototype, "disabled", void 0);
|
|
702
929
|
__decorate([
|
|
703
930
|
property({ type: Boolean, reflect: true })
|
|
704
931
|
], NLDDListItem.prototype, "expanded", void 0);
|