@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,169 @@
|
|
|
1
|
+
import { type ButtonBehavior, createButtonBehavior } from "@hypoth-ui/primitives-dom";
|
|
2
|
+
import { type TemplateResult, html, nothing } from "lit";
|
|
3
|
+
import { property } from "lit/decorators.js";
|
|
4
|
+
import { classMap } from "lit/directives/class-map.js";
|
|
5
|
+
import { DSElement } from "../../base/ds-element.js";
|
|
6
|
+
import { StandardEvents, emitEvent } from "../../events/emit.js";
|
|
7
|
+
import { define } from "../../registry/define.js";
|
|
8
|
+
import { validateProp } from "../../utils/dev-warnings.js";
|
|
9
|
+
|
|
10
|
+
export type ButtonVariant = "primary" | "secondary" | "ghost" | "destructive";
|
|
11
|
+
export type ButtonSize = "sm" | "md" | "lg";
|
|
12
|
+
|
|
13
|
+
const VALID_VARIANTS: readonly ButtonVariant[] = ["primary", "secondary", "ghost", "destructive"];
|
|
14
|
+
const VALID_SIZES: readonly ButtonSize[] = ["sm", "md", "lg"];
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* A button component following WAI-ARIA button pattern.
|
|
18
|
+
*
|
|
19
|
+
* @element ds-button
|
|
20
|
+
* @slot - Default slot for button content
|
|
21
|
+
*
|
|
22
|
+
* @csspart button - The button element
|
|
23
|
+
*
|
|
24
|
+
* @fires ds:press - When the button is activated (click, Enter, Space)
|
|
25
|
+
*/
|
|
26
|
+
export class DsButton extends DSElement {
|
|
27
|
+
static override styles = [];
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* The button variant.
|
|
31
|
+
*/
|
|
32
|
+
@property({ type: String, reflect: true })
|
|
33
|
+
variant: ButtonVariant = "primary";
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* The button size.
|
|
37
|
+
*/
|
|
38
|
+
@property({ type: String, reflect: true })
|
|
39
|
+
size: ButtonSize = "md";
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Whether the button is disabled.
|
|
43
|
+
*/
|
|
44
|
+
@property({ type: Boolean, reflect: true })
|
|
45
|
+
disabled = false;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Whether the button is in a loading state.
|
|
49
|
+
*/
|
|
50
|
+
@property({ type: Boolean, reflect: true })
|
|
51
|
+
loading = false;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Button type attribute.
|
|
55
|
+
*/
|
|
56
|
+
@property({ type: String })
|
|
57
|
+
type: "button" | "submit" | "reset" = "button";
|
|
58
|
+
|
|
59
|
+
/** Button behavior instance */
|
|
60
|
+
private behavior!: ButtonBehavior;
|
|
61
|
+
|
|
62
|
+
override connectedCallback(): void {
|
|
63
|
+
super.connectedCallback();
|
|
64
|
+
// Create behavior with current property values
|
|
65
|
+
this.behavior = createButtonBehavior({
|
|
66
|
+
disabled: this.disabled,
|
|
67
|
+
loading: this.loading,
|
|
68
|
+
type: this.type,
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// Dev warnings: Validate variant and size
|
|
72
|
+
validateProp("ds-button", "variant", this.variant, VALID_VARIANTS);
|
|
73
|
+
validateProp("ds-button", "size", this.size, VALID_SIZES);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
override updated(changedProperties: Map<string, unknown>): void {
|
|
77
|
+
super.updated(changedProperties);
|
|
78
|
+
// Sync behavior state with component properties
|
|
79
|
+
if (
|
|
80
|
+
changedProperties.has("disabled") ||
|
|
81
|
+
changedProperties.has("loading") ||
|
|
82
|
+
changedProperties.has("type")
|
|
83
|
+
) {
|
|
84
|
+
this.behavior.setState({
|
|
85
|
+
disabled: this.disabled,
|
|
86
|
+
loading: this.loading,
|
|
87
|
+
type: this.type,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
private handleClick(event: MouseEvent): void {
|
|
93
|
+
if (this.disabled || this.loading) {
|
|
94
|
+
event.preventDefault();
|
|
95
|
+
event.stopPropagation();
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Dispatch ds:press event per standard event naming convention
|
|
100
|
+
emitEvent(this, StandardEvents.PRESS, {
|
|
101
|
+
detail: {
|
|
102
|
+
originalEvent: event,
|
|
103
|
+
target: this,
|
|
104
|
+
isKeyboard: false,
|
|
105
|
+
},
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
private handleKeyDown(event: KeyboardEvent): void {
|
|
110
|
+
// For WC compatibility, handle both Enter and Space on keydown
|
|
111
|
+
// The behavior only handles Enter on keydown (Space is typically keyup)
|
|
112
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
113
|
+
event.preventDefault();
|
|
114
|
+
if (!this.disabled && !this.loading) {
|
|
115
|
+
// Dispatch ds:press event with keyboard flag
|
|
116
|
+
// Note: We do NOT call this.click() to avoid double event emission
|
|
117
|
+
emitEvent(this, StandardEvents.PRESS, {
|
|
118
|
+
detail: {
|
|
119
|
+
originalEvent: event,
|
|
120
|
+
target: this,
|
|
121
|
+
isKeyboard: true,
|
|
122
|
+
},
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
override render(): TemplateResult {
|
|
129
|
+
const classes = {
|
|
130
|
+
"ds-button": true,
|
|
131
|
+
[`ds-button--${this.variant}`]: true,
|
|
132
|
+
[`ds-button--${this.size}`]: true,
|
|
133
|
+
"ds-button--disabled": this.disabled,
|
|
134
|
+
"ds-button--loading": this.loading,
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
// Compute ARIA props based on current component state
|
|
138
|
+
const isDisabled = this.disabled || this.loading;
|
|
139
|
+
|
|
140
|
+
return html`
|
|
141
|
+
<button
|
|
142
|
+
part="button"
|
|
143
|
+
class=${classMap(classes)}
|
|
144
|
+
type=${this.type}
|
|
145
|
+
?disabled=${this.disabled}
|
|
146
|
+
aria-disabled=${isDisabled ? "true" : nothing}
|
|
147
|
+
aria-busy=${this.loading ? "true" : nothing}
|
|
148
|
+
tabindex=${isDisabled ? -1 : 0}
|
|
149
|
+
@click=${this.handleClick}
|
|
150
|
+
@keydown=${this.handleKeyDown}
|
|
151
|
+
>
|
|
152
|
+
${this.loading ? html`<span class="ds-button__spinner" aria-hidden="true"></span>` : null}
|
|
153
|
+
<span class="ds-button__content">
|
|
154
|
+
<slot></slot>
|
|
155
|
+
</span>
|
|
156
|
+
</button>
|
|
157
|
+
`;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Register the component
|
|
162
|
+
define("ds-button", DsButton);
|
|
163
|
+
|
|
164
|
+
// TypeScript declaration for HTML
|
|
165
|
+
declare global {
|
|
166
|
+
interface HTMLElementTagNameMap {
|
|
167
|
+
"ds-button": DsButton;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { type HTMLAttributes, createElement, forwardRef, useEffect, useRef } from "react";
|
|
4
|
+
import "@hypoth-ui/wc";
|
|
5
|
+
|
|
6
|
+
export type CalendarSize = "default" | "compact";
|
|
7
|
+
|
|
8
|
+
export interface CalendarProps extends Omit<HTMLAttributes<HTMLElement>, "onChange"> {
|
|
9
|
+
/**
|
|
10
|
+
* Selected date (ISO format: YYYY-MM-DD).
|
|
11
|
+
*/
|
|
12
|
+
value?: string;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Minimum selectable date (ISO format).
|
|
16
|
+
*/
|
|
17
|
+
min?: string;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Maximum selectable date (ISO format).
|
|
21
|
+
*/
|
|
22
|
+
max?: string;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Disabled dates (array of ISO format strings).
|
|
26
|
+
*/
|
|
27
|
+
disabledDates?: string[];
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Locale for month/day names.
|
|
31
|
+
* @default "en-US"
|
|
32
|
+
*/
|
|
33
|
+
locale?: string;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Size variant.
|
|
37
|
+
* @default "default"
|
|
38
|
+
*/
|
|
39
|
+
size?: CalendarSize;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* First day of week (0 = Sunday, 1 = Monday).
|
|
43
|
+
* @default 0
|
|
44
|
+
*/
|
|
45
|
+
firstDayOfWeek?: 0 | 1 | 2 | 3 | 4 | 5 | 6;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Callback when a date is selected.
|
|
49
|
+
*/
|
|
50
|
+
onChange?: (value: string, date: Date) => void;
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Callback when the displayed month changes.
|
|
54
|
+
*/
|
|
55
|
+
onMonthChange?: (month: number, year: number) => void;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Calendar component for date selection.
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* ```tsx
|
|
63
|
+
* <Calendar
|
|
64
|
+
* value="2024-01-15"
|
|
65
|
+
* min="2024-01-01"
|
|
66
|
+
* max="2024-12-31"
|
|
67
|
+
* onChange={(value, date) => console.log(value, date)}
|
|
68
|
+
* />
|
|
69
|
+
* ```
|
|
70
|
+
*/
|
|
71
|
+
export const Calendar = forwardRef<HTMLElement, CalendarProps>(function Calendar(
|
|
72
|
+
{
|
|
73
|
+
value,
|
|
74
|
+
min,
|
|
75
|
+
max,
|
|
76
|
+
disabledDates = [],
|
|
77
|
+
locale = "en-US",
|
|
78
|
+
size = "default",
|
|
79
|
+
firstDayOfWeek = 0,
|
|
80
|
+
onChange,
|
|
81
|
+
onMonthChange,
|
|
82
|
+
className,
|
|
83
|
+
...props
|
|
84
|
+
},
|
|
85
|
+
forwardedRef
|
|
86
|
+
) {
|
|
87
|
+
const internalRef = useRef<HTMLElement>(null);
|
|
88
|
+
|
|
89
|
+
// Sync forwarded ref
|
|
90
|
+
useEffect(() => {
|
|
91
|
+
if (typeof forwardedRef === "function") {
|
|
92
|
+
forwardedRef(internalRef.current);
|
|
93
|
+
} else if (forwardedRef) {
|
|
94
|
+
(forwardedRef as React.MutableRefObject<HTMLElement | null>).current = internalRef.current;
|
|
95
|
+
}
|
|
96
|
+
}, [forwardedRef]);
|
|
97
|
+
|
|
98
|
+
// Set up event listeners
|
|
99
|
+
useEffect(() => {
|
|
100
|
+
const element = internalRef.current;
|
|
101
|
+
if (!element) return;
|
|
102
|
+
|
|
103
|
+
const handleChange = (e: Event) => {
|
|
104
|
+
const event = e as CustomEvent<{ value: string; date: string }>;
|
|
105
|
+
onChange?.(event.detail.value, new Date(event.detail.date));
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
const handleMonthChange = (e: Event) => {
|
|
109
|
+
const event = e as CustomEvent<{ month: number; year: number }>;
|
|
110
|
+
onMonthChange?.(event.detail.month, event.detail.year);
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
element.addEventListener("ds:change", handleChange);
|
|
114
|
+
element.addEventListener("ds:month-change", handleMonthChange);
|
|
115
|
+
|
|
116
|
+
return () => {
|
|
117
|
+
element.removeEventListener("ds:change", handleChange);
|
|
118
|
+
element.removeEventListener("ds:month-change", handleMonthChange);
|
|
119
|
+
};
|
|
120
|
+
}, [onChange, onMonthChange]);
|
|
121
|
+
|
|
122
|
+
return createElement("ds-calendar", {
|
|
123
|
+
ref: internalRef,
|
|
124
|
+
value,
|
|
125
|
+
min,
|
|
126
|
+
max,
|
|
127
|
+
"disabled-dates": disabledDates.join(","),
|
|
128
|
+
locale,
|
|
129
|
+
size,
|
|
130
|
+
"first-day-of-week": firstDayOfWeek,
|
|
131
|
+
class: className,
|
|
132
|
+
...props,
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
// TypeScript declaration for JSX
|
|
137
|
+
declare global {
|
|
138
|
+
namespace JSX {
|
|
139
|
+
interface IntrinsicElements {
|
|
140
|
+
"ds-calendar": CalendarProps & {
|
|
141
|
+
ref?: React.Ref<HTMLElement>;
|
|
142
|
+
"disabled-dates"?: string;
|
|
143
|
+
"first-day-of-week"?: number;
|
|
144
|
+
"onDs-change"?: (event: CustomEvent) => void;
|
|
145
|
+
"onDs-month-change"?: (event: CustomEvent) => void;
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
import { type TemplateResult, html, nothing } from "lit";
|
|
2
|
+
import { property, state } 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
|
+
|
|
8
|
+
export type CalendarSize = "default" | "compact";
|
|
9
|
+
|
|
10
|
+
// Navigation icons
|
|
11
|
+
const chevronLeftIcon = html`
|
|
12
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true">
|
|
13
|
+
<path d="M15 18l-6-6 6-6" />
|
|
14
|
+
</svg>
|
|
15
|
+
`;
|
|
16
|
+
|
|
17
|
+
const chevronRightIcon = html`
|
|
18
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true">
|
|
19
|
+
<path d="M9 18l6-6-6-6" />
|
|
20
|
+
</svg>
|
|
21
|
+
`;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Calendar component for date selection.
|
|
25
|
+
*
|
|
26
|
+
* @element ds-calendar
|
|
27
|
+
*
|
|
28
|
+
* @fires ds-change - When a date is selected
|
|
29
|
+
* @fires ds-month-change - When the displayed month changes
|
|
30
|
+
*
|
|
31
|
+
* @cssprop --ds-calendar-width - Calendar width
|
|
32
|
+
* @cssprop --ds-calendar-cell-size - Day cell size
|
|
33
|
+
*/
|
|
34
|
+
export class DsCalendar extends DSElement {
|
|
35
|
+
static override styles = [];
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Selected date (ISO format: YYYY-MM-DD).
|
|
39
|
+
*/
|
|
40
|
+
@property({ type: String })
|
|
41
|
+
value = "";
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Minimum selectable date (ISO format).
|
|
45
|
+
*/
|
|
46
|
+
@property({ type: String })
|
|
47
|
+
min = "";
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Maximum selectable date (ISO format).
|
|
51
|
+
*/
|
|
52
|
+
@property({ type: String })
|
|
53
|
+
max = "";
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Disabled dates (comma-separated ISO format).
|
|
57
|
+
*/
|
|
58
|
+
@property({ type: String, attribute: "disabled-dates" })
|
|
59
|
+
disabledDates = "";
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Locale for month/day names.
|
|
63
|
+
*/
|
|
64
|
+
@property({ type: String })
|
|
65
|
+
locale = "en-US";
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Size variant.
|
|
69
|
+
*/
|
|
70
|
+
@property({ type: String, reflect: true })
|
|
71
|
+
size: CalendarSize = "default";
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* First day of week (0 = Sunday, 1 = Monday).
|
|
75
|
+
*/
|
|
76
|
+
@property({ type: Number, attribute: "first-day-of-week" })
|
|
77
|
+
firstDayOfWeek = 0;
|
|
78
|
+
|
|
79
|
+
@state()
|
|
80
|
+
private viewDate: Date = new Date();
|
|
81
|
+
|
|
82
|
+
private get selectedDate(): Date | null {
|
|
83
|
+
return this.value ? new Date(this.value) : null;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
private get minDate(): Date | null {
|
|
87
|
+
return this.min ? new Date(this.min) : null;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
private get maxDate(): Date | null {
|
|
91
|
+
return this.max ? new Date(this.max) : null;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
private get disabledDateSet(): Set<string> {
|
|
95
|
+
if (!this.disabledDates) return new Set();
|
|
96
|
+
return new Set(this.disabledDates.split(",").map((d) => d.trim()));
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
private get weekdayNames(): string[] {
|
|
100
|
+
const formatter = new Intl.DateTimeFormat(this.locale, { weekday: "short" });
|
|
101
|
+
const days: string[] = [];
|
|
102
|
+
// Start from a known Sunday
|
|
103
|
+
const baseDate = new Date(2024, 0, 7); // Jan 7, 2024 is a Sunday
|
|
104
|
+
for (let i = 0; i < 7; i++) {
|
|
105
|
+
const day = new Date(baseDate);
|
|
106
|
+
day.setDate(baseDate.getDate() + ((i + this.firstDayOfWeek) % 7));
|
|
107
|
+
days.push(formatter.format(day));
|
|
108
|
+
}
|
|
109
|
+
return days;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
private get monthYearLabel(): string {
|
|
113
|
+
const formatter = new Intl.DateTimeFormat(this.locale, {
|
|
114
|
+
month: "long",
|
|
115
|
+
year: "numeric",
|
|
116
|
+
});
|
|
117
|
+
return formatter.format(this.viewDate);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
private get calendarDays(): Array<{ date: Date; isOutside: boolean }> {
|
|
121
|
+
const days: Array<{ date: Date; isOutside: boolean }> = [];
|
|
122
|
+
const year = this.viewDate.getFullYear();
|
|
123
|
+
const month = this.viewDate.getMonth();
|
|
124
|
+
|
|
125
|
+
// First day of the month
|
|
126
|
+
const firstOfMonth = new Date(year, month, 1);
|
|
127
|
+
// Day of week of first day (0-6)
|
|
128
|
+
const startDayOfWeek = firstOfMonth.getDay();
|
|
129
|
+
// How many days to show from previous month
|
|
130
|
+
const daysFromPrevMonth = (startDayOfWeek - this.firstDayOfWeek + 7) % 7;
|
|
131
|
+
|
|
132
|
+
// Add days from previous month
|
|
133
|
+
for (let i = daysFromPrevMonth; i > 0; i--) {
|
|
134
|
+
const date = new Date(year, month, 1 - i);
|
|
135
|
+
days.push({ date, isOutside: true });
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Add days of current month
|
|
139
|
+
const daysInMonth = new Date(year, month + 1, 0).getDate();
|
|
140
|
+
for (let i = 1; i <= daysInMonth; i++) {
|
|
141
|
+
days.push({ date: new Date(year, month, i), isOutside: false });
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Add days from next month to complete grid (6 rows × 7 days = 42)
|
|
145
|
+
const remaining = 42 - days.length;
|
|
146
|
+
for (let i = 1; i <= remaining; i++) {
|
|
147
|
+
const date = new Date(year, month + 1, i);
|
|
148
|
+
days.push({ date, isOutside: true });
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return days;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
private isToday(date: Date): boolean {
|
|
155
|
+
const today = new Date();
|
|
156
|
+
return (
|
|
157
|
+
date.getDate() === today.getDate() &&
|
|
158
|
+
date.getMonth() === today.getMonth() &&
|
|
159
|
+
date.getFullYear() === today.getFullYear()
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
private isSelected(date: Date): boolean {
|
|
164
|
+
if (!this.selectedDate) return false;
|
|
165
|
+
return (
|
|
166
|
+
date.getDate() === this.selectedDate.getDate() &&
|
|
167
|
+
date.getMonth() === this.selectedDate.getMonth() &&
|
|
168
|
+
date.getFullYear() === this.selectedDate.getFullYear()
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
private isDisabled(date: Date): boolean {
|
|
173
|
+
const dateStr = date.toISOString().split("T")[0] ?? "";
|
|
174
|
+
|
|
175
|
+
// Check disabled dates
|
|
176
|
+
if (dateStr && this.disabledDateSet.has(dateStr)) return true;
|
|
177
|
+
|
|
178
|
+
// Check min/max bounds
|
|
179
|
+
if (this.minDate && date < this.minDate) return true;
|
|
180
|
+
if (this.maxDate && date > this.maxDate) return true;
|
|
181
|
+
|
|
182
|
+
return false;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
private formatDateISO(date: Date): string {
|
|
186
|
+
return date.toISOString().split("T")[0] ?? "";
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
private handlePrevMonth(): void {
|
|
190
|
+
const newDate = new Date(this.viewDate);
|
|
191
|
+
newDate.setMonth(newDate.getMonth() - 1);
|
|
192
|
+
this.viewDate = newDate;
|
|
193
|
+
|
|
194
|
+
emitEvent(this, "month-change", {
|
|
195
|
+
detail: {
|
|
196
|
+
month: newDate.getMonth() + 1,
|
|
197
|
+
year: newDate.getFullYear(),
|
|
198
|
+
},
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
private handleNextMonth(): void {
|
|
203
|
+
const newDate = new Date(this.viewDate);
|
|
204
|
+
newDate.setMonth(newDate.getMonth() + 1);
|
|
205
|
+
this.viewDate = newDate;
|
|
206
|
+
|
|
207
|
+
emitEvent(this, "month-change", {
|
|
208
|
+
detail: {
|
|
209
|
+
month: newDate.getMonth() + 1,
|
|
210
|
+
year: newDate.getFullYear(),
|
|
211
|
+
},
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
private handleDateSelect(date: Date): void {
|
|
216
|
+
if (this.isDisabled(date)) return;
|
|
217
|
+
|
|
218
|
+
this.value = this.formatDateISO(date);
|
|
219
|
+
|
|
220
|
+
emitEvent(this, "change", {
|
|
221
|
+
detail: {
|
|
222
|
+
value: this.value,
|
|
223
|
+
date: date.toISOString(),
|
|
224
|
+
},
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
private handleKeyDown(event: KeyboardEvent, date: Date): void {
|
|
229
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
230
|
+
event.preventDefault();
|
|
231
|
+
this.handleDateSelect(date);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
override render(): TemplateResult {
|
|
236
|
+
const classes = {
|
|
237
|
+
"ds-calendar": true,
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
return html`
|
|
241
|
+
<div
|
|
242
|
+
class=${classMap(classes)}
|
|
243
|
+
role="application"
|
|
244
|
+
aria-label="Calendar"
|
|
245
|
+
data-size=${this.size !== "default" ? this.size : nothing}
|
|
246
|
+
>
|
|
247
|
+
<div class="ds-calendar__header">
|
|
248
|
+
<button
|
|
249
|
+
type="button"
|
|
250
|
+
class="ds-calendar__nav-button"
|
|
251
|
+
aria-label="Previous month"
|
|
252
|
+
@click=${this.handlePrevMonth}
|
|
253
|
+
>
|
|
254
|
+
${chevronLeftIcon}
|
|
255
|
+
</button>
|
|
256
|
+
<span class="ds-calendar__title" aria-live="polite">
|
|
257
|
+
${this.monthYearLabel}
|
|
258
|
+
</span>
|
|
259
|
+
<button
|
|
260
|
+
type="button"
|
|
261
|
+
class="ds-calendar__nav-button"
|
|
262
|
+
aria-label="Next month"
|
|
263
|
+
@click=${this.handleNextMonth}
|
|
264
|
+
>
|
|
265
|
+
${chevronRightIcon}
|
|
266
|
+
</button>
|
|
267
|
+
</div>
|
|
268
|
+
|
|
269
|
+
<div class="ds-calendar__weekdays" role="row">
|
|
270
|
+
${this.weekdayNames.map(
|
|
271
|
+
(day) => html`
|
|
272
|
+
<div class="ds-calendar__weekday" role="columnheader">${day}</div>
|
|
273
|
+
`
|
|
274
|
+
)}
|
|
275
|
+
</div>
|
|
276
|
+
|
|
277
|
+
<div class="ds-calendar__grid" role="grid">
|
|
278
|
+
${this.calendarDays.map(({ date, isOutside }) => {
|
|
279
|
+
const disabled = this.isDisabled(date);
|
|
280
|
+
const selected = this.isSelected(date);
|
|
281
|
+
const today = this.isToday(date);
|
|
282
|
+
|
|
283
|
+
return html`
|
|
284
|
+
<button
|
|
285
|
+
type="button"
|
|
286
|
+
class="ds-calendar__day"
|
|
287
|
+
role="gridcell"
|
|
288
|
+
tabindex=${selected ? 0 : -1}
|
|
289
|
+
aria-selected=${selected ? "true" : "false"}
|
|
290
|
+
aria-disabled=${disabled ? "true" : nothing}
|
|
291
|
+
?data-outside=${isOutside}
|
|
292
|
+
?data-selected=${selected}
|
|
293
|
+
?data-today=${today}
|
|
294
|
+
?data-disabled=${disabled}
|
|
295
|
+
@click=${() => this.handleDateSelect(date)}
|
|
296
|
+
@keydown=${(e: KeyboardEvent) => this.handleKeyDown(e, date)}
|
|
297
|
+
>
|
|
298
|
+
${date.getDate()}
|
|
299
|
+
</button>
|
|
300
|
+
`;
|
|
301
|
+
})}
|
|
302
|
+
</div>
|
|
303
|
+
</div>
|
|
304
|
+
`;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// Register the component
|
|
309
|
+
define("ds-calendar", DsCalendar);
|
|
310
|
+
|
|
311
|
+
// TypeScript declaration for HTML
|
|
312
|
+
declare global {
|
|
313
|
+
interface HTMLElementTagNameMap {
|
|
314
|
+
"ds-calendar": DsCalendar;
|
|
315
|
+
}
|
|
316
|
+
}
|