@fusion.dev/helix-headless 0.146.0 → 0.148.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/custom-elements.json +9287 -1084
- package/dist/accordion/item/accordion-item.d.ts +43 -21
- package/dist/accordion/item/accordion-item.js +37 -11
- package/dist/accordion/root/accordion-root.d.ts +8 -2
- package/dist/accordion/root/accordion-root.js +6 -8
- package/dist/announcement/root/announcement-root.d.ts +66 -6
- package/dist/announcement/root/announcement-root.js +144 -13
- package/dist/area-chart/root/area-chart-root.d.ts +18 -1
- package/dist/area-chart/root/area-chart-root.js +14 -7
- package/dist/avatar/root/avatar-root.d.ts +31 -1
- package/dist/avatar/root/avatar-root.js +11 -1
- package/dist/badge/count.d.ts +14 -0
- package/dist/badge/count.js +20 -0
- package/dist/badge/root/badge-root.d.ts +57 -6
- package/dist/badge/root/badge-root.js +77 -8
- package/dist/bar-chart/root/bar-chart-root.js +11 -20
- package/dist/bar-chart/stack.d.ts +10 -0
- package/dist/bar-chart/stack.js +8 -0
- package/dist/blockquote/root/blockquote-root.d.ts +66 -8
- package/dist/blockquote/root/blockquote-root.js +85 -8
- package/dist/breadcrumbs/breadcrumb/breadcrumb.d.ts +14 -0
- package/dist/breadcrumbs/breadcrumb/breadcrumb.js +12 -2
- package/dist/breadcrumbs/root/breadcrumbs-root.js +2 -2
- package/dist/button/root/button-root.d.ts +24 -38
- package/dist/button/root/button-root.js +6 -37
- package/dist/button/submitter.d.ts +27 -0
- package/dist/button/submitter.js +25 -0
- package/dist/button-group/arrows.d.ts +14 -0
- package/dist/button-group/arrows.js +10 -0
- package/dist/button-group/root/button-group-root.d.ts +141 -3
- package/dist/button-group/root/button-group-root.js +142 -2
- package/dist/canvas/edge-pan.d.ts +61 -0
- package/dist/canvas/edge-pan.js +63 -0
- package/dist/canvas/node/canvas-node.d.ts +12 -2
- package/dist/canvas/node/canvas-node.js +6 -2
- package/dist/canvas/root/canvas-document.d.ts +10 -0
- package/dist/canvas/root/canvas-document.js +1 -0
- package/dist/canvas/root/canvas-root.d.ts +107 -5
- package/dist/canvas/root/canvas-root.js +140 -36
- package/dist/canvas/snap.d.ts +42 -0
- package/dist/canvas/snap.js +32 -0
- package/dist/card/root/card-root.d.ts +12 -1
- package/dist/card/root/card-root.js +11 -4
- package/dist/carousel/root/carousel-root.d.ts +4 -3
- package/dist/carousel/root/carousel-root.js +2 -6
- package/dist/chat/root/chat-root.d.ts +28 -4
- package/dist/chat/root/chat-root.js +12 -7
- package/dist/checkbox/root/checkbox-root.js +5 -7
- package/dist/checkbox-group/root/checkbox-group-root.d.ts +13 -0
- package/dist/checkbox-group/root/checkbox-group-root.js +16 -7
- package/dist/checkbox-group/select-all.d.ts +9 -4
- package/dist/checkbox-group/select-all.js +1 -1
- package/dist/code-block/root/code-block-root.d.ts +41 -18
- package/dist/code-block/root/code-block-root.js +21 -6
- package/dist/color-input/root/color-input-root.d.ts +11 -0
- package/dist/color-input/root/color-input-root.js +12 -5
- package/dist/color-picker/channels.js +1 -2
- package/dist/color-picker/root/color-picker-root.d.ts +32 -24
- package/dist/color-picker/root/color-picker-root.js +99 -55
- package/dist/color-picker/wheel.d.ts +28 -0
- package/dist/color-picker/wheel.js +15 -0
- package/dist/combobox/root/combobox-root.d.ts +83 -11
- package/dist/combobox/root/combobox-root.js +81 -18
- package/dist/command/root/command-root.d.ts +7 -4
- package/dist/command/root/command-root.js +2 -19
- package/dist/copy-button/root/copy-button-root.d.ts +16 -1
- package/dist/copy-button/root/copy-button-root.js +7 -2
- package/dist/data-table/keys.d.ts +0 -18
- package/dist/data-table/keys.js +1 -11
- package/dist/data-table/root/data-table-root.js +29 -50
- package/dist/date-input/root/date-input-root.d.ts +8 -1
- package/dist/date-input/root/date-input-root.js +8 -5
- package/dist/date-picker/root/date-picker-root.d.ts +14 -9
- package/dist/date-picker/root/date-picker-root.js +21 -16
- package/dist/description-list/item/description-list-item.d.ts +22 -4
- package/dist/description-list/item/description-list-item.js +14 -4
- package/dist/divider/root/divider-root.d.ts +45 -16
- package/dist/divider/root/divider-root.js +28 -4
- package/dist/donut-chart/root/donut-chart-root.js +13 -6
- package/dist/donut-chart/slice-label.d.ts +35 -0
- package/dist/donut-chart/slice-label.js +11 -0
- package/dist/drawer/root/drawer-root.d.ts +4 -2
- package/dist/drawer/root/drawer-root.js +15 -3
- package/dist/drilldown/item/drilldown-item.d.ts +21 -1
- package/dist/drilldown/item/drilldown-item.js +38 -4
- package/dist/drilldown/root/drilldown-root.js +3 -2
- package/dist/element-events.generated.js +5 -1
- package/dist/empty/root/empty-root.d.ts +46 -2
- package/dist/empty/root/empty-root.js +50 -5
- package/dist/file-input/root/file-input-root.d.ts +34 -6
- package/dist/file-input/root/file-input-root.js +55 -21
- package/dist/file-input/status.d.ts +24 -0
- package/dist/file-input/status.js +11 -0
- package/dist/filter-input/chip/filter-chip.d.ts +23 -0
- package/dist/filter-input/chip/filter-chip.js +10 -2
- package/dist/filter-input/root/filter-input-root.d.ts +8 -0
- package/dist/filter-input/root/filter-input-root.js +17 -27
- package/dist/format-date/fields.d.ts +20 -0
- package/dist/format-date/fields.js +14 -0
- package/dist/format-date/options.d.ts +5 -5
- package/dist/format-date/options.js +10 -39
- package/dist/format-date/root/format-date-root.d.ts +53 -4
- package/dist/format-date/root/format-date-root.js +38 -50
- package/dist/graph/root/graph-root.d.ts +23 -5
- package/dist/graph/root/graph-root.js +17 -20
- package/dist/heatmap/root/buckets.d.ts +21 -0
- package/dist/heatmap/root/buckets.js +34 -0
- package/dist/heatmap/root/heatmap-root.d.ts +76 -3
- package/dist/heatmap/root/heatmap-root.js +105 -20
- package/dist/icon/index.d.ts +1 -1
- package/dist/icon/index.js +1 -1
- package/dist/icon/registry.d.ts +26 -1
- package/dist/icon/registry.js +12 -1
- package/dist/icon/root/icon-root.d.ts +13 -0
- package/dist/icon/root/icon-root.js +23 -2
- package/dist/icon/root/index.d.ts +1 -1
- package/dist/icon/root/index.js +1 -1
- package/dist/image/root/image-root.d.ts +20 -0
- package/dist/image/root/image-root.js +6 -1
- package/dist/input/root/input-root.d.ts +23 -2
- package/dist/input/root/input-root.js +12 -8
- package/dist/kbd/root/kbd-root.d.ts +20 -3
- package/dist/kbd/root/kbd-root.js +23 -50
- package/dist/legend/hidden-series.d.ts +10 -2
- package/dist/legend/hidden-series.js +5 -2
- package/dist/legend/root/legend-root.d.ts +25 -7
- package/dist/legend/root/legend-root.js +25 -26
- package/dist/lightbox/root/lightbox-root.d.ts +50 -5
- package/dist/lightbox/root/lightbox-root.js +76 -8
- package/dist/lightbox/zoom.d.ts +2 -0
- package/dist/lightbox/zoom.js +5 -3
- package/dist/line-chart/root/line-chart-root.d.ts +16 -0
- package/dist/line-chart/root/line-chart-root.js +10 -2
- package/dist/list/root/list-root.d.ts +10 -2
- package/dist/list/root/list-root.js +31 -24
- package/dist/list/selection.d.ts +17 -0
- package/dist/list/selection.js +16 -0
- package/dist/listbox/root/listbox-root.d.ts +125 -26
- package/dist/listbox/root/listbox-root.js +156 -166
- package/dist/map/marker/map-marker.d.ts +2 -1
- package/dist/map/root/map-root.d.ts +40 -2
- package/dist/map/root/map-root.js +64 -23
- package/dist/megamenu/hand-over.d.ts +75 -0
- package/dist/megamenu/hand-over.js +67 -0
- package/dist/megamenu/root/megamenu-root.d.ts +38 -14
- package/dist/megamenu/root/megamenu-root.js +29 -50
- package/dist/menu/item/menu-item.js +4 -4
- package/dist/menu/root/menu-root.d.ts +5 -2
- package/dist/meter/root/meter-root.d.ts +42 -0
- package/dist/meter/root/meter-root.js +33 -7
- package/dist/navigation/root/navigation-root.js +5 -8
- package/dist/notifications/group/notification-group.d.ts +8 -1
- package/dist/notifications/group/notification-group.js +12 -6
- package/dist/notifications/notification/notification.d.ts +12 -1
- package/dist/notifications/notification/notification.js +3 -1
- package/dist/notifications/root/notifications-root.d.ts +48 -3
- package/dist/notifications/root/notifications-root.js +36 -6
- package/dist/number-input/grain.d.ts +28 -0
- package/dist/number-input/grain.js +14 -0
- package/dist/number-input/root/number-input-root.d.ts +17 -1
- package/dist/number-input/root/number-input-root.js +29 -18
- package/dist/object-inspector/root/object-inspector-root.d.ts +17 -6
- package/dist/object-inspector/root/object-inspector-root.js +31 -20
- package/dist/option/index.d.ts +1 -0
- package/dist/option/index.js +1 -0
- package/dist/option/separator/option-separator.d.ts +30 -0
- package/dist/option/separator/option-separator.js +21 -0
- package/dist/outline/root/outline-root.d.ts +12 -0
- package/dist/outline/root/outline-root.js +5 -19
- package/dist/pagination/size/pagination-size.d.ts +6 -0
- package/dist/pagination/size/pagination-size.js +5 -3
- package/dist/pin-input/code.d.ts +51 -1
- package/dist/pin-input/code.js +37 -0
- package/dist/pin-input/root/pin-input-root.d.ts +98 -121
- package/dist/pin-input/root/pin-input-root.js +151 -156
- package/dist/popover/hide-outside.js +2 -9
- package/dist/popover/root/popover-root.d.ts +7 -1
- package/dist/popover/root/popover-root.js +9 -1
- package/dist/progress/root/progress-root.d.ts +27 -0
- package/dist/progress/root/progress-root.js +25 -7
- package/dist/qr-code/export.d.ts +19 -0
- package/dist/qr-code/export.js +14 -0
- package/dist/qr-code/name.d.ts +11 -0
- package/dist/qr-code/name.js +7 -0
- package/dist/qr-code/root/qr-code-root.d.ts +31 -9
- package/dist/qr-code/root/qr-code-root.js +29 -17
- package/dist/radio/group/radio-group.d.ts +15 -0
- package/dist/radio/root/radio-root.js +2 -2
- package/dist/rating/root/rating-root.d.ts +22 -9
- package/dist/rating/root/rating-root.js +15 -39
- package/dist/scatter-chart/measures.d.ts +22 -0
- package/dist/scatter-chart/measures.js +11 -0
- package/dist/scatter-chart/root/scatter-chart-root.d.ts +26 -0
- package/dist/scatter-chart/root/scatter-chart-root.js +21 -7
- package/dist/scroll-area/scrollbar.d.ts +0 -8
- package/dist/scroll-area/scrollbar.js +1 -1
- package/dist/select/align.d.ts +47 -0
- package/dist/select/align.js +7 -0
- package/dist/select/root/select-root.d.ts +115 -11
- package/dist/select/root/select-root.js +104 -20
- package/dist/slider/root/slider-root.d.ts +18 -1
- package/dist/slider/root/slider-root.js +22 -0
- package/dist/sparkline/readings.d.ts +30 -12
- package/dist/sparkline/readings.js +32 -15
- package/dist/sparkline/root/sparkline-root.d.ts +46 -3
- package/dist/sparkline/root/sparkline-root.js +60 -21
- package/dist/speed-dial/group/speed-dial-group.d.ts +48 -0
- package/dist/speed-dial/group/speed-dial-group.js +43 -0
- package/dist/speed-dial/index.d.ts +1 -0
- package/dist/speed-dial/index.js +1 -0
- package/dist/speed-dial/item/speed-dial-item.d.ts +27 -2
- package/dist/speed-dial/item/speed-dial-item.js +43 -5
- package/dist/speed-dial/long-press.d.ts +50 -0
- package/dist/speed-dial/long-press.js +48 -0
- package/dist/speed-dial/root/speed-dial-root.d.ts +86 -1
- package/dist/speed-dial/root/speed-dial-root.js +123 -6
- package/dist/splitter/root/splitter-root.d.ts +9 -2
- package/dist/splitter/root/splitter-root.js +18 -3
- package/dist/steps/root/steps-root.d.ts +8 -1
- package/dist/steps/root/steps-root.js +6 -1
- package/dist/steps/step/step.d.ts +1 -0
- package/dist/steps/step/step.js +1 -1
- package/dist/table/cell/table-cell.d.ts +8 -1
- package/dist/table/cell/table-cell.js +6 -2
- package/dist/table/column/table-column.d.ts +6 -0
- package/dist/table/column/table-column.js +5 -1
- package/dist/table/grid-controller.d.ts +117 -0
- package/dist/table/grid-controller.js +293 -0
- package/dist/table/root/table-root.d.ts +47 -3
- package/dist/table/root/table-root.js +93 -29
- package/dist/table/row/table-row.d.ts +36 -0
- package/dist/table/row/table-row.js +52 -2
- package/dist/tabs/root/tabs-root.d.ts +5 -3
- package/dist/tag/group/tag-group.d.ts +16 -4
- package/dist/tag/group/tag-group.js +23 -20
- package/dist/textarea/root/textarea-root.d.ts +14 -2
- package/dist/textarea/root/textarea-root.js +6 -7
- package/dist/time-input/root/time-input-root.d.ts +5 -1
- package/dist/time-input/root/time-input-root.js +10 -7
- package/dist/time-picker/root/time-picker-root.d.ts +12 -14
- package/dist/time-picker/root/time-picker-root.js +18 -23
- package/dist/toast/item/toast-item.d.ts +9 -6
- package/dist/toast/item/toast-item.js +1 -1
- package/dist/toast/root/toast-root.d.ts +40 -4
- package/dist/toast/root/toast-root.js +68 -16
- package/dist/toast/words.d.ts +12 -0
- package/dist/toast/words.js +25 -0
- package/dist/toggle/group/toggle-group.d.ts +29 -5
- package/dist/toggle/group/toggle-group.js +26 -43
- package/dist/toggle/root/toggle-root.js +2 -4
- package/dist/toolbar/root/toolbar-root.d.ts +52 -5
- package/dist/toolbar/root/toolbar-root.js +88 -13
- package/dist/tooltip/root/tooltip-root.d.ts +7 -1
- package/dist/tooltip/root/tooltip-root.js +10 -2
- package/dist/tour/root/tour-root.d.ts +15 -0
- package/dist/tour/root/tour-root.js +20 -1
- package/dist/tour/stop/tour-stop.d.ts +3 -0
- package/dist/tour/stop/tour-stop.js +3 -3
- package/dist/tree/root/tree-root.js +2 -2
- package/dist/trend/figure.d.ts +16 -0
- package/dist/trend/figure.js +8 -0
- package/dist/trend/root/trend-root.d.ts +41 -2
- package/dist/trend/root/trend-root.js +29 -3
- package/dist/video/root/extra-controls.d.ts +12 -0
- package/dist/video/root/extra-controls.js +6 -2
- package/dist/video/root/video-root.d.ts +16 -1
- package/dist/video/root/video-root.js +15 -1
- package/dist/video-playlist/root/video-playlist-root.d.ts +11 -1
- package/dist/video-playlist/root/video-playlist-root.js +3 -0
- package/dist/virtual-list/fill.d.ts +11 -0
- package/dist/virtual-list/fill.js +9 -0
- package/dist/virtual-list/keys.d.ts +16 -7
- package/dist/virtual-list/keys.js +17 -6
- package/dist/virtual-list/plan.d.ts +17 -1
- package/dist/virtual-list/plan.js +13 -2
- package/dist/virtual-list/root/virtual-list-root.d.ts +25 -3
- package/dist/virtual-list/root/virtual-list-root.js +53 -41
- package/lint.json +1 -1
- package/package.json +5 -5
- package/types/jsx.d.ts +4934 -954
- package/types/svelte.d.ts +2 -0
- package/types/vue.d.ts +946 -253
- package/dist/color-picker/swatches.d.ts +0 -12
- package/dist/color-picker/swatches.js +0 -26
- package/dist/rating/steps.d.ts +0 -7
- package/dist/rating/steps.js +0 -9
- package/dist/tooltip/focus-target.d.ts +0 -6
- package/dist/tooltip/focus-target.js +0 -9
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { AriaForwardController, HelixFormElement } from '@fusion.dev/helix-core';
|
|
2
|
-
import { type PropertyValues, type TemplateResult } from 'lit';
|
|
2
|
+
import { nothing, type PropertyValues, type TemplateResult } from 'lit';
|
|
3
|
+
import { type FileStatus } from '../status.js';
|
|
4
|
+
export type { FileStatus } from '../status.js';
|
|
3
5
|
import '../../tag/index.js';
|
|
4
6
|
declare const HelixHeadlessFileInput_base: (new (...args: any[]) => import("@fusion.dev/helix-core").MixinFieldInterface) & typeof HelixFormElement;
|
|
5
7
|
/**
|
|
@@ -59,6 +61,9 @@ declare const HelixHeadlessFileInput_base: (new (...args: any[]) => import("@fus
|
|
|
59
61
|
* @csspart feedback - The message that says what is wrong.
|
|
60
62
|
* @csspart field - The box you press or drop files on.
|
|
61
63
|
* @csspart file - One chosen file.
|
|
64
|
+
* @csspart file-done - A file whose upload `setFileStatus` says is done. Set together with `file`.
|
|
65
|
+
* @csspart file-error - A file whose upload `setFileStatus` says failed. Set together with `file`.
|
|
66
|
+
* @csspart file-uploading - A file whose upload `setFileStatus` says is under way. Set together with `file`.
|
|
62
67
|
* @csspart hint - Help under the field, while nothing is wrong.
|
|
63
68
|
* @csspart kind - A file's type.
|
|
64
69
|
* @csspart kind-cell - The grid cell around the tag, rendered only when the tag sits in a `Tag.Group`.
|
|
@@ -72,6 +77,7 @@ declare const HelixHeadlessFileInput_base: (new (...args: any[]) => import("@fus
|
|
|
72
77
|
* @csspart live - The live region that says `added-text`, `rejected-text`, and `removed-text`. It is rendered from the first time it has something to say.
|
|
73
78
|
* @csspart meta - The row that holds a file's size and type.
|
|
74
79
|
* @csspart name - A file's name.
|
|
80
|
+
* @csspart progress - A file's upload bar, a `<progress>`, while `setFileStatus` gives it a measure or says it is under way.
|
|
75
81
|
* @csspart remove - The control that removes a file.
|
|
76
82
|
* @csspart size - A file's size.
|
|
77
83
|
* @csspart size-cell - The grid cell around the tag, rendered only when the tag sits in a `Tag.Group`.
|
|
@@ -80,6 +86,8 @@ declare const HelixHeadlessFileInput_base: (new (...args: any[]) => import("@fus
|
|
|
80
86
|
* @csspart size-label - The label, trimmed to its capitals and baseline.
|
|
81
87
|
* @csspart size-link - The link around the label, when the tag has an `href`.
|
|
82
88
|
* @csspart size-start - The category before the label.
|
|
89
|
+
* @csspart status - How a file's upload is going, from `setFileStatus`: the bar and the words.
|
|
90
|
+
* @csspart status-text - The words `setFileStatus` gives a file, such as the reason it failed.
|
|
83
91
|
* @csspart trigger - The label that opens the picker.
|
|
84
92
|
*
|
|
85
93
|
* @cssstate dropping - Files are being dragged over the field.
|
|
@@ -128,6 +136,11 @@ export declare class HelixHeadlessFileInput extends HelixHeadlessFileInput_base
|
|
|
128
136
|
* Whether more than one file can be chosen.
|
|
129
137
|
*/
|
|
130
138
|
multiple: boolean;
|
|
139
|
+
/**
|
|
140
|
+
* The name of a file's progress bar, read by screen readers, with `{name}`
|
|
141
|
+
* filled in. A label with no `{name}` has it added after it.
|
|
142
|
+
*/
|
|
143
|
+
progressLabel: string;
|
|
131
144
|
/**
|
|
132
145
|
* What a reader hears when files are refused, with `{count}` and `{names}`
|
|
133
146
|
* filled in.
|
|
@@ -170,6 +183,19 @@ export declare class HelixHeadlessFileInput extends HelixHeadlessFileInput_base
|
|
|
170
183
|
validate?: (file: File) => string | null | undefined;
|
|
171
184
|
/** The live region, rendered from the first time it has something to say. */
|
|
172
185
|
private readonly status;
|
|
186
|
+
/** What the page has said of each file's upload, by file. */
|
|
187
|
+
private readonly statuses;
|
|
188
|
+
/**
|
|
189
|
+
* Shows how a file's upload is going, in its row: a bar for `progress`,
|
|
190
|
+
* from 0 to 1, or a bar without a measure while `state` is `uploading`, and
|
|
191
|
+
* `text` beside it. `state` names the row `file-uploading`, `file-done` or
|
|
192
|
+
* `file-error` beside `file`, and a reader hears `text` when the state
|
|
193
|
+
* becomes `done` or `error`. `null` clears it.
|
|
194
|
+
*
|
|
195
|
+
* The field uploads nothing, as Zag's file upload does not: your page sends
|
|
196
|
+
* the file and says here how it is going.
|
|
197
|
+
*/
|
|
198
|
+
setFileStatus(file: File, status: FileStatus | null): void;
|
|
173
199
|
/**
|
|
174
200
|
* Screens arriving files and commits what is taken, after the files the
|
|
175
201
|
* field keeps, through `transformFiles` where it is set.
|
|
@@ -193,10 +219,8 @@ export declare class HelixHeadlessFileInput extends HelixHeadlessFileInput_base
|
|
|
193
219
|
* count is written as the language writes a number.
|
|
194
220
|
*/
|
|
195
221
|
private listed;
|
|
196
|
-
/** The element slotted into `remove-icon`,
|
|
197
|
-
private removeIcon;
|
|
198
|
-
/** One copy of `removeIcon` per row, kept so a render does not replace it. */
|
|
199
|
-
private readonly removeIcons;
|
|
222
|
+
/** The element slotted into `remove-icon`, one copy per row's remove button. */
|
|
223
|
+
private readonly removeIcon;
|
|
200
224
|
private readonly handleRemoveIcon;
|
|
201
225
|
/** The icon on one row's remove button: a copy of `remove-icon`, or the bin. */
|
|
202
226
|
private removeMark;
|
|
@@ -342,6 +366,11 @@ export declare class HelixHeadlessFileInput extends HelixHeadlessFileInput_base
|
|
|
342
366
|
* renders the styled one from the same template.
|
|
343
367
|
*/
|
|
344
368
|
protected renderMeta(file: File): TemplateResult;
|
|
369
|
+
/**
|
|
370
|
+
* How a file's upload is going, from `setFileStatus`, behind a seam a tier
|
|
371
|
+
* can move: a `<progress>` named by `progress-label` and the status words.
|
|
372
|
+
*/
|
|
373
|
+
protected renderFileStatus(file: File): TemplateResult | typeof nothing;
|
|
345
374
|
protected render(): TemplateResult;
|
|
346
375
|
}
|
|
347
376
|
declare global {
|
|
@@ -349,4 +378,3 @@ declare global {
|
|
|
349
378
|
'helix-headless-file-input': HelixHeadlessFileInput;
|
|
350
379
|
}
|
|
351
380
|
}
|
|
352
|
-
export {};
|
|
@@ -4,14 +4,14 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
4
4
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
|
-
import { AriaForwardController, customElement, drawIcon, drawStatus, fillTemplate, formatNumbers, HelixBeforeChangeEvent, HelixFormElement, HelixRejectEvent, MixinField, requestChange, restoreValue, StatusController, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { AriaForwardController, customElement, drawIcon, drawStatus, fillTemplate, formatNumbers, HelixBeforeChangeEvent, HelixFormElement, HelixRejectEvent, labelWith, MixinField, requestChange, restoreValue, SlottedGlyph, StatusController, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { trash } from '@fusion.dev/helix-icons';
|
|
9
9
|
import { nothing } from 'lit';
|
|
10
10
|
import { property, state } from 'lit/decorators.js';
|
|
11
11
|
import { html } from 'lit/static-html.js';
|
|
12
12
|
import { screenFiles } from '../screen.js';
|
|
13
|
+
import { barOf, saysStatus } from '../status.js';
|
|
13
14
|
import '../../tag/index.js';
|
|
14
|
-
const named = (label, name) => label.includes('{name}') ? fillTemplate(label, { name }) : `${label} ${name}`;
|
|
15
15
|
const size = (bytes, locale) => {
|
|
16
16
|
const units = ['bytes', 'KB', 'MB', 'GB', 'TB'];
|
|
17
17
|
let value = bytes;
|
|
@@ -46,16 +46,17 @@ let HelixHeadlessFileInput = class HelixHeadlessFileInput extends MixinField(Hel
|
|
|
46
46
|
this.directory = false;
|
|
47
47
|
this.locale = '';
|
|
48
48
|
this.multiple = false;
|
|
49
|
+
this.progressLabel = 'Uploading {name}';
|
|
49
50
|
this.rejectedText = 'Not added: {names}';
|
|
50
51
|
this.removedText = 'Removed: {name}';
|
|
51
52
|
this.removeLabel = 'Remove {name}';
|
|
52
53
|
this.triggerLabel = 'Choose files';
|
|
53
54
|
this.status = new StatusController(this);
|
|
54
|
-
this.
|
|
55
|
-
this.
|
|
55
|
+
this.statuses = new WeakMap();
|
|
56
|
+
this.removeIcon = new SlottedGlyph();
|
|
56
57
|
this.handleRemoveIcon = (event) => {
|
|
57
|
-
this.
|
|
58
|
-
this.
|
|
58
|
+
this.removeIcon.read(event.target);
|
|
59
|
+
this.requestUpdate();
|
|
59
60
|
};
|
|
60
61
|
this.handlePaste = (event) => {
|
|
61
62
|
const pasted = [...(event.clipboardData?.files ?? [])];
|
|
@@ -106,6 +107,19 @@ let HelixHeadlessFileInput = class HelixHeadlessFileInput extends MixinField(Hel
|
|
|
106
107
|
});
|
|
107
108
|
};
|
|
108
109
|
}
|
|
110
|
+
setFileStatus(file, status) {
|
|
111
|
+
const was = this.statuses.get(file);
|
|
112
|
+
if (status) {
|
|
113
|
+
this.statuses.set(file, status);
|
|
114
|
+
if (saysStatus(status, was)) {
|
|
115
|
+
this.status.say(status.text ?? '');
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
this.statuses.delete(file);
|
|
120
|
+
}
|
|
121
|
+
this.requestUpdate();
|
|
122
|
+
}
|
|
109
123
|
take(arriving, keeping, picked = false) {
|
|
110
124
|
const { kept, refused } = screenFiles(arriving, keeping, {
|
|
111
125
|
accept: this.accept,
|
|
@@ -152,12 +166,7 @@ let HelixHeadlessFileInput = class HelixHeadlessFileInput extends MixinField(Hel
|
|
|
152
166
|
});
|
|
153
167
|
}
|
|
154
168
|
removeMark(at) {
|
|
155
|
-
|
|
156
|
-
return drawIcon(trash);
|
|
157
|
-
}
|
|
158
|
-
const held = this.removeIcons.get(at) ?? this.removeIcon.cloneNode(true);
|
|
159
|
-
this.removeIcons.set(at, held);
|
|
160
|
-
return held;
|
|
169
|
+
return this.removeIcon.copyFor(at) ?? drawIcon(trash);
|
|
161
170
|
}
|
|
162
171
|
get files() {
|
|
163
172
|
return [...(this.control?.files ?? [])];
|
|
@@ -258,6 +267,23 @@ let HelixHeadlessFileInput = class HelixHeadlessFileInput extends MixinField(Hel
|
|
|
258
267
|
part="kind"
|
|
259
268
|
exportparts="cell: kind-cell, dismiss: kind-dismiss, dismiss-mark: kind-dismiss-mark, label: kind-label, link: kind-link, start: kind-start">${kind(file)}</${this.tag('tag')}>`;
|
|
260
269
|
}
|
|
270
|
+
renderFileStatus(file) {
|
|
271
|
+
const status = this.statuses.get(file);
|
|
272
|
+
if (!status) {
|
|
273
|
+
return nothing;
|
|
274
|
+
}
|
|
275
|
+
const bar = barOf(status);
|
|
276
|
+
return html `<span part="status"
|
|
277
|
+
>${bar === undefined
|
|
278
|
+
? nothing
|
|
279
|
+
: html `<progress
|
|
280
|
+
part="progress"
|
|
281
|
+
max="1"
|
|
282
|
+
value=${bar === 'unmeasured' ? nothing : bar}
|
|
283
|
+
aria-label=${labelWith(this.progressLabel, 'name', file.name)}
|
|
284
|
+
></progress>`}${status.text ? html `<span part="status-text">${status.text}</span>` : nothing}</span
|
|
285
|
+
>`;
|
|
286
|
+
}
|
|
261
287
|
render() {
|
|
262
288
|
const files = this.files;
|
|
263
289
|
return html `${this.renderLabel()}
|
|
@@ -300,26 +326,34 @@ let HelixHeadlessFileInput = class HelixHeadlessFileInput extends MixinField(Hel
|
|
|
300
326
|
${files.length === 0
|
|
301
327
|
? nothing
|
|
302
328
|
: html `<ul part="list">
|
|
303
|
-
${files.map((file, at) =>
|
|
329
|
+
${files.map((file, at) => {
|
|
330
|
+
const state = this.statuses.get(file)?.state;
|
|
331
|
+
const done = state === 'done';
|
|
332
|
+
const failed = state === 'error';
|
|
333
|
+
const sending = state === 'uploading';
|
|
334
|
+
return html `<li
|
|
335
|
+
part="file${done ? ' file-done' : ''}${failed ? ' file-error' : ''}${sending ? ' file-uploading' : ''}"
|
|
336
|
+
>
|
|
304
337
|
<span part="detail">
|
|
305
338
|
${this.renderFile
|
|
306
|
-
|
|
307
|
-
|
|
339
|
+
? this.renderFile(file, at)
|
|
340
|
+
: html `<span part="name">${file.name}</span>
|
|
308
341
|
<span part="meta">
|
|
309
342
|
${this.renderMeta(file)}
|
|
310
|
-
</span>`}
|
|
343
|
+
</span>`}${this.renderFileStatus(file)}
|
|
311
344
|
</span>
|
|
312
345
|
<button
|
|
313
346
|
part="remove"
|
|
314
347
|
type="button"
|
|
315
|
-
aria-label=${
|
|
348
|
+
aria-label=${labelWith(this.removeLabel, 'name', file.name)}
|
|
316
349
|
data-at=${at}
|
|
317
350
|
?disabled=${this.isDisabled}
|
|
318
351
|
@click=${this.handleRemove}
|
|
319
352
|
>
|
|
320
353
|
${this.removeMark(at)}
|
|
321
354
|
</button>
|
|
322
|
-
</li
|
|
355
|
+
</li>`;
|
|
356
|
+
})}
|
|
323
357
|
</ul>`}`;
|
|
324
358
|
}
|
|
325
359
|
};
|
|
@@ -347,6 +381,9 @@ __decorate([
|
|
|
347
381
|
__decorate([
|
|
348
382
|
property({ reflect: true, type: Boolean })
|
|
349
383
|
], HelixHeadlessFileInput.prototype, "multiple", void 0);
|
|
384
|
+
__decorate([
|
|
385
|
+
property({ attribute: 'progress-label' })
|
|
386
|
+
], HelixHeadlessFileInput.prototype, "progressLabel", void 0);
|
|
350
387
|
__decorate([
|
|
351
388
|
property({ attribute: 'rejected-text' })
|
|
352
389
|
], HelixHeadlessFileInput.prototype, "rejectedText", void 0);
|
|
@@ -368,9 +405,6 @@ __decorate([
|
|
|
368
405
|
__decorate([
|
|
369
406
|
property({ attribute: false })
|
|
370
407
|
], HelixHeadlessFileInput.prototype, "validate", void 0);
|
|
371
|
-
__decorate([
|
|
372
|
-
state()
|
|
373
|
-
], HelixHeadlessFileInput.prototype, "removeIcon", void 0);
|
|
374
408
|
__decorate([
|
|
375
409
|
state()
|
|
376
410
|
], HelixHeadlessFileInput.prototype, "dropping", void 0);
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How one file's upload is going, as a page reports it to File Input. The
|
|
3
|
+
* field does not upload anything: the page does, and says how it is going.
|
|
4
|
+
*/
|
|
5
|
+
export interface FileStatus {
|
|
6
|
+
/** How much is done, from 0 to 1. Left out, the bar moves without a measure while `state` is `uploading`. */
|
|
7
|
+
readonly progress?: number | undefined;
|
|
8
|
+
/** Where the upload is: under way, finished, or failed. */
|
|
9
|
+
readonly state?: 'done' | 'error' | 'uploading' | undefined;
|
|
10
|
+
/** Words beside the bar, such as "Uploaded" or the reason it failed. */
|
|
11
|
+
readonly text?: string | undefined;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* The bar's value, held between 0 and 1, or nothing for a bar without a
|
|
15
|
+
* measure, and no bar at all for a status that is neither measured nor under
|
|
16
|
+
* way.
|
|
17
|
+
*/
|
|
18
|
+
export declare const barOf: (status: FileStatus) => number | 'unmeasured' | undefined;
|
|
19
|
+
/**
|
|
20
|
+
* Whether a new status is worth saying: a finish or a failure with words, the
|
|
21
|
+
* first time the file reaches it. Progress is shown and not said, since a
|
|
22
|
+
* reader hearing every percent hears nothing else.
|
|
23
|
+
*/
|
|
24
|
+
export declare const saysStatus: (next: FileStatus, was: FileStatus | undefined) => boolean;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { clamp } from '@fusion.dev/helix-core';
|
|
2
|
+
export const barOf = (status) => {
|
|
3
|
+
const { progress, state } = status;
|
|
4
|
+
if (typeof progress === 'number' && Number.isFinite(progress)) {
|
|
5
|
+
return clamp(progress, 0, 1);
|
|
6
|
+
}
|
|
7
|
+
return state === 'uploading' ? 'unmeasured' : undefined;
|
|
8
|
+
};
|
|
9
|
+
export const saysStatus = (next, was) => Boolean(next.text) &&
|
|
10
|
+
(next.state === 'done' || next.state === 'error') &&
|
|
11
|
+
next.state !== was?.state;
|
|
@@ -27,6 +27,15 @@ declare const HelixHeadlessFilterChip_base: (new (...args: any[]) => import("@fu
|
|
|
27
27
|
* dismissal, which is also how you take control of the interaction for one
|
|
28
28
|
* press. `requestChange` documents the pattern.
|
|
29
29
|
*
|
|
30
|
+
* **Keyboard.** The remove button is a tab stop of its own, and Enter or Space
|
|
31
|
+
* on it asks to remove the filter. In a `FilterInput`, Backspace in the empty
|
|
32
|
+
* field asks to remove the last chip.
|
|
33
|
+
*
|
|
34
|
+
* The remove button is named `dismiss-label` followed by the chip's words,
|
|
35
|
+
* such as "Remove filter Status is not open", so a row of chips says which
|
|
36
|
+
* filter each button removes. Write `{label}` in `dismiss-label` to put the
|
|
37
|
+
* words elsewhere.
|
|
38
|
+
*
|
|
30
39
|
* To let the user change the operator, slot a menu trigger into `operator`.
|
|
31
40
|
* With the text fallback, the operator is a label. The chip does not interpret
|
|
32
41
|
* operators: their meaning belongs to your domain, as `FilterOperator`
|
|
@@ -100,6 +109,20 @@ export declare class HelixHeadlessFilterChip extends HelixHeadlessFilterChip_bas
|
|
|
100
109
|
* makes an unusual filter look unusual.
|
|
101
110
|
*/
|
|
102
111
|
operatorLabel: string;
|
|
112
|
+
/**
|
|
113
|
+
* The remove button's name: `dismissLabel` with the chip's words, its field,
|
|
114
|
+
* its comparison and its values, such as "Remove filter Status is not open".
|
|
115
|
+
*
|
|
116
|
+
* **Named for its chip**, as File Input names each remove button for its
|
|
117
|
+
* file: a row of buttons each called "Remove filter" says nothing about
|
|
118
|
+
* which filter each one takes away. `{label}` in `dismiss-label` says where
|
|
119
|
+
* the words go, and without it they follow the label.
|
|
120
|
+
*
|
|
121
|
+
* Each word is read from what is slotted and otherwise from `label` and
|
|
122
|
+
* `operator-label`, which is all a server and a hydrating render can read,
|
|
123
|
+
* so the values join the update after.
|
|
124
|
+
*/
|
|
125
|
+
private get removeName();
|
|
103
126
|
protected firstUpdated(changed: PropertyValues): void;
|
|
104
127
|
protected render(): TemplateResult;
|
|
105
128
|
}
|
|
@@ -4,7 +4,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
4
4
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
|
-
import { customElement, HelixElement, MixinDismissible } from '@fusion.dev/helix-core';
|
|
7
|
+
import { customElement, HelixElement, labelWith, MixinDismissible, slottedWords, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { x } from '@fusion.dev/helix-icons';
|
|
9
9
|
import { html, nothing } from 'lit';
|
|
10
10
|
import { property } from 'lit/decorators.js';
|
|
@@ -16,8 +16,16 @@ let HelixHeadlessFilterChip = class HelixHeadlessFilterChip extends MixinDismiss
|
|
|
16
16
|
this.label = '';
|
|
17
17
|
this.operatorLabel = '';
|
|
18
18
|
}
|
|
19
|
+
get removeName() {
|
|
20
|
+
const read = (slot, fallback) => (this.childrenKnown && slottedWords(this, [slot])) || fallback;
|
|
21
|
+
const words = [read('field', this.label), read('operator', this.operatorLabel), read('', '')]
|
|
22
|
+
.filter(Boolean)
|
|
23
|
+
.join(' ');
|
|
24
|
+
return labelWith(this.dismissLabel, 'label', words);
|
|
25
|
+
}
|
|
19
26
|
firstUpdated(changed) {
|
|
20
27
|
super.firstUpdated(changed);
|
|
28
|
+
this.renderRoot.addEventListener('slotchange', () => this.requestUpdate());
|
|
21
29
|
this.finishHydration();
|
|
22
30
|
}
|
|
23
31
|
render() {
|
|
@@ -33,7 +41,7 @@ let HelixHeadlessFilterChip = class HelixHeadlessFilterChip extends MixinDismiss
|
|
|
33
41
|
? html `<button
|
|
34
42
|
part="dismiss"
|
|
35
43
|
type="button"
|
|
36
|
-
aria-label=${this.
|
|
44
|
+
aria-label=${this.removeName}
|
|
37
45
|
@click=${() => this.dismiss()}
|
|
38
46
|
>
|
|
39
47
|
<svg part="dismiss-mark" fill="currentColor" viewBox=${x.viewBox} aria-hidden="true">
|
|
@@ -97,6 +97,7 @@ declare const HelixHeadlessFilterInput_base: (new (...args: any[]) => import("@f
|
|
|
97
97
|
* @aliases SearchField, FacetInput, TokenInput
|
|
98
98
|
* @documentation https://fusion.dev/helix/components/filter-input
|
|
99
99
|
*
|
|
100
|
+
* @slot clear-icon - Replaces the cross on the clear button, under `clearable`.
|
|
100
101
|
* @slot end - Content after the text, such as a count or a control.
|
|
101
102
|
* @slot feedback - The message that says what is wrong, for content richer than a string. It shows while there is a message.
|
|
102
103
|
* @slot hint - Help under the control, for content richer than the `hint` text.
|
|
@@ -256,6 +257,11 @@ export declare class HelixHeadlessFilterInput extends HelixHeadlessFilterInput_b
|
|
|
256
257
|
* and one that pretends it was never there.
|
|
257
258
|
*/
|
|
258
259
|
private get suggestions();
|
|
260
|
+
/**
|
|
261
|
+
* Every option slotted into `suggestions`, and every option one level inside
|
|
262
|
+
* a group slotted there, hidden or not.
|
|
263
|
+
*/
|
|
264
|
+
private get options();
|
|
259
265
|
/**
|
|
260
266
|
* The direction of the selection, named as on `<input>`.
|
|
261
267
|
*
|
|
@@ -437,6 +443,8 @@ export declare class HelixHeadlessFilterInput extends HelixHeadlessFilterInput_b
|
|
|
437
443
|
private markActive;
|
|
438
444
|
/** Puts the caret in the text field. */
|
|
439
445
|
focus(options?: FocusOptions): void;
|
|
446
|
+
/** The cross on the clear button, behind a seam a tier can move. */
|
|
447
|
+
protected renderClearIcon(): TemplateResult;
|
|
440
448
|
protected render(): TemplateResult;
|
|
441
449
|
}
|
|
442
450
|
declare global {
|
|
@@ -162,22 +162,18 @@ let HelixHeadlessFilterInput = class HelixHeadlessFilterInput extends MixinContr
|
|
|
162
162
|
};
|
|
163
163
|
}
|
|
164
164
|
narrow() {
|
|
165
|
-
const slot = this.renderRoot?.querySelector('slot[name="suggestions"]');
|
|
166
165
|
const term = this.filterSuggestions
|
|
167
166
|
? currentTerm(this.value, this.control?.selectionStart ?? this.value.length)
|
|
168
167
|
: '';
|
|
169
|
-
for (const
|
|
170
|
-
const
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
option.hidden = false;
|
|
179
|
-
this.narrowed.delete(option);
|
|
180
|
-
}
|
|
168
|
+
for (const option of this.options) {
|
|
169
|
+
const hide = !suggests(option.textContent ?? '', term);
|
|
170
|
+
if (hide && !option.hidden) {
|
|
171
|
+
option.hidden = true;
|
|
172
|
+
this.narrowed.add(option);
|
|
173
|
+
}
|
|
174
|
+
else if (!hide && this.narrowed.has(option)) {
|
|
175
|
+
option.hidden = false;
|
|
176
|
+
this.narrowed.delete(option);
|
|
181
177
|
}
|
|
182
178
|
}
|
|
183
179
|
}
|
|
@@ -220,20 +216,11 @@ let HelixHeadlessFilterInput = class HelixHeadlessFilterInput extends MixinContr
|
|
|
220
216
|
return this.clearable && this.value !== '' && !this.isDisabled;
|
|
221
217
|
}
|
|
222
218
|
get suggestions() {
|
|
219
|
+
return this.options.filter((option) => !option.disabled && !option.hidden);
|
|
220
|
+
}
|
|
221
|
+
get options() {
|
|
223
222
|
const slot = this.renderRoot?.querySelector('slot[name="suggestions"]');
|
|
224
|
-
|
|
225
|
-
for (const node of slot?.assignedElements({ flatten: true }) ?? []) {
|
|
226
|
-
if (isOption(node)) {
|
|
227
|
-
found.push(node);
|
|
228
|
-
continue;
|
|
229
|
-
}
|
|
230
|
-
for (const child of node.children) {
|
|
231
|
-
if (isOption(child)) {
|
|
232
|
-
found.push(child);
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
return found.filter((option) => !option.disabled && !option.hidden);
|
|
223
|
+
return (slot?.assignedElements({ flatten: true }) ?? []).flatMap((node) => isOption(node) ? [node] : [...node.children].filter(isOption));
|
|
237
224
|
}
|
|
238
225
|
get selectionDirection() {
|
|
239
226
|
return this.control?.selectionDirection ?? 'none';
|
|
@@ -392,6 +379,9 @@ let HelixHeadlessFilterInput = class HelixHeadlessFilterInput extends MixinContr
|
|
|
392
379
|
focus(options) {
|
|
393
380
|
this.control?.focus(options);
|
|
394
381
|
}
|
|
382
|
+
renderClearIcon() {
|
|
383
|
+
return html `<slot name="clear-icon">${drawIcon(x)}</slot>`;
|
|
384
|
+
}
|
|
395
385
|
render() {
|
|
396
386
|
return html `${this.renderLabel()}
|
|
397
387
|
<div part="field" @focusin=${this.handleFocusIn} @focusout=${this.handleFocusOut}>
|
|
@@ -426,7 +416,7 @@ let HelixHeadlessFilterInput = class HelixHeadlessFilterInput extends MixinContr
|
|
|
426
416
|
aria-label=${this.clearLabel}
|
|
427
417
|
@click=${this.handleClear}
|
|
428
418
|
>
|
|
429
|
-
${
|
|
419
|
+
${this.renderClearIcon()}
|
|
430
420
|
</button>`
|
|
431
421
|
: nothing}
|
|
432
422
|
</div>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type TemplateResult } from 'lit';
|
|
2
|
+
/**
|
|
3
|
+
* Each date field `Intl` names, drawn as a part of its own.
|
|
4
|
+
*
|
|
5
|
+
* Keyed by the `type` of `Intl.DateTimeFormat#formatToParts`. Written out one
|
|
6
|
+
* template to a field rather than bound through one `part` binding, because a
|
|
7
|
+
* part is read from the source as a literal: a bound name is a part no
|
|
8
|
+
* stylesheet check can find. A type left out, the punctuation between the
|
|
9
|
+
* fields among them, is drawn as plain text.
|
|
10
|
+
*/
|
|
11
|
+
export declare const FIELD: Record<string, (value: string) => TemplateResult>;
|
|
12
|
+
/**
|
|
13
|
+
* A formatted date, each field in a part of its own and the text between them
|
|
14
|
+
* as it is.
|
|
15
|
+
*
|
|
16
|
+
* The words are the ones `format` would give, in the same order, so the reading
|
|
17
|
+
* a screen reader hears and the text a reader copies do not change: an inline
|
|
18
|
+
* span with no style of its own changes nothing on the page either.
|
|
19
|
+
*/
|
|
20
|
+
export declare const drawFields: (parts: readonly Intl.DateTimeFormatPart[]) => unknown[];
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { html } from 'lit';
|
|
2
|
+
export const FIELD = {
|
|
3
|
+
day: (value) => html `<span part="day">${value}</span>`,
|
|
4
|
+
dayPeriod: (value) => html `<span part="day-period">${value}</span>`,
|
|
5
|
+
era: (value) => html `<span part="era">${value}</span>`,
|
|
6
|
+
hour: (value) => html `<span part="hour">${value}</span>`,
|
|
7
|
+
minute: (value) => html `<span part="minute">${value}</span>`,
|
|
8
|
+
month: (value) => html `<span part="month">${value}</span>`,
|
|
9
|
+
second: (value) => html `<span part="second">${value}</span>`,
|
|
10
|
+
timeZoneName: (value) => html `<span part="time-zone-name">${value}</span>`,
|
|
11
|
+
weekday: (value) => html `<span part="weekday">${value}</span>`,
|
|
12
|
+
year: (value) => html `<span part="year">${value}</span>`,
|
|
13
|
+
};
|
|
14
|
+
export const drawFields = (parts) => parts.map(({ type, value }) => FIELD[type]?.(value) ?? value);
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* What a Format Date was asked for, in its own spelling: the `Intl` options a
|
|
3
|
-
* consumer set
|
|
3
|
+
* consumer set. The element itself is one, so it passes itself.
|
|
4
4
|
*/
|
|
5
5
|
export interface Asked {
|
|
6
|
-
dateOnly: boolean;
|
|
7
6
|
dateStyle?: 'full' | 'long' | 'medium' | 'short' | undefined;
|
|
8
7
|
day?: 'numeric' | '2-digit' | undefined;
|
|
9
8
|
era?: 'long' | 'narrow' | 'short' | undefined;
|
|
@@ -19,15 +18,16 @@ export interface Asked {
|
|
|
19
18
|
year?: 'numeric' | '2-digit' | undefined;
|
|
20
19
|
}
|
|
21
20
|
/**
|
|
22
|
-
* The `Intl.DateTimeFormat` options for what was asked, and none that was not
|
|
21
|
+
* The `Intl.DateTimeFormat` options for what was asked, and none that was not:
|
|
22
|
+
* an option not asked for is `undefined`, which `Intl` reads as absent.
|
|
23
23
|
*
|
|
24
24
|
* **A style wins over the fields.** `dateStyle` and `timeStyle` are each
|
|
25
25
|
* locale's own whole pattern, and `Intl` throws a `TypeError` when one is
|
|
26
26
|
* given beside `month` or `hour`, so the fields are left out wherever a style
|
|
27
27
|
* is set. `hourCycle` and `timeZone` go with either.
|
|
28
28
|
*
|
|
29
|
-
* **A day with no time is read in UTC** unless a zone is given. Parsed, it is
|
|
29
|
+
* **A day with no time, `dateOnly`, is read in UTC** unless a zone is given. Parsed, it is
|
|
30
30
|
* midnight UTC, and read in a zone west of it that is the day before: measured
|
|
31
31
|
* before this, `2026-08-04` read "August 3, 2026" in Los Angeles.
|
|
32
32
|
*/
|
|
33
|
-
export declare const formatOptions: (asked: Asked) => Intl.DateTimeFormatOptions;
|
|
33
|
+
export declare const formatOptions: (asked: Asked, dateOnly?: boolean) => Intl.DateTimeFormatOptions;
|
|
@@ -1,42 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
'
|
|
10
|
-
|
|
11
|
-
];
|
|
12
|
-
export const formatOptions = (asked) => {
|
|
13
|
-
const options = {};
|
|
14
|
-
const styled = asked.dateStyle !== undefined || asked.timeStyle !== undefined;
|
|
15
|
-
if (styled) {
|
|
16
|
-
if (asked.dateStyle) {
|
|
17
|
-
options.dateStyle = asked.dateStyle;
|
|
18
|
-
}
|
|
19
|
-
if (asked.timeStyle) {
|
|
20
|
-
options.timeStyle = asked.timeStyle;
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
else {
|
|
24
|
-
for (const field of FIELDS) {
|
|
25
|
-
const value = asked[field];
|
|
26
|
-
if (value) {
|
|
27
|
-
;
|
|
28
|
-
options[field] = value;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
if (asked.hourCycle) {
|
|
33
|
-
options.hourCycle = asked.hourCycle;
|
|
34
|
-
}
|
|
35
|
-
if (asked.timeZone) {
|
|
36
|
-
options.timeZone = asked.timeZone;
|
|
37
|
-
}
|
|
38
|
-
else if (asked.dateOnly) {
|
|
39
|
-
options.timeZone = 'UTC';
|
|
1
|
+
import { FIELD } from './fields.js';
|
|
2
|
+
const FIELDS = Object.keys(FIELD);
|
|
3
|
+
export const formatOptions = (asked, dateOnly = false) => {
|
|
4
|
+
const options = {
|
|
5
|
+
hourCycle: asked.hourCycle,
|
|
6
|
+
timeZone: asked.timeZone || (dateOnly ? 'UTC' : undefined),
|
|
7
|
+
};
|
|
8
|
+
const styled = asked.dateStyle || asked.timeStyle;
|
|
9
|
+
for (const field of styled ? ['dateStyle', 'timeStyle'] : FIELDS) {
|
|
10
|
+
options[field] = asked[field];
|
|
40
11
|
}
|
|
41
12
|
return options;
|
|
42
13
|
};
|