@fusion.dev/helix-headless 0.145.0 → 0.147.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 +12286 -4281
- package/dist/accordion/item/accordion-item.d.ts +51 -18
- package/dist/accordion/item/accordion-item.js +45 -13
- package/dist/accordion/root/accordion-root.d.ts +16 -7
- package/dist/accordion/root/accordion-root.js +3 -3
- package/dist/announcement/root/announcement-root.d.ts +16 -6
- package/dist/announcement/root/announcement-root.js +37 -7
- package/dist/app-header/root/app-header-root.d.ts +7 -2
- package/dist/app-header/root/app-header-root.js +9 -1
- package/dist/app-header/sectioning.d.ts +3 -1
- package/dist/app-header/sectioning.js +3 -2
- package/dist/area-chart/root/area-chart-root.d.ts +18 -1
- package/dist/area-chart/root/area-chart-root.js +11 -3
- package/dist/avatar/group/avatar-group.d.ts +20 -14
- package/dist/avatar/group/avatar-group.js +17 -19
- package/dist/avatar/root/avatar-root.d.ts +31 -1
- package/dist/avatar/root/avatar-root.js +11 -1
- package/dist/badge/root/badge-root.d.ts +60 -7
- package/dist/badge/root/badge-root.js +89 -6
- package/dist/bar-chart/root/bar-chart-root.d.ts +18 -1
- package/dist/bar-chart/root/bar-chart-root.js +48 -20
- package/dist/bar-chart/stack.d.ts +25 -0
- package/dist/bar-chart/stack.js +27 -0
- package/dist/breadcrumbs/breadcrumb/breadcrumb.d.ts +14 -0
- package/dist/breadcrumbs/breadcrumb/breadcrumb.js +12 -2
- package/dist/breadcrumbs/root/breadcrumbs-root.d.ts +25 -0
- package/dist/breadcrumbs/root/breadcrumbs-root.js +51 -4
- package/dist/button/root/button-root.d.ts +50 -38
- package/dist/button/root/button-root.js +42 -53
- package/dist/button/submitter.d.ts +27 -0
- package/dist/button/submitter.js +25 -0
- package/dist/button-group/root/button-group-root.d.ts +2 -1
- package/dist/button-group/root/button-group-root.js +5 -1
- package/dist/canvas/node/canvas-node.d.ts +4 -3
- package/dist/canvas/node/canvas-node.js +3 -2
- package/dist/canvas/root/canvas-root.js +2 -2
- package/dist/card/root/card-root.d.ts +36 -4
- package/dist/card/root/card-root.js +29 -10
- package/dist/carousel/root/carousel-root.d.ts +43 -4
- package/dist/carousel/root/carousel-root.js +40 -12
- package/dist/carousel/stops.d.ts +20 -0
- package/dist/carousel/stops.js +30 -0
- package/dist/chat/message/chat-message.js +5 -4
- package/dist/chat/naming.d.ts +5 -1
- package/dist/chat/naming.js +4 -2
- package/dist/chat/root/chat-root.d.ts +40 -4
- package/dist/chat/root/chat-root.js +32 -6
- package/dist/checkbox/root/checkbox-root.d.ts +20 -0
- package/dist/checkbox/root/checkbox-root.js +18 -7
- package/dist/checkbox-group/root/checkbox-group-root.d.ts +8 -2
- package/dist/checkbox-group/root/checkbox-group-root.js +14 -11
- package/dist/checkbox-group/select-all.d.ts +21 -0
- package/dist/checkbox-group/select-all.js +7 -0
- package/dist/code-block/highlight.d.ts +15 -0
- package/dist/code-block/highlight.js +4 -0
- package/dist/code-block/root/code-block-root.d.ts +79 -10
- package/dist/code-block/root/code-block-root.js +74 -5
- package/dist/color-input/root/color-input-root.d.ts +14 -0
- package/dist/color-input/root/color-input-root.js +17 -7
- package/dist/color-picker/channels.js +1 -2
- package/dist/color-picker/root/color-picker-root.d.ts +53 -16
- package/dist/color-picker/root/color-picker-root.js +155 -46
- package/dist/color-picker/wheel.d.ts +17 -0
- package/dist/color-picker/wheel.js +6 -0
- package/dist/combobox/root/combobox-root.d.ts +56 -0
- package/dist/combobox/root/combobox-root.js +92 -15
- package/dist/command/root/command-root.d.ts +19 -2
- package/dist/command/root/command-root.js +24 -23
- package/dist/copy-button/root/copy-button-root.d.ts +21 -1
- package/dist/copy-button/root/copy-button-root.js +16 -4
- package/dist/data-table/index.d.ts +1 -1
- package/dist/data-table/index.js +1 -1
- package/dist/data-table/keys.d.ts +6 -0
- package/dist/data-table/keys.js +14 -0
- package/dist/data-table/root/data-table-root.d.ts +27 -18
- package/dist/data-table/root/data-table-root.js +31 -57
- package/dist/data-table/tree.d.ts +16 -1
- package/dist/data-table/tree.js +2 -3
- package/dist/date-input/root/date-input-root.d.ts +11 -2
- package/dist/date-input/root/date-input-root.js +26 -12
- package/dist/date-picker/root/date-picker-root.d.ts +14 -9
- package/dist/date-picker/root/date-picker-root.js +33 -22
- package/dist/description-list/item/description-list-item.d.ts +18 -4
- package/dist/description-list/item/description-list-item.js +8 -4
- package/dist/dialog/description.js +15 -1
- package/dist/dialog/root/dialog-root.d.ts +8 -2
- package/dist/dialog/root/dialog-root.js +16 -1
- package/dist/divider/root/divider-root.d.ts +3 -0
- package/dist/divider/root/divider-root.js +2 -1
- package/dist/donut-chart/root/donut-chart-root.d.ts +31 -0
- package/dist/donut-chart/root/donut-chart-root.js +55 -1
- package/dist/donut-chart/slice-label.d.ts +35 -0
- package/dist/donut-chart/slice-label.js +11 -0
- package/dist/drawer/reveal.d.ts +8 -0
- package/dist/drawer/reveal.js +1 -0
- package/dist/drawer/root/drawer-root.d.ts +63 -2
- package/dist/drawer/root/drawer-root.js +75 -4
- package/dist/drilldown/item/drilldown-item.d.ts +21 -1
- package/dist/drilldown/item/drilldown-item.js +40 -5
- package/dist/drilldown/root/drilldown-root.d.ts +21 -3
- package/dist/drilldown/root/drilldown-root.js +22 -3
- package/dist/element-events.generated.js +35 -6
- package/dist/empty/root/empty-root.d.ts +34 -2
- package/dist/empty/root/empty-root.js +26 -4
- package/dist/file-input/root/file-input-root.d.ts +99 -8
- package/dist/file-input/root/file-input-root.js +120 -22
- package/dist/file-input/screen.d.ts +2 -1
- package/dist/file-input/status.d.ts +24 -0
- package/dist/file-input/status.js +10 -0
- package/dist/filter-input/chip/filter-chip.d.ts +23 -0
- package/dist/filter-input/chip/filter-chip.js +11 -2
- package/dist/filter-input/menu/filter-menu.d.ts +2 -0
- package/dist/filter-input/menu/filter-menu.js +12 -4
- package/dist/filter-input/root/filter-input-root.d.ts +38 -6
- package/dist/filter-input/root/filter-input-root.js +18 -28
- package/dist/filter-input/suggest.d.ts +28 -3
- package/dist/filter-input/suggest.js +18 -8
- package/dist/format-date/options.d.ts +3 -4
- package/dist/format-date/options.js +2 -2
- package/dist/format-date/root/format-date-root.d.ts +27 -17
- package/dist/format-date/root/format-date-root.js +27 -48
- 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 +83 -11
- package/dist/heatmap/root/heatmap-root.js +104 -12
- 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 +25 -1
- package/dist/icon/root/icon-root.js +44 -12
- package/dist/icon/root/index.d.ts +1 -1
- package/dist/icon/root/index.js +1 -1
- package/dist/icon/settle.d.ts +7 -0
- package/dist/icon/settle.js +10 -0
- package/dist/icon-button/root/icon-button-root.d.ts +2 -0
- package/dist/image/root/image-root.d.ts +14 -1
- package/dist/image/root/image-root.js +7 -2
- package/dist/input/root/input-root.d.ts +34 -3
- package/dist/input/root/input-root.js +17 -4
- package/dist/kbd/keys.d.ts +29 -0
- package/dist/kbd/keys.js +52 -0
- package/dist/kbd/root/kbd-root.d.ts +52 -1
- package/dist/kbd/root/kbd-root.js +40 -47
- 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 +77 -12
- package/dist/legend/root/legend-root.js +71 -17
- package/dist/lightbox/root/lightbox-root.d.ts +98 -10
- package/dist/lightbox/root/lightbox-root.js +153 -18
- package/dist/lightbox/zoom-controller.d.ts +59 -0
- package/dist/lightbox/zoom-controller.js +128 -0
- package/dist/lightbox/zoom.d.ts +24 -0
- package/dist/lightbox/zoom.js +18 -0
- package/dist/line-chart/root/line-chart-root.d.ts +38 -1
- package/dist/line-chart/root/line-chart-root.js +31 -3
- package/dist/list/item/list-item.d.ts +2 -0
- package/dist/list/item/list-item.js +11 -2
- package/dist/list/root/list-root.d.ts +70 -13
- package/dist/list/root/list-root.js +91 -13
- package/dist/list/selection.d.ts +54 -7
- package/dist/list/selection.js +32 -7
- package/dist/listbox/root/listbox-root.d.ts +44 -4
- package/dist/listbox/root/listbox-root.js +72 -34
- package/dist/loader/busy.d.ts +10 -0
- package/dist/loader/busy.js +11 -0
- package/dist/loader/root/loader-root.d.ts +9 -2
- package/dist/loader/root/loader-root.js +23 -3
- 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 +80 -15
- package/dist/megamenu/root/megamenu-root.js +76 -19
- package/dist/menu/item/menu-item.d.ts +51 -2
- package/dist/menu/item/menu-item.js +50 -26
- package/dist/menu/root/menu-root.d.ts +17 -0
- package/dist/menu/root/menu-root.js +2 -2
- package/dist/meter/root/meter-root.d.ts +62 -1
- package/dist/meter/root/meter-root.js +38 -16
- package/dist/navigation/root/navigation-root.d.ts +2 -1
- package/dist/navigation/root/navigation-root.js +2 -2
- package/dist/notifications/root/notifications-root.d.ts +20 -4
- package/dist/notifications/root/notifications-root.js +30 -8
- 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 +34 -9
- package/dist/number-input/root/number-input-root.js +31 -25
- package/dist/object-inspector/root/object-inspector-root.d.ts +88 -33
- package/dist/object-inspector/root/object-inspector-root.js +134 -92
- package/dist/object-inspector/rows.d.ts +18 -0
- package/dist/object-inspector/rows.js +33 -0
- package/dist/option/index.d.ts +1 -0
- package/dist/option/index.js +1 -0
- package/dist/option/root/option-root.d.ts +5 -3
- 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 +30 -0
- package/dist/outline/root/outline-root.js +17 -13
- 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 +37 -0
- package/dist/pin-input/code.js +25 -0
- package/dist/pin-input/root/pin-input-root.d.ts +116 -115
- package/dist/pin-input/root/pin-input-root.js +163 -155
- package/dist/popover/hide-outside.d.ts +14 -0
- package/dist/popover/hide-outside.js +34 -0
- package/dist/popover/root/popover-root.d.ts +64 -8
- package/dist/popover/root/popover-root.js +67 -4
- package/dist/progress/root/progress-root.d.ts +47 -0
- package/dist/progress/root/progress-root.js +34 -16
- package/dist/qr-code/export.d.ts +45 -1
- package/dist/qr-code/export.js +28 -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 +36 -11
- package/dist/qr-code/root/qr-code-root.js +58 -11
- package/dist/quote/marks.d.ts +8 -0
- package/dist/quote/marks.js +5 -0
- package/dist/quote/root/quote-root.d.ts +14 -2
- package/dist/quote/root/quote-root.js +23 -1
- package/dist/radio/group/radio-group.d.ts +15 -0
- package/dist/radio/root/radio-root.d.ts +6 -2
- package/dist/radio/root/radio-root.js +7 -2
- package/dist/rating/root/rating-root.d.ts +30 -12
- package/dist/rating/root/rating-root.js +27 -27
- package/dist/scatter-chart/fit.d.ts +15 -0
- package/dist/scatter-chart/fit.js +35 -0
- package/dist/scatter-chart/root/scatter-chart-root.d.ts +51 -1
- package/dist/scatter-chart/root/scatter-chart-root.js +64 -24
- package/dist/scroll-area/root/scroll-area-root.d.ts +22 -51
- package/dist/scroll-area/root/scroll-area-root.js +57 -173
- package/dist/scroll-area/scrollbar-controller.d.ts +111 -0
- package/dist/scroll-area/scrollbar-controller.js +172 -0
- package/dist/scroll-area/scrollbar.d.ts +27 -8
- package/dist/scroll-area/scrollbar.js +10 -1
- package/dist/select/align.d.ts +47 -0
- package/dist/select/align.js +7 -0
- package/dist/select/root/select-root.d.ts +71 -0
- package/dist/select/root/select-root.js +78 -6
- package/dist/skeleton/root/skeleton-root.d.ts +3 -0
- package/dist/skeleton/root/skeleton-root.js +4 -2
- package/dist/skip-link/root/skip-link-root.js +2 -2
- package/dist/slider/root/slider-root.d.ts +59 -5
- package/dist/slider/root/slider-root.js +45 -3
- package/dist/sparkline/readings.d.ts +36 -0
- package/dist/sparkline/readings.js +36 -0
- package/dist/sparkline/root/sparkline-root.d.ts +121 -7
- package/dist/sparkline/root/sparkline-root.js +160 -26
- package/dist/speed-dial/item/speed-dial-item.d.ts +1 -1
- package/dist/speed-dial/item/speed-dial-item.js +2 -2
- package/dist/speed-dial/root/speed-dial-root.d.ts +6 -0
- package/dist/speed-dial/root/speed-dial-root.js +11 -3
- package/dist/splitter/root/splitter-root.d.ts +10 -12
- package/dist/splitter/root/splitter-root.js +211 -204
- package/dist/stat/root/stat-root.d.ts +14 -5
- package/dist/stat/root/stat-root.js +21 -5
- package/dist/steps/reach.d.ts +5 -0
- package/dist/steps/reach.js +3 -0
- package/dist/steps/root/steps-root.d.ts +56 -3
- package/dist/steps/root/steps-root.js +50 -6
- package/dist/steps/step/step.d.ts +8 -0
- package/dist/steps/step/step.js +8 -3
- package/dist/switch/root/switch-root.d.ts +10 -0
- package/dist/table/column/table-column.d.ts +6 -10
- package/dist/table/column/table-column.js +8 -20
- package/dist/table/root/table-root.d.ts +31 -10
- package/dist/table/root/table-root.js +14 -18
- package/dist/table/row/table-row.d.ts +24 -0
- package/dist/table/row/table-row.js +37 -1
- package/dist/tabs/panel/tab-panel.d.ts +16 -3
- package/dist/tabs/panel/tab-panel.js +34 -5
- package/dist/tabs/root/tabs-root.d.ts +17 -3
- package/dist/tabs/root/tabs-root.js +1 -1
- package/dist/tabs/tab/tab.d.ts +5 -0
- package/dist/tabs/tab/tab.js +5 -2
- package/dist/tag/group/tag-group.d.ts +44 -5
- package/dist/tag/group/tag-group.js +60 -9
- package/dist/tag/root/tag-root.js +9 -2
- package/dist/textarea/root/textarea-root.d.ts +41 -2
- package/dist/textarea/root/textarea-root.js +39 -1
- package/dist/time-input/root/time-input-root.d.ts +10 -2
- package/dist/time-input/root/time-input-root.js +24 -13
- package/dist/time-picker/root/time-picker-root.d.ts +28 -17
- package/dist/time-picker/root/time-picker-root.js +18 -29
- package/dist/time-picker/wheel-name.d.ts +9 -0
- package/dist/time-picker/wheel-name.js +15 -0
- package/dist/timeline/group/timeline-group.js +2 -2
- package/dist/toast/item/toast-item.d.ts +16 -3
- package/dist/toast/item/toast-item.js +22 -6
- package/dist/toast/root/toast-root.d.ts +34 -4
- package/dist/toast/root/toast-root.js +74 -13
- package/dist/toast/words.d.ts +12 -0
- package/dist/toast/words.js +25 -0
- package/dist/toggle/group/toggle-group.d.ts +52 -7
- package/dist/toggle/group/toggle-group.js +58 -44
- package/dist/toggle/root/toggle-root.js +2 -4
- package/dist/toolbar/root/toolbar-root.d.ts +21 -5
- package/dist/toolbar/root/toolbar-root.js +52 -8
- package/dist/tooltip/root/tooltip-root.d.ts +20 -3
- package/dist/tooltip/root/tooltip-root.js +18 -1
- package/dist/tour/back.d.ts +10 -0
- package/dist/tour/back.js +8 -0
- package/dist/tour/root/tour-root.d.ts +45 -2
- package/dist/tour/root/tour-root.js +53 -8
- package/dist/tour/stop/tour-stop.d.ts +3 -0
- package/dist/tour/stop/tour-stop.js +3 -3
- package/dist/tree/item/tree-item.d.ts +7 -3
- package/dist/tree/item/tree-item.js +3 -0
- package/dist/tree/root/tree-root.d.ts +24 -3
- package/dist/tree/root/tree-root.js +32 -13
- package/dist/tree/selection.js +2 -15
- package/dist/trend/figure.d.ts +16 -0
- package/dist/trend/figure.js +8 -0
- package/dist/trend/root/trend-root.d.ts +83 -19
- package/dist/trend/root/trend-root.js +59 -8
- package/dist/video/media-events.d.ts +13 -18
- package/dist/video/media-events.js +1 -5
- 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 +23 -6
- package/dist/video/root/video-root.js +19 -10
- package/dist/video-playlist/menu/video-playlist-menu.d.ts +2 -0
- package/dist/video-playlist/menu/video-playlist-menu.js +2 -1
- package/dist/video-playlist/root/video-playlist-root.d.ts +17 -1
- package/dist/video-playlist/root/video-playlist-root.js +3 -0
- package/dist/virtual-list/fill.d.ts +11 -8
- package/dist/virtual-list/fill.js +10 -17
- package/dist/virtual-list/keys.d.ts +16 -7
- package/dist/virtual-list/keys.js +17 -6
- package/dist/virtual-list/plan.d.ts +65 -0
- package/dist/virtual-list/plan.js +27 -0
- package/dist/virtual-list/root/virtual-list-root.d.ts +136 -13
- package/dist/virtual-list/root/virtual-list-root.js +218 -51
- package/lint.json +1 -1
- package/package.json +8 -8
- package/types/jsx.d.ts +7441 -1458
- package/types/svelte.d.ts +1 -0
- package/types/vue.d.ts +1501 -326
- package/dist/chat/relative-clock.d.ts +0 -39
- package/dist/chat/relative-clock.js +0 -31
- package/dist/data-table/root/order.d.ts +0 -141
- package/dist/data-table/root/order.js +0 -76
- package/dist/tag/selection.d.ts +0 -10
- package/dist/tag/selection.js +0 -12
|
@@ -4,11 +4,12 @@ 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, hostAria, reportRuntime } from '@fusion.dev/helix-core';
|
|
7
|
+
import { auditName, customElement, HelixElement, hostAria, reportRuntime, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { html, nothing } from 'lit';
|
|
9
9
|
import { property } from 'lit/decorators.js';
|
|
10
10
|
import { unsafeSVG } from 'lit/directives/unsafe-svg.js';
|
|
11
|
-
import { resolveIcon, watchIcons } from '../registry.js';
|
|
11
|
+
import { iconMutator, resolveIcon, watchIcons } from '../registry.js';
|
|
12
|
+
import { afterPageSettles } from '../settle.js';
|
|
12
13
|
let HelixHeadlessIcon = class HelixHeadlessIcon extends HelixElement {
|
|
13
14
|
constructor() {
|
|
14
15
|
super(...arguments);
|
|
@@ -18,6 +19,7 @@ let HelixHeadlessIcon = class HelixHeadlessIcon extends HelixElement {
|
|
|
18
19
|
this.missed = '';
|
|
19
20
|
this.waiting = false;
|
|
20
21
|
this.arrived = '';
|
|
22
|
+
this.pending = '';
|
|
21
23
|
}
|
|
22
24
|
static get observedAttributes() {
|
|
23
25
|
return [...super.observedAttributes, 'aria-label'];
|
|
@@ -64,27 +66,57 @@ let HelixHeadlessIcon = class HelixHeadlessIcon extends HelixElement {
|
|
|
64
66
|
}
|
|
65
67
|
updated(changed) {
|
|
66
68
|
super.updated(changed);
|
|
69
|
+
if (this.drawn !== undefined) {
|
|
70
|
+
this.mutate();
|
|
71
|
+
this.auditControl();
|
|
72
|
+
}
|
|
67
73
|
if (this.arrived === this.name && this.drawn !== undefined) {
|
|
68
74
|
this.dispatchEvent(new Event('load', { bubbles: false, cancelable: false, composed: false }));
|
|
69
75
|
}
|
|
70
76
|
this.arrived = '';
|
|
71
77
|
if (this.drawn === undefined && this.name !== '' && !this.waiting) {
|
|
72
|
-
if (this.missed !== this.name) {
|
|
73
|
-
this.
|
|
74
|
-
|
|
75
|
-
reportRuntime({
|
|
76
|
-
kind: 'unknown-icon',
|
|
77
|
-
message: `<${this.localName} name="${this.name}"> names no registered icon, so it draws ` +
|
|
78
|
-
'nothing. Check the name, register the glyph with `registerIcons`, or import it ' +
|
|
79
|
-
'and pass it as `icon`.',
|
|
80
|
-
tag: this.localName,
|
|
81
|
-
});
|
|
78
|
+
if (this.missed !== this.name && this.pending !== this.name) {
|
|
79
|
+
this.pending = this.name;
|
|
80
|
+
afterPageSettles(() => this.reportMissing());
|
|
82
81
|
}
|
|
83
82
|
}
|
|
84
83
|
else {
|
|
85
84
|
this.missed = '';
|
|
86
85
|
}
|
|
87
86
|
}
|
|
87
|
+
mutate() {
|
|
88
|
+
const svg = this.renderRoot.querySelector('svg');
|
|
89
|
+
const mutator = this.icon === undefined ? iconMutator(this.name) : undefined;
|
|
90
|
+
if (svg && mutator) {
|
|
91
|
+
mutator(svg);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
auditControl() {
|
|
95
|
+
if (this.label !== '' || this.hasAttribute('aria-label')) {
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
const control = this.closest('a[href], button, summary, [role="button"], [role="link"]');
|
|
99
|
+
if (control) {
|
|
100
|
+
auditName(control, () => null, `Its only content is <${this.localName}>, which is decorative: give the icon a \`label\`, or the control an \`aria-label\`.`, () => (control.textContent ?? '').trim() !== '' ||
|
|
101
|
+
control.querySelector('[alt]:not([alt=""]), [aria-label]:not([aria-label=""])') !== null);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
reportMissing() {
|
|
105
|
+
const name = this.pending;
|
|
106
|
+
this.pending = '';
|
|
107
|
+
if (this.name !== name || this.drawn !== undefined || this.waiting || !this.isConnected) {
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
this.missed = name;
|
|
111
|
+
this.dispatchEvent(new Event('error', { bubbles: false, cancelable: false, composed: false }));
|
|
112
|
+
reportRuntime({
|
|
113
|
+
kind: 'unknown-icon',
|
|
114
|
+
message: `<${this.localName} name="${name}"> names no registered icon, so it draws ` +
|
|
115
|
+
'nothing. Check the name, register the glyph with `registerIcons`, or import it ' +
|
|
116
|
+
'and pass it as `icon`.',
|
|
117
|
+
tag: this.localName,
|
|
118
|
+
});
|
|
119
|
+
}
|
|
88
120
|
render() {
|
|
89
121
|
const icon = this.drawn;
|
|
90
122
|
if (!icon) {
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { type IconResolver, registerIconLibrary, registerIcons, resolveIcon } from '../registry.js';
|
|
1
|
+
export { type IconLibraryOptions, type IconResolver, registerIconLibrary, registerIcons, resolveIcon, } from '../registry.js';
|
|
2
2
|
export * from './icon-root.js';
|
package/dist/icon/root/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { registerIconLibrary, registerIcons, resolveIcon } from '../registry.js';
|
|
1
|
+
export { registerIconLibrary, registerIcons, resolveIcon, } from '../registry.js';
|
|
2
2
|
export * from './icon-root.js';
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Calls back once the page has loaded and painted a frame after it: every
|
|
3
|
+
* module a page lists has run by then, and with it every `registerIcons` and
|
|
4
|
+
* `registerIconLibrary` they hold. A page that has loaded already waits only
|
|
5
|
+
* the frame.
|
|
6
|
+
*/
|
|
7
|
+
export declare const afterPageSettles: (callback: () => void) => void;
|
|
@@ -17,6 +17,8 @@ import { HelixHeadlessButton } from '../../button/root/button-root.js';
|
|
|
17
17
|
* mean a part of a button, and an icon-only button is a complete button with
|
|
18
18
|
* different content and a different shape.
|
|
19
19
|
*
|
|
20
|
+
* **Keyboard.** Enter and Space press the button, as `Button`'s do.
|
|
21
|
+
*
|
|
20
22
|
* @since 0.1.0
|
|
21
23
|
* @status stable
|
|
22
24
|
* @category actions
|
|
@@ -12,13 +12,17 @@ import { type PropertyValues, type TemplateResult } from 'lit';
|
|
|
12
12
|
* The `placeholder` slot is empty by default, so the headless tier does not
|
|
13
13
|
* depend on `Skeleton`, which it does not ship.
|
|
14
14
|
*
|
|
15
|
+
* The placeholder is hidden from screen readers, the picture having a name of
|
|
16
|
+
* its own. The fallback is read once the picture fails, after the picture's
|
|
17
|
+
* `alt`, so a reader hears that it did not load, as a sighted reader sees.
|
|
18
|
+
*
|
|
15
19
|
* @since 0.1.0
|
|
16
20
|
* @status stable
|
|
17
21
|
* @category media
|
|
18
22
|
* @aliases Picture, Img, Figure
|
|
19
23
|
* @documentation https://fusion.dev/helix/components/image
|
|
20
24
|
*
|
|
21
|
-
* @slot fallback - Shown in place of the image if it fails to load.
|
|
25
|
+
* @slot fallback - Shown in place of the image if it fails to load, and read by screen readers then, such as "Photo unavailable".
|
|
22
26
|
* @slot placeholder - Shown until the image loads.
|
|
23
27
|
*
|
|
24
28
|
* @event {Event} error - The image failed to load. Relayed from the inner image, whose own event stays inside the shadow root.
|
|
@@ -30,6 +34,8 @@ import { type PropertyValues, type TemplateResult } from 'lit';
|
|
|
30
34
|
*
|
|
31
35
|
* @cssstate error - The image failed to load, and the fallback shows.
|
|
32
36
|
* @cssstate loaded - The image loaded.
|
|
37
|
+
* @cssstate loading - The image is on its way, so neither `loaded` nor `error` is true yet.
|
|
38
|
+
* @cssstate waiting - The image is on its way and `placeholder-delay` still holds the placeholder back.
|
|
33
39
|
*/
|
|
34
40
|
export declare class HelixHeadlessImage extends HelixElement {
|
|
35
41
|
/**
|
|
@@ -117,6 +123,11 @@ export declare class HelixHeadlessImage extends HelixElement {
|
|
|
117
123
|
*
|
|
118
124
|
* `loading` writes nothing, because it is where every image starts and the
|
|
119
125
|
* resting state of a mirror is the attribute's absence.
|
|
126
|
+
*
|
|
127
|
+
* **Kept beside the custom states, and what the styled tier draws from.** An
|
|
128
|
+
* engine without `CustomStateSet`, Safari before 17.4 and Firefox before
|
|
129
|
+
* 126, records no state, and a picture faded in by `:state(loaded)` alone
|
|
130
|
+
* would stay transparent there for good. A sheet of your own can read either.
|
|
120
131
|
*/
|
|
121
132
|
status: 'error' | 'loaded' | 'loading';
|
|
122
133
|
/**
|
|
@@ -190,6 +201,8 @@ export declare class HelixHeadlessImage extends HelixElement {
|
|
|
190
201
|
private settle;
|
|
191
202
|
protected willUpdate(changed: PropertyValues): void;
|
|
192
203
|
protected updated(changed: PropertyValues): void;
|
|
204
|
+
/** Whether the picture is on its way and the wait still holds the placeholder back. */
|
|
205
|
+
private get waiting();
|
|
193
206
|
private startWait;
|
|
194
207
|
protected firstUpdated(changed: PropertyValues): void;
|
|
195
208
|
/**
|
|
@@ -92,7 +92,12 @@ let HelixHeadlessImage = class HelixHeadlessImage extends HelixElement {
|
|
|
92
92
|
}
|
|
93
93
|
this.toggleState('loaded', this.status === 'loaded');
|
|
94
94
|
this.toggleState('error', this.status === 'error');
|
|
95
|
+
this.toggleState('loading', this.status === 'loading');
|
|
95
96
|
}
|
|
97
|
+
this.toggleState('waiting', this.waiting);
|
|
98
|
+
}
|
|
99
|
+
get waiting() {
|
|
100
|
+
return this.status === 'loading' && this.placeholderDelay > 0 && !this.wait.elapsed;
|
|
96
101
|
}
|
|
97
102
|
startWait() {
|
|
98
103
|
this.wait.start(this.placeholderDelay > 0 ? this.placeholderDelay : undefined);
|
|
@@ -142,12 +147,12 @@ let HelixHeadlessImage = class HelixHeadlessImage extends HelixElement {
|
|
|
142
147
|
<span
|
|
143
148
|
part="placeholder"
|
|
144
149
|
aria-hidden="true"
|
|
145
|
-
?hidden=${this.status !== 'loading' ||
|
|
150
|
+
?hidden=${this.status !== 'loading' || this.waiting}
|
|
146
151
|
><slot name="placeholder"></slot
|
|
147
152
|
></span>
|
|
148
153
|
<span
|
|
149
154
|
part="fallback"
|
|
150
|
-
aria-hidden
|
|
155
|
+
aria-hidden=${this.status === 'error' ? nothing : 'true'}
|
|
151
156
|
?hidden=${this.status !== 'error'}
|
|
152
157
|
><slot name="fallback"></slot
|
|
153
158
|
></span>`;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AriaForwardController, HelixFormElement } from '@fusion.dev/helix-core';
|
|
1
|
+
import { AriaForwardController, HelixFormElement, type OwnRule } from '@fusion.dev/helix-core';
|
|
2
2
|
import { type PropertyValues, type TemplateResult } from 'lit';
|
|
3
3
|
/** What the control accepts, which is text of one kind or another. */
|
|
4
4
|
export type InputType = 'email' | 'number' | 'password' | 'search' | 'tel' | 'text' | 'url';
|
|
@@ -20,7 +20,21 @@ declare const HelixHeadlessInput_base: (new (...args: any[]) => import("@fusion.
|
|
|
20
20
|
* which a reset restores.
|
|
21
21
|
*
|
|
22
22
|
* Validity comes from the browser. `type` and `required` are set on the real
|
|
23
|
-
* input, and its `validity` is copied to the host.
|
|
23
|
+
* input, and its `validity` is copied to the host. `validate` adds your own
|
|
24
|
+
* rule, run on every change once the browser finds nothing wrong, as React
|
|
25
|
+
* Aria's TextField `validate` does. What it returns is the message the field
|
|
26
|
+
* shows once the user has edited it, and the message a submit raises.
|
|
27
|
+
*
|
|
28
|
+
* **Keyboard.** The field's own keys are the platform's. Enter submits the
|
|
29
|
+
* form through its default button, as in a native field. The clear button
|
|
30
|
+
* under `clearable` and the reveal button under `reveal` are tab stops of
|
|
31
|
+
* their own after the field, so a keyboard reaches them.
|
|
32
|
+
*
|
|
33
|
+
* The inner input is named by `label`, or by a host `aria-label`,
|
|
34
|
+
* `aria-labelledby` or `<label for>`, and is described by the hint and the
|
|
35
|
+
* message, with `aria-invalid` while a message shows. The clear button is
|
|
36
|
+
* named `clear-label`, and the reveal button `reveal-label` with
|
|
37
|
+
* `aria-pressed` while the password shows.
|
|
24
38
|
*
|
|
25
39
|
* @since 0.1.0
|
|
26
40
|
* @status stable
|
|
@@ -28,10 +42,13 @@ declare const HelixHeadlessInput_base: (new (...args: any[]) => import("@fusion.
|
|
|
28
42
|
* @aliases TextField, Field, TextInput
|
|
29
43
|
* @documentation https://fusion.dev/helix/components/input
|
|
30
44
|
*
|
|
45
|
+
* @slot clear-icon - Replaces the cross on the clear button, under `clearable`.
|
|
46
|
+
* @slot conceal-icon - Replaces the crossed-out eye on the reveal button while the password shows, under `reveal`.
|
|
31
47
|
* @slot end - After the text, for an icon or a unit.
|
|
32
48
|
* @slot feedback - The message that says what is wrong, for content richer than a string. It shows while there is a message.
|
|
33
49
|
* @slot hint - Help under the control, for content richer than the `hint` text.
|
|
34
50
|
* @slot label - The label, for content richer than the `label` text.
|
|
51
|
+
* @slot reveal-icon - Replaces the eye on the reveal button while the password is hidden, under `reveal`.
|
|
35
52
|
* @slot start - Before the text, for an icon or a prefix.
|
|
36
53
|
*
|
|
37
54
|
* @event {Event} change - Sent when the user finishes changing the value. Relayed from the native input.
|
|
@@ -48,7 +65,8 @@ declare const HelixHeadlessInput_base: (new (...args: any[]) => import("@fusion.
|
|
|
48
65
|
* @csspart reveal - The button that shows and hides a password.
|
|
49
66
|
* @csspart reveal-pressed - The reveal button while the password is shown, added beside `reveal`.
|
|
50
67
|
*
|
|
51
|
-
* @cssstate
|
|
68
|
+
* @cssstate blank - The field holds no text.
|
|
69
|
+
* @cssstate invalid - The control has an error to show, from the browser's validation, `validate`, or your `feedback`.
|
|
52
70
|
*/
|
|
53
71
|
export declare class HelixHeadlessInput extends HelixHeadlessInput_base {
|
|
54
72
|
protected readonly aria: AriaForwardController;
|
|
@@ -281,6 +299,19 @@ export declare class HelixHeadlessInput extends HelixHeadlessInput_base {
|
|
|
281
299
|
* validation follow.
|
|
282
300
|
*/
|
|
283
301
|
type: InputType;
|
|
302
|
+
/**
|
|
303
|
+
* Your own rule for the value, run on every change once the browser finds
|
|
304
|
+
* nothing wrong. Return a message, or a list of them, to mark the field
|
|
305
|
+
* invalid, and `true`, `null`, or nothing to accept the value.
|
|
306
|
+
*/
|
|
307
|
+
validate?: OwnRule;
|
|
308
|
+
/** The cross on the clear button, behind a seam a tier can move. */
|
|
309
|
+
protected renderClearIcon(): TemplateResult;
|
|
310
|
+
/**
|
|
311
|
+
* The eye on the reveal button, behind a seam a tier can move: open while
|
|
312
|
+
* the password is hidden, and crossed out while it shows.
|
|
313
|
+
*/
|
|
314
|
+
protected renderRevealIcon(): TemplateResult;
|
|
284
315
|
protected render(): TemplateResult;
|
|
285
316
|
}
|
|
286
317
|
declare global {
|
|
@@ -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 { AriaForwardController, customElement, drawIcon, HelixClearEvent, HelixFormElement, holdCaret, MixinControllerValue, MixinField, restoreValue, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { AriaForwardController, applyOwnRule, customElement, drawIcon, HelixClearEvent, HelixFormElement, holdCaret, MixinControllerValue, MixinField, restoreValue, submitImplicitly, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { eye, eyeSlash, x } from '@fusion.dev/helix-icons';
|
|
9
9
|
import { html, nothing } from 'lit';
|
|
10
10
|
import { property, state } from 'lit/decorators.js';
|
|
@@ -48,7 +48,7 @@ let HelixHeadlessInput = class HelixHeadlessInput extends MixinControllerValue(M
|
|
|
48
48
|
};
|
|
49
49
|
this.handleKeypress = (event) => {
|
|
50
50
|
if (event.key === 'Enter' && !event.defaultPrevented) {
|
|
51
|
-
this.
|
|
51
|
+
submitImplicitly(this.form);
|
|
52
52
|
}
|
|
53
53
|
};
|
|
54
54
|
this.handleChange = (event) => {
|
|
@@ -112,6 +112,7 @@ let HelixHeadlessInput = class HelixHeadlessInput extends MixinControllerValue(M
|
|
|
112
112
|
return;
|
|
113
113
|
}
|
|
114
114
|
this.copyValidity(control);
|
|
115
|
+
applyOwnRule(this.internals, control, this.validate, this.value);
|
|
115
116
|
this.refreshFeedback();
|
|
116
117
|
}
|
|
117
118
|
focus(options) {
|
|
@@ -136,6 +137,7 @@ let HelixHeadlessInput = class HelixHeadlessInput extends MixinControllerValue(M
|
|
|
136
137
|
}
|
|
137
138
|
willUpdate(changed) {
|
|
138
139
|
super.willUpdate(changed);
|
|
140
|
+
this.toggleState('blank', this.value === '');
|
|
139
141
|
if (!this.hasUpdated) {
|
|
140
142
|
return;
|
|
141
143
|
}
|
|
@@ -150,6 +152,14 @@ let HelixHeadlessInput = class HelixHeadlessInput extends MixinControllerValue(M
|
|
|
150
152
|
this.releaseCaret = undefined;
|
|
151
153
|
this.sync();
|
|
152
154
|
}
|
|
155
|
+
renderClearIcon() {
|
|
156
|
+
return html `<slot name="clear-icon">${drawIcon(x)}</slot>`;
|
|
157
|
+
}
|
|
158
|
+
renderRevealIcon() {
|
|
159
|
+
return this.revealed
|
|
160
|
+
? html `<slot name="conceal-icon">${drawIcon(eyeSlash)}</slot>`
|
|
161
|
+
: html `<slot name="reveal-icon">${drawIcon(eye)}</slot>`;
|
|
162
|
+
}
|
|
153
163
|
render() {
|
|
154
164
|
return html `${this.renderLabel()}
|
|
155
165
|
<div part="field">
|
|
@@ -193,7 +203,7 @@ let HelixHeadlessInput = class HelixHeadlessInput extends MixinControllerValue(M
|
|
|
193
203
|
aria-label=${this.clearLabel}
|
|
194
204
|
@click=${this.handleClear}
|
|
195
205
|
>
|
|
196
|
-
${
|
|
206
|
+
${this.renderClearIcon()}
|
|
197
207
|
</button>`
|
|
198
208
|
: nothing}
|
|
199
209
|
${this.reveal && this.type === 'password'
|
|
@@ -207,7 +217,7 @@ let HelixHeadlessInput = class HelixHeadlessInput extends MixinControllerValue(M
|
|
|
207
217
|
this.revealed = !this.revealed;
|
|
208
218
|
}}
|
|
209
219
|
>
|
|
210
|
-
${
|
|
220
|
+
${this.renderRevealIcon()}
|
|
211
221
|
</button>`
|
|
212
222
|
: nothing}
|
|
213
223
|
</div>
|
|
@@ -268,6 +278,9 @@ __decorate([
|
|
|
268
278
|
__decorate([
|
|
269
279
|
property()
|
|
270
280
|
], HelixHeadlessInput.prototype, "type", void 0);
|
|
281
|
+
__decorate([
|
|
282
|
+
property({ attribute: false })
|
|
283
|
+
], HelixHeadlessInput.prototype, "validate", void 0);
|
|
271
284
|
HelixHeadlessInput = __decorate([
|
|
272
285
|
customElement('helix-headless-input')
|
|
273
286
|
], HelixHeadlessInput);
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The words and glyphs a chord is drawn with, per platform.
|
|
3
|
+
*
|
|
4
|
+
* Beside the family's `index.ts`, because which label a key gets is a table
|
|
5
|
+
* and a rule, and not the key's template.
|
|
6
|
+
*/
|
|
7
|
+
/** A chord's keys as they are shown, and what is shown between two of them. */
|
|
8
|
+
export interface KeyNames {
|
|
9
|
+
/** Each key's label, in the order the chord names them. */
|
|
10
|
+
keys: string[];
|
|
11
|
+
/** What goes between two keys: `+`, a hyphen, or nothing. */
|
|
12
|
+
separator: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* The labels of a chord's keys on a platform, with `own` labels in place of
|
|
16
|
+
* the platform's, and what goes between two keys.
|
|
17
|
+
*
|
|
18
|
+
* `parts` are the chord's names as `chordParts` splits them. A name `own`
|
|
19
|
+
* holds takes that label, a name the platform knows takes its glyph or word,
|
|
20
|
+
* and any other single character is shown in capitals.
|
|
21
|
+
*
|
|
22
|
+
* **On an Apple keyboard glyphs run together and words are joined with a
|
|
23
|
+
* hyphen**, as Apple writes `Command-K`. A label of more than one character
|
|
24
|
+
* from `own` is a word, so `{"mod": "Command"}` shows `Command-K` there, where
|
|
25
|
+
* nothing between the two ran them into `CommandK`. The platform's own `Esc`
|
|
26
|
+
* and `Space` keep running on from a glyph, as `⌘Esc` always has. Everywhere
|
|
27
|
+
* else keys are joined with `+`.
|
|
28
|
+
*/
|
|
29
|
+
export declare const keyNames: (parts: readonly string[], apple: boolean, own?: Readonly<Record<string, string>>) => KeyNames;
|
package/dist/kbd/keys.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
const APPLE = {
|
|
2
|
+
alt: '⌥',
|
|
3
|
+
backspace: '⌫',
|
|
4
|
+
cmd: '⌘',
|
|
5
|
+
ctrl: '⌃',
|
|
6
|
+
del: '⌦',
|
|
7
|
+
down: '↓',
|
|
8
|
+
enter: '↵',
|
|
9
|
+
esc: 'Esc',
|
|
10
|
+
left: '←',
|
|
11
|
+
meta: '⌘',
|
|
12
|
+
mod: '⌘',
|
|
13
|
+
opt: '⌥',
|
|
14
|
+
right: '→',
|
|
15
|
+
shift: '⇧',
|
|
16
|
+
space: 'Space',
|
|
17
|
+
tab: '⇥',
|
|
18
|
+
up: '↑',
|
|
19
|
+
};
|
|
20
|
+
const ELSEWHERE = {
|
|
21
|
+
alt: 'Alt',
|
|
22
|
+
backspace: 'Backspace',
|
|
23
|
+
cmd: 'Win',
|
|
24
|
+
ctrl: 'Ctrl',
|
|
25
|
+
del: 'Del',
|
|
26
|
+
down: '↓',
|
|
27
|
+
enter: 'Enter',
|
|
28
|
+
esc: 'Esc',
|
|
29
|
+
left: '←',
|
|
30
|
+
meta: 'Win',
|
|
31
|
+
mod: 'Ctrl',
|
|
32
|
+
opt: 'Alt',
|
|
33
|
+
right: '→',
|
|
34
|
+
shift: 'Shift',
|
|
35
|
+
space: 'Space',
|
|
36
|
+
tab: 'Tab',
|
|
37
|
+
up: '↑',
|
|
38
|
+
};
|
|
39
|
+
export const keyNames = (parts, apple, own = {}) => {
|
|
40
|
+
const names = apple ? APPLE : ELSEWHERE;
|
|
41
|
+
let worded = false;
|
|
42
|
+
const keys = parts.map((part) => {
|
|
43
|
+
const name = part.toLowerCase();
|
|
44
|
+
const mine = own[name];
|
|
45
|
+
if (mine !== undefined) {
|
|
46
|
+
worded ||= [...mine].length > 1;
|
|
47
|
+
return mine;
|
|
48
|
+
}
|
|
49
|
+
return names[name] ?? (part.length === 1 ? part.toUpperCase() : part);
|
|
50
|
+
});
|
|
51
|
+
return { keys, separator: apple ? (worded ? '-' : '') : '+' };
|
|
52
|
+
};
|
|
@@ -23,6 +23,17 @@ import { type PropertyValues, type TemplateResult } from 'lit';
|
|
|
23
23
|
* the shortcut with the control. A chord the page wrote there itself is left
|
|
24
24
|
* alone, and the key takes back only what it added.
|
|
25
25
|
*
|
|
26
|
+
* `caps` draws a chord as a key per key: each is a `key` part and the `+`
|
|
27
|
+
* between two a `separator` part, so a sheet can draw a cap for each.
|
|
28
|
+
* `key-labels` renames any key, on every platform, such as
|
|
29
|
+
* `key-labels='{"mod":"Command"}'`. On an Apple keyboard a word joins the
|
|
30
|
+
* next key with a hyphen, as in `Command-K`.
|
|
31
|
+
*
|
|
32
|
+
* **`activate` makes the shortcut work the control `for` names**, with no
|
|
33
|
+
* script: `activate="focus"` moves focus to it, as `/` does to a search
|
|
34
|
+
* field, and `activate="click"` presses it. It acts once `helix-shortcut` has
|
|
35
|
+
* gone out and no listener canceled it, and only where `within` listens.
|
|
36
|
+
*
|
|
26
37
|
* @since 0.1.0
|
|
27
38
|
* @status stable
|
|
28
39
|
* @category typography
|
|
@@ -33,9 +44,29 @@ import { type PropertyValues, type TemplateResult } from 'lit';
|
|
|
33
44
|
*
|
|
34
45
|
* @event {HelixShortcutEvent} helix-shortcut - The chord was pressed. Cancelable: cancel it to let the key press keep its usual effect.
|
|
35
46
|
*
|
|
36
|
-
* @csspart kbd - The key
|
|
47
|
+
* @csspart kbd - The key, or the chord under `keys`.
|
|
48
|
+
* @csspart key - One key of a chord under `keys` and `caps`, such as `Ctrl` in `Ctrl+K`.
|
|
49
|
+
* @csspart separator - The `+` between two keys of a chord under `keys` and `caps`, drawn where the platform writes one: on Windows and Linux. An Apple keyboard writes none between glyphs, and a hyphen between words from `key-labels`.
|
|
37
50
|
*/
|
|
38
51
|
export declare class HelixHeadlessKbd extends HelixElement {
|
|
52
|
+
/**
|
|
53
|
+
* What the chord does to the control `for` names once it is pressed:
|
|
54
|
+
* `focus` moves focus to the control and `click` presses it.
|
|
55
|
+
*
|
|
56
|
+
* Unset, the chord sends `helix-shortcut` and does nothing else, for a page
|
|
57
|
+
* that acts on the event itself. It acts only where `within` listens, after
|
|
58
|
+
* `helix-shortcut`, and not when a listener cancels that event.
|
|
59
|
+
*/
|
|
60
|
+
activate?: 'click' | 'focus';
|
|
61
|
+
/**
|
|
62
|
+
* Draws a chord under `keys` as one key per key, each a `key` part with a
|
|
63
|
+
* `separator` part between two where the platform writes a `+`, as GitHub
|
|
64
|
+
* and most docs draw `Ctrl` `K`.
|
|
65
|
+
*
|
|
66
|
+
* Absent, a chord is one key holding the whole label, as it always was.
|
|
67
|
+
* Reflected, because the styled tier draws the caps on the keys under it.
|
|
68
|
+
*/
|
|
69
|
+
caps: boolean;
|
|
39
70
|
/**
|
|
40
71
|
* The id of the control the shortcut works, which is given the chord as its
|
|
41
72
|
* `aria-keyshortcuts`.
|
|
@@ -45,6 +76,18 @@ export declare class HelixHeadlessKbd extends HelixElement {
|
|
|
45
76
|
* shortcut the page binds itself.
|
|
46
77
|
*/
|
|
47
78
|
for: string;
|
|
79
|
+
/**
|
|
80
|
+
* Names for keys in place of the platform's own, by the key's name in
|
|
81
|
+
* `keys`, written as JSON in the attribute: `key-labels='{"mod":"Command",
|
|
82
|
+
* "enter":"Return"}'` shows `Command` and `Return` wherever `mod` and
|
|
83
|
+
* `enter` are written.
|
|
84
|
+
*
|
|
85
|
+
* For a page in another language, or a product with its own word for a key.
|
|
86
|
+
* Absent, the platform's glyphs and words are used. Only what is shown
|
|
87
|
+
* changes: the chord written onto `aria-keyshortcuts` keeps the names a
|
|
88
|
+
* screen reader knows.
|
|
89
|
+
*/
|
|
90
|
+
keyLabels: Record<string, string>;
|
|
48
91
|
/**
|
|
49
92
|
* The key or chord to show, such as `mod+k`, `?`, or `/`.
|
|
50
93
|
*
|
|
@@ -91,8 +134,16 @@ export declare class HelixHeadlessKbd extends HelixElement {
|
|
|
91
134
|
private listen;
|
|
92
135
|
private deafen;
|
|
93
136
|
private readonly handleKeydown;
|
|
137
|
+
/** Focuses or presses the control `for` names, as `activate` says. */
|
|
138
|
+
private act;
|
|
94
139
|
protected firstUpdated(changed: PropertyValues): void;
|
|
95
140
|
protected render(): TemplateResult;
|
|
141
|
+
/**
|
|
142
|
+
* The chord under `caps`, a part for each key and for each `+` between two,
|
|
143
|
+
* so a sheet can draw a cap per key. Written with no space between, so a
|
|
144
|
+
* chord reads as the one label it was.
|
|
145
|
+
*/
|
|
146
|
+
protected renderChord(): TemplateResult;
|
|
96
147
|
}
|
|
97
148
|
declare global {
|
|
98
149
|
interface HTMLElementTagNameMap {
|
|
@@ -4,9 +4,10 @@ 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 { ariaChord, chordParts, customElement, elementById, HelixElement, HelixShortcutEvent, matchesChord, onApple, printableChord, } from '@fusion.dev/helix-core';
|
|
8
|
-
import { html } from 'lit';
|
|
7
|
+
import { ariaChord, chordParts, customElement, elementById, HelixElement, HelixShortcutEvent, matchesChord, onApple, printableChord, wordsConverter, } from '@fusion.dev/helix-core';
|
|
8
|
+
import { html, nothing } from 'lit';
|
|
9
9
|
import { property } from 'lit/decorators.js';
|
|
10
|
+
import { keyNames } from '../keys.js';
|
|
10
11
|
import { claimShortcut, releaseShortcut } from '../shortcut.js';
|
|
11
12
|
const typing = (node) => {
|
|
12
13
|
if (node instanceof HTMLTextAreaElement) {
|
|
@@ -29,48 +30,12 @@ const UNTYPED = new Set([
|
|
|
29
30
|
'reset',
|
|
30
31
|
'submit',
|
|
31
32
|
]);
|
|
32
|
-
const APPLE = {
|
|
33
|
-
alt: '⌥',
|
|
34
|
-
backspace: '⌫',
|
|
35
|
-
cmd: '⌘',
|
|
36
|
-
ctrl: '⌃',
|
|
37
|
-
del: '⌦',
|
|
38
|
-
down: '↓',
|
|
39
|
-
enter: '↵',
|
|
40
|
-
esc: 'Esc',
|
|
41
|
-
left: '←',
|
|
42
|
-
meta: '⌘',
|
|
43
|
-
mod: '⌘',
|
|
44
|
-
opt: '⌥',
|
|
45
|
-
right: '→',
|
|
46
|
-
shift: '⇧',
|
|
47
|
-
space: 'Space',
|
|
48
|
-
tab: '⇥',
|
|
49
|
-
up: '↑',
|
|
50
|
-
};
|
|
51
|
-
const ELSEWHERE = {
|
|
52
|
-
alt: 'Alt',
|
|
53
|
-
backspace: 'Backspace',
|
|
54
|
-
cmd: 'Win',
|
|
55
|
-
ctrl: 'Ctrl',
|
|
56
|
-
del: 'Del',
|
|
57
|
-
down: '↓',
|
|
58
|
-
enter: 'Enter',
|
|
59
|
-
esc: 'Esc',
|
|
60
|
-
left: '←',
|
|
61
|
-
meta: 'Win',
|
|
62
|
-
mod: 'Ctrl',
|
|
63
|
-
opt: 'Alt',
|
|
64
|
-
right: '→',
|
|
65
|
-
shift: 'Shift',
|
|
66
|
-
space: 'Space',
|
|
67
|
-
tab: 'Tab',
|
|
68
|
-
up: '↑',
|
|
69
|
-
};
|
|
70
33
|
let HelixHeadlessKbd = class HelixHeadlessKbd extends HelixElement {
|
|
71
34
|
constructor() {
|
|
72
35
|
super(...arguments);
|
|
36
|
+
this.caps = false;
|
|
73
37
|
this.for = '';
|
|
38
|
+
this.keyLabels = {};
|
|
74
39
|
this.keys = '';
|
|
75
40
|
this.handleKeydown = (event) => {
|
|
76
41
|
const press = event;
|
|
@@ -87,9 +52,11 @@ let HelixHeadlessKbd = class HelixHeadlessKbd extends HelixElement {
|
|
|
87
52
|
}
|
|
88
53
|
const shortcut = new HelixShortcutEvent({ keys: this.keys });
|
|
89
54
|
this.dispatchEvent(shortcut);
|
|
90
|
-
if (
|
|
91
|
-
|
|
55
|
+
if (shortcut.defaultPrevented) {
|
|
56
|
+
return;
|
|
92
57
|
}
|
|
58
|
+
press.preventDefault();
|
|
59
|
+
this.act();
|
|
93
60
|
};
|
|
94
61
|
}
|
|
95
62
|
connectedCallback() {
|
|
@@ -132,10 +99,7 @@ let HelixHeadlessKbd = class HelixHeadlessKbd extends HelixElement {
|
|
|
132
99
|
}
|
|
133
100
|
}
|
|
134
101
|
get label() {
|
|
135
|
-
|
|
136
|
-
const names = apple ? APPLE : ELSEWHERE;
|
|
137
|
-
const parts = chordParts(this.keys).map((part) => names[part.toLowerCase()] ?? (part.length === 1 ? part.toUpperCase() : part));
|
|
138
|
-
return parts.join(apple ? '' : '+');
|
|
102
|
+
return keyNames(chordParts(this.keys), !this.hydrating && onApple(), this.keyLabels ?? {});
|
|
139
103
|
}
|
|
140
104
|
listen() {
|
|
141
105
|
if (!this.within || this.keys === '') {
|
|
@@ -152,17 +116,46 @@ let HelixHeadlessKbd = class HelixHeadlessKbd extends HelixElement {
|
|
|
152
116
|
this.listening?.removeEventListener('keydown', this.handleKeydown);
|
|
153
117
|
this.listening = undefined;
|
|
154
118
|
}
|
|
119
|
+
act() {
|
|
120
|
+
const control = this.activate && this.for !== '' ? elementById(this, this.for) : null;
|
|
121
|
+
if (!(control instanceof HTMLElement)) {
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
if (this.activate === 'click') {
|
|
125
|
+
control.click();
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
control.focus();
|
|
129
|
+
}
|
|
130
|
+
}
|
|
155
131
|
firstUpdated(changed) {
|
|
156
132
|
super.firstUpdated(changed);
|
|
157
133
|
this.finishHydration();
|
|
158
134
|
}
|
|
159
135
|
render() {
|
|
160
|
-
|
|
136
|
+
if (this.keys === '') {
|
|
137
|
+
return html `<kbd part="kbd"><slot></slot></kbd>`;
|
|
138
|
+
}
|
|
139
|
+
const { keys, separator } = this.label;
|
|
140
|
+
return html `<kbd part="kbd">${this.caps ? this.renderChord() : keys.join(separator)}</kbd>`;
|
|
141
|
+
}
|
|
142
|
+
renderChord() {
|
|
143
|
+
const { keys, separator } = this.label;
|
|
144
|
+
return html `${keys.map((key, index) => html `${index > 0 && separator !== '' ? html `<span part="separator">${separator}</span>` : nothing}<span part="key">${key}</span>`)}`;
|
|
161
145
|
}
|
|
162
146
|
};
|
|
147
|
+
__decorate([
|
|
148
|
+
property()
|
|
149
|
+
], HelixHeadlessKbd.prototype, "activate", void 0);
|
|
150
|
+
__decorate([
|
|
151
|
+
property({ reflect: true, type: Boolean })
|
|
152
|
+
], HelixHeadlessKbd.prototype, "caps", void 0);
|
|
163
153
|
__decorate([
|
|
164
154
|
property()
|
|
165
155
|
], HelixHeadlessKbd.prototype, "for", void 0);
|
|
156
|
+
__decorate([
|
|
157
|
+
property({ attribute: 'key-labels', converter: wordsConverter })
|
|
158
|
+
], HelixHeadlessKbd.prototype, "keyLabels", void 0);
|
|
166
159
|
__decorate([
|
|
167
160
|
property()
|
|
168
161
|
], HelixHeadlessKbd.prototype, "keys", void 0);
|