@hypoth-ui/cli 0.0.1 → 0.1.1
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,62 @@
|
|
|
1
|
+
import type React from "react";
|
|
2
|
+
import { type HTMLAttributes, createElement, forwardRef, useEffect, useRef } from "react";
|
|
3
|
+
import type { Placement } from "./popover.js";
|
|
4
|
+
|
|
5
|
+
export interface TooltipProps extends HTMLAttributes<HTMLElement> {
|
|
6
|
+
/** Whether the tooltip is open */
|
|
7
|
+
open?: boolean;
|
|
8
|
+
/** Placement relative to trigger */
|
|
9
|
+
placement?: Placement;
|
|
10
|
+
/** Offset from trigger in pixels */
|
|
11
|
+
offset?: number;
|
|
12
|
+
/** Delay before showing tooltip (ms) */
|
|
13
|
+
showDelay?: number;
|
|
14
|
+
/** Delay before hiding tooltip (ms) */
|
|
15
|
+
hideDelay?: number;
|
|
16
|
+
/** Tooltip content */
|
|
17
|
+
children?: React.ReactNode;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* React wrapper for ds-tooltip Web Component.
|
|
22
|
+
* Informational tooltip shown on hover/focus.
|
|
23
|
+
*/
|
|
24
|
+
export const Tooltip = forwardRef<HTMLElement, TooltipProps>((props, forwardedRef) => {
|
|
25
|
+
const {
|
|
26
|
+
open = false,
|
|
27
|
+
placement = "top",
|
|
28
|
+
offset = 8,
|
|
29
|
+
showDelay = 400,
|
|
30
|
+
hideDelay = 100,
|
|
31
|
+
children,
|
|
32
|
+
className,
|
|
33
|
+
...rest
|
|
34
|
+
} = props;
|
|
35
|
+
|
|
36
|
+
const internalRef = useRef<HTMLElement>(null);
|
|
37
|
+
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
if (typeof forwardedRef === "function") {
|
|
40
|
+
forwardedRef(internalRef.current);
|
|
41
|
+
} else if (forwardedRef) {
|
|
42
|
+
(forwardedRef as React.MutableRefObject<HTMLElement | null>).current = internalRef.current;
|
|
43
|
+
}
|
|
44
|
+
}, [forwardedRef]);
|
|
45
|
+
|
|
46
|
+
return createElement(
|
|
47
|
+
"ds-tooltip",
|
|
48
|
+
{
|
|
49
|
+
ref: internalRef,
|
|
50
|
+
open: open || undefined,
|
|
51
|
+
placement,
|
|
52
|
+
offset,
|
|
53
|
+
"show-delay": showDelay,
|
|
54
|
+
"hide-delay": hideDelay,
|
|
55
|
+
class: className,
|
|
56
|
+
...rest,
|
|
57
|
+
},
|
|
58
|
+
children
|
|
59
|
+
);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
Tooltip.displayName = "Tooltip";
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { html } from "lit";
|
|
2
|
+
import { property } from "lit/decorators.js";
|
|
3
|
+
import { DSElement } from "../../base/ds-element.js";
|
|
4
|
+
import { define } from "../../registry/define.js";
|
|
5
|
+
|
|
6
|
+
export type TooltipContentState = "open" | "closed";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Tooltip content container.
|
|
10
|
+
*
|
|
11
|
+
* @element ds-tooltip-content
|
|
12
|
+
*
|
|
13
|
+
* @slot - Content to display in the tooltip
|
|
14
|
+
*
|
|
15
|
+
* @attr {string} data-state - Animation state ("open" or "closed")
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```html
|
|
19
|
+
* <ds-tooltip>
|
|
20
|
+
* <button slot="trigger">Hover me</button>
|
|
21
|
+
* <ds-tooltip-content>Helpful information</ds-tooltip-content>
|
|
22
|
+
* </ds-tooltip>
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export class DsTooltipContent extends DSElement {
|
|
26
|
+
/** Unique ID for ARIA association */
|
|
27
|
+
@property({ type: String, reflect: true })
|
|
28
|
+
override id = "";
|
|
29
|
+
|
|
30
|
+
/** Animation state (open or closed) - set by parent ds-tooltip */
|
|
31
|
+
@property({ type: String, reflect: true, attribute: "data-state" })
|
|
32
|
+
dataState: TooltipContentState = "closed";
|
|
33
|
+
|
|
34
|
+
override connectedCallback(): void {
|
|
35
|
+
super.connectedCallback();
|
|
36
|
+
|
|
37
|
+
// Generate ID if not set
|
|
38
|
+
if (!this.id) {
|
|
39
|
+
this.id = `tooltip-content-${crypto.randomUUID().slice(0, 8)}`;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Set role for accessibility
|
|
43
|
+
this.setAttribute("role", "tooltip");
|
|
44
|
+
|
|
45
|
+
// Hidden by default (parent tooltip controls visibility)
|
|
46
|
+
this.setAttribute("hidden", "");
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
override render() {
|
|
50
|
+
return html`
|
|
51
|
+
<div class="ds-tooltip-content" part="container">
|
|
52
|
+
<slot></slot>
|
|
53
|
+
</div>
|
|
54
|
+
`;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
define("ds-tooltip-content", DsTooltipContent);
|
|
59
|
+
|
|
60
|
+
declare global {
|
|
61
|
+
interface HTMLElementTagNameMap {
|
|
62
|
+
"ds-tooltip-content": DsTooltipContent;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type AnchorPosition,
|
|
3
|
+
type Placement,
|
|
4
|
+
type Presence,
|
|
5
|
+
createAnchorPosition,
|
|
6
|
+
createPresence,
|
|
7
|
+
prefersReducedMotion,
|
|
8
|
+
} from "@hypoth-ui/primitives-dom";
|
|
9
|
+
import { html } from "lit";
|
|
10
|
+
import { property } from "lit/decorators.js";
|
|
11
|
+
import { DSElement } from "../../base/ds-element.js";
|
|
12
|
+
import { define } from "../../registry/define.js";
|
|
13
|
+
|
|
14
|
+
// Import child component to ensure it's registered
|
|
15
|
+
import type { DsTooltipContent } from "./tooltip-content.js";
|
|
16
|
+
import "./tooltip-content.js";
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Tooltip component with hover/focus trigger and configurable delays.
|
|
20
|
+
*
|
|
21
|
+
* Shows informational content on hover or focus with positioning
|
|
22
|
+
* relative to the trigger element.
|
|
23
|
+
*
|
|
24
|
+
* @element ds-tooltip
|
|
25
|
+
*
|
|
26
|
+
* @slot trigger - Element that triggers the tooltip
|
|
27
|
+
* @slot - Tooltip content (ds-tooltip-content)
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```html
|
|
31
|
+
* <ds-tooltip>
|
|
32
|
+
* <button slot="trigger">Hover for info</button>
|
|
33
|
+
* <ds-tooltip-content>Additional information here</ds-tooltip-content>
|
|
34
|
+
* </ds-tooltip>
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export class DsTooltip extends DSElement {
|
|
38
|
+
/** Whether the tooltip is open */
|
|
39
|
+
@property({ type: Boolean, reflect: true })
|
|
40
|
+
open = false;
|
|
41
|
+
|
|
42
|
+
/** Placement relative to trigger */
|
|
43
|
+
@property({ type: String, reflect: true })
|
|
44
|
+
placement: Placement = "top";
|
|
45
|
+
|
|
46
|
+
/** Offset distance from trigger in pixels */
|
|
47
|
+
@property({ type: Number })
|
|
48
|
+
offset = 8;
|
|
49
|
+
|
|
50
|
+
/** Delay before showing tooltip (ms) */
|
|
51
|
+
@property({ type: Number, attribute: "show-delay" })
|
|
52
|
+
showDelay = 400;
|
|
53
|
+
|
|
54
|
+
/** Delay before hiding tooltip (ms) */
|
|
55
|
+
@property({ type: Number, attribute: "hide-delay" })
|
|
56
|
+
hideDelay = 100;
|
|
57
|
+
|
|
58
|
+
/** Whether to animate open/close transitions */
|
|
59
|
+
@property({ type: Boolean })
|
|
60
|
+
animated = true;
|
|
61
|
+
|
|
62
|
+
private anchorPosition: AnchorPosition | null = null;
|
|
63
|
+
private presence: Presence | null = null;
|
|
64
|
+
private showTimeout: ReturnType<typeof setTimeout> | null = null;
|
|
65
|
+
private hideTimeout: ReturnType<typeof setTimeout> | null = null;
|
|
66
|
+
private escapeHandler: ((event: KeyboardEvent) => void) | null = null;
|
|
67
|
+
|
|
68
|
+
override connectedCallback(): void {
|
|
69
|
+
super.connectedCallback();
|
|
70
|
+
|
|
71
|
+
// Setup after first render
|
|
72
|
+
this.updateComplete.then(() => {
|
|
73
|
+
this.setupTriggerListeners();
|
|
74
|
+
this.setupContentListeners();
|
|
75
|
+
this.setupTriggerAccessibility();
|
|
76
|
+
this.setupEscapeHandler();
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
override disconnectedCallback(): void {
|
|
81
|
+
super.disconnectedCallback();
|
|
82
|
+
this.cleanup();
|
|
83
|
+
this.removeEscapeHandler();
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Shows the tooltip immediately.
|
|
88
|
+
*/
|
|
89
|
+
public show(): void {
|
|
90
|
+
this.clearTimeouts();
|
|
91
|
+
if (this.open) return;
|
|
92
|
+
|
|
93
|
+
this.open = true;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Hides the tooltip immediately.
|
|
98
|
+
*/
|
|
99
|
+
public hide(): void {
|
|
100
|
+
this.clearTimeouts();
|
|
101
|
+
if (!this.open) return;
|
|
102
|
+
|
|
103
|
+
this.cleanup();
|
|
104
|
+
this.open = false;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
private clearTimeouts(): void {
|
|
108
|
+
if (this.showTimeout) {
|
|
109
|
+
clearTimeout(this.showTimeout);
|
|
110
|
+
this.showTimeout = null;
|
|
111
|
+
}
|
|
112
|
+
if (this.hideTimeout) {
|
|
113
|
+
clearTimeout(this.hideTimeout);
|
|
114
|
+
this.hideTimeout = null;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
private scheduleShow(): void {
|
|
119
|
+
this.clearTimeouts();
|
|
120
|
+
if (this.open) return;
|
|
121
|
+
|
|
122
|
+
this.showTimeout = setTimeout(() => {
|
|
123
|
+
this.open = true;
|
|
124
|
+
this.showTimeout = null;
|
|
125
|
+
}, this.showDelay);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
private scheduleHide(): void {
|
|
129
|
+
this.clearTimeouts();
|
|
130
|
+
if (!this.open) return;
|
|
131
|
+
|
|
132
|
+
this.hideTimeout = setTimeout(() => {
|
|
133
|
+
const content = this.querySelector("ds-tooltip-content") as DsTooltipContent | null;
|
|
134
|
+
|
|
135
|
+
// If animated, use presence for exit animation
|
|
136
|
+
if (this.animated && content && !prefersReducedMotion()) {
|
|
137
|
+
this.presence = createPresence({
|
|
138
|
+
onExitComplete: () => {
|
|
139
|
+
this.cleanup();
|
|
140
|
+
this.open = false;
|
|
141
|
+
},
|
|
142
|
+
});
|
|
143
|
+
this.presence.hide(content);
|
|
144
|
+
} else {
|
|
145
|
+
this.cleanup();
|
|
146
|
+
this.open = false;
|
|
147
|
+
}
|
|
148
|
+
this.hideTimeout = null;
|
|
149
|
+
}, this.hideDelay);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
private handleTriggerMouseEnter = (): void => {
|
|
153
|
+
this.scheduleShow();
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
private handleTriggerMouseLeave = (): void => {
|
|
157
|
+
this.scheduleHide();
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
private handleTriggerFocusIn = (): void => {
|
|
161
|
+
this.scheduleShow();
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
private handleTriggerFocusOut = (): void => {
|
|
165
|
+
this.scheduleHide();
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
private handleContentMouseEnter = (): void => {
|
|
169
|
+
// Cancel hide when mouse enters tooltip content (hover persistence)
|
|
170
|
+
this.clearTimeouts();
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
private handleContentMouseLeave = (): void => {
|
|
174
|
+
this.scheduleHide();
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
private setupTriggerListeners(): void {
|
|
178
|
+
const trigger = this.querySelector('[slot="trigger"]');
|
|
179
|
+
if (!trigger) return;
|
|
180
|
+
|
|
181
|
+
trigger.addEventListener("mouseenter", this.handleTriggerMouseEnter);
|
|
182
|
+
trigger.addEventListener("mouseleave", this.handleTriggerMouseLeave);
|
|
183
|
+
trigger.addEventListener("focusin", this.handleTriggerFocusIn);
|
|
184
|
+
trigger.addEventListener("focusout", this.handleTriggerFocusOut);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
private setupContentListeners(): void {
|
|
188
|
+
const content = this.querySelector("ds-tooltip-content");
|
|
189
|
+
if (!content) return;
|
|
190
|
+
|
|
191
|
+
content.addEventListener("mouseenter", this.handleContentMouseEnter);
|
|
192
|
+
content.addEventListener("mouseleave", this.handleContentMouseLeave);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
private setupTriggerAccessibility(): void {
|
|
196
|
+
const trigger = this.querySelector('[slot="trigger"]');
|
|
197
|
+
const content = this.querySelector("ds-tooltip-content");
|
|
198
|
+
|
|
199
|
+
if (trigger && content) {
|
|
200
|
+
// Set aria-describedby on trigger pointing to tooltip content
|
|
201
|
+
trigger.setAttribute("aria-describedby", content.id);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
private setupEscapeHandler(): void {
|
|
206
|
+
this.escapeHandler = (event: KeyboardEvent) => {
|
|
207
|
+
if (event.key === "Escape" && this.open) {
|
|
208
|
+
event.preventDefault();
|
|
209
|
+
this.hide();
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
document.addEventListener("keydown", this.escapeHandler);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
private removeEscapeHandler(): void {
|
|
216
|
+
if (this.escapeHandler) {
|
|
217
|
+
document.removeEventListener("keydown", this.escapeHandler);
|
|
218
|
+
this.escapeHandler = null;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
private setupPositioning(): void {
|
|
223
|
+
const trigger = this.querySelector('[slot="trigger"]') as HTMLElement | null;
|
|
224
|
+
const content = this.querySelector("ds-tooltip-content") as HTMLElement | null;
|
|
225
|
+
|
|
226
|
+
if (!trigger || !content) return;
|
|
227
|
+
|
|
228
|
+
this.anchorPosition = createAnchorPosition({
|
|
229
|
+
anchor: trigger,
|
|
230
|
+
floating: content,
|
|
231
|
+
placement: this.placement,
|
|
232
|
+
offset: this.offset,
|
|
233
|
+
flip: true,
|
|
234
|
+
onPositionChange: (pos) => {
|
|
235
|
+
content.setAttribute("data-placement", pos.placement);
|
|
236
|
+
},
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
private cleanup(): void {
|
|
241
|
+
this.clearTimeouts();
|
|
242
|
+
this.anchorPosition?.destroy();
|
|
243
|
+
this.anchorPosition = null;
|
|
244
|
+
this.presence?.destroy();
|
|
245
|
+
this.presence = null;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
override async updated(changedProperties: Map<string, unknown>): Promise<void> {
|
|
249
|
+
super.updated(changedProperties);
|
|
250
|
+
|
|
251
|
+
if (changedProperties.has("open")) {
|
|
252
|
+
const content = this.querySelector("ds-tooltip-content") as DsTooltipContent | null;
|
|
253
|
+
|
|
254
|
+
if (this.open) {
|
|
255
|
+
// Show content
|
|
256
|
+
content?.removeAttribute("hidden");
|
|
257
|
+
|
|
258
|
+
// Set data-state to open for entry animation
|
|
259
|
+
if (content) {
|
|
260
|
+
content.dataState = "open";
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// Wait for DOM update
|
|
264
|
+
await this.updateComplete;
|
|
265
|
+
|
|
266
|
+
// Setup positioning
|
|
267
|
+
this.setupPositioning();
|
|
268
|
+
} else {
|
|
269
|
+
// Hide content
|
|
270
|
+
content?.setAttribute("hidden", "");
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
override render() {
|
|
276
|
+
return html`
|
|
277
|
+
<slot name="trigger"></slot>
|
|
278
|
+
<slot></slot>
|
|
279
|
+
`;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
define("ds-tooltip", DsTooltip);
|
|
284
|
+
|
|
285
|
+
declare global {
|
|
286
|
+
interface HTMLElementTagNameMap {
|
|
287
|
+
"ds-tooltip": DsTooltip;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Tree compound component exports
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { TreeItem } from "./tree-item.js";
|
|
8
|
+
import { TreeRoot } from "./tree.js";
|
|
9
|
+
|
|
10
|
+
export type { TreeRootProps, TreeSelectionMode, TreeSize } from "./tree.js";
|
|
11
|
+
export type { TreeItemProps } from "./tree-item.js";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Tree compound component for hierarchical data display.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```tsx
|
|
18
|
+
* <Tree selectionMode="single" onSelectionChange={(ids) => console.log(ids)}>
|
|
19
|
+
* <Tree.Item itemId="1">
|
|
20
|
+
* Documents
|
|
21
|
+
* <div slot="children">
|
|
22
|
+
* <Tree.Item itemId="1-1">Work</Tree.Item>
|
|
23
|
+
* <Tree.Item itemId="1-2">Personal</Tree.Item>
|
|
24
|
+
* </div>
|
|
25
|
+
* </Tree.Item>
|
|
26
|
+
* <Tree.Item itemId="2">Pictures</Tree.Item>
|
|
27
|
+
* </Tree>
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export const Tree = Object.assign(TreeRoot, {
|
|
31
|
+
Item: TreeItem,
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
export { TreeItem };
|
|
35
|
+
|
|
36
|
+
// TypeScript declarations for JSX
|
|
37
|
+
declare global {
|
|
38
|
+
namespace JSX {
|
|
39
|
+
interface IntrinsicElements {
|
|
40
|
+
"ds-tree": React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement> & {
|
|
41
|
+
ref?: React.Ref<HTMLElement>;
|
|
42
|
+
"selection-mode"?: string;
|
|
43
|
+
size?: string;
|
|
44
|
+
lines?: boolean;
|
|
45
|
+
label?: string;
|
|
46
|
+
"onDs-selection-change"?: (event: CustomEvent) => void;
|
|
47
|
+
};
|
|
48
|
+
"ds-tree-item": React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement> & {
|
|
49
|
+
ref?: React.Ref<HTMLElement>;
|
|
50
|
+
"item-id"?: string;
|
|
51
|
+
expanded?: boolean;
|
|
52
|
+
selected?: boolean;
|
|
53
|
+
disabled?: boolean;
|
|
54
|
+
"onDs-expand"?: (event: CustomEvent) => void;
|
|
55
|
+
"onDs-select"?: (event: CustomEvent) => void;
|
|
56
|
+
"onDs-activate"?: (event: CustomEvent) => void;
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
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 TreeItemProps extends Omit<HTMLAttributes<HTMLElement>, "onSelect"> {
|
|
14
|
+
/**
|
|
15
|
+
* Unique item ID.
|
|
16
|
+
*/
|
|
17
|
+
itemId?: string;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Whether item is expanded.
|
|
21
|
+
* @default false
|
|
22
|
+
*/
|
|
23
|
+
expanded?: boolean;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Whether item is selected.
|
|
27
|
+
* @default false
|
|
28
|
+
*/
|
|
29
|
+
selected?: boolean;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Whether item is disabled.
|
|
33
|
+
* @default false
|
|
34
|
+
*/
|
|
35
|
+
disabled?: boolean;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Callback when expand state changes.
|
|
39
|
+
*/
|
|
40
|
+
onExpand?: (itemId: string, expanded: boolean) => void;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Callback when item is selected.
|
|
44
|
+
*/
|
|
45
|
+
onItemSelect?: (itemId: string, selected: boolean) => void;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Callback when item is activated (Enter/double-click).
|
|
49
|
+
*/
|
|
50
|
+
onActivate?: (itemId: string) => void;
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Item label content.
|
|
54
|
+
*/
|
|
55
|
+
children?: ReactNode;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Tree item component for hierarchical nodes.
|
|
60
|
+
*/
|
|
61
|
+
export const TreeItem = forwardRef<HTMLElement, TreeItemProps>(function TreeItem(
|
|
62
|
+
{
|
|
63
|
+
itemId,
|
|
64
|
+
expanded = false,
|
|
65
|
+
selected = false,
|
|
66
|
+
disabled = false,
|
|
67
|
+
onExpand,
|
|
68
|
+
onItemSelect,
|
|
69
|
+
onActivate,
|
|
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 handleExpand = (e: Event) => {
|
|
93
|
+
const event = e as CustomEvent<{ itemId: string; expanded: boolean }>;
|
|
94
|
+
onExpand?.(event.detail.itemId, event.detail.expanded);
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const handleSelect = (e: Event) => {
|
|
98
|
+
const event = e as CustomEvent<{ itemId: string; selected: boolean }>;
|
|
99
|
+
onItemSelect?.(event.detail.itemId, event.detail.selected);
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
const handleActivate = (e: Event) => {
|
|
103
|
+
const event = e as CustomEvent<{ itemId: string }>;
|
|
104
|
+
onActivate?.(event.detail.itemId);
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
element.addEventListener("ds:expand", handleExpand);
|
|
108
|
+
element.addEventListener("ds:select", handleSelect);
|
|
109
|
+
element.addEventListener("ds:activate", handleActivate);
|
|
110
|
+
|
|
111
|
+
return () => {
|
|
112
|
+
element.removeEventListener("ds:expand", handleExpand);
|
|
113
|
+
element.removeEventListener("ds:select", handleSelect);
|
|
114
|
+
element.removeEventListener("ds:activate", handleActivate);
|
|
115
|
+
};
|
|
116
|
+
}, [onExpand, onItemSelect, onActivate]);
|
|
117
|
+
|
|
118
|
+
return createElement(
|
|
119
|
+
"ds-tree-item",
|
|
120
|
+
{
|
|
121
|
+
ref: internalRef,
|
|
122
|
+
"item-id": itemId,
|
|
123
|
+
expanded: expanded || undefined,
|
|
124
|
+
selected: selected || undefined,
|
|
125
|
+
disabled: disabled || undefined,
|
|
126
|
+
class: className,
|
|
127
|
+
...props,
|
|
128
|
+
},
|
|
129
|
+
children
|
|
130
|
+
);
|
|
131
|
+
});
|