@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,236 @@
|
|
|
1
|
+
import { cn, Presence } from '@/lib/utils';
|
|
2
|
+
import {
|
|
3
|
+
afterNextRender,
|
|
4
|
+
ChangeDetectionStrategy,
|
|
5
|
+
Component,
|
|
6
|
+
computed,
|
|
7
|
+
effect,
|
|
8
|
+
ElementRef,
|
|
9
|
+
inject,
|
|
10
|
+
input,
|
|
11
|
+
OnDestroy,
|
|
12
|
+
} from '@angular/core';
|
|
13
|
+
import { MENUBAR_CONTEXT, MENUBAR_MENU_CONTEXT } from './menubar-context';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* MenubarContent component - content panel for a menu.
|
|
17
|
+
* Matches shadcn/ui React MenubarContent exactly.
|
|
18
|
+
* Implements full keyboard navigation with arrow keys, Home/End, and typeahead.
|
|
19
|
+
*/
|
|
20
|
+
@Component({
|
|
21
|
+
selector: 'MenubarContent',
|
|
22
|
+
imports: [Presence],
|
|
23
|
+
template: `
|
|
24
|
+
<Presence [present]="menuContext.open()">
|
|
25
|
+
<div
|
|
26
|
+
[class]="computedClass()"
|
|
27
|
+
[attr.data-state]="menuContext.open() ? 'open' : 'closed'"
|
|
28
|
+
role="menu"
|
|
29
|
+
aria-orientation="vertical"
|
|
30
|
+
tabindex="-1"
|
|
31
|
+
(keydown)="onKeydown($event)"
|
|
32
|
+
>
|
|
33
|
+
<ng-content />
|
|
34
|
+
</div>
|
|
35
|
+
</Presence>
|
|
36
|
+
`,
|
|
37
|
+
host: {
|
|
38
|
+
class: 'contents',
|
|
39
|
+
'(document:click)': 'onDocumentClick($event)',
|
|
40
|
+
'(document:keydown.escape)': 'onEscapeKey()',
|
|
41
|
+
},
|
|
42
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
43
|
+
})
|
|
44
|
+
export class MenubarContent implements OnDestroy {
|
|
45
|
+
protected readonly context = inject(MENUBAR_CONTEXT);
|
|
46
|
+
protected readonly menuContext = inject(MENUBAR_MENU_CONTEXT);
|
|
47
|
+
private readonly elementRef = inject(ElementRef);
|
|
48
|
+
|
|
49
|
+
/** Alignment */
|
|
50
|
+
readonly align = input<'start' | 'center' | 'end'>('start');
|
|
51
|
+
|
|
52
|
+
/** Side offset */
|
|
53
|
+
readonly sideOffset = input<number>(8);
|
|
54
|
+
|
|
55
|
+
/** Align offset */
|
|
56
|
+
readonly alignOffset = input<number>(-4);
|
|
57
|
+
|
|
58
|
+
/** Additional CSS classes */
|
|
59
|
+
readonly class = input<string>('');
|
|
60
|
+
|
|
61
|
+
private menuItems: HTMLElement[] = [];
|
|
62
|
+
private typeaheadBuffer = '';
|
|
63
|
+
private typeaheadTimeout: ReturnType<typeof setTimeout> | null = null;
|
|
64
|
+
|
|
65
|
+
protected readonly computedClass = computed(() => {
|
|
66
|
+
const alignClasses = {
|
|
67
|
+
start: 'left-0',
|
|
68
|
+
center: 'left-1/2 -translate-x-1/2',
|
|
69
|
+
end: 'right-0',
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
return cn(
|
|
73
|
+
'absolute top-full z-50 min-w-[12rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md',
|
|
74
|
+
'data-[state=open]:animate-in data-[state=closed]:animate-out',
|
|
75
|
+
'data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',
|
|
76
|
+
'data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95',
|
|
77
|
+
alignClasses[this.align()],
|
|
78
|
+
this.class()
|
|
79
|
+
);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
constructor() {
|
|
83
|
+
// Focus first item when menu opens
|
|
84
|
+
effect(() => {
|
|
85
|
+
if (this.menuContext.open()) {
|
|
86
|
+
setTimeout(() => {
|
|
87
|
+
this.updateMenuItems();
|
|
88
|
+
const focusedIdx = this.menuContext.focusedItemIndex();
|
|
89
|
+
if (focusedIdx >= 0 && this.menuItems[focusedIdx]) {
|
|
90
|
+
this.menuItems[focusedIdx].focus();
|
|
91
|
+
} else if (this.menuItems.length > 0) {
|
|
92
|
+
this.menuItems[0].focus();
|
|
93
|
+
this.menuContext.focusedItemIndex.set(0);
|
|
94
|
+
}
|
|
95
|
+
}, 0);
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
// Initial menu items update (browser-only)
|
|
100
|
+
afterNextRender(() => {
|
|
101
|
+
this.updateMenuItems();
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
ngOnDestroy(): void {
|
|
106
|
+
if (this.typeaheadTimeout) {
|
|
107
|
+
clearTimeout(this.typeaheadTimeout);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
private updateMenuItems(): void {
|
|
112
|
+
const content = this.elementRef.nativeElement.querySelector('[role="menu"]');
|
|
113
|
+
if (content) {
|
|
114
|
+
this.menuItems = Array.from(
|
|
115
|
+
content.querySelectorAll('[role="menuitem"]:not([aria-disabled="true"]):not([data-disabled])')
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
protected onKeydown(event: KeyboardEvent): void {
|
|
121
|
+
this.updateMenuItems();
|
|
122
|
+
|
|
123
|
+
switch (event.key) {
|
|
124
|
+
case 'ArrowDown':
|
|
125
|
+
event.preventDefault();
|
|
126
|
+
this.focusNext();
|
|
127
|
+
break;
|
|
128
|
+
case 'ArrowUp':
|
|
129
|
+
event.preventDefault();
|
|
130
|
+
this.focusPrevious();
|
|
131
|
+
break;
|
|
132
|
+
case 'ArrowRight':
|
|
133
|
+
// Navigate to next menu in menubar
|
|
134
|
+
event.preventDefault();
|
|
135
|
+
this.close();
|
|
136
|
+
this.context.focusNextMenu();
|
|
137
|
+
break;
|
|
138
|
+
case 'ArrowLeft':
|
|
139
|
+
// Navigate to previous menu in menubar
|
|
140
|
+
event.preventDefault();
|
|
141
|
+
this.close();
|
|
142
|
+
this.context.focusPreviousMenu();
|
|
143
|
+
break;
|
|
144
|
+
case 'Home':
|
|
145
|
+
event.preventDefault();
|
|
146
|
+
this.focusFirst();
|
|
147
|
+
break;
|
|
148
|
+
case 'End':
|
|
149
|
+
event.preventDefault();
|
|
150
|
+
this.focusLast();
|
|
151
|
+
break;
|
|
152
|
+
case 'Tab':
|
|
153
|
+
// Close menu and let tab continue
|
|
154
|
+
this.close();
|
|
155
|
+
break;
|
|
156
|
+
default:
|
|
157
|
+
// Typeahead search
|
|
158
|
+
if (event.key.length === 1 && !event.ctrlKey && !event.metaKey) {
|
|
159
|
+
this.handleTypeahead(event.key);
|
|
160
|
+
}
|
|
161
|
+
break;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
private focusNext(): void {
|
|
166
|
+
const currentIndex = this.menuContext.focusedItemIndex();
|
|
167
|
+
const nextIndex = currentIndex < this.menuItems.length - 1 ? currentIndex + 1 : 0;
|
|
168
|
+
this.focusItem(nextIndex);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
private focusPrevious(): void {
|
|
172
|
+
const currentIndex = this.menuContext.focusedItemIndex();
|
|
173
|
+
const prevIndex = currentIndex > 0 ? currentIndex - 1 : this.menuItems.length - 1;
|
|
174
|
+
this.focusItem(prevIndex);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
private focusFirst(): void {
|
|
178
|
+
this.focusItem(0);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
private focusLast(): void {
|
|
182
|
+
this.focusItem(this.menuItems.length - 1);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
private focusItem(index: number): void {
|
|
186
|
+
if (index >= 0 && index < this.menuItems.length) {
|
|
187
|
+
// Update roving tabindex
|
|
188
|
+
this.menuItems.forEach((item, i) => {
|
|
189
|
+
item.setAttribute('tabindex', i === index ? '0' : '-1');
|
|
190
|
+
});
|
|
191
|
+
this.menuItems[index].focus();
|
|
192
|
+
this.menuContext.focusedItemIndex.set(index);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
private handleTypeahead(key: string): void {
|
|
197
|
+
this.typeaheadBuffer += key.toLowerCase();
|
|
198
|
+
|
|
199
|
+
if (this.typeaheadTimeout) {
|
|
200
|
+
clearTimeout(this.typeaheadTimeout);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
this.typeaheadTimeout = setTimeout(() => {
|
|
204
|
+
this.typeaheadBuffer = '';
|
|
205
|
+
}, 500);
|
|
206
|
+
|
|
207
|
+
// Find first matching item
|
|
208
|
+
const matchIndex = this.menuItems.findIndex((item) =>
|
|
209
|
+
item.textContent?.toLowerCase().trim().startsWith(this.typeaheadBuffer)
|
|
210
|
+
);
|
|
211
|
+
|
|
212
|
+
if (matchIndex >= 0) {
|
|
213
|
+
this.focusItem(matchIndex);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
private close(): void {
|
|
218
|
+
this.menuContext.open.set(false);
|
|
219
|
+
this.context.activeMenu.set(null);
|
|
220
|
+
this.menuContext.focusedItemIndex.set(-1);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
protected onDocumentClick(event: MouseEvent): void {
|
|
224
|
+
const target = event.target as HTMLElement;
|
|
225
|
+
const hostElement = this.elementRef.nativeElement;
|
|
226
|
+
const parent = hostElement.closest('MenubarMenu');
|
|
227
|
+
|
|
228
|
+
if (parent && !parent.contains(target)) {
|
|
229
|
+
this.close();
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
protected onEscapeKey(): void {
|
|
234
|
+
this.close();
|
|
235
|
+
}
|
|
236
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { InjectionToken, type WritableSignal } from '@angular/core';
|
|
2
|
+
|
|
3
|
+
// ============================================================================
|
|
4
|
+
// Types
|
|
5
|
+
// ============================================================================
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Direction for menubar layout
|
|
9
|
+
*/
|
|
10
|
+
export type MenubarDirection = 'ltr' | 'rtl';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Keyboard navigation direction
|
|
14
|
+
*/
|
|
15
|
+
export type MenubarNavigationDirection = 'horizontal' | 'vertical';
|
|
16
|
+
|
|
17
|
+
// ============================================================================
|
|
18
|
+
// Context Interfaces
|
|
19
|
+
// ============================================================================
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Context value for the Menubar component
|
|
23
|
+
*
|
|
24
|
+
* @description
|
|
25
|
+
* Provides shared state and navigation methods for all menus within a menubar.
|
|
26
|
+
* Handles menu registration, focus management, and keyboard navigation.
|
|
27
|
+
*/
|
|
28
|
+
export interface MenubarContextValue {
|
|
29
|
+
/** Currently active/open menu ID */
|
|
30
|
+
activeMenu: WritableSignal<string | null>;
|
|
31
|
+
/** List of registered menu IDs */
|
|
32
|
+
menuIds: WritableSignal<string[]>;
|
|
33
|
+
/** Index of the currently focused menu */
|
|
34
|
+
focusedMenuIndex: WritableSignal<number>;
|
|
35
|
+
/** Register a menu with the menubar */
|
|
36
|
+
registerMenu: (menuId: string) => void;
|
|
37
|
+
/** Unregister a menu from the menubar */
|
|
38
|
+
unregisterMenu: (menuId: string) => void;
|
|
39
|
+
/** Focus the next menu (Right arrow) */
|
|
40
|
+
focusNextMenu: () => void;
|
|
41
|
+
/** Focus the previous menu (Left arrow) */
|
|
42
|
+
focusPreviousMenu: () => void;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export const MENUBAR_CONTEXT = new InjectionToken<MenubarContextValue>('MENUBAR_CONTEXT');
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Context value for individual MenubarMenu components
|
|
49
|
+
*
|
|
50
|
+
* @description
|
|
51
|
+
* Provides state for a single menu within the menubar, including
|
|
52
|
+
* its open state and focused item tracking.
|
|
53
|
+
*/
|
|
54
|
+
export interface MenubarMenuContextValue {
|
|
55
|
+
/** Unique identifier for this menu */
|
|
56
|
+
menuId: string;
|
|
57
|
+
/** Whether this menu is open */
|
|
58
|
+
open: WritableSignal<boolean>;
|
|
59
|
+
/** Index of the currently focused item within the menu */
|
|
60
|
+
focusedItemIndex: WritableSignal<number>;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export const MENUBAR_MENU_CONTEXT = new InjectionToken<MenubarMenuContextValue>('MENUBAR_MENU_CONTEXT');
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { cn } from '@/lib/utils';
|
|
2
|
+
import { ChangeDetectionStrategy, Component, computed, inject, input, output } from '@angular/core';
|
|
3
|
+
import { MENUBAR_CONTEXT, MENUBAR_MENU_CONTEXT } from './menubar-context';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* MenubarItem component - individual menu item.
|
|
7
|
+
* Matches shadcn/ui React MenubarItem exactly.
|
|
8
|
+
* Supports roving tabindex for proper keyboard navigation.
|
|
9
|
+
*/
|
|
10
|
+
@Component({
|
|
11
|
+
selector: 'MenubarItem',
|
|
12
|
+
template: `<ng-content />`,
|
|
13
|
+
host: {
|
|
14
|
+
'[class]': 'computedClass()',
|
|
15
|
+
'[attr.role]': '"menuitem"',
|
|
16
|
+
'[attr.tabindex]': 'disabled() ? -1 : -1',
|
|
17
|
+
'[attr.data-disabled]': 'disabled() ? "" : null',
|
|
18
|
+
'[attr.aria-disabled]': 'disabled()',
|
|
19
|
+
'(click)': 'handleClick($event)',
|
|
20
|
+
'(keydown.enter)': 'handleClick($event)',
|
|
21
|
+
'(keydown.space)': 'handleClick($event)',
|
|
22
|
+
},
|
|
23
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
24
|
+
})
|
|
25
|
+
export class MenubarItem {
|
|
26
|
+
private readonly context = inject(MENUBAR_CONTEXT);
|
|
27
|
+
private readonly menuContext = inject(MENUBAR_MENU_CONTEXT);
|
|
28
|
+
|
|
29
|
+
/** Whether the item is disabled */
|
|
30
|
+
readonly disabled = input<boolean>(false);
|
|
31
|
+
|
|
32
|
+
/** Whether the item is inset (extra padding) */
|
|
33
|
+
readonly inset = input<boolean>(false);
|
|
34
|
+
|
|
35
|
+
/** Additional CSS classes */
|
|
36
|
+
readonly class = input<string>('');
|
|
37
|
+
|
|
38
|
+
/** Select event */
|
|
39
|
+
readonly onSelect = output<void>();
|
|
40
|
+
|
|
41
|
+
protected readonly computedClass = computed(() =>
|
|
42
|
+
cn(
|
|
43
|
+
"relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
|
44
|
+
this.inset() && 'pl-8',
|
|
45
|
+
!this.disabled() && 'cursor-pointer hover:bg-accent hover:text-accent-foreground',
|
|
46
|
+
this.class()
|
|
47
|
+
)
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
protected handleClick(event: Event): void {
|
|
51
|
+
if (this.disabled()) {
|
|
52
|
+
event.preventDefault();
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
this.onSelect.emit();
|
|
56
|
+
this.menuContext.open.set(false);
|
|
57
|
+
this.context.activeMenu.set(null);
|
|
58
|
+
this.menuContext.focusedItemIndex.set(-1);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { cn } from '@/lib/utils';
|
|
2
|
+
import { ChangeDetectionStrategy, Component, computed, input } from '@angular/core';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* MenubarLabel component - label in the menu.
|
|
6
|
+
* Matches shadcn/ui React MenubarLabel exactly.
|
|
7
|
+
*/
|
|
8
|
+
@Component({
|
|
9
|
+
selector: 'MenubarLabel',
|
|
10
|
+
template: `<ng-content />`,
|
|
11
|
+
host: {
|
|
12
|
+
'[class]': 'computedClass()',
|
|
13
|
+
},
|
|
14
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
15
|
+
})
|
|
16
|
+
export class MenubarLabel {
|
|
17
|
+
/** Whether the label is inset */
|
|
18
|
+
readonly inset = input<boolean>(false);
|
|
19
|
+
|
|
20
|
+
/** Additional CSS classes */
|
|
21
|
+
readonly class = input<string>('');
|
|
22
|
+
|
|
23
|
+
protected readonly computedClass = computed(() =>
|
|
24
|
+
cn(
|
|
25
|
+
'px-2 py-1.5 text-sm font-semibold',
|
|
26
|
+
this.inset() && 'pl-8',
|
|
27
|
+
this.class()
|
|
28
|
+
)
|
|
29
|
+
);
|
|
30
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { ChangeDetectionStrategy, Component, inject, OnDestroy, OnInit, signal } from '@angular/core';
|
|
2
|
+
import { MENUBAR_CONTEXT, MENUBAR_MENU_CONTEXT, type MenubarMenuContextValue } from './menubar-context';
|
|
3
|
+
|
|
4
|
+
let menuIdCounter = 0;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* MenubarMenu component - individual menu in the menubar.
|
|
8
|
+
* Matches shadcn/ui React MenubarMenu exactly.
|
|
9
|
+
* Registers itself with parent menubar for keyboard navigation.
|
|
10
|
+
*/
|
|
11
|
+
@Component({
|
|
12
|
+
selector: 'MenubarMenu',
|
|
13
|
+
template: `<ng-content />`,
|
|
14
|
+
providers: [
|
|
15
|
+
{
|
|
16
|
+
provide: MENUBAR_MENU_CONTEXT,
|
|
17
|
+
useFactory: (): MenubarMenuContextValue => ({
|
|
18
|
+
menuId: `menubar-menu-${menuIdCounter++}`,
|
|
19
|
+
open: signal(false),
|
|
20
|
+
focusedItemIndex: signal(-1),
|
|
21
|
+
}),
|
|
22
|
+
},
|
|
23
|
+
],
|
|
24
|
+
host: {
|
|
25
|
+
class: 'relative',
|
|
26
|
+
},
|
|
27
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
28
|
+
})
|
|
29
|
+
export class MenubarMenu implements OnInit, OnDestroy {
|
|
30
|
+
protected readonly context = inject(MENUBAR_CONTEXT);
|
|
31
|
+
protected readonly menuContext = inject(MENUBAR_MENU_CONTEXT);
|
|
32
|
+
|
|
33
|
+
ngOnInit(): void {
|
|
34
|
+
this.context.registerMenu(this.menuContext.menuId);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
ngOnDestroy(): void {
|
|
38
|
+
this.context.unregisterMenu(this.menuContext.menuId);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { ChangeDetectionStrategy, Component, InjectionToken, signal, type WritableSignal } from '@angular/core';
|
|
2
|
+
|
|
3
|
+
export interface MenubarRadioGroupContext {
|
|
4
|
+
value: WritableSignal<string>;
|
|
5
|
+
setValue: (value: string) => void;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export const MENUBAR_RADIO_GROUP_CONTEXT = new InjectionToken<MenubarRadioGroupContext>(
|
|
9
|
+
'MENUBAR_RADIO_GROUP_CONTEXT'
|
|
10
|
+
);
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* MenubarRadioGroup component - group of radio items.
|
|
14
|
+
* Matches shadcn/ui React MenubarRadioGroup exactly.
|
|
15
|
+
*/
|
|
16
|
+
@Component({
|
|
17
|
+
selector: 'MenubarRadioGroup',
|
|
18
|
+
template: `<ng-content />`,
|
|
19
|
+
providers: [
|
|
20
|
+
{
|
|
21
|
+
provide: MENUBAR_RADIO_GROUP_CONTEXT,
|
|
22
|
+
useFactory: () => {
|
|
23
|
+
const internalValue = signal('');
|
|
24
|
+
return {
|
|
25
|
+
value: internalValue,
|
|
26
|
+
setValue: (newValue: string) => internalValue.set(newValue),
|
|
27
|
+
};
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
],
|
|
31
|
+
host: {
|
|
32
|
+
'[attr.role]': '"group"',
|
|
33
|
+
},
|
|
34
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
35
|
+
})
|
|
36
|
+
export class MenubarRadioGroup {}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { cn } from '@/lib/utils';
|
|
2
|
+
import { ChangeDetectionStrategy, Component, computed, inject, input, output } from '@angular/core';
|
|
3
|
+
import { Circle, LucideAngularModule } from 'lucide-angular';
|
|
4
|
+
import { MENUBAR_RADIO_GROUP_CONTEXT } from './menubar-radio-group.component';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* MenubarRadioItem component - radio menu item.
|
|
8
|
+
* Matches shadcn/ui React MenubarRadioItem exactly.
|
|
9
|
+
*/
|
|
10
|
+
@Component({
|
|
11
|
+
selector: 'MenubarRadioItem',
|
|
12
|
+
imports: [LucideAngularModule],
|
|
13
|
+
template: `
|
|
14
|
+
<span class="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
|
|
15
|
+
@if (isSelected()) {
|
|
16
|
+
<lucide-icon [img]="CircleIcon" class="h-2 w-2 fill-current" />
|
|
17
|
+
}
|
|
18
|
+
</span>
|
|
19
|
+
<ng-content />
|
|
20
|
+
`,
|
|
21
|
+
host: {
|
|
22
|
+
'[class]': 'computedClass()',
|
|
23
|
+
'[attr.role]': '"menuitemradio"',
|
|
24
|
+
'[attr.aria-checked]': 'isSelected()',
|
|
25
|
+
'[attr.data-state]': 'isSelected() ? "checked" : "unchecked"',
|
|
26
|
+
'(click)': 'handleClick($event)',
|
|
27
|
+
'(keydown.enter)': 'handleClick($event)',
|
|
28
|
+
'(keydown.space)': 'handleClick($event)',
|
|
29
|
+
},
|
|
30
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
31
|
+
})
|
|
32
|
+
export class MenubarRadioItem {
|
|
33
|
+
private readonly radioGroupContext = inject(MENUBAR_RADIO_GROUP_CONTEXT);
|
|
34
|
+
protected readonly CircleIcon = Circle;
|
|
35
|
+
|
|
36
|
+
/** The value of this radio item */
|
|
37
|
+
readonly value = input.required<string>();
|
|
38
|
+
|
|
39
|
+
/** Whether the item is disabled */
|
|
40
|
+
readonly disabled = input<boolean>(false);
|
|
41
|
+
|
|
42
|
+
/** Additional CSS classes */
|
|
43
|
+
readonly class = input<string>('');
|
|
44
|
+
|
|
45
|
+
/** Select event */
|
|
46
|
+
readonly onSelect = output<void>();
|
|
47
|
+
|
|
48
|
+
protected readonly isSelected = computed(() => this.radioGroupContext.value() === this.value());
|
|
49
|
+
|
|
50
|
+
protected readonly computedClass = computed(() =>
|
|
51
|
+
cn(
|
|
52
|
+
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
|
53
|
+
!this.disabled() && 'cursor-pointer hover:bg-accent hover:text-accent-foreground',
|
|
54
|
+
this.class()
|
|
55
|
+
)
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
protected handleClick(event: Event): void {
|
|
59
|
+
if (this.disabled()) {
|
|
60
|
+
event.preventDefault();
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
this.radioGroupContext.setValue(this.value());
|
|
64
|
+
this.onSelect.emit();
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { cn } from '@/lib/utils';
|
|
2
|
+
import { ChangeDetectionStrategy, Component, computed, input } from '@angular/core';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* MenubarSeparator component - separator between menu items.
|
|
6
|
+
* Matches shadcn/ui React MenubarSeparator exactly.
|
|
7
|
+
*/
|
|
8
|
+
@Component({
|
|
9
|
+
selector: 'MenubarSeparator',
|
|
10
|
+
template: ``,
|
|
11
|
+
host: {
|
|
12
|
+
'[class]': 'computedClass()',
|
|
13
|
+
'[attr.role]': '"separator"',
|
|
14
|
+
},
|
|
15
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
16
|
+
})
|
|
17
|
+
export class MenubarSeparator {
|
|
18
|
+
/** Additional CSS classes */
|
|
19
|
+
readonly class = input<string>('');
|
|
20
|
+
|
|
21
|
+
protected readonly computedClass = computed(() =>
|
|
22
|
+
cn('-mx-1 my-1 h-px bg-muted', this.class())
|
|
23
|
+
);
|
|
24
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { cn } from '@/lib/utils';
|
|
2
|
+
import { ChangeDetectionStrategy, Component, computed, input } from '@angular/core';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* MenubarShortcut component - keyboard shortcut hint.
|
|
6
|
+
* Matches shadcn/ui React MenubarShortcut exactly.
|
|
7
|
+
*/
|
|
8
|
+
@Component({
|
|
9
|
+
selector: 'MenubarShortcut',
|
|
10
|
+
template: `<ng-content />`,
|
|
11
|
+
host: {
|
|
12
|
+
'[class]': 'computedClass()',
|
|
13
|
+
},
|
|
14
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
15
|
+
})
|
|
16
|
+
export class MenubarShortcut {
|
|
17
|
+
/** Additional CSS classes */
|
|
18
|
+
readonly class = input<string>('');
|
|
19
|
+
|
|
20
|
+
protected readonly computedClass = computed(() =>
|
|
21
|
+
cn('ml-auto text-xs tracking-widest text-muted-foreground', this.class())
|
|
22
|
+
);
|
|
23
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { cn, Presence } from '@/lib/utils';
|
|
2
|
+
import { ChangeDetectionStrategy, Component, computed, inject, input } from '@angular/core';
|
|
3
|
+
import { MENUBAR_SUB_CONTEXT } from './menubar-sub.component';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* MenubarSubContent component - content panel for submenu.
|
|
7
|
+
* Matches shadcn/ui React MenubarSubContent exactly.
|
|
8
|
+
*/
|
|
9
|
+
@Component({
|
|
10
|
+
selector: 'MenubarSubContent',
|
|
11
|
+
imports: [Presence],
|
|
12
|
+
template: `
|
|
13
|
+
<Presence [present]="subContext.open()">
|
|
14
|
+
<div
|
|
15
|
+
[class]="computedClass()"
|
|
16
|
+
[attr.data-state]="subContext.open() ? 'open' : 'closed'"
|
|
17
|
+
role="menu"
|
|
18
|
+
>
|
|
19
|
+
<ng-content />
|
|
20
|
+
</div>
|
|
21
|
+
</Presence>
|
|
22
|
+
`,
|
|
23
|
+
host: {
|
|
24
|
+
class: 'contents',
|
|
25
|
+
'(mouseenter)': 'onMouseEnter()',
|
|
26
|
+
'(mouseleave)': 'onMouseLeave()',
|
|
27
|
+
},
|
|
28
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
29
|
+
})
|
|
30
|
+
export class MenubarSubContent {
|
|
31
|
+
protected readonly subContext = inject(MENUBAR_SUB_CONTEXT);
|
|
32
|
+
|
|
33
|
+
/** Additional CSS classes */
|
|
34
|
+
readonly class = input<string>('');
|
|
35
|
+
|
|
36
|
+
protected readonly computedClass = computed(() =>
|
|
37
|
+
cn(
|
|
38
|
+
'absolute left-full top-0 z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg',
|
|
39
|
+
'data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95',
|
|
40
|
+
this.class()
|
|
41
|
+
)
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
protected onMouseEnter(): void {
|
|
45
|
+
this.subContext.open.set(true);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
protected onMouseLeave(): void {
|
|
49
|
+
this.subContext.open.set(false);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { cn } from '@/lib/utils';
|
|
2
|
+
import { ChangeDetectionStrategy, Component, computed, inject, input } from '@angular/core';
|
|
3
|
+
import { ChevronRight, LucideAngularModule } from 'lucide-angular';
|
|
4
|
+
import { MENUBAR_SUB_CONTEXT } from './menubar-sub.component';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* MenubarSubTrigger component - trigger for submenu.
|
|
8
|
+
* Matches shadcn/ui React MenubarSubTrigger exactly.
|
|
9
|
+
*/
|
|
10
|
+
@Component({
|
|
11
|
+
selector: 'MenubarSubTrigger',
|
|
12
|
+
imports: [LucideAngularModule],
|
|
13
|
+
template: `
|
|
14
|
+
<ng-content />
|
|
15
|
+
<lucide-icon [img]="ChevronRightIcon" class="ml-auto h-4 w-4" />
|
|
16
|
+
`,
|
|
17
|
+
host: {
|
|
18
|
+
'[class]': 'computedClass()',
|
|
19
|
+
'[attr.data-state]': 'subContext.open() ? "open" : "closed"',
|
|
20
|
+
'(mouseenter)': 'onMouseEnter()',
|
|
21
|
+
'(mouseleave)': 'onMouseLeave()',
|
|
22
|
+
},
|
|
23
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
24
|
+
})
|
|
25
|
+
export class MenubarSubTrigger {
|
|
26
|
+
protected readonly subContext = inject(MENUBAR_SUB_CONTEXT);
|
|
27
|
+
protected readonly ChevronRightIcon = ChevronRight;
|
|
28
|
+
|
|
29
|
+
/** Whether the trigger is inset */
|
|
30
|
+
readonly inset = input<boolean>(false);
|
|
31
|
+
|
|
32
|
+
/** Additional CSS classes */
|
|
33
|
+
readonly class = input<string>('');
|
|
34
|
+
|
|
35
|
+
protected readonly computedClass = computed(() =>
|
|
36
|
+
cn(
|
|
37
|
+
'flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground',
|
|
38
|
+
this.inset() && 'pl-8',
|
|
39
|
+
this.class()
|
|
40
|
+
)
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
protected onMouseEnter(): void {
|
|
44
|
+
this.subContext.open.set(true);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
protected onMouseLeave(): void {
|
|
48
|
+
// Keep open for mouse to move to sub-content
|
|
49
|
+
}
|
|
50
|
+
}
|