@k2b/ui 0.21.0 → 0.23.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/dist/browser/actions/ContextMenu.js +3 -1
- package/dist/browser/actions/ContextMenu.js.map +1 -1
- package/dist/browser/actions/FilterChip.js +3 -1
- package/dist/browser/actions/FilterChip.js.map +1 -1
- package/dist/browser/actions/SpotlightSearch.js +3 -1
- package/dist/browser/actions/SpotlightSearch.js.map +1 -1
- package/dist/browser/actions/filter-messages.js +20 -0
- package/dist/browser/actions/filter-messages.js.map +1 -0
- package/dist/browser/actions/spotlight-messages.js +16 -0
- package/dist/browser/actions/spotlight-messages.js.map +1 -0
- package/dist/browser/chat/ChatComposer.js +47 -41
- package/dist/browser/chat/ChatComposer.js.map +1 -1
- package/dist/browser/chat/ChatPrimitives.js +25 -23
- package/dist/browser/chat/ChatPrimitives.js.map +1 -1
- package/dist/browser/chat/ChatRoot.js +3 -3
- package/dist/browser/chat/ChatRoot.js.map +1 -1
- package/dist/browser/chat/ChatTimeline.js +12 -12
- package/dist/browser/chat/ChatTimeline.js.map +1 -1
- package/dist/browser/chat/chat-messages.js +236 -0
- package/dist/browser/chat/chat-messages.js.map +1 -0
- package/dist/browser/content/Calendar.js +1096 -1060
- package/dist/browser/content/Calendar.js.map +1 -1
- package/dist/browser/content/CalendarDayView.js +1187 -0
- package/dist/browser/content/CalendarDayView.js.map +1 -0
- package/dist/browser/content/CalendarWeekView.js +1571 -0
- package/dist/browser/content/CalendarWeekView.js.map +1 -0
- package/dist/browser/content/Chart.js +15 -8
- package/dist/browser/content/Chart.js.map +1 -1
- package/dist/browser/content/ChartExplorer.js +185 -85
- package/dist/browser/content/ChartExplorer.js.map +1 -1
- package/dist/browser/content/ChartExplorerControls.js +9 -7
- package/dist/browser/content/ChartExplorerControls.js.map +1 -1
- package/dist/browser/content/ChartFilterControls.js +93 -34
- package/dist/browser/content/ChartFilterControls.js.map +1 -1
- package/dist/browser/content/ChartSnapshotView.js +3 -3
- package/dist/browser/content/ChartSnapshotView.js.map +1 -1
- package/dist/browser/content/DataTable.js +238 -201
- package/dist/browser/content/DataTable.js.map +1 -1
- package/dist/browser/content/Docs.js +3 -1
- package/dist/browser/content/Docs.js.map +1 -1
- package/dist/browser/content/FileBrowser.js +30 -26
- package/dist/browser/content/FileBrowser.js.map +1 -1
- package/dist/browser/content/FileTree.js +9 -7
- package/dist/browser/content/FileTree.js.map +1 -1
- package/dist/browser/content/FileView.js +37 -28
- package/dist/browser/content/FileView.js.map +1 -1
- package/dist/browser/content/Lightbox.js +9 -7
- package/dist/browser/content/Lightbox.js.map +1 -1
- package/dist/browser/content/LogEntriesTable.js +3 -3
- package/dist/browser/content/LogEntriesTable.js.map +1 -1
- package/dist/browser/content/MessageRow.js +24 -22
- package/dist/browser/content/MessageRow.js.map +1 -1
- package/dist/browser/content/Pagination.js +7 -7
- package/dist/browser/content/Pagination.js.map +1 -1
- package/dist/browser/content/PdfPreview.js +15 -13
- package/dist/browser/content/PdfPreview.js.map +1 -1
- package/dist/browser/content/RangePicker.js +3 -1
- package/dist/browser/content/RangePicker.js.map +1 -1
- package/dist/browser/content/StructuredDataPreview.js +3 -1
- package/dist/browser/content/StructuredDataPreview.js.map +1 -1
- package/dist/browser/content/Timeline.js +13 -11
- package/dist/browser/content/Timeline.js.map +1 -1
- package/dist/browser/content/VideoPlayer.js +5 -5
- package/dist/browser/content/VideoPlayer.js.map +1 -1
- package/dist/browser/content/VirtualFeed.js +6 -4
- package/dist/browser/content/VirtualFeed.js.map +1 -1
- package/dist/browser/content/ZoomPanViewport.js +10 -7
- package/dist/browser/content/ZoomPanViewport.js.map +1 -1
- package/dist/browser/content/calendar-day-scroll.js +98 -0
- package/dist/browser/content/calendar-day-scroll.js.map +1 -0
- package/dist/browser/content/calendar-days.js +408 -0
- package/dist/browser/content/calendar-days.js.map +1 -0
- package/dist/browser/content/calendar-dialogs.js +236 -0
- package/dist/browser/content/calendar-dialogs.js.map +1 -0
- package/dist/browser/content/calendar-messages.js +249 -3
- package/dist/browser/content/calendar-messages.js.map +1 -1
- package/dist/browser/content/calendar-pointer.js +19 -6
- package/dist/browser/content/calendar-pointer.js.map +1 -1
- package/dist/browser/content/calendar-shared.js +328 -0
- package/dist/browser/content/calendar-shared.js.map +1 -0
- package/dist/browser/content/calendar-time-view.js +1649 -0
- package/dist/browser/content/calendar-time-view.js.map +1 -0
- package/dist/browser/content/chart-messages.js +146 -0
- package/dist/browser/content/chart-messages.js.map +1 -0
- package/dist/browser/content/collection-selection.js +2 -0
- package/dist/browser/content/collection-selection.js.map +1 -1
- package/dist/browser/content/data-table-messages.js +24 -0
- package/dist/browser/content/data-table-messages.js.map +1 -0
- package/dist/browser/content/docs-messages.js +24 -0
- package/dist/browser/content/docs-messages.js.map +1 -0
- package/dist/browser/content/feed-messages.js +34 -0
- package/dist/browser/content/feed-messages.js.map +1 -0
- package/dist/browser/content/file-browser-messages.js +69 -0
- package/dist/browser/content/file-browser-messages.js.map +1 -0
- package/dist/browser/content/file-view-messages.js +64 -0
- package/dist/browser/content/file-view-messages.js.map +1 -0
- package/dist/browser/content/index.js.map +1 -1
- package/dist/browser/content/lightbox-messages.js +36 -0
- package/dist/browser/content/lightbox-messages.js.map +1 -0
- package/dist/browser/content/log-entries-messages.js +20 -0
- package/dist/browser/content/log-entries-messages.js.map +1 -0
- package/dist/browser/content/markdown-info-block-messages.js +24 -0
- package/dist/browser/content/markdown-info-block-messages.js.map +1 -0
- package/dist/browser/content/markdown-info-blocks.js +3 -3
- package/dist/browser/content/markdown-info-blocks.js.map +1 -1
- package/dist/browser/content/markdown-links.js +2 -2
- package/dist/browser/content/markdown-links.js.map +1 -1
- package/dist/browser/content/markdown-reference-messages.js +30 -0
- package/dist/browser/content/markdown-reference-messages.js.map +1 -0
- package/dist/browser/content/pagination-messages.js +38 -0
- package/dist/browser/content/pagination-messages.js.map +1 -0
- package/dist/browser/content/pdf-messages.js +43 -0
- package/dist/browser/content/pdf-messages.js.map +1 -0
- package/dist/browser/content/range-picker-messages.js +20 -0
- package/dist/browser/content/range-picker-messages.js.map +1 -0
- package/dist/browser/content/structured-data-messages.js +22 -0
- package/dist/browser/content/structured-data-messages.js.map +1 -0
- package/dist/browser/content/timeline-messages.js +62 -0
- package/dist/browser/content/timeline-messages.js.map +1 -0
- package/dist/browser/content/video-messages.js +24 -0
- package/dist/browser/content/video-messages.js.map +1 -0
- package/dist/browser/content/viewport-messages.js +28 -0
- package/dist/browser/content/viewport-messages.js.map +1 -0
- package/dist/browser/feedback/HoverPreview.js +34 -6
- package/dist/browser/feedback/HoverPreview.js.map +1 -1
- package/dist/browser/feedback/InstallGuide.js +18 -18
- package/dist/browser/feedback/InstallGuide.js.map +1 -1
- package/dist/browser/feedback/install-messages.js +104 -0
- package/dist/browser/feedback/install-messages.js.map +1 -0
- package/dist/browser/feedback/prompt-messages.js +65 -0
- package/dist/browser/feedback/prompt-messages.js.map +1 -0
- package/dist/browser/feedback/prompts.js +14 -11
- package/dist/browser/feedback/prompts.js.map +1 -1
- package/dist/browser/feedback/toast-messages.js +18 -0
- package/dist/browser/feedback/toast-messages.js.map +1 -0
- package/dist/browser/feedback/toast.js +4 -3
- package/dist/browser/feedback/toast.js.map +1 -1
- package/dist/browser/index.js +1 -1
- package/dist/browser/index.js.map +1 -1
- package/dist/browser/inputs/AutocompleteEditor.js +6 -4
- package/dist/browser/inputs/AutocompleteEditor.js.map +1 -1
- package/dist/browser/inputs/AutocompleteSelect.js +10 -8
- package/dist/browser/inputs/AutocompleteSelect.js.map +1 -1
- package/dist/browser/inputs/ChoiceGroups.js +4 -0
- package/dist/browser/inputs/ChoiceGroups.js.map +1 -1
- package/dist/browser/inputs/ChoiceInputs.js +5 -5
- package/dist/browser/inputs/ChoiceInputs.js.map +1 -1
- package/dist/browser/inputs/Combobox.js +3 -2
- package/dist/browser/inputs/Combobox.js.map +1 -1
- package/dist/browser/inputs/FileDropTarget.js +6 -6
- package/dist/browser/inputs/FileDropTarget.js.map +1 -1
- package/dist/browser/inputs/FileInputs.js +30 -21
- package/dist/browser/inputs/FileInputs.js.map +1 -1
- package/dist/browser/inputs/MultiSelectInput.js +7 -5
- package/dist/browser/inputs/MultiSelectInput.js.map +1 -1
- package/dist/browser/inputs/NumberInput.js +4 -2
- package/dist/browser/inputs/NumberInput.js.map +1 -1
- package/dist/browser/inputs/QrScanner.js +5 -5
- package/dist/browser/inputs/QrScanner.js.map +1 -1
- package/dist/browser/inputs/Select.js +7 -5
- package/dist/browser/inputs/Select.js.map +1 -1
- package/dist/browser/inputs/SelectChip.js +3 -3
- package/dist/browser/inputs/SelectChip.js.map +1 -1
- package/dist/browser/inputs/SignatureInput.js +9 -3
- package/dist/browser/inputs/SignatureInput.js.map +1 -1
- package/dist/browser/inputs/SpecialInputs.js +4 -2
- package/dist/browser/inputs/SpecialInputs.js.map +1 -1
- package/dist/browser/inputs/TagEditor.js +8 -6
- package/dist/browser/inputs/TagEditor.js.map +1 -1
- package/dist/browser/inputs/TagsInput.js +5 -5
- package/dist/browser/inputs/TagsInput.js.map +1 -1
- package/dist/browser/inputs/TemplateEditor.js +5 -5
- package/dist/browser/inputs/TemplateEditor.js.map +1 -1
- package/dist/browser/inputs/TextInput.js +3 -1
- package/dist/browser/inputs/TextInput.js.map +1 -1
- package/dist/browser/inputs/completion-messages.js +24 -0
- package/dist/browser/inputs/completion-messages.js.map +1 -0
- package/dist/browser/inputs/file-drop-messages.js +63 -0
- package/dist/browser/inputs/file-drop-messages.js.map +1 -0
- package/dist/browser/inputs/file-drop.js.map +1 -1
- package/dist/browser/inputs/file-input-messages.js +60 -0
- package/dist/browser/inputs/file-input-messages.js.map +1 -0
- package/dist/browser/inputs/icon-messages.js +22 -0
- package/dist/browser/inputs/icon-messages.js.map +1 -0
- package/dist/browser/inputs/input-messages.js +38 -0
- package/dist/browser/inputs/input-messages.js.map +1 -0
- package/dist/browser/inputs/markdown/MarkdownEditor.js +10 -6
- package/dist/browser/inputs/markdown/MarkdownEditor.js.map +1 -1
- package/dist/browser/inputs/markdown/Toolbar.js +13 -13
- package/dist/browser/inputs/markdown/Toolbar.js.map +1 -1
- package/dist/browser/inputs/markdown/editor-messages.js +43 -0
- package/dist/browser/inputs/markdown/editor-messages.js.map +1 -0
- package/dist/browser/inputs/markdown/toolbar-messages.js +40 -0
- package/dist/browser/inputs/markdown/toolbar-messages.js.map +1 -0
- package/dist/browser/inputs/qr-messages.js +26 -0
- package/dist/browser/inputs/qr-messages.js.map +1 -0
- package/dist/browser/inputs/select-messages.js +63 -0
- package/dist/browser/inputs/select-messages.js.map +1 -0
- package/dist/browser/inputs/tag-messages.js +44 -0
- package/dist/browser/inputs/tag-messages.js.map +1 -0
- package/dist/browser/inputs/template-messages.js +22 -0
- package/dist/browser/inputs/template-messages.js.map +1 -0
- package/dist/browser/internal/render-error-messages.js +20 -0
- package/dist/browser/internal/render-error-messages.js.map +1 -0
- package/dist/browser/internal/render-error.js +3 -1
- package/dist/browser/internal/render-error.js.map +1 -1
- package/dist/browser/internal/text-selection.js +101 -0
- package/dist/browser/internal/text-selection.js.map +1 -0
- package/dist/browser/intl/messages.js +6 -1155
- package/dist/browser/intl/messages.js.map +1 -1
- package/dist/browser/layout/AppWorkspace.js +594 -425
- package/dist/browser/layout/AppWorkspace.js.map +1 -1
- package/dist/browser/layout/BottomSheet.js +6 -1
- package/dist/browser/layout/BottomSheet.js.map +1 -1
- package/dist/browser/layout/Discussion.js +8 -5
- package/dist/browser/layout/Discussion.js.map +1 -1
- package/dist/browser/layout/FloatingWindow.js +8 -5
- package/dist/browser/layout/FloatingWindow.js.map +1 -1
- package/dist/browser/layout/Navigation.js +7 -6
- package/dist/browser/layout/Navigation.js.map +1 -1
- package/dist/browser/layout/PageTitle.js +373 -0
- package/dist/browser/layout/PageTitle.js.map +1 -0
- package/dist/browser/layout/PanelDialog.js +8 -6
- package/dist/browser/layout/PanelDialog.js.map +1 -1
- package/dist/browser/layout/Panes.js +23 -15
- package/dist/browser/layout/Panes.js.map +1 -1
- package/dist/browser/layout/PullToRefresh.js +13 -4
- package/dist/browser/layout/PullToRefresh.js.map +1 -1
- package/dist/browser/layout/Settings.js +14 -12
- package/dist/browser/layout/Settings.js.map +1 -1
- package/dist/browser/layout/SettingsCollection.js +6 -5
- package/dist/browser/layout/SettingsCollection.js.map +1 -1
- package/dist/browser/layout/SettingsModal.js +3 -1
- package/dist/browser/layout/SettingsModal.js.map +1 -1
- package/dist/browser/layout/app-workspace-controller.js +821 -12
- package/dist/browser/layout/app-workspace-controller.js.map +1 -1
- package/dist/browser/layout/app-workspace-state.js +3 -2
- package/dist/browser/layout/app-workspace-state.js.map +1 -1
- package/dist/browser/layout/floating-window-messages.js +28 -0
- package/dist/browser/layout/floating-window-messages.js.map +1 -0
- package/dist/browser/layout/index.js +2 -0
- package/dist/browser/layout/index.js.map +1 -1
- package/dist/browser/layout/navigation-model.js.map +1 -1
- package/dist/browser/layout/page-title-controller.js +169 -0
- package/dist/browser/layout/page-title-controller.js.map +1 -0
- package/dist/browser/layout/panel-dialog-messages.js +20 -0
- package/dist/browser/layout/panel-dialog-messages.js.map +1 -0
- package/dist/browser/layout/panes-messages.js +48 -0
- package/dist/browser/layout/panes-messages.js.map +1 -0
- package/dist/browser/layout/refresh-messages.js +20 -0
- package/dist/browser/layout/refresh-messages.js.map +1 -0
- package/dist/browser/layout/settings-messages.js +54 -0
- package/dist/browser/layout/settings-messages.js.map +1 -0
- package/dist/browser/layout/workspace-messages.js +56 -0
- package/dist/browser/layout/workspace-messages.js.map +1 -0
- package/dist/browser/surfaces/Avatar.js +5 -5
- package/dist/browser/surfaces/Avatar.js.map +1 -1
- package/dist/browser/surfaces/ResourceCard.js +4 -2
- package/dist/browser/surfaces/ResourceCard.js.map +1 -1
- package/dist/browser/surfaces/StatCell.js +18 -6
- package/dist/browser/surfaces/StatCell.js.map +1 -1
- package/dist/browser/surfaces/Tag.js +3 -3
- package/dist/browser/surfaces/Tag.js.map +1 -1
- package/dist/browser/surfaces/avatar-messages.js +26 -0
- package/dist/browser/surfaces/avatar-messages.js.map +1 -0
- package/dist/browser/surfaces/resource-messages.js +26 -0
- package/dist/browser/surfaces/resource-messages.js.map +1 -0
- package/dist/browser/widgets/Widget.js +6 -0
- package/dist/browser/widgets/Widget.js.map +1 -1
- package/dist/ssr/actions/ContextMenu.js.map +1 -1
- package/dist/ssr/actions/FilterChip.js +3 -1
- package/dist/ssr/actions/FilterChip.js.map +1 -1
- package/dist/ssr/actions/SpotlightSearch.js +3 -1
- package/dist/ssr/actions/SpotlightSearch.js.map +1 -1
- package/dist/ssr/actions/filter-messages.js +20 -0
- package/dist/ssr/actions/filter-messages.js.map +1 -0
- package/dist/ssr/actions/spotlight-messages.js +16 -0
- package/dist/ssr/actions/spotlight-messages.js.map +1 -0
- package/dist/ssr/chat/ChatComposer.js +47 -41
- package/dist/ssr/chat/ChatComposer.js.map +1 -1
- package/dist/ssr/chat/ChatPrimitives.js +23 -21
- package/dist/ssr/chat/ChatPrimitives.js.map +1 -1
- package/dist/ssr/chat/ChatRoot.js +3 -3
- package/dist/ssr/chat/ChatRoot.js.map +1 -1
- package/dist/ssr/chat/ChatTimeline.js +11 -11
- package/dist/ssr/chat/ChatTimeline.js.map +1 -1
- package/dist/ssr/chat/chat-messages.js +236 -0
- package/dist/ssr/chat/chat-messages.js.map +1 -0
- package/dist/ssr/content/Calendar.js +534 -346
- package/dist/ssr/content/Calendar.js.map +1 -1
- package/dist/ssr/content/CalendarDayView.js +800 -0
- package/dist/ssr/content/CalendarDayView.js.map +1 -0
- package/dist/ssr/content/CalendarWeekView.js +1069 -0
- package/dist/ssr/content/CalendarWeekView.js.map +1 -0
- package/dist/ssr/content/Chart.js +12 -5
- package/dist/ssr/content/Chart.js.map +1 -1
- package/dist/ssr/content/ChartExplorer.js +98 -37
- package/dist/ssr/content/ChartExplorer.js.map +1 -1
- package/dist/ssr/content/ChartExplorerControls.js +9 -7
- package/dist/ssr/content/ChartExplorerControls.js.map +1 -1
- package/dist/ssr/content/ChartFilterControls.js +52 -8
- package/dist/ssr/content/ChartFilterControls.js.map +1 -1
- package/dist/ssr/content/ChartSnapshotView.js +3 -3
- package/dist/ssr/content/ChartSnapshotView.js.map +1 -1
- package/dist/ssr/content/DataTable.js +77 -53
- package/dist/ssr/content/DataTable.js.map +1 -1
- package/dist/ssr/content/Docs.js +3 -1
- package/dist/ssr/content/Docs.js.map +1 -1
- package/dist/ssr/content/FileBrowser.js +30 -26
- package/dist/ssr/content/FileBrowser.js.map +1 -1
- package/dist/ssr/content/FileTree.js +9 -7
- package/dist/ssr/content/FileTree.js.map +1 -1
- package/dist/ssr/content/FileView.js +37 -28
- package/dist/ssr/content/FileView.js.map +1 -1
- package/dist/ssr/content/Lightbox.js +8 -6
- package/dist/ssr/content/Lightbox.js.map +1 -1
- package/dist/ssr/content/LogEntriesTable.js +3 -3
- package/dist/ssr/content/LogEntriesTable.js.map +1 -1
- package/dist/ssr/content/MessageRow.js +24 -22
- package/dist/ssr/content/MessageRow.js.map +1 -1
- package/dist/ssr/content/Pagination.js +6 -6
- package/dist/ssr/content/Pagination.js.map +1 -1
- package/dist/ssr/content/PdfPreview.js +15 -13
- package/dist/ssr/content/PdfPreview.js.map +1 -1
- package/dist/ssr/content/RangePicker.js +3 -1
- package/dist/ssr/content/RangePicker.js.map +1 -1
- package/dist/ssr/content/StructuredDataPreview.js +3 -1
- package/dist/ssr/content/StructuredDataPreview.js.map +1 -1
- package/dist/ssr/content/Timeline.js +13 -11
- package/dist/ssr/content/Timeline.js.map +1 -1
- package/dist/ssr/content/VideoPlayer.js +5 -5
- package/dist/ssr/content/VideoPlayer.js.map +1 -1
- package/dist/ssr/content/VirtualFeed.js +6 -4
- package/dist/ssr/content/VirtualFeed.js.map +1 -1
- package/dist/ssr/content/ZoomPanViewport.js +7 -4
- package/dist/ssr/content/ZoomPanViewport.js.map +1 -1
- package/dist/ssr/content/calendar-day-scroll.js +98 -0
- package/dist/ssr/content/calendar-day-scroll.js.map +1 -0
- package/dist/ssr/content/calendar-days.js +408 -0
- package/dist/ssr/content/calendar-days.js.map +1 -0
- package/dist/ssr/content/calendar-dialogs.js +159 -0
- package/dist/ssr/content/calendar-dialogs.js.map +1 -0
- package/dist/ssr/content/calendar-messages.js +249 -3
- package/dist/ssr/content/calendar-messages.js.map +1 -1
- package/dist/ssr/content/calendar-pointer.js +19 -6
- package/dist/ssr/content/calendar-pointer.js.map +1 -1
- package/dist/ssr/content/calendar-shared.js +261 -0
- package/dist/ssr/content/calendar-shared.js.map +1 -0
- package/dist/ssr/content/calendar-time-view.js +1306 -0
- package/dist/ssr/content/calendar-time-view.js.map +1 -0
- package/dist/ssr/content/chart-messages.js +146 -0
- package/dist/ssr/content/chart-messages.js.map +1 -0
- package/dist/ssr/content/collection-selection.js +2 -0
- package/dist/ssr/content/collection-selection.js.map +1 -1
- package/dist/ssr/content/data-table-messages.js +24 -0
- package/dist/ssr/content/data-table-messages.js.map +1 -0
- package/dist/ssr/content/docs-messages.js +24 -0
- package/dist/ssr/content/docs-messages.js.map +1 -0
- package/dist/ssr/content/feed-messages.js +34 -0
- package/dist/ssr/content/feed-messages.js.map +1 -0
- package/dist/ssr/content/file-browser-messages.js +69 -0
- package/dist/ssr/content/file-browser-messages.js.map +1 -0
- package/dist/ssr/content/file-view-messages.js +64 -0
- package/dist/ssr/content/file-view-messages.js.map +1 -0
- package/dist/ssr/content/index.js.map +1 -1
- package/dist/ssr/content/lightbox-messages.js +36 -0
- package/dist/ssr/content/lightbox-messages.js.map +1 -0
- package/dist/ssr/content/log-entries-messages.js +20 -0
- package/dist/ssr/content/log-entries-messages.js.map +1 -0
- package/dist/ssr/content/markdown-info-block-messages.js +24 -0
- package/dist/ssr/content/markdown-info-block-messages.js.map +1 -0
- package/dist/ssr/content/markdown-info-blocks.js +3 -3
- package/dist/ssr/content/markdown-info-blocks.js.map +1 -1
- package/dist/ssr/content/markdown-links.js +2 -2
- package/dist/ssr/content/markdown-links.js.map +1 -1
- package/dist/ssr/content/markdown-reference-messages.js +30 -0
- package/dist/ssr/content/markdown-reference-messages.js.map +1 -0
- package/dist/ssr/content/pagination-messages.js +38 -0
- package/dist/ssr/content/pagination-messages.js.map +1 -0
- package/dist/ssr/content/pdf-messages.js +43 -0
- package/dist/ssr/content/pdf-messages.js.map +1 -0
- package/dist/ssr/content/range-picker-messages.js +20 -0
- package/dist/ssr/content/range-picker-messages.js.map +1 -0
- package/dist/ssr/content/structured-data-messages.js +22 -0
- package/dist/ssr/content/structured-data-messages.js.map +1 -0
- package/dist/ssr/content/timeline-messages.js +62 -0
- package/dist/ssr/content/timeline-messages.js.map +1 -0
- package/dist/ssr/content/video-messages.js +24 -0
- package/dist/ssr/content/video-messages.js.map +1 -0
- package/dist/ssr/content/viewport-messages.js +28 -0
- package/dist/ssr/content/viewport-messages.js.map +1 -0
- package/dist/ssr/feedback/HoverPreview.js +34 -6
- package/dist/ssr/feedback/HoverPreview.js.map +1 -1
- package/dist/ssr/feedback/InstallGuide.js +18 -18
- package/dist/ssr/feedback/InstallGuide.js.map +1 -1
- package/dist/ssr/feedback/install-messages.js +104 -0
- package/dist/ssr/feedback/install-messages.js.map +1 -0
- package/dist/ssr/feedback/prompt-messages.js +65 -0
- package/dist/ssr/feedback/prompt-messages.js.map +1 -0
- package/dist/ssr/feedback/prompts.js +14 -11
- package/dist/ssr/feedback/prompts.js.map +1 -1
- package/dist/ssr/feedback/toast-messages.js +18 -0
- package/dist/ssr/feedback/toast-messages.js.map +1 -0
- package/dist/ssr/feedback/toast.js +4 -3
- package/dist/ssr/feedback/toast.js.map +1 -1
- package/dist/ssr/index.js +1 -1
- package/dist/ssr/index.js.map +1 -1
- package/dist/ssr/inputs/AutocompleteEditor.js +5 -3
- package/dist/ssr/inputs/AutocompleteEditor.js.map +1 -1
- package/dist/ssr/inputs/AutocompleteSelect.js +10 -8
- package/dist/ssr/inputs/AutocompleteSelect.js.map +1 -1
- package/dist/ssr/inputs/ChoiceGroups.js +4 -0
- package/dist/ssr/inputs/ChoiceGroups.js.map +1 -1
- package/dist/ssr/inputs/ChoiceInputs.js +5 -5
- package/dist/ssr/inputs/ChoiceInputs.js.map +1 -1
- package/dist/ssr/inputs/Combobox.js +3 -1
- package/dist/ssr/inputs/Combobox.js.map +1 -1
- package/dist/ssr/inputs/FileDropTarget.js +6 -6
- package/dist/ssr/inputs/FileDropTarget.js.map +1 -1
- package/dist/ssr/inputs/FileInputs.js +29 -20
- package/dist/ssr/inputs/FileInputs.js.map +1 -1
- package/dist/ssr/inputs/MultiSelectInput.js +7 -5
- package/dist/ssr/inputs/MultiSelectInput.js.map +1 -1
- package/dist/ssr/inputs/NumberInput.js +4 -2
- package/dist/ssr/inputs/NumberInput.js.map +1 -1
- package/dist/ssr/inputs/QrScanner.js +4 -4
- package/dist/ssr/inputs/QrScanner.js.map +1 -1
- package/dist/ssr/inputs/Select.js +7 -5
- package/dist/ssr/inputs/Select.js.map +1 -1
- package/dist/ssr/inputs/SelectChip.js +3 -3
- package/dist/ssr/inputs/SelectChip.js.map +1 -1
- package/dist/ssr/inputs/SignatureInput.js +9 -3
- package/dist/ssr/inputs/SignatureInput.js.map +1 -1
- package/dist/ssr/inputs/SpecialInputs.js +4 -2
- package/dist/ssr/inputs/SpecialInputs.js.map +1 -1
- package/dist/ssr/inputs/TagEditor.js +8 -6
- package/dist/ssr/inputs/TagEditor.js.map +1 -1
- package/dist/ssr/inputs/TagsInput.js +5 -5
- package/dist/ssr/inputs/TagsInput.js.map +1 -1
- package/dist/ssr/inputs/TemplateEditor.js +5 -5
- package/dist/ssr/inputs/TemplateEditor.js.map +1 -1
- package/dist/ssr/inputs/TextInput.js +3 -1
- package/dist/ssr/inputs/TextInput.js.map +1 -1
- package/dist/ssr/inputs/completion-messages.js +24 -0
- package/dist/ssr/inputs/completion-messages.js.map +1 -0
- package/dist/ssr/inputs/file-drop-messages.js +63 -0
- package/dist/ssr/inputs/file-drop-messages.js.map +1 -0
- package/dist/ssr/inputs/file-drop.js.map +1 -1
- package/dist/ssr/inputs/file-input-messages.js +60 -0
- package/dist/ssr/inputs/file-input-messages.js.map +1 -0
- package/dist/ssr/inputs/icon-messages.js +22 -0
- package/dist/ssr/inputs/icon-messages.js.map +1 -0
- package/dist/ssr/inputs/input-messages.js +38 -0
- package/dist/ssr/inputs/input-messages.js.map +1 -0
- package/dist/ssr/inputs/markdown/MarkdownEditor.js +9 -5
- package/dist/ssr/inputs/markdown/MarkdownEditor.js.map +1 -1
- package/dist/ssr/inputs/markdown/Toolbar.js +13 -13
- package/dist/ssr/inputs/markdown/Toolbar.js.map +1 -1
- package/dist/ssr/inputs/markdown/editor-messages.js +43 -0
- package/dist/ssr/inputs/markdown/editor-messages.js.map +1 -0
- package/dist/ssr/inputs/markdown/toolbar-messages.js +40 -0
- package/dist/ssr/inputs/markdown/toolbar-messages.js.map +1 -0
- package/dist/ssr/inputs/qr-messages.js +26 -0
- package/dist/ssr/inputs/qr-messages.js.map +1 -0
- package/dist/ssr/inputs/select-messages.js +63 -0
- package/dist/ssr/inputs/select-messages.js.map +1 -0
- package/dist/ssr/inputs/tag-messages.js +44 -0
- package/dist/ssr/inputs/tag-messages.js.map +1 -0
- package/dist/ssr/inputs/template-messages.js +22 -0
- package/dist/ssr/inputs/template-messages.js.map +1 -0
- package/dist/ssr/internal/render-error-messages.js +20 -0
- package/dist/ssr/internal/render-error-messages.js.map +1 -0
- package/dist/ssr/internal/render-error.js +3 -1
- package/dist/ssr/internal/render-error.js.map +1 -1
- package/dist/ssr/internal/text-selection.js +101 -0
- package/dist/ssr/internal/text-selection.js.map +1 -0
- package/dist/ssr/intl/messages.js +6 -1155
- package/dist/ssr/intl/messages.js.map +1 -1
- package/dist/ssr/layout/AppWorkspace.js +219 -103
- package/dist/ssr/layout/AppWorkspace.js.map +1 -1
- package/dist/ssr/layout/BottomSheet.js +1 -0
- package/dist/ssr/layout/BottomSheet.js.map +1 -1
- package/dist/ssr/layout/Discussion.js +8 -5
- package/dist/ssr/layout/Discussion.js.map +1 -1
- package/dist/ssr/layout/FloatingWindow.js +8 -5
- package/dist/ssr/layout/FloatingWindow.js.map +1 -1
- package/dist/ssr/layout/Navigation.js +6 -5
- package/dist/ssr/layout/Navigation.js.map +1 -1
- package/dist/ssr/layout/PageTitle.js +256 -0
- package/dist/ssr/layout/PageTitle.js.map +1 -0
- package/dist/ssr/layout/PanelDialog.js +8 -6
- package/dist/ssr/layout/PanelDialog.js.map +1 -1
- package/dist/ssr/layout/Panes.js +22 -14
- package/dist/ssr/layout/Panes.js.map +1 -1
- package/dist/ssr/layout/PullToRefresh.js +13 -4
- package/dist/ssr/layout/PullToRefresh.js.map +1 -1
- package/dist/ssr/layout/Settings.js +14 -12
- package/dist/ssr/layout/Settings.js.map +1 -1
- package/dist/ssr/layout/SettingsCollection.js +6 -5
- package/dist/ssr/layout/SettingsCollection.js.map +1 -1
- package/dist/ssr/layout/SettingsModal.js +3 -1
- package/dist/ssr/layout/SettingsModal.js.map +1 -1
- package/dist/ssr/layout/app-workspace-controller.js +821 -12
- package/dist/ssr/layout/app-workspace-controller.js.map +1 -1
- package/dist/ssr/layout/app-workspace-state.js +3 -2
- package/dist/ssr/layout/app-workspace-state.js.map +1 -1
- package/dist/ssr/layout/floating-window-messages.js +28 -0
- package/dist/ssr/layout/floating-window-messages.js.map +1 -0
- package/dist/ssr/layout/index.js +2 -0
- package/dist/ssr/layout/index.js.map +1 -1
- package/dist/ssr/layout/navigation-model.js.map +1 -1
- package/dist/ssr/layout/page-title-controller.js +169 -0
- package/dist/ssr/layout/page-title-controller.js.map +1 -0
- package/dist/ssr/layout/panel-dialog-messages.js +20 -0
- package/dist/ssr/layout/panel-dialog-messages.js.map +1 -0
- package/dist/ssr/layout/panes-messages.js +48 -0
- package/dist/ssr/layout/panes-messages.js.map +1 -0
- package/dist/ssr/layout/refresh-messages.js +20 -0
- package/dist/ssr/layout/refresh-messages.js.map +1 -0
- package/dist/ssr/layout/settings-messages.js +54 -0
- package/dist/ssr/layout/settings-messages.js.map +1 -0
- package/dist/ssr/layout/workspace-messages.js +56 -0
- package/dist/ssr/layout/workspace-messages.js.map +1 -0
- package/dist/ssr/surfaces/Avatar.js +5 -5
- package/dist/ssr/surfaces/Avatar.js.map +1 -1
- package/dist/ssr/surfaces/ResourceCard.js +4 -2
- package/dist/ssr/surfaces/ResourceCard.js.map +1 -1
- package/dist/ssr/surfaces/StatCell.js +2 -2
- package/dist/ssr/surfaces/StatCell.js.map +1 -1
- package/dist/ssr/surfaces/Tag.js +3 -3
- package/dist/ssr/surfaces/Tag.js.map +1 -1
- package/dist/ssr/surfaces/avatar-messages.js +26 -0
- package/dist/ssr/surfaces/avatar-messages.js.map +1 -0
- package/dist/ssr/surfaces/resource-messages.js +26 -0
- package/dist/ssr/surfaces/resource-messages.js.map +1 -0
- package/dist/ssr/widgets/Widget.js +6 -0
- package/dist/ssr/widgets/Widget.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/types/actions/filter-messages.d.ts +8 -0
- package/dist/types/actions/spotlight-messages.d.ts +8 -0
- package/dist/types/chat/chat-messages.d.ts +116 -0
- package/dist/types/content/Calendar.d.ts +91 -0
- package/dist/types/content/CalendarDayView.d.ts +7 -0
- package/dist/types/content/CalendarWeekView.d.ts +7 -0
- package/dist/types/content/ChartExplorer.d.ts +36 -1
- package/dist/types/content/ChartFilterControls.d.ts +6 -1
- package/dist/types/content/DataTable.d.ts +7 -0
- package/dist/types/content/FileView.d.ts +0 -10
- package/dist/types/content/calendar-day-scroll.d.ts +42 -0
- package/dist/types/content/calendar-days.d.ts +192 -0
- package/dist/types/content/calendar-dialogs.d.ts +22 -0
- package/dist/types/content/calendar-messages.d.ts +119 -1
- package/dist/types/content/calendar-pointer.d.ts +9 -0
- package/dist/types/content/calendar-shared.d.ts +69 -0
- package/dist/types/content/calendar-time-view.d.ts +252 -0
- package/dist/types/content/chart-messages.d.ts +37 -0
- package/dist/types/content/data-table-messages.d.ts +10 -0
- package/dist/types/content/docs-messages.d.ts +10 -0
- package/dist/types/content/feed-messages.d.ts +15 -0
- package/dist/types/content/file-browser-messages.d.ts +33 -0
- package/dist/types/content/file-view-messages.d.ts +30 -0
- package/dist/types/content/index.d.ts +2 -2
- package/dist/types/content/lightbox-messages.d.ts +16 -0
- package/dist/types/content/log-entries-messages.d.ts +8 -0
- package/dist/types/content/markdown-info-block-messages.d.ts +12 -0
- package/dist/types/content/markdown-reference-messages.d.ts +15 -0
- package/dist/types/content/pagination-messages.d.ts +17 -0
- package/dist/types/content/pdf-messages.d.ts +20 -0
- package/dist/types/content/range-picker-messages.d.ts +8 -0
- package/dist/types/content/structured-data-messages.d.ts +9 -0
- package/dist/types/content/timeline-messages.d.ts +29 -0
- package/dist/types/content/video-messages.d.ts +10 -0
- package/dist/types/content/viewport-messages.d.ts +12 -0
- package/dist/types/feedback/install-messages.d.ts +50 -0
- package/dist/types/feedback/prompt-messages.d.ts +31 -0
- package/dist/types/feedback/toast-messages.d.ts +9 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/inputs/completion-messages.d.ts +10 -0
- package/dist/types/inputs/file-drop-messages.d.ts +30 -0
- package/dist/types/inputs/file-drop.d.ts +3 -3
- package/dist/types/inputs/file-input-messages.d.ts +28 -0
- package/dist/types/inputs/icon-messages.d.ts +9 -0
- package/dist/types/inputs/input-messages.d.ts +17 -0
- package/dist/types/inputs/markdown/editor-messages.d.ts +20 -0
- package/dist/types/inputs/markdown/toolbar-messages.d.ts +18 -0
- package/dist/types/inputs/qr-messages.d.ts +11 -0
- package/dist/types/inputs/select-messages.d.ts +30 -0
- package/dist/types/inputs/tag-messages.d.ts +20 -0
- package/dist/types/inputs/template-messages.d.ts +9 -0
- package/dist/types/internal/render-error-messages.d.ts +8 -0
- package/dist/types/internal/text-selection.d.ts +18 -0
- package/dist/types/intl/messages.d.ts +3 -544
- package/dist/types/layout/AppWorkspace.d.ts +42 -5
- package/dist/types/layout/PageTitle.d.ts +65 -0
- package/dist/types/layout/app-workspace-controller.d.ts +12 -0
- package/dist/types/layout/app-workspace-state.d.ts +3 -2
- package/dist/types/layout/floating-window-messages.d.ts +12 -0
- package/dist/types/layout/index.d.ts +3 -0
- package/dist/types/layout/navigation-model.d.ts +7 -0
- package/dist/types/layout/page-title-controller.d.ts +13 -0
- package/dist/types/layout/panel-dialog-messages.d.ts +8 -0
- package/dist/types/layout/panes-messages.d.ts +22 -0
- package/dist/types/layout/refresh-messages.d.ts +8 -0
- package/dist/types/layout/settings-messages.d.ts +25 -0
- package/dist/types/layout/workspace-messages.d.ts +26 -0
- package/dist/types/surfaces/StatCell.d.ts +5 -0
- package/dist/types/surfaces/avatar-messages.d.ts +11 -0
- package/dist/types/surfaces/resource-messages.d.ts +11 -0
- package/dist/types/widgets/Widget.d.ts +5 -1
- package/package.json +1 -1
|
@@ -1,8 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { suppressTextSelection } from "../internal/text-selection";
|
|
2
|
+
import { APP_WORKSPACE_DETAIL_DEFAULT, APP_WORKSPACE_DETAIL_MAX, APP_WORKSPACE_DETAIL_MIN, APP_WORKSPACE_DRAWER_MAX, APP_WORKSPACE_DRAWER_MIN, APP_WORKSPACE_MAIN_MIN, APP_WORKSPACE_PANE_MAX, APP_WORKSPACE_PANE_MIN, APP_WORKSPACE_SIDEBAR_COLLAPSED, APP_WORKSPACE_SIDEBAR_MAX, APP_WORKSPACE_SIDEBAR_MIN, appWorkspacePanelVariable, appWorkspaceResizeLimits, fitAppWorkspacePaneSizes, normalizeAppWorkspaceLayoutState, resolveAppWorkspaceSidebarWidth, safeAppWorkspacePanelId, shouldCollapseAppWorkspaceSidebar } from "./app-workspace-state";
|
|
2
3
|
import { installScrollFades } from "./scroll-fade";
|
|
3
4
|
const HANDLE_SELECTOR = "[data-app-workspace-resize]";
|
|
4
5
|
const ROOT_SELECTOR = "[data-k2b-app-workspace]";
|
|
5
6
|
const LAYOUT_REGION_SELECTOR = [ROOT_SELECTOR, ".k2b-app-workspace__sidebar", ".k2b-app-workspace__main-pane", ".k2b-app-workspace__detail", ".k2b-app-workspace__drawer", HANDLE_SELECTOR].join(",");
|
|
7
|
+
const TOGGLE_SELECTOR = "[data-app-workspace-sidebar-toggle]";
|
|
8
|
+
/** The width range in which the sidebar is an overlay; it matches the compact media query in the stylesheet. */
|
|
9
|
+
const COMPACT_QUERY = "(min-width: 48rem) and (max-width: 63.999rem)";
|
|
10
|
+
const FOCUSABLE_SELECTOR = ["a[href]", "button:not([disabled])", "input:not([disabled]):not([type='hidden'])", "select:not([disabled])", "textarea:not([disabled])", "[tabindex]:not([tabindex='-1'])"].join(",");
|
|
11
|
+
/** Text entry, menus, dialogs, and open popups keep their own keys. */
|
|
12
|
+
const KEY_OWNER_SELECTOR = "input, textarea, select, [contenteditable]:not([contenteditable='false']), [role='textbox'], [role='combobox'], [role='searchbox'], [role='spinbutton'], [role='menu'], [role='listbox'], [role='dialog'], dialog, [aria-haspopup]:not([aria-haspopup='false'])[aria-expanded='true']";
|
|
6
13
|
const LABEL_SELECTOR = ".k2b-app-workspace__sidebar-item-label[data-marquee='true']";
|
|
7
14
|
const LABEL_TEXT_SELECTOR = ".k2b-app-workspace__sidebar-item-label-text";
|
|
8
15
|
const ITEM_SELECTOR = ".k2b-app-workspace__sidebar-item";
|
|
@@ -26,6 +33,14 @@ const sidebarHideable = root => sidebarElement(root)?.dataset.workspaceHideable
|
|
|
26
33
|
* stays application state, so the controller only requests the change.
|
|
27
34
|
*/
|
|
28
35
|
export const APP_WORKSPACE_SIDEBAR_HIDE_EVENT = "k2b-app-workspace-sidebar-hide";
|
|
36
|
+
/** Asks the owning `AppWorkspace.Detail` to close; its `onClose` decides. */
|
|
37
|
+
export const APP_WORKSPACE_DETAIL_CLOSE_EVENT = "k2b-app-workspace-detail-close";
|
|
38
|
+
/**
|
|
39
|
+
* Asks the owning Detail to step by `detail.direction` (`-1` or `1`). It writes
|
|
40
|
+
* the Main element showing the selection to `detail.item`, read synchronously
|
|
41
|
+
* by the controller after dispatch.
|
|
42
|
+
*/
|
|
43
|
+
export const APP_WORKSPACE_DETAIL_STEP_EVENT = "k2b-app-workspace-detail-step";
|
|
29
44
|
const previewSidebarHidden = (root, hidden) => {
|
|
30
45
|
const sidebar = sidebarElement(root);
|
|
31
46
|
if (!sidebar) return;
|
|
@@ -53,15 +68,17 @@ const sizeLimits = (root, handle, kind) => {
|
|
|
53
68
|
const controlled = controlledPanel(root, handle);
|
|
54
69
|
const main = kind === "pane" ? handle.closest(".k2b-app-workspace__main") : mainElement(root);
|
|
55
70
|
const panes = main ? Array.from(main.querySelectorAll(".k2b-app-workspace__main-pane")).filter(pane => pane.closest(".k2b-app-workspace__main") === main && !pane.classList.contains("is-primary") && isVisible(pane)) : [];
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
71
|
+
// Content ends before the detail track, so its width alone would shrink a
|
|
72
|
+
// persisted panel again on every reconciliation. Measure from Content's
|
|
73
|
+
// start to the workspace's inner end: this includes the detail column and
|
|
74
|
+
// leaves out a desktop sidebar, while an overlay sidebar takes no width.
|
|
75
|
+
const content = kind === "detail" ? controlled?.closest(".k2b-app-workspace__content") : null;
|
|
59
76
|
const defaultMin = kind === "sidebar" ? APP_WORKSPACE_SIDEBAR_MIN : kind === "pane" ? APP_WORKSPACE_PANE_MIN : kind === "detail" ? APP_WORKSPACE_DETAIL_MIN : APP_WORKSPACE_DRAWER_MIN;
|
|
60
77
|
const defaultMax = kind === "sidebar" ? APP_WORKSPACE_SIDEBAR_MAX : kind === "pane" ? APP_WORKSPACE_PANE_MAX : kind === "detail" ? APP_WORKSPACE_DETAIL_MAX : APP_WORKSPACE_DRAWER_MAX;
|
|
61
78
|
return appWorkspaceResizeLimits({
|
|
62
79
|
kind,
|
|
63
|
-
workspaceSize: kind === "drawer" ? root.getBoundingClientRect().height : kind === "pane" && main ? main.getBoundingClientRect().width : root.getBoundingClientRect().width,
|
|
64
|
-
reservedSize: kind === "
|
|
80
|
+
workspaceSize: kind === "drawer" ? root.getBoundingClientRect().height : kind === "pane" && main ? main.getBoundingClientRect().width : content ? root.getBoundingClientRect().right - root.clientLeft - content.getBoundingClientRect().left : root.getBoundingClientRect().width,
|
|
81
|
+
reservedSize: kind === "detail" ? 8 : kind === "pane" ? panes.reduce((total, pane) => total + (pane === controlled ? 0 : elementSize(pane, "pane")), 0) : 0,
|
|
65
82
|
min: numberData(handle, "workspaceMinSize", defaultMin),
|
|
66
83
|
max: numberData(handle, "workspaceMaxSize", defaultMax),
|
|
67
84
|
sidebarCollapsible: kind === "sidebar" && sidebarCollapsible(root)
|
|
@@ -165,8 +182,693 @@ const measureLabel = label => {
|
|
|
165
182
|
label.style.setProperty("--k2b-sidebar-label-overflow", `${overflow}px`);
|
|
166
183
|
if (overflow > 2) label.dataset.overflow = "true";else delete label.dataset.overflow;
|
|
167
184
|
};
|
|
185
|
+
|
|
186
|
+
/** An open overlay remembers the regions it made inert, so it leaves the application's own `inert` alone. */
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* The elements Tab stops at, in order. A roving tab index, as in a tree, keeps
|
|
190
|
+
* links and buttons at `tabindex="-1"`; they take focus but are no stops.
|
|
191
|
+
*/
|
|
192
|
+
const tabStopsIn = container => Array.from(container.querySelectorAll(FOCUSABLE_SELECTOR)).filter(element => element.tabIndex >= 0 && element.getClientRects().length > 0 && !element.closest("[inert]") && getComputedStyle(element).visibility !== "hidden");
|
|
193
|
+
/** Several controllers can see one click on a nested workspace's button; the innermost one, which sees it first, owns it. */
|
|
194
|
+
const claimedToggleClicks = new WeakSet();
|
|
195
|
+
const claimedDetailGestures = new WeakSet();
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* The compact overlay: from 48 to 64 rem the sidebar opens over the work area
|
|
199
|
+
* from the button in the workspace's head. While it is open the rest of
|
|
200
|
+
* the workspace is inert, Tab stays in the sidebar, and Escape, the scrim,
|
|
201
|
+
* choosing an item, hiding the sidebar, or leaving the width range close it
|
|
202
|
+
* again. The state is one attribute on the workspace root, so server-rendered
|
|
203
|
+
* and hydrated workspaces behave the same.
|
|
204
|
+
*/
|
|
205
|
+
const overlayTarget = toggle => {
|
|
206
|
+
const root = workspaceRoot(toggle);
|
|
207
|
+
// The button belongs to its workspace's own sidebar. A sidebar rendered apart
|
|
208
|
+
// from the head, for example in an island, can carry another id than the one
|
|
209
|
+
// the head named, so the button learns the real one here.
|
|
210
|
+
const sidebar = root ? sidebarElement(root) : null;
|
|
211
|
+
if (!root || !sidebar || sidebar.hidden || sidebar.dataset.mobile === "stacked") return null;
|
|
212
|
+
if (sidebar.id) toggle.setAttribute("aria-controls", sidebar.id);
|
|
213
|
+
return {
|
|
214
|
+
root,
|
|
215
|
+
sidebar,
|
|
216
|
+
toggle
|
|
217
|
+
};
|
|
218
|
+
};
|
|
219
|
+
const overlayRegions = (root, sidebar) => Array.from(root.children).flatMap(child => child instanceof HTMLElement && (child.localName === "solid-island" || child.localName === "solid-client") ? Array.from(child.children) : [child]).filter(child => child instanceof HTMLElement && child !== sidebar && !child.contains(sidebar));
|
|
168
220
|
export const installAppWorkspaceController = (options = {}) => {
|
|
169
221
|
const eventRoot = options.root ?? document;
|
|
222
|
+
// A document has no owner document; an element root listens on its own.
|
|
223
|
+
const ownerDocument = eventRoot.ownerDocument ?? document;
|
|
224
|
+
const ownerWindow = ownerDocument.defaultView ?? window;
|
|
225
|
+
let overlay = null;
|
|
226
|
+
const compact = typeof window.matchMedia === "function" ? window.matchMedia(COMPACT_QUERY) : null;
|
|
227
|
+
// A server-rendered head names the sidebar before the sidebar renders; the button learns its real id now.
|
|
228
|
+
for (const toggle of eventRoot.querySelectorAll(TOGGLE_SELECTOR)) overlayTarget(toggle);
|
|
229
|
+
const openOverlay = target => {
|
|
230
|
+
if (overlay) closeOverlay("none");
|
|
231
|
+
const inerted = overlayRegions(target.root, target.sidebar).filter(region => !region.hasAttribute("inert"));
|
|
232
|
+
overlay = {
|
|
233
|
+
...target,
|
|
234
|
+
inerted
|
|
235
|
+
};
|
|
236
|
+
target.root.dataset.sidebarOverlay = "open";
|
|
237
|
+
target.toggle.setAttribute("aria-expanded", "true");
|
|
238
|
+
inerted.forEach(region => region.setAttribute("inert", ""));
|
|
239
|
+
// Focus starts on the current destination, so the reader knows where they
|
|
240
|
+
// are: on its own tab stop, or on the tree item around it.
|
|
241
|
+
const current = target.sidebar.querySelector("[aria-current='page'], .is-active");
|
|
242
|
+
const stops = tabStopsIn(target.sidebar);
|
|
243
|
+
const first = (current && (stops.find(element => current.contains(element)) ?? stops.findLast(element => element.contains(current)))) ?? stops[0];
|
|
244
|
+
if (first) first.focus();else {
|
|
245
|
+
target.sidebar.tabIndex = -1;
|
|
246
|
+
target.sidebar.focus();
|
|
247
|
+
}
|
|
248
|
+
};
|
|
249
|
+
/**
|
|
250
|
+
* `"button"` returns focus to the button. `"kept"` leaves it where it moved,
|
|
251
|
+
* for example into a dialog an item opened, and only rescues focus that the
|
|
252
|
+
* closing sidebar would hide. `"none"` moves nothing, for cleanup.
|
|
253
|
+
*/
|
|
254
|
+
const closeOverlay = focus => {
|
|
255
|
+
const closing = overlay;
|
|
256
|
+
if (!closing) return;
|
|
257
|
+
overlay = null;
|
|
258
|
+
delete closing.root.dataset.sidebarOverlay;
|
|
259
|
+
closing.toggle.setAttribute("aria-expanded", "false");
|
|
260
|
+
closing.inerted.forEach(region => region.removeAttribute("inert"));
|
|
261
|
+
if (focus === "none") return;
|
|
262
|
+
const active = document.activeElement;
|
|
263
|
+
if (focus === "button" || !active || active === document.body || closing.sidebar.contains(active)) closing.toggle.focus();
|
|
264
|
+
};
|
|
265
|
+
const onClick = event => {
|
|
266
|
+
const target = eventElement(event);
|
|
267
|
+
const toggle = target?.closest(TOGGLE_SELECTOR);
|
|
268
|
+
if (toggle) {
|
|
269
|
+
const next = overlayTarget(toggle);
|
|
270
|
+
if (!next || claimedToggleClicks.has(event)) return;
|
|
271
|
+
claimedToggleClicks.add(event);
|
|
272
|
+
if (overlay?.sidebar === next.sidebar) closeOverlay("button");else if (compact?.matches) openOverlay(next);
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
if (!overlay || !target) return;
|
|
276
|
+
// The scrim is the workspace root's own pseudo-element.
|
|
277
|
+
if (target === overlay.root) {
|
|
278
|
+
closeOverlay("button");
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
// Choosing a destination closes the overlay: a link, or the button of a
|
|
282
|
+
// row. A tree folder that only expands, a control that opens a popup or
|
|
283
|
+
// expands something, such as a row's preview, and an item's own actions
|
|
284
|
+
// keep it open.
|
|
285
|
+
const control = target.closest("a[href], button");
|
|
286
|
+
if (!control || !overlay.sidebar.contains(control)) return;
|
|
287
|
+
if (target.closest("[data-k2b-nav-tree-toggle]") || control.closest("[data-k2b-nav-tree-disclosure], .k2b-app-workspace__sidebar-item-action, .k2b-app-workspace__sidebar-item-actions") || control.matches("[aria-haspopup], [aria-expanded]")) return;
|
|
288
|
+
if (control.matches("a[href]") || control.closest(ITEM_SELECTOR)) closeOverlay("kept");
|
|
289
|
+
};
|
|
290
|
+
const onOverlayKeyDown = event => {
|
|
291
|
+
if (!overlay || event.defaultPrevented) return;
|
|
292
|
+
const target = eventElement(event);
|
|
293
|
+
if (!target) return;
|
|
294
|
+
// Escape also closes it when a click left focus on nothing, so on the body.
|
|
295
|
+
if (event.key === "Escape" && (overlay.sidebar.contains(target) || target === ownerDocument.body)) {
|
|
296
|
+
event.preventDefault();
|
|
297
|
+
closeOverlay("button");
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
if (event.key !== "Tab" || !overlay.sidebar.contains(target)) return;
|
|
301
|
+
const stops = tabStopsIn(overlay.sidebar);
|
|
302
|
+
const first = stops[0];
|
|
303
|
+
const last = stops.at(-1);
|
|
304
|
+
if (!first || !last) {
|
|
305
|
+
event.preventDefault();
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
308
|
+
if (event.shiftKey && (document.activeElement === first || document.activeElement === overlay.sidebar)) {
|
|
309
|
+
event.preventDefault();
|
|
310
|
+
last.focus();
|
|
311
|
+
} else if (!event.shiftKey && document.activeElement === last) {
|
|
312
|
+
event.preventDefault();
|
|
313
|
+
first.focus();
|
|
314
|
+
}
|
|
315
|
+
};
|
|
316
|
+
const onCompactChange = () => {
|
|
317
|
+
if (!compact?.matches) closeOverlay("none");
|
|
318
|
+
};
|
|
319
|
+
const phone = typeof window.matchMedia === "function" ? window.matchMedia("(max-width: 47.999rem)") : null;
|
|
320
|
+
const wide = typeof window.matchMedia === "function" ? window.matchMedia("(min-width: 48rem)") : null;
|
|
321
|
+
const touchDrawer = typeof window.matchMedia === "function" ? window.matchMedia(`${COMPACT_QUERY} and (pointer: coarse)`) : null;
|
|
322
|
+
const reducedMotion = typeof window.matchMedia === "function" ? window.matchMedia("(prefers-reduced-motion: reduce)") : null;
|
|
323
|
+
const detailSelector = ".k2b-app-workspace__detail";
|
|
324
|
+
const grabberSelector = ".k2b-app-workspace__detail-grabber";
|
|
325
|
+
const detailHidden = new WeakMap();
|
|
326
|
+
const remembered = new WeakMap();
|
|
327
|
+
const lastFocus = new WeakMap();
|
|
328
|
+
const touchedDetails = new Set();
|
|
329
|
+
// Only a panel blocks scrolling for its touch gestures; a document-wide
|
|
330
|
+
// non-passive listener would make every scroll on the page wait for script.
|
|
331
|
+
const touchMoveAsides = new Set();
|
|
332
|
+
const titleTabIndices = new Set();
|
|
333
|
+
const motionFrames = new Map();
|
|
334
|
+
const pendingAnchors = new Map();
|
|
335
|
+
const slides = new Map();
|
|
336
|
+
const motionRoots = new Set();
|
|
337
|
+
const revealFrames = new Map();
|
|
338
|
+
const openDetails = root => rootElements(root, detailSelector).filter(aside => !aside.hidden);
|
|
339
|
+
const closeControl = aside => Array.from(aside.querySelectorAll("[data-workspace-detail-close]")).find(control => control.closest(detailSelector) === aside);
|
|
340
|
+
const closable = aside => aside.hasAttribute("data-workspace-detail-closable") || Boolean(closeControl(aside));
|
|
341
|
+
const requestClose = aside => {
|
|
342
|
+
if (aside.hasAttribute("data-workspace-detail-closable")) aside.dispatchEvent(new CustomEvent(APP_WORKSPACE_DETAIL_CLOSE_EVENT));else closeControl(aside)?.click();
|
|
343
|
+
};
|
|
344
|
+
const scrollerOn = (axis, target, boundary) => {
|
|
345
|
+
for (let element = target; element && boundary.contains(element); element = element.parentElement) {
|
|
346
|
+
if (element instanceof HTMLElement && /^(auto|scroll)$/.test(axis === "y" ? getComputedStyle(element).overflowY : getComputedStyle(element).overflowX) && (axis === "y" ? element.scrollHeight > element.clientHeight : element.scrollWidth > element.clientWidth)) return element;
|
|
347
|
+
if (element === boundary) break;
|
|
348
|
+
}
|
|
349
|
+
return null;
|
|
350
|
+
};
|
|
351
|
+
const verticalScroller = (target, boundary) => scrollerOn("y", target, boundary);
|
|
352
|
+
const refreshItem = snapshot => {
|
|
353
|
+
snapshot.top = snapshot.item.getBoundingClientRect().top;
|
|
354
|
+
snapshot.scrollTop = snapshot.scroller?.scrollTop ?? 0;
|
|
355
|
+
};
|
|
356
|
+
// A table row can exceed its scroller's width, so keep the clicked cell for horizontal reveal.
|
|
357
|
+
const rememberInteraction = event => {
|
|
358
|
+
const target = eventElement(event);
|
|
359
|
+
const root = target?.closest(ROOT_SELECTOR);
|
|
360
|
+
if (!target || !root || !observedRoots.has(root)) return;
|
|
361
|
+
const previous = remembered.get(root);
|
|
362
|
+
if (previous && openDetails(root).length) refreshItem(previous);
|
|
363
|
+
const main = mainElement(root);
|
|
364
|
+
const item = target.closest(FOCUSABLE_SELECTOR);
|
|
365
|
+
if (!main || !item || !main.contains(item) || item.closest(ROOT_SELECTOR) !== root) return;
|
|
366
|
+
if (event instanceof KeyboardEvent && event.key !== "Enter" && event.key !== " ") return;
|
|
367
|
+
const cell = target.closest("td, th");
|
|
368
|
+
const snapshot = {
|
|
369
|
+
item,
|
|
370
|
+
cell: cell && main.contains(cell) && cell.closest(ROOT_SELECTOR) === root ? cell : null,
|
|
371
|
+
interaction: event instanceof KeyboardEvent ? "keyboard" : "pointer",
|
|
372
|
+
scroller: verticalScroller(item, main),
|
|
373
|
+
scrollTop: 0,
|
|
374
|
+
top: 0,
|
|
375
|
+
fresh: true
|
|
376
|
+
};
|
|
377
|
+
refreshItem(snapshot);
|
|
378
|
+
remembered.set(root, snapshot);
|
|
379
|
+
// Enter in an editor or a field types; only an item that chooses something moves on to its title.
|
|
380
|
+
if (event instanceof KeyboardEvent && !target.closest(KEY_OWNER_SELECTOR)) {
|
|
381
|
+
const aside = openDetails(root).find(isVisible);
|
|
382
|
+
if (aside) requestTitle(aside, true);
|
|
383
|
+
}
|
|
384
|
+
};
|
|
385
|
+
const onDetailFocusIn = event => {
|
|
386
|
+
const target = eventElement(event);
|
|
387
|
+
const root = target?.closest(ROOT_SELECTOR);
|
|
388
|
+
if (!target || !root || !observedRoots.has(root)) return;
|
|
389
|
+
lastFocus.set(root, target);
|
|
390
|
+
const previous = remembered.get(root);
|
|
391
|
+
// Pointer focus follows pointerdown; keeping that snapshot also keeps the
|
|
392
|
+
// interaction that opened the panel rather than treating focus as a new one.
|
|
393
|
+
if (previous?.item.contains(target)) {
|
|
394
|
+
const main = mainElement(root);
|
|
395
|
+
if (target !== previous.item && target instanceof HTMLElement && main) {
|
|
396
|
+
previous.item = target;
|
|
397
|
+
previous.scroller = verticalScroller(target, main);
|
|
398
|
+
refreshItem(previous);
|
|
399
|
+
}
|
|
400
|
+
return;
|
|
401
|
+
}
|
|
402
|
+
rememberInteraction(event);
|
|
403
|
+
};
|
|
404
|
+
const titleIn = aside => aside.querySelector("h1, h2, h3, [role='heading']");
|
|
405
|
+
let focusingTitle = null;
|
|
406
|
+
const focusTitle = aside => {
|
|
407
|
+
const title = titleIn(aside);
|
|
408
|
+
if (!title) return false;
|
|
409
|
+
if (!title.matches(FOCUSABLE_SELECTOR) && !title.hasAttribute("tabindex")) {
|
|
410
|
+
title.tabIndex = -1;
|
|
411
|
+
titleTabIndices.add(title);
|
|
412
|
+
}
|
|
413
|
+
focusingTitle = title;
|
|
414
|
+
try {
|
|
415
|
+
title.focus({
|
|
416
|
+
preventScroll: true
|
|
417
|
+
});
|
|
418
|
+
} finally {
|
|
419
|
+
focusingTitle = null;
|
|
420
|
+
}
|
|
421
|
+
return true;
|
|
422
|
+
};
|
|
423
|
+
let pendingTitle = null;
|
|
424
|
+
const cancelTitle = () => {
|
|
425
|
+
pendingTitle?.observer.disconnect();
|
|
426
|
+
pendingTitle = null;
|
|
427
|
+
};
|
|
428
|
+
// A step from inside the panel can remove the focused element with the old
|
|
429
|
+
// content, so focus falls to the body. The panel keeps owning the steps until
|
|
430
|
+
// focus or a pointer goes elsewhere, so a quick second J still ends on the title.
|
|
431
|
+
let panelStep = null;
|
|
432
|
+
const cancelTitleOnInteraction = event => {
|
|
433
|
+
if (event.type !== "keydown" && !(event.target instanceof Node && panelStep?.contains(event.target))) panelStep = null;
|
|
434
|
+
if (event.type !== "focusin" || event.target !== focusingTitle) cancelTitle();
|
|
435
|
+
};
|
|
436
|
+
const requestTitle = (aside, waitForChange = false) => {
|
|
437
|
+
cancelTitle();
|
|
438
|
+
if (aside.hidden || !aside.isConnected) return;
|
|
439
|
+
if (!waitForChange && focusTitle(aside)) return;
|
|
440
|
+
const previousTitle = titleIn(aside);
|
|
441
|
+
const previousText = previousTitle?.textContent;
|
|
442
|
+
// Loading fallbacks and selection changes can produce their heading after
|
|
443
|
+
// the opening interaction. A later user action always takes precedence.
|
|
444
|
+
const observer = new MutationObserver(() => {
|
|
445
|
+
if (aside.hidden || !aside.isConnected) {
|
|
446
|
+
cancelTitle();
|
|
447
|
+
return;
|
|
448
|
+
}
|
|
449
|
+
const title = titleIn(aside);
|
|
450
|
+
if (!title || waitForChange && title === previousTitle && title.textContent === previousText) return;
|
|
451
|
+
cancelTitle();
|
|
452
|
+
focusTitle(aside);
|
|
453
|
+
});
|
|
454
|
+
pendingTitle = {
|
|
455
|
+
aside,
|
|
456
|
+
observer
|
|
457
|
+
};
|
|
458
|
+
observer.observe(aside, {
|
|
459
|
+
childList: true,
|
|
460
|
+
subtree: true,
|
|
461
|
+
characterData: true
|
|
462
|
+
});
|
|
463
|
+
// An element-scoped controller cannot see its own root leave the document.
|
|
464
|
+
observer.observe(ownerDocument, {
|
|
465
|
+
childList: true,
|
|
466
|
+
subtree: true
|
|
467
|
+
});
|
|
468
|
+
};
|
|
469
|
+
const setDetent = (aside, full) => {
|
|
470
|
+
touchedDetails.add(aside);
|
|
471
|
+
if (full) aside.dataset.workspaceDetailSheet = "full";else delete aside.dataset.workspaceDetailSheet;
|
|
472
|
+
aside.querySelector(grabberSelector)?.setAttribute("aria-pressed", String(full));
|
|
473
|
+
};
|
|
474
|
+
const clearDrag = aside => {
|
|
475
|
+
aside.style.removeProperty("--k2b-workspace-detail-sheet-height");
|
|
476
|
+
aside.style.removeProperty("transform");
|
|
477
|
+
delete aside.dataset.workspaceDetailDragging;
|
|
478
|
+
};
|
|
479
|
+
const anchorItem = (root, aside, snapshot) => {
|
|
480
|
+
if (!wide?.matches || touchDrawer?.matches && closable(aside) || !snapshot?.item.isConnected) return;
|
|
481
|
+
if (!mainElement(root)?.contains(snapshot.item) || snapshot.item.closest(ROOT_SELECTOR) !== root) return;
|
|
482
|
+
const scroller = snapshot.scroller;
|
|
483
|
+
if (scroller?.isConnected && scroller.scrollTop === snapshot.scrollTop) scroller.scrollTop += snapshot.item.getBoundingClientRect().top - snapshot.top;
|
|
484
|
+
};
|
|
485
|
+
// From 64 rem the workspace does not clip, so the panel's shadow shows on
|
|
486
|
+
// every edge. A panel sliding in or out would cross a framed workspace's
|
|
487
|
+
// edge, so the workspace clips while the panel moves (see the stylesheet).
|
|
488
|
+
const slide = (root, aside) => {
|
|
489
|
+
slides.get(root)?.();
|
|
490
|
+
if (!root.hasAttribute("data-workspace-motion") || reducedMotion?.matches || !wide?.matches) return;
|
|
491
|
+
const end = () => {
|
|
492
|
+
aside.removeEventListener("transitionend", onEnd);
|
|
493
|
+
aside.removeEventListener("transitioncancel", onEnd);
|
|
494
|
+
cancelAnimationFrame(frame);
|
|
495
|
+
slides.delete(root);
|
|
496
|
+
delete root.dataset.workspaceDetailSliding;
|
|
497
|
+
};
|
|
498
|
+
const onEnd = event => {
|
|
499
|
+
if (event.target === aside && event.propertyName === "transform") end();
|
|
500
|
+
};
|
|
501
|
+
aside.addEventListener("transitionend", onEnd);
|
|
502
|
+
aside.addEventListener("transitioncancel", onEnd);
|
|
503
|
+
// A slow first frame must not end the clip early, so only a panel that
|
|
504
|
+
// does not slide at all ends it in that frame.
|
|
505
|
+
const frame = requestAnimationFrame(() => {
|
|
506
|
+
const sliding = aside.getAnimations?.().some(animation => "transitionProperty" in animation && animation.transitionProperty === "transform");
|
|
507
|
+
if (!sliding) end();
|
|
508
|
+
});
|
|
509
|
+
slides.set(root, end);
|
|
510
|
+
root.dataset.workspaceDetailSliding = "";
|
|
511
|
+
};
|
|
512
|
+
const revealItem = (root, aside, snapshot) => {
|
|
513
|
+
const pending = revealFrames.get(root);
|
|
514
|
+
if (pending !== undefined) cancelAnimationFrame(pending);
|
|
515
|
+
revealFrames.set(root, requestAnimationFrame(() => {
|
|
516
|
+
revealFrames.delete(root);
|
|
517
|
+
if (!aside.hidden && aside.isConnected && snapshot.item.isConnected && mainElement(root)?.contains(snapshot.item) && snapshot.item.closest(ROOT_SELECTOR) === root) {
|
|
518
|
+
const behavior = reducedMotion?.matches ? "auto" : "smooth";
|
|
519
|
+
const main = mainElement(root);
|
|
520
|
+
const cell = snapshot.cell;
|
|
521
|
+
const target = cell?.isConnected && main?.contains(cell) ? cell : snapshot.item;
|
|
522
|
+
if (phone?.matches && main) {
|
|
523
|
+
// The sheet covers Main's lower part, so the item ends 8px above it;
|
|
524
|
+
// a step can also land above Main's top or beside it, as in a board.
|
|
525
|
+
const page = ownerDocument.scrollingElement;
|
|
526
|
+
const vertical = verticalScroller(target, main) ?? page;
|
|
527
|
+
const horizontal = scrollerOn("x", target, main) ?? page;
|
|
528
|
+
const bounds = scroller => scroller && scroller !== page ? scroller.getBoundingClientRect() : null;
|
|
529
|
+
const box = target.getBoundingClientRect();
|
|
530
|
+
const top = Math.max(0, bounds(vertical)?.top ?? 0);
|
|
531
|
+
const left = Math.max(0, bounds(horizontal)?.left ?? 0);
|
|
532
|
+
const right = Math.min(ownerWindow.innerWidth, bounds(horizontal)?.right ?? Infinity);
|
|
533
|
+
const dy = box.top < top ? box.top - top - 8 : Math.max(0, box.bottom - (ownerWindow.innerHeight - aside.offsetHeight) + 8);
|
|
534
|
+
// As with scrollIntoView's "nearest", an item past both edges stays put
|
|
535
|
+
// and one wider than the view keeps its start in view.
|
|
536
|
+
const dx = box.left < left && box.right > right ? 0 : box.left < left ? box.left - left - 8 : box.right > right ? Math.min(box.right - right + 8, Math.max(0, box.left - left - 8)) : 0;
|
|
537
|
+
if (vertical && vertical === horizontal) {
|
|
538
|
+
if (dy || dx) vertical.scrollBy({
|
|
539
|
+
top: dy,
|
|
540
|
+
left: dx,
|
|
541
|
+
behavior
|
|
542
|
+
});
|
|
543
|
+
} else {
|
|
544
|
+
if (dy) vertical?.scrollBy({
|
|
545
|
+
top: dy,
|
|
546
|
+
behavior
|
|
547
|
+
});
|
|
548
|
+
if (dx) horizontal?.scrollBy({
|
|
549
|
+
left: dx,
|
|
550
|
+
behavior
|
|
551
|
+
});
|
|
552
|
+
}
|
|
553
|
+
} else target.scrollIntoView({
|
|
554
|
+
block: "nearest",
|
|
555
|
+
inline: "nearest",
|
|
556
|
+
behavior
|
|
557
|
+
});
|
|
558
|
+
}
|
|
559
|
+
}));
|
|
560
|
+
};
|
|
561
|
+
const detailTransition = (aside, wasHidden) => {
|
|
562
|
+
const root = aside.closest(ROOT_SELECTOR);
|
|
563
|
+
detailHidden.set(aside, Boolean(aside.hidden));
|
|
564
|
+
if (!root || !observedRoots.has(root) || Boolean(aside.hidden) === wasHidden) return;
|
|
565
|
+
pendingAnchors.get(root)?.();
|
|
566
|
+
slide(root, aside);
|
|
567
|
+
touchedDetails.add(aside);
|
|
568
|
+
const pending = revealFrames.get(root);
|
|
569
|
+
if (pending !== undefined) cancelAnimationFrame(pending);
|
|
570
|
+
revealFrames.delete(root);
|
|
571
|
+
const snapshot = remembered.get(root);
|
|
572
|
+
const followedInteraction = snapshot?.fresh ?? false;
|
|
573
|
+
if (snapshot) snapshot.fresh = false;
|
|
574
|
+
if (aside.hidden) {
|
|
575
|
+
if (pendingTitle?.aside === aside) cancelTitle();
|
|
576
|
+
if (panelStep === aside) panelStep = null;
|
|
577
|
+
if (root.hasAttribute("data-workspace-motion") && !reducedMotion?.matches && wide?.matches) {
|
|
578
|
+
// Closing holds the detail column until the slide ends; anchor after Main widens.
|
|
579
|
+
const cancel = () => {
|
|
580
|
+
root.removeEventListener("transitionend", onTransitionEnd);
|
|
581
|
+
clearTimeout(timer);
|
|
582
|
+
pendingAnchors.delete(root);
|
|
583
|
+
};
|
|
584
|
+
const finish = () => {
|
|
585
|
+
cancel();
|
|
586
|
+
if (aside.hidden && aside.isConnected) anchorItem(root, aside, snapshot);
|
|
587
|
+
};
|
|
588
|
+
const onTransitionEnd = event => {
|
|
589
|
+
if (event.target === root && event.propertyName === "--k2b-workspace-detail-track") finish();
|
|
590
|
+
};
|
|
591
|
+
const timer = setTimeout(finish, 300);
|
|
592
|
+
root.addEventListener("transitionend", onTransitionEnd);
|
|
593
|
+
pendingAnchors.set(root, cancel);
|
|
594
|
+
} else anchorItem(root, aside, snapshot);
|
|
595
|
+
const focused = ownerDocument.activeElement;
|
|
596
|
+
if (snapshot?.item.isConnected && (aside.contains(lastFocus.get(root) ?? null) || aside.contains(focused) || focused === ownerDocument.body)) snapshot.item.focus({
|
|
597
|
+
preventScroll: true
|
|
598
|
+
});
|
|
599
|
+
clearDrag(aside);
|
|
600
|
+
if (detailDrag?.aside === aside) finishDetailDrag(true);
|
|
601
|
+
return;
|
|
602
|
+
}
|
|
603
|
+
anchorItem(root, aside, snapshot);
|
|
604
|
+
if (phone?.matches) setDetent(aside, false);
|
|
605
|
+
if (followedInteraction && snapshot) {
|
|
606
|
+
revealItem(root, aside, snapshot);
|
|
607
|
+
if (snapshot.interaction === "keyboard" || phone?.matches) requestTitle(aside);
|
|
608
|
+
}
|
|
609
|
+
};
|
|
610
|
+
const onDetailKeyDown = event => {
|
|
611
|
+
if (event.defaultPrevented || event.ctrlKey || event.metaKey || event.altKey) return;
|
|
612
|
+
const target = eventElement(event);
|
|
613
|
+
if (!target || target.closest(KEY_OWNER_SELECTOR)) return;
|
|
614
|
+
if (ownerDocument.querySelector("dialog[open], [aria-modal='true']")) return;
|
|
615
|
+
try {
|
|
616
|
+
if (ownerDocument.querySelector(":popover-open")) return;
|
|
617
|
+
} catch {
|
|
618
|
+
// Older engines have no popover selector; the other popup guards still apply.
|
|
619
|
+
}
|
|
620
|
+
const root = target.closest(ROOT_SELECTOR);
|
|
621
|
+
let aside = target.closest(detailSelector);
|
|
622
|
+
if (aside?.hidden || aside && (!eventRoot.contains(aside) || aside.closest(ROOT_SELECTOR) !== root)) aside = null;
|
|
623
|
+
if (!aside && root && observedRoots.has(root) && mainElement(root)?.contains(target)) aside = openDetails(root)[0] ?? null;
|
|
624
|
+
if (!aside && target === ownerDocument.body) {
|
|
625
|
+
const open = allRoots().flatMap(openDetails);
|
|
626
|
+
if (open.length === 1) aside = open[0];
|
|
627
|
+
}
|
|
628
|
+
const owningRoot = aside?.closest(ROOT_SELECTOR);
|
|
629
|
+
if (!aside || !owningRoot) return;
|
|
630
|
+
if (event.key === "Escape" && closable(aside)) requestClose(aside);else if ((event.key.toLowerCase() === "j" || event.key.toLowerCase() === "k") && aside.hasAttribute("data-workspace-detail-steppable")) {
|
|
631
|
+
const main = mainElement(owningRoot);
|
|
632
|
+
const inMain = remembered.get(owningRoot)?.item.contains(target) || main?.contains(target);
|
|
633
|
+
const inPanel = aside.contains(target) || target === ownerDocument.body && panelStep === aside;
|
|
634
|
+
panelStep = inPanel ? aside : null;
|
|
635
|
+
const previousTitle = inPanel ? titleIn(aside) : null;
|
|
636
|
+
const previousText = previousTitle?.textContent;
|
|
637
|
+
const detail = {
|
|
638
|
+
direction: event.key.toLowerCase() === "j" ? 1 : -1
|
|
639
|
+
};
|
|
640
|
+
aside.dispatchEvent(new CustomEvent(APP_WORKSPACE_DETAIL_STEP_EVENT, {
|
|
641
|
+
detail
|
|
642
|
+
}));
|
|
643
|
+
const shown = detail.item;
|
|
644
|
+
const item = shown instanceof HTMLElement && main?.contains(shown) && shown.closest(ROOT_SELECTOR) === owningRoot ? shown : null;
|
|
645
|
+
if (item && main) {
|
|
646
|
+
const snapshot = {
|
|
647
|
+
item,
|
|
648
|
+
cell: null,
|
|
649
|
+
interaction: "keyboard",
|
|
650
|
+
scroller: verticalScroller(item, main),
|
|
651
|
+
scrollTop: 0,
|
|
652
|
+
top: 0,
|
|
653
|
+
fresh: false
|
|
654
|
+
};
|
|
655
|
+
refreshItem(snapshot);
|
|
656
|
+
remembered.set(owningRoot, snapshot);
|
|
657
|
+
revealItem(owningRoot, aside, snapshot);
|
|
658
|
+
}
|
|
659
|
+
const title = titleIn(aside);
|
|
660
|
+
if (item && inMain) item.focus({
|
|
661
|
+
preventScroll: true
|
|
662
|
+
});
|
|
663
|
+
// A panel that swapped its title during the event has the new one now.
|
|
664
|
+
else if (item && inPanel && title && (title !== previousTitle || title.textContent !== previousText)) focusTitle(aside);
|
|
665
|
+
// This key's capture cancelled an earlier step's title request, so a
|
|
666
|
+
// step from the body, even past the last item, asks again.
|
|
667
|
+
else if (inPanel && (item || target === ownerDocument.body)) requestTitle(aside, Boolean(item));
|
|
668
|
+
} else if (event.key === "F6") {
|
|
669
|
+
if (aside.contains(target)) {
|
|
670
|
+
const item = remembered.get(owningRoot)?.item;
|
|
671
|
+
const main = mainElement(owningRoot);
|
|
672
|
+
(item?.isConnected ? item : main ? tabStopsIn(main)[0] : null)?.focus({
|
|
673
|
+
preventScroll: true
|
|
674
|
+
});
|
|
675
|
+
} else focusTitle(aside);
|
|
676
|
+
} else return;
|
|
677
|
+
event.preventDefault();
|
|
678
|
+
};
|
|
679
|
+
let detailDrag = null;
|
|
680
|
+
let detailDragFrame = null;
|
|
681
|
+
let suppressedClick = null;
|
|
682
|
+
let suppressedClickTimer = null;
|
|
683
|
+
const paintDetailDrag = () => {
|
|
684
|
+
detailDragFrame = null;
|
|
685
|
+
const drag = detailDrag;
|
|
686
|
+
if (!drag?.moved) return;
|
|
687
|
+
drag.aside.dataset.workspaceDetailDragging = "true";
|
|
688
|
+
touchedDetails.add(drag.aside);
|
|
689
|
+
if (drag.source === "drawer") drag.aside.style.transform = `translateX(${Math.max(0, drag.dx)}px)`;else {
|
|
690
|
+
const height = ownerWindow.innerHeight;
|
|
691
|
+
drag.aside.style.setProperty("--k2b-workspace-detail-sheet-height", `${clamp(drag.startHeight - drag.dy, 0, Math.max(0, height - 8))}px`);
|
|
692
|
+
}
|
|
693
|
+
};
|
|
694
|
+
const scheduleDetailDrag = () => {
|
|
695
|
+
if (detailDragFrame === null) detailDragFrame = requestAnimationFrame(paintDetailDrag);
|
|
696
|
+
};
|
|
697
|
+
const finishDetailDrag = cancelled => {
|
|
698
|
+
const drag = detailDrag;
|
|
699
|
+
if (!drag) return;
|
|
700
|
+
detailDrag = null;
|
|
701
|
+
if (detailDragFrame !== null) cancelAnimationFrame(detailDragFrame);
|
|
702
|
+
detailDragFrame = null;
|
|
703
|
+
drag.releaseTextSelection?.();
|
|
704
|
+
if (drag.source === "pointer") {
|
|
705
|
+
if (drag.target instanceof HTMLElement && drag.target.hasPointerCapture?.(drag.pointerId)) drag.target.releasePointerCapture(drag.pointerId);
|
|
706
|
+
if (drag.moved) {
|
|
707
|
+
suppressedClick = drag.aside;
|
|
708
|
+
if (suppressedClickTimer !== null) clearTimeout(suppressedClickTimer);
|
|
709
|
+
suppressedClickTimer = setTimeout(() => {
|
|
710
|
+
suppressedClick = null;
|
|
711
|
+
suppressedClickTimer = null;
|
|
712
|
+
}, 0);
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
clearDrag(drag.aside);
|
|
716
|
+
if (cancelled || !drag.moved) return;
|
|
717
|
+
if (drag.source === "drawer") {
|
|
718
|
+
if (drag.dx > 80 || drag.dx > 30 && drag.velocity > 0.5) requestClose(drag.aside);
|
|
719
|
+
} else if (drag.dy > 60) {
|
|
720
|
+
setDetent(drag.aside, false);
|
|
721
|
+
if (!drag.full && closable(drag.aside)) requestClose(drag.aside);
|
|
722
|
+
} else if (drag.dy < -60) setDetent(drag.aside, true);
|
|
723
|
+
};
|
|
724
|
+
const beginDetailDrag = (aside, target, source, x, y, pointerId) => {
|
|
725
|
+
detailDrag = {
|
|
726
|
+
aside,
|
|
727
|
+
target,
|
|
728
|
+
source,
|
|
729
|
+
pointerId,
|
|
730
|
+
startX: x,
|
|
731
|
+
startY: y,
|
|
732
|
+
startHeight: aside.getBoundingClientRect().height,
|
|
733
|
+
full: aside.dataset.workspaceDetailSheet === "full",
|
|
734
|
+
dx: 0,
|
|
735
|
+
dy: 0,
|
|
736
|
+
time: performance.now(),
|
|
737
|
+
velocity: 0,
|
|
738
|
+
moved: false
|
|
739
|
+
};
|
|
740
|
+
return detailDrag;
|
|
741
|
+
};
|
|
742
|
+
const onSheetPointerDown = event => {
|
|
743
|
+
if (!(event instanceof PointerEvent) || !phone?.matches || event.button !== 0 || !event.isPrimary || claimedDetailGestures.has(event)) return;
|
|
744
|
+
const target = eventElement(event);
|
|
745
|
+
const aside = target?.closest(detailSelector);
|
|
746
|
+
const root = aside?.closest(ROOT_SELECTOR);
|
|
747
|
+
if (!target || !aside || !root || aside.hidden || !observedRoots.has(root) || target.closest(ROOT_SELECTOR) !== root) return;
|
|
748
|
+
const grabber = target.closest(grabberSelector);
|
|
749
|
+
if (!grabber && (!target.closest(".k2b-detail-panel__header") || target.closest("a, button, input, select, textarea, [role='button'], [contenteditable]:not([contenteditable='false'])"))) return;
|
|
750
|
+
claimedDetailGestures.add(event);
|
|
751
|
+
if (detailDrag) finishDetailDrag(true);
|
|
752
|
+
const drag = beginDetailDrag(aside, grabber ?? target, "pointer", event.clientX, event.clientY, event.pointerId);
|
|
753
|
+
drag.releaseTextSelection = suppressTextSelection(event.pointerId);
|
|
754
|
+
if (drag.target instanceof HTMLElement) drag.target.setPointerCapture?.(event.pointerId);
|
|
755
|
+
aside.dataset.workspaceDetailDragging = "true";
|
|
756
|
+
touchedDetails.add(aside);
|
|
757
|
+
};
|
|
758
|
+
const onSheetPointerMove = event => {
|
|
759
|
+
const drag = detailDrag;
|
|
760
|
+
if (!drag || drag.source !== "pointer" || drag.pointerId !== event.pointerId) return;
|
|
761
|
+
drag.dy = event.clientY - drag.startY;
|
|
762
|
+
drag.moved ||= Math.abs(drag.dy) > 4;
|
|
763
|
+
if (drag.moved) scheduleDetailDrag();
|
|
764
|
+
};
|
|
765
|
+
const onSheetPointerEnd = event => {
|
|
766
|
+
if (!(event instanceof PointerEvent)) return;
|
|
767
|
+
if (detailDrag?.source === "pointer" && detailDrag.pointerId === event.pointerId) finishDetailDrag(event.type !== "pointerup");
|
|
768
|
+
};
|
|
769
|
+
const onGrabberClick = event => {
|
|
770
|
+
const target = eventElement(event);
|
|
771
|
+
const grabber = target?.closest(grabberSelector);
|
|
772
|
+
const aside = grabber?.closest(detailSelector);
|
|
773
|
+
if (!aside || aside.hidden || !phone?.matches || claimedToggleClicks.has(event)) return;
|
|
774
|
+
claimedToggleClicks.add(event);
|
|
775
|
+
if (suppressedClick === aside && event instanceof MouseEvent && event.detail !== 0) {
|
|
776
|
+
event.preventDefault();
|
|
777
|
+
suppressedClick = null;
|
|
778
|
+
return;
|
|
779
|
+
}
|
|
780
|
+
setDetent(aside, aside.dataset.workspaceDetailSheet !== "full");
|
|
781
|
+
};
|
|
782
|
+
const ownsTouchGesture = (target, aside, source) => {
|
|
783
|
+
for (let element = target; element && element !== aside; element = element.parentElement) {
|
|
784
|
+
if (element.matches("input, textarea, select, [contenteditable]:not([contenteditable='false']), [role='slider'], [draggable='true'], canvas")) return true;
|
|
785
|
+
const action = getComputedStyle(element).getPropertyValue("touch-action");
|
|
786
|
+
const horizontal = /\bpan-(x|left|right)\b/.test(action);
|
|
787
|
+
const vertical = /\bpan-(y|up|down)\b/.test(action);
|
|
788
|
+
if (action.trim() === "none" || (source === "drawer" ? vertical && !horizontal : horizontal && !vertical)) return true;
|
|
789
|
+
}
|
|
790
|
+
return false;
|
|
791
|
+
};
|
|
792
|
+
const onDetailTouchStart = event => {
|
|
793
|
+
if (!(event instanceof TouchEvent) || event.touches.length !== 1) {
|
|
794
|
+
if (detailDrag && detailDrag.source !== "pointer") finishDetailDrag(true);
|
|
795
|
+
return;
|
|
796
|
+
}
|
|
797
|
+
if (detailDrag || claimedDetailGestures.has(event)) return;
|
|
798
|
+
const target = eventElement(event);
|
|
799
|
+
const aside = target?.closest(detailSelector);
|
|
800
|
+
const touch = event.touches[0];
|
|
801
|
+
const root = aside?.closest(ROOT_SELECTOR);
|
|
802
|
+
if (!target || !aside || !root || aside.hidden || !touch || !observedRoots.has(root) || target.closest(ROOT_SELECTOR) !== root) return;
|
|
803
|
+
if (phone?.matches && (verticalScroller(target, aside) ?? aside).scrollTop <= 0) {
|
|
804
|
+
if (!ownsTouchGesture(target, aside, "sheet")) beginDetailDrag(aside, target, "sheet", touch.clientX, touch.clientY, touch.identifier);
|
|
805
|
+
} else if (touchDrawer?.matches && closable(aside)) {
|
|
806
|
+
if (!ownsTouchGesture(target, aside, "drawer")) beginDetailDrag(aside, target, "drawer", touch.clientX, touch.clientY, touch.identifier);
|
|
807
|
+
}
|
|
808
|
+
if (detailDrag) claimedDetailGestures.add(event);
|
|
809
|
+
};
|
|
810
|
+
const onDetailTouchMove = event => {
|
|
811
|
+
const drag = detailDrag;
|
|
812
|
+
if (!(event instanceof TouchEvent) || !drag || drag.source === "pointer") return;
|
|
813
|
+
const touch = Array.from(event.touches).find(touch => touch.identifier === drag.pointerId);
|
|
814
|
+
if (!touch || event.touches.length !== 1) {
|
|
815
|
+
finishDetailDrag(true);
|
|
816
|
+
return;
|
|
817
|
+
}
|
|
818
|
+
const dx = touch.clientX - drag.startX;
|
|
819
|
+
const dy = touch.clientY - drag.startY;
|
|
820
|
+
const now = performance.now();
|
|
821
|
+
drag.velocity = (dx - drag.dx) / Math.max(1, now - drag.time);
|
|
822
|
+
drag.time = now;
|
|
823
|
+
drag.dx = dx;
|
|
824
|
+
drag.dy = dy;
|
|
825
|
+
if (!drag.moved) {
|
|
826
|
+
if (drag.source === "sheet") {
|
|
827
|
+
if (dy < 0 || (verticalScroller(drag.target, drag.aside) ?? drag.aside).scrollTop > 0) {
|
|
828
|
+
finishDetailDrag(true);
|
|
829
|
+
return;
|
|
830
|
+
}
|
|
831
|
+
if (dy <= 4) return;
|
|
832
|
+
} else {
|
|
833
|
+
if (Math.max(Math.abs(dx), Math.abs(dy)) <= 8) return;
|
|
834
|
+
if (dx <= Math.abs(dy)) {
|
|
835
|
+
finishDetailDrag(true);
|
|
836
|
+
return;
|
|
837
|
+
}
|
|
838
|
+
for (let element = drag.target; element && drag.aside.contains(element); element = element.parentElement) {
|
|
839
|
+
if (element instanceof HTMLElement && /^(auto|scroll)$/.test(getComputedStyle(element).overflowX) && element.scrollWidth > element.clientWidth && element.scrollLeft > 0) {
|
|
840
|
+
finishDetailDrag(true);
|
|
841
|
+
return;
|
|
842
|
+
}
|
|
843
|
+
if (element === drag.aside) break;
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
drag.moved = true;
|
|
847
|
+
}
|
|
848
|
+
event.preventDefault();
|
|
849
|
+
scheduleDetailDrag();
|
|
850
|
+
};
|
|
851
|
+
const onDetailTouchEnd = event => {
|
|
852
|
+
if (detailDrag && detailDrag.source !== "pointer") finishDetailDrag(event.type === "touchcancel");
|
|
853
|
+
};
|
|
854
|
+
const onDetailDoubleClick = event => {
|
|
855
|
+
const handle = resizeHandle(event);
|
|
856
|
+
const root = handle?.closest(ROOT_SELECTOR);
|
|
857
|
+
if (!handle || !root || resizeKind(handle) !== "detail" || !workspaceResizable(root) || !controlsResizableRegion(root, handle, "detail")) return;
|
|
858
|
+
const widths = {
|
|
859
|
+
...layoutState.detailWidths
|
|
860
|
+
};
|
|
861
|
+
delete widths[panelId(handle)];
|
|
862
|
+
layoutState = {
|
|
863
|
+
...layoutState,
|
|
864
|
+
detailWidths: widths
|
|
865
|
+
};
|
|
866
|
+
const variable = appWorkspacePanelVariable("detail", panelId(handle));
|
|
867
|
+
root.style.removeProperty(variable);
|
|
868
|
+
if (getComputedStyle(root).getPropertyValue(variable).trim()) root.style.setProperty(variable, `${numberData(handle, "workspaceDefaultSize", APP_WORKSPACE_DETAIL_DEFAULT)}px`);
|
|
869
|
+
updateHandleValue(root, handle, "detail", currentSize(root, handle, "detail"));
|
|
870
|
+
options.writeState?.(layoutState);
|
|
871
|
+
};
|
|
170
872
|
const stopScrollFades = installScrollFades(eventRoot);
|
|
171
873
|
let layoutState = normalizeAppWorkspaceLayoutState(options.readState?.()) ?? {
|
|
172
874
|
version: 2
|
|
@@ -248,7 +950,7 @@ export const installAppWorkspaceController = (options = {}) => {
|
|
|
248
950
|
if (finished.kind !== "drawer") reconcilePanes(finished.root, layoutState);
|
|
249
951
|
}
|
|
250
952
|
if (finished.handle.hasPointerCapture?.(finished.pointerId)) finished.handle.releasePointerCapture(finished.pointerId);
|
|
251
|
-
|
|
953
|
+
finished.releaseTextSelection();
|
|
252
954
|
window.removeEventListener("pointermove", onPointerMove);
|
|
253
955
|
window.removeEventListener("pointerup", stopResize);
|
|
254
956
|
window.removeEventListener("pointercancel", stopResize);
|
|
@@ -274,11 +976,10 @@ export const installAppWorkspaceController = (options = {}) => {
|
|
|
274
976
|
moved: false,
|
|
275
977
|
hiding: false,
|
|
276
978
|
direction: resizeDirection(handle, kind),
|
|
277
|
-
|
|
979
|
+
releaseTextSelection: suppressTextSelection(event.pointerId)
|
|
278
980
|
};
|
|
279
981
|
root.dataset.workspaceResizeActive = kind;
|
|
280
982
|
handle.dataset.workspaceResizeActive = "true";
|
|
281
|
-
document.body.style.userSelect = "none";
|
|
282
983
|
handle.setPointerCapture?.(event.pointerId);
|
|
283
984
|
window.addEventListener("pointermove", onPointerMove);
|
|
284
985
|
window.addEventListener("pointerup", stopResize);
|
|
@@ -324,6 +1025,14 @@ export const installAppWorkspaceController = (options = {}) => {
|
|
|
324
1025
|
return allRoots().filter(root => getComputedStyle(root).display !== "none" && root.getBoundingClientRect().width > 0);
|
|
325
1026
|
};
|
|
326
1027
|
const reconcile = () => {
|
|
1028
|
+
if (detailDrag && (detailDrag.source === "drawer" ? !touchDrawer?.matches : !phone?.matches)) finishDetailDrag(true);
|
|
1029
|
+
allRoots().forEach(root => {
|
|
1030
|
+
if (!phone?.matches) {
|
|
1031
|
+
for (const aside of rootElements(root, detailSelector)) {
|
|
1032
|
+
if (aside.dataset.workspaceDetailSheet === "full") setDetent(aside, false);
|
|
1033
|
+
}
|
|
1034
|
+
}
|
|
1035
|
+
});
|
|
327
1036
|
roots().forEach(root => {
|
|
328
1037
|
// `data-workspace-resizable="false"` already refuses pointer and keyboard
|
|
329
1038
|
// resizing; without this the same workspace still had persisted sizes
|
|
@@ -400,28 +1109,91 @@ export const installAppWorkspaceController = (options = {}) => {
|
|
|
400
1109
|
scheduleReconcile(true);
|
|
401
1110
|
});
|
|
402
1111
|
const syncObservedRoots = () => {
|
|
403
|
-
|
|
1112
|
+
for (const elements of [touchedDetails, titleTabIndices, motionRoots]) {
|
|
1113
|
+
elements.forEach(element => {
|
|
1114
|
+
if (!element.isConnected) elements.delete(element);
|
|
1115
|
+
});
|
|
1116
|
+
}
|
|
404
1117
|
const next = new Set(allRoots());
|
|
405
1118
|
observedRoots.forEach(root => {
|
|
406
1119
|
if (!next.has(root)) {
|
|
407
|
-
|
|
1120
|
+
pendingAnchors.get(root)?.();
|
|
1121
|
+
slides.get(root)?.();
|
|
1122
|
+
resizeObserver?.unobserve(root);
|
|
1123
|
+
const frame = motionFrames.get(root);
|
|
1124
|
+
if (frame !== undefined) cancelAnimationFrame(frame);
|
|
1125
|
+
motionFrames.delete(root);
|
|
408
1126
|
observedRoots.delete(root);
|
|
409
1127
|
}
|
|
410
1128
|
});
|
|
1129
|
+
touchMoveAsides.forEach(aside => {
|
|
1130
|
+
if (aside.isConnected) return;
|
|
1131
|
+
aside.removeEventListener("touchmove", onDetailTouchMove);
|
|
1132
|
+
touchMoveAsides.delete(aside);
|
|
1133
|
+
});
|
|
411
1134
|
next.forEach(root => {
|
|
1135
|
+
rootElements(root, detailSelector).forEach(aside => {
|
|
1136
|
+
if (!detailHidden.has(aside)) detailHidden.set(aside, Boolean(aside.hidden));
|
|
1137
|
+
if (touchMoveAsides.has(aside)) return;
|
|
1138
|
+
aside.addEventListener("touchmove", onDetailTouchMove, {
|
|
1139
|
+
passive: false
|
|
1140
|
+
});
|
|
1141
|
+
touchMoveAsides.add(aside);
|
|
1142
|
+
});
|
|
412
1143
|
if (observedRoots.has(root)) return;
|
|
413
1144
|
observedRoots.add(root);
|
|
414
|
-
resizeObserver
|
|
1145
|
+
resizeObserver?.observe(root);
|
|
1146
|
+
if (!root.hasAttribute("data-workspace-motion")) {
|
|
1147
|
+
motionRoots.add(root);
|
|
1148
|
+
motionFrames.set(root, requestAnimationFrame(() => {
|
|
1149
|
+
motionFrames.set(root, requestAnimationFrame(() => {
|
|
1150
|
+
motionFrames.delete(root);
|
|
1151
|
+
if (observedRoots.has(root)) root.dataset.workspaceMotion = "true";
|
|
1152
|
+
}));
|
|
1153
|
+
}));
|
|
1154
|
+
}
|
|
415
1155
|
});
|
|
416
1156
|
};
|
|
417
1157
|
const layoutNode = node => node instanceof Element && (node.matches(LAYOUT_REGION_SELECTOR) || Boolean(node.querySelector(LAYOUT_REGION_SELECTOR)));
|
|
418
1158
|
const mutationObserver = typeof MutationObserver === "undefined" ? null : new MutationObserver(records => {
|
|
1159
|
+
if (pendingTitle && (pendingTitle.aside.hidden || !pendingTitle.aside.isConnected)) cancelTitle();
|
|
1160
|
+
// Hiding or removing the sidebar, or its button, ends the overlay.
|
|
1161
|
+
if (overlay && (overlay.sidebar.hidden || !overlay.sidebar.isConnected || !overlay.toggle.isConnected)) closeOverlay("kept");
|
|
1162
|
+
const details = new Set();
|
|
1163
|
+
for (const record of records) {
|
|
1164
|
+
if (record.type === "attributes" && record.target instanceof HTMLElement && record.target.matches(detailSelector) && !details.has(record.target)) {
|
|
1165
|
+
details.add(record.target);
|
|
1166
|
+
detailTransition(record.target, detailHidden.get(record.target) ?? record.oldValue !== null);
|
|
1167
|
+
}
|
|
1168
|
+
}
|
|
419
1169
|
const changed = records.some(record => record.type === "attributes" ? record.target instanceof Element && record.target.matches(LAYOUT_REGION_SELECTOR) : [...Array.from(record.addedNodes), ...Array.from(record.removedNodes)].some(layoutNode));
|
|
420
1170
|
if (!changed) return;
|
|
421
1171
|
syncObservedRoots();
|
|
422
1172
|
scheduleReconcile();
|
|
423
1173
|
});
|
|
424
1174
|
eventRoot.addEventListener("pointerdown", onPointerDown);
|
|
1175
|
+
eventRoot.addEventListener("click", onClick);
|
|
1176
|
+
ownerDocument.addEventListener("keydown", onOverlayKeyDown);
|
|
1177
|
+
ownerWindow.addEventListener("keydown", onDetailKeyDown);
|
|
1178
|
+
ownerDocument.addEventListener("focusin", cancelTitleOnInteraction, true);
|
|
1179
|
+
ownerDocument.addEventListener("pointerdown", cancelTitleOnInteraction, true);
|
|
1180
|
+
ownerDocument.addEventListener("keydown", cancelTitleOnInteraction, true);
|
|
1181
|
+
eventRoot.addEventListener("pointerdown", rememberInteraction, true);
|
|
1182
|
+
eventRoot.addEventListener("keydown", rememberInteraction, true);
|
|
1183
|
+
eventRoot.addEventListener("focusin", onDetailFocusIn);
|
|
1184
|
+
eventRoot.addEventListener("pointerdown", onSheetPointerDown);
|
|
1185
|
+
eventRoot.addEventListener("click", onGrabberClick);
|
|
1186
|
+
eventRoot.addEventListener("dblclick", onDetailDoubleClick);
|
|
1187
|
+
window.addEventListener("pointermove", onSheetPointerMove);
|
|
1188
|
+
window.addEventListener("pointerup", onSheetPointerEnd);
|
|
1189
|
+
window.addEventListener("pointercancel", onSheetPointerEnd);
|
|
1190
|
+
eventRoot.addEventListener("lostpointercapture", onSheetPointerEnd);
|
|
1191
|
+
eventRoot.addEventListener("touchstart", onDetailTouchStart, {
|
|
1192
|
+
passive: true
|
|
1193
|
+
});
|
|
1194
|
+
eventRoot.addEventListener("touchend", onDetailTouchEnd);
|
|
1195
|
+
eventRoot.addEventListener("touchcancel", onDetailTouchEnd);
|
|
1196
|
+
compact?.addEventListener("change", onCompactChange);
|
|
425
1197
|
eventRoot.addEventListener("keydown", onKeyDown);
|
|
426
1198
|
eventRoot.addEventListener("focusin", onFocusIn);
|
|
427
1199
|
eventRoot.addEventListener("pointerover", onPointerOver);
|
|
@@ -429,13 +1201,46 @@ export const installAppWorkspaceController = (options = {}) => {
|
|
|
429
1201
|
syncObservedRoots();
|
|
430
1202
|
mutationObserver?.observe(eventRoot, {
|
|
431
1203
|
attributes: true,
|
|
1204
|
+
attributeOldValue: true,
|
|
432
1205
|
attributeFilter: ["hidden"],
|
|
433
1206
|
childList: true,
|
|
434
1207
|
subtree: true
|
|
435
1208
|
});
|
|
436
1209
|
scheduleReconcile();
|
|
437
1210
|
return () => {
|
|
1211
|
+
cancelTitle();
|
|
1212
|
+
pendingAnchors.forEach(cancel => cancel());
|
|
1213
|
+
slides.forEach(end => end());
|
|
438
1214
|
stopScrollFades();
|
|
1215
|
+
finishDetailDrag(true);
|
|
1216
|
+
if (suppressedClickTimer !== null) clearTimeout(suppressedClickTimer);
|
|
1217
|
+
motionFrames.forEach(cancelAnimationFrame);
|
|
1218
|
+
revealFrames.forEach(cancelAnimationFrame);
|
|
1219
|
+
motionRoots.forEach(root => delete root.dataset.workspaceMotion);
|
|
1220
|
+
touchedDetails.forEach(aside => {
|
|
1221
|
+
clearDrag(aside);
|
|
1222
|
+
delete aside.dataset.workspaceDetailSheet;
|
|
1223
|
+
aside.querySelector(grabberSelector)?.setAttribute("aria-pressed", "false");
|
|
1224
|
+
});
|
|
1225
|
+
titleTabIndices.forEach(title => title.removeAttribute("tabindex"));
|
|
1226
|
+
ownerWindow.removeEventListener("keydown", onDetailKeyDown);
|
|
1227
|
+
ownerDocument.removeEventListener("focusin", cancelTitleOnInteraction, true);
|
|
1228
|
+
ownerDocument.removeEventListener("pointerdown", cancelTitleOnInteraction, true);
|
|
1229
|
+
ownerDocument.removeEventListener("keydown", cancelTitleOnInteraction, true);
|
|
1230
|
+
eventRoot.removeEventListener("pointerdown", rememberInteraction, true);
|
|
1231
|
+
eventRoot.removeEventListener("keydown", rememberInteraction, true);
|
|
1232
|
+
eventRoot.removeEventListener("focusin", onDetailFocusIn);
|
|
1233
|
+
eventRoot.removeEventListener("pointerdown", onSheetPointerDown);
|
|
1234
|
+
eventRoot.removeEventListener("click", onGrabberClick);
|
|
1235
|
+
eventRoot.removeEventListener("dblclick", onDetailDoubleClick);
|
|
1236
|
+
window.removeEventListener("pointermove", onSheetPointerMove);
|
|
1237
|
+
window.removeEventListener("pointerup", onSheetPointerEnd);
|
|
1238
|
+
window.removeEventListener("pointercancel", onSheetPointerEnd);
|
|
1239
|
+
eventRoot.removeEventListener("lostpointercapture", onSheetPointerEnd);
|
|
1240
|
+
eventRoot.removeEventListener("touchstart", onDetailTouchStart);
|
|
1241
|
+
touchMoveAsides.forEach(aside => aside.removeEventListener("touchmove", onDetailTouchMove));
|
|
1242
|
+
eventRoot.removeEventListener("touchend", onDetailTouchEnd);
|
|
1243
|
+
eventRoot.removeEventListener("touchcancel", onDetailTouchEnd);
|
|
439
1244
|
// Flush the latest coalesced pointer sample before listeners and frames are
|
|
440
1245
|
// torn down, so unmounting during a drag cannot lose the final size.
|
|
441
1246
|
stopResize();
|
|
@@ -443,7 +1248,11 @@ export const installAppWorkspaceController = (options = {}) => {
|
|
|
443
1248
|
mutationObserver?.disconnect();
|
|
444
1249
|
resizeObserver?.disconnect();
|
|
445
1250
|
observedRoots.clear();
|
|
1251
|
+
closeOverlay("none");
|
|
446
1252
|
eventRoot.removeEventListener("pointerdown", onPointerDown);
|
|
1253
|
+
eventRoot.removeEventListener("click", onClick);
|
|
1254
|
+
ownerDocument.removeEventListener("keydown", onOverlayKeyDown);
|
|
1255
|
+
compact?.removeEventListener("change", onCompactChange);
|
|
447
1256
|
eventRoot.removeEventListener("keydown", onKeyDown);
|
|
448
1257
|
eventRoot.removeEventListener("focusin", onFocusIn);
|
|
449
1258
|
eventRoot.removeEventListener("pointerover", onPointerOver);
|