@hypoth-ui/cli 0.0.1 → 0.1.0
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/LICENSE +21 -0
- package/README.md +19 -115
- package/dist/{add-PDBC4JTE.js → add-V5PW73GC.js} +29 -17
- package/dist/{chunk-5LTQ2XVL.js → chunk-27CLUUVC.js} +0 -2
- package/dist/{chunk-YPKFYE45.js → chunk-NWIRSZUQ.js} +6 -13
- package/dist/{chunk-GJ6JOQ3Q.js → chunk-PBK72SJJ.js} +1 -1
- package/dist/{diff-BQEXG7HU.js → diff-776UATCA.js} +2 -2
- package/dist/index.js +5 -5
- package/dist/{init-7AZXYAPJ.js → init-GDU2PW7K.js} +10 -13
- package/dist/{list-X6ZLM2NQ.js → list-XDP5I537.js} +3 -3
- package/package.json +16 -12
- package/registry/components.json +1820 -206
- package/templates/accordion/index.tsx +266 -0
- package/templates/accordion/wc/accordion-content.ts +113 -0
- package/templates/accordion/wc/accordion-item.ts +111 -0
- package/templates/accordion/wc/accordion-trigger.ts +105 -0
- package/templates/accordion/wc/accordion.ts +213 -0
- package/templates/accordion/wc/index.ts +12 -0
- package/templates/alert/index.tsx +177 -0
- package/templates/alert/wc/alert.ts +167 -0
- package/templates/alert/wc/index.ts +1 -0
- package/templates/alert-dialog/index.tsx +360 -0
- package/templates/alert-dialog/wc/alert-dialog-action.ts +43 -0
- package/templates/alert-dialog/wc/alert-dialog-cancel.ts +43 -0
- package/templates/alert-dialog/wc/alert-dialog-content.ts +42 -0
- package/templates/alert-dialog/wc/alert-dialog-description.ts +34 -0
- package/templates/alert-dialog/wc/alert-dialog-footer.ts +25 -0
- package/templates/alert-dialog/wc/alert-dialog-header.ts +25 -0
- package/templates/alert-dialog/wc/alert-dialog-title.ts +34 -0
- package/templates/alert-dialog/wc/alert-dialog-trigger.ts +46 -0
- package/templates/alert-dialog/wc/alert-dialog.ts +302 -0
- package/templates/alert-dialog/wc/index.ts +13 -0
- package/templates/aspect-ratio/index.tsx +50 -0
- package/templates/aspect-ratio/wc/aspect-ratio.ts +78 -0
- package/templates/aspect-ratio/wc/index.ts +5 -0
- package/templates/avatar/avatar-group.tsx +88 -0
- package/templates/avatar/avatar.tsx +124 -0
- package/templates/avatar/index.tsx +33 -0
- package/templates/avatar/wc/avatar-group.ts +112 -0
- package/templates/avatar/wc/avatar.ts +184 -0
- package/templates/avatar/wc/index.ts +5 -0
- package/templates/badge/index.tsx +140 -0
- package/templates/badge/wc/badge.ts +119 -0
- package/templates/badge/wc/index.ts +9 -0
- package/templates/breadcrumb/index.tsx +157 -0
- package/templates/breadcrumb/wc/breadcrumb-item.ts +30 -0
- package/templates/breadcrumb/wc/breadcrumb-link.ts +70 -0
- package/templates/breadcrumb/wc/breadcrumb-list.ts +30 -0
- package/templates/breadcrumb/wc/breadcrumb-page.ts +32 -0
- package/templates/breadcrumb/wc/breadcrumb-separator.ts +31 -0
- package/templates/breadcrumb/wc/breadcrumb.ts +55 -0
- package/templates/breadcrumb/wc/index.ts +10 -0
- package/templates/button/button.tsx +119 -0
- package/templates/button/index.ts +1 -0
- package/templates/button/wc/button.ts +169 -0
- package/templates/calendar/index.tsx +149 -0
- package/templates/calendar/wc/calendar.ts +316 -0
- package/templates/calendar/wc/index.ts +4 -0
- package/templates/card/index.tsx +108 -0
- package/templates/card/wc/card-content.ts +25 -0
- package/templates/card/wc/card-footer.ts +25 -0
- package/templates/card/wc/card-header.ts +25 -0
- package/templates/card/wc/card.ts +43 -0
- package/templates/card/wc/index.ts +8 -0
- package/templates/checkbox/checkbox.tsx +85 -0
- package/templates/checkbox/wc/checkbox.ts +247 -0
- package/templates/collapsible/index.tsx +172 -0
- package/templates/collapsible/wc/collapsible-content.ts +97 -0
- package/templates/collapsible/wc/collapsible-trigger.ts +39 -0
- package/templates/collapsible/wc/collapsible.ts +143 -0
- package/templates/collapsible/wc/index.ts +7 -0
- package/templates/combobox/combobox-content.tsx +141 -0
- package/templates/combobox/combobox-context.ts +36 -0
- package/templates/combobox/combobox-empty.tsx +38 -0
- package/templates/combobox/combobox-input.tsx +159 -0
- package/templates/combobox/combobox-loading.tsx +38 -0
- package/templates/combobox/combobox-option.tsx +99 -0
- package/templates/combobox/combobox-root.tsx +207 -0
- package/templates/combobox/combobox-tag.tsx +62 -0
- package/templates/combobox/index.ts +62 -0
- package/templates/combobox/wc/combobox-content.ts +97 -0
- package/templates/combobox/wc/combobox-input.ts +134 -0
- package/templates/combobox/wc/combobox-option.ts +111 -0
- package/templates/combobox/wc/combobox-tag.ts +103 -0
- package/templates/combobox/wc/combobox.ts +981 -0
- package/templates/combobox/wc/index.ts +5 -0
- package/templates/command/index.tsx +279 -0
- package/templates/command/wc/command-empty.ts +24 -0
- package/templates/command/wc/command-group.ts +60 -0
- package/templates/command/wc/command-input.ts +136 -0
- package/templates/command/wc/command-item.ts +78 -0
- package/templates/command/wc/command-list.ts +103 -0
- package/templates/command/wc/command-loading.ts +24 -0
- package/templates/command/wc/command-separator.ts +23 -0
- package/templates/command/wc/command.ts +176 -0
- package/templates/context-menu/index.tsx +262 -0
- package/templates/context-menu/wc/context-menu-content.ts +41 -0
- package/templates/context-menu/wc/context-menu-item.ts +83 -0
- package/templates/context-menu/wc/context-menu-label.ts +30 -0
- package/templates/context-menu/wc/context-menu-separator.ts +28 -0
- package/templates/context-menu/wc/context-menu.ts +324 -0
- package/templates/context-menu/wc/index.ts +9 -0
- package/templates/data-table/index.tsx +263 -0
- package/templates/data-table/wc/data-table.ts +405 -0
- package/templates/data-table/wc/index.ts +10 -0
- package/templates/date-picker/date-picker-calendar.tsx +352 -0
- package/templates/date-picker/date-picker-content.tsx +121 -0
- package/templates/date-picker/date-picker-context.ts +46 -0
- package/templates/date-picker/date-picker-root.tsx +201 -0
- package/templates/date-picker/date-picker-trigger.tsx +95 -0
- package/templates/date-picker/index.ts +44 -0
- package/templates/date-picker/wc/date-picker-calendar.ts +457 -0
- package/templates/date-picker/wc/date-picker.ts +592 -0
- package/templates/date-picker/wc/date-utils.ts +467 -0
- package/templates/date-picker/wc/index.ts +3 -0
- package/templates/dialog/dialog-close.tsx +57 -0
- package/templates/dialog/dialog-content.tsx +106 -0
- package/templates/dialog/dialog-context.ts +24 -0
- package/templates/dialog/dialog-description.tsx +51 -0
- package/templates/dialog/dialog-root.tsx +104 -0
- package/templates/dialog/dialog-title.tsx +38 -0
- package/templates/dialog/dialog-trigger.tsx +94 -0
- package/templates/dialog/index.ts +52 -0
- package/templates/dialog/wc/dialog-content.ts +59 -0
- package/templates/dialog/wc/dialog-description.ts +58 -0
- package/templates/dialog/wc/dialog-title.ts +56 -0
- package/templates/dialog/wc/dialog.ts +411 -0
- package/templates/drawer/index.tsx +263 -0
- package/templates/drawer/wc/drawer-content.ts +150 -0
- package/templates/drawer/wc/drawer-description.ts +34 -0
- package/templates/drawer/wc/drawer-footer.ts +25 -0
- package/templates/drawer/wc/drawer-header.ts +25 -0
- package/templates/drawer/wc/drawer-title.ts +34 -0
- package/templates/drawer/wc/drawer.ts +348 -0
- package/templates/drawer/wc/index.ts +10 -0
- package/templates/dropdown-menu/index.tsx +454 -0
- package/templates/dropdown-menu/wc/dropdown-menu-checkbox-item.ts +93 -0
- package/templates/dropdown-menu/wc/dropdown-menu-content.ts +43 -0
- package/templates/dropdown-menu/wc/dropdown-menu-item.ts +85 -0
- package/templates/dropdown-menu/wc/dropdown-menu-label.ts +31 -0
- package/templates/dropdown-menu/wc/dropdown-menu-radio-group.ts +80 -0
- package/templates/dropdown-menu/wc/dropdown-menu-radio-item.ts +101 -0
- package/templates/dropdown-menu/wc/dropdown-menu-separator.ts +28 -0
- package/templates/dropdown-menu/wc/dropdown-menu.ts +358 -0
- package/templates/dropdown-menu/wc/index.ts +12 -0
- package/templates/field/field-description.tsx +39 -0
- package/templates/field/field-error.tsx +37 -0
- package/templates/field/field.tsx +46 -0
- package/templates/field/index.ts +4 -0
- package/templates/field/label.tsx +40 -0
- package/templates/field/wc/field-description.ts +42 -0
- package/templates/field/wc/field-error.ts +46 -0
- package/templates/field/wc/field.ts +210 -0
- package/templates/field/wc/label.ts +54 -0
- package/templates/file-upload/file-upload-context.ts +26 -0
- package/templates/file-upload/file-upload-dropzone.tsx +111 -0
- package/templates/file-upload/file-upload-input.tsx +86 -0
- package/templates/file-upload/file-upload-item.tsx +105 -0
- package/templates/file-upload/file-upload-root.tsx +115 -0
- package/templates/file-upload/index.ts +50 -0
- package/templates/file-upload/wc/file-upload.ts +380 -0
- package/templates/file-upload/wc/index.ts +1 -0
- package/templates/hover-card/index.tsx +203 -0
- package/templates/hover-card/wc/hover-card-content.ts +50 -0
- package/templates/hover-card/wc/hover-card.ts +382 -0
- package/templates/hover-card/wc/index.ts +6 -0
- package/templates/icon/icon.tsx +76 -0
- package/templates/icon/wc/icon-adapter.ts +108 -0
- package/templates/icon/wc/icon.ts +161 -0
- package/templates/input/input.tsx +130 -0
- package/templates/input/wc/input.ts +216 -0
- package/templates/layout/app-shell.tsx +177 -0
- package/templates/layout/box.tsx +53 -0
- package/templates/layout/center.tsx +42 -0
- package/templates/layout/container.tsx +43 -0
- package/templates/layout/flow.tsx +83 -0
- package/templates/layout/grid.tsx +79 -0
- package/templates/layout/index.ts +33 -0
- package/templates/layout/inline.tsx +16 -0
- package/templates/layout/page.tsx +43 -0
- package/templates/layout/section.tsx +39 -0
- package/templates/layout/spacer.tsx +30 -0
- package/templates/layout/split.tsx +47 -0
- package/templates/layout/stack.tsx +16 -0
- package/templates/layout/wc/app-shell.ts +58 -0
- package/templates/layout/wc/box.ts +117 -0
- package/templates/layout/wc/center.ts +78 -0
- package/templates/layout/wc/container.ts +77 -0
- package/templates/layout/wc/flow.ts +149 -0
- package/templates/layout/wc/footer.ts +57 -0
- package/templates/layout/wc/grid.ts +142 -0
- package/templates/layout/wc/header.ts +57 -0
- package/templates/layout/wc/index.ts +41 -0
- package/templates/layout/wc/main.ts +46 -0
- package/templates/layout/wc/page.ts +81 -0
- package/templates/layout/wc/section.ts +65 -0
- package/templates/layout/wc/spacer.ts +77 -0
- package/templates/layout/wc/split.ts +94 -0
- package/templates/layout/wc/wrap.ts +93 -0
- package/templates/layout/wrap.tsx +46 -0
- package/templates/link/link.tsx +109 -0
- package/templates/link/wc/link.ts +124 -0
- package/templates/list/index.tsx +55 -0
- package/templates/list/list-item.tsx +117 -0
- package/templates/list/list.tsx +115 -0
- package/templates/list/wc/index.ts +5 -0
- package/templates/list/wc/list-item.ts +127 -0
- package/templates/list/wc/list.ts +114 -0
- package/templates/menu/index.ts +49 -0
- package/templates/menu/menu-content.tsx +109 -0
- package/templates/menu/menu-context.ts +17 -0
- package/templates/menu/menu-item.tsx +108 -0
- package/templates/menu/menu-label.tsx +32 -0
- package/templates/menu/menu-root.tsx +108 -0
- package/templates/menu/menu-separator.tsx +24 -0
- package/templates/menu/menu-trigger.tsx +104 -0
- package/templates/menu/wc/menu-content.ts +67 -0
- package/templates/menu/wc/menu-item.ts +109 -0
- package/templates/menu/wc/menu.ts +449 -0
- package/templates/navigation-menu/index.tsx +328 -0
- package/templates/navigation-menu/wc/index.ts +12 -0
- package/templates/navigation-menu/wc/navigation-menu-content.ts +30 -0
- package/templates/navigation-menu/wc/navigation-menu-indicator.ts +30 -0
- package/templates/navigation-menu/wc/navigation-menu-item.ts +60 -0
- package/templates/navigation-menu/wc/navigation-menu-link.ts +97 -0
- package/templates/navigation-menu/wc/navigation-menu-list.ts +30 -0
- package/templates/navigation-menu/wc/navigation-menu-trigger.ts +110 -0
- package/templates/navigation-menu/wc/navigation-menu-viewport.ts +85 -0
- package/templates/navigation-menu/wc/navigation-menu.ts +272 -0
- package/templates/number-input/index.ts +46 -0
- package/templates/number-input/number-input-context.ts +38 -0
- package/templates/number-input/number-input-decrement.tsx +53 -0
- package/templates/number-input/number-input-field.tsx +93 -0
- package/templates/number-input/number-input-increment.tsx +53 -0
- package/templates/number-input/number-input-root.tsx +137 -0
- package/templates/number-input/wc/index.ts +1 -0
- package/templates/number-input/wc/number-input.ts +283 -0
- package/templates/pagination/index.tsx +198 -0
- package/templates/pagination/wc/index.ts +11 -0
- package/templates/pagination/wc/pagination-content.ts +30 -0
- package/templates/pagination/wc/pagination-ellipsis.ts +28 -0
- package/templates/pagination/wc/pagination-item.ts +30 -0
- package/templates/pagination/wc/pagination-link.ts +76 -0
- package/templates/pagination/wc/pagination-next.ts +69 -0
- package/templates/pagination/wc/pagination-previous.ts +69 -0
- package/templates/pagination/wc/pagination.ts +156 -0
- package/templates/pin-input/index.ts +39 -0
- package/templates/pin-input/pin-input-context.ts +30 -0
- package/templates/pin-input/pin-input-field.tsx +186 -0
- package/templates/pin-input/pin-input-root.tsx +120 -0
- package/templates/pin-input/wc/index.ts +1 -0
- package/templates/pin-input/wc/pin-input.ts +259 -0
- package/templates/popover/popover.tsx +121 -0
- package/templates/popover/wc/popover-content.ts +66 -0
- package/templates/popover/wc/popover.ts +343 -0
- package/templates/progress/index.tsx +117 -0
- package/templates/progress/wc/index.ts +4 -0
- package/templates/progress/wc/progress.ts +174 -0
- package/templates/radio/radio.tsx +43 -0
- package/templates/radio/wc/radio-group.ts +261 -0
- package/templates/radio/wc/radio.ts +145 -0
- package/templates/scroll-area/index.tsx +144 -0
- package/templates/scroll-area/wc/index.ts +8 -0
- package/templates/scroll-area/wc/scroll-area-scrollbar.ts +143 -0
- package/templates/scroll-area/wc/scroll-area-thumb.ts +225 -0
- package/templates/scroll-area/wc/scroll-area-viewport.ts +120 -0
- package/templates/scroll-area/wc/scroll-area.ts +63 -0
- package/templates/select/index.ts +57 -0
- package/templates/select/select-content.tsx +243 -0
- package/templates/select/select-context.ts +30 -0
- package/templates/select/select-group.tsx +53 -0
- package/templates/select/select-label.tsx +34 -0
- package/templates/select/select-option.tsx +97 -0
- package/templates/select/select-root.tsx +153 -0
- package/templates/select/select-separator.tsx +27 -0
- package/templates/select/select-trigger.tsx +112 -0
- package/templates/select/select-value.tsx +48 -0
- package/templates/select/wc/index.ts +6 -0
- package/templates/select/wc/select-content.ts +89 -0
- package/templates/select/wc/select-group.ts +82 -0
- package/templates/select/wc/select-label.ts +49 -0
- package/templates/select/wc/select-option.ts +111 -0
- package/templates/select/wc/select-trigger.ts +101 -0
- package/templates/select/wc/select.ts +840 -0
- package/templates/separator/index.tsx +49 -0
- package/templates/separator/wc/index.ts +5 -0
- package/templates/separator/wc/separator.ts +60 -0
- package/templates/sheet/index.tsx +291 -0
- package/templates/sheet/wc/index.ts +12 -0
- package/templates/sheet/wc/sheet-close.ts +43 -0
- package/templates/sheet/wc/sheet-content.ts +47 -0
- package/templates/sheet/wc/sheet-description.ts +34 -0
- package/templates/sheet/wc/sheet-footer.ts +25 -0
- package/templates/sheet/wc/sheet-header.ts +25 -0
- package/templates/sheet/wc/sheet-overlay.ts +23 -0
- package/templates/sheet/wc/sheet-title.ts +34 -0
- package/templates/sheet/wc/sheet.ts +336 -0
- package/templates/skeleton/index.tsx +131 -0
- package/templates/skeleton/wc/index.ts +10 -0
- package/templates/skeleton/wc/skeleton.ts +107 -0
- package/templates/slider/index.ts +41 -0
- package/templates/slider/slider-context.ts +36 -0
- package/templates/slider/slider-range.tsx +59 -0
- package/templates/slider/slider-root.tsx +166 -0
- package/templates/slider/slider-thumb.tsx +213 -0
- package/templates/slider/slider-track.tsx +113 -0
- package/templates/slider/wc/index.ts +1 -0
- package/templates/slider/wc/slider.ts +465 -0
- package/templates/spinner/spinner.tsx +64 -0
- package/templates/spinner/wc/spinner.ts +70 -0
- package/templates/stepper/index.tsx +230 -0
- package/templates/stepper/wc/index.ts +12 -0
- package/templates/stepper/wc/stepper-content.ts +30 -0
- package/templates/stepper/wc/stepper-description.ts +25 -0
- package/templates/stepper/wc/stepper-indicator.ts +30 -0
- package/templates/stepper/wc/stepper-item.ts +55 -0
- package/templates/stepper/wc/stepper-separator.ts +29 -0
- package/templates/stepper/wc/stepper-title.ts +25 -0
- package/templates/stepper/wc/stepper-trigger.ts +67 -0
- package/templates/stepper/wc/stepper.ts +164 -0
- package/templates/switch/switch.tsx +90 -0
- package/templates/switch/wc/switch.ts +228 -0
- package/templates/table/body.tsx +21 -0
- package/templates/table/cell.tsx +44 -0
- package/templates/table/head.tsx +112 -0
- package/templates/table/header.tsx +21 -0
- package/templates/table/index.tsx +93 -0
- package/templates/table/root.tsx +82 -0
- package/templates/table/row.tsx +36 -0
- package/templates/table/wc/index.ts +9 -0
- package/templates/table/wc/table-body.ts +32 -0
- package/templates/table/wc/table-cell.ts +58 -0
- package/templates/table/wc/table-head.ts +129 -0
- package/templates/table/wc/table-header.ts +32 -0
- package/templates/table/wc/table-row.ts +50 -0
- package/templates/table/wc/table.ts +93 -0
- package/templates/tabs/index.tsx +222 -0
- package/templates/tabs/wc/index.ts +8 -0
- package/templates/tabs/wc/tabs-content.ts +82 -0
- package/templates/tabs/wc/tabs-list.ts +56 -0
- package/templates/tabs/wc/tabs-trigger.ts +136 -0
- package/templates/tabs/wc/tabs.ts +202 -0
- package/templates/tag/index.tsx +186 -0
- package/templates/tag/wc/index.ts +4 -0
- package/templates/tag/wc/tag.ts +166 -0
- package/templates/text/text.tsx +100 -0
- package/templates/text/wc/text.ts +94 -0
- package/templates/textarea/textarea.tsx +134 -0
- package/templates/textarea/wc/textarea.ts +280 -0
- package/templates/time-picker/index.ts +42 -0
- package/templates/time-picker/time-picker-context.ts +28 -0
- package/templates/time-picker/time-picker-root.tsx +113 -0
- package/templates/time-picker/time-picker-segment.tsx +91 -0
- package/templates/time-picker/wc/index.ts +1 -0
- package/templates/time-picker/wc/time-picker.ts +221 -0
- package/templates/toast/index.tsx +71 -0
- package/templates/toast/provider.tsx +228 -0
- package/templates/toast/toast.tsx +142 -0
- package/templates/toast/use-toast.ts +89 -0
- package/templates/toast/wc/index.ts +15 -0
- package/templates/toast/wc/toast-controller.ts +282 -0
- package/templates/toast/wc/toast-provider.ts +161 -0
- package/templates/toast/wc/toast.ts +165 -0
- package/templates/tooltip/tooltip.tsx +62 -0
- package/templates/tooltip/wc/tooltip-content.ts +64 -0
- package/templates/tooltip/wc/tooltip.ts +289 -0
- package/templates/tree/index.tsx +60 -0
- package/templates/tree/tree-item.tsx +131 -0
- package/templates/tree/tree.tsx +138 -0
- package/templates/tree/wc/index.ts +11 -0
- package/templates/tree/wc/tree-item.ts +273 -0
- package/templates/tree/wc/tree-utils.ts +143 -0
- package/templates/tree/wc/tree.ts +139 -0
- package/templates/visually-hidden/visually-hidden.tsx +45 -0
- package/templates/visually-hidden/wc/visually-hidden.ts +64 -0
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DropdownMenuRadioGroup component - container for radio items.
|
|
3
|
+
*
|
|
4
|
+
* @element ds-dropdown-menu-radio-group
|
|
5
|
+
*
|
|
6
|
+
* @slot - Radio items
|
|
7
|
+
*
|
|
8
|
+
* @fires ds:change - Fired when selection changes
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { html } from "lit";
|
|
12
|
+
import { property } from "lit/decorators.js";
|
|
13
|
+
import { DSElement } from "../../base/ds-element.js";
|
|
14
|
+
import { emitEvent } from "../../events/emit.js";
|
|
15
|
+
import { define } from "../../registry/define.js";
|
|
16
|
+
|
|
17
|
+
export class DsDropdownMenuRadioGroup extends DSElement {
|
|
18
|
+
/** Currently selected value */
|
|
19
|
+
@property()
|
|
20
|
+
value = "";
|
|
21
|
+
|
|
22
|
+
override connectedCallback(): void {
|
|
23
|
+
super.connectedCallback();
|
|
24
|
+
|
|
25
|
+
this.setAttribute("role", "group");
|
|
26
|
+
|
|
27
|
+
// Listen for radio item selections
|
|
28
|
+
this.addEventListener("ds:radio-select", this.handleRadioSelect as EventListener);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
override disconnectedCallback(): void {
|
|
32
|
+
super.disconnectedCallback();
|
|
33
|
+
this.removeEventListener("ds:radio-select", this.handleRadioSelect as EventListener);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
private handleRadioSelect = (event: CustomEvent<{ value: string }>): void => {
|
|
37
|
+
event.stopPropagation();
|
|
38
|
+
|
|
39
|
+
const newValue = event.detail.value;
|
|
40
|
+
if (newValue !== this.value) {
|
|
41
|
+
this.value = newValue;
|
|
42
|
+
this.updateRadioItems();
|
|
43
|
+
|
|
44
|
+
emitEvent(this, "ds:change", {
|
|
45
|
+
detail: { value: this.value },
|
|
46
|
+
bubbles: true,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
private updateRadioItems(): void {
|
|
52
|
+
const items = this.querySelectorAll("ds-dropdown-menu-radio-item");
|
|
53
|
+
for (const item of items) {
|
|
54
|
+
const itemValue = item.getAttribute("value");
|
|
55
|
+
if (itemValue === this.value) {
|
|
56
|
+
item.setAttribute("checked", "");
|
|
57
|
+
} else {
|
|
58
|
+
item.removeAttribute("checked");
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
override updated(changedProperties: Map<string, unknown>): void {
|
|
64
|
+
if (changedProperties.has("value")) {
|
|
65
|
+
this.updateRadioItems();
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
override render() {
|
|
70
|
+
return html`<slot></slot>`;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
define("ds-dropdown-menu-radio-group", DsDropdownMenuRadioGroup);
|
|
75
|
+
|
|
76
|
+
declare global {
|
|
77
|
+
interface HTMLElementTagNameMap {
|
|
78
|
+
"ds-dropdown-menu-radio-group": DsDropdownMenuRadioGroup;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DropdownMenuRadioItem component - radio button menu item.
|
|
3
|
+
*
|
|
4
|
+
* @element ds-dropdown-menu-radio-item
|
|
5
|
+
*
|
|
6
|
+
* @slot - Item content
|
|
7
|
+
*
|
|
8
|
+
* @fires ds:radio-select - Fired when item is selected (internal)
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { html } from "lit";
|
|
12
|
+
import { property } from "lit/decorators.js";
|
|
13
|
+
import { DSElement } from "../../base/ds-element.js";
|
|
14
|
+
import { emitEvent } from "../../events/emit.js";
|
|
15
|
+
import { define } from "../../registry/define.js";
|
|
16
|
+
|
|
17
|
+
export class DsDropdownMenuRadioItem extends DSElement {
|
|
18
|
+
/** Value for selection */
|
|
19
|
+
@property()
|
|
20
|
+
value = "";
|
|
21
|
+
|
|
22
|
+
/** Whether the radio is selected */
|
|
23
|
+
@property({ type: Boolean, reflect: true })
|
|
24
|
+
checked = false;
|
|
25
|
+
|
|
26
|
+
/** Disabled state */
|
|
27
|
+
@property({ type: Boolean, reflect: true })
|
|
28
|
+
disabled = false;
|
|
29
|
+
|
|
30
|
+
override connectedCallback(): void {
|
|
31
|
+
super.connectedCallback();
|
|
32
|
+
|
|
33
|
+
this.setAttribute("role", "menuitemradio");
|
|
34
|
+
this.setAttribute("tabindex", "-1");
|
|
35
|
+
this.updateAriaChecked();
|
|
36
|
+
|
|
37
|
+
this.addEventListener("click", this.handleSelect);
|
|
38
|
+
this.addEventListener("keydown", this.handleKeyDown);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
override disconnectedCallback(): void {
|
|
42
|
+
super.disconnectedCallback();
|
|
43
|
+
this.removeEventListener("click", this.handleSelect);
|
|
44
|
+
this.removeEventListener("keydown", this.handleKeyDown);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
private handleSelect = (): void => {
|
|
48
|
+
if (this.disabled || this.checked) return;
|
|
49
|
+
|
|
50
|
+
// Emit internal event for radio group to handle
|
|
51
|
+
emitEvent(this, "ds:radio-select", {
|
|
52
|
+
detail: { value: this.value },
|
|
53
|
+
bubbles: true,
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
// Also emit ds:select for menu to close
|
|
57
|
+
emitEvent(this, "ds:select", {
|
|
58
|
+
detail: { value: this.value },
|
|
59
|
+
bubbles: true,
|
|
60
|
+
});
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
private handleKeyDown = (event: KeyboardEvent): void => {
|
|
64
|
+
if (this.disabled) return;
|
|
65
|
+
|
|
66
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
67
|
+
event.preventDefault();
|
|
68
|
+
this.handleSelect();
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
private updateAriaChecked(): void {
|
|
73
|
+
this.setAttribute("aria-checked", String(this.checked));
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
override updated(changedProperties: Map<string, unknown>): void {
|
|
77
|
+
if (changedProperties.has("disabled")) {
|
|
78
|
+
this.setAttribute("aria-disabled", String(this.disabled));
|
|
79
|
+
}
|
|
80
|
+
if (changedProperties.has("checked")) {
|
|
81
|
+
this.updateAriaChecked();
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
override render() {
|
|
86
|
+
return html`
|
|
87
|
+
<span class="ds-dropdown-menu-radio-item__indicator" aria-hidden="true">
|
|
88
|
+
${this.checked ? "●" : "○"}
|
|
89
|
+
</span>
|
|
90
|
+
<slot></slot>
|
|
91
|
+
`;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
define("ds-dropdown-menu-radio-item", DsDropdownMenuRadioItem);
|
|
96
|
+
|
|
97
|
+
declare global {
|
|
98
|
+
interface HTMLElementTagNameMap {
|
|
99
|
+
"ds-dropdown-menu-radio-item": DsDropdownMenuRadioItem;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DropdownMenuSeparator component - visual divider between menu items.
|
|
3
|
+
*
|
|
4
|
+
* @element ds-dropdown-menu-separator
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { html } from "lit";
|
|
8
|
+
import { DSElement } from "../../base/ds-element.js";
|
|
9
|
+
import { define } from "../../registry/define.js";
|
|
10
|
+
|
|
11
|
+
export class DsDropdownMenuSeparator extends DSElement {
|
|
12
|
+
override connectedCallback(): void {
|
|
13
|
+
super.connectedCallback();
|
|
14
|
+
this.setAttribute("role", "separator");
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
override render() {
|
|
18
|
+
return html``;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
define("ds-dropdown-menu-separator", DsDropdownMenuSeparator);
|
|
23
|
+
|
|
24
|
+
declare global {
|
|
25
|
+
interface HTMLElementTagNameMap {
|
|
26
|
+
"ds-dropdown-menu-separator": DsDropdownMenuSeparator;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DropdownMenu component - action menu with items, separators, and submenus.
|
|
3
|
+
*
|
|
4
|
+
* Implements WAI-ARIA Menu Button pattern with full keyboard navigation.
|
|
5
|
+
*
|
|
6
|
+
* @element ds-dropdown-menu
|
|
7
|
+
*
|
|
8
|
+
* @slot trigger - Button that opens the menu
|
|
9
|
+
* @slot - Menu content (ds-dropdown-menu-content)
|
|
10
|
+
*
|
|
11
|
+
* @fires ds:open - Fired when menu opens
|
|
12
|
+
* @fires ds:close - Fired when menu closes
|
|
13
|
+
* @fires ds:select - Fired when an item is selected
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```html
|
|
17
|
+
* <ds-dropdown-menu>
|
|
18
|
+
* <button slot="trigger">Actions</button>
|
|
19
|
+
* <ds-dropdown-menu-content>
|
|
20
|
+
* <ds-dropdown-menu-label>Actions</ds-dropdown-menu-label>
|
|
21
|
+
* <ds-dropdown-menu-item value="edit">Edit</ds-dropdown-menu-item>
|
|
22
|
+
* <ds-dropdown-menu-item value="copy">Copy</ds-dropdown-menu-item>
|
|
23
|
+
* <ds-dropdown-menu-separator></ds-dropdown-menu-separator>
|
|
24
|
+
* <ds-dropdown-menu-item value="delete" variant="destructive">Delete</ds-dropdown-menu-item>
|
|
25
|
+
* </ds-dropdown-menu-content>
|
|
26
|
+
* </ds-dropdown-menu>
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
import {
|
|
31
|
+
type MenuBehavior,
|
|
32
|
+
type Placement,
|
|
33
|
+
type Presence,
|
|
34
|
+
createMenuBehavior,
|
|
35
|
+
createPresence,
|
|
36
|
+
prefersReducedMotion,
|
|
37
|
+
} from "@hypoth-ui/primitives-dom";
|
|
38
|
+
import { html } from "lit";
|
|
39
|
+
import { property } from "lit/decorators.js";
|
|
40
|
+
import { DSElement } from "../../base/ds-element.js";
|
|
41
|
+
import { StandardEvents, emitEvent } from "../../events/emit.js";
|
|
42
|
+
import { define } from "../../registry/define.js";
|
|
43
|
+
|
|
44
|
+
// Import child components to ensure they're registered
|
|
45
|
+
import type { DsDropdownMenuContent } from "./dropdown-menu-content.js";
|
|
46
|
+
import "./dropdown-menu-content.js";
|
|
47
|
+
import "./dropdown-menu-item.js";
|
|
48
|
+
import "./dropdown-menu-separator.js";
|
|
49
|
+
import "./dropdown-menu-label.js";
|
|
50
|
+
import "./dropdown-menu-checkbox-item.js";
|
|
51
|
+
import "./dropdown-menu-radio-group.js";
|
|
52
|
+
import "./dropdown-menu-radio-item.js";
|
|
53
|
+
|
|
54
|
+
export class DsDropdownMenu extends DSElement {
|
|
55
|
+
/** Whether the menu is open */
|
|
56
|
+
@property({ type: Boolean, reflect: true })
|
|
57
|
+
open = false;
|
|
58
|
+
|
|
59
|
+
/** Placement relative to trigger */
|
|
60
|
+
@property({ type: String, reflect: true })
|
|
61
|
+
placement: Placement = "bottom-start";
|
|
62
|
+
|
|
63
|
+
/** Offset distance from trigger in pixels */
|
|
64
|
+
@property({ type: Number })
|
|
65
|
+
offset = 4;
|
|
66
|
+
|
|
67
|
+
/** Whether to flip placement when near viewport edge */
|
|
68
|
+
@property({ type: Boolean })
|
|
69
|
+
flip = true;
|
|
70
|
+
|
|
71
|
+
/** Whether to animate open/close transitions */
|
|
72
|
+
@property({ type: Boolean })
|
|
73
|
+
animated = true;
|
|
74
|
+
|
|
75
|
+
/** Modal behavior - blocks interaction outside menu */
|
|
76
|
+
@property({ type: Boolean })
|
|
77
|
+
modal = true;
|
|
78
|
+
|
|
79
|
+
private menuBehavior: MenuBehavior | null = null;
|
|
80
|
+
private presence: Presence | null = null;
|
|
81
|
+
private focusFirstOnOpen: "first" | "last" | null = null;
|
|
82
|
+
|
|
83
|
+
override connectedCallback(): void {
|
|
84
|
+
super.connectedCallback();
|
|
85
|
+
|
|
86
|
+
// Listen for trigger interactions
|
|
87
|
+
this.addEventListener("click", this.handleTriggerClick);
|
|
88
|
+
this.addEventListener("keydown", this.handleTriggerKeyDown);
|
|
89
|
+
|
|
90
|
+
// Listen for item selection
|
|
91
|
+
this.addEventListener("ds:select", this.handleItemSelect);
|
|
92
|
+
|
|
93
|
+
// Initialize menu behavior
|
|
94
|
+
this.initMenuBehavior();
|
|
95
|
+
|
|
96
|
+
// Setup after first render
|
|
97
|
+
this.updateComplete.then(() => {
|
|
98
|
+
this.setupTriggerAccessibility();
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
override disconnectedCallback(): void {
|
|
103
|
+
super.disconnectedCallback();
|
|
104
|
+
this.removeEventListener("click", this.handleTriggerClick);
|
|
105
|
+
this.removeEventListener("keydown", this.handleTriggerKeyDown);
|
|
106
|
+
this.removeEventListener("ds:select", this.handleItemSelect);
|
|
107
|
+
this.cleanup();
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Initializes the menu behavior primitive.
|
|
112
|
+
*/
|
|
113
|
+
private initMenuBehavior(): void {
|
|
114
|
+
this.menuBehavior = createMenuBehavior({
|
|
115
|
+
defaultOpen: this.open,
|
|
116
|
+
placement: this.placement,
|
|
117
|
+
offset: this.offset,
|
|
118
|
+
flip: this.flip,
|
|
119
|
+
loop: true,
|
|
120
|
+
onOpenChange: (open) => {
|
|
121
|
+
// Sync state when behavior changes (e.g., from escape or outside click)
|
|
122
|
+
if (!open && this.open) {
|
|
123
|
+
this.handleBehaviorClose();
|
|
124
|
+
}
|
|
125
|
+
},
|
|
126
|
+
onSelect: (value) => {
|
|
127
|
+
emitEvent(this, StandardEvents.SELECT, { detail: { value } });
|
|
128
|
+
},
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
// Set trigger element if one exists
|
|
132
|
+
const trigger = this.querySelector('[slot="trigger"]') as HTMLElement | null;
|
|
133
|
+
if (trigger) {
|
|
134
|
+
this.menuBehavior.setTriggerElement(trigger);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Handles close triggered by the behavior (escape/outside click).
|
|
140
|
+
*/
|
|
141
|
+
private handleBehaviorClose(): void {
|
|
142
|
+
const content = this.querySelector("ds-dropdown-menu-content") as DsDropdownMenuContent | null;
|
|
143
|
+
|
|
144
|
+
if (this.animated && content && !prefersReducedMotion()) {
|
|
145
|
+
this.presence = createPresence({
|
|
146
|
+
onExitComplete: () => {
|
|
147
|
+
this.completeClose();
|
|
148
|
+
},
|
|
149
|
+
});
|
|
150
|
+
this.presence.hide(content);
|
|
151
|
+
} else {
|
|
152
|
+
this.open = false;
|
|
153
|
+
emitEvent(this, StandardEvents.CLOSE);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Opens the menu.
|
|
159
|
+
*/
|
|
160
|
+
public show(): void {
|
|
161
|
+
if (this.open) return;
|
|
162
|
+
|
|
163
|
+
this.open = true;
|
|
164
|
+
this.menuBehavior?.open(this.focusFirstOnOpen ?? "first");
|
|
165
|
+
emitEvent(this, StandardEvents.OPEN);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Closes the menu.
|
|
170
|
+
*/
|
|
171
|
+
public close(): void {
|
|
172
|
+
if (!this.open) return;
|
|
173
|
+
|
|
174
|
+
const content = this.querySelector("ds-dropdown-menu-content") as DsDropdownMenuContent | null;
|
|
175
|
+
|
|
176
|
+
// Close the behavior
|
|
177
|
+
this.menuBehavior?.close();
|
|
178
|
+
|
|
179
|
+
if (this.animated && content && !prefersReducedMotion()) {
|
|
180
|
+
this.presence = createPresence({
|
|
181
|
+
onExitComplete: () => {
|
|
182
|
+
this.completeClose();
|
|
183
|
+
},
|
|
184
|
+
});
|
|
185
|
+
this.presence.hide(content);
|
|
186
|
+
} else {
|
|
187
|
+
this.open = false;
|
|
188
|
+
emitEvent(this, StandardEvents.CLOSE);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
private completeClose(): void {
|
|
193
|
+
this.presence?.destroy();
|
|
194
|
+
this.presence = null;
|
|
195
|
+
this.open = false;
|
|
196
|
+
emitEvent(this, StandardEvents.CLOSE);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
public toggle(): void {
|
|
200
|
+
if (this.open) {
|
|
201
|
+
this.close();
|
|
202
|
+
} else {
|
|
203
|
+
this.show();
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
private handleTriggerClick = (event: Event): void => {
|
|
208
|
+
const target = event.target as HTMLElement;
|
|
209
|
+
const trigger = target.closest('[slot="trigger"]');
|
|
210
|
+
|
|
211
|
+
if (trigger && this.contains(trigger)) {
|
|
212
|
+
event.preventDefault();
|
|
213
|
+
this.menuBehavior?.setTriggerElement(trigger as HTMLElement);
|
|
214
|
+
this.focusFirstOnOpen = "first";
|
|
215
|
+
this.toggle();
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
private handleTriggerKeyDown = (event: KeyboardEvent): void => {
|
|
220
|
+
const target = event.target as HTMLElement;
|
|
221
|
+
const trigger = target.closest('[slot="trigger"]');
|
|
222
|
+
|
|
223
|
+
if (!trigger || !this.contains(trigger)) return;
|
|
224
|
+
|
|
225
|
+
this.menuBehavior?.setTriggerElement(trigger as HTMLElement);
|
|
226
|
+
|
|
227
|
+
switch (event.key) {
|
|
228
|
+
case "Enter":
|
|
229
|
+
case " ":
|
|
230
|
+
event.preventDefault();
|
|
231
|
+
this.focusFirstOnOpen = "first";
|
|
232
|
+
this.toggle();
|
|
233
|
+
break;
|
|
234
|
+
case "ArrowDown":
|
|
235
|
+
event.preventDefault();
|
|
236
|
+
this.focusFirstOnOpen = "first";
|
|
237
|
+
if (!this.open) this.show();
|
|
238
|
+
break;
|
|
239
|
+
case "ArrowUp":
|
|
240
|
+
event.preventDefault();
|
|
241
|
+
this.focusFirstOnOpen = "last";
|
|
242
|
+
if (!this.open) this.show();
|
|
243
|
+
break;
|
|
244
|
+
}
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
private handleItemSelect = (): void => {
|
|
248
|
+
this.close();
|
|
249
|
+
};
|
|
250
|
+
|
|
251
|
+
private setupTriggerAccessibility(): void {
|
|
252
|
+
const trigger = this.querySelector('[slot="trigger"]');
|
|
253
|
+
const content = this.querySelector("ds-dropdown-menu-content");
|
|
254
|
+
|
|
255
|
+
if (trigger && content && this.menuBehavior) {
|
|
256
|
+
this.menuBehavior.setTriggerElement(trigger as HTMLElement);
|
|
257
|
+
|
|
258
|
+
// Apply trigger props from behavior
|
|
259
|
+
const triggerProps = this.menuBehavior.getTriggerProps();
|
|
260
|
+
trigger.setAttribute("aria-haspopup", triggerProps["aria-haspopup"]);
|
|
261
|
+
trigger.setAttribute("aria-expanded", triggerProps["aria-expanded"]);
|
|
262
|
+
trigger.setAttribute("aria-controls", triggerProps["aria-controls"]);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
private updateTriggerAria(): void {
|
|
267
|
+
const trigger = this.querySelector('[slot="trigger"]');
|
|
268
|
+
if (trigger && this.menuBehavior) {
|
|
269
|
+
const triggerProps = this.menuBehavior.getTriggerProps();
|
|
270
|
+
trigger.setAttribute("aria-expanded", triggerProps["aria-expanded"]);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
private registerMenuItems(): void {
|
|
275
|
+
const content = this.querySelector("ds-dropdown-menu-content");
|
|
276
|
+
if (!content || !this.menuBehavior) return;
|
|
277
|
+
|
|
278
|
+
const items = content.querySelectorAll<HTMLElement>(
|
|
279
|
+
"ds-dropdown-menu-item:not([disabled]), ds-dropdown-menu-checkbox-item:not([disabled]), ds-dropdown-menu-radio-item:not([disabled])"
|
|
280
|
+
);
|
|
281
|
+
|
|
282
|
+
items.forEach((item) => {
|
|
283
|
+
this.menuBehavior?.registerItem(item);
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
private cleanup(): void {
|
|
288
|
+
this.menuBehavior?.destroy();
|
|
289
|
+
this.menuBehavior = null;
|
|
290
|
+
this.presence?.destroy();
|
|
291
|
+
this.presence = null;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
override async updated(changedProperties: Map<string, unknown>): Promise<void> {
|
|
295
|
+
super.updated(changedProperties);
|
|
296
|
+
|
|
297
|
+
if (changedProperties.has("open")) {
|
|
298
|
+
this.updateTriggerAria();
|
|
299
|
+
|
|
300
|
+
const content = this.querySelector(
|
|
301
|
+
"ds-dropdown-menu-content"
|
|
302
|
+
) as DsDropdownMenuContent | null;
|
|
303
|
+
|
|
304
|
+
if (this.open) {
|
|
305
|
+
content?.removeAttribute("hidden");
|
|
306
|
+
|
|
307
|
+
if (content) {
|
|
308
|
+
content.dataState = "open";
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
await this.updateComplete;
|
|
312
|
+
|
|
313
|
+
// Register menu items with behavior
|
|
314
|
+
this.registerMenuItems();
|
|
315
|
+
|
|
316
|
+
// Set content element (activates positioning, dismiss layer, roving focus, type-ahead)
|
|
317
|
+
this.menuBehavior?.setContentElement(content);
|
|
318
|
+
} else {
|
|
319
|
+
content?.setAttribute("hidden", "");
|
|
320
|
+
|
|
321
|
+
// Clear content element
|
|
322
|
+
this.menuBehavior?.setContentElement(null);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// Re-create behavior if placement/offset/flip change
|
|
327
|
+
if (
|
|
328
|
+
changedProperties.has("placement") ||
|
|
329
|
+
changedProperties.has("offset") ||
|
|
330
|
+
changedProperties.has("flip")
|
|
331
|
+
) {
|
|
332
|
+
const wasOpen = this.menuBehavior?.state.open;
|
|
333
|
+
this.menuBehavior?.destroy();
|
|
334
|
+
this.initMenuBehavior();
|
|
335
|
+
if (wasOpen) {
|
|
336
|
+
this.menuBehavior?.open();
|
|
337
|
+
const content = this.querySelector("ds-dropdown-menu-content") as HTMLElement | null;
|
|
338
|
+
this.registerMenuItems();
|
|
339
|
+
this.menuBehavior?.setContentElement(content);
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
override render() {
|
|
345
|
+
return html`
|
|
346
|
+
<slot name="trigger"></slot>
|
|
347
|
+
<slot></slot>
|
|
348
|
+
`;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
define("ds-dropdown-menu", DsDropdownMenu);
|
|
353
|
+
|
|
354
|
+
declare global {
|
|
355
|
+
interface HTMLElementTagNameMap {
|
|
356
|
+
"ds-dropdown-menu": DsDropdownMenu;
|
|
357
|
+
}
|
|
358
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DropdownMenu component exports.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export { DsDropdownMenu } from "./dropdown-menu.js";
|
|
6
|
+
export { DsDropdownMenuContent } from "./dropdown-menu-content.js";
|
|
7
|
+
export { DsDropdownMenuItem, type DropdownMenuItemVariant } from "./dropdown-menu-item.js";
|
|
8
|
+
export { DsDropdownMenuSeparator } from "./dropdown-menu-separator.js";
|
|
9
|
+
export { DsDropdownMenuLabel } from "./dropdown-menu-label.js";
|
|
10
|
+
export { DsDropdownMenuCheckboxItem } from "./dropdown-menu-checkbox-item.js";
|
|
11
|
+
export { DsDropdownMenuRadioGroup } from "./dropdown-menu-radio-group.js";
|
|
12
|
+
export { DsDropdownMenuRadioItem } from "./dropdown-menu-radio-item.js";
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type React from "react";
|
|
2
|
+
import { type HTMLAttributes, createElement, forwardRef, useEffect, useRef } from "react";
|
|
3
|
+
|
|
4
|
+
export interface FieldDescriptionProps extends HTMLAttributes<HTMLElement> {
|
|
5
|
+
/** Description content */
|
|
6
|
+
children?: React.ReactNode;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* React wrapper for ds-field-description Web Component.
|
|
11
|
+
* Help text for form fields.
|
|
12
|
+
*/
|
|
13
|
+
export const FieldDescription = forwardRef<HTMLElement, FieldDescriptionProps>(
|
|
14
|
+
(props, forwardedRef) => {
|
|
15
|
+
const { children, className, ...rest } = props;
|
|
16
|
+
|
|
17
|
+
const internalRef = useRef<HTMLElement>(null);
|
|
18
|
+
|
|
19
|
+
useEffect(() => {
|
|
20
|
+
if (typeof forwardedRef === "function") {
|
|
21
|
+
forwardedRef(internalRef.current);
|
|
22
|
+
} else if (forwardedRef) {
|
|
23
|
+
(forwardedRef as React.MutableRefObject<HTMLElement | null>).current = internalRef.current;
|
|
24
|
+
}
|
|
25
|
+
}, [forwardedRef]);
|
|
26
|
+
|
|
27
|
+
return createElement(
|
|
28
|
+
"ds-field-description",
|
|
29
|
+
{
|
|
30
|
+
ref: internalRef,
|
|
31
|
+
class: className,
|
|
32
|
+
...rest,
|
|
33
|
+
},
|
|
34
|
+
children
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
FieldDescription.displayName = "FieldDescription";
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type React from "react";
|
|
2
|
+
import { type HTMLAttributes, createElement, forwardRef, useEffect, useRef } from "react";
|
|
3
|
+
|
|
4
|
+
export interface FieldErrorProps extends HTMLAttributes<HTMLElement> {
|
|
5
|
+
/** Error message content */
|
|
6
|
+
children?: React.ReactNode;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* React wrapper for ds-field-error Web Component.
|
|
11
|
+
* Error message for form fields.
|
|
12
|
+
*/
|
|
13
|
+
export const FieldError = forwardRef<HTMLElement, FieldErrorProps>((props, forwardedRef) => {
|
|
14
|
+
const { children, className, ...rest } = props;
|
|
15
|
+
|
|
16
|
+
const internalRef = useRef<HTMLElement>(null);
|
|
17
|
+
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
if (typeof forwardedRef === "function") {
|
|
20
|
+
forwardedRef(internalRef.current);
|
|
21
|
+
} else if (forwardedRef) {
|
|
22
|
+
(forwardedRef as React.MutableRefObject<HTMLElement | null>).current = internalRef.current;
|
|
23
|
+
}
|
|
24
|
+
}, [forwardedRef]);
|
|
25
|
+
|
|
26
|
+
return createElement(
|
|
27
|
+
"ds-field-error",
|
|
28
|
+
{
|
|
29
|
+
ref: internalRef,
|
|
30
|
+
class: className,
|
|
31
|
+
...rest,
|
|
32
|
+
},
|
|
33
|
+
children
|
|
34
|
+
);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
FieldError.displayName = "FieldError";
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type React from "react";
|
|
2
|
+
import { type HTMLAttributes, createElement, forwardRef, useEffect, useRef } from "react";
|
|
3
|
+
|
|
4
|
+
export interface FieldProps extends HTMLAttributes<HTMLElement> {
|
|
5
|
+
/** Whether the field has an error */
|
|
6
|
+
error?: boolean;
|
|
7
|
+
/** Whether the field is disabled */
|
|
8
|
+
disabled?: boolean;
|
|
9
|
+
/** Whether the field is required */
|
|
10
|
+
required?: boolean;
|
|
11
|
+
/** Field content */
|
|
12
|
+
children?: React.ReactNode;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* React wrapper for ds-field Web Component.
|
|
17
|
+
* Container for form field with label, input, description, and error message.
|
|
18
|
+
*/
|
|
19
|
+
export const Field = forwardRef<HTMLElement, FieldProps>((props, forwardedRef) => {
|
|
20
|
+
const { error = false, disabled = false, required = false, children, className, ...rest } = props;
|
|
21
|
+
|
|
22
|
+
const internalRef = useRef<HTMLElement>(null);
|
|
23
|
+
|
|
24
|
+
useEffect(() => {
|
|
25
|
+
if (typeof forwardedRef === "function") {
|
|
26
|
+
forwardedRef(internalRef.current);
|
|
27
|
+
} else if (forwardedRef) {
|
|
28
|
+
(forwardedRef as React.MutableRefObject<HTMLElement | null>).current = internalRef.current;
|
|
29
|
+
}
|
|
30
|
+
}, [forwardedRef]);
|
|
31
|
+
|
|
32
|
+
return createElement(
|
|
33
|
+
"ds-field",
|
|
34
|
+
{
|
|
35
|
+
ref: internalRef,
|
|
36
|
+
error: error || undefined,
|
|
37
|
+
disabled: disabled || undefined,
|
|
38
|
+
required: required || undefined,
|
|
39
|
+
class: className,
|
|
40
|
+
...rest,
|
|
41
|
+
},
|
|
42
|
+
children
|
|
43
|
+
);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
Field.displayName = "Field";
|