@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,109 @@
|
|
|
1
|
+
import type { AnchorHTMLAttributes, ReactNode } from "react";
|
|
2
|
+
import { createElement, forwardRef, useCallback, useEffect, useRef } from "react";
|
|
3
|
+
import { Slot } from "../primitives/slot.js";
|
|
4
|
+
import type { DsNavigateEventDetail, NavigateEventHandler } from "../types/events.js";
|
|
5
|
+
import type { AsChildProps } from "../types/polymorphic.js";
|
|
6
|
+
import { mergeClassNames } from "../utils/merge-props.js";
|
|
7
|
+
|
|
8
|
+
export type LinkVariant = "default" | "muted" | "underline";
|
|
9
|
+
|
|
10
|
+
export interface LinkProps
|
|
11
|
+
extends Omit<AnchorHTMLAttributes<HTMLAnchorElement>, "href">,
|
|
12
|
+
AsChildProps {
|
|
13
|
+
/** Target URL */
|
|
14
|
+
href: string;
|
|
15
|
+
/** Whether the link opens in a new tab */
|
|
16
|
+
external?: boolean;
|
|
17
|
+
/** Visual variant */
|
|
18
|
+
variant?: LinkVariant;
|
|
19
|
+
/** Handler for ds:navigate event. Can prevent default navigation. */
|
|
20
|
+
onNavigate?: NavigateEventHandler;
|
|
21
|
+
/** Link content */
|
|
22
|
+
children?: ReactNode;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* React wrapper for ds-link Web Component.
|
|
27
|
+
* Provides type-safe props and onNavigate event handler.
|
|
28
|
+
* Supports asChild for Next.js Link integration.
|
|
29
|
+
*/
|
|
30
|
+
export const Link = forwardRef<HTMLElement, LinkProps>((props, forwardedRef) => {
|
|
31
|
+
const {
|
|
32
|
+
href,
|
|
33
|
+
external = false,
|
|
34
|
+
variant = "default",
|
|
35
|
+
onNavigate,
|
|
36
|
+
asChild = false,
|
|
37
|
+
children,
|
|
38
|
+
className,
|
|
39
|
+
...rest
|
|
40
|
+
} = props;
|
|
41
|
+
|
|
42
|
+
const internalRef = useRef<HTMLElement>(null);
|
|
43
|
+
|
|
44
|
+
// Store handler in ref for stable callback reference
|
|
45
|
+
const onNavigateRef = useRef(onNavigate);
|
|
46
|
+
onNavigateRef.current = onNavigate;
|
|
47
|
+
|
|
48
|
+
// Merge refs
|
|
49
|
+
useEffect(() => {
|
|
50
|
+
if (typeof forwardedRef === "function") {
|
|
51
|
+
forwardedRef(internalRef.current);
|
|
52
|
+
} else if (forwardedRef) {
|
|
53
|
+
(forwardedRef as React.MutableRefObject<HTMLElement | null>).current = internalRef.current;
|
|
54
|
+
}
|
|
55
|
+
}, [forwardedRef]);
|
|
56
|
+
|
|
57
|
+
// Stable handler that reads from ref
|
|
58
|
+
const handleNavigate = useCallback((event: Event) => {
|
|
59
|
+
onNavigateRef.current?.(event as CustomEvent<DsNavigateEventDetail>);
|
|
60
|
+
}, []);
|
|
61
|
+
|
|
62
|
+
// Attach ds:navigate event listener - no handler deps needed
|
|
63
|
+
useEffect(() => {
|
|
64
|
+
const element = internalRef.current;
|
|
65
|
+
if (!element) return;
|
|
66
|
+
|
|
67
|
+
element.addEventListener("ds:navigate", handleNavigate);
|
|
68
|
+
return () => element.removeEventListener("ds:navigate", handleNavigate);
|
|
69
|
+
}, [handleNavigate]);
|
|
70
|
+
|
|
71
|
+
// asChild mode: render child with link styling classes
|
|
72
|
+
if (asChild) {
|
|
73
|
+
const linkClasses = mergeClassNames(
|
|
74
|
+
"ds-link",
|
|
75
|
+
`ds-link--${variant}`,
|
|
76
|
+
external && "ds-link--external",
|
|
77
|
+
className
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
return createElement(
|
|
81
|
+
Slot,
|
|
82
|
+
{
|
|
83
|
+
ref: internalRef,
|
|
84
|
+
className: linkClasses,
|
|
85
|
+
...rest,
|
|
86
|
+
},
|
|
87
|
+
children
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Default mode: render ds-link Web Component
|
|
92
|
+
return createElement(
|
|
93
|
+
"ds-link",
|
|
94
|
+
{
|
|
95
|
+
ref: internalRef,
|
|
96
|
+
href,
|
|
97
|
+
external: external || undefined,
|
|
98
|
+
variant,
|
|
99
|
+
class: className,
|
|
100
|
+
...rest,
|
|
101
|
+
},
|
|
102
|
+
children
|
|
103
|
+
);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
Link.displayName = "Link";
|
|
107
|
+
|
|
108
|
+
// Re-export event types for convenience
|
|
109
|
+
export type { DsNavigateEventDetail, NavigateEventHandler };
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { type TemplateResult, html, nothing } from "lit";
|
|
2
|
+
import { property } from "lit/decorators.js";
|
|
3
|
+
import { classMap } from "lit/directives/class-map.js";
|
|
4
|
+
import { DSElement } from "../../base/ds-element.js";
|
|
5
|
+
import { StandardEvents, emitEvent } from "../../events/emit.js";
|
|
6
|
+
import { define } from "../../registry/define.js";
|
|
7
|
+
|
|
8
|
+
export type LinkVariant = "default" | "muted" | "underline";
|
|
9
|
+
|
|
10
|
+
export interface DsNavigateEventDetail {
|
|
11
|
+
href: string;
|
|
12
|
+
external: boolean;
|
|
13
|
+
originalEvent: MouseEvent | KeyboardEvent;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* A link component following WAI-ARIA link pattern.
|
|
18
|
+
*
|
|
19
|
+
* @element ds-link
|
|
20
|
+
* @slot - Default slot for link content
|
|
21
|
+
*
|
|
22
|
+
* @fires ds:navigate - When the link is activated (cancelable)
|
|
23
|
+
*/
|
|
24
|
+
export class DsLink extends DSElement {
|
|
25
|
+
static override styles = [];
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* The URL to navigate to.
|
|
29
|
+
* Required for proper link functionality.
|
|
30
|
+
*/
|
|
31
|
+
@property({ type: String, reflect: true })
|
|
32
|
+
href = "";
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Whether this link opens in a new tab.
|
|
36
|
+
* When true, adds target="_blank" and rel="noopener noreferrer".
|
|
37
|
+
*/
|
|
38
|
+
@property({ type: Boolean, reflect: true })
|
|
39
|
+
external = false;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* The link visual variant.
|
|
43
|
+
*/
|
|
44
|
+
@property({ type: String, reflect: true })
|
|
45
|
+
variant: LinkVariant = "default";
|
|
46
|
+
|
|
47
|
+
private handleClick(event: MouseEvent): void {
|
|
48
|
+
// Emit cancelable ds:navigate event
|
|
49
|
+
const navigateEvent = emitEvent<DsNavigateEventDetail>(this, StandardEvents.NAVIGATE, {
|
|
50
|
+
detail: {
|
|
51
|
+
href: this.href,
|
|
52
|
+
external: this.external,
|
|
53
|
+
originalEvent: event,
|
|
54
|
+
},
|
|
55
|
+
cancelable: true,
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
// If consumer prevented the event, prevent navigation
|
|
59
|
+
if (navigateEvent.defaultPrevented) {
|
|
60
|
+
event.preventDefault();
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
override render(): TemplateResult {
|
|
65
|
+
const classes = {
|
|
66
|
+
"ds-link": true,
|
|
67
|
+
[`ds-link--${this.variant}`]: true,
|
|
68
|
+
"ds-link--external": this.external,
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
// If href is empty, render as span (not a real link)
|
|
72
|
+
if (!this.href) {
|
|
73
|
+
return html`
|
|
74
|
+
<span class=${classMap(classes)}>
|
|
75
|
+
<span class="ds-link__content"><slot></slot></span>
|
|
76
|
+
</span>
|
|
77
|
+
`;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return html`
|
|
81
|
+
<a
|
|
82
|
+
class=${classMap(classes)}
|
|
83
|
+
href=${this.href}
|
|
84
|
+
target=${this.external ? "_blank" : nothing}
|
|
85
|
+
rel=${this.external ? "noopener noreferrer" : nothing}
|
|
86
|
+
@click=${this.handleClick}
|
|
87
|
+
>
|
|
88
|
+
<span class="ds-link__content"><slot></slot></span>
|
|
89
|
+
${this.external ? this.renderExternalIndicator() : nothing}
|
|
90
|
+
</a>
|
|
91
|
+
`;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
private renderExternalIndicator(): TemplateResult {
|
|
95
|
+
return html`
|
|
96
|
+
<span class="ds-link__external-icon" aria-hidden="true">
|
|
97
|
+
<svg
|
|
98
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
99
|
+
viewBox="0 0 24 24"
|
|
100
|
+
fill="none"
|
|
101
|
+
stroke="currentColor"
|
|
102
|
+
stroke-width="2"
|
|
103
|
+
stroke-linecap="round"
|
|
104
|
+
stroke-linejoin="round"
|
|
105
|
+
>
|
|
106
|
+
<path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" />
|
|
107
|
+
<polyline points="15 3 21 3 21 9" />
|
|
108
|
+
<line x1="10" y1="14" x2="21" y2="3" />
|
|
109
|
+
</svg>
|
|
110
|
+
</span>
|
|
111
|
+
<span class="ds-visually-hidden">(opens in new tab)</span>
|
|
112
|
+
`;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Register the component
|
|
117
|
+
define("ds-link", DsLink);
|
|
118
|
+
|
|
119
|
+
// TypeScript declaration for HTML
|
|
120
|
+
declare global {
|
|
121
|
+
interface HTMLElementTagNameMap {
|
|
122
|
+
"ds-link": DsLink;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* List compound component exports
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { ListItem } from "./list-item.js";
|
|
8
|
+
import { ListRoot } from "./list.js";
|
|
9
|
+
|
|
10
|
+
export type { ListRootProps, ListSelectionMode, ListOrientation, ListSize } from "./list.js";
|
|
11
|
+
export type { ListItemProps } from "./list-item.js";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* List compound component for collection display.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```tsx
|
|
18
|
+
* <List selectionMode="single" onSelectionChange={(ids) => console.log(ids)}>
|
|
19
|
+
* <List.Item itemId="1">Item 1</List.Item>
|
|
20
|
+
* <List.Item itemId="2">Item 2</List.Item>
|
|
21
|
+
* <List.Item itemId="3" disabled>Item 3 (disabled)</List.Item>
|
|
22
|
+
* </List>
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export const List = Object.assign(ListRoot, {
|
|
26
|
+
Item: ListItem,
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
export { ListItem };
|
|
30
|
+
|
|
31
|
+
// TypeScript declarations for JSX
|
|
32
|
+
declare global {
|
|
33
|
+
namespace JSX {
|
|
34
|
+
interface IntrinsicElements {
|
|
35
|
+
"ds-list": React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement> & {
|
|
36
|
+
ref?: React.Ref<HTMLElement>;
|
|
37
|
+
"selection-mode"?: string;
|
|
38
|
+
orientation?: string;
|
|
39
|
+
size?: string;
|
|
40
|
+
bordered?: boolean;
|
|
41
|
+
label?: string;
|
|
42
|
+
"onDs-selection-change"?: (event: CustomEvent) => void;
|
|
43
|
+
};
|
|
44
|
+
"ds-list-item": React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement> & {
|
|
45
|
+
ref?: React.Ref<HTMLElement>;
|
|
46
|
+
"item-id"?: string;
|
|
47
|
+
selected?: boolean;
|
|
48
|
+
disabled?: boolean;
|
|
49
|
+
value?: string;
|
|
50
|
+
"onDs-select"?: (event: CustomEvent) => void;
|
|
51
|
+
"onDs-activate"?: (event: CustomEvent) => void;
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
type HTMLAttributes,
|
|
5
|
+
type ReactNode,
|
|
6
|
+
createElement,
|
|
7
|
+
forwardRef,
|
|
8
|
+
useEffect,
|
|
9
|
+
useRef,
|
|
10
|
+
} from "react";
|
|
11
|
+
import "@hypoth-ui/wc";
|
|
12
|
+
|
|
13
|
+
export interface ListItemProps extends Omit<HTMLAttributes<HTMLElement>, "onSelect"> {
|
|
14
|
+
/**
|
|
15
|
+
* Unique item ID.
|
|
16
|
+
*/
|
|
17
|
+
itemId?: string;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Whether item is selected.
|
|
21
|
+
* @default false
|
|
22
|
+
*/
|
|
23
|
+
selected?: boolean;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Whether item is disabled.
|
|
27
|
+
* @default false
|
|
28
|
+
*/
|
|
29
|
+
disabled?: boolean;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Value for identification.
|
|
33
|
+
*/
|
|
34
|
+
value?: string;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Callback when item is selected.
|
|
38
|
+
*/
|
|
39
|
+
onItemSelect?: (itemId: string, value: string, selected: boolean) => void;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Callback when item is activated (Enter/double-click).
|
|
43
|
+
*/
|
|
44
|
+
onActivate?: (itemId: string, value: string) => void;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Item content.
|
|
48
|
+
*/
|
|
49
|
+
children?: ReactNode;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* List item component for collection items.
|
|
54
|
+
*/
|
|
55
|
+
export const ListItem = forwardRef<HTMLElement, ListItemProps>(function ListItem(
|
|
56
|
+
{
|
|
57
|
+
itemId,
|
|
58
|
+
selected = false,
|
|
59
|
+
disabled = false,
|
|
60
|
+
value,
|
|
61
|
+
onItemSelect,
|
|
62
|
+
onActivate,
|
|
63
|
+
children,
|
|
64
|
+
className,
|
|
65
|
+
...props
|
|
66
|
+
},
|
|
67
|
+
forwardedRef
|
|
68
|
+
) {
|
|
69
|
+
const internalRef = useRef<HTMLElement>(null);
|
|
70
|
+
|
|
71
|
+
// Sync forwarded ref
|
|
72
|
+
useEffect(() => {
|
|
73
|
+
if (typeof forwardedRef === "function") {
|
|
74
|
+
forwardedRef(internalRef.current);
|
|
75
|
+
} else if (forwardedRef) {
|
|
76
|
+
(forwardedRef as React.MutableRefObject<HTMLElement | null>).current = internalRef.current;
|
|
77
|
+
}
|
|
78
|
+
}, [forwardedRef]);
|
|
79
|
+
|
|
80
|
+
// Set up event listeners
|
|
81
|
+
useEffect(() => {
|
|
82
|
+
const element = internalRef.current;
|
|
83
|
+
if (!element) return;
|
|
84
|
+
|
|
85
|
+
const handleSelect = (e: Event) => {
|
|
86
|
+
const event = e as CustomEvent<{ itemId: string; value: string; selected: boolean }>;
|
|
87
|
+
onItemSelect?.(event.detail.itemId, event.detail.value, event.detail.selected);
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
const handleActivate = (e: Event) => {
|
|
91
|
+
const event = e as CustomEvent<{ itemId: string; value: string }>;
|
|
92
|
+
onActivate?.(event.detail.itemId, event.detail.value);
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
element.addEventListener("ds:select", handleSelect);
|
|
96
|
+
element.addEventListener("ds:activate", handleActivate);
|
|
97
|
+
|
|
98
|
+
return () => {
|
|
99
|
+
element.removeEventListener("ds:select", handleSelect);
|
|
100
|
+
element.removeEventListener("ds:activate", handleActivate);
|
|
101
|
+
};
|
|
102
|
+
}, [onItemSelect, onActivate]);
|
|
103
|
+
|
|
104
|
+
return createElement(
|
|
105
|
+
"ds-list-item",
|
|
106
|
+
{
|
|
107
|
+
ref: internalRef,
|
|
108
|
+
"item-id": itemId,
|
|
109
|
+
selected: selected || undefined,
|
|
110
|
+
disabled: disabled || undefined,
|
|
111
|
+
value,
|
|
112
|
+
class: className,
|
|
113
|
+
...props,
|
|
114
|
+
},
|
|
115
|
+
children
|
|
116
|
+
);
|
|
117
|
+
});
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
type HTMLAttributes,
|
|
5
|
+
type ReactNode,
|
|
6
|
+
createElement,
|
|
7
|
+
forwardRef,
|
|
8
|
+
useEffect,
|
|
9
|
+
useRef,
|
|
10
|
+
} from "react";
|
|
11
|
+
import "@hypoth-ui/wc";
|
|
12
|
+
|
|
13
|
+
export type ListSelectionMode = "single" | "multiple" | "none";
|
|
14
|
+
export type ListOrientation = "vertical" | "horizontal";
|
|
15
|
+
export type ListSize = "default" | "compact" | "spacious";
|
|
16
|
+
|
|
17
|
+
export interface ListRootProps extends HTMLAttributes<HTMLElement> {
|
|
18
|
+
/**
|
|
19
|
+
* Selection mode.
|
|
20
|
+
* @default "single"
|
|
21
|
+
*/
|
|
22
|
+
selectionMode?: ListSelectionMode;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* List orientation.
|
|
26
|
+
* @default "vertical"
|
|
27
|
+
*/
|
|
28
|
+
orientation?: ListOrientation;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Size variant.
|
|
32
|
+
* @default "default"
|
|
33
|
+
*/
|
|
34
|
+
size?: ListSize;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Show border around list.
|
|
38
|
+
* @default false
|
|
39
|
+
*/
|
|
40
|
+
bordered?: boolean;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Accessible label.
|
|
44
|
+
* @default "List"
|
|
45
|
+
*/
|
|
46
|
+
label?: string;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Callback when selection changes.
|
|
50
|
+
*/
|
|
51
|
+
onSelectionChange?: (selectedItems: string[]) => void;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* List content (ListItem elements).
|
|
55
|
+
*/
|
|
56
|
+
children?: ReactNode;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* List root component for collection display.
|
|
61
|
+
*/
|
|
62
|
+
export const ListRoot = forwardRef<HTMLElement, ListRootProps>(function ListRoot(
|
|
63
|
+
{
|
|
64
|
+
selectionMode = "single",
|
|
65
|
+
orientation = "vertical",
|
|
66
|
+
size = "default",
|
|
67
|
+
bordered = false,
|
|
68
|
+
label = "List",
|
|
69
|
+
onSelectionChange,
|
|
70
|
+
children,
|
|
71
|
+
className,
|
|
72
|
+
...props
|
|
73
|
+
},
|
|
74
|
+
forwardedRef
|
|
75
|
+
) {
|
|
76
|
+
const internalRef = useRef<HTMLElement>(null);
|
|
77
|
+
|
|
78
|
+
// Sync forwarded ref
|
|
79
|
+
useEffect(() => {
|
|
80
|
+
if (typeof forwardedRef === "function") {
|
|
81
|
+
forwardedRef(internalRef.current);
|
|
82
|
+
} else if (forwardedRef) {
|
|
83
|
+
(forwardedRef as React.MutableRefObject<HTMLElement | null>).current = internalRef.current;
|
|
84
|
+
}
|
|
85
|
+
}, [forwardedRef]);
|
|
86
|
+
|
|
87
|
+
// Set up event listeners
|
|
88
|
+
useEffect(() => {
|
|
89
|
+
const element = internalRef.current;
|
|
90
|
+
if (!element) return;
|
|
91
|
+
|
|
92
|
+
const handleSelectionChange = (e: Event) => {
|
|
93
|
+
const event = e as CustomEvent<{ selectedItems: string[] }>;
|
|
94
|
+
onSelectionChange?.(event.detail.selectedItems);
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
element.addEventListener("ds:selection-change", handleSelectionChange);
|
|
98
|
+
return () => element.removeEventListener("ds:selection-change", handleSelectionChange);
|
|
99
|
+
}, [onSelectionChange]);
|
|
100
|
+
|
|
101
|
+
return createElement(
|
|
102
|
+
"ds-list",
|
|
103
|
+
{
|
|
104
|
+
ref: internalRef,
|
|
105
|
+
"selection-mode": selectionMode,
|
|
106
|
+
orientation,
|
|
107
|
+
size,
|
|
108
|
+
bordered: bordered || undefined,
|
|
109
|
+
label,
|
|
110
|
+
class: className,
|
|
111
|
+
...props,
|
|
112
|
+
},
|
|
113
|
+
children
|
|
114
|
+
);
|
|
115
|
+
});
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { type TemplateResult, html, nothing } from "lit";
|
|
2
|
+
import { property } from "lit/decorators.js";
|
|
3
|
+
import { classMap } from "lit/directives/class-map.js";
|
|
4
|
+
import { DSElement } from "../../base/ds-element.js";
|
|
5
|
+
import { emitEvent } from "../../events/emit.js";
|
|
6
|
+
import { define } from "../../registry/define.js";
|
|
7
|
+
import type { DsList } from "./list.js";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* List item component for collection items.
|
|
11
|
+
*
|
|
12
|
+
* @element ds-list-item
|
|
13
|
+
*
|
|
14
|
+
* @slot - Item content
|
|
15
|
+
* @slot leading - Optional leading element (icon, avatar)
|
|
16
|
+
* @slot secondary - Optional secondary text
|
|
17
|
+
* @slot trailing - Optional trailing element (action, badge)
|
|
18
|
+
*
|
|
19
|
+
* @fires ds-select - When item is selected
|
|
20
|
+
* @fires ds-activate - When item is activated (Enter/double-click)
|
|
21
|
+
*/
|
|
22
|
+
export class DsListItem extends DSElement {
|
|
23
|
+
static override styles = [];
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Unique item ID.
|
|
27
|
+
*/
|
|
28
|
+
@property({ type: String, attribute: "item-id" })
|
|
29
|
+
itemId = "";
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Whether item is selected.
|
|
33
|
+
*/
|
|
34
|
+
@property({ type: Boolean, reflect: true })
|
|
35
|
+
selected = false;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Whether item is disabled.
|
|
39
|
+
*/
|
|
40
|
+
@property({ type: Boolean, reflect: true })
|
|
41
|
+
disabled = false;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Value for identification.
|
|
45
|
+
*/
|
|
46
|
+
@property({ type: String })
|
|
47
|
+
value = "";
|
|
48
|
+
|
|
49
|
+
private get listRoot(): DsList | null {
|
|
50
|
+
return this.closest("ds-list") as DsList | null;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
private handleClick(): void {
|
|
54
|
+
if (this.disabled) return;
|
|
55
|
+
|
|
56
|
+
const list = this.listRoot;
|
|
57
|
+
if (list) {
|
|
58
|
+
list.handleItemSelect(this.itemId || this.value);
|
|
59
|
+
this.selected = list.isItemSelected(this.itemId || this.value);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
emitEvent(this, "select", {
|
|
63
|
+
detail: {
|
|
64
|
+
itemId: this.itemId,
|
|
65
|
+
value: this.value,
|
|
66
|
+
selected: this.selected,
|
|
67
|
+
},
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
private handleKeyDown(event: KeyboardEvent): void {
|
|
72
|
+
if (this.disabled) return;
|
|
73
|
+
|
|
74
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
75
|
+
event.preventDefault();
|
|
76
|
+
this.handleClick();
|
|
77
|
+
|
|
78
|
+
if (event.key === "Enter") {
|
|
79
|
+
emitEvent(this, "activate", {
|
|
80
|
+
detail: {
|
|
81
|
+
itemId: this.itemId,
|
|
82
|
+
value: this.value,
|
|
83
|
+
},
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
override render(): TemplateResult {
|
|
90
|
+
const classes = {
|
|
91
|
+
"ds-list-item": true,
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
return html`
|
|
95
|
+
<li
|
|
96
|
+
class=${classMap(classes)}
|
|
97
|
+
role="option"
|
|
98
|
+
tabindex=${this.disabled ? -1 : 0}
|
|
99
|
+
aria-selected=${this.selected ? "true" : "false"}
|
|
100
|
+
?data-selected=${this.selected}
|
|
101
|
+
?data-disabled=${this.disabled}
|
|
102
|
+
aria-disabled=${this.disabled ? "true" : nothing}
|
|
103
|
+
@click=${this.handleClick}
|
|
104
|
+
@keydown=${this.handleKeyDown}
|
|
105
|
+
>
|
|
106
|
+
<slot name="leading"></slot>
|
|
107
|
+
<div class="ds-list-item__content">
|
|
108
|
+
<span class="ds-list-item__primary">
|
|
109
|
+
<slot></slot>
|
|
110
|
+
</span>
|
|
111
|
+
<slot name="secondary"></slot>
|
|
112
|
+
</div>
|
|
113
|
+
<slot name="trailing"></slot>
|
|
114
|
+
</li>
|
|
115
|
+
`;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Register the component
|
|
120
|
+
define("ds-list-item", DsListItem);
|
|
121
|
+
|
|
122
|
+
// TypeScript declaration for HTML
|
|
123
|
+
declare global {
|
|
124
|
+
interface HTMLElementTagNameMap {
|
|
125
|
+
"ds-list-item": DsListItem;
|
|
126
|
+
}
|
|
127
|
+
}
|