@fusion.dev/helix-headless 0.0.0-dev
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/custom-elements.json +75202 -0
- package/dist/accordion/index.d.ts +2 -0
- package/dist/accordion/index.js +2 -0
- package/dist/accordion/item/accordion-item.d.ts +141 -0
- package/dist/accordion/item/accordion-item.js +214 -0
- package/dist/accordion/root/accordion-root.d.ts +57 -0
- package/dist/accordion/root/accordion-root.js +96 -0
- package/dist/announcement/index.d.ts +1 -0
- package/dist/announcement/index.js +1 -0
- package/dist/announcement/root/announcement-root.d.ts +106 -0
- package/dist/announcement/root/announcement-root.js +144 -0
- package/dist/app-header/index.d.ts +1 -0
- package/dist/app-header/index.js +1 -0
- package/dist/app-header/root/app-header-root.d.ts +113 -0
- package/dist/app-header/root/app-header-root.js +147 -0
- package/dist/avatar/group/avatar-group.d.ts +116 -0
- package/dist/avatar/group/avatar-group.js +136 -0
- package/dist/avatar/index.d.ts +2 -0
- package/dist/avatar/index.js +2 -0
- package/dist/avatar/root/avatar-root.d.ts +71 -0
- package/dist/avatar/root/avatar-root.js +147 -0
- package/dist/badge/index.d.ts +1 -0
- package/dist/badge/index.js +1 -0
- package/dist/badge/root/badge-root.d.ts +61 -0
- package/dist/badge/root/badge-root.js +121 -0
- package/dist/bar-chart/index.d.ts +1 -0
- package/dist/bar-chart/index.js +1 -0
- package/dist/bar-chart/root/bar-chart-root.d.ts +266 -0
- package/dist/bar-chart/root/bar-chart-root.js +515 -0
- package/dist/blockquote/index.d.ts +1 -0
- package/dist/blockquote/index.js +1 -0
- package/dist/blockquote/root/blockquote-root.d.ts +51 -0
- package/dist/blockquote/root/blockquote-root.js +84 -0
- package/dist/breadcrumbs/breadcrumb/breadcrumb.d.ts +104 -0
- package/dist/breadcrumbs/breadcrumb/breadcrumb.js +137 -0
- package/dist/breadcrumbs/index.d.ts +2 -0
- package/dist/breadcrumbs/index.js +2 -0
- package/dist/breadcrumbs/root/breadcrumbs-root.d.ts +77 -0
- package/dist/breadcrumbs/root/breadcrumbs-root.js +94 -0
- package/dist/button/index.d.ts +1 -0
- package/dist/button/index.js +1 -0
- package/dist/button/root/button-root.d.ts +251 -0
- package/dist/button/root/button-root.js +401 -0
- package/dist/button-group/index.d.ts +1 -0
- package/dist/button-group/index.js +1 -0
- package/dist/button-group/root/button-group-root.d.ts +62 -0
- package/dist/button-group/root/button-group-root.js +62 -0
- package/dist/callout/index.d.ts +1 -0
- package/dist/callout/index.js +1 -0
- package/dist/callout/root/callout-root.d.ts +72 -0
- package/dist/callout/root/callout-root.js +90 -0
- package/dist/card/index.d.ts +1 -0
- package/dist/card/index.js +1 -0
- package/dist/card/root/card-root.d.ts +54 -0
- package/dist/card/root/card-root.js +71 -0
- package/dist/carousel/index.d.ts +1 -0
- package/dist/carousel/index.js +1 -0
- package/dist/carousel/root/carousel-root.d.ts +399 -0
- package/dist/carousel/root/carousel-root.js +723 -0
- package/dist/chat/composer/chat-composer.d.ts +160 -0
- package/dist/chat/composer/chat-composer.js +273 -0
- package/dist/chat/index.d.ts +3 -0
- package/dist/chat/index.js +3 -0
- package/dist/chat/message/chat-message.d.ts +170 -0
- package/dist/chat/message/chat-message.js +271 -0
- package/dist/chat/root/chat-root.d.ts +216 -0
- package/dist/chat/root/chat-root.js +389 -0
- package/dist/checkbox/index.d.ts +1 -0
- package/dist/checkbox/index.js +1 -0
- package/dist/checkbox/root/checkbox-root.d.ts +108 -0
- package/dist/checkbox/root/checkbox-root.js +207 -0
- package/dist/checkbox-group/index.d.ts +1 -0
- package/dist/checkbox-group/index.js +1 -0
- package/dist/checkbox-group/root/checkbox-group-root.d.ts +155 -0
- package/dist/checkbox-group/root/checkbox-group-root.js +293 -0
- package/dist/code/index.d.ts +1 -0
- package/dist/code/index.js +1 -0
- package/dist/code/root/code-root.d.ts +36 -0
- package/dist/code/root/code-root.js +43 -0
- package/dist/code-block/index.d.ts +1 -0
- package/dist/code-block/index.js +1 -0
- package/dist/code-block/root/code-block-root.d.ts +112 -0
- package/dist/code-block/root/code-block-root.js +155 -0
- package/dist/color-input/index.d.ts +1 -0
- package/dist/color-input/index.js +1 -0
- package/dist/color-input/root/color-input-root.d.ts +227 -0
- package/dist/color-input/root/color-input-root.js +456 -0
- package/dist/color-picker/color.d.ts +74 -0
- package/dist/color-picker/color.js +238 -0
- package/dist/color-picker/index.d.ts +2 -0
- package/dist/color-picker/index.js +2 -0
- package/dist/color-picker/root/color-picker-root.d.ts +303 -0
- package/dist/color-picker/root/color-picker-root.js +576 -0
- package/dist/combobox/index.d.ts +1 -0
- package/dist/combobox/index.js +1 -0
- package/dist/combobox/root/combobox-root.d.ts +396 -0
- package/dist/combobox/root/combobox-root.js +808 -0
- package/dist/command/index.d.ts +1 -0
- package/dist/command/index.js +1 -0
- package/dist/command/root/command-root.d.ts +166 -0
- package/dist/command/root/command-root.js +353 -0
- package/dist/copy-button/index.d.ts +1 -0
- package/dist/copy-button/index.js +1 -0
- package/dist/copy-button/root/copy-button-root.d.ts +154 -0
- package/dist/copy-button/root/copy-button-root.js +225 -0
- package/dist/data-table/index.d.ts +2 -0
- package/dist/data-table/index.js +2 -0
- package/dist/data-table/root/data-table-root.d.ts +392 -0
- package/dist/data-table/root/data-table-root.js +729 -0
- package/dist/data-table/root/order.d.ts +116 -0
- package/dist/data-table/root/order.js +175 -0
- package/dist/date-input/index.d.ts +1 -0
- package/dist/date-input/index.js +1 -0
- package/dist/date-input/root/date-input-root.d.ts +361 -0
- package/dist/date-input/root/date-input-root.js +791 -0
- package/dist/date-picker/index.d.ts +1 -0
- package/dist/date-picker/index.js +1 -0
- package/dist/date-picker/root/date-picker-root.d.ts +361 -0
- package/dist/date-picker/root/date-picker-root.js +837 -0
- package/dist/dialog/index.d.ts +1 -0
- package/dist/dialog/index.js +1 -0
- package/dist/dialog/root/dialog-root.d.ts +185 -0
- package/dist/dialog/root/dialog-root.js +319 -0
- package/dist/divider/index.d.ts +1 -0
- package/dist/divider/index.js +1 -0
- package/dist/divider/root/divider-root.d.ts +68 -0
- package/dist/divider/root/divider-root.js +116 -0
- package/dist/donut-chart/index.d.ts +1 -0
- package/dist/donut-chart/index.js +1 -0
- package/dist/donut-chart/root/donut-chart-root.d.ts +209 -0
- package/dist/donut-chart/root/donut-chart-root.js +395 -0
- package/dist/drawer/index.d.ts +1 -0
- package/dist/drawer/index.js +1 -0
- package/dist/drawer/root/drawer-root.d.ts +144 -0
- package/dist/drawer/root/drawer-root.js +222 -0
- package/dist/drilldown/index.d.ts +2 -0
- package/dist/drilldown/index.js +2 -0
- package/dist/drilldown/item/drilldown-item.d.ts +87 -0
- package/dist/drilldown/item/drilldown-item.js +152 -0
- package/dist/drilldown/root/drilldown-root.d.ts +115 -0
- package/dist/drilldown/root/drilldown-root.js +263 -0
- package/dist/element-events.generated.d.ts +1 -0
- package/dist/element-events.generated.js +125 -0
- package/dist/empty/index.d.ts +1 -0
- package/dist/empty/index.js +1 -0
- package/dist/empty/root/empty-root.d.ts +47 -0
- package/dist/empty/root/empty-root.js +68 -0
- package/dist/file-input/index.d.ts +1 -0
- package/dist/file-input/index.js +1 -0
- package/dist/file-input/root/file-input-root.d.ts +196 -0
- package/dist/file-input/root/file-input-root.js +488 -0
- package/dist/format-date/index.d.ts +1 -0
- package/dist/format-date/index.js +1 -0
- package/dist/format-date/root/format-date-root.d.ts +151 -0
- package/dist/format-date/root/format-date-root.js +266 -0
- package/dist/heatmap/index.d.ts +2 -0
- package/dist/heatmap/index.js +2 -0
- package/dist/heatmap/root/buckets.d.ts +62 -0
- package/dist/heatmap/root/buckets.js +85 -0
- package/dist/heatmap/root/heatmap-root.d.ts +330 -0
- package/dist/heatmap/root/heatmap-root.js +526 -0
- package/dist/icon/index.d.ts +1 -0
- package/dist/icon/index.js +1 -0
- package/dist/icon/root/icon-root.d.ts +53 -0
- package/dist/icon/root/icon-root.js +93 -0
- package/dist/icon-button/index.d.ts +1 -0
- package/dist/icon-button/index.js +1 -0
- package/dist/icon-button/root/icon-button-root.d.ts +40 -0
- package/dist/icon-button/root/icon-button-root.js +46 -0
- package/dist/image/index.d.ts +1 -0
- package/dist/image/index.js +1 -0
- package/dist/image/root/image-root.d.ts +213 -0
- package/dist/image/root/image-root.js +335 -0
- package/dist/index.d.ts +99 -0
- package/dist/index.js +99 -0
- package/dist/input/index.d.ts +1 -0
- package/dist/input/index.js +1 -0
- package/dist/input/root/input-root.d.ts +281 -0
- package/dist/input/root/input-root.js +472 -0
- package/dist/kbd/index.d.ts +1 -0
- package/dist/kbd/index.js +1 -0
- package/dist/kbd/root/kbd-root.d.ts +98 -0
- package/dist/kbd/root/kbd-root.js +230 -0
- package/dist/legend/index.d.ts +1 -0
- package/dist/legend/index.js +1 -0
- package/dist/legend/root/legend-root.d.ts +83 -0
- package/dist/legend/root/legend-root.js +125 -0
- package/dist/line-chart/index.d.ts +1 -0
- package/dist/line-chart/index.js +1 -0
- package/dist/line-chart/root/line-chart-root.d.ts +238 -0
- package/dist/line-chart/root/line-chart-root.js +365 -0
- package/dist/list/index.d.ts +2 -0
- package/dist/list/index.js +2 -0
- package/dist/list/item/list-item.d.ts +95 -0
- package/dist/list/item/list-item.js +148 -0
- package/dist/list/root/list-root.d.ts +72 -0
- package/dist/list/root/list-root.js +61 -0
- package/dist/listbox/index.d.ts +1 -0
- package/dist/listbox/index.js +1 -0
- package/dist/listbox/root/listbox-root.d.ts +357 -0
- package/dist/listbox/root/listbox-root.js +890 -0
- package/dist/loader/index.d.ts +1 -0
- package/dist/loader/index.js +1 -0
- package/dist/loader/root/loader-root.d.ts +52 -0
- package/dist/loader/root/loader-root.js +74 -0
- package/dist/megamenu/index.d.ts +1 -0
- package/dist/megamenu/index.js +1 -0
- package/dist/megamenu/root/megamenu-root.d.ts +254 -0
- package/dist/megamenu/root/megamenu-root.js +526 -0
- package/dist/menu/index.d.ts +2 -0
- package/dist/menu/index.js +2 -0
- package/dist/menu/item/menu-item.d.ts +231 -0
- package/dist/menu/item/menu-item.js +405 -0
- package/dist/menu/root/menu-root.d.ts +158 -0
- package/dist/menu/root/menu-root.js +422 -0
- package/dist/meter/index.d.ts +1 -0
- package/dist/meter/index.js +1 -0
- package/dist/meter/root/meter-root.d.ts +234 -0
- package/dist/meter/root/meter-root.js +316 -0
- package/dist/navigation/index.d.ts +1 -0
- package/dist/navigation/index.js +1 -0
- package/dist/navigation/root/navigation-root.d.ts +55 -0
- package/dist/navigation/root/navigation-root.js +130 -0
- package/dist/notifications/index.d.ts +2 -0
- package/dist/notifications/index.js +2 -0
- package/dist/notifications/notification/notification.d.ts +181 -0
- package/dist/notifications/notification/notification.js +305 -0
- package/dist/notifications/root/notifications-root.d.ts +168 -0
- package/dist/notifications/root/notifications-root.js +291 -0
- package/dist/number-input/index.d.ts +1 -0
- package/dist/number-input/index.js +1 -0
- package/dist/number-input/root/number-input-root.d.ts +282 -0
- package/dist/number-input/root/number-input-root.js +592 -0
- package/dist/option/group/option-group.d.ts +38 -0
- package/dist/option/group/option-group.js +58 -0
- package/dist/option/index.d.ts +2 -0
- package/dist/option/index.js +2 -0
- package/dist/option/root/option-root.d.ts +194 -0
- package/dist/option/root/option-root.js +247 -0
- package/dist/outline/index.d.ts +1 -0
- package/dist/outline/index.js +1 -0
- package/dist/outline/root/outline-root.d.ts +237 -0
- package/dist/outline/root/outline-root.js +519 -0
- package/dist/pagination/index.d.ts +3 -0
- package/dist/pagination/index.js +3 -0
- package/dist/pagination/root/pagination-root.d.ts +390 -0
- package/dist/pagination/root/pagination-root.js +695 -0
- package/dist/pagination/size/pagination-size.d.ts +127 -0
- package/dist/pagination/size/pagination-size.js +232 -0
- package/dist/pagination/summary/pagination-summary.d.ts +90 -0
- package/dist/pagination/summary/pagination-summary.js +145 -0
- package/dist/pin-input/index.d.ts +1 -0
- package/dist/pin-input/index.js +1 -0
- package/dist/pin-input/root/pin-input-root.d.ts +292 -0
- package/dist/pin-input/root/pin-input-root.js +553 -0
- package/dist/popover/index.d.ts +1 -0
- package/dist/popover/index.js +1 -0
- package/dist/popover/root/popover-root.d.ts +108 -0
- package/dist/popover/root/popover-root.js +231 -0
- package/dist/progress/index.d.ts +1 -0
- package/dist/progress/index.js +1 -0
- package/dist/progress/root/progress-root.d.ts +125 -0
- package/dist/progress/root/progress-root.js +212 -0
- package/dist/qr-code/index.d.ts +1 -0
- package/dist/qr-code/index.js +1 -0
- package/dist/qr-code/root/qr-code-root.d.ts +93 -0
- package/dist/qr-code/root/qr-code-root.js +233 -0
- package/dist/quote/index.d.ts +1 -0
- package/dist/quote/index.js +1 -0
- package/dist/quote/root/quote-root.d.ts +36 -0
- package/dist/quote/root/quote-root.js +50 -0
- package/dist/radio/group/radio-group.d.ts +84 -0
- package/dist/radio/group/radio-group.js +170 -0
- package/dist/radio/index.d.ts +2 -0
- package/dist/radio/index.js +2 -0
- package/dist/radio/root/radio-root.d.ts +102 -0
- package/dist/radio/root/radio-root.js +151 -0
- package/dist/rating/index.d.ts +1 -0
- package/dist/rating/index.js +1 -0
- package/dist/rating/root/rating-root.d.ts +242 -0
- package/dist/rating/root/rating-root.js +484 -0
- package/dist/scroll-area/index.d.ts +1 -0
- package/dist/scroll-area/index.js +1 -0
- package/dist/scroll-area/root/scroll-area-root.d.ts +96 -0
- package/dist/scroll-area/root/scroll-area-root.js +215 -0
- package/dist/select/index.d.ts +1 -0
- package/dist/select/index.js +1 -0
- package/dist/select/root/select-root.d.ts +170 -0
- package/dist/select/root/select-root.js +419 -0
- package/dist/skeleton/index.d.ts +1 -0
- package/dist/skeleton/index.js +1 -0
- package/dist/skeleton/root/skeleton-root.d.ts +31 -0
- package/dist/skeleton/root/skeleton-root.js +42 -0
- package/dist/slider/index.d.ts +1 -0
- package/dist/slider/index.js +1 -0
- package/dist/slider/root/slider-root.d.ts +235 -0
- package/dist/slider/root/slider-root.js +488 -0
- package/dist/sparkline/index.d.ts +1 -0
- package/dist/sparkline/index.js +1 -0
- package/dist/sparkline/root/sparkline-root.d.ts +147 -0
- package/dist/sparkline/root/sparkline-root.js +278 -0
- package/dist/speed-dial/index.d.ts +2 -0
- package/dist/speed-dial/index.js +2 -0
- package/dist/speed-dial/item/speed-dial-item.d.ts +71 -0
- package/dist/speed-dial/item/speed-dial-item.js +113 -0
- package/dist/speed-dial/root/speed-dial-root.d.ts +122 -0
- package/dist/speed-dial/root/speed-dial-root.js +251 -0
- package/dist/splitter/index.d.ts +1 -0
- package/dist/splitter/index.js +1 -0
- package/dist/splitter/root/splitter-root.d.ts +491 -0
- package/dist/splitter/root/splitter-root.js +1030 -0
- package/dist/stat/group/stat-group.d.ts +30 -0
- package/dist/stat/group/stat-group.js +47 -0
- package/dist/stat/index.d.ts +2 -0
- package/dist/stat/index.js +2 -0
- package/dist/stat/root/stat-root.d.ts +62 -0
- package/dist/stat/root/stat-root.js +51 -0
- package/dist/steps/index.d.ts +2 -0
- package/dist/steps/index.js +2 -0
- package/dist/steps/root/steps-root.d.ts +110 -0
- package/dist/steps/root/steps-root.js +130 -0
- package/dist/steps/step/step.d.ts +139 -0
- package/dist/steps/step/step.js +215 -0
- package/dist/switch/index.d.ts +1 -0
- package/dist/switch/index.js +1 -0
- package/dist/switch/root/switch-root.d.ts +74 -0
- package/dist/switch/root/switch-root.js +153 -0
- package/dist/table/cell/table-cell.d.ts +34 -0
- package/dist/table/cell/table-cell.js +52 -0
- package/dist/table/column/table-column.d.ts +165 -0
- package/dist/table/column/table-column.js +222 -0
- package/dist/table/index.d.ts +4 -0
- package/dist/table/index.js +4 -0
- package/dist/table/root/table-root.d.ts +98 -0
- package/dist/table/root/table-root.js +161 -0
- package/dist/table/row/table-row.d.ts +27 -0
- package/dist/table/row/table-row.js +42 -0
- package/dist/tabs/index.d.ts +3 -0
- package/dist/tabs/index.js +3 -0
- package/dist/tabs/panel/tab-panel.d.ts +67 -0
- package/dist/tabs/panel/tab-panel.js +98 -0
- package/dist/tabs/root/tabs-root.d.ts +123 -0
- package/dist/tabs/root/tabs-root.js +217 -0
- package/dist/tabs/tab/tab.d.ts +64 -0
- package/dist/tabs/tab/tab.js +116 -0
- package/dist/tag/index.d.ts +1 -0
- package/dist/tag/index.js +1 -0
- package/dist/tag/root/tag-root.d.ts +41 -0
- package/dist/tag/root/tag-root.js +67 -0
- package/dist/textarea/index.d.ts +1 -0
- package/dist/textarea/index.js +1 -0
- package/dist/textarea/root/textarea-root.d.ts +215 -0
- package/dist/textarea/root/textarea-root.js +380 -0
- package/dist/time-input/index.d.ts +1 -0
- package/dist/time-input/index.js +1 -0
- package/dist/time-input/root/time-input-root.d.ts +322 -0
- package/dist/time-input/root/time-input-root.js +661 -0
- package/dist/time-picker/index.d.ts +1 -0
- package/dist/time-picker/index.js +1 -0
- package/dist/time-picker/root/time-picker-root.d.ts +380 -0
- package/dist/time-picker/root/time-picker-root.js +669 -0
- package/dist/timeline/index.d.ts +2 -0
- package/dist/timeline/index.js +2 -0
- package/dist/timeline/item/timeline-item.d.ts +81 -0
- package/dist/timeline/item/timeline-item.js +128 -0
- package/dist/timeline/root/timeline-root.d.ts +52 -0
- package/dist/timeline/root/timeline-root.js +72 -0
- package/dist/toast/index.d.ts +2 -0
- package/dist/toast/index.js +2 -0
- package/dist/toast/item/toast-item.d.ts +183 -0
- package/dist/toast/item/toast-item.js +345 -0
- package/dist/toast/root/toast-root.d.ts +72 -0
- package/dist/toast/root/toast-root.js +87 -0
- package/dist/toggle/group/toggle-group.d.ts +140 -0
- package/dist/toggle/group/toggle-group.js +278 -0
- package/dist/toggle/index.d.ts +2 -0
- package/dist/toggle/index.js +2 -0
- package/dist/toggle/root/toggle-root.d.ts +99 -0
- package/dist/toggle/root/toggle-root.js +146 -0
- package/dist/toolbar/index.d.ts +1 -0
- package/dist/toolbar/index.js +1 -0
- package/dist/toolbar/root/toolbar-root.d.ts +105 -0
- package/dist/toolbar/root/toolbar-root.js +260 -0
- package/dist/tooltip/index.d.ts +1 -0
- package/dist/tooltip/index.js +1 -0
- package/dist/tooltip/root/tooltip-root.d.ts +388 -0
- package/dist/tooltip/root/tooltip-root.js +707 -0
- package/dist/tour/index.d.ts +2 -0
- package/dist/tour/index.js +2 -0
- package/dist/tour/root/tour-root.d.ts +161 -0
- package/dist/tour/root/tour-root.js +351 -0
- package/dist/tour/stop/tour-stop.d.ts +131 -0
- package/dist/tour/stop/tour-stop.js +249 -0
- package/dist/tree/index.d.ts +2 -0
- package/dist/tree/index.js +2 -0
- package/dist/tree/item/tree-item.d.ts +208 -0
- package/dist/tree/item/tree-item.js +381 -0
- package/dist/tree/root/tree-root.d.ts +88 -0
- package/dist/tree/root/tree-root.js +287 -0
- package/dist/trend/index.d.ts +1 -0
- package/dist/trend/index.js +1 -0
- package/dist/trend/root/trend-root.d.ts +67 -0
- package/dist/trend/root/trend-root.js +106 -0
- package/dist/video/index.d.ts +1 -0
- package/dist/video/index.js +1 -0
- package/dist/video/root/video-root.d.ts +711 -0
- package/dist/video/root/video-root.js +1821 -0
- package/dist/video-playlist/index.d.ts +3 -0
- package/dist/video-playlist/index.js +3 -0
- package/dist/video-playlist/item/video-playlist-item.d.ts +101 -0
- package/dist/video-playlist/item/video-playlist-item.js +162 -0
- package/dist/video-playlist/menu/video-playlist-menu.d.ts +121 -0
- package/dist/video-playlist/menu/video-playlist-menu.js +237 -0
- package/dist/video-playlist/root/video-playlist-root.d.ts +108 -0
- package/dist/video-playlist/root/video-playlist-root.js +218 -0
- package/dist/virtual-list/index.d.ts +1 -0
- package/dist/virtual-list/index.js +1 -0
- package/dist/virtual-list/root/virtual-list-root.d.ts +121 -0
- package/dist/virtual-list/root/virtual-list-root.js +221 -0
- package/jsx.d.ts +49767 -0
- package/package.json +77 -0
- package/svelte.d.ts +129 -0
- package/vue.d.ts +9242 -0
|
@@ -0,0 +1,1030 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
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
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var HelixHeadlessSplitter_1;
|
|
8
|
+
import { capturePointer, closestInstance, customElement, HelixBeforeCollapseEvent, HelixBeforeResizeEvent, HelixElement, requestChange, } from '@fusion.dev/helix-core';
|
|
9
|
+
import { html } from 'lit';
|
|
10
|
+
import { property, state } from 'lit/decorators.js';
|
|
11
|
+
/**
|
|
12
|
+
* The inline size under which `orientation="auto"` stacks, in pixels.
|
|
13
|
+
*
|
|
14
|
+
* 32rem at the default root size. Two panes side by side under this have about
|
|
15
|
+
* 240px each before the divider, which is narrower than the content anybody
|
|
16
|
+
* puts in one: the sandbox at 390 gave its source pane 237px and cut every line
|
|
17
|
+
* mid-token, which is the measurement this number comes from.
|
|
18
|
+
*
|
|
19
|
+
* A constant and not a property, until something wants a different one. The
|
|
20
|
+
* axis is the decision worth exposing; where it turns is a detail of this
|
|
21
|
+
* component doing what it was asked.
|
|
22
|
+
*/
|
|
23
|
+
const STACK_BELOW = 512;
|
|
24
|
+
/**
|
|
25
|
+
* @summary Two panes and a divider the reader can move.
|
|
26
|
+
*
|
|
27
|
+
* @description
|
|
28
|
+
* **One axis, and nesting is how you get two.** The sandbox this was taken from
|
|
29
|
+
* moves a cross: a divider down the middle, another across the bottom, and a
|
|
30
|
+
* corner that moves both. That is a layout rather than a component, and every
|
|
31
|
+
* part of it that is worth sharing is one divider between two panes. A splitter
|
|
32
|
+
* inside a splitter gives the cross back, and gives the three-pane and the
|
|
33
|
+
* four-pane arrangements it never had.
|
|
34
|
+
*
|
|
35
|
+
* **Where two of them cross there is a corner, and it moves both.** A splitter
|
|
36
|
+
* slotted into a pane of another, at right angles to it, has one end of its
|
|
37
|
+
* divider sitting exactly on the other's. That end grows a handle: `move` under
|
|
38
|
+
* the pointer, both arrow axes on the keyboard, and a drag that carries the two
|
|
39
|
+
* positions at once.
|
|
40
|
+
*
|
|
41
|
+
* **The outer splitter draws it and the nested one announces itself upward.**
|
|
42
|
+
* Built the other way round first, because a splitter already knows where its
|
|
43
|
+
* own divider begins and needs no measurement of the other, and that version was
|
|
44
|
+
* clipped: the crossing lies on the boundary between a pane and the divider
|
|
45
|
+
* beside it, a handle centered there reaches back over the boundary, and a pane
|
|
46
|
+
* is `overflow: auto`. Exactly half the corner was cut off. The outer separator
|
|
47
|
+
* is the one element that already straddles the seam, so the corner belongs in
|
|
48
|
+
* it.
|
|
49
|
+
*
|
|
50
|
+
* That makes the channel between the two a single call in a single direction:
|
|
51
|
+
* `cross(child, at)` says where the child crosses, `moveTo` drives either one,
|
|
52
|
+
* and neither reads the other's state. The child is what calls it, because a
|
|
53
|
+
* parent cannot poll for a child that has not upgraded yet.
|
|
54
|
+
*
|
|
55
|
+
* The one number it carries is a percentage rather than a measurement, which is
|
|
56
|
+
* what keeps either of them from measuring the other, and it assumes the nested
|
|
57
|
+
* splitter fills its pane. That is what slotting one into a pane does. Give the
|
|
58
|
+
* nested splitter its own inset, or wrap it in something smaller than the pane,
|
|
59
|
+
* and the corner is drawn where the crossing would be rather than where it is.
|
|
60
|
+
*
|
|
61
|
+
* **It is a client-side enhancement and says so.** Finding the parent means
|
|
62
|
+
* inspecting the tree, which a server cannot do, so the corner appears at
|
|
63
|
+
* `firstUpdated` and never in the served markup. That is allowed for exactly
|
|
64
|
+
* this: it is an affordance rather than content, and a splitter with no corner
|
|
65
|
+
* yet is a splitter with two working dividers.
|
|
66
|
+
*
|
|
67
|
+
* Where two dividers are parallel there is no corner, because there is nothing
|
|
68
|
+
* to take hold of. Where they cross without a corner, the inner divider takes
|
|
69
|
+
* the pointer: every separator sits on the same layer, so a tie goes to document
|
|
70
|
+
* order and a deeper splitter is always later.
|
|
71
|
+
*
|
|
72
|
+
* **A divider that is moving says so, whoever is moving it.** `:hover` cannot
|
|
73
|
+
* carry that: a drag holds the pointer through capture and a fast one leaves the
|
|
74
|
+
* target behind, and a corner moves the nested divider while the reader is on
|
|
75
|
+
* the crossing, nowhere near it. So a drag in progress is a state, and both
|
|
76
|
+
* dividers a corner moves are lit for as long as it moves them.
|
|
77
|
+
*
|
|
78
|
+
* **The divider is a real `role="separator"` with `aria-valuenow`, moved by the
|
|
79
|
+
* arrow keys as well as by pointer.** A divider only a mouse can move is
|
|
80
|
+
* unusable without one, which is the reason the sandbox's carries the same, and
|
|
81
|
+
* `Home` and `End` take it to its bounds.
|
|
82
|
+
*
|
|
83
|
+
* **It goes where it is put, all the way to either end.** `min` and `max` are
|
|
84
|
+
* nothing and everything unless a consumer says otherwise, because a divider
|
|
85
|
+
* that stops dead short of the edge gives a reader no way to put a pane away.
|
|
86
|
+
* Where a pane should keep a sliver of itself, only whoever put the tabs on it
|
|
87
|
+
* knows how much, so they say so.
|
|
88
|
+
*
|
|
89
|
+
* **A pane can be shut, and that is not the same as a divider at the edge.**
|
|
90
|
+
* The geometry is identical and the knowledge is not: only a shut pane knows
|
|
91
|
+
* where to open back to. So `collapsed` is a second state rather than a reading
|
|
92
|
+
* of the position, and the position it opens to is simply the one collapsing
|
|
93
|
+
* never overwrote. `collapsed-size` keeps a sliver showing where a pane has a
|
|
94
|
+
* tab strip worth leaving, and collapse overrides `min` and `max`, which is
|
|
95
|
+
* what those are for: they keep a pane from vanishing by accident, and this is
|
|
96
|
+
* the deliberate version.
|
|
97
|
+
*
|
|
98
|
+
* The two are kept in step in one direction only: a drag that settles on the
|
|
99
|
+
* collapsed size latches shut, and any move opens it again. Otherwise a reader
|
|
100
|
+
* could drag a pane closed and the consumer's own button would still be
|
|
101
|
+
* offering to close it.
|
|
102
|
+
*
|
|
103
|
+
* A pane shut to nothing is told apart from one shut to a sliver, because the
|
|
104
|
+
* two want different dividers: a sliver still has a boundary worth drawing, and
|
|
105
|
+
* nothing leaves the divider sitting on the container's own edge.
|
|
106
|
+
*
|
|
107
|
+
* **The box is measured once, when a drag starts.** Measuring per move is a
|
|
108
|
+
* forced layout on every pointer event, in the middle of a gesture whose whole
|
|
109
|
+
* job is to stay ahead of the pointer, and nothing about the box moves while the
|
|
110
|
+
* divider does.
|
|
111
|
+
*
|
|
112
|
+
* **`helix-before-resize` fires when it settles, not while it moves.** A drag is a
|
|
113
|
+
* stream of positions and only the one it ends at is a preference; announcing
|
|
114
|
+
* each would ask a consumer to write to storage a hundred times to record one
|
|
115
|
+
* decision. Nothing is stored here either: where a preference lives, and whether
|
|
116
|
+
* it should be kept at all, is the consumer's to decide, and a component writing
|
|
117
|
+
* to storage on its own would be deciding for all of them under a key it chose.
|
|
118
|
+
*
|
|
119
|
+
* The properties below are written by this component and read by whoever draws
|
|
120
|
+
* it. A consumer sets none of them: they carry a number this element computed
|
|
121
|
+
* and CSS cannot, which is what lets a stylesheet on this tier draw the thing
|
|
122
|
+
* without measuring anything itself.
|
|
123
|
+
*
|
|
124
|
+
* @since 0.1.0
|
|
125
|
+
* @status experimental
|
|
126
|
+
* @category layout
|
|
127
|
+
* @aliases SplitPane, Resizable, SplitView
|
|
128
|
+
* @documentation https://helix.fusion.dev/components/splitter
|
|
129
|
+
*
|
|
130
|
+
* @slot end - The pane after it.
|
|
131
|
+
* @slot start - The pane before the divider.
|
|
132
|
+
*
|
|
133
|
+
* @event {HelixBeforeCollapseEvent} helix-before-collapse - Fired before a pane shuts or reopens, and cancelable.
|
|
134
|
+
* @event {HelixBeforeResizeEvent} helix-before-resize - Fired before the divider settles, and cancelable.
|
|
135
|
+
*
|
|
136
|
+
* @csspart corner - The handle where two dividers cross, added on the client.
|
|
137
|
+
* @csspart end - The box holding the second.
|
|
138
|
+
* @csspart separator - The divider itself.
|
|
139
|
+
* @csspart start - The box holding the first pane.
|
|
140
|
+
*
|
|
141
|
+
* @cssproperty --splitter-corner-at - Where a nested splitter crosses this one, as a percentage.
|
|
142
|
+
* @cssproperty --splitter-position - Where the divider sits, as a percentage of the box.
|
|
143
|
+
*/
|
|
144
|
+
let HelixHeadlessSplitter = HelixHeadlessSplitter_1 = class HelixHeadlessSplitter extends HelixElement {
|
|
145
|
+
constructor() {
|
|
146
|
+
super(...arguments);
|
|
147
|
+
/**
|
|
148
|
+
* Where the divider starts, where nothing declared it.
|
|
149
|
+
*/
|
|
150
|
+
this.defaultPosition = 50;
|
|
151
|
+
/**
|
|
152
|
+
* How much of a shut pane is still shown, as a percentage.
|
|
153
|
+
*
|
|
154
|
+
* Zero by default, which is a pane fully gone. A tab strip or a title bar
|
|
155
|
+
* that should survive its own collapse says how much of itself to keep, and
|
|
156
|
+
* only whoever put it there knows that, which is the same reason `min` is a
|
|
157
|
+
* consumer's to set.
|
|
158
|
+
*/
|
|
159
|
+
this.collapsedSize = 0;
|
|
160
|
+
/**
|
|
161
|
+
* Nearest the divider may come to the start.
|
|
162
|
+
*
|
|
163
|
+
* A bare number is a percentage, which is what this always took. A CSS length
|
|
164
|
+
* is resolved against the splitter's own box along its axis, so `min="15rem"`
|
|
165
|
+
* means fifteen rem of pane whatever the container is doing.
|
|
166
|
+
*
|
|
167
|
+
* **The length is the one that holds.** A percentage minimum does not: twenty
|
|
168
|
+
* per cent is 280px in a 1400px splitter and 100px in a 500px one, and the
|
|
169
|
+
* number a consumer picked was almost certainly about how much text fits
|
|
170
|
+
* rather than about a ratio. The pane that a percentage protects at desk
|
|
171
|
+
* width is squeezed past reading at half of it.
|
|
172
|
+
*
|
|
173
|
+
* **It does not fight `collapsed`.** Collapse overrides `min` and `max`, as
|
|
174
|
+
* the class docstring says, so a pane can still be shut and reopened. What a
|
|
175
|
+
* minimum forbids is the space between shut and usable: a pane wide enough to
|
|
176
|
+
* be there and too narrow to read is the state nobody wants and every drag
|
|
177
|
+
* passes through.
|
|
178
|
+
*/
|
|
179
|
+
this.min = 0;
|
|
180
|
+
/**
|
|
181
|
+
* Nearest it may come to the end, on the same terms as `min`.
|
|
182
|
+
*/
|
|
183
|
+
this.max = 100;
|
|
184
|
+
/**
|
|
185
|
+
* How far one arrow press moves it, as a percentage.
|
|
186
|
+
*/
|
|
187
|
+
this.step = 2;
|
|
188
|
+
/**
|
|
189
|
+
* Accessible name for the divider.
|
|
190
|
+
*/
|
|
191
|
+
this.label = 'Resize panes';
|
|
192
|
+
/**
|
|
193
|
+
* Accessible name for the handle where two dividers cross.
|
|
194
|
+
*/
|
|
195
|
+
this.cornerLabel = 'Resize both';
|
|
196
|
+
/** The position, whoever set it, and `undefined` until somebody has. */
|
|
197
|
+
this.positionState = undefined;
|
|
198
|
+
/** The collapse, whoever set it, and `undefined` until somebody has. */
|
|
199
|
+
this.collapsedState = undefined;
|
|
200
|
+
/**
|
|
201
|
+
* Where the divider was before the gesture that may be about to shut it.
|
|
202
|
+
*
|
|
203
|
+
* A drag writes a position on every pointer move, so by the time it reaches
|
|
204
|
+
* the edge the number it started from is gone. Taken once, on the press, and
|
|
205
|
+
* written back if the gesture ends shut, so the pane opens to where it was
|
|
206
|
+
* rather than to the edge it was dragged against.
|
|
207
|
+
*/
|
|
208
|
+
this.opened = undefined;
|
|
209
|
+
/**
|
|
210
|
+
* Where the gesture has moved to, whether or not it was applied. See `move`.
|
|
211
|
+
*
|
|
212
|
+
* `@state`, because the divider is drawn from it while a drag is under way.
|
|
213
|
+
*/
|
|
214
|
+
this.reached = undefined;
|
|
215
|
+
/**
|
|
216
|
+
* Whether this divider is being moved right now, by anything.
|
|
217
|
+
*
|
|
218
|
+
* `:hover` is not enough on its own. A drag holds the pointer through capture
|
|
219
|
+
* and a fast one leaves the eight pixel target behind, and a corner moves a
|
|
220
|
+
* divider the pointer is nowhere near: the nested one, while the reader is on
|
|
221
|
+
* the crossing. Both are dividers that are moving and should say so.
|
|
222
|
+
*
|
|
223
|
+
* A `data-` attribute on an element in this shadow root, never on the host.
|
|
224
|
+
*/
|
|
225
|
+
this.dragging = false;
|
|
226
|
+
/**
|
|
227
|
+
* Nested splitters that cross this one, and how far along they cross it.
|
|
228
|
+
*
|
|
229
|
+
* Written by the child, not found by the parent: a parent cannot poll for a
|
|
230
|
+
* child that has not upgraded, so the child announces itself once it has. The
|
|
231
|
+
* number is the child's own `position`, which is also its offset along this
|
|
232
|
+
* divider, because the child fills the pane and the pane spans this splitter
|
|
233
|
+
* end to end on the axis the divider runs.
|
|
234
|
+
*
|
|
235
|
+
* Not `@state`, because the array is mutated in place. `cross` and `uncross`
|
|
236
|
+
* request the update themselves.
|
|
237
|
+
*/
|
|
238
|
+
this.crossings = [];
|
|
239
|
+
/** The splitter this one is nested in, once it has found it. */
|
|
240
|
+
this.outer = null;
|
|
241
|
+
/** The last position announced upward, so an unchanged one costs nothing. */
|
|
242
|
+
this.crossedAt = undefined;
|
|
243
|
+
/** The two boxes a corner drag is measured against, taken once. */
|
|
244
|
+
this.cornerOrigin = null;
|
|
245
|
+
/**
|
|
246
|
+
* The host's box, measured once when a drag starts.
|
|
247
|
+
*
|
|
248
|
+
* Measuring per move is a forced layout on every pointer event, in the middle
|
|
249
|
+
* of a gesture whose whole job is to stay ahead of the pointer. Nothing about
|
|
250
|
+
* it moves while the divider does.
|
|
251
|
+
*/
|
|
252
|
+
this.origin = null;
|
|
253
|
+
/**
|
|
254
|
+
* Whether `auto` has resolved to stacked, which only the observer sets.
|
|
255
|
+
*/
|
|
256
|
+
this.stacked = false;
|
|
257
|
+
this.handlePointerDown = (event) => {
|
|
258
|
+
const separator = event.currentTarget;
|
|
259
|
+
const box = this.getBoundingClientRect();
|
|
260
|
+
this.origin = this.vertical
|
|
261
|
+
? { length: box.height, start: box.top }
|
|
262
|
+
: { length: box.width, start: box.left };
|
|
263
|
+
/* Captured, so the divider keeps the pointer once it has it: a drag that
|
|
264
|
+
outruns a thin target otherwise ends the moment the pointer leaves it,
|
|
265
|
+
which on a fast gesture is immediately. */
|
|
266
|
+
capturePointer(separator, event.pointerId);
|
|
267
|
+
this.opened = this.collapsed ? undefined : this.position;
|
|
268
|
+
// Cleared, so a number from the last gesture cannot settle this one.
|
|
269
|
+
this.reached = undefined;
|
|
270
|
+
// On the press rather than the first move, so holding it still says so too.
|
|
271
|
+
this.dragging = true;
|
|
272
|
+
event.preventDefault();
|
|
273
|
+
};
|
|
274
|
+
this.handlePointerMove = (event) => {
|
|
275
|
+
const origin = this.origin;
|
|
276
|
+
if (!origin || origin.length === 0) {
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
const along = this.vertical ? event.clientY : event.clientX;
|
|
280
|
+
/* Signed against the writing direction, because a pointer is physical and
|
|
281
|
+
the panes are not: in a right-to-left document the start pane is on the
|
|
282
|
+
right, so dragging right makes it *larger*. */
|
|
283
|
+
const raw = ((along - origin.start) / origin.length) * 100;
|
|
284
|
+
const rtl = !this.vertical && getComputedStyle(this).direction === 'rtl';
|
|
285
|
+
this.move(rtl ? 100 - raw : raw);
|
|
286
|
+
};
|
|
287
|
+
this.handlePointerUp = (event) => {
|
|
288
|
+
if (!this.origin) {
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
const separator = event.currentTarget;
|
|
292
|
+
if (separator.hasPointerCapture(event.pointerId)) {
|
|
293
|
+
separator.releasePointerCapture(event.pointerId);
|
|
294
|
+
}
|
|
295
|
+
this.origin = null;
|
|
296
|
+
this.dragging = false;
|
|
297
|
+
/* Nothing moved, so nothing is announced.
|
|
298
|
+
Every press on the divider used to settle, which dispatched a change
|
|
299
|
+
carrying the position it already had: a plain click rewrote a consumer's
|
|
300
|
+
stored value from a gesture that moved nothing. Harmless where the value
|
|
301
|
+
round-trips exactly, and not where it does not, which is any consumer
|
|
302
|
+
storing pixels and dividing by a box. */
|
|
303
|
+
if (this.reached === undefined) {
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
/* `reached` is deliberately left standing. It is what the divider is drawn
|
|
307
|
+
from until the consumer answers, and the setter is what clears it. */
|
|
308
|
+
this.settle(this.reached);
|
|
309
|
+
};
|
|
310
|
+
/**
|
|
311
|
+
* The keys a separator answers.
|
|
312
|
+
*
|
|
313
|
+
* One axis, the one the divider actually travels along, plus `Home` and `End`
|
|
314
|
+
* for its bounds. The other two arrows are left alone and the page scrolls
|
|
315
|
+
* under them as it would anywhere else.
|
|
316
|
+
*
|
|
317
|
+
* *Corrected 18 Aug 2026. This said "both axes, always", on the reasoning
|
|
318
|
+
* `KeyboardNavigationController` uses for a set of items: a reader who guesses
|
|
319
|
+
* the wrong arrow gets nothing. The code has never done it, and measuring the
|
|
320
|
+
* three tab stops of a nested pair is what turned that up, so the prose was
|
|
321
|
+
* describing a decision nobody implemented.*
|
|
322
|
+
*
|
|
323
|
+
* *Leaving it as one axis, because nesting is what settles it. Taking all four
|
|
324
|
+
* would mean `ArrowLeft` moving a horizontal divider up and down, which is not
|
|
325
|
+
* a reader being helped past a guess, it is an arrow that does not go the way
|
|
326
|
+
* it points. And the guess it was protecting against is answered better by the
|
|
327
|
+
* corner: there, all four arrows are live and each moves the divider it points
|
|
328
|
+
* along, which is the only place in a splitter where a second axis means
|
|
329
|
+
* anything.*
|
|
330
|
+
*/
|
|
331
|
+
this.handleKeydown = (event) => {
|
|
332
|
+
const back = this.vertical ? 'ArrowUp' : 'ArrowLeft';
|
|
333
|
+
const forward = this.vertical ? 'ArrowDown' : 'ArrowRight';
|
|
334
|
+
let next;
|
|
335
|
+
if (event.key === back) {
|
|
336
|
+
next = this.position - this.step;
|
|
337
|
+
}
|
|
338
|
+
else if (event.key === forward) {
|
|
339
|
+
next = this.position + this.step;
|
|
340
|
+
}
|
|
341
|
+
else if (event.key === 'Home') {
|
|
342
|
+
next = this.minPercent;
|
|
343
|
+
}
|
|
344
|
+
else if (event.key === 'End') {
|
|
345
|
+
next = this.maxPercent;
|
|
346
|
+
}
|
|
347
|
+
else {
|
|
348
|
+
return;
|
|
349
|
+
}
|
|
350
|
+
this.move(next);
|
|
351
|
+
this.settle(next);
|
|
352
|
+
// Or the arrows scroll the page under the divider being moved.
|
|
353
|
+
event.preventDefault();
|
|
354
|
+
};
|
|
355
|
+
this.handleDoubleClick = () => {
|
|
356
|
+
this.reset();
|
|
357
|
+
};
|
|
358
|
+
/**
|
|
359
|
+
* Both of them, because the corner moves both.
|
|
360
|
+
*
|
|
361
|
+
* It needs its own handler now. Inside the separator this came free by
|
|
362
|
+
* bubbling, and moving the corner out to sit against the host for the stacking
|
|
363
|
+
* reason took the double click with it: the divider reset and the crossing
|
|
364
|
+
* did not. Reported.
|
|
365
|
+
*/
|
|
366
|
+
this.handleCornerDoubleClick = (event) => {
|
|
367
|
+
const crossing = this.crossings[Number(event.currentTarget.dataset.cross)];
|
|
368
|
+
if (!crossing) {
|
|
369
|
+
return;
|
|
370
|
+
}
|
|
371
|
+
this.reset();
|
|
372
|
+
crossing.by.reset();
|
|
373
|
+
this.leaveSeparator(event);
|
|
374
|
+
};
|
|
375
|
+
this.handleCornerDown = (event) => {
|
|
376
|
+
const handle = event.currentTarget;
|
|
377
|
+
const crossing = this.crossings[Number(handle.dataset.cross)];
|
|
378
|
+
if (!crossing) {
|
|
379
|
+
return;
|
|
380
|
+
}
|
|
381
|
+
const mine = this.getBoundingClientRect();
|
|
382
|
+
const theirs = crossing.by.getBoundingClientRect();
|
|
383
|
+
this.cornerOrigin = {
|
|
384
|
+
by: crossing.by,
|
|
385
|
+
inner: crossing.by.vertical
|
|
386
|
+
? { length: theirs.height, start: theirs.top }
|
|
387
|
+
: { length: theirs.width, start: theirs.left },
|
|
388
|
+
outer: this.vertical
|
|
389
|
+
? { length: mine.height, start: mine.top }
|
|
390
|
+
: { length: mine.width, start: mine.left },
|
|
391
|
+
};
|
|
392
|
+
capturePointer(handle, event.pointerId);
|
|
393
|
+
this.opened = this.collapsed ? undefined : this.position;
|
|
394
|
+
crossing.by.opened = crossing.by.collapsed ? undefined : crossing.by.position;
|
|
395
|
+
this.reached = undefined;
|
|
396
|
+
crossing.by.reached = undefined;
|
|
397
|
+
/* Both of them, on the press. The nested one is reachable here because it is
|
|
398
|
+
the same class, and this is the whole of what the corner needs beyond
|
|
399
|
+
`moveTo`: a divider being moved looks like one. */
|
|
400
|
+
this.dragging = true;
|
|
401
|
+
crossing.by.dragging = true;
|
|
402
|
+
this.leaveSeparator(event);
|
|
403
|
+
};
|
|
404
|
+
/** Both axes at once, each measured against the splitter that owns it. */
|
|
405
|
+
this.handleCornerMove = (event) => {
|
|
406
|
+
const origin = this.cornerOrigin;
|
|
407
|
+
if (!origin) {
|
|
408
|
+
return;
|
|
409
|
+
}
|
|
410
|
+
const rtl = getComputedStyle(this).direction === 'rtl';
|
|
411
|
+
const along = (box, at, inline) => {
|
|
412
|
+
if (box.length === 0) {
|
|
413
|
+
return undefined;
|
|
414
|
+
}
|
|
415
|
+
const raw = ((at - box.start) / box.length) * 100;
|
|
416
|
+
return inline && rtl ? 100 - raw : raw;
|
|
417
|
+
};
|
|
418
|
+
const mine = along(origin.outer, this.vertical ? event.clientY : event.clientX, !this.vertical);
|
|
419
|
+
const theirs = along(origin.inner, origin.by.vertical ? event.clientY : event.clientX, !origin.by.vertical);
|
|
420
|
+
if (mine !== undefined) {
|
|
421
|
+
this.moveTo(mine);
|
|
422
|
+
}
|
|
423
|
+
if (theirs !== undefined) {
|
|
424
|
+
origin.by.moveTo(theirs);
|
|
425
|
+
}
|
|
426
|
+
this.leaveSeparator(event);
|
|
427
|
+
};
|
|
428
|
+
this.handleCornerUp = (event) => {
|
|
429
|
+
const origin = this.cornerOrigin;
|
|
430
|
+
if (!origin) {
|
|
431
|
+
return;
|
|
432
|
+
}
|
|
433
|
+
const handle = event.currentTarget;
|
|
434
|
+
if (handle.hasPointerCapture(event.pointerId)) {
|
|
435
|
+
handle.releasePointerCapture(event.pointerId);
|
|
436
|
+
}
|
|
437
|
+
this.cornerOrigin = null;
|
|
438
|
+
this.moveTo(this.reached ?? this.position, true);
|
|
439
|
+
origin.by.moveTo(origin.by.reached ?? origin.by.position, true);
|
|
440
|
+
this.leaveSeparator(event);
|
|
441
|
+
};
|
|
442
|
+
/**
|
|
443
|
+
* The corner takes every arrow, each moving the splitter whose axis it points
|
|
444
|
+
* along, which is the only reading a keyboard can give a handle that moves in
|
|
445
|
+
* two directions.
|
|
446
|
+
*/
|
|
447
|
+
this.handleCornerKeydown = (event) => {
|
|
448
|
+
const crossing = this.crossings[Number(event.currentTarget.dataset.cross)];
|
|
449
|
+
if (!crossing) {
|
|
450
|
+
return;
|
|
451
|
+
}
|
|
452
|
+
const inner = crossing.by;
|
|
453
|
+
const mineBack = this.vertical ? 'ArrowUp' : 'ArrowLeft';
|
|
454
|
+
const mineForward = this.vertical ? 'ArrowDown' : 'ArrowRight';
|
|
455
|
+
const theirsBack = inner.vertical ? 'ArrowUp' : 'ArrowLeft';
|
|
456
|
+
const theirsForward = inner.vertical ? 'ArrowDown' : 'ArrowRight';
|
|
457
|
+
if (event.key === mineBack || event.key === mineForward) {
|
|
458
|
+
this.moveTo(this.position + (event.key === mineBack ? -this.step : this.step), true);
|
|
459
|
+
}
|
|
460
|
+
else if (event.key === theirsBack || event.key === theirsForward) {
|
|
461
|
+
inner.moveTo(inner.position + (event.key === theirsBack ? -inner.step : inner.step), true);
|
|
462
|
+
}
|
|
463
|
+
else {
|
|
464
|
+
return;
|
|
465
|
+
}
|
|
466
|
+
this.leaveSeparator(event);
|
|
467
|
+
};
|
|
468
|
+
}
|
|
469
|
+
/**
|
|
470
|
+
* Where the divider sits, as a percentage of the whole.
|
|
471
|
+
*
|
|
472
|
+
* Reading gives where it is; writing declares it the consumer's, and
|
|
473
|
+
* `default-position` seeds one this element owns. The same accessor pair
|
|
474
|
+
* `Pagination.page` and the calendar's `month` carry.
|
|
475
|
+
*
|
|
476
|
+
*
|
|
477
|
+
*/
|
|
478
|
+
get position() {
|
|
479
|
+
const shut = this.collapsed;
|
|
480
|
+
if (shut) {
|
|
481
|
+
return shut === 'start' ? this.sliver : 100 - this.sliver;
|
|
482
|
+
}
|
|
483
|
+
return this.clamp(this.positionState ?? this.defaultPosition);
|
|
484
|
+
}
|
|
485
|
+
set position(next) {
|
|
486
|
+
const previous = this.position;
|
|
487
|
+
this.positionState = next;
|
|
488
|
+
/* The consumer has spoken, so the drag stops standing in for them.
|
|
489
|
+
Without this the divider flashed back: `dragging` goes false on
|
|
490
|
+
`pointerup`, `showing` fell straight back to the position they had set
|
|
491
|
+
before the gesture, and it was drawn there for the frame it took them to
|
|
492
|
+
answer the announcement. Snapping to where it started and then jumping to
|
|
493
|
+
where it was dropped, on every drag. */
|
|
494
|
+
this.reached = undefined;
|
|
495
|
+
this.requestUpdate('position', previous);
|
|
496
|
+
}
|
|
497
|
+
/**
|
|
498
|
+
* Which pane is shut, if either.
|
|
499
|
+
*
|
|
500
|
+
* The same accessor pair as `position`, and deliberately a second state
|
|
501
|
+
* rather than a reading of the first. A pane shut by dragging the divider to
|
|
502
|
+
* the edge and a pane shut on purpose look identical in geometry and are not
|
|
503
|
+
* the same thing: only the second knows where to go back to. Kept apart, the
|
|
504
|
+
* open position is simply the one collapsing never overwrote, so restoring
|
|
505
|
+
* needs no memory of its own.
|
|
506
|
+
*
|
|
507
|
+
* It overrides `min` and `max`, which is the point of it. Those keep a sliver
|
|
508
|
+
* of a pane during a drag; this is the thing that says the sliver can go.
|
|
509
|
+
*
|
|
510
|
+
*
|
|
511
|
+
*/
|
|
512
|
+
get collapsed() {
|
|
513
|
+
const held = this.collapsedState;
|
|
514
|
+
if (held === undefined) {
|
|
515
|
+
return this.defaultCollapsed;
|
|
516
|
+
}
|
|
517
|
+
return held === 'none' ? undefined : held;
|
|
518
|
+
}
|
|
519
|
+
set collapsed(next) {
|
|
520
|
+
const previous = this.collapsed;
|
|
521
|
+
/* `none` rather than `undefined`, because the two mean different things
|
|
522
|
+
here and conflating them cost a spec: `undefined` is nobody having
|
|
523
|
+
spoken, which is the seed's cue to answer, so clearing a collapse handed
|
|
524
|
+
it straight back to `default-collapsed` and the pane would not open. */
|
|
525
|
+
this.collapsedState = next ?? 'none';
|
|
526
|
+
this.requestUpdate('collapsed', previous);
|
|
527
|
+
}
|
|
528
|
+
/**
|
|
529
|
+
* Either kind of bound as a percentage of the box.
|
|
530
|
+
*
|
|
531
|
+
* Measured rather than cached: a length is only meaningful against the size
|
|
532
|
+
* the splitter is right now, and the drag that asks is already reading layout.
|
|
533
|
+
* Falls back where there is nothing to measure, which is the server and an
|
|
534
|
+
* element that is not displayed, so `aria-valuemin` is a number either way.
|
|
535
|
+
*/
|
|
536
|
+
toPercent(value, fallback) {
|
|
537
|
+
if (typeof value === 'number') {
|
|
538
|
+
return Number.isFinite(value) ? value : fallback;
|
|
539
|
+
}
|
|
540
|
+
const text = value.trim();
|
|
541
|
+
if (text === '') {
|
|
542
|
+
return fallback;
|
|
543
|
+
}
|
|
544
|
+
const bare = Number(text);
|
|
545
|
+
if (Number.isFinite(bare)) {
|
|
546
|
+
return bare;
|
|
547
|
+
}
|
|
548
|
+
const length = /^(-?[\d.]+)(em|px|rem)$/.exec(text);
|
|
549
|
+
if (!length || typeof window === 'undefined') {
|
|
550
|
+
return fallback;
|
|
551
|
+
}
|
|
552
|
+
const amount = Number(length[1]);
|
|
553
|
+
const root = Number.parseFloat(getComputedStyle(document.documentElement).fontSize) || 16;
|
|
554
|
+
const own = Number.parseFloat(getComputedStyle(this).fontSize) || root;
|
|
555
|
+
const pixels = length[2] === 'px' ? amount : amount * (length[2] === 'rem' ? root : own);
|
|
556
|
+
const box = this.getBoundingClientRect();
|
|
557
|
+
const extent = this.vertical ? box.height : box.width;
|
|
558
|
+
return extent > 0 ? (pixels / extent) * 100 : fallback;
|
|
559
|
+
}
|
|
560
|
+
/** `min` as a percentage, whichever way it was written. */
|
|
561
|
+
get minPercent() {
|
|
562
|
+
return this.toPercent(this.min, 0);
|
|
563
|
+
}
|
|
564
|
+
/** `max` as a percentage, whichever way it was written. */
|
|
565
|
+
get maxPercent() {
|
|
566
|
+
return this.toPercent(this.max, 100);
|
|
567
|
+
}
|
|
568
|
+
/**
|
|
569
|
+
* The position to draw, which is not always the position to report.
|
|
570
|
+
*
|
|
571
|
+
* A controlled splitter applies nothing, so `position` holds still for the
|
|
572
|
+
* whole gesture and the divider stayed where it was until the pointer came up
|
|
573
|
+
* and the consumer answered: it jumped to the end rather than following the
|
|
574
|
+
* hand. Reported as resizing that was not seamless and did not work as it had.
|
|
575
|
+
*
|
|
576
|
+
* So a drag draws itself. The number is not announced until it settles, which
|
|
577
|
+
* is the rule that has not changed, and the consumer's answer takes over the
|
|
578
|
+
* moment they give one. It is what the sandbox did for itself before it used
|
|
579
|
+
* this component: write the size on every pointer move, tell anyone once.
|
|
580
|
+
*/
|
|
581
|
+
get showing() {
|
|
582
|
+
return this.reached === undefined ? this.position : this.clamp(this.reached);
|
|
583
|
+
}
|
|
584
|
+
/**
|
|
585
|
+
* Moves the divider, and optionally says so.
|
|
586
|
+
*
|
|
587
|
+
* Public because a corner on a nested splitter has to drive the one it is
|
|
588
|
+
* nested in, and that is the whole of what it needs: the pair are not
|
|
589
|
+
* otherwise coupled and neither reads the other's state. `settled` is false
|
|
590
|
+
* for each step of a drag and true once, at the end, for the reason a drag
|
|
591
|
+
* announces once: only the position it ends at is a preference.
|
|
592
|
+
*/
|
|
593
|
+
moveTo(next, settled = false) {
|
|
594
|
+
/* An unsettled move is a drag in progress, which is what `settled` already
|
|
595
|
+
means, so the nested splitter a corner drives lights up without either of
|
|
596
|
+
them being told about the other's presentation. */
|
|
597
|
+
this.dragging = !settled;
|
|
598
|
+
if (settled) {
|
|
599
|
+
this.settle(next);
|
|
600
|
+
}
|
|
601
|
+
else {
|
|
602
|
+
this.move(next);
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
/*
|
|
606
|
+
* The collapse a settled position amounts to, if any.
|
|
607
|
+
*
|
|
608
|
+
* So that a pane dragged shut and a pane shut by a consumer's button are the
|
|
609
|
+
* same state. Left apart, a reader could drag the panel closed and the button
|
|
610
|
+
* offering to reopen it would read as already open.
|
|
611
|
+
*
|
|
612
|
+
* No separate threshold. Landing on the collapsed size *is* the gesture, and
|
|
613
|
+
* `clamp` puts every overshoot exactly on the bound, so the default of zero
|
|
614
|
+
* latches on any drag that runs off the end.
|
|
615
|
+
*/
|
|
616
|
+
/** The collapsed size, held inside the range a percentage can be. */
|
|
617
|
+
get sliver() {
|
|
618
|
+
return Math.min(100, Math.max(0, this.collapsedSize));
|
|
619
|
+
}
|
|
620
|
+
/**
|
|
621
|
+
* Whether the divider is against an edge with nothing beside it.
|
|
622
|
+
*
|
|
623
|
+
* Geometry, not state, which is the second answer here: it asked whether the
|
|
624
|
+
* pane was `collapsed`, and a divider driven to the edge by a consumer setting
|
|
625
|
+
* `position` is just as flush and drew a line anyway. What the stylesheet
|
|
626
|
+
* needs to know is whether there is a pane on both sides, and that is a fact
|
|
627
|
+
* about where the divider is however it got there.
|
|
628
|
+
*
|
|
629
|
+
* Still not the same question as `collapsed`: a pane shut to a sliver has a
|
|
630
|
+
* boundary worth drawing, and one shut to nothing has the container's own edge
|
|
631
|
+
* there instead.
|
|
632
|
+
*/
|
|
633
|
+
get flush() {
|
|
634
|
+
return this.sliver === 0 && this.shutAt(this.position) !== undefined;
|
|
635
|
+
}
|
|
636
|
+
shutAt(position) {
|
|
637
|
+
const size = this.sliver;
|
|
638
|
+
if (position <= size) {
|
|
639
|
+
return 'start';
|
|
640
|
+
}
|
|
641
|
+
return position >= 100 - size ? 'end' : undefined;
|
|
642
|
+
}
|
|
643
|
+
/** Pulled between the bounds, which are the ends unless a consumer moved them. */
|
|
644
|
+
clamp(next) {
|
|
645
|
+
const min = Math.max(0, Math.min(100, this.minPercent));
|
|
646
|
+
const max = Math.max(min, Math.min(100, this.maxPercent));
|
|
647
|
+
return Math.min(max, Math.max(min, Number.isFinite(next) ? next : min));
|
|
648
|
+
}
|
|
649
|
+
/**
|
|
650
|
+
* Starts or stops watching, according to what the axis was asked to be.
|
|
651
|
+
*
|
|
652
|
+
* Called from `firstUpdated` and from `updated`, so a consumer switching to
|
|
653
|
+
* `auto` after mount is observed and one switching away stops being: an
|
|
654
|
+
* observer left running would keep writing `stacked` that nothing reads, and
|
|
655
|
+
* a splitter told `horizontal` has been given its answer already.
|
|
656
|
+
*/
|
|
657
|
+
watchWidth() {
|
|
658
|
+
if (this.orientation !== 'auto') {
|
|
659
|
+
this.sizes?.disconnect();
|
|
660
|
+
this.sizes = undefined;
|
|
661
|
+
return;
|
|
662
|
+
}
|
|
663
|
+
if (this.sizes) {
|
|
664
|
+
return;
|
|
665
|
+
}
|
|
666
|
+
this.sizes = new ResizeObserver(([entry]) => {
|
|
667
|
+
const width = entry?.borderBoxSize?.[0]?.inlineSize ?? entry?.contentRect.width ?? 0;
|
|
668
|
+
/* Zero while the element is `display: none` or not yet laid out, and a
|
|
669
|
+
zero is not a narrow splitter: taking it would stack every instance
|
|
670
|
+
that starts hidden and never turn it back. */
|
|
671
|
+
if (width > 0) {
|
|
672
|
+
this.stacked = width < STACK_BELOW;
|
|
673
|
+
}
|
|
674
|
+
});
|
|
675
|
+
this.sizes.observe(this);
|
|
676
|
+
}
|
|
677
|
+
/**
|
|
678
|
+
* Public because a nested splitter compares axes with the one it is in.
|
|
679
|
+
*
|
|
680
|
+
* The one place the axis is decided, which is why `auto` costs a single line
|
|
681
|
+
* here rather than a pass over seventeen readers: the drag, the arrow keys and
|
|
682
|
+
* `aria-orientation` all ask this and all turn together.
|
|
683
|
+
*/
|
|
684
|
+
get vertical() {
|
|
685
|
+
return this.orientation === 'vertical' || (this.orientation === 'auto' && this.stacked);
|
|
686
|
+
}
|
|
687
|
+
/**
|
|
688
|
+
* Asks to move, and applies it where the position is this element's to move.
|
|
689
|
+
*
|
|
690
|
+
* Not announced per step: `helix-before-resize` is the settling, below. A drag that
|
|
691
|
+
* announced every position would be asking a consumer to record a hundred
|
|
692
|
+
* decisions to keep one.
|
|
693
|
+
*/
|
|
694
|
+
move(next) {
|
|
695
|
+
const wanted = this.clamp(next);
|
|
696
|
+
/* Where the gesture has reached, recorded before anything decides whether to
|
|
697
|
+
apply it. A controlled splitter applies nothing, so its `position` is
|
|
698
|
+
whatever the consumer last said, and settling at *that* announces the
|
|
699
|
+
number it already had: the drag ended where it began and the divider never
|
|
700
|
+
moved. Reported as a splitter that could not be dragged at all, and it was
|
|
701
|
+
every controlled one. The keyboard was fine because it computes its next
|
|
702
|
+
position rather than reading it back. */
|
|
703
|
+
this.reached = wanted;
|
|
704
|
+
if (wanted === this.position) {
|
|
705
|
+
return;
|
|
706
|
+
}
|
|
707
|
+
const previous = this.position;
|
|
708
|
+
this.positionState = wanted;
|
|
709
|
+
/* A divider that is moving is a pane that is opening, and a shut one is
|
|
710
|
+
still draggable precisely so it can be. Silent, like the move itself:
|
|
711
|
+
the settling below is what announces either. */
|
|
712
|
+
this.collapsedState = 'none';
|
|
713
|
+
this.requestUpdate('position', previous);
|
|
714
|
+
}
|
|
715
|
+
/**
|
|
716
|
+
* Says the arrangement has settled, so a consumer can keep it.
|
|
717
|
+
*
|
|
718
|
+
* Through the audited path, so a consumer who owns `position` is told what was
|
|
719
|
+
* asked for and decides, and one who does not has already had it applied.
|
|
720
|
+
*/
|
|
721
|
+
settle(next) {
|
|
722
|
+
const wanted = this.clamp(next);
|
|
723
|
+
const shut = this.shutAt(wanted);
|
|
724
|
+
requestChange({
|
|
725
|
+
apply: (value) => {
|
|
726
|
+
const previous = this.position;
|
|
727
|
+
this.positionState = value;
|
|
728
|
+
this.requestUpdate('position', previous);
|
|
729
|
+
},
|
|
730
|
+
event: (value) => new HelixBeforeResizeEvent({ value: String(value) }),
|
|
731
|
+
host: this,
|
|
732
|
+
next: wanted,
|
|
733
|
+
});
|
|
734
|
+
if (shut !== this.collapsed) {
|
|
735
|
+
/* Two values from one gesture, so two announcements. `ChangeDetail`
|
|
736
|
+
carries a name for exactly this, and a consumer listening for one of
|
|
737
|
+
them is not made to care about the other. */
|
|
738
|
+
requestChange({
|
|
739
|
+
apply: (value) => {
|
|
740
|
+
const previous = this.collapsed;
|
|
741
|
+
// Back to where the gesture started, so opening it again is a return
|
|
742
|
+
// rather than a jump to the edge it was dragged against.
|
|
743
|
+
if (value !== '' && this.opened !== undefined) {
|
|
744
|
+
this.positionState = this.opened;
|
|
745
|
+
}
|
|
746
|
+
this.collapsedState = value === '' ? 'none' : value;
|
|
747
|
+
this.requestUpdate('collapsed', previous);
|
|
748
|
+
},
|
|
749
|
+
event: (value) => new HelixBeforeCollapseEvent({ value }),
|
|
750
|
+
host: this,
|
|
751
|
+
next: shut ?? '',
|
|
752
|
+
});
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
/** Puts the divider back where the markup put it. */
|
|
756
|
+
reset() {
|
|
757
|
+
/* `default-position`, not the position at first render, which is what this
|
|
758
|
+
read and which is only the same thing when nobody owns the position. A
|
|
759
|
+
consumer who does owns what it was on that first frame too, and theirs can
|
|
760
|
+
be a number they cannot compute yet: the sandbox sizes its panel in pixels
|
|
761
|
+
and has no box to divide by until it has rendered once, so the divider
|
|
762
|
+
recorded "panel closed" as home and a double click on the crossing shut
|
|
763
|
+
the panel instead of restoring it. Reported.
|
|
764
|
+
|
|
765
|
+
Declared rather than remembered, so it is a value a consumer can state and
|
|
766
|
+
change, and it needs no capture at all. */
|
|
767
|
+
const home = this.clamp(this.defaultPosition);
|
|
768
|
+
this.move(home);
|
|
769
|
+
this.settle(home);
|
|
770
|
+
}
|
|
771
|
+
/**
|
|
772
|
+
* Records that a nested splitter crosses this one at `at` percent along it.
|
|
773
|
+
*
|
|
774
|
+
* Public because it is the whole of the channel between the two, and it runs
|
|
775
|
+
* one way: the child tells the parent where it is, and the parent draws the
|
|
776
|
+
* corner and drives them both. Nothing is read back, so neither has to know
|
|
777
|
+
* anything about the other's state.
|
|
778
|
+
*/
|
|
779
|
+
cross(by, at) {
|
|
780
|
+
const found = this.crossings.find((crossing) => crossing.by === by);
|
|
781
|
+
if (found) {
|
|
782
|
+
if (found.at === at) {
|
|
783
|
+
return;
|
|
784
|
+
}
|
|
785
|
+
found.at = at;
|
|
786
|
+
}
|
|
787
|
+
else {
|
|
788
|
+
this.crossings.push({ at, by });
|
|
789
|
+
}
|
|
790
|
+
this.requestUpdate();
|
|
791
|
+
}
|
|
792
|
+
/** Forgets a nested splitter that has left the tree. See `cross`. */
|
|
793
|
+
uncross(by) {
|
|
794
|
+
const at = this.crossings.findIndex((crossing) => crossing.by === by);
|
|
795
|
+
if (at === -1) {
|
|
796
|
+
return;
|
|
797
|
+
}
|
|
798
|
+
this.crossings.splice(at, 1);
|
|
799
|
+
this.requestUpdate();
|
|
800
|
+
}
|
|
801
|
+
/**
|
|
802
|
+
* Announces this splitter to the one it is nested in, if they cross.
|
|
803
|
+
*
|
|
804
|
+
* Client only. The server has no tree to walk, and a parent that has not
|
|
805
|
+
* upgraded has no `orientation` to compare against, so this waits for
|
|
806
|
+
* `firstUpdated`. That is what the corner is allowed to be: an affordance
|
|
807
|
+
* rather than content, absent from the served markup and appearing at
|
|
808
|
+
* hydration, with two working dividers in the meantime.
|
|
809
|
+
*
|
|
810
|
+
* `parentElement` first, so a splitter does not find itself.
|
|
811
|
+
*
|
|
812
|
+
* **By identity rather than by tag, which `closestInstance` exists for and
|
|
813
|
+
* counts this file in its own documentation.** It matched
|
|
814
|
+
* `'helix-splitter, helix-headless-splitter'`, and only `@fusion.dev/helix` registers
|
|
815
|
+
* the first of those: a headless package naming a styled one by string. Under
|
|
816
|
+
* any third tag, which is exactly what subclassing a headless element is for and
|
|
817
|
+
* what `helix/styled` itself does, the lookup returned null and a nested
|
|
818
|
+
* splitter had no corner, with no error anywhere.
|
|
819
|
+
*
|
|
820
|
+
* It also crosses shadow boundaries, which `closest` does not: a splitter
|
|
821
|
+
* slotted into another component's shadow root has a `parentNode` chain
|
|
822
|
+
* ending at a `ShadowRoot`, and nesting through a slot is the ordinary case
|
|
823
|
+
* for anything composable.
|
|
824
|
+
*/
|
|
825
|
+
findOuter() {
|
|
826
|
+
const outer = closestInstance(this.parentElement, HelixHeadlessSplitter_1);
|
|
827
|
+
if (!outer || outer === this || outer.vertical === this.vertical) {
|
|
828
|
+
// Parallel dividers never meet, so there is no corner to take hold of.
|
|
829
|
+
return;
|
|
830
|
+
}
|
|
831
|
+
this.outer = outer;
|
|
832
|
+
this.crossedAt = this.position;
|
|
833
|
+
outer.cross(this, this.position);
|
|
834
|
+
}
|
|
835
|
+
/**
|
|
836
|
+
* Keeps a gesture on the corner to itself.
|
|
837
|
+
*
|
|
838
|
+
* The corner was a child of the separator first, and every one of its events
|
|
839
|
+
* bubbled there, so the separator started its own drag from the same press.
|
|
840
|
+
* That is worse than moving twice: the separator calls `setPointerCapture`,
|
|
841
|
+
* which retargets every later pointer event to *it*, so the corner's
|
|
842
|
+
* `pointerup` never arrived, its origin was never cleared, and it went on
|
|
843
|
+
* resizing with no button held. Reported as resizing without a press.
|
|
844
|
+
*
|
|
845
|
+
* The corner is a sibling now, for the stacking reason in the stylesheet, so
|
|
846
|
+
* nothing reaches the separator by bubbling. This stays because the fix should
|
|
847
|
+
* not depend on where the element happens to sit, and `preventDefault` is
|
|
848
|
+
* still needed either way: a drag across a pane would otherwise select the
|
|
849
|
+
* text under it.
|
|
850
|
+
*/
|
|
851
|
+
leaveSeparator(event) {
|
|
852
|
+
event.stopPropagation();
|
|
853
|
+
event.preventDefault();
|
|
854
|
+
}
|
|
855
|
+
connectedCallback() {
|
|
856
|
+
super.connectedCallback();
|
|
857
|
+
// Only on a re-connect. The first pass waits for `firstUpdated`, which is
|
|
858
|
+
// where a parent is guaranteed to have upgraded.
|
|
859
|
+
if (this.hasUpdated) {
|
|
860
|
+
/* The width watch too, and it belongs here for a plainer reason than the
|
|
861
|
+
one above: `disconnectedCallback` drops the observer on every move, so
|
|
862
|
+
a splitter reordered in the DOM would stop watching its own width and
|
|
863
|
+
`auto` would freeze on whatever it last saw. `check:observers` is what
|
|
864
|
+
said so. */
|
|
865
|
+
this.watchWidth();
|
|
866
|
+
this.findOuter();
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
disconnectedCallback() {
|
|
870
|
+
super.disconnectedCallback();
|
|
871
|
+
this.sizes?.disconnect();
|
|
872
|
+
this.sizes = undefined;
|
|
873
|
+
this.outer?.uncross(this);
|
|
874
|
+
this.outer = null;
|
|
875
|
+
this.crossedAt = undefined;
|
|
876
|
+
}
|
|
877
|
+
firstUpdated(changed) {
|
|
878
|
+
super.firstUpdated(changed);
|
|
879
|
+
this.watchWidth();
|
|
880
|
+
this.findOuter();
|
|
881
|
+
}
|
|
882
|
+
/** Keeps the corner in step while this divider moves under it. */
|
|
883
|
+
updated(changed) {
|
|
884
|
+
super.updated(changed);
|
|
885
|
+
if (changed.has('orientation')) {
|
|
886
|
+
this.watchWidth();
|
|
887
|
+
}
|
|
888
|
+
/* The resolved collapse, mirrored for a consumer's own rules: a shut pane
|
|
889
|
+
usually wants its contents to stop being read as well as stop being seen.
|
|
890
|
+
`data-` and not `collapsed`, so a serialized host cannot be re-parsed with
|
|
891
|
+
it declared, which is the trap `value` records. It carries which pane
|
|
892
|
+
rather than a bare boolean, and that is still a state and not a payload:
|
|
893
|
+
two names for the two sides, nothing of the consumer's in it. */
|
|
894
|
+
if (this.collapsed) {
|
|
895
|
+
this.dataset.collapsed = this.collapsed;
|
|
896
|
+
}
|
|
897
|
+
else {
|
|
898
|
+
delete this.dataset.collapsed;
|
|
899
|
+
}
|
|
900
|
+
/* The resolved axis, mirrored for the same reason and on the same terms: a
|
|
901
|
+
stylesheet selecting `[orientation="vertical"]` cannot see an `auto` that
|
|
902
|
+
has turned, so the layout would stay side by side while the drag, the keys
|
|
903
|
+
and `aria-orientation` had all gone the other way. That is the lie the
|
|
904
|
+
policy warns a CSS-only version tells, arrived at from the other side.
|
|
905
|
+
|
|
906
|
+
Only where `auto` produced it. An explicit `vertical` already carries an
|
|
907
|
+
attribute saying so, and writing a second would put two sources of one
|
|
908
|
+
truth on the host and a flash of the wrong axis before hydration. */
|
|
909
|
+
if (this.orientation === 'auto' && this.stacked) {
|
|
910
|
+
this.dataset.axis = 'vertical';
|
|
911
|
+
}
|
|
912
|
+
else {
|
|
913
|
+
delete this.dataset.axis;
|
|
914
|
+
}
|
|
915
|
+
/* `showing` rather than `position`, so a corner drawn on the splitter above
|
|
916
|
+
follows this divider through a drag instead of catching up at the end. */
|
|
917
|
+
if (this.outer && this.showing !== this.crossedAt) {
|
|
918
|
+
this.crossedAt = this.showing;
|
|
919
|
+
this.outer.cross(this, this.showing);
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
willUpdate(changed) {
|
|
923
|
+
super.willUpdate(changed);
|
|
924
|
+
}
|
|
925
|
+
render() {
|
|
926
|
+
const position = this.showing;
|
|
927
|
+
/* The panes are marked while the divider moves, so the styled tier can take
|
|
928
|
+
them out of the pointer's way.
|
|
929
|
+
A pane holds whatever a consumer put in it, and an `<iframe>` is the case
|
|
930
|
+
that breaks: a cross-origin frame is its own hit-testing world, and a drag
|
|
931
|
+
whose path crosses one can be lost to it. The sandbox is exactly this, a
|
|
932
|
+
sandboxed preview sitting against the panel divider, so the drag that
|
|
933
|
+
makes the panel bigger is the drag that goes straight over it.
|
|
934
|
+
On the panes rather than on the host, which the `dragging` state above
|
|
935
|
+
records as a rule: a `data-` attribute here is one this element owns, and
|
|
936
|
+
one on the host is one a React consumer's server markup never had. */
|
|
937
|
+
return html `<div
|
|
938
|
+
part="start"
|
|
939
|
+
?data-dragging=${this.dragging}
|
|
940
|
+
style="--splitter-position: ${position}%"
|
|
941
|
+
>
|
|
942
|
+
<slot name="start"></slot>
|
|
943
|
+
</div>
|
|
944
|
+
<div
|
|
945
|
+
part="separator"
|
|
946
|
+
role="separator"
|
|
947
|
+
tabindex="0"
|
|
948
|
+
aria-label=${this.label}
|
|
949
|
+
aria-orientation=${this.vertical ? 'horizontal' : 'vertical'}
|
|
950
|
+
aria-valuemax=${this.clamp(this.maxPercent)}
|
|
951
|
+
aria-valuemin=${this.clamp(this.minPercent)}
|
|
952
|
+
aria-valuenow=${Math.round(position)}
|
|
953
|
+
?data-dragging=${this.dragging}
|
|
954
|
+
?data-flush=${this.flush}
|
|
955
|
+
@dblclick=${this.handleDoubleClick}
|
|
956
|
+
@keydown=${this.handleKeydown}
|
|
957
|
+
@pointercancel=${this.handlePointerUp}
|
|
958
|
+
@pointerdown=${this.handlePointerDown}
|
|
959
|
+
@pointermove=${this.handlePointerMove}
|
|
960
|
+
@pointerup=${this.handlePointerUp}
|
|
961
|
+
></div>
|
|
962
|
+
<div part="end" ?data-dragging=${this.dragging}>
|
|
963
|
+
<slot name="end"></slot>
|
|
964
|
+
</div>
|
|
965
|
+
${this.crossings.map((crossing, index) => html `<div
|
|
966
|
+
part="corner"
|
|
967
|
+
role="separator"
|
|
968
|
+
tabindex="0"
|
|
969
|
+
aria-label=${this.cornerLabel}
|
|
970
|
+
aria-orientation=${crossing.by.vertical ? 'horizontal' : 'vertical'}
|
|
971
|
+
aria-valuemax="100"
|
|
972
|
+
aria-valuemin="0"
|
|
973
|
+
aria-valuenow=${Math.round(crossing.at)}
|
|
974
|
+
data-cross=${index}
|
|
975
|
+
style="--splitter-corner-at: ${crossing.at}%; --splitter-position: ${position}%"
|
|
976
|
+
@dblclick=${this.handleCornerDoubleClick}
|
|
977
|
+
@keydown=${this.handleCornerKeydown}
|
|
978
|
+
@pointercancel=${this.handleCornerUp}
|
|
979
|
+
@pointerdown=${this.handleCornerDown}
|
|
980
|
+
@pointermove=${this.handleCornerMove}
|
|
981
|
+
@pointerup=${this.handleCornerUp}
|
|
982
|
+
></div>`)}`;
|
|
983
|
+
}
|
|
984
|
+
};
|
|
985
|
+
__decorate([
|
|
986
|
+
property({ reflect: true })
|
|
987
|
+
], HelixHeadlessSplitter.prototype, "orientation", void 0);
|
|
988
|
+
__decorate([
|
|
989
|
+
property({ type: Number })
|
|
990
|
+
], HelixHeadlessSplitter.prototype, "position", null);
|
|
991
|
+
__decorate([
|
|
992
|
+
property({ attribute: 'default-position', type: Number })
|
|
993
|
+
], HelixHeadlessSplitter.prototype, "defaultPosition", void 0);
|
|
994
|
+
__decorate([
|
|
995
|
+
property()
|
|
996
|
+
], HelixHeadlessSplitter.prototype, "collapsed", null);
|
|
997
|
+
__decorate([
|
|
998
|
+
property({ attribute: 'default-collapsed' })
|
|
999
|
+
], HelixHeadlessSplitter.prototype, "defaultCollapsed", void 0);
|
|
1000
|
+
__decorate([
|
|
1001
|
+
property({ attribute: 'collapsed-size', type: Number })
|
|
1002
|
+
], HelixHeadlessSplitter.prototype, "collapsedSize", void 0);
|
|
1003
|
+
__decorate([
|
|
1004
|
+
property()
|
|
1005
|
+
], HelixHeadlessSplitter.prototype, "min", void 0);
|
|
1006
|
+
__decorate([
|
|
1007
|
+
property()
|
|
1008
|
+
], HelixHeadlessSplitter.prototype, "max", void 0);
|
|
1009
|
+
__decorate([
|
|
1010
|
+
property({ type: Number })
|
|
1011
|
+
], HelixHeadlessSplitter.prototype, "step", void 0);
|
|
1012
|
+
__decorate([
|
|
1013
|
+
property()
|
|
1014
|
+
], HelixHeadlessSplitter.prototype, "label", void 0);
|
|
1015
|
+
__decorate([
|
|
1016
|
+
property({ attribute: 'corner-label' })
|
|
1017
|
+
], HelixHeadlessSplitter.prototype, "cornerLabel", void 0);
|
|
1018
|
+
__decorate([
|
|
1019
|
+
state()
|
|
1020
|
+
], HelixHeadlessSplitter.prototype, "reached", void 0);
|
|
1021
|
+
__decorate([
|
|
1022
|
+
state()
|
|
1023
|
+
], HelixHeadlessSplitter.prototype, "dragging", void 0);
|
|
1024
|
+
__decorate([
|
|
1025
|
+
state()
|
|
1026
|
+
], HelixHeadlessSplitter.prototype, "stacked", void 0);
|
|
1027
|
+
HelixHeadlessSplitter = HelixHeadlessSplitter_1 = __decorate([
|
|
1028
|
+
customElement('helix-headless-splitter')
|
|
1029
|
+
], HelixHeadlessSplitter);
|
|
1030
|
+
export { HelixHeadlessSplitter };
|