@ng-cn/core 1.0.10 → 1.0.12
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 +3 -2
- 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,263 @@
|
|
|
1
|
+
import { cn } from '@/lib/utils';
|
|
2
|
+
import { AriaIdService } from '@/lib/utils/accessibility';
|
|
3
|
+
import {
|
|
4
|
+
ChangeDetectionStrategy,
|
|
5
|
+
Component,
|
|
6
|
+
computed,
|
|
7
|
+
effect,
|
|
8
|
+
ElementRef,
|
|
9
|
+
forwardRef,
|
|
10
|
+
inject,
|
|
11
|
+
input,
|
|
12
|
+
model,
|
|
13
|
+
output,
|
|
14
|
+
signal,
|
|
15
|
+
} from '@angular/core';
|
|
16
|
+
import { SELECT_CONTEXT, type SelectContext } from './select-context';
|
|
17
|
+
|
|
18
|
+
// ============================================================================
|
|
19
|
+
// Types
|
|
20
|
+
// ============================================================================
|
|
21
|
+
|
|
22
|
+
export type SelectState = 'open' | 'closed';
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Props for the Select component
|
|
26
|
+
*/
|
|
27
|
+
export interface SelectProps {
|
|
28
|
+
/** The value of the select when initially rendered.
|
|
29
|
+
* Use when you do not need to control the state of the select. */
|
|
30
|
+
defaultValue?: string;
|
|
31
|
+
/** The controlled value of the select.
|
|
32
|
+
* Should be used in conjunction with onValueChange. */
|
|
33
|
+
value?: string;
|
|
34
|
+
/** The controlled open state of the select.
|
|
35
|
+
* Must be used in conjunction with onOpenChange. */
|
|
36
|
+
open?: boolean;
|
|
37
|
+
/** When true, prevents the user from interacting with select.
|
|
38
|
+
* @default false */
|
|
39
|
+
disabled?: boolean;
|
|
40
|
+
/** The name of the select. Submitted with its owning form as part of a name/value pair. */
|
|
41
|
+
name?: string;
|
|
42
|
+
/** When true, indicates that the user must select a value before the owning form can be submitted.
|
|
43
|
+
* @default false */
|
|
44
|
+
required?: boolean;
|
|
45
|
+
/** Additional CSS classes */
|
|
46
|
+
class?: string;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// ============================================================================
|
|
50
|
+
// Component
|
|
51
|
+
// ============================================================================
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* @component Select
|
|
55
|
+
*
|
|
56
|
+
* Displays a list of options for the user to pick from—triggered by a button.
|
|
57
|
+
*
|
|
58
|
+
* @description
|
|
59
|
+
* Select provides a dropdown selection input that implements the WAI-ARIA
|
|
60
|
+
* listbox pattern with full keyboard navigation.
|
|
61
|
+
*
|
|
62
|
+
* ## Features
|
|
63
|
+
* - Full keyboard navigation
|
|
64
|
+
* - Supports controlled and uncontrolled usage
|
|
65
|
+
* - Groups and separators for organizing options
|
|
66
|
+
* - Disabled items and groups
|
|
67
|
+
* - Custom trigger and value display
|
|
68
|
+
* - Form submission with native hidden input
|
|
69
|
+
*
|
|
70
|
+
* ## Accessibility
|
|
71
|
+
* Implements the WAI-ARIA Listbox Pattern:
|
|
72
|
+
* - `role="listbox"` on content
|
|
73
|
+
* - `role="option"` on items
|
|
74
|
+
* - `aria-expanded` on trigger
|
|
75
|
+
* - `aria-labelledby` relationships
|
|
76
|
+
* - Roving tabindex for keyboard navigation
|
|
77
|
+
*
|
|
78
|
+
* ## Keyboard Navigation
|
|
79
|
+
* When focus is on the trigger:
|
|
80
|
+
* - `Enter` / `Space` / `ArrowDown` / `ArrowUp` - Open the select
|
|
81
|
+
*
|
|
82
|
+
* When focus is on an item:
|
|
83
|
+
* - `Enter` / `Space` - Select the focused item
|
|
84
|
+
* - `ArrowDown` - Focus next item
|
|
85
|
+
* - `ArrowUp` - Focus previous item
|
|
86
|
+
* - `Home` - Focus first item
|
|
87
|
+
* - `End` - Focus last item
|
|
88
|
+
* - `Escape` - Close the select
|
|
89
|
+
* - Type to search - Focus matching item
|
|
90
|
+
*
|
|
91
|
+
* @example Basic usage
|
|
92
|
+
* ```html
|
|
93
|
+
* <Select [(value)]="selectedFruit">
|
|
94
|
+
* <SelectTrigger class="w-[180px]">
|
|
95
|
+
* <SelectValue placeholder="Select a fruit" />
|
|
96
|
+
* </SelectTrigger>
|
|
97
|
+
* <SelectContent>
|
|
98
|
+
* <SelectItem value="apple">Apple</SelectItem>
|
|
99
|
+
* <SelectItem value="banana">Banana</SelectItem>
|
|
100
|
+
* <SelectItem value="orange">Orange</SelectItem>
|
|
101
|
+
* </SelectContent>
|
|
102
|
+
* </Select>
|
|
103
|
+
* ```
|
|
104
|
+
*
|
|
105
|
+
* @example With groups
|
|
106
|
+
* ```html
|
|
107
|
+
* <Select>
|
|
108
|
+
* <SelectTrigger>
|
|
109
|
+
* <SelectValue placeholder="Select a timezone" />
|
|
110
|
+
* </SelectTrigger>
|
|
111
|
+
* <SelectContent>
|
|
112
|
+
* <SelectGroup>
|
|
113
|
+
* <SelectLabel>North America</SelectLabel>
|
|
114
|
+
* <SelectItem value="est">Eastern Time</SelectItem>
|
|
115
|
+
* <SelectItem value="cst">Central Time</SelectItem>
|
|
116
|
+
* </SelectGroup>
|
|
117
|
+
* <SelectSeparator />
|
|
118
|
+
* <SelectGroup>
|
|
119
|
+
* <SelectLabel>Europe</SelectLabel>
|
|
120
|
+
* <SelectItem value="gmt">GMT</SelectItem>
|
|
121
|
+
* <SelectItem value="cet">Central European</SelectItem>
|
|
122
|
+
* </SelectGroup>
|
|
123
|
+
* </SelectContent>
|
|
124
|
+
* </Select>
|
|
125
|
+
* ```
|
|
126
|
+
*
|
|
127
|
+
* @example Form usage
|
|
128
|
+
* ```html
|
|
129
|
+
* <Select name="fruit" [required]="true">
|
|
130
|
+
* <SelectTrigger>
|
|
131
|
+
* <SelectValue placeholder="Required field" />
|
|
132
|
+
* </SelectTrigger>
|
|
133
|
+
* <SelectContent>
|
|
134
|
+
* <SelectItem value="apple">Apple</SelectItem>
|
|
135
|
+
* </SelectContent>
|
|
136
|
+
* </Select>
|
|
137
|
+
* ```
|
|
138
|
+
*
|
|
139
|
+
* @data-attributes
|
|
140
|
+
* - `data-state` - 'open' | 'closed'
|
|
141
|
+
* - `data-disabled` - Present when disabled
|
|
142
|
+
*/
|
|
143
|
+
@Component({
|
|
144
|
+
selector: 'Select',
|
|
145
|
+
template: `<ng-content />`,
|
|
146
|
+
host: {
|
|
147
|
+
'[class]': 'computedClass()',
|
|
148
|
+
'[attr.data-state]': 'context.open() ? "open" : "closed"',
|
|
149
|
+
'[attr.data-disabled]': 'disabled() ? "" : null',
|
|
150
|
+
'data-slot': 'select',
|
|
151
|
+
},
|
|
152
|
+
providers: [
|
|
153
|
+
{
|
|
154
|
+
provide: SELECT_CONTEXT,
|
|
155
|
+
useFactory: (component: Select) => component.context,
|
|
156
|
+
deps: [forwardRef(() => Select)],
|
|
157
|
+
},
|
|
158
|
+
],
|
|
159
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
160
|
+
})
|
|
161
|
+
export class Select {
|
|
162
|
+
private readonly elementRef = inject(ElementRef<HTMLElement>);
|
|
163
|
+
private readonly ariaIdService = inject(AriaIdService);
|
|
164
|
+
private readonly ariaIds = this.ariaIdService.generateMenuIds('select');
|
|
165
|
+
|
|
166
|
+
/** The controlled value of the select */
|
|
167
|
+
readonly value = model<string>('');
|
|
168
|
+
|
|
169
|
+
/** The controlled open state of the select */
|
|
170
|
+
readonly open = model<boolean>(false);
|
|
171
|
+
|
|
172
|
+
/** When true, prevents the user from interacting with select */
|
|
173
|
+
readonly disabled = input<boolean>(false);
|
|
174
|
+
|
|
175
|
+
/** The name of the select for form submission */
|
|
176
|
+
readonly name = input<string>('');
|
|
177
|
+
|
|
178
|
+
/** When true, indicates that the user must select a value */
|
|
179
|
+
readonly required = input<boolean>(false);
|
|
180
|
+
|
|
181
|
+
/** Additional CSS classes */
|
|
182
|
+
readonly class = input<string>('');
|
|
183
|
+
|
|
184
|
+
/** Event handler called when the value changes */
|
|
185
|
+
readonly valueChange = output<string>();
|
|
186
|
+
|
|
187
|
+
/** Event handler called when the open state changes */
|
|
188
|
+
readonly openChange = output<boolean>();
|
|
189
|
+
|
|
190
|
+
/** Internal signals for context */
|
|
191
|
+
private readonly _value = signal<string>('');
|
|
192
|
+
private readonly _open = signal<boolean>(false);
|
|
193
|
+
private readonly _disabled = signal<boolean>(false);
|
|
194
|
+
|
|
195
|
+
/** Context for child components */
|
|
196
|
+
readonly context: SelectContext = {
|
|
197
|
+
value: this._value,
|
|
198
|
+
open: this._open,
|
|
199
|
+
disabled: this._disabled,
|
|
200
|
+
placeholder: signal(''),
|
|
201
|
+
selectedLabel: signal(''),
|
|
202
|
+
contentId: this.ariaIds.contentId,
|
|
203
|
+
triggerElement: signal<HTMLElement | null>(null),
|
|
204
|
+
itemValues: signal<string[]>([]),
|
|
205
|
+
focusedIndex: signal(-1),
|
|
206
|
+
required: () => this.required(),
|
|
207
|
+
name: () => this.name(),
|
|
208
|
+
setValue: (value: string, label?: string) => {
|
|
209
|
+
this._value.set(value);
|
|
210
|
+
this.value.set(value);
|
|
211
|
+
this.valueChange.emit(value);
|
|
212
|
+
if (label) {
|
|
213
|
+
this.context.selectedLabel.set(label);
|
|
214
|
+
}
|
|
215
|
+
this._open.set(false);
|
|
216
|
+
this.open.set(false);
|
|
217
|
+
this.openChange.emit(false);
|
|
218
|
+
// Restore focus to trigger
|
|
219
|
+
const trigger = this.context.triggerElement();
|
|
220
|
+
if (trigger) {
|
|
221
|
+
setTimeout(() => trigger.focus());
|
|
222
|
+
}
|
|
223
|
+
},
|
|
224
|
+
focusItem: (index: number) => this.focusItemByIndex(index),
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
/** Computed class combining base styles and custom classes */
|
|
228
|
+
protected readonly computedClass = computed(() =>
|
|
229
|
+
cn('relative inline-block', this.class())
|
|
230
|
+
);
|
|
231
|
+
|
|
232
|
+
constructor() {
|
|
233
|
+
// Sync value input to internal signal
|
|
234
|
+
effect(() => {
|
|
235
|
+
this._value.set(this.value());
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
// Sync open input to internal signal
|
|
239
|
+
effect(() => {
|
|
240
|
+
this._open.set(this.open());
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
// Sync disabled input to internal signal
|
|
244
|
+
effect(() => {
|
|
245
|
+
this._disabled.set(this.disabled());
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/** Focus an item by index */
|
|
250
|
+
private focusItemByIndex(index: number): void {
|
|
251
|
+
const values = this.context.itemValues();
|
|
252
|
+
if (index < 0 || index >= values.length) return;
|
|
253
|
+
|
|
254
|
+
this.context.focusedIndex.set(index);
|
|
255
|
+
const value = values[index];
|
|
256
|
+
const item = this.elementRef.nativeElement.querySelector(
|
|
257
|
+
`[data-slot="select-item"][data-value="${value}"]`
|
|
258
|
+
) as HTMLElement;
|
|
259
|
+
if (item) {
|
|
260
|
+
item.focus();
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { cn } from '@/lib/utils';
|
|
2
|
+
import {
|
|
3
|
+
ChangeDetectionStrategy,
|
|
4
|
+
Component,
|
|
5
|
+
computed,
|
|
6
|
+
input,
|
|
7
|
+
} from '@angular/core';
|
|
8
|
+
|
|
9
|
+
// ============================================================================
|
|
10
|
+
// Types
|
|
11
|
+
// ============================================================================
|
|
12
|
+
|
|
13
|
+
export type SeparatorOrientation = 'horizontal' | 'vertical';
|
|
14
|
+
|
|
15
|
+
export type SeparatorProps = {
|
|
16
|
+
/** The orientation of the separator */
|
|
17
|
+
orientation?: SeparatorOrientation;
|
|
18
|
+
/**
|
|
19
|
+
* Whether the separator is purely decorative.
|
|
20
|
+
* When true, removes from accessibility tree (role="none").
|
|
21
|
+
* When false, uses role="separator" for screen readers.
|
|
22
|
+
*/
|
|
23
|
+
decorative?: boolean;
|
|
24
|
+
/** Additional CSS classes to apply */
|
|
25
|
+
class?: string;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
// ============================================================================
|
|
29
|
+
// Separator Component
|
|
30
|
+
// ============================================================================
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Separator component creates a visual divider between content.
|
|
34
|
+
* Based on Radix UI Separator primitive with shadcn/ui styling.
|
|
35
|
+
*
|
|
36
|
+
* ## Features
|
|
37
|
+
* - Horizontal or vertical orientation
|
|
38
|
+
* - Decorative mode for purely visual separators
|
|
39
|
+
* - Semantic separator role for accessibility when not decorative
|
|
40
|
+
* - Full ARIA support
|
|
41
|
+
*
|
|
42
|
+
* ## Accessibility
|
|
43
|
+
* - Uses `role="separator"` for semantic meaning (unless decorative)
|
|
44
|
+
* - `aria-orientation` indicates the separator direction
|
|
45
|
+
* - Decorative separators are hidden from assistive technology
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* <!-- Horizontal separator (default) -->
|
|
49
|
+
* <div class="space-y-4">
|
|
50
|
+
* <p>Some content above</p>
|
|
51
|
+
* <Separator />
|
|
52
|
+
* <p>Some content below</p>
|
|
53
|
+
* </div>
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* <!-- Vertical separator -->
|
|
57
|
+
* <div class="flex h-5 items-center space-x-4 text-sm">
|
|
58
|
+
* <span>Blog</span>
|
|
59
|
+
* <Separator orientation="vertical" />
|
|
60
|
+
* <span>Docs</span>
|
|
61
|
+
* <Separator orientation="vertical" />
|
|
62
|
+
* <span>Source</span>
|
|
63
|
+
* </div>
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* <!-- Decorative separator (hidden from screen readers) -->
|
|
67
|
+
* <Separator [decorative]="true" />
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* <!-- With custom styling -->
|
|
71
|
+
* <Separator class="my-4 bg-primary/50" />
|
|
72
|
+
*
|
|
73
|
+
* @see {@link https://www.radix-ui.com/primitives/docs/components/separator Radix Separator}
|
|
74
|
+
* @see {@link https://ui.shadcn.com/docs/components/separator shadcn/ui Separator}
|
|
75
|
+
*/
|
|
76
|
+
@Component({
|
|
77
|
+
selector: 'Separator',
|
|
78
|
+
template: ``,
|
|
79
|
+
host: {
|
|
80
|
+
'[class]': 'computedClass()',
|
|
81
|
+
'[attr.role]': 'role()',
|
|
82
|
+
'[attr.aria-orientation]': 'ariaOrientation()',
|
|
83
|
+
'[attr.data-orientation]': 'orientation()',
|
|
84
|
+
'data-slot': 'separator',
|
|
85
|
+
},
|
|
86
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
87
|
+
})
|
|
88
|
+
export class Separator {
|
|
89
|
+
/** The orientation of the separator */
|
|
90
|
+
readonly orientation = input<SeparatorOrientation>('horizontal');
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Whether the separator is purely decorative.
|
|
94
|
+
* When true, removes from accessibility tree.
|
|
95
|
+
*/
|
|
96
|
+
readonly decorative = input<boolean>(false);
|
|
97
|
+
|
|
98
|
+
/** Additional CSS classes to apply */
|
|
99
|
+
readonly class = input<string>('');
|
|
100
|
+
|
|
101
|
+
/** Computed role - none for decorative, separator otherwise */
|
|
102
|
+
protected readonly role = computed(() =>
|
|
103
|
+
this.decorative() ? 'none' : 'separator'
|
|
104
|
+
);
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* aria-orientation is only needed for non-decorative separators.
|
|
108
|
+
* Per WAI-ARIA, separators default to horizontal, so we only need
|
|
109
|
+
* to specify when vertical.
|
|
110
|
+
*/
|
|
111
|
+
protected readonly ariaOrientation = computed(() => {
|
|
112
|
+
if (this.decorative()) return undefined;
|
|
113
|
+
// Only specify aria-orientation for vertical (horizontal is default)
|
|
114
|
+
return this.orientation() === 'vertical' ? 'vertical' : undefined;
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
/** Computed class based on orientation */
|
|
118
|
+
protected readonly computedClass = computed(() =>
|
|
119
|
+
cn(
|
|
120
|
+
// Base styles
|
|
121
|
+
'bg-border shrink-0',
|
|
122
|
+
// Orientation-specific styles
|
|
123
|
+
this.orientation() === 'horizontal' ? 'h-px w-full' : 'h-full w-px',
|
|
124
|
+
// Custom classes
|
|
125
|
+
this.class()
|
|
126
|
+
)
|
|
127
|
+
);
|
|
128
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export { SheetClose } from './sheet-close.component';
|
|
2
|
+
export { SheetContent } from './sheet-content.component';
|
|
3
|
+
export { SHEET_CONTEXT, type SheetContextValue } from './sheet-context';
|
|
4
|
+
export { SheetDescription } from './sheet-description.component';
|
|
5
|
+
export { SheetFooter } from './sheet-footer.component';
|
|
6
|
+
export { SheetHeader } from './sheet-header.component';
|
|
7
|
+
export { SheetTitle } from './sheet-title.component';
|
|
8
|
+
export { SheetTrigger } from './sheet-trigger.component';
|
|
9
|
+
export { sheetVariants, type SheetVariants } from './sheet-variants';
|
|
10
|
+
export { Sheet } from './sheet.component';
|
|
11
|
+
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ChangeDetectionStrategy,
|
|
3
|
+
Component,
|
|
4
|
+
inject,
|
|
5
|
+
input,
|
|
6
|
+
} from '@angular/core';
|
|
7
|
+
import { SHEET_CONTEXT } from './sheet-context';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* SheetClose component - button that closes the sheet.
|
|
11
|
+
* Matches shadcn/ui React SheetClose exactly.
|
|
12
|
+
*/
|
|
13
|
+
@Component({
|
|
14
|
+
selector: 'SheetClose',
|
|
15
|
+
template: `<ng-content />`,
|
|
16
|
+
host: {
|
|
17
|
+
class: 'contents',
|
|
18
|
+
'(click)': 'onClick($event)',
|
|
19
|
+
},
|
|
20
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
21
|
+
})
|
|
22
|
+
export class SheetClose {
|
|
23
|
+
protected readonly context = inject(SHEET_CONTEXT);
|
|
24
|
+
|
|
25
|
+
/** Render as child */
|
|
26
|
+
readonly asChild = input<boolean>(false);
|
|
27
|
+
|
|
28
|
+
onClick(event: Event): void {
|
|
29
|
+
event.stopPropagation();
|
|
30
|
+
this.context.setOpen(false);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { cn, Presence } from '@/lib/utils';
|
|
2
|
+
import { FocusTrapDirective } from '@/lib/utils/accessibility';
|
|
3
|
+
import {
|
|
4
|
+
ChangeDetectionStrategy,
|
|
5
|
+
Component,
|
|
6
|
+
computed,
|
|
7
|
+
effect,
|
|
8
|
+
inject,
|
|
9
|
+
input,
|
|
10
|
+
OnDestroy
|
|
11
|
+
} from '@angular/core';
|
|
12
|
+
import { SHEET_CONTEXT } from './sheet-context';
|
|
13
|
+
import { sheetVariants, type SheetVariants } from './sheet-variants';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* SheetContent component - the content of the sheet panel.
|
|
17
|
+
* Matches shadcn/ui React SheetContent exactly.
|
|
18
|
+
* Includes focus trapping, focus restoration, proper ARIA relationships,
|
|
19
|
+
* and Radix-compatible exit animations via Presence component.
|
|
20
|
+
*/
|
|
21
|
+
@Component({
|
|
22
|
+
selector: 'SheetContent',
|
|
23
|
+
imports: [FocusTrapDirective, Presence],
|
|
24
|
+
template: `
|
|
25
|
+
<Presence [present]="context.open()">
|
|
26
|
+
<!-- Overlay -->
|
|
27
|
+
<div
|
|
28
|
+
class="fixed inset-0 z-[100] bg-black/50 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0"
|
|
29
|
+
[attr.data-state]="context.open() ? 'open' : 'closed'"
|
|
30
|
+
(click)="onOverlayClick($event)"
|
|
31
|
+
aria-hidden="true"
|
|
32
|
+
></div>
|
|
33
|
+
<!-- Content -->
|
|
34
|
+
<div
|
|
35
|
+
hlmFocusTrap
|
|
36
|
+
[trapFocus]="context.open()"
|
|
37
|
+
[autoFocus]="true"
|
|
38
|
+
[restoreFocus]="false"
|
|
39
|
+
[class]="computedClass()"
|
|
40
|
+
[attr.data-state]="context.open() ? 'open' : 'closed'"
|
|
41
|
+
[attr.data-side]="side()"
|
|
42
|
+
[attr.id]="context.contentId"
|
|
43
|
+
[attr.aria-labelledby]="context.titleId"
|
|
44
|
+
[attr.aria-describedby]="context.descriptionId"
|
|
45
|
+
role="dialog"
|
|
46
|
+
aria-modal="true"
|
|
47
|
+
(keydown.escape)="onEscapeKey()"
|
|
48
|
+
>
|
|
49
|
+
<ng-content />
|
|
50
|
+
<!-- Close button -->
|
|
51
|
+
<button
|
|
52
|
+
type="button"
|
|
53
|
+
class="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-secondary"
|
|
54
|
+
(click)="onClose()"
|
|
55
|
+
aria-label="Close sheet"
|
|
56
|
+
>
|
|
57
|
+
<svg
|
|
58
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
59
|
+
width="24"
|
|
60
|
+
height="24"
|
|
61
|
+
viewBox="0 0 24 24"
|
|
62
|
+
fill="none"
|
|
63
|
+
stroke="currentColor"
|
|
64
|
+
stroke-width="2"
|
|
65
|
+
stroke-linecap="round"
|
|
66
|
+
stroke-linejoin="round"
|
|
67
|
+
class="h-4 w-4"
|
|
68
|
+
aria-hidden="true"
|
|
69
|
+
>
|
|
70
|
+
<path d="M18 6 6 18" />
|
|
71
|
+
<path d="m6 6 12 12" />
|
|
72
|
+
</svg>
|
|
73
|
+
<span class="sr-only">Close</span>
|
|
74
|
+
</button>
|
|
75
|
+
</div>
|
|
76
|
+
</Presence>
|
|
77
|
+
`,
|
|
78
|
+
host: {
|
|
79
|
+
class: 'contents',
|
|
80
|
+
},
|
|
81
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
82
|
+
})
|
|
83
|
+
export class SheetContent implements OnDestroy {
|
|
84
|
+
protected readonly context = inject(SHEET_CONTEXT);
|
|
85
|
+
|
|
86
|
+
/** Side from which the sheet appears */
|
|
87
|
+
readonly side = input<SheetVariants['side']>('right');
|
|
88
|
+
|
|
89
|
+
/** Additional CSS classes */
|
|
90
|
+
readonly class = input<string>('');
|
|
91
|
+
|
|
92
|
+
/** Previous body overflow for restoration */
|
|
93
|
+
private previousBodyOverflow = '';
|
|
94
|
+
|
|
95
|
+
protected readonly computedClass = computed(() =>
|
|
96
|
+
cn(sheetVariants({ side: this.side() }), this.class())
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
constructor() {
|
|
100
|
+
// Handle body scroll lock based on open state (browser-only via effect + afterNextRender)
|
|
101
|
+
effect(() => {
|
|
102
|
+
const isOpen = this.context.open();
|
|
103
|
+
if (isOpen) {
|
|
104
|
+
this.lockBodyScroll();
|
|
105
|
+
} else {
|
|
106
|
+
this.unlockBodyScroll();
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
private lockBodyScroll(): void {
|
|
112
|
+
if (typeof document !== 'undefined') {
|
|
113
|
+
this.previousBodyOverflow = document.body.style.overflow;
|
|
114
|
+
document.body.style.overflow = 'hidden';
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
private unlockBodyScroll(): void {
|
|
119
|
+
if (typeof document !== 'undefined') {
|
|
120
|
+
document.body.style.overflow = this.previousBodyOverflow;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
ngOnDestroy(): void {
|
|
125
|
+
// Restore body scroll
|
|
126
|
+
this.unlockBodyScroll();
|
|
127
|
+
// Restore focus to trigger element
|
|
128
|
+
this.restoreFocus();
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
onOverlayClick(event: Event): void {
|
|
132
|
+
event.stopPropagation();
|
|
133
|
+
this.close();
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
onEscapeKey(): void {
|
|
137
|
+
this.close();
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
onClose(): void {
|
|
141
|
+
this.close();
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
private close(): void {
|
|
145
|
+
this.restoreFocus();
|
|
146
|
+
this.context.setOpen(false);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
private restoreFocus(): void {
|
|
150
|
+
const triggerEl = this.context.triggerElement();
|
|
151
|
+
if (triggerEl) {
|
|
152
|
+
setTimeout(() => {
|
|
153
|
+
triggerEl.focus();
|
|
154
|
+
}, 0);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { InjectionToken, Signal, WritableSignal } from '@angular/core';
|
|
2
|
+
|
|
3
|
+
export interface SheetContextValue {
|
|
4
|
+
open: Signal<boolean>;
|
|
5
|
+
setOpen: (open: boolean) => void;
|
|
6
|
+
side: 'top' | 'right' | 'bottom' | 'left';
|
|
7
|
+
/** Unique IDs for ARIA relationships */
|
|
8
|
+
titleId: string;
|
|
9
|
+
descriptionId: string;
|
|
10
|
+
contentId: string;
|
|
11
|
+
/** Trigger element reference for focus restoration */
|
|
12
|
+
triggerElement: WritableSignal<HTMLElement | null>;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const SHEET_CONTEXT = new InjectionToken<SheetContextValue>('SHEET_CONTEXT');
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { cn } from '@/lib/utils';
|
|
2
|
+
import {
|
|
3
|
+
ChangeDetectionStrategy,
|
|
4
|
+
Component,
|
|
5
|
+
computed,
|
|
6
|
+
inject,
|
|
7
|
+
input,
|
|
8
|
+
} from '@angular/core';
|
|
9
|
+
import { SHEET_CONTEXT } from './sheet-context';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* SheetDescription component - description text of the sheet.
|
|
13
|
+
* Matches shadcn/ui React SheetDescription exactly.
|
|
14
|
+
* Automatically links to sheet via aria-describedby.
|
|
15
|
+
*/
|
|
16
|
+
@Component({
|
|
17
|
+
selector: 'SheetDescription',
|
|
18
|
+
template: `<ng-content />`,
|
|
19
|
+
host: {
|
|
20
|
+
'[class]': 'computedClass()',
|
|
21
|
+
'[attr.id]': 'context.descriptionId',
|
|
22
|
+
},
|
|
23
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
24
|
+
})
|
|
25
|
+
export class SheetDescription {
|
|
26
|
+
protected readonly context = inject(SHEET_CONTEXT);
|
|
27
|
+
|
|
28
|
+
/** Additional CSS classes */
|
|
29
|
+
readonly class = input<string>('');
|
|
30
|
+
|
|
31
|
+
protected readonly computedClass = computed(() =>
|
|
32
|
+
cn('text-sm text-muted-foreground', this.class())
|
|
33
|
+
);
|
|
34
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { cn } from '@/lib/utils';
|
|
2
|
+
import {
|
|
3
|
+
ChangeDetectionStrategy,
|
|
4
|
+
Component,
|
|
5
|
+
computed,
|
|
6
|
+
input,
|
|
7
|
+
} from '@angular/core';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* SheetFooter component - footer area of the sheet.
|
|
11
|
+
* Matches shadcn/ui React SheetFooter exactly.
|
|
12
|
+
*/
|
|
13
|
+
@Component({
|
|
14
|
+
selector: 'SheetFooter',
|
|
15
|
+
template: `<ng-content />`,
|
|
16
|
+
host: {
|
|
17
|
+
'[class]': 'computedClass()',
|
|
18
|
+
},
|
|
19
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
20
|
+
})
|
|
21
|
+
export class SheetFooter {
|
|
22
|
+
/** Additional CSS classes */
|
|
23
|
+
readonly class = input<string>('');
|
|
24
|
+
|
|
25
|
+
protected readonly computedClass = computed(() =>
|
|
26
|
+
cn('flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2', this.class())
|
|
27
|
+
);
|
|
28
|
+
}
|