@kouji-ui/core 0.0.4 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +7 -4
- package/CHANGELOG.md +169 -0
- package/ng-package.json +5 -1
- package/package.json +18 -6
- package/src/a11y/aria-describedby.ts +7 -3
- package/src/a11y/aria-labelledby.spec.ts +55 -0
- package/src/a11y/aria-labelledby.ts +38 -0
- package/src/a11y/focus-trap.ts +4 -2
- package/src/a11y/index.ts +1 -0
- package/src/a11y/live-region.ts +4 -2
- package/src/a11y/roving-tabindex.spec.ts +139 -0
- package/src/a11y/roving-tabindex.ts +56 -7
- package/src/a11y/visually-hidden.ts +4 -2
- package/src/accordion/accordion.context.ts +22 -0
- package/src/accordion/accordion.spec.ts +233 -23
- package/src/accordion/accordion.ts +311 -39
- package/src/accordion/index.ts +8 -2
- package/src/alert/alert.context.ts +28 -0
- package/src/alert/alert.spec.ts +217 -0
- package/src/alert/alert.ts +417 -0
- package/src/alert/config.ts +46 -0
- package/src/alert/index.ts +19 -0
- package/src/avatar/avatar-group.context.ts +45 -0
- package/src/avatar/avatar-group.spec.ts +358 -0
- package/src/avatar/avatar-group.ts +259 -0
- package/src/avatar/avatar.ts +17 -4
- package/src/avatar/index.ts +11 -1
- package/src/badge/badge.spec.ts +8 -0
- package/src/badge/badge.ts +24 -3
- package/src/breadcrumb/breadcrumb-current.ts +38 -0
- package/src/breadcrumb/breadcrumb-ellipsis.ts +71 -0
- package/src/breadcrumb/breadcrumb-item.ts +41 -0
- package/src/breadcrumb/breadcrumb-link.ts +44 -0
- package/src/breadcrumb/breadcrumb-list.ts +42 -0
- package/src/breadcrumb/breadcrumb-separator.ts +45 -0
- package/src/breadcrumb/breadcrumb.context.ts +45 -0
- package/src/breadcrumb/breadcrumb.spec.ts +354 -0
- package/src/breadcrumb/breadcrumb.ts +239 -0
- package/src/breadcrumb/config.ts +84 -0
- package/src/breadcrumb/index.ts +18 -0
- package/src/button/_examples/button.example.ts +71 -0
- package/src/button/_examples/button.finance.example.ts +83 -0
- package/src/button/_examples/button.retro.example.ts +91 -0
- package/src/button/_examples/button.sizes.example.ts +60 -0
- package/src/button/_examples/index.ts +6 -0
- package/src/button/button.spec.ts +139 -8
- package/src/button/button.ts +114 -16
- package/src/button/config.spec.ts +33 -0
- package/src/button/config.ts +45 -0
- package/src/button/index.ts +2 -1
- package/src/button-group/button-group.context.ts +28 -0
- package/src/button-group/button-group.spec.ts +99 -0
- package/src/button-group/button-group.ts +99 -0
- package/src/button-group/index.ts +2 -0
- package/src/calendar/calendar-day.ts +102 -0
- package/src/calendar/calendar-grid.ts +90 -0
- package/src/calendar/calendar-header.ts +65 -0
- package/src/calendar/calendar.context.ts +53 -0
- package/src/calendar/calendar.spec.ts +225 -0
- package/src/calendar/calendar.ts +233 -0
- package/src/calendar/date-utils.ts +225 -0
- package/src/calendar/index.ts +28 -0
- package/src/carousel/carousel.context.ts +81 -0
- package/src/carousel/carousel.spec.ts +337 -0
- package/src/carousel/carousel.ts +919 -0
- package/src/carousel/index.ts +22 -0
- package/src/cascade-select/cascade-select-option.ts +205 -0
- package/src/cascade-select/cascade-select-panel.ts +106 -0
- package/src/cascade-select/cascade-select-root.ts +265 -0
- package/src/cascade-select/cascade-select-sub-panel.ts +168 -0
- package/src/cascade-select/cascade-select-trigger.ts +44 -0
- package/src/cascade-select/cascade-select.context.ts +71 -0
- package/src/cascade-select/cascade-select.spec.ts +241 -0
- package/src/cascade-select/cascade-select.ts +5 -0
- package/src/cascade-select/index.ts +11 -0
- package/src/chart/chart.ts +6 -2
- package/src/chat/chat-avatar.ts +31 -0
- package/src/chat/chat-bubble.ts +49 -0
- package/src/chat/chat-footer.ts +67 -0
- package/src/chat/chat-header.ts +41 -0
- package/src/chat/chat-log.ts +43 -0
- package/src/chat/chat.context.ts +64 -0
- package/src/chat/chat.spec.ts +341 -0
- package/src/chat/chat.ts +191 -0
- package/src/chat/config.ts +53 -0
- package/src/chat/index.ts +21 -0
- package/src/checkbox/checkbox.ts +9 -2
- package/src/color-picker/color-picker.context.ts +74 -0
- package/src/color-picker/color-picker.spec.ts +241 -0
- package/src/color-picker/color-picker.ts +698 -0
- package/src/color-picker/color-picker.utils.ts +140 -0
- package/src/color-picker/index.ts +28 -0
- package/src/combobox/combobox-input.ts +143 -0
- package/src/combobox/combobox-listbox.ts +49 -0
- package/src/combobox/combobox-option.ts +43 -0
- package/src/combobox/combobox-root.ts +281 -0
- package/src/combobox/combobox.spec.ts +75 -0
- package/src/combobox/combobox.ts +4 -0
- package/src/combobox/index.ts +4 -0
- package/src/command-palette/command-empty.ts +36 -0
- package/src/command-palette/command-group.ts +21 -0
- package/src/command-palette/command-input.ts +70 -0
- package/src/command-palette/command-item.ts +60 -0
- package/src/command-palette/command-list.ts +25 -0
- package/src/command-palette/command-palette-dialog.ts +74 -0
- package/src/command-palette/command-palette-trigger.ts +64 -0
- package/src/command-palette/command-palette.filters.ts +53 -0
- package/src/command-palette/command-palette.spec.ts +349 -0
- package/src/command-palette/command-palette.ts +204 -0
- package/src/command-palette/command-separator.ts +18 -0
- package/src/command-palette/index.ts +15 -0
- package/src/confirm-popup/confirm-popup-action.ts +39 -0
- package/src/confirm-popup/confirm-popup-cancel.ts +38 -0
- package/src/confirm-popup/confirm-popup-content.ts +113 -0
- package/src/confirm-popup/confirm-popup-message.ts +36 -0
- package/src/confirm-popup/confirm-popup-trigger.ts +31 -0
- package/src/confirm-popup/confirm-popup.context.ts +41 -0
- package/src/confirm-popup/confirm-popup.spec.ts +337 -0
- package/src/confirm-popup/confirm-popup.ts +109 -0
- package/src/confirm-popup/index.ts +12 -0
- package/src/date-picker/date-picker-calendar.ts +65 -0
- package/src/date-picker/date-picker-trigger.ts +215 -0
- package/src/date-picker/date-picker.context.ts +50 -0
- package/src/date-picker/date-picker.spec.ts +117 -0
- package/src/date-picker/date-picker.ts +127 -0
- package/src/date-picker/index.ts +7 -0
- package/src/dialog/_examples/dialog.confirm.example.ts +145 -0
- package/src/dialog/_examples/dialog.example.ts +106 -0
- package/src/dialog/_examples/dialog.finance.example.ts +121 -0
- package/src/dialog/_examples/dialog.retro.example.ts +126 -0
- package/src/dialog/_examples/index.ts +6 -0
- package/src/dialog/dialog.ref.ts +42 -0
- package/src/dialog/dialog.service.ts +57 -167
- package/src/dialog/dialog.spec.ts +35 -120
- package/src/dialog/dialog.ts +17 -192
- package/src/dialog/index.ts +3 -9
- package/src/divider/divider.spec.ts +223 -0
- package/src/divider/divider.ts +137 -0
- package/src/divider/index.ts +5 -0
- package/src/drawer/drawer.ref.ts +63 -0
- package/src/drawer/drawer.service.ts +106 -0
- package/src/drawer/drawer.spec.ts +117 -0
- package/src/drawer/drawer.ts +122 -0
- package/src/drawer/index.ts +10 -0
- package/src/dropdown-menu/dropdown-menu-content.ts +258 -0
- package/src/dropdown-menu/dropdown-menu-group.ts +31 -0
- package/src/dropdown-menu/dropdown-menu-item.ts +51 -0
- package/src/dropdown-menu/dropdown-menu-label.ts +41 -0
- package/src/dropdown-menu/dropdown-menu-separator.ts +27 -0
- package/src/dropdown-menu/dropdown-menu-trigger.ts +140 -0
- package/src/dropdown-menu/dropdown-menu.spec.ts +265 -0
- package/src/dropdown-menu/dropdown-menu.ts +60 -0
- package/src/dropdown-menu/index.ts +15 -0
- package/src/example-components.ts +39 -30
- package/src/field/field-error.ts +49 -0
- package/src/field/field-group.ts +39 -0
- package/src/field/field-help.ts +47 -0
- package/src/field/field-label.ts +30 -0
- package/src/field/field.context.ts +28 -0
- package/src/field/field.spec.ts +179 -0
- package/src/field/field.ts +121 -0
- package/src/field/index.ts +6 -0
- package/src/file-upload/file-upload.context.ts +89 -0
- package/src/file-upload/file-upload.spec.ts +290 -0
- package/src/file-upload/file-upload.ts +639 -0
- package/src/file-upload/file-upload.types.ts +59 -0
- package/src/file-upload/index.ts +23 -0
- package/src/form/form-error-summary.ts +87 -0
- package/src/form/form-field.context.ts +3 -0
- package/src/form/form-field.spec.ts +25 -0
- package/src/form/form-field.ts +52 -0
- package/src/form/form.context.ts +52 -2
- package/src/form/form.spec.ts +155 -18
- package/src/form/form.ts +315 -35
- package/src/form/index.ts +11 -2
- package/src/icon/E2E.md +14 -0
- package/src/icon/icon.css +40 -0
- package/src/icon/icon.directive.spec.ts +198 -0
- package/src/icon/icon.directive.ts +113 -0
- package/src/icon/icon.mode.spec.ts +29 -0
- package/src/icon/icon.mode.ts +23 -0
- package/src/icon/icon.providers.spec.ts +63 -0
- package/src/icon/icon.providers.ts +47 -0
- package/src/icon/icon.resolver.spec.ts +96 -0
- package/src/icon/icon.resolver.ts +49 -0
- package/src/icon/icon.tokens.ts +88 -0
- package/src/icon/icon.types.ts +48 -0
- package/src/icon/index.ts +21 -0
- package/src/input/input.ts +12 -3
- package/src/input-group/index.ts +3 -0
- package/src/input-group/input-group-addon.ts +92 -0
- package/src/input-group/input-group.context.ts +27 -0
- package/src/input-group/input-group.spec.ts +186 -0
- package/src/input-group/input-group.ts +136 -0
- package/src/input-mask/index.ts +11 -0
- package/src/input-mask/input-mask.compile.ts +69 -0
- package/src/input-mask/input-mask.engine.ts +376 -0
- package/src/input-mask/input-mask.presets.ts +24 -0
- package/src/input-mask/input-mask.spec.ts +304 -0
- package/src/input-mask/input-mask.tokens.ts +49 -0
- package/src/input-mask/input-mask.ts +280 -0
- package/src/input-otp/index.ts +2 -0
- package/src/input-otp/input-otp.context.ts +41 -0
- package/src/input-otp/input-otp.spec.ts +308 -0
- package/src/input-otp/input-otp.ts +470 -0
- package/src/kbd/index.ts +1 -0
- package/src/kbd/kbd.spec.ts +127 -0
- package/src/kbd/kbd.ts +132 -0
- package/src/link/config.ts +44 -0
- package/src/link/index.ts +2 -0
- package/src/link/link.spec.ts +246 -0
- package/src/link/link.ts +226 -0
- package/src/list/index.ts +11 -0
- package/src/list/list.spec.ts +237 -0
- package/src/list/list.ts +277 -0
- package/src/menubar/index.ts +7 -0
- package/src/menubar/menubar-item.ts +204 -0
- package/src/menubar/menubar.context.ts +43 -0
- package/src/menubar/menubar.spec.ts +433 -0
- package/src/menubar/menubar.ts +309 -0
- package/src/number-input/index.ts +4 -0
- package/src/number-input/number-input-group.ts +64 -0
- package/src/number-input/number-input.context.ts +31 -0
- package/src/number-input/number-input.format.ts +148 -0
- package/src/number-input/number-input.spec.ts +170 -0
- package/src/number-input/number-input.ts +457 -0
- package/src/number-input/number-stepper.ts +193 -0
- package/src/overlay-badge/index.ts +7 -0
- package/src/overlay-badge/overlay-badge-content.ts +73 -0
- package/src/overlay-badge/overlay-badge.context.ts +37 -0
- package/src/overlay-badge/overlay-badge.spec.ts +220 -0
- package/src/overlay-badge/overlay-badge.ts +128 -0
- package/src/pagination/config.ts +82 -0
- package/src/pagination/index.ts +19 -0
- package/src/pagination/page-tokens.ts +78 -0
- package/src/pagination/pagination-ellipsis.ts +69 -0
- package/src/pagination/pagination-first.ts +84 -0
- package/src/pagination/pagination-info.ts +70 -0
- package/src/pagination/pagination-item.ts +81 -0
- package/src/pagination/pagination-last.ts +85 -0
- package/src/pagination/pagination-next.ts +86 -0
- package/src/pagination/pagination-previous.ts +90 -0
- package/src/pagination/pagination.context.ts +52 -0
- package/src/pagination/pagination.spec.ts +388 -0
- package/src/pagination/pagination.ts +288 -0
- package/src/password-input/index.ts +15 -0
- package/src/password-input/password-input.context.ts +65 -0
- package/src/password-input/password-input.scorer.ts +34 -0
- package/src/password-input/password-input.spec.ts +274 -0
- package/src/password-input/password-input.ts +488 -0
- package/src/popover/_examples/index.ts +5 -0
- package/src/popover/_examples/popover.example.ts +92 -0
- package/src/popover/_examples/popover.finance.example.ts +106 -0
- package/src/popover/_examples/popover.retro.example.ts +103 -0
- package/src/popover/index.ts +5 -12
- package/src/popover/popover-arrow.ts +30 -0
- package/src/popover/popover-close.ts +36 -0
- package/src/popover/popover-content.ts +41 -0
- package/src/popover/popover-title.ts +39 -0
- package/src/popover/popover-trigger.ts +40 -0
- package/src/popover/popover.spec.ts +51 -44
- package/src/popover/popover.ts +5 -124
- package/src/presets/bind-presets.spec.ts +50 -0
- package/src/presets/bind-presets.ts +43 -0
- package/src/presets/index.ts +3 -0
- package/src/presets/size.spec.ts +67 -0
- package/src/presets/size.ts +59 -0
- package/src/presets/variant.spec.ts +72 -0
- package/src/presets/variant.ts +62 -0
- package/src/primitives/directionality/directionality.spec.ts +112 -0
- package/src/primitives/directionality/directionality.ts +89 -0
- package/src/primitives/directionality/index.ts +1 -0
- package/src/primitives/forms/form-control.spec.ts +11 -3
- package/src/primitives/forms/form-control.ts +6 -2
- package/src/primitives/index.ts +3 -0
- package/src/primitives/interaction/disabled.ts +12 -5
- package/src/primitives/interaction/focus-ring.ts +4 -2
- package/src/primitives/list/filterable-list.spec.ts +114 -0
- package/src/primitives/list/filterable-list.ts +126 -0
- package/src/primitives/list/group.spec.ts +99 -0
- package/src/primitives/list/group.ts +139 -0
- package/src/primitives/list/index.ts +8 -0
- package/src/primitives/list/inject-helpers.ts +8 -0
- package/src/primitives/list/item.spec.ts +173 -0
- package/src/primitives/list/item.ts +222 -0
- package/src/primitives/list/navigator.spec.ts +286 -0
- package/src/primitives/list/navigator.ts +238 -0
- package/src/primitives/list/selection.spec.ts +214 -0
- package/src/primitives/list/selection.ts +339 -0
- package/src/primitives/list/tokens.ts +106 -0
- package/src/primitives/list/type-ahead.spec.ts +58 -0
- package/src/primitives/list/type-ahead.ts +46 -0
- package/src/primitives/overlay/backdrop.spec.ts +54 -0
- package/src/primitives/overlay/backdrop.ts +31 -0
- package/src/primitives/overlay/builder.spec.ts +38 -0
- package/src/primitives/overlay/builder.ts +151 -0
- package/src/primitives/overlay/container.ts +42 -0
- package/src/primitives/overlay/context.ts +14 -0
- package/src/primitives/overlay/controller.spec.ts +86 -0
- package/src/primitives/overlay/controller.ts +190 -0
- package/src/primitives/overlay/id.spec.ts +24 -0
- package/src/primitives/overlay/id.ts +17 -0
- package/src/primitives/overlay/index.ts +18 -1
- package/src/primitives/overlay/overlay.css +42 -0
- package/src/primitives/overlay/panel.spec.ts +52 -0
- package/src/primitives/overlay/panel.ts +102 -0
- package/src/primitives/overlay/stack.spec.ts +55 -0
- package/src/primitives/overlay/stack.ts +113 -0
- package/src/primitives/overlay/strategies/backdrop/blurred.spec.ts +11 -0
- package/src/primitives/overlay/strategies/backdrop/blurred.ts +5 -0
- package/src/primitives/overlay/strategies/backdrop/none.spec.ts +10 -0
- package/src/primitives/overlay/strategies/backdrop/none.ts +9 -0
- package/src/primitives/overlay/strategies/backdrop/solid.spec.ts +18 -0
- package/src/primitives/overlay/strategies/backdrop/solid.ts +23 -0
- package/src/primitives/overlay/strategies/focus-trap/inert-based.spec.ts +28 -0
- package/src/primitives/overlay/strategies/focus-trap/inert-based.ts +38 -0
- package/src/primitives/overlay/strategies/focus-trap/no-trap.spec.ts +9 -0
- package/src/primitives/overlay/strategies/focus-trap/no-trap.ts +8 -0
- package/src/primitives/overlay/strategies/focus-trap/tab-cycle.spec.ts +49 -0
- package/src/primitives/overlay/strategies/focus-trap/tab-cycle.ts +85 -0
- package/src/primitives/overlay/strategies/index.ts +34 -0
- package/src/primitives/overlay/strategies/live-announcer/_announce.ts +35 -0
- package/src/primitives/overlay/strategies/live-announcer/assertive.spec.ts +21 -0
- package/src/primitives/overlay/strategies/live-announcer/assertive.ts +11 -0
- package/src/primitives/overlay/strategies/live-announcer/polite.spec.ts +21 -0
- package/src/primitives/overlay/strategies/live-announcer/polite.ts +11 -0
- package/src/primitives/overlay/strategies/live-announcer/silent.spec.ts +12 -0
- package/src/primitives/overlay/strategies/live-announcer/silent.ts +5 -0
- package/src/primitives/overlay/strategies/mount/body-portal.spec.ts +40 -0
- package/src/primitives/overlay/strategies/mount/body-portal.ts +91 -0
- package/src/primitives/overlay/strategies/mount/in-container.spec.ts +43 -0
- package/src/primitives/overlay/strategies/mount/in-container.ts +39 -0
- package/src/primitives/overlay/strategies/mount/in-place.spec.ts +40 -0
- package/src/primitives/overlay/strategies/mount/in-place.ts +20 -0
- package/src/primitives/overlay/strategies/position/anchored-to.spec.ts +56 -0
- package/src/primitives/overlay/strategies/position/anchored-to.ts +248 -0
- package/src/primitives/overlay/strategies/position/corner.spec.ts +36 -0
- package/src/primitives/overlay/strategies/position/corner.ts +33 -0
- package/src/primitives/overlay/strategies/position/edge-sheet.spec.ts +32 -0
- package/src/primitives/overlay/strategies/position/edge-sheet.ts +36 -0
- package/src/primitives/overlay/strategies/position/in-place-sibling.spec.ts +25 -0
- package/src/primitives/overlay/strategies/position/in-place-sibling.ts +13 -0
- package/src/primitives/overlay/strategies/position/point-at.spec.ts +40 -0
- package/src/primitives/overlay/strategies/position/point-at.ts +34 -0
- package/src/primitives/overlay/strategies/position/viewport-centered.spec.ts +31 -0
- package/src/primitives/overlay/strategies/position/viewport-centered.ts +31 -0
- package/src/primitives/overlay/strategies/scroll-lock/css-clip.spec.ts +15 -0
- package/src/primitives/overlay/strategies/scroll-lock/css-clip.ts +39 -0
- package/src/primitives/overlay/strategies/scroll-lock/html-overflow.spec.ts +21 -0
- package/src/primitives/overlay/strategies/scroll-lock/html-overflow.ts +44 -0
- package/src/primitives/overlay/strategies/scroll-lock/none.spec.ts +9 -0
- package/src/primitives/overlay/strategies/scroll-lock/none.ts +5 -0
- package/src/primitives/overlay/strategies/trigger-event/on-click.spec.ts +32 -0
- package/src/primitives/overlay/strategies/trigger-event/on-click.ts +28 -0
- package/src/primitives/overlay/strategies/trigger-event/on-context-menu.spec.ts +45 -0
- package/src/primitives/overlay/strategies/trigger-event/on-context-menu.ts +70 -0
- package/src/primitives/overlay/strategies/trigger-event/on-focus-or-input.spec.ts +35 -0
- package/src/primitives/overlay/strategies/trigger-event/on-focus-or-input.ts +34 -0
- package/src/primitives/overlay/strategies/trigger-event/on-focus.spec.ts +64 -0
- package/src/primitives/overlay/strategies/trigger-event/on-focus.ts +37 -0
- package/src/primitives/overlay/strategies/trigger-event/on-hotkey.spec.ts +37 -0
- package/src/primitives/overlay/strategies/trigger-event/on-hotkey.ts +59 -0
- package/src/primitives/overlay/strategies/trigger-event/on-hover.spec.ts +34 -0
- package/src/primitives/overlay/strategies/trigger-event/on-hover.ts +86 -0
- package/src/primitives/overlay/strategies/trigger-event/programmatic.spec.ts +16 -0
- package/src/primitives/overlay/strategies/trigger-event/programmatic.ts +12 -0
- package/src/primitives/overlay/tokens.ts +54 -0
- package/src/primitives/overlay/trigger.spec.ts +103 -0
- package/src/primitives/overlay/trigger.ts +75 -0
- package/src/primitives/overlay/types.ts +24 -0
- package/src/primitives/overlay/wrapper.ts +50 -0
- package/src/primitives/signals/deep-signal.ts +109 -0
- package/src/primitives/signals/index.ts +1 -0
- package/src/progress-bar/config.ts +48 -0
- package/src/progress-bar/index.ts +12 -0
- package/src/progress-bar/progress-bar-fill.ts +37 -0
- package/src/progress-bar/progress-bar.context.ts +34 -0
- package/src/progress-bar/progress-bar.spec.ts +423 -0
- package/src/progress-bar/progress-bar.ts +217 -0
- package/src/public-api.ts +58 -9
- package/src/radio/radio.ts +14 -3
- package/src/select/index.ts +4 -2
- package/src/select/select-content.ts +69 -0
- package/src/select/select-option.ts +35 -0
- package/src/select/select-root.ts +129 -0
- package/src/select/select-trigger.ts +93 -0
- package/src/select/select.spec.ts +133 -140
- package/src/select/select.ts +4 -250
- package/src/skeleton/index.ts +5 -0
- package/src/skeleton/skeleton.spec.ts +115 -0
- package/src/skeleton/skeleton.ts +56 -0
- package/src/slider/index.ts +10 -0
- package/src/slider/slider-range.ts +49 -0
- package/src/slider/slider-thumb.ts +335 -0
- package/src/slider/slider-track.ts +70 -0
- package/src/slider/slider.context.ts +79 -0
- package/src/slider/slider.geometry.ts +73 -0
- package/src/slider/slider.spec.ts +216 -0
- package/src/slider/slider.ts +443 -0
- package/src/speed-dial/index.ts +10 -0
- package/src/speed-dial/speed-dial-action.ts +40 -0
- package/src/speed-dial/speed-dial-actions.ts +31 -0
- package/src/speed-dial/speed-dial-trigger.ts +55 -0
- package/src/speed-dial/speed-dial.context.ts +36 -0
- package/src/speed-dial/speed-dial.spec.ts +143 -0
- package/src/speed-dial/speed-dial.ts +127 -0
- package/src/spinner/config.ts +48 -0
- package/src/spinner/index.ts +8 -0
- package/src/spinner/spinner.spec.ts +262 -0
- package/src/spinner/spinner.ts +129 -0
- package/src/stepper/index.ts +15 -0
- package/src/stepper/stepper.context.ts +63 -0
- package/src/stepper/stepper.spec.ts +403 -0
- package/src/stepper/stepper.ts +544 -0
- package/src/styles.css +17 -0
- package/src/table/column-helpers.spec.ts +74 -0
- package/src/table/column-helpers.ts +68 -0
- package/src/table/filter-fns.ts +230 -0
- package/src/table/filter-models.spec.ts +240 -0
- package/src/table/filter-models.ts +124 -0
- package/src/table/filter-params.ts +90 -0
- package/src/table/grid-api-impl.ts +321 -0
- package/src/table/grid-api.spec.ts +178 -0
- package/src/table/grid-api.ts +285 -0
- package/src/table/index.ts +73 -1
- package/src/table/table-cell.spec.ts +43 -0
- package/src/table/table-cell.ts +38 -0
- package/src/table/table-filter-outlet.ts +120 -0
- package/src/table/table-header.spec.ts +54 -0
- package/src/table/table-header.ts +63 -0
- package/src/table/table-keyboard.spec.ts +68 -0
- package/src/table/table-keyboard.ts +107 -0
- package/src/table/table-resource.spec.ts +37 -0
- package/src/table/table-resource.ts +36 -0
- package/src/table/table-row.spec.ts +54 -0
- package/src/table/table-row.ts +31 -0
- package/src/table/table-storage.spec.ts +67 -0
- package/src/table/table-storage.ts +76 -0
- package/src/table/table.spec.ts +101 -42
- package/src/table/table.ts +228 -73
- package/src/table/table.types.ts +83 -0
- package/src/tabs/index.ts +7 -2
- package/src/tabs/tabs.context.ts +27 -4
- package/src/tabs/tabs.spec.ts +336 -24
- package/src/tabs/tabs.ts +313 -79
- package/src/tag/config.ts +53 -0
- package/src/tag/index.ts +7 -0
- package/src/tag/tag-list.ts +76 -0
- package/src/tag/tag-remove.ts +61 -0
- package/src/tag/tag.context.ts +36 -0
- package/src/tag/tag.spec.ts +240 -0
- package/src/tag/tag.ts +203 -0
- package/src/textarea/config.ts +42 -0
- package/src/textarea/index.ts +8 -0
- package/src/textarea/textarea.spec.ts +176 -0
- package/src/textarea/textarea.ts +235 -0
- package/src/time-picker/index.ts +15 -0
- package/src/time-picker/time-picker-meridiem.ts +123 -0
- package/src/time-picker/time-picker-segment.ts +318 -0
- package/src/time-picker/time-picker.context.ts +38 -0
- package/src/time-picker/time-picker.format.ts +181 -0
- package/src/time-picker/time-picker.spec.ts +189 -0
- package/src/time-picker/time-picker.ts +274 -0
- package/src/toast/_examples/index.ts +5 -0
- package/src/toast/_examples/toast.example.ts +282 -0
- package/src/toast/_examples/toast.finance.example.ts +180 -0
- package/src/toast/_examples/toast.retro.example.ts +161 -0
- package/src/toast/index.ts +8 -1
- package/src/toast/toast.ref.ts +26 -0
- package/src/toast/toast.service.ts +227 -41
- package/src/toast/toast.spec.ts +166 -14
- package/src/toast/toast.strategy.ts +10 -0
- package/src/toast/toast.ts +177 -21
- package/src/toggle/toggle.ts +10 -2
- package/src/tooltip/_examples/index.ts +6 -0
- package/src/tooltip/_examples/tooltip.example.ts +82 -0
- package/src/tooltip/_examples/tooltip.finance.example.ts +97 -0
- package/src/tooltip/_examples/tooltip.placements.example.ts +83 -0
- package/src/tooltip/_examples/tooltip.retro.example.ts +107 -0
- package/src/tooltip/index.ts +4 -5
- package/src/tooltip/tooltip-arrow.ts +31 -0
- package/src/tooltip/tooltip-content.ts +38 -0
- package/src/tooltip/tooltip-group.ts +32 -0
- package/src/tooltip/tooltip-trigger.ts +47 -0
- package/src/tooltip/tooltip.spec.ts +38 -102
- package/src/tooltip/tooltip.ts +5 -129
- package/src/tree-select/index.ts +12 -0
- package/src/tree-select/tree-select-content.ts +199 -0
- package/src/tree-select/tree-select-node.ts +132 -0
- package/src/tree-select/tree-select-root.ts +272 -0
- package/src/tree-select/tree-select-trigger.ts +90 -0
- package/src/tree-select/tree-select.context.ts +63 -0
- package/src/tree-select/tree-select.spec.ts +433 -0
- package/src/tree-select/tree-select.ts +2 -0
- package/src/typography/blockquote.ts +57 -0
- package/src/typography/code.ts +53 -0
- package/src/typography/index.ts +22 -0
- package/src/typography/lead.ts +49 -0
- package/src/typography/muted.ts +29 -0
- package/src/typography/prose.css +312 -0
- package/src/typography/truncate.ts +99 -0
- package/src/typography/typography.spec.ts +203 -0
- package/tsconfig.lib.json +9 -1
- package/tsconfig.lib.prod.json +7 -1
- package/tsconfig.spec.json +9 -1
- package/vite.config.ts +8 -0
- package/src/button/button.example.ts +0 -30
- package/src/button/button.finance.example.ts +0 -37
- package/src/button/button.retro.example.ts +0 -47
- package/src/button/button.sizes.example.ts +0 -25
- package/src/dialog/dialog.confirm.example.ts +0 -57
- package/src/dialog/dialog.context.ts +0 -11
- package/src/dialog/dialog.example.ts +0 -40
- package/src/dialog/dialog.finance.example.ts +0 -47
- package/src/dialog/dialog.retro.example.ts +0 -46
- package/src/menu/index.ts +0 -2
- package/src/menu/menu.context.ts +0 -10
- package/src/menu/menu.example.ts +0 -39
- package/src/menu/menu.spec.ts +0 -168
- package/src/menu/menu.ts +0 -176
- package/src/popover/popover.context.ts +0 -18
- package/src/popover/popover.example.ts +0 -50
- package/src/popover/popover.finance.example.ts +0 -52
- package/src/popover/popover.retro.example.ts +0 -53
- package/src/primitives/overlay/overlay.spec.ts +0 -90
- package/src/primitives/overlay/overlay.ts +0 -106
- package/src/select/select.context.ts +0 -3
- package/src/toast/toast.example.ts +0 -134
- package/src/toast/toast.finance.example.ts +0 -68
- package/src/toast/toast.retro.example.ts +0 -69
- package/src/tooltip/tooltip.example.ts +0 -46
- package/src/tooltip/tooltip.finance.example.ts +0 -54
- package/src/tooltip/tooltip.placements.example.ts +0 -56
- package/src/tooltip/tooltip.retro.example.ts +0 -65
|
@@ -1,126 +1,398 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import {
|
|
2
|
+
Directive,
|
|
3
|
+
ElementRef,
|
|
4
|
+
OnDestroy,
|
|
5
|
+
OnInit,
|
|
6
|
+
Signal,
|
|
7
|
+
booleanAttribute,
|
|
8
|
+
computed,
|
|
9
|
+
effect,
|
|
10
|
+
inject,
|
|
11
|
+
input,
|
|
12
|
+
model,
|
|
13
|
+
signal,
|
|
14
|
+
untracked,
|
|
15
|
+
} from '@angular/core';
|
|
16
|
+
import {
|
|
17
|
+
KJ_ACCORDION,
|
|
18
|
+
KJ_ACCORDION_ITEM,
|
|
19
|
+
KjAccordionContext,
|
|
20
|
+
KjAccordionItemContext,
|
|
21
|
+
KjAccordionType,
|
|
22
|
+
} from './accordion.context';
|
|
23
|
+
|
|
24
|
+
let kjAccordionSeedCounter = 0;
|
|
25
|
+
function nextSeed(): string {
|
|
26
|
+
// Try crypto.randomUUID where available (browser, jsdom 22+, node 19+).
|
|
27
|
+
// Fall back to a counter so SSR / older environments still produce a stable string.
|
|
28
|
+
const cryptoLike = (globalThis as { crypto?: { randomUUID?: () => string } }).crypto;
|
|
29
|
+
if (cryptoLike?.randomUUID) return cryptoLike.randomUUID().slice(0, 8);
|
|
30
|
+
return `kj${(++kjAccordionSeedCounter).toString(36)}`;
|
|
31
|
+
}
|
|
3
32
|
|
|
4
33
|
/**
|
|
5
34
|
* Root accordion container. Manages open/close state for accordion items.
|
|
6
35
|
* Supports `'single'` (only one item open) or `'multiple'` (any number open).
|
|
7
36
|
*
|
|
37
|
+
* Two-way bound `kjValue` mirrors the open set as a string (single mode) or
|
|
38
|
+
* `string[]` (multiple mode). Internally the directive keeps a single
|
|
39
|
+
* `ReadonlySet<string>` so single ↔ multiple flips don't lose state.
|
|
40
|
+
*
|
|
41
|
+
* Arrow-key roving navigation is opt-in via `kjArrowNavigation`; when enabled
|
|
42
|
+
* the root listens for ArrowUp/ArrowDown/Home/End on registered triggers and
|
|
43
|
+
* moves focus between them. When disabled (the default) each trigger is a
|
|
44
|
+
* plain button in the page tab sequence — the WAI-ARIA APG-recommended
|
|
45
|
+
* arrangement for FAQ-style content.
|
|
46
|
+
*
|
|
8
47
|
* @example
|
|
9
48
|
* ```html
|
|
10
|
-
* <div kjAccordion [
|
|
11
|
-
* <div kjAccordionItem
|
|
49
|
+
* <div kjAccordion [(kjValue)]="open" kjType="multiple">
|
|
50
|
+
* <div kjAccordionItem kjItemValue="billing">
|
|
51
|
+
* <button kjAccordionTrigger>Billing</button>
|
|
52
|
+
* <div kjAccordionContent>...</div>
|
|
53
|
+
* </div>
|
|
12
54
|
* </div>
|
|
13
55
|
* ```
|
|
14
|
-
* @category Core/
|
|
56
|
+
* @doc-category Core/Data display
|
|
57
|
+
* @doc
|
|
58
|
+
* @doc-name accordion
|
|
59
|
+
* @doc-description Unstyled accordion root that manages expand/collapse state across child accordion items.
|
|
60
|
+
* @doc-is-main
|
|
15
61
|
*/
|
|
16
62
|
@Directive({
|
|
17
63
|
selector: '[kjAccordion]',
|
|
18
64
|
standalone: true,
|
|
19
65
|
providers: [{ provide: KJ_ACCORDION, useExisting: KjAccordion }],
|
|
66
|
+
host: {
|
|
67
|
+
'[attr.data-orientation]': '"vertical"',
|
|
68
|
+
},
|
|
20
69
|
})
|
|
21
|
-
export class KjAccordion {
|
|
22
|
-
/**
|
|
23
|
-
readonly
|
|
70
|
+
export class KjAccordion implements KjAccordionContext {
|
|
71
|
+
/** Mode: `'single'` (one open at a time) or `'multiple'` (any number open). */
|
|
72
|
+
readonly kjType = input<KjAccordionType>('single');
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Two-way bound open value. In `'single'` mode it is a string (the open
|
|
76
|
+
* item's value, or `''` when nothing is open); in `'multiple'` mode it is a
|
|
77
|
+
* `string[]` (open item values, in insertion order).
|
|
78
|
+
*/
|
|
79
|
+
readonly kjValue = model<string | string[]>('');
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Opt-in roving tabindex on triggers. When `true`, ArrowUp/ArrowDown/Home/End
|
|
83
|
+
* move focus between triggers and the group becomes a single tab stop.
|
|
84
|
+
* When `false` (default), each trigger is a plain button in the page tab
|
|
85
|
+
* sequence — the simpler arrangement for FAQ-style content where Tab also
|
|
86
|
+
* needs to reach links and form fields inside an open panel.
|
|
87
|
+
*/
|
|
88
|
+
readonly kjArrowNavigation = input(false, { transform: booleanAttribute });
|
|
24
89
|
|
|
25
90
|
private readonly _openIds = signal<ReadonlySet<string>>(new Set());
|
|
26
91
|
/** Set of currently open item values. */
|
|
27
92
|
readonly openIds = this._openIds.asReadonly();
|
|
28
93
|
|
|
29
|
-
/**
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
94
|
+
/** Read-only view of `kjType` for context consumers. */
|
|
95
|
+
readonly type: Signal<KjAccordionType> = this.kjType;
|
|
96
|
+
|
|
97
|
+
/** Read-only view of `kjArrowNavigation` for context consumers. */
|
|
98
|
+
readonly arrowNavigation: Signal<boolean> = this.kjArrowNavigation;
|
|
99
|
+
|
|
100
|
+
/** @internal Registered triggers in document order — for arrow-key roving. */
|
|
101
|
+
private readonly _triggers = signal<readonly KjAccordionTrigger[]>([]);
|
|
102
|
+
|
|
103
|
+
/** Public read-only registration list, in document order. */
|
|
104
|
+
readonly triggers = this._triggers.asReadonly();
|
|
105
|
+
|
|
106
|
+
constructor() {
|
|
107
|
+
// Reconcile incoming kjValue → internal _openIds (controlled binding).
|
|
108
|
+
effect(() => {
|
|
109
|
+
const v = this.kjValue();
|
|
110
|
+
const next = new Set<string>();
|
|
111
|
+
if (typeof v === 'string') {
|
|
112
|
+
if (v) next.add(v);
|
|
113
|
+
} else if (Array.isArray(v)) {
|
|
114
|
+
for (const id of v) if (id) next.add(id);
|
|
38
115
|
}
|
|
39
|
-
|
|
116
|
+
// In single mode, only first wins.
|
|
117
|
+
if (this.kjType() === 'single' && next.size > 1) {
|
|
118
|
+
const [first] = next;
|
|
119
|
+
next.clear();
|
|
120
|
+
next.add(first);
|
|
121
|
+
}
|
|
122
|
+
// Avoid set-equal write loops with the toggle path.
|
|
123
|
+
const current = untracked(this._openIds);
|
|
124
|
+
if (!setsEqual(current, next)) this._openIds.set(next);
|
|
40
125
|
});
|
|
41
126
|
}
|
|
42
127
|
|
|
128
|
+
/** Toggles an item open or closed. In single mode, closes all others first. */
|
|
129
|
+
toggle(id: string): void {
|
|
130
|
+
const next = new Set(this._openIds());
|
|
131
|
+
if (next.has(id)) {
|
|
132
|
+
next.delete(id);
|
|
133
|
+
} else {
|
|
134
|
+
if (this.kjType() === 'single') next.clear();
|
|
135
|
+
next.add(id);
|
|
136
|
+
}
|
|
137
|
+
this._openIds.set(next);
|
|
138
|
+
this.syncModelFromSet(next);
|
|
139
|
+
}
|
|
140
|
+
|
|
43
141
|
/** Returns whether the given item value is currently open. */
|
|
44
142
|
isOpen(id: string): boolean {
|
|
45
143
|
return this._openIds().has(id);
|
|
46
144
|
}
|
|
145
|
+
|
|
146
|
+
/** @internal Trigger registration — called from `KjAccordionTrigger.ngOnInit`. */
|
|
147
|
+
registerTrigger(t: KjAccordionTrigger): void {
|
|
148
|
+
this._triggers.update((list) => (list.includes(t) ? list : [...list, t]));
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/** @internal Trigger un-registration — called from `KjAccordionTrigger.ngOnDestroy`. */
|
|
152
|
+
unregisterTrigger(t: KjAccordionTrigger): void {
|
|
153
|
+
this._triggers.update((list) => list.filter((x) => x !== t));
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/** @internal Move focus by delta among non-disabled triggers. */
|
|
157
|
+
focusTrigger(delta: number, fromIndex: number): void {
|
|
158
|
+
const list = this._triggers();
|
|
159
|
+
if (!list.length) return;
|
|
160
|
+
const len = list.length;
|
|
161
|
+
let i = fromIndex;
|
|
162
|
+
for (let step = 0; step < len; step++) {
|
|
163
|
+
i = (i + delta + len) % len;
|
|
164
|
+
const t = list[i];
|
|
165
|
+
if (!t.item.disabled()) {
|
|
166
|
+
t.el.nativeElement.focus();
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/** @internal Focus first / last non-disabled trigger. */
|
|
173
|
+
focusEdge(edge: 'first' | 'last'): void {
|
|
174
|
+
const list = this._triggers();
|
|
175
|
+
if (!list.length) return;
|
|
176
|
+
const range = edge === 'first' ? list : [...list].reverse();
|
|
177
|
+
for (const t of range) {
|
|
178
|
+
if (!t.item.disabled()) {
|
|
179
|
+
t.el.nativeElement.focus();
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
private syncModelFromSet(set: ReadonlySet<string>): void {
|
|
186
|
+
if (this.kjType() === 'single') {
|
|
187
|
+
const first = set.values().next().value ?? '';
|
|
188
|
+
const current = this.kjValue();
|
|
189
|
+
if (typeof current === 'string') {
|
|
190
|
+
if (current !== first) this.kjValue.set(first);
|
|
191
|
+
} else {
|
|
192
|
+
this.kjValue.set(first);
|
|
193
|
+
}
|
|
194
|
+
} else {
|
|
195
|
+
const arr = Array.from(set);
|
|
196
|
+
const current = this.kjValue();
|
|
197
|
+
if (Array.isArray(current) && arraysEqual(current, arr)) return;
|
|
198
|
+
this.kjValue.set(arr);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function setsEqual(a: ReadonlySet<string>, b: ReadonlySet<string>): boolean {
|
|
204
|
+
if (a.size !== b.size) return false;
|
|
205
|
+
for (const v of a) if (!b.has(v)) return false;
|
|
206
|
+
return true;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
function arraysEqual(a: readonly string[], b: readonly string[]): boolean {
|
|
210
|
+
if (a.length !== b.length) return false;
|
|
211
|
+
for (let i = 0; i < a.length; i++) if (a[i] !== b[i]) return false;
|
|
212
|
+
return true;
|
|
47
213
|
}
|
|
48
214
|
|
|
49
215
|
/**
|
|
50
|
-
* Individual accordion item.
|
|
216
|
+
* Individual accordion item. Owns the per-item `value`, `expanded` state, and
|
|
217
|
+
* the stable `headerId` / `contentId` pair the trigger and content use to wire
|
|
218
|
+
* `aria-controls` / `aria-labelledby`.
|
|
51
219
|
*
|
|
52
220
|
* @example
|
|
53
221
|
* ```html
|
|
54
|
-
* <div kjAccordionItem
|
|
222
|
+
* <div kjAccordionItem kjItemValue="section-1">
|
|
55
223
|
* <button kjAccordionTrigger>Section 1</button>
|
|
56
224
|
* <div kjAccordionContent>Content</div>
|
|
57
225
|
* </div>
|
|
58
226
|
* ```
|
|
59
|
-
* @category Core/
|
|
227
|
+
* @doc-category Core/Data display
|
|
228
|
+
* @doc
|
|
229
|
+
* @doc-name accordion
|
|
60
230
|
*/
|
|
61
231
|
@Directive({
|
|
62
232
|
selector: '[kjAccordionItem]',
|
|
63
233
|
standalone: true,
|
|
64
234
|
providers: [{ provide: KJ_ACCORDION_ITEM, useExisting: KjAccordionItem }],
|
|
235
|
+
host: {
|
|
236
|
+
'[attr.data-state]': 'expanded() ? "open" : "closed"',
|
|
237
|
+
'[attr.data-disabled]': 'kjItemDisabled() ? "" : null',
|
|
238
|
+
},
|
|
65
239
|
})
|
|
66
|
-
export class KjAccordionItem {
|
|
240
|
+
export class KjAccordionItem implements KjAccordionItemContext {
|
|
67
241
|
private readonly accordion = inject(KJ_ACCORDION) as KjAccordion;
|
|
68
242
|
|
|
69
243
|
/** The unique value identifying this item within the accordion. */
|
|
70
244
|
readonly kjItemValue = input.required<string>();
|
|
71
245
|
|
|
246
|
+
/**
|
|
247
|
+
* Whether this item is disabled. Gates `toggle`/`open`/`close`, drives
|
|
248
|
+
* `aria-disabled` on the trigger and `data-disabled` on the item host.
|
|
249
|
+
*/
|
|
250
|
+
readonly kjItemDisabled = input(false, { transform: booleanAttribute });
|
|
251
|
+
|
|
252
|
+
private readonly idSeed = nextSeed();
|
|
253
|
+
|
|
254
|
+
/** Stable id for the trigger element. */
|
|
255
|
+
readonly headerId = computed(() => `kj-accordion-trigger-${this.kjItemValue()}-${this.idSeed}`);
|
|
256
|
+
|
|
257
|
+
/** Stable id for the content region element. */
|
|
258
|
+
readonly contentId = computed(() => `kj-accordion-content-${this.kjItemValue()}-${this.idSeed}`);
|
|
259
|
+
|
|
260
|
+
/** Read-only mirror of the item value for context consumers. */
|
|
261
|
+
readonly value: Signal<string> = this.kjItemValue;
|
|
262
|
+
|
|
263
|
+
/** Read-only mirror of the disabled flag for context consumers. */
|
|
264
|
+
readonly disabled: Signal<boolean> = this.kjItemDisabled;
|
|
265
|
+
|
|
72
266
|
/** Whether this item is currently expanded. */
|
|
73
267
|
readonly expanded = computed(() => this.accordion.isOpen(this.kjItemValue()));
|
|
74
268
|
|
|
75
|
-
/** Toggles this item's expanded state. */
|
|
76
|
-
toggle(): void {
|
|
269
|
+
/** Toggles this item's expanded state. No-op when disabled. */
|
|
270
|
+
toggle(): void {
|
|
271
|
+
if (this.kjItemDisabled()) return;
|
|
272
|
+
this.accordion.toggle(this.kjItemValue());
|
|
273
|
+
}
|
|
77
274
|
|
|
78
|
-
/** Opens this item. */
|
|
79
|
-
open(): void {
|
|
275
|
+
/** Opens this item. No-op when disabled. */
|
|
276
|
+
open(): void {
|
|
277
|
+
if (this.kjItemDisabled()) return;
|
|
278
|
+
if (!this.expanded()) this.accordion.toggle(this.kjItemValue());
|
|
279
|
+
}
|
|
80
280
|
|
|
81
|
-
/** Closes this item. */
|
|
82
|
-
close(): void {
|
|
281
|
+
/** Closes this item. No-op when disabled. */
|
|
282
|
+
close(): void {
|
|
283
|
+
if (this.kjItemDisabled()) return;
|
|
284
|
+
if (this.expanded()) this.accordion.toggle(this.kjItemValue());
|
|
285
|
+
}
|
|
83
286
|
}
|
|
84
287
|
|
|
85
288
|
/**
|
|
86
|
-
* Trigger button for an accordion item.
|
|
87
|
-
*
|
|
289
|
+
* Trigger button for an accordion item. Wires `aria-expanded`, `aria-controls`,
|
|
290
|
+
* `aria-disabled`, and the click toggle. Also provides Enter / Space / arrow
|
|
291
|
+
* key handling — arrow keys are gated on the root's `kjArrowNavigation` flag.
|
|
292
|
+
*
|
|
293
|
+
* The host element should be a `<button>` per WAI-ARIA APG so Enter / Space
|
|
294
|
+
* activation, focus, and disabled semantics work without extra wiring.
|
|
88
295
|
*
|
|
89
296
|
* @example
|
|
90
297
|
* ```html
|
|
91
298
|
* <button kjAccordionTrigger>Section title</button>
|
|
92
299
|
* ```
|
|
93
|
-
* @category Core/
|
|
300
|
+
* @doc-category Core/Data display
|
|
301
|
+
* @doc
|
|
302
|
+
* @doc-name accordion
|
|
94
303
|
*/
|
|
95
304
|
@Directive({
|
|
96
305
|
selector: '[kjAccordionTrigger]',
|
|
97
306
|
standalone: true,
|
|
98
307
|
host: {
|
|
99
|
-
'[attr.
|
|
308
|
+
'[attr.id]': 'item.headerId()',
|
|
309
|
+
'[attr.aria-expanded]': 'item.expanded() ? "true" : "false"',
|
|
310
|
+
'[attr.aria-controls]': 'item.contentId()',
|
|
311
|
+
'[attr.aria-disabled]': 'item.disabled() ? "true" : null',
|
|
312
|
+
'[attr.data-state]': 'item.expanded() ? "open" : "closed"',
|
|
100
313
|
'[attr.data-open]': 'item.expanded() ? "" : null',
|
|
101
|
-
'
|
|
314
|
+
'[attr.data-disabled]': 'item.disabled() ? "" : null',
|
|
315
|
+
'(click)': 'onClick()',
|
|
316
|
+
'(keydown)': 'onKeydown($event)',
|
|
102
317
|
},
|
|
103
318
|
})
|
|
104
|
-
export class KjAccordionTrigger {
|
|
319
|
+
export class KjAccordionTrigger implements OnInit, OnDestroy {
|
|
105
320
|
/** The parent accordion item context. */
|
|
106
|
-
readonly item = inject(KJ_ACCORDION_ITEM);
|
|
321
|
+
readonly item = inject(KJ_ACCORDION_ITEM) as KjAccordionItem;
|
|
322
|
+
private readonly accordion = inject(KJ_ACCORDION) as KjAccordion;
|
|
323
|
+
/** @internal Native host element. */
|
|
324
|
+
readonly el = inject<ElementRef<HTMLElement>>(ElementRef);
|
|
325
|
+
|
|
326
|
+
ngOnInit(): void {
|
|
327
|
+
this.accordion.registerTrigger(this);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
ngOnDestroy(): void {
|
|
331
|
+
this.accordion.unregisterTrigger(this);
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/** @internal Click handler. */
|
|
335
|
+
onClick(): void {
|
|
336
|
+
if (this.item.disabled()) return;
|
|
337
|
+
this.item.toggle();
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
/** @internal Keydown handler — arrow-nav opt-in via `kjArrowNavigation` on the root. */
|
|
341
|
+
onKeydown(event: KeyboardEvent): void {
|
|
342
|
+
if (!this.accordion.arrowNavigation()) return;
|
|
343
|
+
const list = this.accordion.triggers();
|
|
344
|
+
const idx = list.indexOf(this);
|
|
345
|
+
if (idx === -1) return;
|
|
346
|
+
switch (event.key) {
|
|
347
|
+
case 'ArrowDown':
|
|
348
|
+
event.preventDefault();
|
|
349
|
+
this.accordion.focusTrigger(1, idx);
|
|
350
|
+
return;
|
|
351
|
+
case 'ArrowUp':
|
|
352
|
+
event.preventDefault();
|
|
353
|
+
this.accordion.focusTrigger(-1, idx);
|
|
354
|
+
return;
|
|
355
|
+
case 'Home':
|
|
356
|
+
event.preventDefault();
|
|
357
|
+
this.accordion.focusEdge('first');
|
|
358
|
+
return;
|
|
359
|
+
case 'End':
|
|
360
|
+
event.preventDefault();
|
|
361
|
+
this.accordion.focusEdge('last');
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
364
|
+
}
|
|
107
365
|
}
|
|
108
366
|
|
|
109
367
|
/**
|
|
110
|
-
* Accordion content panel.
|
|
111
|
-
*
|
|
368
|
+
* Accordion content panel. Hosts `role="region"` + `aria-labelledby` to the
|
|
369
|
+
* trigger's id. Visibility is signalled via `[data-state]` (`"open"` /
|
|
370
|
+
* `"closed"`) so consumers can CSS-animate the open/close transition. While
|
|
371
|
+
* closed, `aria-hidden="true"` and `inert` keep the panel out of the AT tree
|
|
372
|
+
* and tab sequence — the element stays in the DOM rather than being removed
|
|
373
|
+
* with `hidden`, which would interrupt the animation.
|
|
112
374
|
*
|
|
113
375
|
* @example
|
|
114
376
|
* ```html
|
|
115
377
|
* <div kjAccordionContent>Panel content</div>
|
|
116
378
|
* ```
|
|
117
|
-
* @category Core/
|
|
379
|
+
* @doc-category Core/Data display
|
|
380
|
+
* @doc
|
|
381
|
+
* @doc-name accordion
|
|
118
382
|
*/
|
|
119
383
|
@Directive({
|
|
120
384
|
selector: '[kjAccordionContent]',
|
|
121
385
|
standalone: true,
|
|
122
386
|
host: {
|
|
123
|
-
'[attr.
|
|
387
|
+
'[attr.role]': '"region"',
|
|
388
|
+
'[attr.id]': 'item.contentId()',
|
|
389
|
+
'[attr.aria-labelledby]': 'item.headerId()',
|
|
390
|
+
'[attr.data-state]': 'item.expanded() ? "open" : "closed"',
|
|
391
|
+
// `aria-hidden` keeps the closed panel out of the AT tree while leaving
|
|
392
|
+
// the element in the DOM so CSS can animate its open/close transition
|
|
393
|
+
// (driven by [data-state]). The visual hide is owned by the component CSS.
|
|
394
|
+
'[attr.aria-hidden]': '!item.expanded() ? "true" : null',
|
|
395
|
+
'[attr.inert]': '!item.expanded() ? "" : null',
|
|
124
396
|
},
|
|
125
397
|
})
|
|
126
398
|
export class KjAccordionContent {
|
package/src/accordion/index.ts
CHANGED
|
@@ -1,2 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
export {
|
|
1
|
+
export { KjAccordion, KjAccordionItem, KjAccordionTrigger, KjAccordionContent } from './accordion';
|
|
2
|
+
export {
|
|
3
|
+
KJ_ACCORDION,
|
|
4
|
+
KJ_ACCORDION_ITEM,
|
|
5
|
+
type KjAccordionContext,
|
|
6
|
+
type KjAccordionItemContext,
|
|
7
|
+
type KjAccordionType,
|
|
8
|
+
} from './accordion.context';
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { InjectionToken, Signal } from '@angular/core';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Resolved alert mode after applying the matrix. See `alert.md` for the
|
|
5
|
+
* full role/aria-live mapping.
|
|
6
|
+
*/
|
|
7
|
+
export type KjAlertMode = 'assertive' | 'polite' | 'static' | 'off';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Context exposed by `KjAlert` to its descendant directives via the
|
|
11
|
+
* `KJ_ALERT` injection token. Title/description register their generated
|
|
12
|
+
* ids so the root can reflect `aria-labelledby` / `aria-describedby`.
|
|
13
|
+
*/
|
|
14
|
+
export interface KjAlertContext {
|
|
15
|
+
readonly alertId: Signal<string>;
|
|
16
|
+
readonly variant: Signal<string>;
|
|
17
|
+
readonly mode: Signal<KjAlertMode>;
|
|
18
|
+
readonly titleId: Signal<string | null>;
|
|
19
|
+
readonly descriptionId: Signal<string | null>;
|
|
20
|
+
registerTitle(id: string): void;
|
|
21
|
+
unregisterTitle(id: string): void;
|
|
22
|
+
registerDescription(id: string): void;
|
|
23
|
+
unregisterDescription(id: string): void;
|
|
24
|
+
dismiss(): void;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** DI token for the alert context — provided by `KjAlert`. */
|
|
28
|
+
export const KJ_ALERT = new InjectionToken<KjAlertContext>('KjAlert');
|