@ojiepermana/angular 22.1.11 → 22.1.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/README.md +32 -26
- package/chart/README.md +272 -0
- package/component/README.md +89 -0
- package/component/accordion/README.md +195 -0
- package/component/alert/README.md +184 -0
- package/component/alert-dialog/README.md +255 -0
- package/component/aspect-ratio/README.md +116 -0
- package/component/avatar/README.md +182 -0
- package/component/badge/README.md +143 -0
- package/component/breadcrumb/README.md +223 -0
- package/component/button/README.md +141 -0
- package/component/button-group/README.md +214 -0
- package/component/calendar/README.md +137 -0
- package/component/card/README.md +232 -0
- package/component/carousel/README.md +276 -0
- package/component/checkbox/README.md +153 -0
- package/component/collapsible/README.md +216 -0
- package/component/combobox/README.md +202 -0
- package/component/command/README.md +287 -0
- package/component/composer/README.md +241 -0
- package/component/context-menu/README.md +268 -0
- package/component/date-picker/README.md +202 -0
- package/component/dialog/README.md +276 -0
- package/component/drawer/README.md +147 -0
- package/component/dropdown-menu/README.md +336 -0
- package/component/editor/README.md +152 -0
- package/component/empty/README.md +193 -0
- package/component/form/README.md +216 -0
- package/component/hover-card/README.md +150 -0
- package/component/icon/README.md +25 -0
- package/component/input/README.md +160 -0
- package/component/input-group/README.md +245 -0
- package/component/input-otp/README.md +331 -0
- package/component/item/README.md +254 -0
- package/component/kanban/README.md +81 -0
- package/component/kbd/README.md +141 -0
- package/component/label/README.md +137 -0
- package/component/menubar/README.md +270 -0
- package/component/native-select/README.md +176 -0
- package/component/navigation-menu/README.md +165 -0
- package/component/pagination/README.md +151 -0
- package/component/pillbox/README.md +68 -0
- package/component/popover/README.md +54 -0
- package/component/progress/README.md +160 -0
- package/component/radio/README.md +212 -0
- package/component/resizable/README.md +178 -0
- package/component/scroll-area/README.md +150 -0
- package/component/select/README.md +228 -0
- package/component/separator/README.md +175 -0
- package/component/sheet/README.md +190 -0
- package/component/skeleton/README.md +158 -0
- package/component/slider/README.md +207 -0
- package/component/spinner/README.md +160 -0
- package/component/switch/README.md +170 -0
- package/component/table/README.md +292 -0
- package/component/tabs/README.md +220 -0
- package/component/textarea/README.md +169 -0
- package/component/timeline/README.md +94 -0
- package/component/toast/README.md +173 -0
- package/component/toggle/README.md +133 -0
- package/component/toggle-group/README.md +234 -0
- package/component/tooltip/README.md +230 -0
- package/fesm2022/ojiepermana-angular-chart-area.mjs +289 -3
- package/fesm2022/ojiepermana-angular-chart-bar.mjs +722 -3
- package/fesm2022/ojiepermana-angular-chart-core.mjs +1482 -3
- package/fesm2022/ojiepermana-angular-chart-line.mjs +294 -3
- package/fesm2022/ojiepermana-angular-chart-pie.mjs +291 -3
- package/fesm2022/ojiepermana-angular-chart-primitives.mjs +1301 -3
- package/fesm2022/ojiepermana-angular-chart-radar.mjs +421 -3
- package/fesm2022/ojiepermana-angular-chart-radial.mjs +295 -3
- package/fesm2022/ojiepermana-angular-chart-scatter.mjs +306 -3
- package/fesm2022/ojiepermana-angular-chart.mjs +12 -3
- package/fesm2022/ojiepermana-angular-component-accordion.mjs +267 -3
- package/fesm2022/ojiepermana-angular-component-alert-dialog.mjs +359 -3
- package/fesm2022/ojiepermana-angular-component-alert.mjs +101 -3
- package/fesm2022/ojiepermana-angular-component-aspect-ratio.mjs +31 -3
- package/fesm2022/ojiepermana-angular-component-avatar.mjs +139 -3
- package/fesm2022/ojiepermana-angular-component-badge.mjs +57 -3
- package/fesm2022/ojiepermana-angular-component-breadcrumb.mjs +192 -3
- package/fesm2022/ojiepermana-angular-component-button-group.mjs +95 -3
- package/fesm2022/ojiepermana-angular-component-button.mjs +73 -3
- package/fesm2022/ojiepermana-angular-component-calendar.mjs +718 -3
- package/fesm2022/ojiepermana-angular-component-card.mjs +167 -3
- package/fesm2022/ojiepermana-angular-component-carousel.mjs +326 -3
- package/fesm2022/ojiepermana-angular-component-checkbox.mjs +190 -3
- package/fesm2022/ojiepermana-angular-component-collapsible.mjs +117 -3
- package/fesm2022/ojiepermana-angular-component-combobox.mjs +327 -3
- package/fesm2022/ojiepermana-angular-component-command.mjs +351 -3
- package/fesm2022/ojiepermana-angular-component-composer.mjs +359 -3
- package/fesm2022/ojiepermana-angular-component-context-menu.mjs +158 -3
- package/fesm2022/ojiepermana-angular-component-date-picker.mjs +482 -3
- package/fesm2022/ojiepermana-angular-component-dialog.mjs +400 -3
- package/fesm2022/ojiepermana-angular-component-drawer.mjs +1 -3
- package/fesm2022/ojiepermana-angular-component-dropdown-menu.mjs +689 -3
- package/fesm2022/ojiepermana-angular-component-editor.mjs +511 -3
- package/fesm2022/ojiepermana-angular-component-empty.mjs +134 -3
- package/fesm2022/ojiepermana-angular-component-form.mjs +438 -3
- package/fesm2022/ojiepermana-angular-component-hover-card.mjs +273 -3
- package/fesm2022/ojiepermana-angular-component-icon.mjs +139 -3
- package/fesm2022/ojiepermana-angular-component-input-group.mjs +176 -3
- package/fesm2022/ojiepermana-angular-component-input-otp.mjs +550 -3
- package/fesm2022/ojiepermana-angular-component-input.mjs +52 -3
- package/fesm2022/ojiepermana-angular-component-item.mjs +264 -3
- package/fesm2022/ojiepermana-angular-component-kanban.mjs +310 -3
- package/fesm2022/ojiepermana-angular-component-kbd.mjs +48 -3
- package/fesm2022/ojiepermana-angular-component-label.mjs +27 -3
- package/fesm2022/ojiepermana-angular-component-menubar.mjs +327 -3
- package/fesm2022/ojiepermana-angular-component-native-select.mjs +62 -3
- package/fesm2022/ojiepermana-angular-component-navigation-menu.mjs +378 -3
- package/fesm2022/ojiepermana-angular-component-pagination.mjs +238 -3
- package/fesm2022/ojiepermana-angular-component-pillbox.mjs +999 -3
- package/fesm2022/ojiepermana-angular-component-popover.mjs +201 -3
- package/fesm2022/ojiepermana-angular-component-progress.mjs +57 -3
- package/fesm2022/ojiepermana-angular-component-radio.mjs +180 -3
- package/fesm2022/ojiepermana-angular-component-resizable.mjs +493 -3
- package/fesm2022/ojiepermana-angular-component-scroll-area.mjs +51 -3
- package/fesm2022/ojiepermana-angular-component-segmented-control.mjs +227 -3
- package/fesm2022/ojiepermana-angular-component-select.mjs +609 -3
- package/fesm2022/ojiepermana-angular-component-separator.mjs +31 -3
- package/fesm2022/ojiepermana-angular-component-sheet.mjs +407 -3
- package/fesm2022/ojiepermana-angular-component-skeleton.mjs +25 -3
- package/fesm2022/ojiepermana-angular-component-slider.mjs +456 -3
- package/fesm2022/ojiepermana-angular-component-spinner.mjs +56 -3
- package/fesm2022/ojiepermana-angular-component-switch.mjs +145 -3
- package/fesm2022/ojiepermana-angular-component-table.mjs +155 -3
- package/fesm2022/ojiepermana-angular-component-tabs.mjs +315 -3
- package/fesm2022/ojiepermana-angular-component-textarea.mjs +46 -3
- package/fesm2022/ojiepermana-angular-component-timeline.mjs +237 -3
- package/fesm2022/ojiepermana-angular-component-toast.mjs +241 -3
- package/fesm2022/ojiepermana-angular-component-toggle-group.mjs +290 -3
- package/fesm2022/ojiepermana-angular-component-toggle.mjs +76 -3
- package/fesm2022/ojiepermana-angular-component-tooltip.mjs +519 -3
- package/fesm2022/ojiepermana-angular-component-utils-core.mjs +310 -3
- package/fesm2022/ojiepermana-angular-component-utils-overlay.mjs +62 -3
- package/fesm2022/ojiepermana-angular-component-utils-scale.mjs +34 -3
- package/fesm2022/ojiepermana-angular-component-utils.mjs +3 -2
- package/fesm2022/ojiepermana-angular-component.mjs +4 -4
- package/fesm2022/ojiepermana-angular-navigation-core.mjs +21 -3
- package/fesm2022/ojiepermana-angular-navigation-icon.mjs +20 -3
- package/fesm2022/ojiepermana-angular-navigation-navigation-badge-count.component-CDBxQ8rk.mjs +91 -0
- package/fesm2022/ojiepermana-angular-navigation-navigation-dockbar-menu.component-DBQHdvGa.mjs +512 -0
- package/fesm2022/ojiepermana-angular-navigation-navigation-entry-grid.component-Cd-jh6tg.mjs +623 -0
- package/fesm2022/ojiepermana-angular-navigation-navigation-flyout-menu.component-BCGvhoYj.mjs +404 -0
- package/fesm2022/ojiepermana-angular-navigation-navigation-horizontal.component-Dk_03e-6.mjs +466 -0
- package/fesm2022/ojiepermana-angular-navigation-ojiepermana-angular-navigation-DNKU6viC.mjs +2642 -0
- package/fesm2022/ojiepermana-angular-navigation-service.mjs +725 -3
- package/fesm2022/ojiepermana-angular-navigation-types.mjs +65 -4
- package/fesm2022/ojiepermana-angular-navigation.mjs +4 -10
- package/fesm2022/ojiepermana-angular-sdk.mjs +204 -4
- package/fesm2022/ojiepermana-angular-theme-component-settings.mjs +1387 -3
- package/fesm2022/ojiepermana-angular-theme-layout-services.mjs +331 -3
- package/fesm2022/ojiepermana-angular-theme-layout-types.mjs +45 -4
- package/fesm2022/ojiepermana-angular-theme-layout-wrapper.mjs +1044 -3
- package/fesm2022/ojiepermana-angular-theme-layout.mjs +729 -3
- package/fesm2022/ojiepermana-angular-theme-page-core.mjs +381 -3
- package/fesm2022/ojiepermana-angular-theme-page-filter.mjs +267 -3
- package/fesm2022/ojiepermana-angular-theme-page-root.mjs +361 -3
- package/fesm2022/ojiepermana-angular-theme-page-side.mjs +198 -3
- package/fesm2022/ojiepermana-angular-theme-page-slots.mjs +110 -3
- package/fesm2022/ojiepermana-angular-theme-page.mjs +7 -2
- package/fesm2022/ojiepermana-angular-theme-shell-services.mjs +338 -3
- package/fesm2022/ojiepermana-angular-theme-shell-types.mjs +160 -4
- package/fesm2022/ojiepermana-angular-theme-shell.mjs +811 -3
- package/fesm2022/ojiepermana-angular-theme-styles.mjs +783 -3
- package/fesm2022/ojiepermana-angular-theme.mjs +4 -4
- package/fesm2022/ojiepermana-angular.mjs +6 -11
- package/navigation/README.md +374 -0
- package/package.json +81 -20
- package/sdk/README.md +212 -0
- package/sdk/schematics/collection.json +20 -0
- package/sdk/schematics/init/index.js +83 -0
- package/sdk/schematics/init/schema.json +19 -0
- package/sdk/schematics/ng-add/index.js +147 -0
- package/sdk/schematics/ng-add/schema.json +14 -0
- package/sdk/schematics/package.json +3 -0
- package/sdk/schematics/sdk/index.js +175 -0
- package/sdk/schematics/sdk/schema.json +19 -0
- package/sdk/sdk.config.example.json +24 -0
- package/sdk/src/config/loader.js +43 -0
- package/sdk/src/config/schema.js +59 -0
- package/sdk/src/emit/client.js +251 -0
- package/sdk/src/emit/metadata.js +310 -0
- package/sdk/src/emit/models.js +104 -0
- package/sdk/src/emit/navigation.js +56 -0
- package/sdk/src/emit/operations.js +118 -0
- package/sdk/src/emit/public-api.js +54 -0
- package/sdk/src/emit/services.js +110 -0
- package/sdk/src/engine.js +67 -0
- package/sdk/src/layout/per-domain.js +360 -0
- package/sdk/src/package.json +3 -0
- package/sdk/src/parser/bundle.js +25 -0
- package/sdk/src/parser/ir.js +429 -0
- package/sdk/src/parser/types.js +7 -0
- package/sdk/src/render/template.js +152 -0
- package/sdk/src/writer/index.js +286 -0
- package/theme/README.md +126 -0
- package/theme/component/settings/README.md +135 -0
- package/theme/layout/README.md +539 -0
- package/theme/page/README.md +453 -0
- package/theme/shell/README.md +340 -0
- package/theme/styles/README.md +178 -0
- package/theme/styles/css/base/components.css +553 -0
- package/theme/styles/css/base/index.css +14 -0
- package/theme/styles/css/base/package.css +9 -0
- package/theme/styles/css/base/prefers-dark.css +86 -0
- package/theme/styles/css/base/print.css +62 -0
- package/theme/styles/css/base/status.css +38 -0
- package/theme/styles/css/base/tailwind.css +165 -0
- package/theme/styles/css/base/theme.css +373 -0
- package/theme/styles/css/base/tokens.css +361 -0
- package/theme/styles/css/color/amber.css +72 -0
- package/theme/styles/css/color/blue.css +72 -0
- package/theme/styles/css/color/brand.css +38 -0
- package/theme/styles/css/color/cyan.css +72 -0
- package/theme/styles/css/color/emerald.css +72 -0
- package/theme/styles/css/color/fuchsia.css +72 -0
- package/theme/styles/css/color/green.css +72 -0
- package/theme/styles/css/color/index.css +19 -0
- package/theme/styles/css/color/indigo.css +72 -0
- package/theme/styles/css/color/lime.css +72 -0
- package/theme/styles/css/color/orange.css +72 -0
- package/theme/styles/css/color/pink.css +72 -0
- package/theme/styles/css/color/purple.css +72 -0
- package/theme/styles/css/color/red.css +72 -0
- package/theme/styles/css/color/rose.css +72 -0
- package/theme/styles/css/color/sky.css +72 -0
- package/theme/styles/css/color/teal.css +72 -0
- package/theme/styles/css/color/violet.css +72 -0
- package/theme/styles/css/color/yellow.css +72 -0
- package/theme/styles/css/index.css +18 -0
- package/theme/styles/css/neutral/gray.css +63 -0
- package/theme/styles/css/neutral/index.css +11 -0
- package/theme/styles/css/neutral/mauve.css +63 -0
- package/theme/styles/css/neutral/mist.css +63 -0
- package/theme/styles/css/neutral/neutral.css +63 -0
- package/theme/styles/css/neutral/olive.css +63 -0
- package/theme/styles/css/neutral/slate.css +63 -0
- package/theme/styles/css/neutral/stone.css +63 -0
- package/theme/styles/css/neutral/taupe.css +63 -0
- package/theme/styles/css/neutral/zinc.css +63 -0
- package/theme/styles/css/radius/index.css +30 -0
- package/theme/styles/css/space/index.css +20 -0
- package/types/ojiepermana-angular-chart-area.d.ts +76 -1
- package/types/ojiepermana-angular-chart-bar.d.ts +201 -1
- package/types/ojiepermana-angular-chart-core.d.ts +811 -1
- package/types/ojiepermana-angular-chart-line.d.ts +75 -1
- package/types/ojiepermana-angular-chart-pie.d.ts +131 -1
- package/types/ojiepermana-angular-chart-primitives.d.ts +291 -1
- package/types/ojiepermana-angular-chart-radar.d.ts +116 -1
- package/types/ojiepermana-angular-chart-radial.d.ts +116 -1
- package/types/ojiepermana-angular-chart-scatter.d.ts +125 -1
- package/types/ojiepermana-angular-chart.d.ts +2 -1
- package/types/ojiepermana-angular-component-accordion.d.ts +85 -1
- package/types/ojiepermana-angular-component-alert-dialog.d.ts +140 -1
- package/types/ojiepermana-angular-component-alert.d.ts +42 -1
- package/types/ojiepermana-angular-component-aspect-ratio.d.ts +12 -1
- package/types/ojiepermana-angular-component-avatar.d.ts +56 -1
- package/types/ojiepermana-angular-component-badge.d.ts +24 -1
- package/types/ojiepermana-angular-component-breadcrumb.d.ts +46 -1
- package/types/ojiepermana-angular-component-button-group.d.ts +26 -1
- package/types/ojiepermana-angular-component-button.d.ts +27 -1
- package/types/ojiepermana-angular-component-calendar.d.ts +111 -1
- package/types/ojiepermana-angular-component-card.d.ts +69 -1
- package/types/ojiepermana-angular-component-carousel.d.ts +86 -1
- package/types/ojiepermana-angular-component-checkbox.d.ts +42 -1
- package/types/ojiepermana-angular-component-collapsible.d.ts +42 -1
- package/types/ojiepermana-angular-component-combobox.d.ts +60 -1
- package/types/ojiepermana-angular-component-command.d.ts +130 -1
- package/types/ojiepermana-angular-component-composer.d.ts +90 -1
- package/types/ojiepermana-angular-component-context-menu.d.ts +54 -1
- package/types/ojiepermana-angular-component-date-picker.d.ts +109 -1
- package/types/ojiepermana-angular-component-dialog.d.ts +136 -1
- package/types/ojiepermana-angular-component-drawer.d.ts +1 -1
- package/types/ojiepermana-angular-component-dropdown-menu.d.ts +248 -1
- package/types/ojiepermana-angular-component-editor.d.ts +135 -1
- package/types/ojiepermana-angular-component-empty.d.ts +50 -1
- package/types/ojiepermana-angular-component-form.d.ts +159 -1
- package/types/ojiepermana-angular-component-hover-card.d.ts +75 -1
- package/types/ojiepermana-angular-component-icon.d.ts +89 -1
- package/types/ojiepermana-angular-component-input-group.d.ts +51 -1
- package/types/ojiepermana-angular-component-input-otp.d.ts +155 -1
- package/types/ojiepermana-angular-component-input.d.ts +21 -1
- package/types/ojiepermana-angular-component-item.d.ts +93 -1
- package/types/ojiepermana-angular-component-kanban.d.ts +70 -1
- package/types/ojiepermana-angular-component-kbd.d.ts +16 -1
- package/types/ojiepermana-angular-component-label.d.ts +11 -1
- package/types/ojiepermana-angular-component-menubar.d.ts +93 -1
- package/types/ojiepermana-angular-component-native-select.d.ts +26 -1
- package/types/ojiepermana-angular-component-navigation-menu.d.ts +104 -1
- package/types/ojiepermana-angular-component-pagination.d.ts +33 -1
- package/types/ojiepermana-angular-component-pillbox.d.ts +222 -1
- package/types/ojiepermana-angular-component-popover.d.ts +66 -1
- package/types/ojiepermana-angular-component-progress.d.ts +17 -1
- package/types/ojiepermana-angular-component-radio.d.ts +60 -1
- package/types/ojiepermana-angular-component-resizable.d.ts +117 -1
- package/types/ojiepermana-angular-component-scroll-area.d.ts +19 -1
- package/types/ojiepermana-angular-component-segmented-control.d.ts +58 -1
- package/types/ojiepermana-angular-component-select.d.ts +122 -1
- package/types/ojiepermana-angular-component-separator.d.ts +14 -1
- package/types/ojiepermana-angular-component-sheet.d.ts +130 -1
- package/types/ojiepermana-angular-component-skeleton.d.ts +10 -1
- package/types/ojiepermana-angular-component-slider.d.ts +83 -1
- package/types/ojiepermana-angular-component-spinner.d.ts +13 -1
- package/types/ojiepermana-angular-component-switch.d.ts +44 -1
- package/types/ojiepermana-angular-component-table.d.ts +57 -1
- package/types/ojiepermana-angular-component-tabs.d.ts +124 -1
- package/types/ojiepermana-angular-component-textarea.d.ts +17 -1
- package/types/ojiepermana-angular-component-timeline.d.ts +64 -1
- package/types/ojiepermana-angular-component-toast.d.ts +64 -1
- package/types/ojiepermana-angular-component-toggle-group.d.ts +90 -1
- package/types/ojiepermana-angular-component-toggle.d.ts +25 -1
- package/types/ojiepermana-angular-component-tooltip.d.ts +143 -1
- package/types/ojiepermana-angular-component-utils-core.d.ts +184 -1
- package/types/ojiepermana-angular-component-utils-overlay.d.ts +21 -1
- package/types/ojiepermana-angular-component-utils-scale.d.ts +19 -1
- package/types/ojiepermana-angular-component-utils.d.ts +2 -1
- package/types/ojiepermana-angular-component.d.ts +2 -1
- package/types/ojiepermana-angular-navigation-core.d.ts +59 -1
- package/types/ojiepermana-angular-navigation-icon.d.ts +12 -1
- package/types/ojiepermana-angular-navigation-service.d.ts +116 -1
- package/types/ojiepermana-angular-navigation-types.d.ts +144 -1
- package/types/ojiepermana-angular-navigation.d.ts +507 -1
- package/types/ojiepermana-angular-sdk.d.ts +89 -1
- package/types/ojiepermana-angular-theme-component-settings.d.ts +154 -1
- package/types/ojiepermana-angular-theme-layout-services.d.ts +147 -1
- package/types/ojiepermana-angular-theme-layout-types.d.ts +40 -1
- package/types/ojiepermana-angular-theme-layout-wrapper.d.ts +299 -1
- package/types/ojiepermana-angular-theme-layout.d.ts +129 -1
- package/types/ojiepermana-angular-theme-page-core.d.ts +157 -1
- package/types/ojiepermana-angular-theme-page-filter.d.ts +77 -1
- package/types/ojiepermana-angular-theme-page-root.d.ts +88 -1
- package/types/ojiepermana-angular-theme-page-side.d.ts +50 -1
- package/types/ojiepermana-angular-theme-page-slots.d.ts +40 -1
- package/types/ojiepermana-angular-theme-page.d.ts +5 -1
- package/types/ojiepermana-angular-theme-shell-services.d.ts +193 -1
- package/types/ojiepermana-angular-theme-shell-types.d.ts +105 -1
- package/types/ojiepermana-angular-theme-shell.d.ts +100 -1
- package/types/ojiepermana-angular-theme-styles.d.ts +319 -1
- package/types/ojiepermana-angular-theme.d.ts +2 -1
- package/types/ojiepermana-angular.d.ts +5 -5
|
@@ -1,7 +1,314 @@
|
|
|
1
|
-
|
|
1
|
+
import { clsx } from 'clsx';
|
|
2
|
+
import { twMerge } from 'tailwind-merge';
|
|
3
|
+
import { InjectionToken, inject, APP_ID, signal } from '@angular/core';
|
|
2
4
|
|
|
3
|
-
|
|
5
|
+
function cn(...inputs) {
|
|
6
|
+
return twMerge(clsx(inputs));
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/** Request/application-scoped DOM id generator with deterministic sequencing. */
|
|
10
|
+
class UiIdGenerator {
|
|
11
|
+
counter = 0;
|
|
12
|
+
appInfix;
|
|
13
|
+
constructor(appId = 'ng') {
|
|
14
|
+
const safeAppId = appId.replace(/[^a-zA-Z0-9_-]/g, '');
|
|
15
|
+
this.appInfix = appId === 'ng' || !safeAppId ? '' : `-${safeAppId}`;
|
|
16
|
+
}
|
|
17
|
+
next(prefix) {
|
|
18
|
+
this.counter += 1;
|
|
19
|
+
return `${prefix}${this.appInfix}-${this.counter}`;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* One generator per Angular application injector. Separate SSR requests and a
|
|
24
|
+
* hydrating browser application therefore start from the same deterministic
|
|
25
|
+
* sequence instead of sharing process-global state.
|
|
26
|
+
*/
|
|
27
|
+
const UI_ID_GENERATOR = new InjectionToken('UI_ID_GENERATOR', {
|
|
28
|
+
providedIn: 'root',
|
|
29
|
+
factory: () => new UiIdGenerator(inject(APP_ID)),
|
|
30
|
+
});
|
|
31
|
+
/** Generates an id during component/directive construction. */
|
|
32
|
+
function injectUniqueId(prefix) {
|
|
33
|
+
return inject(UI_ID_GENERATOR).next(prefix);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Roving focus across one horizontal row of items, with at most one open
|
|
38
|
+
* disclosure among them.
|
|
39
|
+
*
|
|
40
|
+
* Shared by `Menubar` and `NavigationMenu`: both walk a single row with the
|
|
41
|
+
* arrow keys plus Home/End, hold exactly one tab stop, and keep at most one
|
|
42
|
+
* panel open. Everything that differs between the two -- roles, ARIA, and what
|
|
43
|
+
* happens to an open panel when focus moves on -- stays in the components.
|
|
44
|
+
*/
|
|
45
|
+
class RovingRow {
|
|
46
|
+
config;
|
|
47
|
+
activeItem = signal(null, /* @ts-ignore */
|
|
48
|
+
...(ngDevMode ? [{ debugName: "activeItem" }] : /* istanbul ignore next */ []));
|
|
49
|
+
open = signal(null, /* @ts-ignore */
|
|
50
|
+
...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
|
|
51
|
+
constructor(config) {
|
|
52
|
+
this.config = config;
|
|
53
|
+
}
|
|
54
|
+
items() {
|
|
55
|
+
return this.config.items();
|
|
56
|
+
}
|
|
57
|
+
enabledItems() {
|
|
58
|
+
return this.items().filter((item) => !item.disabled());
|
|
59
|
+
}
|
|
60
|
+
setActive(item) {
|
|
61
|
+
if (item.disabled()) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
this.activeItem.set(item);
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* The roving `tabindex` for one row item.
|
|
68
|
+
*
|
|
69
|
+
* A composite widget carries exactly one tab stop: normally the active item
|
|
70
|
+
* owns it, falling back to the first enabled one. When EVERY item is disabled
|
|
71
|
+
* there is no enabled candidate, and leaving them all at `-1` drops the whole
|
|
72
|
+
* widget out of the tab order -- it becomes unreachable and a keyboard user
|
|
73
|
+
* cannot even discover that it is there. The first item keeps the tab stop
|
|
74
|
+
* instead and announces its state through `aria-disabled`, which is the APG
|
|
75
|
+
* focusable-disabled-item approach.
|
|
76
|
+
*/
|
|
77
|
+
tabIndexFor(item) {
|
|
78
|
+
const enabledItems = this.enabledItems();
|
|
79
|
+
if (enabledItems.length === 0) {
|
|
80
|
+
return this.items()[0] === item ? 0 : -1;
|
|
81
|
+
}
|
|
82
|
+
if (item.disabled()) {
|
|
83
|
+
return -1;
|
|
84
|
+
}
|
|
85
|
+
const activeItem = this.activeItem();
|
|
86
|
+
const resolvedActiveItem = activeItem && enabledItems.includes(activeItem) ? activeItem : enabledItems[0];
|
|
87
|
+
return resolvedActiveItem === item ? 0 : -1;
|
|
88
|
+
}
|
|
89
|
+
openTrigger() {
|
|
90
|
+
return this.open();
|
|
91
|
+
}
|
|
92
|
+
hasOpenTrigger(except) {
|
|
93
|
+
const currentOpenTrigger = this.open();
|
|
94
|
+
return !!currentOpenTrigger && currentOpenTrigger !== except;
|
|
95
|
+
}
|
|
96
|
+
notifyOpen(trigger) {
|
|
97
|
+
const currentOpenTrigger = this.open();
|
|
98
|
+
if (currentOpenTrigger && currentOpenTrigger !== trigger) {
|
|
99
|
+
currentOpenTrigger.close({ restoreFocus: false });
|
|
100
|
+
}
|
|
101
|
+
this.open.set(trigger);
|
|
102
|
+
this.setActive(trigger);
|
|
103
|
+
}
|
|
104
|
+
notifyClosed(trigger) {
|
|
105
|
+
if (this.open() === trigger) {
|
|
106
|
+
this.open.set(null);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
/** The row item an event came from, or `null` when it came from outside the row. */
|
|
110
|
+
itemFrom(target, scope) {
|
|
111
|
+
const candidates = scope === 'all' ? this.items() : this.enabledItems();
|
|
112
|
+
return candidates.find((item) => item.containsTarget(target)) ?? null;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Handles the keys that walk the row itself -- Home, End and the horizontal
|
|
116
|
+
* arrows -- and reports whether it claimed the event, so a component can add
|
|
117
|
+
* its own keys around this without restating the row model.
|
|
118
|
+
*/
|
|
119
|
+
handleNavigationKey(item, event) {
|
|
120
|
+
if (event.key === 'Home' || event.key === 'End') {
|
|
121
|
+
event.preventDefault();
|
|
122
|
+
this.move(item, event.key === 'Home' ? 'start' : 'end');
|
|
123
|
+
return true;
|
|
124
|
+
}
|
|
125
|
+
if (event.key === 'ArrowRight' || event.key === 'ArrowLeft') {
|
|
126
|
+
event.preventDefault();
|
|
127
|
+
this.move(item, event.key === 'ArrowRight' ? 'next' : 'previous');
|
|
128
|
+
return true;
|
|
129
|
+
}
|
|
130
|
+
return false;
|
|
131
|
+
}
|
|
132
|
+
move(currentItem, direction) {
|
|
133
|
+
const enabledItems = this.enabledItems();
|
|
134
|
+
if (enabledItems.length === 0) {
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
const currentIndex = enabledItems.indexOf(currentItem);
|
|
138
|
+
if (currentIndex === -1) {
|
|
139
|
+
enabledItems[0]?.focus();
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
const nextItem = direction === 'start'
|
|
143
|
+
? enabledItems[0]
|
|
144
|
+
: direction === 'end'
|
|
145
|
+
? enabledItems[enabledItems.length - 1]
|
|
146
|
+
: enabledItems[this.nextIndex(currentIndex, direction === 'next' ? this.horizontalStep() : -this.horizontalStep(), enabledItems.length)];
|
|
147
|
+
if (!nextItem || nextItem === currentItem) {
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
this.config.enter(nextItem);
|
|
151
|
+
}
|
|
152
|
+
nextIndex(currentIndex, delta, length) {
|
|
153
|
+
const rawIndex = currentIndex + delta;
|
|
154
|
+
if (this.config.loop()) {
|
|
155
|
+
return (rawIndex + length) % length;
|
|
156
|
+
}
|
|
157
|
+
return Math.max(0, Math.min(length - 1, rawIndex));
|
|
158
|
+
}
|
|
159
|
+
horizontalStep() {
|
|
160
|
+
return getComputedStyle(this.config.host()).direction === 'rtl' ? -1 : 1;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Per-component corner-radius / spacing-density override helpers.
|
|
166
|
+
*
|
|
167
|
+
* These mirror the global `theme-radius` / `theme-space` preset values from
|
|
168
|
+
* `@ojiepermana/angular/theme` — kept as a local copy so this package stays
|
|
169
|
+
* decoupled from the theme package (see its empty peer/deps on -theme).
|
|
170
|
+
*
|
|
171
|
+
* A component that accepts a `radius` / `density` input binds the resolved value
|
|
172
|
+
* onto its surface element via `[style.--radius-base]` / `[style.--spacing-base]`.
|
|
173
|
+
* Tailwind's `rounded-*` utilities resolve `calc(var(--radius-base) * n)` and the
|
|
174
|
+
* spacing utilities resolve `calc(var(--spacing-base) * n)` (see the theme's
|
|
175
|
+
* `base/tailwind.css` `@theme inline` mapping), so the override rescales that
|
|
176
|
+
* subtree and shadows the global `<html theme-radius|theme-space>` axis. The
|
|
177
|
+
* `'inherit'` preset binds nothing, so the component keeps following the axis.
|
|
178
|
+
*/
|
|
179
|
+
/** Corner-radius presets for a per-component `radius` input. */
|
|
180
|
+
const COMPONENT_RADII = ['inherit', 'none', 'xs', 'sm', 'md', 'xl', 'full'];
|
|
181
|
+
/** Spacing-density presets for a per-component `density` input. */
|
|
182
|
+
const COMPONENT_DENSITIES = ['inherit', 'compact', 'normal', 'relaxed', 'spacious'];
|
|
183
|
+
/**
|
|
184
|
+
* `--radius-base` knob value per preset; mirrors theme `radius/index.css`, which
|
|
185
|
+
* takes Tailwind's stock radius for each name.
|
|
186
|
+
*/
|
|
187
|
+
const RADIUS_BASE_VALUES = {
|
|
188
|
+
none: '0px',
|
|
189
|
+
xs: '0.125rem',
|
|
190
|
+
sm: '0.25rem',
|
|
191
|
+
md: '0.375rem',
|
|
192
|
+
xl: '0.75rem',
|
|
193
|
+
full: 'calc(infinity * 1px)',
|
|
194
|
+
};
|
|
195
|
+
/** `--spacing-base` knob value per preset; mirrors theme `space/index.css`. */
|
|
196
|
+
const DENSITY_BASE_VALUES = {
|
|
197
|
+
compact: '0.2rem',
|
|
198
|
+
normal: '0.25rem',
|
|
199
|
+
relaxed: '0.28rem',
|
|
200
|
+
spacious: '0.32rem',
|
|
201
|
+
};
|
|
202
|
+
/**
|
|
203
|
+
* Resolves a `radius` input to a `--radius-base` value, or `null` to inherit the
|
|
204
|
+
* global axis. Bind the result to the surface host: `[style.--radius-base]`.
|
|
205
|
+
*/
|
|
206
|
+
function radiusBaseValue(radius) {
|
|
207
|
+
return radius === 'inherit' ? null : RADIUS_BASE_VALUES[radius];
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Resolves a `density` input to a `--spacing-base` value, or `null` to inherit
|
|
211
|
+
* the global axis. Bind the result to the surface host: `[style.--spacing-base]`.
|
|
212
|
+
*/
|
|
213
|
+
function densityBaseValue(density) {
|
|
214
|
+
return density === 'inherit' ? null : DENSITY_BASE_VALUES[density];
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
let counter = 0;
|
|
218
|
+
/**
|
|
219
|
+
* Returns a document-unique id with the given prefix, e.g. `uniqueId('Checkbox')`
|
|
220
|
+
* → `"checkbox-1"`. Single shared counter for every component in the library.
|
|
221
|
+
*
|
|
222
|
+
* @deprecated Use `injectUniqueId` or inject `UI_ID_GENERATOR`. This legacy
|
|
223
|
+
* function cannot isolate concurrent server-rendering requests.
|
|
224
|
+
*/
|
|
225
|
+
function uniqueId(prefix) {
|
|
226
|
+
counter += 1;
|
|
227
|
+
return `${prefix}-${counter}`;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* One safe way to touch `localStorage`, for every library that persists a
|
|
232
|
+
* preference.
|
|
233
|
+
*
|
|
234
|
+
* The same "reach localStorage through the document's window, wrap everything in
|
|
235
|
+
* try/catch" block was hand-copied across the theme axes and the navigation
|
|
236
|
+
* persistence unit. Every copy had to get three things right:
|
|
237
|
+
*
|
|
238
|
+
* 1. there may be no document at all (server side rendering),
|
|
239
|
+
* 2. `window.localStorage` can THROW on property access, not just on `getItem`
|
|
240
|
+
* (a blocked or partitioned storage), so the getter itself needs guarding,
|
|
241
|
+
* 3. a quota error on write must never break the caller.
|
|
242
|
+
*
|
|
243
|
+
* This lives in `component/utils/core` rather than in the theme package on
|
|
244
|
+
* purpose: `navigation` also needs it, and navigation must not depend on
|
|
245
|
+
* `theme`, which already depends on navigation. Both already depend on this
|
|
246
|
+
* entry point.
|
|
247
|
+
*/
|
|
248
|
+
/** Shared no-op, used whenever storage cannot be reached at all. */
|
|
249
|
+
const UNAVAILABLE = {
|
|
250
|
+
read: () => null,
|
|
251
|
+
write: () => { },
|
|
252
|
+
remove: () => { },
|
|
253
|
+
};
|
|
254
|
+
/**
|
|
255
|
+
* `localStorage` reached through a document's own window.
|
|
256
|
+
*
|
|
257
|
+
* Resolved lazily on every call and never cached: the property access is the
|
|
258
|
+
* part that can throw, and a storage that is blocked now may be available later
|
|
259
|
+
* (or the other way round).
|
|
260
|
+
*/
|
|
261
|
+
function documentLocalStorage(documentRef) {
|
|
262
|
+
const resolve = () => {
|
|
263
|
+
try {
|
|
264
|
+
return documentRef?.defaultView?.localStorage ?? null;
|
|
265
|
+
}
|
|
266
|
+
catch {
|
|
267
|
+
return null;
|
|
268
|
+
}
|
|
269
|
+
};
|
|
270
|
+
return {
|
|
271
|
+
read: (key) => {
|
|
272
|
+
try {
|
|
273
|
+
return resolve()?.getItem(key) ?? null;
|
|
274
|
+
}
|
|
275
|
+
catch {
|
|
276
|
+
return null;
|
|
277
|
+
}
|
|
278
|
+
},
|
|
279
|
+
write: (key, value) => {
|
|
280
|
+
try {
|
|
281
|
+
resolve()?.setItem(key, value);
|
|
282
|
+
}
|
|
283
|
+
catch {
|
|
284
|
+
// A full or blocked storage must never break the caller: the preference
|
|
285
|
+
// simply does not survive the reload.
|
|
286
|
+
}
|
|
287
|
+
},
|
|
288
|
+
remove: (key) => {
|
|
289
|
+
try {
|
|
290
|
+
resolve()?.removeItem(key);
|
|
291
|
+
}
|
|
292
|
+
catch {
|
|
293
|
+
// Same reasoning as write.
|
|
294
|
+
}
|
|
295
|
+
},
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* `localStorage` from the global scope, for callers that only know whether they
|
|
300
|
+
* are in a browser (the `isPlatformBrowser` flavour) rather than holding a
|
|
301
|
+
* `Document`.
|
|
302
|
+
*/
|
|
303
|
+
function globalLocalStorage(isBrowser) {
|
|
304
|
+
if (!isBrowser) {
|
|
305
|
+
return UNAVAILABLE;
|
|
306
|
+
}
|
|
307
|
+
return documentLocalStorage(typeof document === 'undefined' ? null : document);
|
|
308
|
+
}
|
|
4
309
|
|
|
5
310
|
/**
|
|
6
311
|
* Generated bundle index. Do not edit.
|
|
7
|
-
*/
|
|
312
|
+
*/
|
|
313
|
+
|
|
314
|
+
export { COMPONENT_DENSITIES, COMPONENT_RADII, RovingRow, UI_ID_GENERATOR, UiIdGenerator, cn, densityBaseValue, documentLocalStorage, globalLocalStorage, injectUniqueId, radiusBaseValue, uniqueId };
|
|
@@ -1,7 +1,66 @@
|
|
|
1
|
-
|
|
1
|
+
import { merge } from 'rxjs';
|
|
2
|
+
import { filter } from 'rxjs/operators';
|
|
2
3
|
|
|
3
|
-
|
|
4
|
+
const POSITION_ANCHORS = {
|
|
5
|
+
top: (align) => ({
|
|
6
|
+
originX: align === 'start' ? 'start' : align === 'end' ? 'end' : 'center',
|
|
7
|
+
originY: 'top',
|
|
8
|
+
overlayX: align === 'start' ? 'start' : align === 'end' ? 'end' : 'center',
|
|
9
|
+
overlayY: 'bottom',
|
|
10
|
+
}),
|
|
11
|
+
bottom: (align) => ({
|
|
12
|
+
originX: align === 'start' ? 'start' : align === 'end' ? 'end' : 'center',
|
|
13
|
+
originY: 'bottom',
|
|
14
|
+
overlayX: align === 'start' ? 'start' : align === 'end' ? 'end' : 'center',
|
|
15
|
+
overlayY: 'top',
|
|
16
|
+
}),
|
|
17
|
+
left: (align) => ({
|
|
18
|
+
originX: 'start',
|
|
19
|
+
originY: align === 'start' ? 'top' : align === 'end' ? 'bottom' : 'center',
|
|
20
|
+
overlayX: 'end',
|
|
21
|
+
overlayY: align === 'start' ? 'top' : align === 'end' ? 'bottom' : 'center',
|
|
22
|
+
}),
|
|
23
|
+
right: (align) => ({
|
|
24
|
+
originX: 'end',
|
|
25
|
+
originY: align === 'start' ? 'top' : align === 'end' ? 'bottom' : 'center',
|
|
26
|
+
overlayX: 'start',
|
|
27
|
+
overlayY: align === 'start' ? 'top' : align === 'end' ? 'bottom' : 'center',
|
|
28
|
+
}),
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Builds the CDK `ConnectedPosition` for a shadcn-style `side`/`align`/`sideOffset`
|
|
32
|
+
* triple. Shared by every anchored overlay in the library (popover, tooltip,
|
|
33
|
+
* hover-card, menus, combobox).
|
|
34
|
+
*/
|
|
35
|
+
function connectedPositionFor(side, align, sideOffset) {
|
|
36
|
+
const anchor = POSITION_ANCHORS[side](align);
|
|
37
|
+
if (side === 'top') {
|
|
38
|
+
return { ...anchor, offsetY: -sideOffset };
|
|
39
|
+
}
|
|
40
|
+
if (side === 'bottom') {
|
|
41
|
+
return { ...anchor, offsetY: sideOffset };
|
|
42
|
+
}
|
|
43
|
+
if (side === 'left') {
|
|
44
|
+
return { ...anchor, offsetX: -sideOffset };
|
|
45
|
+
}
|
|
46
|
+
return { ...anchor, offsetX: sideOffset };
|
|
47
|
+
}
|
|
48
|
+
function oppositeSide(side) {
|
|
49
|
+
return side === 'top' ? 'bottom' : side === 'bottom' ? 'top' : side === 'left' ? 'right' : 'left';
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Emits whenever the user dismisses the overlay: pointer down outside (ignoring
|
|
53
|
+
* the origin element so trigger clicks keep toggling), Escape, or detachment.
|
|
54
|
+
* Subscribers decide how to close.
|
|
55
|
+
*/
|
|
56
|
+
function overlayDismissals(overlayRef, origin) {
|
|
57
|
+
return merge(overlayRef
|
|
58
|
+
.outsidePointerEvents()
|
|
59
|
+
.pipe(filter((event) => !origin || !origin.contains(event.target))), overlayRef.keydownEvents().pipe(filter((event) => event.key === 'Escape')), overlayRef.detachments());
|
|
60
|
+
}
|
|
4
61
|
|
|
5
62
|
/**
|
|
6
63
|
* Generated bundle index. Do not edit.
|
|
7
|
-
*/
|
|
64
|
+
*/
|
|
65
|
+
|
|
66
|
+
export { connectedPositionFor, oppositeSide, overlayDismissals };
|
|
@@ -1,7 +1,38 @@
|
|
|
1
|
-
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { input, computed, Directive } from '@angular/core';
|
|
3
|
+
import { radiusBaseValue, densityBaseValue } from '@ojiepermana/angular/component/utils/core';
|
|
2
4
|
|
|
3
|
-
|
|
5
|
+
/**
|
|
6
|
+
* Shared host behavior for the per-component radius and density axes.
|
|
7
|
+
*
|
|
8
|
+
* Components expose the directive inputs through `hostDirectives`, preserving
|
|
9
|
+
* their public `radius`/`density` API while keeping the CSS-variable mapping in
|
|
10
|
+
* one implementation.
|
|
11
|
+
*/
|
|
12
|
+
class ComponentScaleDirective {
|
|
13
|
+
radius = input('inherit', /* @ts-ignore */
|
|
14
|
+
...(ngDevMode ? [{ debugName: "radius" }] : /* istanbul ignore next */ []));
|
|
15
|
+
density = input('inherit', /* @ts-ignore */
|
|
16
|
+
...(ngDevMode ? [{ debugName: "density" }] : /* istanbul ignore next */ []));
|
|
17
|
+
radiusBase = computed(() => radiusBaseValue(this.radius()), /* @ts-ignore */
|
|
18
|
+
...(ngDevMode ? [{ debugName: "radiusBase" }] : /* istanbul ignore next */ []));
|
|
19
|
+
densityBase = computed(() => densityBaseValue(this.density()), /* @ts-ignore */
|
|
20
|
+
...(ngDevMode ? [{ debugName: "densityBase" }] : /* istanbul ignore next */ []));
|
|
21
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: ComponentScaleDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
22
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.1.4", type: ComponentScaleDirective, isStandalone: true, inputs: { radius: { classPropertyName: "radius", publicName: "radius", isSignal: true, isRequired: false, transformFunction: null }, density: { classPropertyName: "density", publicName: "density", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "style.--radius-base": "radiusBase()", "style.--spacing-base": "densityBase()" } }, ngImport: i0 });
|
|
23
|
+
}
|
|
24
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: ComponentScaleDirective, decorators: [{
|
|
25
|
+
type: Directive,
|
|
26
|
+
args: [{
|
|
27
|
+
host: {
|
|
28
|
+
'[style.--radius-base]': 'radiusBase()',
|
|
29
|
+
'[style.--spacing-base]': 'densityBase()',
|
|
30
|
+
},
|
|
31
|
+
}]
|
|
32
|
+
}], propDecorators: { radius: [{ type: i0.Input, args: [{ isSignal: true, alias: "radius", required: false }] }], density: [{ type: i0.Input, args: [{ isSignal: true, alias: "density", required: false }] }] } });
|
|
4
33
|
|
|
5
34
|
/**
|
|
6
35
|
* Generated bundle index. Do not edit.
|
|
7
|
-
*/
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
export { ComponentScaleDirective };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
export * from '@ojiepermana/angular
|
|
1
|
+
export * from '@ojiepermana/angular/component/utils/core';
|
|
2
|
+
export * from '@ojiepermana/angular/component/utils/overlay';
|
|
2
3
|
|
|
3
|
-
|
|
4
|
+
/** @deprecated Prefer the focused `utils/core` or `utils/overlay` entry point. */
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Generated bundle index. Do not edit.
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
export * from '@ojiepermana/angular-component';
|
|
2
|
-
|
|
3
1
|
/*
|
|
4
|
-
* Public API of @ojiepermana/angular/component
|
|
5
|
-
*
|
|
2
|
+
* Public API Surface of @ojiepermana/angular/component
|
|
3
|
+
*
|
|
4
|
+
* Komponen dan utilitas diekspos lewat secondary entry point pada setiap folder
|
|
5
|
+
* di dalam library/component.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
/**
|
|
@@ -1,7 +1,25 @@
|
|
|
1
|
-
|
|
1
|
+
import { InjectionToken, inject } from '@angular/core';
|
|
2
|
+
import { NavigationService } from '@ojiepermana/angular/navigation/service';
|
|
2
3
|
|
|
3
|
-
|
|
4
|
+
/** Override this token to supply a custom state/persistence adapter. */
|
|
5
|
+
const NAVIGATION_ADAPTER = new InjectionToken('NAVIGATION_ADAPTER', {
|
|
6
|
+
providedIn: 'root',
|
|
7
|
+
factory: () => {
|
|
8
|
+
const adapter = inject(NavigationService);
|
|
9
|
+
return adapter;
|
|
10
|
+
},
|
|
11
|
+
});
|
|
12
|
+
/** Override token ini untuk memasok route context dari router/state host lain. */
|
|
13
|
+
const NAVIGATION_ROUTE_CONTEXT_ADAPTER = new InjectionToken('NAVIGATION_ROUTE_CONTEXT_ADAPTER', {
|
|
14
|
+
providedIn: 'root',
|
|
15
|
+
factory: () => {
|
|
16
|
+
const adapter = inject(NavigationService);
|
|
17
|
+
return adapter;
|
|
18
|
+
},
|
|
19
|
+
});
|
|
4
20
|
|
|
5
21
|
/**
|
|
6
22
|
* Generated bundle index. Do not edit.
|
|
7
|
-
*/
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
export { NAVIGATION_ADAPTER, NAVIGATION_ROUTE_CONTEXT_ADAPTER };
|
|
@@ -1,7 +1,24 @@
|
|
|
1
|
-
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { inject, TemplateRef, Directive } from '@angular/core';
|
|
2
3
|
|
|
3
|
-
|
|
4
|
+
class NavigationIconDirective {
|
|
5
|
+
template = inject(TemplateRef);
|
|
6
|
+
static ngTemplateContextGuard(_directive, context) {
|
|
7
|
+
void context;
|
|
8
|
+
return true;
|
|
9
|
+
}
|
|
10
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: NavigationIconDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
11
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.4", type: NavigationIconDirective, isStandalone: true, selector: "ng-template[NavigationIcon]", ngImport: i0 });
|
|
12
|
+
}
|
|
13
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: NavigationIconDirective, decorators: [{
|
|
14
|
+
type: Directive,
|
|
15
|
+
args: [{
|
|
16
|
+
selector: 'ng-template[NavigationIcon]',
|
|
17
|
+
}]
|
|
18
|
+
}] });
|
|
4
19
|
|
|
5
20
|
/**
|
|
6
21
|
* Generated bundle index. Do not edit.
|
|
7
|
-
*/
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
export { NavigationIconDirective };
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { input, computed, isSignal, Component } from '@angular/core';
|
|
3
|
+
import { toSignal, toObservable } from '@angular/core/rxjs-interop';
|
|
4
|
+
import { cn } from '@ojiepermana/angular/component/utils/core';
|
|
5
|
+
import { formatNavigationBadgeCount } from '@ojiepermana/angular/navigation/types';
|
|
6
|
+
import { isObservable, of, switchMap, catchError } from 'rxjs';
|
|
7
|
+
|
|
8
|
+
class NavigationBadgeCountComponent {
|
|
9
|
+
badge = input(null, /* @ts-ignore */
|
|
10
|
+
...(ngDevMode ? [{ debugName: "badge" }] : /* istanbul ignore next */ []));
|
|
11
|
+
class = input('', /* @ts-ignore */
|
|
12
|
+
...(ngDevMode ? [{ debugName: "class" }] : /* istanbul ignore next */ []));
|
|
13
|
+
observableSource = computed(() => {
|
|
14
|
+
const value = this.badge()?.value;
|
|
15
|
+
return isObservable(value) ? value : of(null);
|
|
16
|
+
}, /* @ts-ignore */
|
|
17
|
+
...(ngDevMode ? [{ debugName: "observableSource" }] : /* istanbul ignore next */ []));
|
|
18
|
+
observableValue = toSignal(toObservable(this.observableSource).pipe(switchMap((source) => source.pipe(catchError(() => of(null))))), { initialValue: null });
|
|
19
|
+
rawValue() {
|
|
20
|
+
const value = this.badge()?.value;
|
|
21
|
+
if (isObservable(value)) {
|
|
22
|
+
return this.observableValue();
|
|
23
|
+
}
|
|
24
|
+
if (isSignal(value)) {
|
|
25
|
+
return value();
|
|
26
|
+
}
|
|
27
|
+
if (typeof value === 'function') {
|
|
28
|
+
return value();
|
|
29
|
+
}
|
|
30
|
+
return value;
|
|
31
|
+
}
|
|
32
|
+
resolvedBadge() {
|
|
33
|
+
const value = this.rawValue();
|
|
34
|
+
const count = value === null || value === undefined || !Number.isFinite(value)
|
|
35
|
+
? 0
|
|
36
|
+
: Math.max(Math.trunc(value), 0);
|
|
37
|
+
const display = formatNavigationBadgeCount(count);
|
|
38
|
+
if (display === null) {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
const label = this.badge()?.ariaLabel;
|
|
42
|
+
const accessibleLabel = typeof label === 'function' ? label(count) : label;
|
|
43
|
+
return {
|
|
44
|
+
count,
|
|
45
|
+
display,
|
|
46
|
+
accessibleLabel: accessibleLabel?.trim() || `${count} items`,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
badgeClasses = computed(() => cn('nav-badge inline-flex h-5 min-w-5 items-center justify-center rounded-full bg-destructive px-1 text-xs font-semibold text-destructive-foreground', this.badge()?.classes, this.class()), /* @ts-ignore */
|
|
50
|
+
...(ngDevMode ? [{ debugName: "badgeClasses" }] : /* istanbul ignore next */ []));
|
|
51
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: NavigationBadgeCountComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
52
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.4", type: NavigationBadgeCountComponent, isStandalone: true, selector: "NavigationBadgeCount", inputs: { badge: { classPropertyName: "badge", publicName: "badge", isSignal: true, isRequired: false, transformFunction: null }, class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "contents" }, ngImport: i0, template: `
|
|
53
|
+
@if (resolvedBadge(); as resolved) {
|
|
54
|
+
<span
|
|
55
|
+
role="status"
|
|
56
|
+
aria-atomic="true"
|
|
57
|
+
data-navigation-badge="true"
|
|
58
|
+
[attr.data-navigation-badge-count]="resolved.count"
|
|
59
|
+
[attr.aria-label]="resolved.accessibleLabel"
|
|
60
|
+
[class]="badgeClasses()"
|
|
61
|
+
>
|
|
62
|
+
{{ resolved.display }}
|
|
63
|
+
</span>
|
|
64
|
+
}
|
|
65
|
+
`, isInline: true });
|
|
66
|
+
}
|
|
67
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: NavigationBadgeCountComponent, decorators: [{
|
|
68
|
+
type: Component,
|
|
69
|
+
args: [{
|
|
70
|
+
selector: 'NavigationBadgeCount',
|
|
71
|
+
host: {
|
|
72
|
+
class: 'contents',
|
|
73
|
+
},
|
|
74
|
+
template: `
|
|
75
|
+
@if (resolvedBadge(); as resolved) {
|
|
76
|
+
<span
|
|
77
|
+
role="status"
|
|
78
|
+
aria-atomic="true"
|
|
79
|
+
data-navigation-badge="true"
|
|
80
|
+
[attr.data-navigation-badge-count]="resolved.count"
|
|
81
|
+
[attr.aria-label]="resolved.accessibleLabel"
|
|
82
|
+
[class]="badgeClasses()"
|
|
83
|
+
>
|
|
84
|
+
{{ resolved.display }}
|
|
85
|
+
</span>
|
|
86
|
+
}
|
|
87
|
+
`,
|
|
88
|
+
}]
|
|
89
|
+
}], propDecorators: { badge: [{ type: i0.Input, args: [{ isSignal: true, alias: "badge", required: false }] }], class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
|
|
90
|
+
|
|
91
|
+
export { NavigationBadgeCountComponent };
|