@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,302 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AlertDialog component - modal dialog requiring explicit user action.
|
|
3
|
+
*
|
|
4
|
+
* AlertDialog is used for important decisions that require confirmation.
|
|
5
|
+
* Unlike Dialog, it cannot be dismissed by clicking outside or pressing Escape.
|
|
6
|
+
*
|
|
7
|
+
* Implements WAI-ARIA AlertDialog pattern.
|
|
8
|
+
*
|
|
9
|
+
* @element ds-alert-dialog
|
|
10
|
+
*
|
|
11
|
+
* @slot trigger - Button or element that opens the alert dialog
|
|
12
|
+
* @slot - AlertDialog content (ds-alert-dialog-content)
|
|
13
|
+
*
|
|
14
|
+
* @fires ds:open - Fired when alert dialog opens
|
|
15
|
+
* @fires ds:close - Fired when alert dialog closes
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```html
|
|
19
|
+
* <ds-alert-dialog>
|
|
20
|
+
* <button slot="trigger">Delete Account</button>
|
|
21
|
+
* <ds-alert-dialog-content>
|
|
22
|
+
* <ds-alert-dialog-header>
|
|
23
|
+
* <ds-alert-dialog-title>Are you absolutely sure?</ds-alert-dialog-title>
|
|
24
|
+
* <ds-alert-dialog-description>
|
|
25
|
+
* This action cannot be undone.
|
|
26
|
+
* </ds-alert-dialog-description>
|
|
27
|
+
* </ds-alert-dialog-header>
|
|
28
|
+
* <ds-alert-dialog-footer>
|
|
29
|
+
* <ds-alert-dialog-cancel>Cancel</ds-alert-dialog-cancel>
|
|
30
|
+
* <ds-alert-dialog-action>Delete</ds-alert-dialog-action>
|
|
31
|
+
* </ds-alert-dialog-footer>
|
|
32
|
+
* </ds-alert-dialog-content>
|
|
33
|
+
* </ds-alert-dialog>
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
import {
|
|
38
|
+
type DialogBehavior,
|
|
39
|
+
type Presence,
|
|
40
|
+
createDialogBehavior,
|
|
41
|
+
createPresence,
|
|
42
|
+
prefersReducedMotion,
|
|
43
|
+
} from "@hypoth-ui/primitives-dom";
|
|
44
|
+
import { html } from "lit";
|
|
45
|
+
import { property, state } from "lit/decorators.js";
|
|
46
|
+
import { DSElement } from "../../base/ds-element.js";
|
|
47
|
+
import { StandardEvents, emitEvent } from "../../events/emit.js";
|
|
48
|
+
import { define } from "../../registry/define.js";
|
|
49
|
+
import { devWarn, hasRequiredChild, Warnings } from "../../utils/dev-warnings.js";
|
|
50
|
+
|
|
51
|
+
// Import child components to ensure they're registered
|
|
52
|
+
import type { DsAlertDialogContent } from "./alert-dialog-content.js";
|
|
53
|
+
import "./alert-dialog-content.js";
|
|
54
|
+
import "./alert-dialog-header.js";
|
|
55
|
+
import "./alert-dialog-footer.js";
|
|
56
|
+
import "./alert-dialog-title.js";
|
|
57
|
+
import "./alert-dialog-description.js";
|
|
58
|
+
import "./alert-dialog-action.js";
|
|
59
|
+
import "./alert-dialog-cancel.js";
|
|
60
|
+
|
|
61
|
+
export class DsAlertDialog extends DSElement {
|
|
62
|
+
/** Whether the alert dialog is open */
|
|
63
|
+
@property({ type: Boolean, reflect: true })
|
|
64
|
+
open = false;
|
|
65
|
+
|
|
66
|
+
/** Whether to animate open/close transitions */
|
|
67
|
+
@property({ type: Boolean })
|
|
68
|
+
animated = true;
|
|
69
|
+
|
|
70
|
+
/** Whether the alert dialog is closing (for animation) */
|
|
71
|
+
@state()
|
|
72
|
+
private isClosing = false;
|
|
73
|
+
|
|
74
|
+
private dialogBehavior: DialogBehavior | null = null;
|
|
75
|
+
private presence: Presence | null = null;
|
|
76
|
+
|
|
77
|
+
override connectedCallback(): void {
|
|
78
|
+
super.connectedCallback();
|
|
79
|
+
|
|
80
|
+
// Listen for trigger clicks via event delegation
|
|
81
|
+
this.addEventListener("click", this.handleTriggerClick);
|
|
82
|
+
|
|
83
|
+
// Listen for action/cancel clicks
|
|
84
|
+
this.addEventListener("ds:alert-dialog-action", this.handleAction as EventListener);
|
|
85
|
+
this.addEventListener("ds:alert-dialog-cancel", this.handleCancel as EventListener);
|
|
86
|
+
|
|
87
|
+
// Initialize dialog behavior (AlertDialog does NOT close on escape or outside click)
|
|
88
|
+
this.initDialogBehavior();
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
override disconnectedCallback(): void {
|
|
92
|
+
super.disconnectedCallback();
|
|
93
|
+
this.removeEventListener("click", this.handleTriggerClick);
|
|
94
|
+
this.removeEventListener("ds:alert-dialog-action", this.handleAction as EventListener);
|
|
95
|
+
this.removeEventListener("ds:alert-dialog-cancel", this.handleCancel as EventListener);
|
|
96
|
+
this.cleanup();
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Initializes the dialog behavior primitive.
|
|
101
|
+
* AlertDialog uses role="alertdialog" and disables dismiss on escape/outside click.
|
|
102
|
+
*/
|
|
103
|
+
private initDialogBehavior(): void {
|
|
104
|
+
this.dialogBehavior = createDialogBehavior({
|
|
105
|
+
defaultOpen: this.open,
|
|
106
|
+
role: "alertdialog",
|
|
107
|
+
closeOnEscape: false, // AlertDialog does NOT close on escape
|
|
108
|
+
closeOnOutsideClick: false, // AlertDialog does NOT close on outside click
|
|
109
|
+
onOpenChange: () => {
|
|
110
|
+
// AlertDialog only closes via explicit action/cancel buttons
|
|
111
|
+
// so we don't handle behavior-initiated closes here
|
|
112
|
+
},
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
// Set trigger element if one exists
|
|
116
|
+
const trigger = this.querySelector('[slot="trigger"]') as HTMLElement | null;
|
|
117
|
+
if (trigger) {
|
|
118
|
+
this.dialogBehavior.setTriggerElement(trigger);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Opens the alert dialog.
|
|
124
|
+
*/
|
|
125
|
+
public show(): void {
|
|
126
|
+
if (this.open) return;
|
|
127
|
+
|
|
128
|
+
// Store trigger element for focus return
|
|
129
|
+
const trigger = this.querySelector('[slot="trigger"]') as HTMLElement | null;
|
|
130
|
+
if (trigger) {
|
|
131
|
+
this.dialogBehavior?.setTriggerElement(trigger);
|
|
132
|
+
} else if (document.activeElement instanceof HTMLElement) {
|
|
133
|
+
this.dialogBehavior?.setTriggerElement(document.activeElement);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
this.open = true;
|
|
137
|
+
this.dialogBehavior?.open();
|
|
138
|
+
emitEvent(this, StandardEvents.OPEN);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Closes the alert dialog.
|
|
143
|
+
*/
|
|
144
|
+
public close(): void {
|
|
145
|
+
if (!this.open) return;
|
|
146
|
+
|
|
147
|
+
const content = this.querySelector("ds-alert-dialog-content") as DsAlertDialogContent | null;
|
|
148
|
+
|
|
149
|
+
// Close the behavior (deactivates focus trap and dismiss layer)
|
|
150
|
+
this.dialogBehavior?.close();
|
|
151
|
+
|
|
152
|
+
// If animated, use presence for exit animation
|
|
153
|
+
if (this.animated && content && !prefersReducedMotion()) {
|
|
154
|
+
this.isClosing = true;
|
|
155
|
+
|
|
156
|
+
// Create presence for exit animation
|
|
157
|
+
this.presence = createPresence({
|
|
158
|
+
onExitComplete: () => {
|
|
159
|
+
this.completeClose();
|
|
160
|
+
},
|
|
161
|
+
});
|
|
162
|
+
this.presence.hide(content);
|
|
163
|
+
} else {
|
|
164
|
+
// No animation - close immediately
|
|
165
|
+
this.open = false;
|
|
166
|
+
this.isClosing = false;
|
|
167
|
+
emitEvent(this, StandardEvents.CLOSE);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Completes the close after exit animation.
|
|
173
|
+
*/
|
|
174
|
+
private completeClose(): void {
|
|
175
|
+
this.presence?.destroy();
|
|
176
|
+
this.presence = null;
|
|
177
|
+
this.open = false;
|
|
178
|
+
this.isClosing = false;
|
|
179
|
+
emitEvent(this, StandardEvents.CLOSE);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
private handleTriggerClick = (event: Event): void => {
|
|
183
|
+
const target = event.target as HTMLElement;
|
|
184
|
+
const trigger = target.closest('[slot="trigger"]');
|
|
185
|
+
|
|
186
|
+
if (trigger && this.contains(trigger)) {
|
|
187
|
+
// Store trigger before opening
|
|
188
|
+
this.dialogBehavior?.setTriggerElement(trigger as HTMLElement);
|
|
189
|
+
this.show();
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
private handleAction = (): void => {
|
|
194
|
+
// Action clicked - close the dialog
|
|
195
|
+
this.close();
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
private handleCancel = (): void => {
|
|
199
|
+
// Cancel clicked - close the dialog
|
|
200
|
+
this.close();
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
private cleanup(): void {
|
|
204
|
+
this.dialogBehavior?.destroy();
|
|
205
|
+
this.dialogBehavior = null;
|
|
206
|
+
this.presence?.destroy();
|
|
207
|
+
this.presence = null;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
override async updated(changedProperties: Map<string, unknown>): Promise<void> {
|
|
211
|
+
super.updated(changedProperties);
|
|
212
|
+
|
|
213
|
+
if (changedProperties.has("open")) {
|
|
214
|
+
const content = this.querySelector("ds-alert-dialog-content") as DsAlertDialogContent | null;
|
|
215
|
+
|
|
216
|
+
if (this.open) {
|
|
217
|
+
// Wait for the next microtask to ensure DOM is committed
|
|
218
|
+
await this.updateComplete;
|
|
219
|
+
|
|
220
|
+
// Set data-state to open for entry animation
|
|
221
|
+
if (content) {
|
|
222
|
+
content.dataState = "open";
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// Set content element on behavior (activates focus trap and dismiss layer)
|
|
226
|
+
this.dialogBehavior?.setContentElement(content);
|
|
227
|
+
this.updateContentAccessibility();
|
|
228
|
+
} else {
|
|
229
|
+
// Clear content element on behavior
|
|
230
|
+
this.dialogBehavior?.setContentElement(null);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Updates accessibility attributes on alert dialog content.
|
|
237
|
+
*/
|
|
238
|
+
private updateContentAccessibility(): void {
|
|
239
|
+
const content = this.querySelector("ds-alert-dialog-content");
|
|
240
|
+
if (!content || !this.dialogBehavior) return;
|
|
241
|
+
|
|
242
|
+
// Get props from behavior
|
|
243
|
+
const contentProps = this.dialogBehavior.getContentProps();
|
|
244
|
+
|
|
245
|
+
// Set role on content - always alertdialog
|
|
246
|
+
content.setAttribute("role", "alertdialog");
|
|
247
|
+
content.setAttribute("aria-modal", contentProps["aria-modal"]);
|
|
248
|
+
|
|
249
|
+
// Dev warning: Check for required alert dialog title
|
|
250
|
+
if (!hasRequiredChild(this, "ds-alert-dialog-title") && !this.getAttribute("aria-label")) {
|
|
251
|
+
devWarn(Warnings.dialogMissingTitle("ds-alert-dialog"));
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// Connect title via aria-labelledby
|
|
255
|
+
const title = this.querySelector("ds-alert-dialog-title");
|
|
256
|
+
if (title) {
|
|
257
|
+
const titleProps = this.dialogBehavior.getTitleProps();
|
|
258
|
+
if (!title.id) {
|
|
259
|
+
title.id = titleProps.id;
|
|
260
|
+
}
|
|
261
|
+
content.setAttribute("aria-labelledby", title.id);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// Connect description via aria-describedby
|
|
265
|
+
const description = this.querySelector("ds-alert-dialog-description");
|
|
266
|
+
if (description) {
|
|
267
|
+
const descProps = this.dialogBehavior.getDescriptionProps();
|
|
268
|
+
if (!description.id) {
|
|
269
|
+
description.id = descProps.id;
|
|
270
|
+
}
|
|
271
|
+
content.setAttribute("aria-describedby", description.id);
|
|
272
|
+
this.dialogBehavior.setHasDescription(true);
|
|
273
|
+
} else {
|
|
274
|
+
// Dev warning: Title without description
|
|
275
|
+
if (title) {
|
|
276
|
+
devWarn(Warnings.dialogMissingDescription("ds-alert-dialog"));
|
|
277
|
+
}
|
|
278
|
+
this.dialogBehavior.setHasDescription(false);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
override render() {
|
|
283
|
+
return html`
|
|
284
|
+
<slot name="trigger"></slot>
|
|
285
|
+
<div
|
|
286
|
+
class="ds-alert-dialog__backdrop"
|
|
287
|
+
?hidden=${!this.open}
|
|
288
|
+
?data-closing=${this.isClosing}
|
|
289
|
+
>
|
|
290
|
+
<slot></slot>
|
|
291
|
+
</div>
|
|
292
|
+
`;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
define("ds-alert-dialog", DsAlertDialog);
|
|
297
|
+
|
|
298
|
+
declare global {
|
|
299
|
+
interface HTMLElementTagNameMap {
|
|
300
|
+
"ds-alert-dialog": DsAlertDialog;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AlertDialog component exports.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export { DsAlertDialog } from "./alert-dialog.js";
|
|
6
|
+
export { DsAlertDialogTrigger } from "./alert-dialog-trigger.js";
|
|
7
|
+
export { DsAlertDialogContent, type AlertDialogContentSize } from "./alert-dialog-content.js";
|
|
8
|
+
export { DsAlertDialogHeader } from "./alert-dialog-header.js";
|
|
9
|
+
export { DsAlertDialogFooter } from "./alert-dialog-footer.js";
|
|
10
|
+
export { DsAlertDialogTitle } from "./alert-dialog-title.js";
|
|
11
|
+
export { DsAlertDialogDescription } from "./alert-dialog-description.js";
|
|
12
|
+
export { DsAlertDialogAction } from "./alert-dialog-action.js";
|
|
13
|
+
export { DsAlertDialogCancel } from "./alert-dialog-cancel.js";
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AspectRatio component React wrapper.
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* ```tsx
|
|
6
|
+
* import { AspectRatio } from "@/components/ui";
|
|
7
|
+
*
|
|
8
|
+
* <AspectRatio ratio="16/9">
|
|
9
|
+
* <img src="image.jpg" alt="..." />
|
|
10
|
+
* </AspectRatio>
|
|
11
|
+
* ```
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { type HTMLAttributes, type ReactNode, createElement, forwardRef } from "react";
|
|
15
|
+
|
|
16
|
+
// ============================================================================
|
|
17
|
+
// Types
|
|
18
|
+
// ============================================================================
|
|
19
|
+
|
|
20
|
+
export interface AspectRatioProps extends HTMLAttributes<HTMLElement> {
|
|
21
|
+
/** Content to maintain aspect ratio */
|
|
22
|
+
children?: ReactNode;
|
|
23
|
+
/**
|
|
24
|
+
* Aspect ratio as width/height (e.g., "16/9", "4/3", "1/1").
|
|
25
|
+
* Can also be a number (e.g., 1.777 for 16:9).
|
|
26
|
+
*/
|
|
27
|
+
ratio?: string | number;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// ============================================================================
|
|
31
|
+
// Component
|
|
32
|
+
// ============================================================================
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* AspectRatio component - maintains consistent width-to-height ratio.
|
|
36
|
+
*/
|
|
37
|
+
export const AspectRatio = forwardRef<HTMLElement, AspectRatioProps>(function AspectRatio(
|
|
38
|
+
{ children, className, ratio = "1/1", ...props },
|
|
39
|
+
ref
|
|
40
|
+
) {
|
|
41
|
+
const ratioString = typeof ratio === "number" ? String(ratio) : ratio;
|
|
42
|
+
|
|
43
|
+
return createElement(
|
|
44
|
+
"ds-aspect-ratio",
|
|
45
|
+
{ ref, class: className, ratio: ratioString, ...props },
|
|
46
|
+
children
|
|
47
|
+
);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
AspectRatio.displayName = "AspectRatio";
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AspectRatio component - maintains consistent width-to-height ratio.
|
|
3
|
+
*
|
|
4
|
+
* @element ds-aspect-ratio
|
|
5
|
+
*
|
|
6
|
+
* @slot - Default slot for content to maintain aspect ratio
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```html
|
|
10
|
+
* <ds-aspect-ratio ratio="16/9">
|
|
11
|
+
* <img src="image.jpg" alt="..." />
|
|
12
|
+
* </ds-aspect-ratio>
|
|
13
|
+
* <ds-aspect-ratio ratio="4/3">
|
|
14
|
+
* <video src="video.mp4"></video>
|
|
15
|
+
* </ds-aspect-ratio>
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import { html } from "lit";
|
|
20
|
+
import { property } from "lit/decorators.js";
|
|
21
|
+
import { DSElement } from "../../base/ds-element.js";
|
|
22
|
+
import { define } from "../../registry/define.js";
|
|
23
|
+
|
|
24
|
+
export class DsAspectRatio extends DSElement {
|
|
25
|
+
/**
|
|
26
|
+
* Aspect ratio as width/height (e.g., "16/9", "4/3", "1/1").
|
|
27
|
+
* Can also be a number (e.g., 1.777 for 16:9).
|
|
28
|
+
*/
|
|
29
|
+
@property({ reflect: true })
|
|
30
|
+
ratio = "1/1";
|
|
31
|
+
|
|
32
|
+
override updated(): void {
|
|
33
|
+
this.updateCssVariable();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
override connectedCallback(): void {
|
|
37
|
+
super.connectedCallback();
|
|
38
|
+
this.updateCssVariable();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
private updateCssVariable(): void {
|
|
42
|
+
const ratioValue = this.parseRatio(this.ratio);
|
|
43
|
+
this.style.setProperty("--ds-aspect-ratio", String(ratioValue));
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
private parseRatio(ratio: string): number {
|
|
47
|
+
// Handle fraction format like "16/9"
|
|
48
|
+
if (ratio.includes("/")) {
|
|
49
|
+
const parts = ratio.split("/").map(Number);
|
|
50
|
+
const width = parts[0];
|
|
51
|
+
const height = parts[1];
|
|
52
|
+
if (
|
|
53
|
+
width !== undefined &&
|
|
54
|
+
height !== undefined &&
|
|
55
|
+
!Number.isNaN(width) &&
|
|
56
|
+
!Number.isNaN(height) &&
|
|
57
|
+
height !== 0
|
|
58
|
+
) {
|
|
59
|
+
return width / height;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
// Handle decimal format
|
|
63
|
+
const parsed = Number.parseFloat(ratio);
|
|
64
|
+
return Number.isNaN(parsed) ? 1 : parsed;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
override render() {
|
|
68
|
+
return html`<slot></slot>`;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
define("ds-aspect-ratio", DsAspectRatio);
|
|
73
|
+
|
|
74
|
+
declare global {
|
|
75
|
+
interface HTMLElementTagNameMap {
|
|
76
|
+
"ds-aspect-ratio": DsAspectRatio;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { type HTMLAttributes, type ReactNode, createElement, forwardRef } from "react";
|
|
4
|
+
import "@hypoth-ui/wc";
|
|
5
|
+
import {
|
|
6
|
+
type ResponsiveProp,
|
|
7
|
+
generateResponsiveDataAttr,
|
|
8
|
+
isResponsiveObject,
|
|
9
|
+
resolveResponsiveValue,
|
|
10
|
+
} from "../../primitives/responsive.js";
|
|
11
|
+
import type { AvatarSize } from "./avatar.js";
|
|
12
|
+
|
|
13
|
+
export interface AvatarGroupProps extends HTMLAttributes<HTMLElement> {
|
|
14
|
+
/**
|
|
15
|
+
* Maximum number of avatars to display before showing overflow.
|
|
16
|
+
* @default 5
|
|
17
|
+
*/
|
|
18
|
+
max?: number;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Size variant (inherited by child avatars) - supports responsive object syntax.
|
|
22
|
+
* @default "md"
|
|
23
|
+
* @example
|
|
24
|
+
* ```tsx
|
|
25
|
+
* // Single value
|
|
26
|
+
* <AvatarGroup size="md">...</AvatarGroup>
|
|
27
|
+
*
|
|
28
|
+
* // Responsive
|
|
29
|
+
* <AvatarGroup size={{ base: "sm", md: "lg" }}>...</AvatarGroup>
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
size?: ResponsiveProp<AvatarSize>;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Avatar children.
|
|
36
|
+
*/
|
|
37
|
+
children?: ReactNode;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Avatar group component for displaying multiple avatars with overflow indicator.
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```tsx
|
|
45
|
+
* <AvatarGroup max={3}>
|
|
46
|
+
* <Avatar name="Alice" />
|
|
47
|
+
* <Avatar name="Bob" />
|
|
48
|
+
* <Avatar name="Charlie" />
|
|
49
|
+
* <Avatar name="Diana" />
|
|
50
|
+
* <Avatar name="Eve" />
|
|
51
|
+
* </AvatarGroup>
|
|
52
|
+
* // Shows 3 avatars + "+2" overflow indicator
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
export const AvatarGroup = forwardRef<HTMLElement, AvatarGroupProps>(function AvatarGroup(
|
|
56
|
+
{ max = 5, size = "md", children, className, ...props },
|
|
57
|
+
ref
|
|
58
|
+
) {
|
|
59
|
+
// Resolve responsive size - use base value for the WC attribute
|
|
60
|
+
const resolvedSize = resolveResponsiveValue(size, "md");
|
|
61
|
+
const isResponsive = isResponsiveObject(size);
|
|
62
|
+
const responsiveSizeAttr = isResponsive ? generateResponsiveDataAttr(size) : undefined;
|
|
63
|
+
|
|
64
|
+
return createElement(
|
|
65
|
+
"ds-avatar-group",
|
|
66
|
+
{
|
|
67
|
+
ref,
|
|
68
|
+
max,
|
|
69
|
+
size: resolvedSize,
|
|
70
|
+
class: className,
|
|
71
|
+
// Add responsive data attribute for CSS targeting
|
|
72
|
+
"data-size-responsive": responsiveSizeAttr,
|
|
73
|
+
...props,
|
|
74
|
+
},
|
|
75
|
+
children
|
|
76
|
+
);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
// TypeScript declaration for JSX
|
|
80
|
+
declare global {
|
|
81
|
+
namespace JSX {
|
|
82
|
+
interface IntrinsicElements {
|
|
83
|
+
"ds-avatar-group": AvatarGroupProps & {
|
|
84
|
+
ref?: React.Ref<HTMLElement>;
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { type HTMLAttributes, createElement, forwardRef } from "react";
|
|
4
|
+
import "@hypoth-ui/wc";
|
|
5
|
+
import {
|
|
6
|
+
type ResponsiveProp,
|
|
7
|
+
generateResponsiveDataAttr,
|
|
8
|
+
isResponsiveObject,
|
|
9
|
+
resolveResponsiveValue,
|
|
10
|
+
} from "../../primitives/responsive.js";
|
|
11
|
+
|
|
12
|
+
export type AvatarSize = "xs" | "sm" | "md" | "lg" | "xl" | "2xl";
|
|
13
|
+
export type AvatarShape = "circle" | "square";
|
|
14
|
+
export type AvatarStatus = "online" | "offline" | "away" | "busy";
|
|
15
|
+
|
|
16
|
+
export interface AvatarProps extends Omit<HTMLAttributes<HTMLElement>, "children"> {
|
|
17
|
+
/**
|
|
18
|
+
* Image source URL.
|
|
19
|
+
*/
|
|
20
|
+
src?: string;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Alt text for image.
|
|
24
|
+
*/
|
|
25
|
+
alt?: string;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* User's name (used for initials fallback).
|
|
29
|
+
*/
|
|
30
|
+
name?: string;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Size variant - supports responsive object syntax.
|
|
34
|
+
* @default "md"
|
|
35
|
+
* @example
|
|
36
|
+
* ```tsx
|
|
37
|
+
* // Single value
|
|
38
|
+
* <Avatar name="John Doe" size="md" />
|
|
39
|
+
*
|
|
40
|
+
* // Responsive
|
|
41
|
+
* <Avatar name="John Doe" size={{ base: "sm", md: "lg" }} />
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
size?: ResponsiveProp<AvatarSize>;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Shape variant.
|
|
48
|
+
* @default "circle"
|
|
49
|
+
*/
|
|
50
|
+
shape?: AvatarShape;
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Status indicator.
|
|
54
|
+
*/
|
|
55
|
+
status?: AvatarStatus;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Whether to show status indicator.
|
|
59
|
+
* @default false
|
|
60
|
+
*/
|
|
61
|
+
showStatus?: boolean;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Avatar component for user representation with image, initials fallback, and status indicators.
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* ```tsx
|
|
69
|
+
* // With image
|
|
70
|
+
* <Avatar src="/user.jpg" alt="John Doe" name="John Doe" />
|
|
71
|
+
*
|
|
72
|
+
* // With initials fallback
|
|
73
|
+
* <Avatar name="John Doe" />
|
|
74
|
+
*
|
|
75
|
+
* // With status indicator
|
|
76
|
+
* <Avatar name="John" status="online" showStatus />
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
79
|
+
export const Avatar = forwardRef<HTMLElement, AvatarProps>(function Avatar(
|
|
80
|
+
{
|
|
81
|
+
src,
|
|
82
|
+
alt,
|
|
83
|
+
name,
|
|
84
|
+
size = "md",
|
|
85
|
+
shape = "circle",
|
|
86
|
+
status,
|
|
87
|
+
showStatus = false,
|
|
88
|
+
className,
|
|
89
|
+
...props
|
|
90
|
+
},
|
|
91
|
+
ref
|
|
92
|
+
) {
|
|
93
|
+
// Resolve responsive size - use base value for the WC attribute
|
|
94
|
+
const resolvedSize = resolveResponsiveValue(size, "md");
|
|
95
|
+
const isResponsive = isResponsiveObject(size);
|
|
96
|
+
const responsiveSizeAttr = isResponsive ? generateResponsiveDataAttr(size) : undefined;
|
|
97
|
+
|
|
98
|
+
return createElement("ds-avatar", {
|
|
99
|
+
ref,
|
|
100
|
+
src,
|
|
101
|
+
alt,
|
|
102
|
+
name,
|
|
103
|
+
size: resolvedSize,
|
|
104
|
+
shape,
|
|
105
|
+
status,
|
|
106
|
+
"show-status": showStatus || undefined,
|
|
107
|
+
class: className,
|
|
108
|
+
// Add responsive data attribute for CSS targeting
|
|
109
|
+
"data-size-responsive": responsiveSizeAttr,
|
|
110
|
+
...props,
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
// TypeScript declaration for JSX
|
|
115
|
+
declare global {
|
|
116
|
+
namespace JSX {
|
|
117
|
+
interface IntrinsicElements {
|
|
118
|
+
"ds-avatar": AvatarProps & {
|
|
119
|
+
ref?: React.Ref<HTMLElement>;
|
|
120
|
+
"show-status"?: boolean;
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Avatar compound component exports
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { AvatarGroup } from "./avatar-group.js";
|
|
8
|
+
import { Avatar as AvatarRoot } from "./avatar.js";
|
|
9
|
+
|
|
10
|
+
export type { AvatarProps, AvatarSize, AvatarShape, AvatarStatus } from "./avatar.js";
|
|
11
|
+
export type { AvatarGroupProps } from "./avatar-group.js";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Avatar compound component for user representation.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```tsx
|
|
18
|
+
* // Single avatar
|
|
19
|
+
* <Avatar src="/user.jpg" name="John Doe" />
|
|
20
|
+
*
|
|
21
|
+
* // Avatar group
|
|
22
|
+
* <Avatar.Group max={3}>
|
|
23
|
+
* <Avatar name="Alice" />
|
|
24
|
+
* <Avatar name="Bob" />
|
|
25
|
+
* <Avatar name="Charlie" />
|
|
26
|
+
* </Avatar.Group>
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export const Avatar = Object.assign(AvatarRoot, {
|
|
30
|
+
Group: AvatarGroup,
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
export { AvatarGroup };
|