@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,31 +4,44 @@ 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 { CommandController, customElement, deepActiveElement, deepContains, FullscreenController, fillTemplate, HelixElement, hostAria, IdleController, inlineStep, isRtl, keyClaimed, lockScroll, MixinControllerActive, MixinControllerOpen, resolveActiveItem, SwipeController, swipeStep, unlockScroll, whenHydrated, } from '@fusion.dev/helix-core';
|
|
8
|
-
import { caretLeft, caretRight,
|
|
7
|
+
import { CommandController, customElement, DelayController, deepActiveElement, deepContains, drawDismiss, drawDismissGlyph, FullscreenController, fillTemplate, HelixElement, hostAria, IdleController, inlineStep, isRtl, keyClaimed, lockScroll, MixinControllerActive, MixinControllerOpen, resolveActiveItem, SwipeController, swipeStep, unlockScroll, whenHydrated, } from '@fusion.dev/helix-core';
|
|
8
|
+
import { caretLeft, caretRight, minus, plus } from '@fusion.dev/helix-icons';
|
|
9
9
|
import { html, nothing } from 'lit';
|
|
10
10
|
import { property, state } from 'lit/decorators.js';
|
|
11
11
|
import { unsafeSVG } from 'lit/directives/unsafe-svg.js';
|
|
12
12
|
import { HelixHeadlessLightboxItem } from '../item/lightbox-item.js';
|
|
13
|
+
import { percentOf } from '../zoom.js';
|
|
14
|
+
import { ZoomController } from '../zoom-controller.js';
|
|
13
15
|
let HelixHeadlessLightbox = class HelixHeadlessLightbox extends MixinControllerActive(MixinControllerOpen(HelixElement)) {
|
|
14
16
|
constructor() {
|
|
15
17
|
super(...arguments);
|
|
16
18
|
this.controls = false;
|
|
19
|
+
this.counter = false;
|
|
17
20
|
this.dismissLabel = 'Close';
|
|
18
21
|
this.idleDelay = 0;
|
|
19
22
|
this.label = '';
|
|
20
23
|
this.loop = false;
|
|
24
|
+
this.maxZoom = 1;
|
|
21
25
|
this.nextLabel = 'Next';
|
|
22
26
|
this.previousLabel = 'Previous';
|
|
23
27
|
this.slideLabel = '{index} of {count}';
|
|
24
28
|
this.slideRoleLabel = 'slide';
|
|
25
29
|
this.statusLabel = '{index} of {count}';
|
|
30
|
+
this.zoomInLabel = 'Zoom in';
|
|
31
|
+
this.zoomOutLabel = 'Zoom out';
|
|
32
|
+
this.zoomStatusLabel = 'Zoomed to {percent}%';
|
|
26
33
|
this.resting = false;
|
|
27
34
|
this.filled = false;
|
|
28
35
|
this.announcement = '';
|
|
36
|
+
this.zoomScale = 1;
|
|
37
|
+
this.zoomSaid = new DelayController(this, { renders: false });
|
|
38
|
+
this.quietZoom = false;
|
|
29
39
|
this.swipes = new SwipeController(this, {
|
|
30
|
-
axis: () => (this.open ? 'x' : undefined),
|
|
40
|
+
axis: () => (this.open && !this.zoomer.engaged ? 'x' : undefined),
|
|
31
41
|
end: (dx, _dy, vx) => {
|
|
42
|
+
if (this.zoomer.pinched) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
32
45
|
const width = this.partNamed('viewport')?.getBoundingClientRect().width ?? 0;
|
|
33
46
|
const step = swipeStep(dx, vx, width, isRtl(this));
|
|
34
47
|
if (step !== 0) {
|
|
@@ -39,6 +52,11 @@ let HelixHeadlessLightbox = class HelixHeadlessLightbox extends MixinControllerA
|
|
|
39
52
|
start: (_target, event) => event.pointerType !== 'mouse',
|
|
40
53
|
surface: () => this.dialog,
|
|
41
54
|
});
|
|
55
|
+
this.zoomer = new ZoomController(this, {
|
|
56
|
+
max: () => (this.open ? this.maxZoom : 1),
|
|
57
|
+
onChange: (scale, pan) => this.drawZoom(scale, pan),
|
|
58
|
+
surface: () => this.partNamed('viewport'),
|
|
59
|
+
});
|
|
42
60
|
this.fullscreen = new FullscreenController(this, (full) => {
|
|
43
61
|
this.filled = full;
|
|
44
62
|
});
|
|
@@ -70,6 +88,10 @@ let HelixHeadlessLightbox = class HelixHeadlessLightbox extends MixinControllerA
|
|
|
70
88
|
if (keyClaimed(event) || event.altKey || event.ctrlKey || event.metaKey) {
|
|
71
89
|
return;
|
|
72
90
|
}
|
|
91
|
+
if (this.zoomKey(event.key)) {
|
|
92
|
+
event.preventDefault();
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
73
95
|
const along = inlineStep(this, event.key);
|
|
74
96
|
if (along === 1 || event.key === 'ArrowDown') {
|
|
75
97
|
event.preventDefault();
|
|
@@ -103,9 +125,34 @@ let HelixHeadlessLightbox = class HelixHeadlessLightbox extends MixinControllerA
|
|
|
103
125
|
this.requestOpen(false);
|
|
104
126
|
};
|
|
105
127
|
}
|
|
128
|
+
drawZoom(scale, pan) {
|
|
129
|
+
const viewport = this.partNamed('viewport');
|
|
130
|
+
const zoomed = scale > 1;
|
|
131
|
+
viewport?.style.setProperty('--lightbox-zoom', zoomed ? String(scale) : '');
|
|
132
|
+
viewport?.style.setProperty('--lightbox-pan-x', zoomed ? `${Math.round(pan.x)}px` : '');
|
|
133
|
+
viewport?.style.setProperty('--lightbox-pan-y', zoomed ? `${Math.round(pan.y)}px` : '');
|
|
134
|
+
this.toggleState('zoomed', zoomed);
|
|
135
|
+
this.idle.stir();
|
|
136
|
+
if (scale !== this.zoomScale) {
|
|
137
|
+
this.zoomScale = scale;
|
|
138
|
+
this.sayZoom();
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
sayZoom() {
|
|
142
|
+
if (this.quietZoom || !this.open || this.zoomStatusLabel === '') {
|
|
143
|
+
this.zoomSaid.cancel();
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
this.zoomSaid.start(400, () => {
|
|
147
|
+
this.announcement = fillTemplate(this.zoomStatusLabel, { percent: percentOf(this.zoomScale) });
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
zoomTo(scale) {
|
|
151
|
+
this.zoomer.zoomTo(scale);
|
|
152
|
+
}
|
|
106
153
|
chromeHasFocus() {
|
|
107
154
|
const active = deepActiveElement();
|
|
108
|
-
const own = this.shadowRoot?.activeElement?.matches('[part="previous"], [part="next"], [part="dismiss"]');
|
|
155
|
+
const own = this.shadowRoot?.activeElement?.matches('[part="previous"], [part="next"], [part="dismiss"], [part="zoom-in"], [part="zoom-out"]');
|
|
109
156
|
return (own === true ||
|
|
110
157
|
this.knownChildren.some((child) => (child.slot === 'header' || child.slot === 'footer') && deepContains(child, active)));
|
|
111
158
|
}
|
|
@@ -147,6 +194,30 @@ let HelixHeadlessLightbox = class HelixHeadlessLightbox extends MixinControllerA
|
|
|
147
194
|
this.requestActive(target.value);
|
|
148
195
|
}
|
|
149
196
|
}
|
|
197
|
+
zoomKey(key) {
|
|
198
|
+
if (this.maxZoom <= 1) {
|
|
199
|
+
return false;
|
|
200
|
+
}
|
|
201
|
+
if (key === '+' || key === '=') {
|
|
202
|
+
this.zoomIn();
|
|
203
|
+
}
|
|
204
|
+
else if (key === '-') {
|
|
205
|
+
this.zoomOut();
|
|
206
|
+
}
|
|
207
|
+
else if (key === '0') {
|
|
208
|
+
this.zoomer.reset();
|
|
209
|
+
}
|
|
210
|
+
else {
|
|
211
|
+
return false;
|
|
212
|
+
}
|
|
213
|
+
return true;
|
|
214
|
+
}
|
|
215
|
+
zoomIn() {
|
|
216
|
+
this.zoomer.zoomTo(this.zoomer.scale * 1.5);
|
|
217
|
+
}
|
|
218
|
+
zoomOut() {
|
|
219
|
+
this.zoomer.zoomTo(this.zoomer.scale / 1.5);
|
|
220
|
+
}
|
|
150
221
|
toEnd(at) {
|
|
151
222
|
const target = this.items[at];
|
|
152
223
|
if (target && target !== this.shown) {
|
|
@@ -161,6 +232,12 @@ let HelixHeadlessLightbox = class HelixHeadlessLightbox extends MixinControllerA
|
|
|
161
232
|
hostAria(this.internals, { label: this.label });
|
|
162
233
|
this.toggleState('fullscreen', this.filled);
|
|
163
234
|
this.toggleState('idle', this.resting);
|
|
235
|
+
this.toggleState('zoomable', this.maxZoom > 1);
|
|
236
|
+
if (changed.has('active') || (changed.has('open') && !this.open)) {
|
|
237
|
+
this.quietZoom = true;
|
|
238
|
+
this.zoomer.reset();
|
|
239
|
+
this.quietZoom = false;
|
|
240
|
+
}
|
|
164
241
|
this.say(changed);
|
|
165
242
|
}
|
|
166
243
|
disconnectedCallback() {
|
|
@@ -230,6 +307,17 @@ let HelixHeadlessLightbox = class HelixHeadlessLightbox extends MixinControllerA
|
|
|
230
307
|
label: current.label,
|
|
231
308
|
});
|
|
232
309
|
}
|
|
310
|
+
place() {
|
|
311
|
+
const items = this.items;
|
|
312
|
+
const current = resolveActiveItem(this.active, items);
|
|
313
|
+
return current
|
|
314
|
+
? fillTemplate(this.statusLabel, {
|
|
315
|
+
count: items.length,
|
|
316
|
+
index: items.indexOf(current) + 1,
|
|
317
|
+
label: current.label,
|
|
318
|
+
})
|
|
319
|
+
: '';
|
|
320
|
+
}
|
|
233
321
|
render() {
|
|
234
322
|
return html `<dialog
|
|
235
323
|
part="dialog"
|
|
@@ -244,12 +332,13 @@ let HelixHeadlessLightbox = class HelixHeadlessLightbox extends MixinControllerA
|
|
|
244
332
|
@pointerleave=${this.idle.leave}
|
|
245
333
|
@pointermove=${this.idle.stir}
|
|
246
334
|
>
|
|
247
|
-
<slot name="header"></slot>
|
|
335
|
+
<slot name="header" part="header"></slot>
|
|
248
336
|
<div part="viewport">
|
|
249
337
|
<slot></slot>
|
|
250
338
|
</div>
|
|
251
|
-
<slot name="footer"></slot>
|
|
339
|
+
<slot name="footer" part="footer"></slot>
|
|
252
340
|
${this.controls ? this.renderControls() : nothing}
|
|
341
|
+
${this.counter ? html `<span part="counter" aria-hidden="true">${this.place()}</span>` : nothing}
|
|
253
342
|
<span part="live" role="status" aria-live="polite">${this.announcement || nothing}</span>
|
|
254
343
|
</dialog>`;
|
|
255
344
|
}
|
|
@@ -261,9 +350,11 @@ let HelixHeadlessLightbox = class HelixHeadlessLightbox extends MixinControllerA
|
|
|
261
350
|
aria-disabled=${this.atEnd(-1) ? 'true' : nothing}
|
|
262
351
|
@click=${() => this.previous()}
|
|
263
352
|
>
|
|
264
|
-
<
|
|
265
|
-
|
|
266
|
-
|
|
353
|
+
<slot name="previous-icon">
|
|
354
|
+
<svg part="previous-mark" data-mirror fill="currentColor" viewBox=${caretLeft.viewBox} aria-hidden="true">
|
|
355
|
+
${unsafeSVG(caretLeft.content)}
|
|
356
|
+
</svg>
|
|
357
|
+
</slot>
|
|
267
358
|
</button>
|
|
268
359
|
<button
|
|
269
360
|
part="next"
|
|
@@ -272,25 +363,54 @@ let HelixHeadlessLightbox = class HelixHeadlessLightbox extends MixinControllerA
|
|
|
272
363
|
aria-disabled=${this.atEnd(1) ? 'true' : nothing}
|
|
273
364
|
@click=${() => this.next()}
|
|
274
365
|
>
|
|
275
|
-
<
|
|
276
|
-
|
|
277
|
-
|
|
366
|
+
<slot name="next-icon">
|
|
367
|
+
<svg part="next-mark" data-mirror fill="currentColor" viewBox=${caretRight.viewBox} aria-hidden="true">
|
|
368
|
+
${unsafeSVG(caretRight.content)}
|
|
369
|
+
</svg>
|
|
370
|
+
</slot>
|
|
371
|
+
</button>
|
|
372
|
+
${this.maxZoom > 1 ? this.renderZoomControls() : nothing}
|
|
373
|
+
${drawDismiss({
|
|
374
|
+
label: this.dismissLabel,
|
|
375
|
+
mark: html `<slot name="dismiss-icon">${drawDismissGlyph()}</slot>`,
|
|
376
|
+
onDismiss: () => this.close(),
|
|
377
|
+
})}`;
|
|
378
|
+
}
|
|
379
|
+
renderZoomControls() {
|
|
380
|
+
return html `<button
|
|
381
|
+
part="zoom-out"
|
|
382
|
+
type="button"
|
|
383
|
+
aria-label=${this.zoomOutLabel}
|
|
384
|
+
aria-disabled=${this.zoomScale <= 1 ? 'true' : nothing}
|
|
385
|
+
@click=${() => this.zoomOut()}
|
|
386
|
+
>
|
|
387
|
+
<slot name="zoom-out-icon">
|
|
388
|
+
<svg part="zoom-out-mark" fill="currentColor" viewBox=${minus.viewBox} aria-hidden="true">
|
|
389
|
+
${unsafeSVG(minus.content)}
|
|
390
|
+
</svg>
|
|
391
|
+
</slot>
|
|
278
392
|
</button>
|
|
279
393
|
<button
|
|
280
|
-
part="
|
|
394
|
+
part="zoom-in"
|
|
281
395
|
type="button"
|
|
282
|
-
aria-label=${this.
|
|
283
|
-
|
|
396
|
+
aria-label=${this.zoomInLabel}
|
|
397
|
+
aria-disabled=${this.zoomScale >= this.maxZoom ? 'true' : nothing}
|
|
398
|
+
@click=${() => this.zoomIn()}
|
|
284
399
|
>
|
|
285
|
-
<
|
|
286
|
-
|
|
287
|
-
|
|
400
|
+
<slot name="zoom-in-icon">
|
|
401
|
+
<svg part="zoom-in-mark" fill="currentColor" viewBox=${plus.viewBox} aria-hidden="true">
|
|
402
|
+
${unsafeSVG(plus.content)}
|
|
403
|
+
</svg>
|
|
404
|
+
</slot>
|
|
288
405
|
</button>`;
|
|
289
406
|
}
|
|
290
407
|
};
|
|
291
408
|
__decorate([
|
|
292
409
|
property({ reflect: true, type: Boolean })
|
|
293
410
|
], HelixHeadlessLightbox.prototype, "controls", void 0);
|
|
411
|
+
__decorate([
|
|
412
|
+
property({ reflect: true, type: Boolean })
|
|
413
|
+
], HelixHeadlessLightbox.prototype, "counter", void 0);
|
|
294
414
|
__decorate([
|
|
295
415
|
property({ attribute: 'dismiss-label' })
|
|
296
416
|
], HelixHeadlessLightbox.prototype, "dismissLabel", void 0);
|
|
@@ -303,6 +423,9 @@ __decorate([
|
|
|
303
423
|
__decorate([
|
|
304
424
|
property({ reflect: true, type: Boolean })
|
|
305
425
|
], HelixHeadlessLightbox.prototype, "loop", void 0);
|
|
426
|
+
__decorate([
|
|
427
|
+
property({ attribute: 'max-zoom', type: Number })
|
|
428
|
+
], HelixHeadlessLightbox.prototype, "maxZoom", void 0);
|
|
306
429
|
__decorate([
|
|
307
430
|
property({ attribute: 'next-label' })
|
|
308
431
|
], HelixHeadlessLightbox.prototype, "nextLabel", void 0);
|
|
@@ -318,6 +441,15 @@ __decorate([
|
|
|
318
441
|
__decorate([
|
|
319
442
|
property({ attribute: 'status-label' })
|
|
320
443
|
], HelixHeadlessLightbox.prototype, "statusLabel", void 0);
|
|
444
|
+
__decorate([
|
|
445
|
+
property({ attribute: 'zoom-in-label' })
|
|
446
|
+
], HelixHeadlessLightbox.prototype, "zoomInLabel", void 0);
|
|
447
|
+
__decorate([
|
|
448
|
+
property({ attribute: 'zoom-out-label' })
|
|
449
|
+
], HelixHeadlessLightbox.prototype, "zoomOutLabel", void 0);
|
|
450
|
+
__decorate([
|
|
451
|
+
property({ attribute: 'zoom-status-label' })
|
|
452
|
+
], HelixHeadlessLightbox.prototype, "zoomStatusLabel", void 0);
|
|
321
453
|
__decorate([
|
|
322
454
|
state()
|
|
323
455
|
], HelixHeadlessLightbox.prototype, "resting", void 0);
|
|
@@ -327,6 +459,9 @@ __decorate([
|
|
|
327
459
|
__decorate([
|
|
328
460
|
state()
|
|
329
461
|
], HelixHeadlessLightbox.prototype, "announcement", void 0);
|
|
462
|
+
__decorate([
|
|
463
|
+
state()
|
|
464
|
+
], HelixHeadlessLightbox.prototype, "zoomScale", void 0);
|
|
330
465
|
HelixHeadlessLightbox = __decorate([
|
|
331
466
|
customElement('helix-headless-lightbox')
|
|
332
467
|
], HelixHeadlessLightbox);
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { ReactiveController, ReactiveControllerHost } from 'lit';
|
|
2
|
+
import { type Offset } from './zoom.js';
|
|
3
|
+
export interface ZoomOptions {
|
|
4
|
+
/** The most the item may grow, as a scale. 1 or less turns zooming off. */
|
|
5
|
+
max: () => number;
|
|
6
|
+
/** Told every time the scale or the position changes. */
|
|
7
|
+
onChange: (scale: number, pan: Offset) => void;
|
|
8
|
+
/** The box the item is shown in, which presses must land in and the item scales from the middle of. */
|
|
9
|
+
surface: () => HTMLElement | null | undefined;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Pinch, double press and drag to zoom into the item a viewer shows, and to
|
|
13
|
+
* move about it once zoomed.
|
|
14
|
+
*
|
|
15
|
+
* Two fingers scale the item about the point between them. A double press, a
|
|
16
|
+
* double click or a double tap, zooms all the way in about the point pressed,
|
|
17
|
+
* and back out again. One pointer dragged across a zoomed item moves it, never
|
|
18
|
+
* so far that an edge comes inside the box. What it reports is a scale and an
|
|
19
|
+
* offset from the middle of the box; drawing them is the caller's.
|
|
20
|
+
*/
|
|
21
|
+
export declare class ZoomController implements ReactiveController {
|
|
22
|
+
private readonly host;
|
|
23
|
+
private readonly options;
|
|
24
|
+
/** The pointers down on the box, where each one is now. */
|
|
25
|
+
private readonly pointers;
|
|
26
|
+
/** What the gesture under way started from. */
|
|
27
|
+
private from;
|
|
28
|
+
/** The scale, 1 at rest. */
|
|
29
|
+
scale: number;
|
|
30
|
+
/** How far the item is moved from the middle of the box, in pixels. */
|
|
31
|
+
pan: Offset;
|
|
32
|
+
/**
|
|
33
|
+
* Whether two fingers have been down since the last gesture began, so a
|
|
34
|
+
* swipe that started with the first of them can be told it was a pinch.
|
|
35
|
+
*/
|
|
36
|
+
pinched: boolean;
|
|
37
|
+
constructor(host: ReactiveControllerHost & HTMLElement, options: ZoomOptions);
|
|
38
|
+
/** Whether the item is zoomed, or two fingers are on it: either way, a drag is not a swipe. */
|
|
39
|
+
get engaged(): boolean;
|
|
40
|
+
hostConnected(): void;
|
|
41
|
+
hostDisconnected(): void;
|
|
42
|
+
/** Zooms to `scale` about the middle of the box, held to the range. */
|
|
43
|
+
zoomTo(scale: number, at?: Offset): void;
|
|
44
|
+
/** Back to the item at its own size, in the middle. */
|
|
45
|
+
reset(): void;
|
|
46
|
+
private set;
|
|
47
|
+
/** A point on the page, measured from the middle of the box. */
|
|
48
|
+
private offset;
|
|
49
|
+
/** Whether a press landed in the box, through slotted content as well. */
|
|
50
|
+
private inside;
|
|
51
|
+
/** Starts over from where every pointer down is now. */
|
|
52
|
+
private begin;
|
|
53
|
+
private readonly handleDown;
|
|
54
|
+
private readonly handleMove;
|
|
55
|
+
private readonly handleUp;
|
|
56
|
+
/** A double press zooms all the way in about the point, or back out. */
|
|
57
|
+
private readonly handleDouble;
|
|
58
|
+
private release;
|
|
59
|
+
}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { between, clampPan, clampScale, spread, zoomAt } from './zoom.js';
|
|
2
|
+
export class ZoomController {
|
|
3
|
+
constructor(host, options) {
|
|
4
|
+
this.pointers = new Map();
|
|
5
|
+
this.scale = 1;
|
|
6
|
+
this.pan = { x: 0, y: 0 };
|
|
7
|
+
this.pinched = false;
|
|
8
|
+
this.handleDown = (event) => {
|
|
9
|
+
if (this.options.max() <= 1 || event.button !== 0 || !this.inside(event)) {
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
if (this.pointers.size === 0) {
|
|
13
|
+
this.pinched = false;
|
|
14
|
+
window.addEventListener('pointermove', this.handleMove);
|
|
15
|
+
window.addEventListener('pointerup', this.handleUp);
|
|
16
|
+
window.addEventListener('pointercancel', this.handleUp);
|
|
17
|
+
}
|
|
18
|
+
this.pointers.set(event.pointerId, this.offset(event));
|
|
19
|
+
if (this.pointers.size > 1) {
|
|
20
|
+
this.pinched = true;
|
|
21
|
+
}
|
|
22
|
+
this.begin();
|
|
23
|
+
};
|
|
24
|
+
this.handleMove = (event) => {
|
|
25
|
+
const from = this.from;
|
|
26
|
+
if (!from || !this.pointers.has(event.pointerId)) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
this.pointers.set(event.pointerId, this.offset(event));
|
|
30
|
+
const [a, b] = [...this.pointers.values()];
|
|
31
|
+
if (a && b && from.spread > 0) {
|
|
32
|
+
const at = between(a, b);
|
|
33
|
+
const scale = clampScale((from.scale * spread(a, b)) / from.spread, this.options.max());
|
|
34
|
+
const about = zoomAt(from.at, from.scale, scale, from.pan);
|
|
35
|
+
this.set(scale, { x: about.x + at.x - from.at.x, y: about.y + at.y - from.at.y });
|
|
36
|
+
}
|
|
37
|
+
else if (a && this.scale > 1) {
|
|
38
|
+
this.set(this.scale, { x: from.pan.x + a.x - from.at.x, y: from.pan.y + a.y - from.at.y });
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
this.handleUp = (event) => {
|
|
42
|
+
if (!this.pointers.delete(event.pointerId)) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
if (this.pointers.size === 0) {
|
|
46
|
+
this.release();
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
this.begin();
|
|
50
|
+
};
|
|
51
|
+
this.handleDouble = (event) => {
|
|
52
|
+
if (this.options.max() <= 1 || !this.inside(event)) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
if (this.scale > 1) {
|
|
56
|
+
this.reset();
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
this.zoomTo(this.options.max(), this.offset(event));
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
this.host = host;
|
|
63
|
+
this.options = options;
|
|
64
|
+
host.addController(this);
|
|
65
|
+
}
|
|
66
|
+
get engaged() {
|
|
67
|
+
return this.scale > 1 || this.pointers.size > 1;
|
|
68
|
+
}
|
|
69
|
+
hostConnected() {
|
|
70
|
+
this.host.addEventListener('pointerdown', this.handleDown);
|
|
71
|
+
this.host.addEventListener('dblclick', this.handleDouble);
|
|
72
|
+
}
|
|
73
|
+
hostDisconnected() {
|
|
74
|
+
this.host.removeEventListener('pointerdown', this.handleDown);
|
|
75
|
+
this.host.removeEventListener('dblclick', this.handleDouble);
|
|
76
|
+
this.release();
|
|
77
|
+
}
|
|
78
|
+
zoomTo(scale, at = { x: 0, y: 0 }) {
|
|
79
|
+
const next = clampScale(scale, this.options.max());
|
|
80
|
+
this.set(next, zoomAt(at, this.scale, next, this.pan));
|
|
81
|
+
}
|
|
82
|
+
reset() {
|
|
83
|
+
if (this.scale !== 1 || this.pan.x !== 0 || this.pan.y !== 0) {
|
|
84
|
+
this.set(1, { x: 0, y: 0 });
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
set(scale, pan) {
|
|
88
|
+
const box = this.options.surface()?.getBoundingClientRect();
|
|
89
|
+
const held = clampPan(pan, scale, box?.width ?? 0, box?.height ?? 0);
|
|
90
|
+
if (scale === this.scale && held.x === this.pan.x && held.y === this.pan.y) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
this.scale = scale;
|
|
94
|
+
this.pan = held;
|
|
95
|
+
this.options.onChange(scale, held);
|
|
96
|
+
}
|
|
97
|
+
offset(event) {
|
|
98
|
+
const box = this.options.surface()?.getBoundingClientRect();
|
|
99
|
+
return {
|
|
100
|
+
x: event.clientX - (box ? box.left + box.width / 2 : 0),
|
|
101
|
+
y: event.clientY - (box ? box.top + box.height / 2 : 0),
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
inside(event) {
|
|
105
|
+
const surface = this.options.surface();
|
|
106
|
+
return surface !== null && surface !== undefined && event.composedPath().includes(surface);
|
|
107
|
+
}
|
|
108
|
+
begin() {
|
|
109
|
+
const [a, b] = [...this.pointers.values()];
|
|
110
|
+
if (!a) {
|
|
111
|
+
this.from = undefined;
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
this.from = {
|
|
115
|
+
at: b ? between(a, b) : a,
|
|
116
|
+
pan: { ...this.pan },
|
|
117
|
+
scale: this.scale,
|
|
118
|
+
spread: b ? spread(a, b) : 0,
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
release() {
|
|
122
|
+
window.removeEventListener('pointermove', this.handleMove);
|
|
123
|
+
window.removeEventListener('pointerup', this.handleUp);
|
|
124
|
+
window.removeEventListener('pointercancel', this.handleUp);
|
|
125
|
+
this.pointers.clear();
|
|
126
|
+
this.from = undefined;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/** A distance from the middle of the viewer, or a point measured from it, in pixels. */
|
|
2
|
+
export interface Offset {
|
|
3
|
+
x: number;
|
|
4
|
+
y: number;
|
|
5
|
+
}
|
|
6
|
+
/** A scale held between 1, the item at its own size, and `max`. */
|
|
7
|
+
export declare const clampScale: (scale: number, max: number) => number;
|
|
8
|
+
/**
|
|
9
|
+
* How far a zoomed item may move, kept so its edges never come inside the
|
|
10
|
+
* viewer's: at a scale of 2 in a box 400 wide, 200 either way.
|
|
11
|
+
*/
|
|
12
|
+
export declare const clampPan: (pan: Offset, scale: number, width: number, height: number) => Offset;
|
|
13
|
+
/**
|
|
14
|
+
* Where the item moves to as its scale goes from `from` to `to`, so the point
|
|
15
|
+
* under `at` stays under it. Both are measured from the middle of the viewer,
|
|
16
|
+
* which is where the item scales from.
|
|
17
|
+
*/
|
|
18
|
+
export declare const zoomAt: (at: Offset, from: number, to: number, pan: Offset) => Offset;
|
|
19
|
+
/** The distance between two fingers. */
|
|
20
|
+
export declare const spread: (a: Offset, b: Offset) => number;
|
|
21
|
+
/** The point halfway between two fingers. */
|
|
22
|
+
export declare const between: (a: Offset, b: Offset) => Offset;
|
|
23
|
+
/** A scale as a whole percent, which is how a reader hears it: 1.5 is 150. */
|
|
24
|
+
export declare const percentOf: (scale: number) => number;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { clamp } from '@fusion.dev/helix-core';
|
|
2
|
+
const held = (value, low, high) => clamp(value, low, high) || 0;
|
|
3
|
+
export const clampScale = (scale, max) => held(scale, 1, Math.max(max, 1));
|
|
4
|
+
export const clampPan = (pan, scale, width, height) => {
|
|
5
|
+
const x = ((scale - 1) * width) / 2;
|
|
6
|
+
const y = ((scale - 1) * height) / 2;
|
|
7
|
+
return { x: held(pan.x, -x, x), y: held(pan.y, -y, y) };
|
|
8
|
+
};
|
|
9
|
+
export const zoomAt = (at, from, to, pan) => ({
|
|
10
|
+
x: at.x - ((at.x - pan.x) * to) / from,
|
|
11
|
+
y: at.y - ((at.y - pan.y) * to) / from,
|
|
12
|
+
});
|
|
13
|
+
export const spread = (a, b) => Math.hypot(a.x - b.x, a.y - b.y);
|
|
14
|
+
export const between = (a, b) => ({
|
|
15
|
+
x: (a.x + b.x) / 2,
|
|
16
|
+
y: (a.y + b.y) / 2,
|
|
17
|
+
});
|
|
18
|
+
export const percentOf = (scale) => Math.round(scale * 100);
|
|
@@ -15,6 +15,10 @@ declare const HelixHeadlessLineChart_base: typeof HelixElement & (new (...args:
|
|
|
15
15
|
*
|
|
16
16
|
* Every series shares one scale, as in the bar chart.
|
|
17
17
|
*
|
|
18
|
+
* `dashed` names the series drawn as a dashed line, such as a forecast or a
|
|
19
|
+
* target beside the readings: `dashed="Forecast"`. Each takes a
|
|
20
|
+
* `line-dashed` part beside `line`.
|
|
21
|
+
*
|
|
18
22
|
* `area` fills each series down to the floor on its own, so the fills overlap.
|
|
19
23
|
* For a total made of parts, use `Area Chart`, which stacks the series so the
|
|
20
24
|
* top edge is the total and each band is a share.
|
|
@@ -47,8 +51,11 @@ declare const HelixHeadlessLineChart_base: typeof HelixElement & (new (...args:
|
|
|
47
51
|
* @csspart label - One reading's name.
|
|
48
52
|
* @csspart labels - The row of reading names.
|
|
49
53
|
* @csspart line - The line for one series.
|
|
54
|
+
* @csspart line-dashed - A `line` whose series `dashed` names. Set alongside `line`.
|
|
50
55
|
* @csspart live - The readout: a polite live region that says the reading the keys moved to. Hide it visually.
|
|
51
56
|
* @csspart mark - The invisible point the tooltip is anchored to.
|
|
57
|
+
* @csspart marker - The mark on one reading, under `markers`, and on a reading with a blank on either side. Placed with `inset-inline-start` and `inset-block-start`, and carries its series color as `--chart-series`.
|
|
58
|
+
* @csspart marker-lone - A `marker` on a reading with a blank on either side, which no line reaches. Set alongside `marker`.
|
|
52
59
|
* @csspart plot - The drawing, which takes focus to be read by key.
|
|
53
60
|
* @csspart summary - The chart's name and each series' latest reading, written as a sentence for screen readers. Hide it visually.
|
|
54
61
|
* @csspart svg - The drawing surface the lines and areas sit on.
|
|
@@ -110,6 +117,15 @@ export declare class HelixHeadlessLineChart extends HelixHeadlessLineChart_base
|
|
|
110
117
|
* here, which is what lets a line take the reading aid.
|
|
111
118
|
*/
|
|
112
119
|
curve?: Curve;
|
|
120
|
+
/**
|
|
121
|
+
* The series drawn as a dashed line, by their headings, separated by
|
|
122
|
+
* commas: `dashed="Forecast, Target"`.
|
|
123
|
+
*
|
|
124
|
+
* For a series that is not a reading, such as a forecast or a goal, drawn
|
|
125
|
+
* beside the ones that are. Each takes a `line-dashed` part beside `line`,
|
|
126
|
+
* which a stylesheet draws dashed. Absent, every line is solid.
|
|
127
|
+
*/
|
|
128
|
+
dashed: string;
|
|
113
129
|
/**
|
|
114
130
|
* Which rules are drawn across the plot, if any.
|
|
115
131
|
*
|
|
@@ -138,6 +154,15 @@ export declare class HelixHeadlessLineChart extends HelixHeadlessLineChart_base
|
|
|
138
154
|
protected get rulesValue(): boolean;
|
|
139
155
|
/** Whether each reading is ruled, which only two values ask for. */
|
|
140
156
|
protected get rulesCategory(): boolean;
|
|
157
|
+
/**
|
|
158
|
+
* Draws a mark on every reading, the `marker` part, so a reader sees where
|
|
159
|
+
* the readings are, as well as the line between them.
|
|
160
|
+
*
|
|
161
|
+
* Absent draws none, except on a reading with a blank on either side: it
|
|
162
|
+
* has no line to be part of, so it takes a mark, the `marker` part with
|
|
163
|
+
* `marker-lone` beside it, or it would not be drawn at all.
|
|
164
|
+
*/
|
|
165
|
+
markers: boolean;
|
|
141
166
|
/**
|
|
142
167
|
* The shape of the mark on each series' last reading.
|
|
143
168
|
*
|
|
@@ -200,7 +225,8 @@ export declare class HelixHeadlessLineChart extends HelixHeadlessLineChart_base
|
|
|
200
225
|
* The latest, because where a series ended is the question a line over time
|
|
201
226
|
* is asked first, which is what `AreaChart` gives too. Each series' own last
|
|
202
227
|
* reading, so a series with a blank in the last row still says where it was.
|
|
203
|
-
* Written the way the table writes it, such as `$128k` for `128000`.
|
|
228
|
+
* Written the way the table writes it, such as `$128k` for `128000`. A
|
|
229
|
+
* series a legend hid is not drawn and is not said.
|
|
204
230
|
*/
|
|
205
231
|
protected renderSummary(series: Series[]): TemplateResult;
|
|
206
232
|
/**
|
|
@@ -255,6 +281,17 @@ export declare class HelixHeadlessLineChart extends HelixHeadlessLineChart_base
|
|
|
255
281
|
x: number;
|
|
256
282
|
y: number;
|
|
257
283
|
}>): TemplateResult | typeof nothing;
|
|
284
|
+
/**
|
|
285
|
+
* The marks on the readings: every one under `markers`, and otherwise only
|
|
286
|
+
* a reading no line reaches, which has a blank on either side.
|
|
287
|
+
*
|
|
288
|
+
* Elements beside the drawing, as the termini are, so a mark is round in a
|
|
289
|
+
* drawing `preserveAspectRatio="none"` stretches. Placed from the inline
|
|
290
|
+
* start, as the drawing is mirrored.
|
|
291
|
+
*/
|
|
292
|
+
protected renderMarkers(series: Series[], x: (value: number) => number, y: (value: number) => number): TemplateResult | typeof nothing;
|
|
293
|
+
/** Whether `dashed` names this series, matched as a heading is. */
|
|
294
|
+
private dashes;
|
|
258
295
|
/**
|
|
259
296
|
* One series, its wash first so the line is drawn over its own fill.
|
|
260
297
|
*
|