@ng-cn/core 1.0.11 → 1.0.14
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/package.json +2 -1
- package/schematics/ng-add/index.js +8 -3
- package/schematics/ng-add/index.ts +11 -4
- package/src/app/lib/components/ui/accordion/accordion-content.component.ts +53 -0
- package/src/app/lib/components/ui/accordion/accordion-context.ts +33 -0
- package/src/app/lib/components/ui/accordion/accordion-item.component.ts +86 -0
- package/src/app/lib/components/ui/accordion/accordion-trigger.component.ts +73 -0
- package/src/app/lib/components/ui/accordion/accordion.component.ts +197 -0
- package/src/app/lib/components/ui/accordion/index.ts +15 -0
- package/src/app/lib/components/ui/alert/alert-description.component.ts +33 -0
- package/src/app/lib/components/ui/alert/alert-title.component.ts +30 -0
- package/src/app/lib/components/ui/alert/alert-variants.ts +23 -0
- package/src/app/lib/components/ui/alert/alert.component.ts +50 -0
- package/src/app/lib/components/ui/alert/index.ts +5 -0
- package/src/app/lib/components/ui/alert-dialog/alert-dialog-action.component.ts +44 -0
- package/src/app/lib/components/ui/alert-dialog/alert-dialog-cancel.component.ts +45 -0
- package/src/app/lib/components/ui/alert-dialog/alert-dialog-content.component.ts +146 -0
- package/src/app/lib/components/ui/alert-dialog/alert-dialog-context.ts +14 -0
- package/src/app/lib/components/ui/alert-dialog/alert-dialog-description.component.ts +37 -0
- package/src/app/lib/components/ui/alert-dialog/alert-dialog-footer.component.ts +35 -0
- package/src/app/lib/components/ui/alert-dialog/alert-dialog-header.component.ts +35 -0
- package/src/app/lib/components/ui/alert-dialog/alert-dialog-title.component.ts +37 -0
- package/src/app/lib/components/ui/alert-dialog/alert-dialog-trigger.component.ts +44 -0
- package/src/app/lib/components/ui/alert-dialog/alert-dialog.component.ts +91 -0
- package/src/app/lib/components/ui/alert-dialog/index.ts +11 -0
- package/src/app/lib/components/ui/aspect-ratio/aspect-ratio.component.ts +63 -0
- package/src/app/lib/components/ui/aspect-ratio/index.ts +1 -0
- package/src/app/lib/components/ui/avatar/avatar-fallback.component.ts +34 -0
- package/src/app/lib/components/ui/avatar/avatar-image.component.ts +31 -0
- package/src/app/lib/components/ui/avatar/avatar.component.ts +37 -0
- package/src/app/lib/components/ui/avatar/index.ts +5 -0
- package/src/app/lib/components/ui/avatar/ui-avatar.component.ts +52 -0
- package/src/app/lib/components/ui/badge/badge-variants.ts +28 -0
- package/src/app/lib/components/ui/badge/badge.component.ts +50 -0
- package/src/app/lib/components/ui/badge/index.ts +3 -0
- package/src/app/lib/components/ui/breadcrumb/breadcrumb-ellipsis.component.ts +48 -0
- package/src/app/lib/components/ui/breadcrumb/breadcrumb-item.component.ts +28 -0
- package/src/app/lib/components/ui/breadcrumb/breadcrumb-link.component.ts +32 -0
- package/src/app/lib/components/ui/breadcrumb/breadcrumb-list.component.ts +31 -0
- package/src/app/lib/components/ui/breadcrumb/breadcrumb-page.component.ts +31 -0
- package/src/app/lib/components/ui/breadcrumb/breadcrumb-separator.component.ts +47 -0
- package/src/app/lib/components/ui/breadcrumb/breadcrumb.component.ts +43 -0
- package/src/app/lib/components/ui/breadcrumb/index.ts +8 -0
- package/src/app/lib/components/ui/button/button-variants.ts +38 -0
- package/src/app/lib/components/ui/button/button.component.ts +103 -0
- package/src/app/lib/components/ui/button/index.ts +3 -0
- package/src/app/lib/components/ui/button-group/button-group-variants.ts +24 -0
- package/src/app/lib/components/ui/button-group/button-group.component.ts +57 -0
- package/src/app/lib/components/ui/button-group/index.ts +6 -0
- package/src/app/lib/components/ui/calendar/calendar.component.ts +368 -0
- package/src/app/lib/components/ui/calendar/index.ts +1 -0
- package/src/app/lib/components/ui/card/card-action.component.ts +39 -0
- package/src/app/lib/components/ui/card/card-content.component.ts +31 -0
- package/src/app/lib/components/ui/card/card-description.component.ts +31 -0
- package/src/app/lib/components/ui/card/card-footer.component.ts +34 -0
- package/src/app/lib/components/ui/card/card-header.component.ts +37 -0
- package/src/app/lib/components/ui/card/card-title.component.ts +31 -0
- package/src/app/lib/components/ui/card/card.component.ts +41 -0
- package/src/app/lib/components/ui/card/index.ts +8 -0
- package/src/app/lib/components/ui/carousel/carousel-content.component.ts +38 -0
- package/src/app/lib/components/ui/carousel/carousel-context.ts +18 -0
- package/src/app/lib/components/ui/carousel/carousel-item.component.ts +32 -0
- package/src/app/lib/components/ui/carousel/carousel-next.component.ts +54 -0
- package/src/app/lib/components/ui/carousel/carousel-previous.component.ts +54 -0
- package/src/app/lib/components/ui/carousel/carousel.component.ts +125 -0
- package/src/app/lib/components/ui/carousel/index.ts +7 -0
- package/src/app/lib/components/ui/chart/chart-container.component.ts +81 -0
- package/src/app/lib/components/ui/chart/chart-context.ts +38 -0
- package/src/app/lib/components/ui/chart/chart-legend-content.component.ts +51 -0
- package/src/app/lib/components/ui/chart/chart-legend.component.ts +28 -0
- package/src/app/lib/components/ui/chart/chart-tooltip-content.component.ts +37 -0
- package/src/app/lib/components/ui/chart/chart-tooltip.component.ts +28 -0
- package/src/app/lib/components/ui/chart/chart.component.ts +308 -0
- package/src/app/lib/components/ui/chart/index.ts +16 -0
- package/src/app/lib/components/ui/checkbox/checkbox.component.ts +203 -0
- package/src/app/lib/components/ui/checkbox/index.ts +1 -0
- package/src/app/lib/components/ui/collapsible/collapsible-content.component.ts +58 -0
- package/src/app/lib/components/ui/collapsible/collapsible-context.ts +17 -0
- package/src/app/lib/components/ui/collapsible/collapsible-trigger.component.ts +56 -0
- package/src/app/lib/components/ui/collapsible/collapsible.component.ts +102 -0
- package/src/app/lib/components/ui/collapsible/index.ts +5 -0
- package/src/app/lib/components/ui/combobox/combobox-content.component.ts +59 -0
- package/src/app/lib/components/ui/combobox/combobox-context.ts +49 -0
- package/src/app/lib/components/ui/combobox/combobox-empty.component.ts +35 -0
- package/src/app/lib/components/ui/combobox/combobox-group.component.ts +32 -0
- package/src/app/lib/components/ui/combobox/combobox-input.component.ts +89 -0
- package/src/app/lib/components/ui/combobox/combobox-item.component.ts +129 -0
- package/src/app/lib/components/ui/combobox/combobox-list.component.ts +40 -0
- package/src/app/lib/components/ui/combobox/combobox-trigger.component.ts +53 -0
- package/src/app/lib/components/ui/combobox/combobox-value.component.ts +47 -0
- package/src/app/lib/components/ui/combobox/combobox.component.ts +290 -0
- package/src/app/lib/components/ui/combobox/index.ts +15 -0
- package/src/app/lib/components/ui/command/command-context.ts +24 -0
- package/src/app/lib/components/ui/command/command-dialog.component.ts +69 -0
- package/src/app/lib/components/ui/command/command-empty.component.ts +23 -0
- package/src/app/lib/components/ui/command/command-group.component.ts +66 -0
- package/src/app/lib/components/ui/command/command-input.component.ts +137 -0
- package/src/app/lib/components/ui/command/command-item.component.ts +148 -0
- package/src/app/lib/components/ui/command/command-list.component.ts +30 -0
- package/src/app/lib/components/ui/command/command-separator.component.ts +23 -0
- package/src/app/lib/components/ui/command/command-shortcut.component.ts +23 -0
- package/src/app/lib/components/ui/command/command.component.ts +105 -0
- package/src/app/lib/components/ui/command/index.ts +11 -0
- package/src/app/lib/components/ui/context-menu/context-menu-checkbox-item.component.ts +68 -0
- package/src/app/lib/components/ui/context-menu/context-menu-content.component.ts +213 -0
- package/src/app/lib/components/ui/context-menu/context-menu-context.ts +17 -0
- package/src/app/lib/components/ui/context-menu/context-menu-item.component.ts +63 -0
- package/src/app/lib/components/ui/context-menu/context-menu-label.component.ts +30 -0
- package/src/app/lib/components/ui/context-menu/context-menu-radio-group.component.ts +36 -0
- package/src/app/lib/components/ui/context-menu/context-menu-radio-item.component.ts +71 -0
- package/src/app/lib/components/ui/context-menu/context-menu-separator.component.ts +24 -0
- package/src/app/lib/components/ui/context-menu/context-menu-shortcut.component.ts +23 -0
- package/src/app/lib/components/ui/context-menu/context-menu-sub-content.component.ts +51 -0
- package/src/app/lib/components/ui/context-menu/context-menu-sub-trigger.component.ts +50 -0
- package/src/app/lib/components/ui/context-menu/context-menu-sub.component.ts +31 -0
- package/src/app/lib/components/ui/context-menu/context-menu-trigger.component.ts +51 -0
- package/src/app/lib/components/ui/context-menu/context-menu.component.ts +27 -0
- package/src/app/lib/components/ui/context-menu/index.ts +15 -0
- package/src/app/lib/components/ui/data-table/data-table-content.component.ts +226 -0
- package/src/app/lib/components/ui/data-table/data-table-context.ts +49 -0
- package/src/app/lib/components/ui/data-table/data-table-pagination.component.ts +138 -0
- package/src/app/lib/components/ui/data-table/data-table-search.component.ts +52 -0
- package/src/app/lib/components/ui/data-table/data-table-toolbar.component.ts +27 -0
- package/src/app/lib/components/ui/data-table/data-table-view-options.component.ts +92 -0
- package/src/app/lib/components/ui/data-table/data-table.component.ts +131 -0
- package/src/app/lib/components/ui/data-table/index.ts +16 -0
- package/src/app/lib/components/ui/date-picker/date-picker.component.ts +94 -0
- package/src/app/lib/components/ui/date-picker/index.ts +1 -0
- package/src/app/lib/components/ui/dialog/dialog-close.component.ts +31 -0
- package/src/app/lib/components/ui/dialog/dialog-content.component.ts +177 -0
- package/src/app/lib/components/ui/dialog/dialog-context.ts +15 -0
- package/src/app/lib/components/ui/dialog/dialog-description.component.ts +34 -0
- package/src/app/lib/components/ui/dialog/dialog-footer.component.ts +28 -0
- package/src/app/lib/components/ui/dialog/dialog-header.component.ts +28 -0
- package/src/app/lib/components/ui/dialog/dialog-title.component.ts +34 -0
- package/src/app/lib/components/ui/dialog/dialog-trigger.component.ts +38 -0
- package/src/app/lib/components/ui/dialog/dialog.component.ts +87 -0
- package/src/app/lib/components/ui/dialog/index.ts +10 -0
- package/src/app/lib/components/ui/drawer/drawer-close.component.ts +31 -0
- package/src/app/lib/components/ui/drawer/drawer-content.component.ts +143 -0
- package/src/app/lib/components/ui/drawer/drawer-context.ts +17 -0
- package/src/app/lib/components/ui/drawer/drawer-description.component.ts +33 -0
- package/src/app/lib/components/ui/drawer/drawer-footer.component.ts +28 -0
- package/src/app/lib/components/ui/drawer/drawer-header.component.ts +28 -0
- package/src/app/lib/components/ui/drawer/drawer-title.component.ts +33 -0
- package/src/app/lib/components/ui/drawer/drawer-trigger.component.ts +38 -0
- package/src/app/lib/components/ui/drawer/drawer.component.ts +93 -0
- package/src/app/lib/components/ui/drawer/index.ts +10 -0
- package/src/app/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-item.component.ts +68 -0
- package/src/app/lib/components/ui/dropdown-menu/dropdown-menu-content.component.ts +234 -0
- package/src/app/lib/components/ui/dropdown-menu/dropdown-menu-context.ts +15 -0
- package/src/app/lib/components/ui/dropdown-menu/dropdown-menu-group.component.ts +15 -0
- package/src/app/lib/components/ui/dropdown-menu/dropdown-menu-item.component.ts +56 -0
- package/src/app/lib/components/ui/dropdown-menu/dropdown-menu-label.component.ts +30 -0
- package/src/app/lib/components/ui/dropdown-menu/dropdown-menu-radio-group.component.ts +42 -0
- package/src/app/lib/components/ui/dropdown-menu/dropdown-menu-radio-item.component.ts +71 -0
- package/src/app/lib/components/ui/dropdown-menu/dropdown-menu-separator.component.ts +24 -0
- package/src/app/lib/components/ui/dropdown-menu/dropdown-menu-shortcut.component.ts +23 -0
- package/src/app/lib/components/ui/dropdown-menu/dropdown-menu-sub-content.component.ts +51 -0
- package/src/app/lib/components/ui/dropdown-menu/dropdown-menu-sub-trigger.component.ts +53 -0
- package/src/app/lib/components/ui/dropdown-menu/dropdown-menu-sub.component.ts +31 -0
- package/src/app/lib/components/ui/dropdown-menu/dropdown-menu-trigger.component.ts +45 -0
- package/src/app/lib/components/ui/dropdown-menu/dropdown-menu.component.ts +32 -0
- package/src/app/lib/components/ui/dropdown-menu/index.ts +16 -0
- package/src/app/lib/components/ui/empty/empty-action.component.ts +28 -0
- package/src/app/lib/components/ui/empty/empty-description.component.ts +31 -0
- package/src/app/lib/components/ui/empty/empty-icon.component.ts +31 -0
- package/src/app/lib/components/ui/empty/empty-title.component.ts +28 -0
- package/src/app/lib/components/ui/empty/empty.component.ts +53 -0
- package/src/app/lib/components/ui/empty/index.ts +6 -0
- package/src/app/lib/components/ui/form/form-context.ts +34 -0
- package/src/app/lib/components/ui/form/form-control.component.ts +137 -0
- package/src/app/lib/components/ui/form/form-description.component.ts +37 -0
- package/src/app/lib/components/ui/form/form-field.component.ts +84 -0
- package/src/app/lib/components/ui/form/form-item.component.ts +42 -0
- package/src/app/lib/components/ui/form/form-label.component.ts +58 -0
- package/src/app/lib/components/ui/form/form-message.component.ts +107 -0
- package/src/app/lib/components/ui/form/form.component.ts +123 -0
- package/src/app/lib/components/ui/form/index.ts +17 -0
- package/src/app/lib/components/ui/hover-card/hover-card-content.component.ts +203 -0
- package/src/app/lib/components/ui/hover-card/hover-card-context.ts +25 -0
- package/src/app/lib/components/ui/hover-card/hover-card-trigger.component.ts +160 -0
- package/src/app/lib/components/ui/hover-card/hover-card.component.ts +147 -0
- package/src/app/lib/components/ui/hover-card/index.ts +13 -0
- package/src/app/lib/components/ui/index.ts +551 -0
- package/src/app/lib/components/ui/input/index.ts +1 -0
- package/src/app/lib/components/ui/input/input.component.ts +165 -0
- package/src/app/lib/components/ui/input-group/index.ts +4 -0
- package/src/app/lib/components/ui/input-group/input-group-addon.component.ts +43 -0
- package/src/app/lib/components/ui/input-group/input-group-input.component.ts +33 -0
- package/src/app/lib/components/ui/input-group/input-group.component.ts +53 -0
- package/src/app/lib/components/ui/input-otp/index.ts +14 -0
- package/src/app/lib/components/ui/input-otp/input-otp-context.ts +31 -0
- package/src/app/lib/components/ui/input-otp/input-otp-group.component.ts +23 -0
- package/src/app/lib/components/ui/input-otp/input-otp-separator.component.ts +31 -0
- package/src/app/lib/components/ui/input-otp/input-otp-slot.component.ts +67 -0
- package/src/app/lib/components/ui/input-otp/input-otp.component.ts +240 -0
- package/src/app/lib/components/ui/kbd/index.ts +3 -0
- package/src/app/lib/components/ui/kbd/kbd-variants.ts +23 -0
- package/src/app/lib/components/ui/kbd/kbd.component.ts +50 -0
- package/src/app/lib/components/ui/label/index.ts +1 -0
- package/src/app/lib/components/ui/label/label.component.ts +139 -0
- package/src/app/lib/components/ui/menubar/index.ts +26 -0
- package/src/app/lib/components/ui/menubar/menubar-checkbox-item.component.ts +66 -0
- package/src/app/lib/components/ui/menubar/menubar-content.component.ts +236 -0
- package/src/app/lib/components/ui/menubar/menubar-context.ts +63 -0
- package/src/app/lib/components/ui/menubar/menubar-item.component.ts +60 -0
- package/src/app/lib/components/ui/menubar/menubar-label.component.ts +30 -0
- package/src/app/lib/components/ui/menubar/menubar-menu.component.ts +40 -0
- package/src/app/lib/components/ui/menubar/menubar-radio-group.component.ts +36 -0
- package/src/app/lib/components/ui/menubar/menubar-radio-item.component.ts +66 -0
- package/src/app/lib/components/ui/menubar/menubar-separator.component.ts +24 -0
- package/src/app/lib/components/ui/menubar/menubar-shortcut.component.ts +23 -0
- package/src/app/lib/components/ui/menubar/menubar-sub-content.component.ts +51 -0
- package/src/app/lib/components/ui/menubar/menubar-sub-trigger.component.ts +50 -0
- package/src/app/lib/components/ui/menubar/menubar-sub.component.ts +29 -0
- package/src/app/lib/components/ui/menubar/menubar-trigger.component.ts +132 -0
- package/src/app/lib/components/ui/menubar/menubar.component.ts +158 -0
- package/src/app/lib/components/ui/native-select/index.ts +6 -0
- package/src/app/lib/components/ui/native-select/native-select-variants.ts +23 -0
- package/src/app/lib/components/ui/native-select/native-select.component.ts +74 -0
- package/src/app/lib/components/ui/navigation-menu/index.ts +21 -0
- package/src/app/lib/components/ui/navigation-menu/navigation-menu-content.component.ts +66 -0
- package/src/app/lib/components/ui/navigation-menu/navigation-menu-context.ts +55 -0
- package/src/app/lib/components/ui/navigation-menu/navigation-menu-indicator.component.ts +28 -0
- package/src/app/lib/components/ui/navigation-menu/navigation-menu-item.component.ts +29 -0
- package/src/app/lib/components/ui/navigation-menu/navigation-menu-link.component.ts +43 -0
- package/src/app/lib/components/ui/navigation-menu/navigation-menu-list.component.ts +26 -0
- package/src/app/lib/components/ui/navigation-menu/navigation-menu-trigger-style.ts +7 -0
- package/src/app/lib/components/ui/navigation-menu/navigation-menu-trigger.component.ts +58 -0
- package/src/app/lib/components/ui/navigation-menu/navigation-menu-viewport.component.ts +26 -0
- package/src/app/lib/components/ui/navigation-menu/navigation-menu.component.ts +149 -0
- package/src/app/lib/components/ui/pagination/index.ts +8 -0
- package/src/app/lib/components/ui/pagination/pagination-content.component.ts +28 -0
- package/src/app/lib/components/ui/pagination/pagination-ellipsis.component.ts +47 -0
- package/src/app/lib/components/ui/pagination/pagination-item.component.ts +28 -0
- package/src/app/lib/components/ui/pagination/pagination-link.component.ts +46 -0
- package/src/app/lib/components/ui/pagination/pagination-next.component.ts +54 -0
- package/src/app/lib/components/ui/pagination/pagination-previous.component.ts +54 -0
- package/src/app/lib/components/ui/pagination/pagination.component.ts +48 -0
- package/src/app/lib/components/ui/popover/index.ts +14 -0
- package/src/app/lib/components/ui/popover/popover-anchor.component.ts +64 -0
- package/src/app/lib/components/ui/popover/popover-content.component.ts +231 -0
- package/src/app/lib/components/ui/popover/popover-context.ts +29 -0
- package/src/app/lib/components/ui/popover/popover-trigger.component.ts +100 -0
- package/src/app/lib/components/ui/popover/popover.component.ts +163 -0
- package/src/app/lib/components/ui/progress/index.ts +6 -0
- package/src/app/lib/components/ui/progress/progress.component.ts +212 -0
- package/src/app/lib/components/ui/radio-group/index.ts +10 -0
- package/src/app/lib/components/ui/radio-group/radio-group-context.ts +38 -0
- package/src/app/lib/components/ui/radio-group/radio-group-item.component.ts +298 -0
- package/src/app/lib/components/ui/radio-group/radio-group.component.ts +275 -0
- package/src/app/lib/components/ui/resizable/index.ts +5 -0
- package/src/app/lib/components/ui/resizable/resizable-context.ts +14 -0
- package/src/app/lib/components/ui/resizable/resizable-handle.component.ts +232 -0
- package/src/app/lib/components/ui/resizable/resizable-panel-group.component.ts +140 -0
- package/src/app/lib/components/ui/resizable/resizable-panel.component.ts +77 -0
- package/src/app/lib/components/ui/scroll-area/index.ts +8 -0
- package/src/app/lib/components/ui/scroll-area/scroll-area.component.ts +126 -0
- package/src/app/lib/components/ui/scroll-area/scroll-bar.component.ts +93 -0
- package/src/app/lib/components/ui/segmented/index.ts +13 -0
- package/src/app/lib/components/ui/segmented/segmented-context.ts +11 -0
- package/src/app/lib/components/ui/segmented/segmented-item.component.ts +72 -0
- package/src/app/lib/components/ui/segmented/segmented-variants.ts +40 -0
- package/src/app/lib/components/ui/segmented/segmented.component.ts +99 -0
- package/src/app/lib/components/ui/select/index.ts +19 -0
- package/src/app/lib/components/ui/select/select-content.component.ts +97 -0
- package/src/app/lib/components/ui/select/select-context.ts +53 -0
- package/src/app/lib/components/ui/select/select-group.component.ts +56 -0
- package/src/app/lib/components/ui/select/select-item.component.ts +163 -0
- package/src/app/lib/components/ui/select/select-label.component.ts +32 -0
- package/src/app/lib/components/ui/select/select-separator.component.ts +34 -0
- package/src/app/lib/components/ui/select/select-trigger.component.ts +164 -0
- package/src/app/lib/components/ui/select/select-value.component.ts +49 -0
- package/src/app/lib/components/ui/select/select.component.ts +263 -0
- package/src/app/lib/components/ui/separator/index.ts +6 -0
- package/src/app/lib/components/ui/separator/separator.component.ts +128 -0
- package/src/app/lib/components/ui/sheet/index.ts +11 -0
- package/src/app/lib/components/ui/sheet/sheet-close.component.ts +32 -0
- package/src/app/lib/components/ui/sheet/sheet-content.component.ts +157 -0
- package/src/app/lib/components/ui/sheet/sheet-context.ts +15 -0
- package/src/app/lib/components/ui/sheet/sheet-description.component.ts +34 -0
- package/src/app/lib/components/ui/sheet/sheet-footer.component.ts +28 -0
- package/src/app/lib/components/ui/sheet/sheet-header.component.ts +28 -0
- package/src/app/lib/components/ui/sheet/sheet-title.component.ts +34 -0
- package/src/app/lib/components/ui/sheet/sheet-trigger.component.ts +38 -0
- package/src/app/lib/components/ui/sheet/sheet-variants.ts +22 -0
- package/src/app/lib/components/ui/sheet/sheet.component.ts +97 -0
- package/src/app/lib/components/ui/sidebar/index.ts +41 -0
- package/src/app/lib/components/ui/sidebar/sidebar-content.component.ts +31 -0
- package/src/app/lib/components/ui/sidebar/sidebar-context.ts +33 -0
- package/src/app/lib/components/ui/sidebar/sidebar-footer.component.ts +28 -0
- package/src/app/lib/components/ui/sidebar/sidebar-group-action.component.ts +33 -0
- package/src/app/lib/components/ui/sidebar/sidebar-group-content.component.ts +28 -0
- package/src/app/lib/components/ui/sidebar/sidebar-group-label.component.ts +32 -0
- package/src/app/lib/components/ui/sidebar/sidebar-group.component.ts +28 -0
- package/src/app/lib/components/ui/sidebar/sidebar-header.component.ts +28 -0
- package/src/app/lib/components/ui/sidebar/sidebar-input.component.ts +31 -0
- package/src/app/lib/components/ui/sidebar/sidebar-inset.component.ts +31 -0
- package/src/app/lib/components/ui/sidebar/sidebar-menu-action.component.ts +56 -0
- package/src/app/lib/components/ui/sidebar/sidebar-menu-badge.component.ts +42 -0
- package/src/app/lib/components/ui/sidebar/sidebar-menu-button.component.ts +64 -0
- package/src/app/lib/components/ui/sidebar/sidebar-menu-item.component.ts +32 -0
- package/src/app/lib/components/ui/sidebar/sidebar-menu-skeleton.component.ts +39 -0
- package/src/app/lib/components/ui/sidebar/sidebar-menu-sub-button.component.ts +59 -0
- package/src/app/lib/components/ui/sidebar/sidebar-menu-sub-item.component.ts +25 -0
- package/src/app/lib/components/ui/sidebar/sidebar-menu-sub.component.ts +32 -0
- package/src/app/lib/components/ui/sidebar/sidebar-menu.component.ts +31 -0
- package/src/app/lib/components/ui/sidebar/sidebar-provider.component.ts +141 -0
- package/src/app/lib/components/ui/sidebar/sidebar-rail.component.ts +47 -0
- package/src/app/lib/components/ui/sidebar/sidebar-route-active.service.ts +124 -0
- package/src/app/lib/components/ui/sidebar/sidebar-separator.component.ts +28 -0
- package/src/app/lib/components/ui/sidebar/sidebar-trigger.component.ts +57 -0
- package/src/app/lib/components/ui/sidebar/sidebar.component.ts +130 -0
- package/src/app/lib/components/ui/skeleton/index.ts +1 -0
- package/src/app/lib/components/ui/skeleton/skeleton.component.ts +52 -0
- package/src/app/lib/components/ui/slider/index.ts +6 -0
- package/src/app/lib/components/ui/slider/slider.component.ts +477 -0
- package/src/app/lib/components/ui/spinner/index.ts +3 -0
- package/src/app/lib/components/ui/spinner/spinner-variants.ts +32 -0
- package/src/app/lib/components/ui/spinner/spinner.component.ts +77 -0
- package/src/app/lib/components/ui/switch/index.ts +6 -0
- package/src/app/lib/components/ui/switch/switch.component.ts +282 -0
- package/src/app/lib/components/ui/table/index.ts +9 -0
- package/src/app/lib/components/ui/table/table-body.component.ts +28 -0
- package/src/app/lib/components/ui/table/table-caption.component.ts +28 -0
- package/src/app/lib/components/ui/table/table-cell.component.ts +31 -0
- package/src/app/lib/components/ui/table/table-footer.component.ts +28 -0
- package/src/app/lib/components/ui/table/table-head.component.ts +36 -0
- package/src/app/lib/components/ui/table/table-header.component.ts +28 -0
- package/src/app/lib/components/ui/table/table-row.component.ts +34 -0
- package/src/app/lib/components/ui/table/table.component.ts +52 -0
- package/src/app/lib/components/ui/tabs/index.ts +14 -0
- package/src/app/lib/components/ui/tabs/tabs-content.component.ts +132 -0
- package/src/app/lib/components/ui/tabs/tabs-context.ts +33 -0
- package/src/app/lib/components/ui/tabs/tabs-list.component.ts +228 -0
- package/src/app/lib/components/ui/tabs/tabs-trigger.component.ts +167 -0
- package/src/app/lib/components/ui/tabs/tabs.component.ts +203 -0
- package/src/app/lib/components/ui/textarea/index.ts +1 -0
- package/src/app/lib/components/ui/textarea/textarea.component.ts +44 -0
- package/src/app/lib/components/ui/toast/index.ts +16 -0
- package/src/app/lib/components/ui/toast/toast-action.component.ts +77 -0
- package/src/app/lib/components/ui/toast/toast-description.component.ts +52 -0
- package/src/app/lib/components/ui/toast/toast-title.component.ts +52 -0
- package/src/app/lib/components/ui/toast/toast-variants.ts +24 -0
- package/src/app/lib/components/ui/toast/toast.component.ts +177 -0
- package/src/app/lib/components/ui/toast/toast.service.ts +202 -0
- package/src/app/lib/components/ui/toast/toaster.component.ts +128 -0
- package/src/app/lib/components/ui/toggle/index.ts +6 -0
- package/src/app/lib/components/ui/toggle/toggle-variants.ts +30 -0
- package/src/app/lib/components/ui/toggle/toggle.component.ts +199 -0
- package/src/app/lib/components/ui/toggle-group/index.ts +11 -0
- package/src/app/lib/components/ui/toggle-group/toggle-group-context.ts +48 -0
- package/src/app/lib/components/ui/toggle-group/toggle-group-item.component.ts +241 -0
- package/src/app/lib/components/ui/toggle-group/toggle-group.component.ts +288 -0
- package/src/app/lib/components/ui/tooltip/index.ts +14 -0
- package/src/app/lib/components/ui/tooltip/tooltip-content.component.ts +154 -0
- package/src/app/lib/components/ui/tooltip/tooltip-context.ts +29 -0
- package/src/app/lib/components/ui/tooltip/tooltip-provider.component.ts +95 -0
- package/src/app/lib/components/ui/tooltip/tooltip-trigger.component.ts +138 -0
- package/src/app/lib/components/ui/tooltip/tooltip.component.ts +159 -0
- package/src/app/lib/components/ui/typography/index.ts +13 -0
- package/src/app/lib/components/ui/typography/typography-blockquote.component.ts +31 -0
- package/src/app/lib/components/ui/typography/typography-h1.component.ts +32 -0
- package/src/app/lib/components/ui/typography/typography-h2.component.ts +32 -0
- package/src/app/lib/components/ui/typography/typography-h3.component.ts +29 -0
- package/src/app/lib/components/ui/typography/typography-h4.component.ts +29 -0
- package/src/app/lib/components/ui/typography/typography-inline-code.component.ts +31 -0
- package/src/app/lib/components/ui/typography/typography-large.component.ts +28 -0
- package/src/app/lib/components/ui/typography/typography-lead.component.ts +31 -0
- package/src/app/lib/components/ui/typography/typography-list.component.ts +31 -0
- package/src/app/lib/components/ui/typography/typography-muted.component.ts +28 -0
- package/src/app/lib/components/ui/typography/typography-p.component.ts +29 -0
- package/src/app/lib/components/ui/typography/typography-small.component.ts +28 -0
- package/src/app/lib/index.ts +7 -0
- package/src/app/lib/utils/accessibility/aria-id.service.ts +118 -0
- package/src/app/lib/utils/accessibility/click-outside.directive.ts +85 -0
- package/src/app/lib/utils/accessibility/focus-management.service.ts +231 -0
- package/src/app/lib/utils/accessibility/focus-trap.directive.ts +203 -0
- package/src/app/lib/utils/accessibility/index.ts +23 -0
- package/src/app/lib/utils/accessibility/keyboard-navigation.directive.ts +440 -0
- package/src/app/lib/utils/accessibility/live-region.directive.ts +260 -0
- package/src/app/lib/utils/accessibility/touch-target.directive.ts +81 -0
- package/src/app/lib/utils/accessibility/visually-hidden.component.ts +79 -0
- package/src/app/lib/utils/animation/animated.directive.ts +191 -0
- package/src/app/lib/utils/animation/animation-tokens.service.ts +88 -0
- package/src/app/lib/utils/animation/animation.types.ts +55 -0
- package/src/app/lib/utils/animation/animation.utils.ts +158 -0
- package/src/app/lib/utils/animation/index.ts +17 -0
- package/src/app/lib/utils/animation/presence.component.ts +168 -0
- package/src/app/lib/utils/animation/presence.directive.ts +169 -0
- package/src/app/lib/utils/cn.ts +15 -0
- package/src/app/lib/utils/index.ts +11 -0
- package/src/app/lib/utils/positioning/index.ts +218 -0
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { cn } from '@/lib/utils';
|
|
2
|
+
import {
|
|
3
|
+
ChangeDetectionStrategy,
|
|
4
|
+
Component,
|
|
5
|
+
computed,
|
|
6
|
+
inject,
|
|
7
|
+
input,
|
|
8
|
+
} from '@angular/core';
|
|
9
|
+
import { TABS_CONTEXT } from './tabs-context';
|
|
10
|
+
|
|
11
|
+
// ============================================================================
|
|
12
|
+
// Types
|
|
13
|
+
// ============================================================================
|
|
14
|
+
|
|
15
|
+
export type TabsContentState = 'active' | 'inactive';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Props for the TabsContent component
|
|
19
|
+
*/
|
|
20
|
+
export interface TabsContentProps {
|
|
21
|
+
/** A unique value that associates the content with a trigger */
|
|
22
|
+
value: string;
|
|
23
|
+
/** Used to force mounting when more control is needed.
|
|
24
|
+
* Useful when controlling animation with CSS animation libraries.
|
|
25
|
+
* @default false */
|
|
26
|
+
forceMount?: boolean;
|
|
27
|
+
/** Additional CSS classes */
|
|
28
|
+
class?: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// ============================================================================
|
|
32
|
+
// Component
|
|
33
|
+
// ============================================================================
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* @component TabsContent
|
|
37
|
+
*
|
|
38
|
+
* Contains the content associated with each trigger.
|
|
39
|
+
*
|
|
40
|
+
* @description
|
|
41
|
+
* TabsContent holds the content for each tab panel. It is shown when its
|
|
42
|
+
* associated TabsTrigger is activated.
|
|
43
|
+
*
|
|
44
|
+
* ## Features
|
|
45
|
+
* - Conditional rendering (unmounts when inactive by default)
|
|
46
|
+
* - Force mount option for animation control
|
|
47
|
+
* - Proper ARIA tabpanel role
|
|
48
|
+
* - Focusable when active
|
|
49
|
+
*
|
|
50
|
+
* ## Accessibility
|
|
51
|
+
* - `role="tabpanel"` on the element
|
|
52
|
+
* - `aria-labelledby` points to associated trigger
|
|
53
|
+
* - `hidden` attribute when inactive
|
|
54
|
+
* - `tabindex="0"` when active for keyboard access
|
|
55
|
+
*
|
|
56
|
+
* @example Basic usage
|
|
57
|
+
* ```html
|
|
58
|
+
* <TabsContent value="account">
|
|
59
|
+
* <p>Account settings content here</p>
|
|
60
|
+
* </TabsContent>
|
|
61
|
+
* ```
|
|
62
|
+
*
|
|
63
|
+
* @example Force mounted (for animations)
|
|
64
|
+
* ```html
|
|
65
|
+
* <TabsContent value="account" [forceMount]="true">
|
|
66
|
+
* <p>Content stays in DOM even when inactive</p>
|
|
67
|
+
* </TabsContent>
|
|
68
|
+
* ```
|
|
69
|
+
*
|
|
70
|
+
* @data-attributes
|
|
71
|
+
* - `data-state` - 'active' | 'inactive'
|
|
72
|
+
* - `data-orientation` - Inherited from parent Tabs
|
|
73
|
+
*/
|
|
74
|
+
@Component({
|
|
75
|
+
selector: 'TabsContent',
|
|
76
|
+
template: `
|
|
77
|
+
@if (shouldRender()) {
|
|
78
|
+
<ng-content />
|
|
79
|
+
}
|
|
80
|
+
`,
|
|
81
|
+
host: {
|
|
82
|
+
'[class]': 'computedClass()',
|
|
83
|
+
'[attr.id]': 'panelId()',
|
|
84
|
+
'[attr.data-state]': 'state()',
|
|
85
|
+
'[attr.data-orientation]': 'tabs.orientation()',
|
|
86
|
+
'[attr.aria-labelledby]': 'tabId()',
|
|
87
|
+
'[attr.hidden]': '!isActive() ? true : null',
|
|
88
|
+
'[attr.tabindex]': 'isActive() ? 0 : -1',
|
|
89
|
+
'role': 'tabpanel',
|
|
90
|
+
},
|
|
91
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
92
|
+
})
|
|
93
|
+
export class TabsContent {
|
|
94
|
+
protected readonly tabs = inject(TABS_CONTEXT);
|
|
95
|
+
|
|
96
|
+
/** A unique value that associates the content with a trigger */
|
|
97
|
+
readonly value = input.required<string>();
|
|
98
|
+
|
|
99
|
+
/** Used to force mounting when more control is needed */
|
|
100
|
+
readonly forceMount = input<boolean>(false);
|
|
101
|
+
|
|
102
|
+
/** Additional CSS classes */
|
|
103
|
+
readonly class = input<string>('');
|
|
104
|
+
|
|
105
|
+
/** Check if this content should be visible */
|
|
106
|
+
protected readonly isActive = computed(() => this.tabs.value() === this.value());
|
|
107
|
+
|
|
108
|
+
/** Current state: active or inactive */
|
|
109
|
+
protected readonly state = computed<TabsContentState>(() =>
|
|
110
|
+
this.isActive() ? 'active' : 'inactive'
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
/** Whether content should be rendered (force mount or active) */
|
|
114
|
+
protected readonly shouldRender = computed(() =>
|
|
115
|
+
this.forceMount() || this.isActive()
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
/** Generate panel ID */
|
|
119
|
+
protected readonly panelId = computed(() => this.tabs.getPanelId(this.value()));
|
|
120
|
+
|
|
121
|
+
/** Generate tab ID for aria-labelledby */
|
|
122
|
+
protected readonly tabId = computed(() => this.tabs.getTabId(this.value()));
|
|
123
|
+
|
|
124
|
+
protected readonly computedClass = computed(() =>
|
|
125
|
+
cn(
|
|
126
|
+
'flex-1 outline-none',
|
|
127
|
+
'ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',
|
|
128
|
+
'mt-2',
|
|
129
|
+
this.class()
|
|
130
|
+
)
|
|
131
|
+
);
|
|
132
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { InjectionToken, WritableSignal } from '@angular/core';
|
|
2
|
+
|
|
3
|
+
// ============================================================================
|
|
4
|
+
// Types
|
|
5
|
+
// ============================================================================
|
|
6
|
+
|
|
7
|
+
export type TabsOrientation = 'horizontal' | 'vertical';
|
|
8
|
+
export type TabsActivationMode = 'automatic' | 'manual';
|
|
9
|
+
|
|
10
|
+
export interface TabsContext {
|
|
11
|
+
/** Current active tab value */
|
|
12
|
+
value: () => string;
|
|
13
|
+
/** Handle tab change */
|
|
14
|
+
onValueChange: (value: string) => void;
|
|
15
|
+
/** ARIA ID for the tablist */
|
|
16
|
+
tablistId: string;
|
|
17
|
+
/** Generate tab ID for a specific value */
|
|
18
|
+
getTabId: (value: string) => string;
|
|
19
|
+
/** Generate panel ID for a specific value */
|
|
20
|
+
getPanelId: (value: string) => string;
|
|
21
|
+
/** Orientation for keyboard navigation */
|
|
22
|
+
orientation: () => TabsOrientation;
|
|
23
|
+
/** Activation mode: automatic (on focus) or manual (on click/enter) */
|
|
24
|
+
activationMode: () => TabsActivationMode;
|
|
25
|
+
/** Registry of tab values for keyboard navigation */
|
|
26
|
+
tabValues: WritableSignal<string[]>;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// ============================================================================
|
|
30
|
+
// Injection Tokens
|
|
31
|
+
// ============================================================================
|
|
32
|
+
|
|
33
|
+
export const TABS_CONTEXT = new InjectionToken<TabsContext>('TabsContext');
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import { cn } from '@/lib/utils';
|
|
2
|
+
import {
|
|
3
|
+
afterNextRender,
|
|
4
|
+
ChangeDetectionStrategy,
|
|
5
|
+
Component,
|
|
6
|
+
computed,
|
|
7
|
+
effect,
|
|
8
|
+
ElementRef,
|
|
9
|
+
inject,
|
|
10
|
+
Injector,
|
|
11
|
+
input,
|
|
12
|
+
signal,
|
|
13
|
+
} from '@angular/core';
|
|
14
|
+
import { TABS_CONTEXT } from './tabs-context';
|
|
15
|
+
|
|
16
|
+
// ============================================================================
|
|
17
|
+
// Types
|
|
18
|
+
// ============================================================================
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Props for the TabsList component
|
|
22
|
+
*/
|
|
23
|
+
export interface TabsListProps {
|
|
24
|
+
/** Whether to show the animated indicator.
|
|
25
|
+
* @default true */
|
|
26
|
+
showIndicator?: boolean;
|
|
27
|
+
/** Additional CSS classes for the indicator */
|
|
28
|
+
indicatorClass?: string;
|
|
29
|
+
/** Additional CSS classes */
|
|
30
|
+
class?: string;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// ============================================================================
|
|
34
|
+
// Component
|
|
35
|
+
// ============================================================================
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @component TabsList
|
|
39
|
+
*
|
|
40
|
+
* Contains the tab triggers. Provides proper ARIA tablist role and keyboard navigation.
|
|
41
|
+
*
|
|
42
|
+
* @description
|
|
43
|
+
* TabsList serves as the container for TabsTrigger components and implements
|
|
44
|
+
* the tablist role with proper ARIA attributes and keyboard navigation.
|
|
45
|
+
*
|
|
46
|
+
* ## Features
|
|
47
|
+
* - Animated indicator showing active tab
|
|
48
|
+
* - Full keyboard navigation (arrow keys, Home, End)
|
|
49
|
+
* - Proper ARIA tablist role
|
|
50
|
+
* - Horizontal and vertical orientation support
|
|
51
|
+
* - Automatic or manual activation modes
|
|
52
|
+
*
|
|
53
|
+
* ## Accessibility
|
|
54
|
+
* - `role="tablist"` on the container
|
|
55
|
+
* - `aria-orientation` reflects the orientation
|
|
56
|
+
* - Manages focus between tabs via roving tabindex
|
|
57
|
+
*
|
|
58
|
+
* ## Keyboard Navigation
|
|
59
|
+
* - `ArrowRight/ArrowLeft` - Navigate tabs (horizontal)
|
|
60
|
+
* - `ArrowDown/ArrowUp` - Navigate tabs (vertical)
|
|
61
|
+
* - `Home` - Focus first tab
|
|
62
|
+
* - `End` - Focus last tab
|
|
63
|
+
*
|
|
64
|
+
* @example Basic usage
|
|
65
|
+
* ```html
|
|
66
|
+
* <TabsList>
|
|
67
|
+
* <TabsTrigger value="tab1">Tab 1</TabsTrigger>
|
|
68
|
+
* <TabsTrigger value="tab2">Tab 2</TabsTrigger>
|
|
69
|
+
* </TabsList>
|
|
70
|
+
* ```
|
|
71
|
+
*
|
|
72
|
+
* @example Without indicator
|
|
73
|
+
* ```html
|
|
74
|
+
* <TabsList [showIndicator]="false">
|
|
75
|
+
* <TabsTrigger value="tab1">Tab 1</TabsTrigger>
|
|
76
|
+
* <TabsTrigger value="tab2">Tab 2</TabsTrigger>
|
|
77
|
+
* </TabsList>
|
|
78
|
+
* ```
|
|
79
|
+
*
|
|
80
|
+
* @data-attributes Inherits data-orientation from parent Tabs
|
|
81
|
+
*/
|
|
82
|
+
@Component({
|
|
83
|
+
selector: 'TabsList',
|
|
84
|
+
template: `
|
|
85
|
+
<ng-content />
|
|
86
|
+
@if (showIndicator()) {
|
|
87
|
+
<span
|
|
88
|
+
data-slot="tabs-indicator"
|
|
89
|
+
[class]="computedIndicatorClass()"
|
|
90
|
+
[style.width.px]="indicatorStyle().width"
|
|
91
|
+
[style.left.px]="indicatorStyle().left"
|
|
92
|
+
aria-hidden="true"
|
|
93
|
+
></span>
|
|
94
|
+
}
|
|
95
|
+
`,
|
|
96
|
+
host: {
|
|
97
|
+
'[class]': 'computedClass()',
|
|
98
|
+
'role': 'tablist',
|
|
99
|
+
'[attr.id]': 'tabs.tablistId',
|
|
100
|
+
'[attr.aria-orientation]': 'tabs.orientation()',
|
|
101
|
+
'(keydown)': 'onKeydown($event)',
|
|
102
|
+
},
|
|
103
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
104
|
+
})
|
|
105
|
+
export class TabsList {
|
|
106
|
+
protected readonly tabs = inject(TABS_CONTEXT);
|
|
107
|
+
private readonly elementRef = inject(ElementRef);
|
|
108
|
+
private readonly injector = inject(Injector);
|
|
109
|
+
|
|
110
|
+
/** Additional CSS classes */
|
|
111
|
+
readonly class = input<string>('');
|
|
112
|
+
|
|
113
|
+
/** Whether to show the animated indicator */
|
|
114
|
+
readonly showIndicator = input<boolean>(false);
|
|
115
|
+
|
|
116
|
+
/** Additional indicator CSS classes */
|
|
117
|
+
readonly indicatorClass = input<string>('');
|
|
118
|
+
|
|
119
|
+
/** Indicator position and size */
|
|
120
|
+
protected readonly indicatorStyle = signal({ width: 0, left: 0 });
|
|
121
|
+
|
|
122
|
+
protected readonly computedClass = computed(() =>
|
|
123
|
+
cn(
|
|
124
|
+
'text-muted-foreground inline-flex h-9 w-fit items-center justify-center gap-1 rounded-lg bg-transparent p-1',
|
|
125
|
+
this.class()
|
|
126
|
+
)
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
protected readonly computedIndicatorClass = computed(() =>
|
|
130
|
+
cn(
|
|
131
|
+
'absolute inset-y-1 bg-background rounded-md shadow-sm transition-all duration-200',
|
|
132
|
+
this.indicatorClass()
|
|
133
|
+
)
|
|
134
|
+
);
|
|
135
|
+
|
|
136
|
+
constructor() {
|
|
137
|
+
// Update indicator when value changes (browser-only via afterNextRender)
|
|
138
|
+
effect(() => {
|
|
139
|
+
const _ = this.tabs.value(); // Subscribe to value changes
|
|
140
|
+
// Schedule browser-only DOM update
|
|
141
|
+
afterNextRender(() => {
|
|
142
|
+
this.updateIndicator();
|
|
143
|
+
}, { injector: this.injector });
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
private updateIndicator(): void {
|
|
148
|
+
const activeValue = this.tabs.value();
|
|
149
|
+
if (!activeValue) return;
|
|
150
|
+
|
|
151
|
+
const tabId = this.tabs.getTabId(activeValue);
|
|
152
|
+
const tabElement = document.getElementById(tabId);
|
|
153
|
+
const listElement = this.elementRef.nativeElement;
|
|
154
|
+
|
|
155
|
+
if (tabElement && listElement) {
|
|
156
|
+
const tabRect = tabElement.getBoundingClientRect();
|
|
157
|
+
const listRect = listElement.getBoundingClientRect();
|
|
158
|
+
|
|
159
|
+
this.indicatorStyle.set({
|
|
160
|
+
width: tabRect.width,
|
|
161
|
+
left: tabRect.left - listRect.left,
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
onKeydown(event: KeyboardEvent): void {
|
|
167
|
+
const tabValues = this.tabs.tabValues();
|
|
168
|
+
if (tabValues.length === 0) return;
|
|
169
|
+
|
|
170
|
+
const currentValue = this.tabs.value();
|
|
171
|
+
const currentIndex = tabValues.indexOf(currentValue);
|
|
172
|
+
const orientation = this.tabs.orientation();
|
|
173
|
+
const activationMode = this.tabs.activationMode();
|
|
174
|
+
|
|
175
|
+
let newIndex = currentIndex;
|
|
176
|
+
let handled = false;
|
|
177
|
+
|
|
178
|
+
switch (event.key) {
|
|
179
|
+
case 'ArrowLeft':
|
|
180
|
+
if (orientation === 'horizontal') {
|
|
181
|
+
newIndex = currentIndex > 0 ? currentIndex - 1 : tabValues.length - 1;
|
|
182
|
+
handled = true;
|
|
183
|
+
}
|
|
184
|
+
break;
|
|
185
|
+
case 'ArrowRight':
|
|
186
|
+
if (orientation === 'horizontal') {
|
|
187
|
+
newIndex = currentIndex < tabValues.length - 1 ? currentIndex + 1 : 0;
|
|
188
|
+
handled = true;
|
|
189
|
+
}
|
|
190
|
+
break;
|
|
191
|
+
case 'ArrowUp':
|
|
192
|
+
if (orientation === 'vertical') {
|
|
193
|
+
newIndex = currentIndex > 0 ? currentIndex - 1 : tabValues.length - 1;
|
|
194
|
+
handled = true;
|
|
195
|
+
}
|
|
196
|
+
break;
|
|
197
|
+
case 'ArrowDown':
|
|
198
|
+
if (orientation === 'vertical') {
|
|
199
|
+
newIndex = currentIndex < tabValues.length - 1 ? currentIndex + 1 : 0;
|
|
200
|
+
handled = true;
|
|
201
|
+
}
|
|
202
|
+
break;
|
|
203
|
+
case 'Home':
|
|
204
|
+
newIndex = 0;
|
|
205
|
+
handled = true;
|
|
206
|
+
break;
|
|
207
|
+
case 'End':
|
|
208
|
+
newIndex = tabValues.length - 1;
|
|
209
|
+
handled = true;
|
|
210
|
+
break;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
if (handled) {
|
|
214
|
+
event.preventDefault();
|
|
215
|
+
const newValue = tabValues[newIndex];
|
|
216
|
+
|
|
217
|
+
// In automatic mode, activate on focus; in manual mode, just focus
|
|
218
|
+
if (activationMode === 'automatic') {
|
|
219
|
+
this.tabs.onValueChange(newValue);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// Focus the new tab
|
|
223
|
+
const tabId = this.tabs.getTabId(newValue);
|
|
224
|
+
const tabElement = document.getElementById(tabId);
|
|
225
|
+
tabElement?.focus();
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { cn } from '@/lib/utils';
|
|
2
|
+
import {
|
|
3
|
+
ChangeDetectionStrategy,
|
|
4
|
+
Component,
|
|
5
|
+
computed,
|
|
6
|
+
inject,
|
|
7
|
+
input,
|
|
8
|
+
OnDestroy,
|
|
9
|
+
OnInit
|
|
10
|
+
} from '@angular/core';
|
|
11
|
+
import { TABS_CONTEXT } from './tabs-context';
|
|
12
|
+
|
|
13
|
+
// ============================================================================
|
|
14
|
+
// Types
|
|
15
|
+
// ============================================================================
|
|
16
|
+
|
|
17
|
+
export type TabsTriggerState = 'active' | 'inactive';
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Props for the TabsTrigger component
|
|
21
|
+
*/
|
|
22
|
+
export interface TabsTriggerProps {
|
|
23
|
+
/** A unique value that associates the trigger with a content */
|
|
24
|
+
value: string;
|
|
25
|
+
/** When true, prevents the user from interacting with the tab.
|
|
26
|
+
* @default false */
|
|
27
|
+
disabled?: boolean;
|
|
28
|
+
/** Additional CSS classes */
|
|
29
|
+
class?: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// ============================================================================
|
|
33
|
+
// Component
|
|
34
|
+
// ============================================================================
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* @component TabsTrigger
|
|
38
|
+
*
|
|
39
|
+
* The button that activates its associated content.
|
|
40
|
+
*
|
|
41
|
+
* @description
|
|
42
|
+
* TabsTrigger is the interactive element users click or focus to activate
|
|
43
|
+
* a tab panel. It implements the tab role with proper ARIA attributes.
|
|
44
|
+
*
|
|
45
|
+
* ## Features
|
|
46
|
+
* - Click activation
|
|
47
|
+
* - Keyboard activation (Enter/Space)
|
|
48
|
+
* - Disabled state support
|
|
49
|
+
* - Roving tabindex for keyboard navigation
|
|
50
|
+
* - Auto-registration with parent TabsList
|
|
51
|
+
*
|
|
52
|
+
* ## Accessibility
|
|
53
|
+
* - `role="tab"` on the element
|
|
54
|
+
* - `aria-selected` reflects active state
|
|
55
|
+
* - `aria-controls` points to associated panel
|
|
56
|
+
* - `tabindex` follows roving tabindex pattern (0 for active, -1 for inactive)
|
|
57
|
+
* - `aria-disabled` when disabled
|
|
58
|
+
*
|
|
59
|
+
* @example Basic usage
|
|
60
|
+
* ```html
|
|
61
|
+
* <TabsTrigger value="account">Account</TabsTrigger>
|
|
62
|
+
* ```
|
|
63
|
+
*
|
|
64
|
+
* @example Disabled trigger
|
|
65
|
+
* ```html
|
|
66
|
+
* <TabsTrigger value="settings" [disabled]="true">Settings</TabsTrigger>
|
|
67
|
+
* ```
|
|
68
|
+
*
|
|
69
|
+
* @example With icon
|
|
70
|
+
* ```html
|
|
71
|
+
* <TabsTrigger value="account">
|
|
72
|
+
* <UserIcon class="size-4" />
|
|
73
|
+
* Account
|
|
74
|
+
* </TabsTrigger>
|
|
75
|
+
* ```
|
|
76
|
+
*
|
|
77
|
+
* @data-attributes
|
|
78
|
+
* - `data-state` - 'active' | 'inactive'
|
|
79
|
+
* - `data-disabled` - Present when disabled
|
|
80
|
+
*/
|
|
81
|
+
@Component({
|
|
82
|
+
selector: 'TabsTrigger',
|
|
83
|
+
template: `<ng-content />`,
|
|
84
|
+
host: {
|
|
85
|
+
'[class]': 'computedClass()',
|
|
86
|
+
'[attr.id]': 'tabId()',
|
|
87
|
+
'[attr.data-state]': 'state()',
|
|
88
|
+
'[attr.data-disabled]': 'disabled() ? "" : null',
|
|
89
|
+
'[attr.aria-selected]': 'isActive()',
|
|
90
|
+
'[attr.aria-controls]': 'panelId()',
|
|
91
|
+
'[attr.aria-disabled]': 'disabled() || null',
|
|
92
|
+
'[attr.tabindex]': 'isActive() ? 0 : -1',
|
|
93
|
+
'[attr.disabled]': 'disabled() ? "" : null',
|
|
94
|
+
'(click)': 'onClick()',
|
|
95
|
+
'(keydown.enter)': 'onClick()',
|
|
96
|
+
'(keydown.space)': 'onSpace($event)',
|
|
97
|
+
'role': 'tab',
|
|
98
|
+
},
|
|
99
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
100
|
+
})
|
|
101
|
+
export class TabsTrigger implements OnInit, OnDestroy {
|
|
102
|
+
protected readonly tabs = inject(TABS_CONTEXT);
|
|
103
|
+
|
|
104
|
+
/** A unique value that associates the trigger with a content */
|
|
105
|
+
readonly value = input.required<string>();
|
|
106
|
+
|
|
107
|
+
/** When true, prevents the user from interacting with the tab */
|
|
108
|
+
readonly disabled = input<boolean>(false);
|
|
109
|
+
|
|
110
|
+
/** Additional CSS classes */
|
|
111
|
+
readonly class = input<string>('');
|
|
112
|
+
|
|
113
|
+
/** Check if this tab is currently active */
|
|
114
|
+
protected readonly isActive = computed(() => this.tabs.value() === this.value());
|
|
115
|
+
|
|
116
|
+
/** Current state: active or inactive */
|
|
117
|
+
protected readonly state = computed<TabsTriggerState>(() =>
|
|
118
|
+
this.isActive() ? 'active' : 'inactive'
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
/** Generate tab ID */
|
|
122
|
+
protected readonly tabId = computed(() => this.tabs.getTabId(this.value()));
|
|
123
|
+
|
|
124
|
+
/** Generate panel ID for aria-controls */
|
|
125
|
+
protected readonly panelId = computed(() => this.tabs.getPanelId(this.value()));
|
|
126
|
+
|
|
127
|
+
protected readonly computedClass = computed(() =>
|
|
128
|
+
cn(
|
|
129
|
+
'inline-flex items-center justify-center gap-1.5 whitespace-nowrap rounded-md px-3 py-1.5 text-sm font-medium ring-offset-background transition-all',
|
|
130
|
+
'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',
|
|
131
|
+
'disabled:pointer-events-none disabled:opacity-50',
|
|
132
|
+
'data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:border data-[state=active]:border-border data-[state=active]:shadow-sm',
|
|
133
|
+
'data-[state=inactive]:hover:text-foreground',
|
|
134
|
+
'cursor-pointer',
|
|
135
|
+
this.disabled() && 'pointer-events-none opacity-50',
|
|
136
|
+
this.class()
|
|
137
|
+
)
|
|
138
|
+
);
|
|
139
|
+
|
|
140
|
+
ngOnInit(): void {
|
|
141
|
+
// Register this tab's value for keyboard navigation
|
|
142
|
+
this.tabs.tabValues.update(values => {
|
|
143
|
+
if (!values.includes(this.value())) {
|
|
144
|
+
return [...values, this.value()];
|
|
145
|
+
}
|
|
146
|
+
return values;
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
ngOnDestroy(): void {
|
|
151
|
+
// Unregister this tab's value
|
|
152
|
+
this.tabs.tabValues.update(values =>
|
|
153
|
+
values.filter(v => v !== this.value())
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
protected onClick(): void {
|
|
158
|
+
if (!this.disabled()) {
|
|
159
|
+
this.tabs.onValueChange(this.value());
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
protected onSpace(event: Event): void {
|
|
164
|
+
event.preventDefault();
|
|
165
|
+
this.onClick();
|
|
166
|
+
}
|
|
167
|
+
}
|