@ojiepermana/angular 22.1.10 → 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
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
# Composer
|
|
2
|
+
|
|
3
|
+
Configurable prompt composer for chat, AI, and message surfaces.
|
|
4
|
+
|
|
5
|
+
This Angular implementation takes conceptual inspiration from Flux Composer, but the API, styling, and composition model follow the shadcn-style patterns already established in this library.
|
|
6
|
+
|
|
7
|
+
## Import
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import {
|
|
11
|
+
ComposerActionsLeadingComponent,
|
|
12
|
+
ComposerActionsTrailingComponent,
|
|
13
|
+
ComposerComponent,
|
|
14
|
+
ComposerFooterComponent,
|
|
15
|
+
ComposerHeaderComponent,
|
|
16
|
+
ComposerInputComponent,
|
|
17
|
+
ComposerTextareaComponent,
|
|
18
|
+
} from '@ojiepermana/angular/component/composer';
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Composition
|
|
22
|
+
|
|
23
|
+
```text
|
|
24
|
+
Composer
|
|
25
|
+
├── ComposerHeader (optional)
|
|
26
|
+
├── ComposerActionsLeading (optional)
|
|
27
|
+
├── textarea[ComposerInput] or ComposerInput
|
|
28
|
+
├── ComposerActionsTrailing (optional)
|
|
29
|
+
└── ComposerFooter (optional)
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Use `textarea[ComposerInput]` when you want native textarea behavior, template-driven forms, or reactive forms.
|
|
33
|
+
Use `ComposerInput` when you want to project a custom rich-text surface or editor shell.
|
|
34
|
+
|
|
35
|
+
## Basic Usage
|
|
36
|
+
|
|
37
|
+
```html
|
|
38
|
+
<form (ngSubmit)="send()">
|
|
39
|
+
<Composer (submitRequested)="send()">
|
|
40
|
+
<textarea
|
|
41
|
+
ComposerInput
|
|
42
|
+
rows="2"
|
|
43
|
+
maxRows="6"
|
|
44
|
+
placeholder="How can I help you today?"
|
|
45
|
+
[(ngModel)]="prompt"
|
|
46
|
+
name="prompt"
|
|
47
|
+
></textarea>
|
|
48
|
+
|
|
49
|
+
<ComposerActionsTrailing>
|
|
50
|
+
<button Button type="submit" size="icon-sm" aria-label="Send prompt">Send</button>
|
|
51
|
+
</ComposerActionsTrailing>
|
|
52
|
+
</Composer>
|
|
53
|
+
</form>
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## With Header
|
|
57
|
+
|
|
58
|
+
Use the header slot for file previews, avatars, upload summaries, or compact context cards.
|
|
59
|
+
|
|
60
|
+
```html
|
|
61
|
+
<Composer>
|
|
62
|
+
<ComposerHeader>
|
|
63
|
+
<div class="flex items-center gap-3 rounded-lg border border-border bg-muted/40 px-3 py-2">
|
|
64
|
+
<img src="/avatar.png" alt="Uploaded file owner" class="size-10 rounded-md object-cover" />
|
|
65
|
+
<div class="min-w-0">
|
|
66
|
+
<p class="truncate text-sm font-medium">profile-shot.png</p>
|
|
67
|
+
<p class="text-xs text-muted-foreground">2.1 MB</p>
|
|
68
|
+
</div>
|
|
69
|
+
</div>
|
|
70
|
+
</ComposerHeader>
|
|
71
|
+
|
|
72
|
+
<textarea ComposerInput rows="2" maxRows="6" placeholder="Ask about this asset..."></textarea>
|
|
73
|
+
|
|
74
|
+
<ComposerActionsTrailing>
|
|
75
|
+
<button Button type="button" size="sm">Send</button>
|
|
76
|
+
</ComposerActionsTrailing>
|
|
77
|
+
</Composer>
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Inline Layout
|
|
81
|
+
|
|
82
|
+
Set `inline` when actions and input should share a compact single-row shell.
|
|
83
|
+
|
|
84
|
+
```html
|
|
85
|
+
<Composer inline submit="enter">
|
|
86
|
+
<ComposerActionsLeading>
|
|
87
|
+
<button Button type="button" variant="ghost" size="icon-sm" aria-label="Add attachment">
|
|
88
|
+
+
|
|
89
|
+
</button>
|
|
90
|
+
</ComposerActionsLeading>
|
|
91
|
+
|
|
92
|
+
<textarea ComposerInput rows="1" maxRows="4" placeholder="Reply..."></textarea>
|
|
93
|
+
|
|
94
|
+
<ComposerActionsTrailing>
|
|
95
|
+
<button Button type="button" variant="secondary" size="icon-sm" aria-label="Voice input">
|
|
96
|
+
Mic
|
|
97
|
+
</button>
|
|
98
|
+
<button Button type="submit" size="icon-sm" aria-label="Send reply">Send</button>
|
|
99
|
+
</ComposerActionsTrailing>
|
|
100
|
+
</Composer>
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Input Variant
|
|
104
|
+
|
|
105
|
+
Set `variant="input"` when the composer should align more closely with the radius and density of other input surfaces.
|
|
106
|
+
|
|
107
|
+
```html
|
|
108
|
+
<Composer variant="input">
|
|
109
|
+
<textarea ComposerInput rows="2" maxRows="5" placeholder="What's on your mind?"></textarea>
|
|
110
|
+
</Composer>
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## Height And Autosize
|
|
114
|
+
|
|
115
|
+
`rows` sets the initial height of the native textarea surface.
|
|
116
|
+
`maxRows` caps autosize growth before the textarea begins scrolling.
|
|
117
|
+
|
|
118
|
+
```html
|
|
119
|
+
<Composer>
|
|
120
|
+
<textarea ComposerInput rows="3" maxRows="8" placeholder="Write a longer prompt..."></textarea>
|
|
121
|
+
</Composer>
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## Submit Behavior
|
|
125
|
+
|
|
126
|
+
By default, keyboard submission uses `cmd-enter`, which means `Cmd+Enter` on macOS and `Ctrl+Enter` on Windows/Linux.
|
|
127
|
+
|
|
128
|
+
Use `submit="enter"` when pressing `Enter` should submit immediately. `Shift+Enter` still inserts a new line.
|
|
129
|
+
|
|
130
|
+
```html
|
|
131
|
+
<Composer submit="enter" (submitRequested)="send()">
|
|
132
|
+
<textarea ComposerInput rows="1" maxRows="4" placeholder="Quick reply..."></textarea>
|
|
133
|
+
</Composer>
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
When `submitForm` stays `true`, the composer also calls the nearest native `form.requestSubmit()` after emitting `submitRequested`.
|
|
137
|
+
|
|
138
|
+
## Rich Text Slot
|
|
139
|
+
|
|
140
|
+
Project a custom editor shell through `ComposerInput` when you want a richer surface without changing the composer container API.
|
|
141
|
+
|
|
142
|
+
```html
|
|
143
|
+
<Composer>
|
|
144
|
+
<ComposerInput>
|
|
145
|
+
<div
|
|
146
|
+
contenteditable="true"
|
|
147
|
+
role="textbox"
|
|
148
|
+
aria-multiline="true"
|
|
149
|
+
class="min-h-20 w-full rounded-sm bg-transparent px-2 py-2 outline-none"
|
|
150
|
+
>
|
|
151
|
+
Draft a richer message...
|
|
152
|
+
</div>
|
|
153
|
+
</ComposerInput>
|
|
154
|
+
|
|
155
|
+
<ComposerActionsLeading>
|
|
156
|
+
<button Button type="button" variant="ghost" size="icon-sm" aria-label="Insert file">+</button>
|
|
157
|
+
</ComposerActionsLeading>
|
|
158
|
+
|
|
159
|
+
<ComposerActionsTrailing>
|
|
160
|
+
<button Button type="button" size="icon-sm" aria-label="Send rich text message">Send</button>
|
|
161
|
+
</ComposerActionsTrailing>
|
|
162
|
+
</Composer>
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
## Disabled And Invalid
|
|
166
|
+
|
|
167
|
+
Use the root inputs for shared composer state.
|
|
168
|
+
|
|
169
|
+
```html
|
|
170
|
+
<Composer [disabled]="isSending" [invalid]="promptInvalid">
|
|
171
|
+
<textarea ComposerInput rows="2" maxRows="6"></textarea>
|
|
172
|
+
</Composer>
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
For native textarea integrations, `aria-invalid` can still be supplied directly on `textarea[ComposerInput]` when state comes from another layer.
|
|
176
|
+
|
|
177
|
+
## API Reference
|
|
178
|
+
|
|
179
|
+
### `ComposerComponent`
|
|
180
|
+
|
|
181
|
+
| Input | Type | Default | Notes |
|
|
182
|
+
| ------------ | ------------------------ | ------------- | --------------------------------------------------------------------- |
|
|
183
|
+
| `variant` | `'default' \| 'input'` | `'default'` | Controls shell radius and density. |
|
|
184
|
+
| `inline` | `boolean` | `false` | Places leading actions, input, and trailing actions in a compact row. |
|
|
185
|
+
| `disabled` | `boolean` | `false` | Applies shared disabled treatment and prevents keyboard submit. |
|
|
186
|
+
| `invalid` | `boolean` | `false` | Applies destructive border and ring treatment. |
|
|
187
|
+
| `submit` | `'cmd-enter' \| 'enter'` | `'cmd-enter'` | Controls keyboard submit behavior. |
|
|
188
|
+
| `submitForm` | `boolean` | `true` | Requests native form submission after `submitRequested`. |
|
|
189
|
+
| `class` | `string` | `''` | Appends classes to the composer host. |
|
|
190
|
+
|
|
191
|
+
### `ComposerComponent` output
|
|
192
|
+
|
|
193
|
+
| Output | Type | Notes |
|
|
194
|
+
| ----------------- | --------------- | --------------------------------------------------------------------- |
|
|
195
|
+
| `submitRequested` | `KeyboardEvent` | Emitted when keyboard submission is triggered from the input surface. |
|
|
196
|
+
|
|
197
|
+
### `ComposerTextareaComponent`
|
|
198
|
+
|
|
199
|
+
| Input | Type | Default | Notes |
|
|
200
|
+
| -------------- | ---------------- | ------- | --------------------------------------------------- |
|
|
201
|
+
| `rows` | `number` | `2` | Initial line count. |
|
|
202
|
+
| `maxRows` | `number \| null` | `null` | Maximum autosize line count before scrolling. |
|
|
203
|
+
| `disabled` | `boolean` | `false` | Disables the textarea even if the root is enabled. |
|
|
204
|
+
| `aria-invalid` | `boolean` | `false` | Applies invalid styling on the textarea input slot. |
|
|
205
|
+
| `class` | `string` | `''` | Appends classes to the textarea host. |
|
|
206
|
+
|
|
207
|
+
### Slot Components
|
|
208
|
+
|
|
209
|
+
`ComposerHeaderComponent`, `ComposerFooterComponent`, `ComposerActionsLeadingComponent`, `ComposerActionsTrailingComponent`, and `ComposerInputComponent` each accept a single `class` input.
|
|
210
|
+
|
|
211
|
+
## Accessibility
|
|
212
|
+
|
|
213
|
+
- Pair `textarea[ComposerInput]` with an accessible label from surrounding copy, `aria-label`, or form-field composition.
|
|
214
|
+
- Give icon-only buttons inside action slots explicit `aria-label` values.
|
|
215
|
+
- Keep meaningful supporting text in `ComposerFooter` or nearby description content.
|
|
216
|
+
- Use `submit="enter"` carefully in multiline experiences so users still understand `Shift+Enter` for a new line.
|
|
217
|
+
- When projecting a custom editor through `ComposerInput`, provide `role="textbox"`, `aria-multiline="true"`, and clear keyboard handling in the editor surface itself.
|
|
218
|
+
|
|
219
|
+
## Keyboard Interactions
|
|
220
|
+
|
|
221
|
+
- `Cmd+Enter` or `Ctrl+Enter` submits by default.
|
|
222
|
+
- `Enter` submits when `submit="enter"`.
|
|
223
|
+
- `Shift+Enter` keeps inserting new lines in `submit="enter"` mode.
|
|
224
|
+
- Standard textarea editing, selection, clipboard, and IME behavior remain native when using `textarea[ComposerInput]`.
|
|
225
|
+
|
|
226
|
+
## Styling And Theming
|
|
227
|
+
|
|
228
|
+
The composer uses the shared `border-input`, `bg-background`, `ring-ring`, `text-foreground`, and `placeholder:text-muted-foreground` tokens.
|
|
229
|
+
|
|
230
|
+
Override layout and density by passing `class` to the root or individual slot components.
|
|
231
|
+
Keep the projected input surface transparent so the composer shell remains the visible boundary.
|
|
232
|
+
|
|
233
|
+
## Angular Notes
|
|
234
|
+
|
|
235
|
+
- `textarea[ComposerInput]` remains a native textarea surface and autosizes without replacing native browser editing behavior.
|
|
236
|
+
- `ComposerInput` is intentionally presentational. It is meant for custom editor projection, not as a built-in rich-text editor.
|
|
237
|
+
- The composer shell is presentational and does not import layout or theme services, which keeps the entrypoint compatible with the library's component-layer rules.
|
|
238
|
+
|
|
239
|
+
## Source Inspiration
|
|
240
|
+
|
|
241
|
+
This component borrows the high-level idea of a structured prompt composer from Flux Composer, but the Angular API, slot names, styling tokens, keyboard behavior contract, and examples are implemented specifically for this library's shadcn-style component system.
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
# Context Menu
|
|
2
|
+
|
|
3
|
+
Displays a menu of actions triggered by a right click. The Angular version maps the
|
|
4
|
+
shadcn `ContextMenuTrigger` to a directive on any focusable host and reuses the
|
|
5
|
+
shared menu primitives from [Dropdown Menu](../dropdown-menu/README.md) for the
|
|
6
|
+
overlay content.
|
|
7
|
+
|
|
8
|
+
## Import
|
|
9
|
+
|
|
10
|
+
```ts
|
|
11
|
+
import { ContextMenuTriggerDirective } from '@ojiepermana/angular/component/context-menu';
|
|
12
|
+
import {
|
|
13
|
+
MenuCheckboxItemComponent,
|
|
14
|
+
MenuContentDirective,
|
|
15
|
+
MenuGroupComponent,
|
|
16
|
+
MenuItemComponent,
|
|
17
|
+
MenuLabelComponent,
|
|
18
|
+
MenuRadioGroupComponent,
|
|
19
|
+
MenuRadioItemComponent,
|
|
20
|
+
MenuSeparatorComponent,
|
|
21
|
+
MenuShortcutComponent,
|
|
22
|
+
MenuSurfaceComponent,
|
|
23
|
+
MenuTriggerDirective,
|
|
24
|
+
} from '@ojiepermana/angular/component/dropdown-menu';
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Composition
|
|
28
|
+
|
|
29
|
+
The Angular composition stays close to shadcn while exposing the root behavior
|
|
30
|
+
through directives and shared menu primitives.
|
|
31
|
+
|
|
32
|
+
```text
|
|
33
|
+
div[ContextMenuTrigger]
|
|
34
|
+
└── ng-template[MenuContent]
|
|
35
|
+
└── MenuSurface
|
|
36
|
+
├── MenuGroup
|
|
37
|
+
│ └── button[MenuItem]
|
|
38
|
+
├── MenuSeparator
|
|
39
|
+
├── button[MenuCheckboxItem]
|
|
40
|
+
├── MenuLabel
|
|
41
|
+
├── MenuRadioGroup
|
|
42
|
+
│ └── button[MenuRadioItem]
|
|
43
|
+
└── button[MenuItem][MenuTrigger]
|
|
44
|
+
└── ng-template[MenuContent]
|
|
45
|
+
└── MenuSurface
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Basic usage
|
|
49
|
+
|
|
50
|
+
Prefer a focusable trigger so pointer users can right-click and keyboard users can
|
|
51
|
+
open the same menu with Shift+F10 or the context-menu key.
|
|
52
|
+
|
|
53
|
+
```html
|
|
54
|
+
<div
|
|
55
|
+
[ContextMenuTrigger]="menu"
|
|
56
|
+
tabindex="0"
|
|
57
|
+
aria-label="Open file actions"
|
|
58
|
+
class="flex h-32 w-full max-w-sm items-center justify-center rounded-xl border border-dashed border-border"
|
|
59
|
+
>
|
|
60
|
+
Right-click here
|
|
61
|
+
</div>
|
|
62
|
+
|
|
63
|
+
<ng-template MenuContent #menu="MenuContent">
|
|
64
|
+
<MenuSurface class="w-56">
|
|
65
|
+
<MenuGroup>
|
|
66
|
+
<button MenuItem>Profile</button>
|
|
67
|
+
<button MenuItem>Billing</button>
|
|
68
|
+
<button MenuItem>Team</button>
|
|
69
|
+
</MenuGroup>
|
|
70
|
+
</MenuSurface>
|
|
71
|
+
</ng-template>
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Common patterns
|
|
75
|
+
|
|
76
|
+
### Browser-style actions
|
|
77
|
+
|
|
78
|
+
Use grouped commands and shortcuts for browser or editor surfaces.
|
|
79
|
+
|
|
80
|
+
```html
|
|
81
|
+
<MenuSurface class="w-60">
|
|
82
|
+
<MenuGroup>
|
|
83
|
+
<button MenuItem>
|
|
84
|
+
Back
|
|
85
|
+
<span MenuShortcut>⌘[</span>
|
|
86
|
+
</button>
|
|
87
|
+
<button MenuItem [disabled]="true">
|
|
88
|
+
Forward
|
|
89
|
+
<span MenuShortcut>⌘]</span>
|
|
90
|
+
</button>
|
|
91
|
+
<button MenuItem>
|
|
92
|
+
Reload
|
|
93
|
+
<span MenuShortcut>⌘R</span>
|
|
94
|
+
</button>
|
|
95
|
+
</MenuGroup>
|
|
96
|
+
</MenuSurface>
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### Nested tools menu
|
|
100
|
+
|
|
101
|
+
Map shadcn `ContextMenuSub` to `MenuTrigger` on a menu item. This keeps submenu
|
|
102
|
+
composition explicit and works with the same overlay primitive used by dropdown menus.
|
|
103
|
+
|
|
104
|
+
```html
|
|
105
|
+
<ng-template MenuContent #moreTools="MenuContent">
|
|
106
|
+
<MenuSurface class="w-48">
|
|
107
|
+
<button MenuItem>Save Page...</button>
|
|
108
|
+
<button MenuItem>Create Shortcut...</button>
|
|
109
|
+
<button MenuItem>Name Window...</button>
|
|
110
|
+
</MenuSurface>
|
|
111
|
+
</ng-template>
|
|
112
|
+
|
|
113
|
+
<MenuSurface class="w-56">
|
|
114
|
+
<button MenuItem [MenuTrigger]="moreTools" side="right" align="start">
|
|
115
|
+
More tools
|
|
116
|
+
<span class="ml-auto text-xs text-muted-foreground">›</span>
|
|
117
|
+
</button>
|
|
118
|
+
</MenuSurface>
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Checkbox rows
|
|
122
|
+
|
|
123
|
+
Use checkbox rows for independent toggles such as browser preferences.
|
|
124
|
+
|
|
125
|
+
```ts
|
|
126
|
+
const showBookmarks = signal(true);
|
|
127
|
+
const showFullUrls = signal(false);
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
```html
|
|
131
|
+
<MenuSurface class="w-56">
|
|
132
|
+
<MenuGroup>
|
|
133
|
+
<button MenuCheckboxItem [(checked)]="showBookmarks">Show bookmarks</button>
|
|
134
|
+
<button MenuCheckboxItem [(checked)]="showFullUrls">Show full URLs</button>
|
|
135
|
+
</MenuGroup>
|
|
136
|
+
</MenuSurface>
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### Radio groups
|
|
140
|
+
|
|
141
|
+
Use `MenuRadioGroup` when the menu exposes an exclusive choice.
|
|
142
|
+
|
|
143
|
+
```ts
|
|
144
|
+
const selectedTheme = signal<'light' | 'dark' | 'system'>('system');
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
```html
|
|
148
|
+
<MenuSurface class="w-56">
|
|
149
|
+
<MenuLabel [inset]="true">Theme</MenuLabel>
|
|
150
|
+
<MenuRadioGroup [(value)]="selectedTheme">
|
|
151
|
+
<button MenuRadioItem value="light">Light</button>
|
|
152
|
+
<button MenuRadioItem value="dark">Dark</button>
|
|
153
|
+
<button MenuRadioItem value="system">System</button>
|
|
154
|
+
</MenuRadioGroup>
|
|
155
|
+
</MenuSurface>
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### Destructive rows
|
|
159
|
+
|
|
160
|
+
Pass `variant="destructive"` when the row should read as irreversible.
|
|
161
|
+
|
|
162
|
+
```html
|
|
163
|
+
<MenuSurface class="w-56">
|
|
164
|
+
<MenuGroup>
|
|
165
|
+
<button MenuItem>Edit</button>
|
|
166
|
+
<button MenuItem>Share</button>
|
|
167
|
+
</MenuGroup>
|
|
168
|
+
<MenuSeparator />
|
|
169
|
+
<MenuGroup>
|
|
170
|
+
<button MenuItem variant="destructive">Delete</button>
|
|
171
|
+
</MenuGroup>
|
|
172
|
+
</MenuSurface>
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### RTL
|
|
176
|
+
|
|
177
|
+
Set `dir="rtl"` on the surface and prefer `side="left"` for nested menus so the
|
|
178
|
+
submenu opens toward the visual start edge.
|
|
179
|
+
|
|
180
|
+
```html
|
|
181
|
+
<ng-template MenuContent #rtlTools="MenuContent">
|
|
182
|
+
<MenuSurface dir="rtl" lang="ar" class="w-44 text-right">
|
|
183
|
+
<button MenuItem>حفظ الصفحة...</button>
|
|
184
|
+
<button MenuItem>إنشاء اختصار...</button>
|
|
185
|
+
</MenuSurface>
|
|
186
|
+
</ng-template>
|
|
187
|
+
|
|
188
|
+
<MenuSurface dir="rtl" lang="ar" class="w-56 text-right">
|
|
189
|
+
<button MenuItem [MenuTrigger]="rtlTools" side="left" align="start">
|
|
190
|
+
المزيد من الأدوات
|
|
191
|
+
<span class="mr-auto text-xs text-muted-foreground">‹</span>
|
|
192
|
+
</button>
|
|
193
|
+
</MenuSurface>
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
## API reference
|
|
197
|
+
|
|
198
|
+
### `[ContextMenuTrigger]`
|
|
199
|
+
|
|
200
|
+
| Input | Type | Default |
|
|
201
|
+
| -------------------- | ---------------------- | ---------- |
|
|
202
|
+
| `ContextMenuTrigger` | `MenuContentDirective` | _required_ |
|
|
203
|
+
| `disabled` | `boolean` | `false` |
|
|
204
|
+
|
|
205
|
+
Output: `openedChange: boolean`
|
|
206
|
+
|
|
207
|
+
Methods:
|
|
208
|
+
|
|
209
|
+
- `openAt(x, y)` opens the projected surface at the given viewport coordinates.
|
|
210
|
+
- `close()` closes the active overlay.
|
|
211
|
+
|
|
212
|
+
### Shared menu parts
|
|
213
|
+
|
|
214
|
+
| Part | Purpose |
|
|
215
|
+
| -------------------------- | ---------------------------------------------------------------------------------------- |
|
|
216
|
+
| `MenuSurface` | Overlay container with roving focus, typeahead, Escape close, and Tab-to-close behavior. |
|
|
217
|
+
| `MenuGroup` | Lightweight grouping wrapper for related rows. |
|
|
218
|
+
| `button[MenuItem]` | Standard command row with optional `variant="destructive"`. |
|
|
219
|
+
| `button[MenuCheckboxItem]` | Toggle row with `[(checked)]` and `role="menuitemcheckbox"`. |
|
|
220
|
+
| `MenuRadioGroup` | Exclusive-selection container with signal-friendly `[(value)]`. |
|
|
221
|
+
| `button[MenuRadioItem]` | Exclusive option row with `role="menuitemradio"`. |
|
|
222
|
+
| `MenuLabel` | Non-interactive label row. |
|
|
223
|
+
| `MenuShortcut` | Right-aligned shortcut hint. |
|
|
224
|
+
| `MenuSeparator` | Visual divider between command groups. |
|
|
225
|
+
|
|
226
|
+
For lower-level behavior details, see the Radix Context Menu API reference:
|
|
227
|
+
<https://www.radix-ui.com/docs/primitives/components/context-menu#api-reference>.
|
|
228
|
+
|
|
229
|
+
## Styling and theming
|
|
230
|
+
|
|
231
|
+
Pass `class` to `MenuSurface`, `MenuGroup`, labels, and items to tune width,
|
|
232
|
+
spacing, alignment, and emphasis. Destructive rows use the shared `destructive` theme
|
|
233
|
+
tokens. Visible dividers and borders follow the shared border tokens rather than the
|
|
234
|
+
current text color.
|
|
235
|
+
|
|
236
|
+
## Accessibility
|
|
237
|
+
|
|
238
|
+
- Make the trigger focusable if keyboard users need access to the menu.
|
|
239
|
+
- Native `contextmenu` is captured and its default prevented.
|
|
240
|
+
- Menu rows expose the expected `menuitem`, `menuitemcheckbox`, and `menuitemradio`
|
|
241
|
+
roles plus `aria-checked` and `aria-disabled` where appropriate.
|
|
242
|
+
- Keep item labels short and descriptive, and avoid placing unrelated interactive
|
|
243
|
+
controls inside a menu row.
|
|
244
|
+
|
|
245
|
+
## Keyboard interactions
|
|
246
|
+
|
|
247
|
+
- Right click opens the menu at the pointer location.
|
|
248
|
+
- Shift+F10 and the context-menu key open the menu at the trigger center when the
|
|
249
|
+
trigger is focusable.
|
|
250
|
+
- Arrow Up and Arrow Down move between enabled items.
|
|
251
|
+
- Home and End jump to the start or end of the list.
|
|
252
|
+
- Typeahead matches row text.
|
|
253
|
+
- Enter and Space activate the focused row.
|
|
254
|
+
- Escape and Tab close the surface.
|
|
255
|
+
|
|
256
|
+
## Angular notes
|
|
257
|
+
|
|
258
|
+
- There is no dedicated `context-menu` root component. The root behavior lives on the
|
|
259
|
+
`[ContextMenuTrigger]` directive plus `ng-template[MenuContent]`.
|
|
260
|
+
- Use signals with `[(checked)]` and `[(value)]` for checkbox and radio rows.
|
|
261
|
+
- Reuse `MenuTrigger` when a submenu is needed.
|
|
262
|
+
- Long-press support depends on the browser firing the native `contextmenu` event.
|
|
263
|
+
|
|
264
|
+
## Source parity
|
|
265
|
+
|
|
266
|
+
This implementation keeps the shadcn information architecture while mapping the trigger
|
|
267
|
+
to Angular directives, submenu behavior to nested `MenuTrigger` composition, and
|
|
268
|
+
checkbox or radio state to signal-friendly APIs.
|