@k2b/ui 0.2.0 → 0.4.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/Button.js +11 -2
- package/dist/browser/actions/Button.js.map +1 -1
- package/dist/browser/actions/Disclosure.js +11 -8
- package/dist/browser/actions/Disclosure.js.map +1 -1
- package/dist/browser/actions/Dropdown.js +4 -1
- package/dist/browser/actions/Dropdown.js.map +1 -1
- package/dist/browser/actions/FilterChip.js +16 -2
- package/dist/browser/actions/FilterChip.js.map +1 -1
- package/dist/browser/actions/SplitButton.js +69 -22
- package/dist/browser/actions/SplitButton.js.map +1 -1
- package/dist/browser/actions/SpotlightSearch.js +3 -7
- package/dist/browser/actions/SpotlightSearch.js.map +1 -1
- package/dist/browser/actions/Tabs.js +132 -47
- package/dist/browser/actions/Tabs.js.map +1 -1
- package/dist/browser/actions/index.js +2 -2
- package/dist/browser/actions/index.js.map +1 -1
- package/dist/browser/chat/ChatComposer.js +751 -423
- package/dist/browser/chat/ChatComposer.js.map +1 -1
- package/dist/browser/chat/ChatContextPopup.js +123 -0
- package/dist/browser/chat/ChatContextPopup.js.map +1 -0
- package/dist/browser/chat/ChatPrimitives.js +141 -78
- package/dist/browser/chat/ChatPrimitives.js.map +1 -1
- package/dist/browser/chat/ChatTasks.js +112 -0
- package/dist/browser/chat/ChatTasks.js.map +1 -0
- package/dist/browser/chat/ChatTimeline.js +31 -14
- package/dist/browser/chat/ChatTimeline.js.map +1 -1
- package/dist/browser/chat/chat-behavior.js +0 -5
- package/dist/browser/chat/chat-behavior.js.map +1 -1
- package/dist/browser/chat/composer-document.js +55 -0
- package/dist/browser/chat/composer-document.js.map +1 -0
- package/dist/browser/chat/index.js +6 -1
- package/dist/browser/chat/index.js.map +1 -1
- package/dist/browser/chat/types.js.map +1 -1
- package/dist/browser/content/Chart.js +148 -239
- package/dist/browser/content/Chart.js.map +1 -1
- package/dist/browser/content/ChartExplorer.js +324 -0
- package/dist/browser/content/ChartExplorer.js.map +1 -0
- package/dist/browser/content/ChartExplorerControls.js +153 -0
- package/dist/browser/content/ChartExplorerControls.js.map +1 -0
- package/dist/browser/content/ChartFilterControls.js +200 -0
- package/dist/browser/content/ChartFilterControls.js.map +1 -0
- package/dist/browser/content/ChartSnapshotView.js +114 -0
- package/dist/browser/content/ChartSnapshotView.js.map +1 -0
- package/dist/browser/content/DataTable.js +48 -32
- package/dist/browser/content/DataTable.js.map +1 -1
- package/dist/browser/content/FileBrowser.js +3 -0
- package/dist/browser/content/FileBrowser.js.map +1 -1
- package/dist/browser/content/FileGrid.js +93 -0
- package/dist/browser/content/FileGrid.js.map +1 -0
- package/dist/browser/content/FileTree.js +2 -2
- package/dist/browser/content/FileTree.js.map +1 -1
- package/dist/browser/content/FileView.js +511 -162
- package/dist/browser/content/FileView.js.map +1 -1
- package/dist/browser/content/MarkdownView.js +6 -0
- package/dist/browser/content/MarkdownView.js.map +1 -1
- package/dist/browser/content/Pagination.js.map +1 -1
- package/dist/browser/content/PdfPreview.js +107 -90
- package/dist/browser/content/PdfPreview.js.map +1 -1
- package/dist/browser/content/chart-cursor.js +33 -0
- package/dist/browser/content/chart-cursor.js.map +1 -0
- package/dist/browser/content/chart-explorer.js +147 -0
- package/dist/browser/content/chart-explorer.js.map +1 -0
- package/dist/browser/content/chart-inspection.js +447 -0
- package/dist/browser/content/chart-inspection.js.map +1 -0
- package/dist/browser/content/chart-line-gaps.js +53 -0
- package/dist/browser/content/chart-line-gaps.js.map +1 -0
- package/dist/browser/content/chart-map-viewport.js +5 -1
- package/dist/browser/content/chart-map-viewport.js.map +1 -1
- package/dist/browser/content/chart-snapshot.js +63 -0
- package/dist/browser/content/chart-snapshot.js.map +1 -0
- package/dist/browser/content/chart-state-timeline.js +32 -4
- package/dist/browser/content/chart-state-timeline.js.map +1 -1
- package/dist/browser/content/chart-svg.js +54 -0
- package/dist/browser/content/chart-svg.js.map +1 -0
- package/dist/browser/content/collection-selection.js +109 -0
- package/dist/browser/content/collection-selection.js.map +1 -0
- package/dist/browser/content/delimited-preferences.js +21 -0
- package/dist/browser/content/delimited-preferences.js.map +1 -0
- package/dist/browser/content/file-tree.js.map +1 -1
- package/dist/browser/content/file-view-preview.js +11 -7
- package/dist/browser/content/file-view-preview.js.map +1 -1
- package/dist/browser/content/index.js +9 -0
- package/dist/browser/content/index.js.map +1 -1
- package/dist/browser/feedback/InlineGuidance.js +17 -3
- package/dist/browser/feedback/InlineGuidance.js.map +1 -1
- package/dist/browser/feedback/dialog-core.js +81 -7
- package/dist/browser/feedback/dialog-core.js.map +1 -1
- package/dist/browser/feedback/prompts.js +6 -0
- package/dist/browser/feedback/prompts.js.map +1 -1
- package/dist/browser/feedback/toast.js +29 -6
- package/dist/browser/feedback/toast.js.map +1 -1
- package/dist/browser/inputs/ChoiceGroups.js.map +1 -1
- package/dist/browser/inputs/Select.js.map +1 -1
- package/dist/browser/inputs/SelectChip.js +3 -2
- package/dist/browser/inputs/SelectChip.js.map +1 -1
- package/dist/browser/inputs/TextInput.js +7 -1
- package/dist/browser/inputs/TextInput.js.map +1 -1
- package/dist/browser/inputs/markdown/MarkdownEditor.js +61 -37
- package/dist/browser/inputs/markdown/MarkdownEditor.js.map +1 -1
- package/dist/browser/inputs/markdown/behaviors.js +1 -1
- package/dist/browser/inputs/markdown/behaviors.js.map +1 -1
- package/dist/browser/intl/Format.js +89 -16
- package/dist/browser/intl/Format.js.map +1 -1
- package/dist/browser/intl/index.js.map +1 -1
- package/dist/browser/intl/messages.js +130 -2
- package/dist/browser/intl/messages.js.map +1 -1
- package/dist/browser/layout/AppWorkspace.js +712 -624
- package/dist/browser/layout/AppWorkspace.js.map +1 -1
- package/dist/browser/layout/BottomSheet.js +95 -0
- package/dist/browser/layout/BottomSheet.js.map +1 -0
- package/dist/browser/layout/DetailPanel.js +56 -44
- package/dist/browser/layout/DetailPanel.js.map +1 -1
- package/dist/browser/layout/Navigation.js +278 -0
- package/dist/browser/layout/Navigation.js.map +1 -0
- package/dist/browser/layout/PanelDialog.js +219 -71
- package/dist/browser/layout/PanelDialog.js.map +1 -1
- package/dist/browser/layout/ScrollArea.js +21 -1
- package/dist/browser/layout/ScrollArea.js.map +1 -1
- package/dist/browser/layout/Settings.js.map +1 -1
- package/dist/browser/layout/SidebarItemPreview.js +183 -0
- package/dist/browser/layout/SidebarItemPreview.js.map +1 -0
- package/dist/browser/layout/app-workspace-controller.js +3 -0
- package/dist/browser/layout/app-workspace-controller.js.map +1 -1
- package/dist/browser/layout/app-workspace-state.js.map +1 -1
- package/dist/browser/layout/index.js +3 -0
- package/dist/browser/layout/index.js.map +1 -1
- package/dist/browser/layout/navigation-model.js +23 -0
- package/dist/browser/layout/navigation-model.js.map +1 -0
- package/dist/browser/layout/scroll-fade.js +100 -0
- package/dist/browser/layout/scroll-fade.js.map +1 -0
- package/dist/browser/surfaces/DescriptionList.js.map +1 -1
- package/dist/browser/surfaces/StatusBadge.js +2 -1
- package/dist/browser/surfaces/StatusBadge.js.map +1 -1
- package/dist/fonts/ibm-plex-mono-cyrillic-400-italic-4aded3f2f2a7d27d.woff2 +0 -0
- package/dist/fonts/ibm-plex-mono-cyrillic-400-normal-7635422bd10ddbbc.woff2 +0 -0
- package/dist/fonts/ibm-plex-mono-cyrillic-500-normal-1d89462e86cb8e87.woff2 +0 -0
- package/dist/fonts/ibm-plex-mono-cyrillic-600-normal-2b05a8695c7f9f4a.woff2 +0 -0
- package/dist/fonts/ibm-plex-mono-cyrillic-ext-400-italic-a0b3b8cbe5a516e7.woff2 +0 -0
- package/dist/fonts/ibm-plex-mono-cyrillic-ext-400-normal-f8c22ec1804bd696.woff2 +0 -0
- package/dist/fonts/ibm-plex-mono-cyrillic-ext-500-normal-3febe5c7f22e4b07.woff2 +0 -0
- package/dist/fonts/ibm-plex-mono-cyrillic-ext-600-normal-83109cdd4f8665b4.woff2 +0 -0
- package/dist/fonts/ibm-plex-mono-latin-400-italic-0840095faae86403.woff2 +0 -0
- package/dist/fonts/ibm-plex-mono-latin-400-normal-08949f728dc52d52.woff2 +0 -0
- package/dist/fonts/ibm-plex-mono-latin-500-normal-01d285447409c8a5.woff2 +0 -0
- package/dist/fonts/ibm-plex-mono-latin-600-normal-0d1f0b8d0722224e.woff2 +0 -0
- package/dist/fonts/ibm-plex-mono-latin-ext-400-italic-1b07eee6df7d26b3.woff2 +0 -0
- package/dist/fonts/ibm-plex-mono-latin-ext-400-normal-6bc0f226a5b7884a.woff2 +0 -0
- package/dist/fonts/ibm-plex-mono-latin-ext-500-normal-6bb06407c97584b0.woff2 +0 -0
- package/dist/fonts/ibm-plex-mono-latin-ext-600-normal-32057cf50dd14bdb.woff2 +0 -0
- package/dist/fonts/ibm-plex-mono-vietnamese-400-italic-a6bab38af4f9c761.woff2 +0 -0
- package/dist/fonts/ibm-plex-mono-vietnamese-400-normal-62632b6375305e70.woff2 +0 -0
- package/dist/fonts/ibm-plex-mono-vietnamese-500-normal-781633d95de88040.woff2 +0 -0
- package/dist/fonts/ibm-plex-mono-vietnamese-600-normal-51b74d53e106ba8a.woff2 +0 -0
- package/dist/fonts/ibm-plex-sans-cyrillic-400-italic-e8731a7e2b00fc4f.woff2 +0 -0
- package/dist/fonts/ibm-plex-sans-cyrillic-400-normal-69afad88a0740b6e.woff2 +0 -0
- package/dist/fonts/ibm-plex-sans-cyrillic-500-normal-200be3a2a6b1789f.woff2 +0 -0
- package/dist/fonts/ibm-plex-sans-cyrillic-600-normal-730becc6f005c18c.woff2 +0 -0
- package/dist/fonts/ibm-plex-sans-cyrillic-700-normal-40540598b4c9eb2c.woff2 +0 -0
- package/dist/fonts/ibm-plex-sans-cyrillic-ext-400-italic-4ffb25726a7ce4cc.woff2 +0 -0
- package/dist/fonts/ibm-plex-sans-cyrillic-ext-400-normal-e2580ad78906551e.woff2 +0 -0
- package/dist/fonts/ibm-plex-sans-cyrillic-ext-500-normal-08578d906af6d986.woff2 +0 -0
- package/dist/fonts/ibm-plex-sans-cyrillic-ext-600-normal-d60d3d0b182753d5.woff2 +0 -0
- package/dist/fonts/ibm-plex-sans-cyrillic-ext-700-normal-d07dd53642480097.woff2 +0 -0
- package/dist/fonts/ibm-plex-sans-greek-400-italic-1bc10b01688ba9fa.woff2 +0 -0
- package/dist/fonts/ibm-plex-sans-greek-400-normal-02296067bc904d2a.woff2 +0 -0
- package/dist/fonts/ibm-plex-sans-greek-500-normal-8cb6e20b4dbbaa5f.woff2 +0 -0
- package/dist/fonts/ibm-plex-sans-greek-600-normal-0a9ebd9019415ee9.woff2 +0 -0
- package/dist/fonts/ibm-plex-sans-greek-700-normal-c949641d10a3bebc.woff2 +0 -0
- package/dist/fonts/ibm-plex-sans-latin-400-italic-6de912e531b6c980.woff2 +0 -0
- package/dist/fonts/ibm-plex-sans-latin-400-normal-3b646991d30055a9.woff2 +0 -0
- package/dist/fonts/ibm-plex-sans-latin-500-normal-0717336fb31fcdcd.woff2 +0 -0
- package/dist/fonts/ibm-plex-sans-latin-600-normal-8960851d691c054e.woff2 +0 -0
- package/dist/fonts/ibm-plex-sans-latin-700-normal-42e7b0c143c19df9.woff2 +0 -0
- package/dist/fonts/ibm-plex-sans-latin-ext-400-italic-c5c00e8a32022dfe.woff2 +0 -0
- package/dist/fonts/ibm-plex-sans-latin-ext-400-normal-c93d2a12aaa280f6.woff2 +0 -0
- package/dist/fonts/ibm-plex-sans-latin-ext-500-normal-2846035d85100f84.woff2 +0 -0
- package/dist/fonts/ibm-plex-sans-latin-ext-600-normal-b25dfd4f979e442a.woff2 +0 -0
- package/dist/fonts/ibm-plex-sans-latin-ext-700-normal-92f0392bd74fa395.woff2 +0 -0
- package/dist/fonts/ibm-plex-sans-vietnamese-400-italic-675d4bace127bffb.woff2 +0 -0
- package/dist/fonts/ibm-plex-sans-vietnamese-400-normal-771538f7f26551bd.woff2 +0 -0
- package/dist/fonts/ibm-plex-sans-vietnamese-500-normal-85ba3d9c2488a813.woff2 +0 -0
- package/dist/fonts/ibm-plex-sans-vietnamese-600-normal-5d34b803637befe3.woff2 +0 -0
- package/dist/fonts/ibm-plex-sans-vietnamese-700-normal-b79d0c4b68b85007.woff2 +0 -0
- package/dist/plex.css +1 -1
- package/dist/ssr/actions/Button.js +11 -2
- package/dist/ssr/actions/Button.js.map +1 -1
- package/dist/ssr/actions/Disclosure.js +2 -2
- package/dist/ssr/actions/Disclosure.js.map +1 -1
- package/dist/ssr/actions/Dropdown.js +4 -1
- package/dist/ssr/actions/Dropdown.js.map +1 -1
- package/dist/ssr/actions/FilterChip.js +16 -2
- package/dist/ssr/actions/FilterChip.js.map +1 -1
- package/dist/ssr/actions/SplitButton.js +69 -22
- package/dist/ssr/actions/SplitButton.js.map +1 -1
- package/dist/ssr/actions/SpotlightSearch.js +3 -7
- package/dist/ssr/actions/SpotlightSearch.js.map +1 -1
- package/dist/ssr/actions/Tabs.js +58 -11
- package/dist/ssr/actions/Tabs.js.map +1 -1
- package/dist/ssr/actions/index.js +2 -2
- package/dist/ssr/actions/index.js.map +1 -1
- package/dist/ssr/chat/ChatComposer.js +366 -134
- package/dist/ssr/chat/ChatComposer.js.map +1 -1
- package/dist/ssr/chat/ChatContextPopup.js +86 -0
- package/dist/ssr/chat/ChatContextPopup.js.map +1 -0
- package/dist/ssr/chat/ChatPrimitives.js +49 -11
- package/dist/ssr/chat/ChatPrimitives.js.map +1 -1
- package/dist/ssr/chat/ChatTasks.js +48 -0
- package/dist/ssr/chat/ChatTasks.js.map +1 -0
- package/dist/ssr/chat/ChatTimeline.js +14 -4
- package/dist/ssr/chat/ChatTimeline.js.map +1 -1
- package/dist/ssr/chat/chat-behavior.js +0 -5
- package/dist/ssr/chat/chat-behavior.js.map +1 -1
- package/dist/ssr/chat/composer-document.js +55 -0
- package/dist/ssr/chat/composer-document.js.map +1 -0
- package/dist/ssr/chat/index.js +6 -1
- package/dist/ssr/chat/index.js.map +1 -1
- package/dist/ssr/chat/types.js.map +1 -1
- package/dist/ssr/content/Chart.js +121 -219
- package/dist/ssr/content/Chart.js.map +1 -1
- package/dist/ssr/content/ChartExplorer.js +257 -0
- package/dist/ssr/content/ChartExplorer.js.map +1 -0
- package/dist/ssr/content/ChartExplorerControls.js +105 -0
- package/dist/ssr/content/ChartExplorerControls.js.map +1 -0
- package/dist/ssr/content/ChartFilterControls.js +139 -0
- package/dist/ssr/content/ChartFilterControls.js.map +1 -0
- package/dist/ssr/content/ChartSnapshotView.js +58 -0
- package/dist/ssr/content/ChartSnapshotView.js.map +1 -0
- package/dist/ssr/content/DataTable.js +13 -9
- package/dist/ssr/content/DataTable.js.map +1 -1
- package/dist/ssr/content/FileBrowser.js +3 -0
- package/dist/ssr/content/FileBrowser.js.map +1 -1
- package/dist/ssr/content/FileGrid.js +38 -0
- package/dist/ssr/content/FileGrid.js.map +1 -0
- package/dist/ssr/content/FileTree.js +2 -2
- package/dist/ssr/content/FileTree.js.map +1 -1
- package/dist/ssr/content/FileView.js +356 -75
- package/dist/ssr/content/FileView.js.map +1 -1
- package/dist/ssr/content/MarkdownView.js +6 -0
- package/dist/ssr/content/MarkdownView.js.map +1 -1
- package/dist/ssr/content/Pagination.js.map +1 -1
- package/dist/ssr/content/PdfPreview.js +37 -24
- package/dist/ssr/content/PdfPreview.js.map +1 -1
- package/dist/ssr/content/chart-cursor.js +33 -0
- package/dist/ssr/content/chart-cursor.js.map +1 -0
- package/dist/ssr/content/chart-explorer.js +147 -0
- package/dist/ssr/content/chart-explorer.js.map +1 -0
- package/dist/ssr/content/chart-inspection.js +447 -0
- package/dist/ssr/content/chart-inspection.js.map +1 -0
- package/dist/ssr/content/chart-line-gaps.js +53 -0
- package/dist/ssr/content/chart-line-gaps.js.map +1 -0
- package/dist/ssr/content/chart-map-viewport.js +5 -1
- package/dist/ssr/content/chart-map-viewport.js.map +1 -1
- package/dist/ssr/content/chart-snapshot.js +63 -0
- package/dist/ssr/content/chart-snapshot.js.map +1 -0
- package/dist/ssr/content/chart-state-timeline.js +32 -4
- package/dist/ssr/content/chart-state-timeline.js.map +1 -1
- package/dist/ssr/content/chart-svg.js +54 -0
- package/dist/ssr/content/chart-svg.js.map +1 -0
- package/dist/ssr/content/collection-selection.js +109 -0
- package/dist/ssr/content/collection-selection.js.map +1 -0
- package/dist/ssr/content/delimited-preferences.js +21 -0
- package/dist/ssr/content/delimited-preferences.js.map +1 -0
- package/dist/ssr/content/file-tree.js.map +1 -1
- package/dist/ssr/content/file-view-preview.js +11 -7
- package/dist/ssr/content/file-view-preview.js.map +1 -1
- package/dist/ssr/content/index.js +9 -0
- package/dist/ssr/content/index.js.map +1 -1
- package/dist/ssr/feedback/InlineGuidance.js +17 -3
- package/dist/ssr/feedback/InlineGuidance.js.map +1 -1
- package/dist/ssr/feedback/dialog-core.js +81 -7
- package/dist/ssr/feedback/dialog-core.js.map +1 -1
- package/dist/ssr/feedback/prompts.js +6 -0
- package/dist/ssr/feedback/prompts.js.map +1 -1
- package/dist/ssr/feedback/toast.js +29 -6
- package/dist/ssr/feedback/toast.js.map +1 -1
- package/dist/ssr/inputs/ChoiceGroups.js.map +1 -1
- 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/TextInput.js.map +1 -1
- package/dist/ssr/inputs/markdown/MarkdownEditor.js +19 -11
- package/dist/ssr/inputs/markdown/MarkdownEditor.js.map +1 -1
- package/dist/ssr/inputs/markdown/behaviors.js +1 -1
- package/dist/ssr/inputs/markdown/behaviors.js.map +1 -1
- package/dist/ssr/intl/Format.js +61 -0
- package/dist/ssr/intl/Format.js.map +1 -1
- package/dist/ssr/intl/index.js.map +1 -1
- package/dist/ssr/intl/messages.js +130 -2
- package/dist/ssr/intl/messages.js.map +1 -1
- package/dist/ssr/layout/AppWorkspace.js +368 -275
- package/dist/ssr/layout/AppWorkspace.js.map +1 -1
- package/dist/ssr/layout/BottomSheet.js +43 -0
- package/dist/ssr/layout/BottomSheet.js.map +1 -0
- package/dist/ssr/layout/DetailPanel.js +11 -4
- package/dist/ssr/layout/DetailPanel.js.map +1 -1
- package/dist/ssr/layout/Navigation.js +181 -0
- package/dist/ssr/layout/Navigation.js.map +1 -0
- package/dist/ssr/layout/PanelDialog.js +111 -26
- package/dist/ssr/layout/PanelDialog.js.map +1 -1
- package/dist/ssr/layout/ScrollArea.js +16 -1
- package/dist/ssr/layout/ScrollArea.js.map +1 -1
- package/dist/ssr/layout/Settings.js.map +1 -1
- package/dist/ssr/layout/SidebarItemPreview.js +133 -0
- package/dist/ssr/layout/SidebarItemPreview.js.map +1 -0
- package/dist/ssr/layout/app-workspace-controller.js +3 -0
- package/dist/ssr/layout/app-workspace-controller.js.map +1 -1
- package/dist/ssr/layout/app-workspace-state.js.map +1 -1
- package/dist/ssr/layout/index.js +3 -0
- package/dist/ssr/layout/index.js.map +1 -1
- package/dist/ssr/layout/navigation-model.js +23 -0
- package/dist/ssr/layout/navigation-model.js.map +1 -0
- package/dist/ssr/layout/scroll-fade.js +100 -0
- package/dist/ssr/layout/scroll-fade.js.map +1 -0
- package/dist/ssr/surfaces/DescriptionList.js.map +1 -1
- package/dist/ssr/surfaces/StatusBadge.js +2 -1
- package/dist/ssr/surfaces/StatusBadge.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/tabler.css +1 -1
- package/dist/types/actions/Button.d.ts +4 -0
- package/dist/types/actions/Disclosure.d.ts +1 -0
- package/dist/types/actions/FilterChip.d.ts +4 -0
- package/dist/types/actions/SplitButton.d.ts +6 -0
- package/dist/types/actions/SpotlightSearch.d.ts +0 -4
- package/dist/types/actions/Tabs.d.ts +4 -0
- package/dist/types/actions/index.d.ts +4 -4
- package/dist/types/chat/ChatComposer.d.ts +20 -2
- package/dist/types/chat/ChatContextPopup.d.ts +6 -0
- package/dist/types/chat/ChatPrimitives.d.ts +4 -0
- package/dist/types/chat/ChatTasks.d.ts +15 -0
- package/dist/types/chat/ChatTimeline.d.ts +2 -0
- package/dist/types/chat/chat-behavior.d.ts +0 -3
- package/dist/types/chat/composer-document.d.ts +14 -0
- package/dist/types/chat/index.d.ts +8 -1
- package/dist/types/chat/types.d.ts +7 -0
- package/dist/types/content/Chart.d.ts +42 -23
- package/dist/types/content/ChartExplorer.d.ts +34 -0
- package/dist/types/content/ChartExplorerControls.d.ts +10 -0
- package/dist/types/content/ChartFilterControls.d.ts +21 -0
- package/dist/types/content/ChartSnapshotView.d.ts +11 -0
- package/dist/types/content/DataTable.d.ts +4 -0
- package/dist/types/content/FileBrowser.d.ts +1 -0
- package/dist/types/content/FileGrid.d.ts +21 -0
- package/dist/types/content/FileView.d.ts +20 -0
- package/dist/types/content/PdfPreview.d.ts +8 -1
- package/dist/types/content/chart-cursor.d.ts +15 -0
- package/dist/types/content/chart-explorer.d.ts +48 -0
- package/dist/types/content/chart-inspection.d.ts +40 -0
- package/dist/types/content/chart-line-gaps.d.ts +5 -0
- package/dist/types/content/chart-map-viewport.d.ts +1 -1
- package/dist/types/content/chart-snapshot.d.ts +26 -0
- package/dist/types/content/chart-svg.d.ts +21 -0
- package/dist/types/content/collection-selection.d.ts +24 -0
- package/dist/types/content/delimited-preferences.d.ts +11 -0
- package/dist/types/content/file-tree.d.ts +2 -0
- package/dist/types/content/file-view-preview.d.ts +4 -1
- package/dist/types/content/index.d.ts +16 -2
- package/dist/types/feedback/InlineGuidance.d.ts +1 -0
- package/dist/types/feedback/dialog-core.d.ts +11 -0
- package/dist/types/feedback/prompts.d.ts +2 -0
- package/dist/types/feedback/toast.d.ts +7 -1
- package/dist/types/inputs/markdown/MarkdownEditor.d.ts +5 -1
- package/dist/types/intl/Format.d.ts +9 -0
- package/dist/types/intl/index.d.ts +1 -1
- package/dist/types/intl/messages.d.ts +31 -1
- package/dist/types/layout/AppWorkspace.d.ts +35 -18
- package/dist/types/layout/BottomSheet.d.ts +23 -0
- package/dist/types/layout/DetailPanel.d.ts +1 -0
- package/dist/types/layout/Navigation.d.ts +8 -0
- package/dist/types/layout/PanelDialog.d.ts +14 -1
- package/dist/types/layout/ScrollArea.d.ts +4 -0
- package/dist/types/layout/Settings.d.ts +1 -1
- package/dist/types/layout/SidebarItemPreview.d.ts +11 -0
- package/dist/types/layout/index.d.ts +4 -1
- package/dist/types/layout/navigation-model.d.ts +48 -0
- package/dist/types/layout/scroll-fade.d.ts +3 -0
- package/dist/types/surfaces/DescriptionList.d.ts +1 -1
- package/dist/types/surfaces/StatusBadge.d.ts +1 -1
- package/package.json +5 -7
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["DEFAULT_MAP_VIEWPORT","latitude","longitude","zoom","MIN_ZOOM","MAX_ZOOM","clamp","value","min","max","Math","normalizeMapViewport","viewport","Number","isFinite","scale","latitudeLimit","longitudeLimit","zoomMapViewport","delta","panMapViewport","deltaX","deltaY","width","height"],"sources":["content/chart-map-viewport.ts"],"sourcesContent":["import type { MapViewport } from \"@k2b/stdlib\";\n\nexport const DEFAULT_MAP_VIEWPORT: MapViewport = {\n latitude: 0,\n longitude: 0,\n zoom: 0,\n};\n\nconst MIN_ZOOM = 0;\nconst MAX_ZOOM = 5;\n\nconst clamp = (value: number, min: number, max: number): number => Math.min(max, Math.max(min, value));\n\nexport const normalizeMapViewport = (viewport: MapViewport | undefined): MapViewport => {\n const zoom = clamp(viewport && Number.isFinite(viewport.zoom) ? viewport.zoom : MIN_ZOOM, MIN_ZOOM, MAX_ZOOM);\n const scale = 2 ** zoom;\n const latitudeLimit = 90 - 90 / scale;\n const longitudeLimit = 180 - 180 / scale;\n\n return {\n latitude: clamp(viewport && Number.isFinite(viewport.latitude) ? viewport.latitude : 0, -latitudeLimit, latitudeLimit),\n longitude: clamp(viewport && Number.isFinite(viewport.longitude) ? viewport.longitude : 0, -longitudeLimit, longitudeLimit),\n zoom,\n };\n};\n\nexport const zoomMapViewport = (viewport: MapViewport,
|
|
1
|
+
{"version":3,"names":["DEFAULT_MAP_VIEWPORT","latitude","longitude","zoom","MIN_ZOOM","MAX_ZOOM","clamp","value","min","max","Math","normalizeMapViewport","viewport","Number","isFinite","scale","latitudeLimit","longitudeLimit","zoomMapViewport","delta","focus","panMapViewport","deltaX","deltaY","width","height"],"sources":["content/chart-map-viewport.ts"],"sourcesContent":["import type { MapViewport } from \"@k2b/stdlib\";\n\nexport const DEFAULT_MAP_VIEWPORT: MapViewport = {\n latitude: 0,\n longitude: 0,\n zoom: 0,\n};\n\nconst MIN_ZOOM = 0;\nconst MAX_ZOOM = 5;\n\nconst clamp = (value: number, min: number, max: number): number => Math.min(max, Math.max(min, value));\n\nexport const normalizeMapViewport = (viewport: MapViewport | undefined): MapViewport => {\n const zoom = clamp(viewport && Number.isFinite(viewport.zoom) ? viewport.zoom : MIN_ZOOM, MIN_ZOOM, MAX_ZOOM);\n const scale = 2 ** zoom;\n const latitudeLimit = 90 - 90 / scale;\n const longitudeLimit = 180 - 180 / scale;\n\n return {\n latitude: clamp(viewport && Number.isFinite(viewport.latitude) ? viewport.latitude : 0, -latitudeLimit, latitudeLimit),\n longitude: clamp(viewport && Number.isFinite(viewport.longitude) ? viewport.longitude : 0, -longitudeLimit, longitudeLimit),\n zoom,\n };\n};\n\nexport const zoomMapViewport = (\n viewport: MapViewport,\n delta: number,\n focus: Pick<MapViewport, \"latitude\" | \"longitude\"> = { latitude: 50, longitude: 10 },\n): MapViewport =>\n normalizeMapViewport({\n ...viewport,\n ...(viewport.zoom === 0 && delta > 0 ? focus : {}),\n zoom: viewport.zoom + delta,\n });\n\nexport const panMapViewport = (viewport: MapViewport, deltaX: number, deltaY: number, width: number, height: number): MapViewport => {\n if (width <= 0 || height <= 0) return normalizeMapViewport(viewport);\n\n const scale = 2 ** viewport.zoom;\n return normalizeMapViewport({\n latitude: viewport.latitude + (deltaY / height) * (180 / scale),\n longitude: viewport.longitude - (deltaX / width) * (360 / scale),\n zoom: viewport.zoom,\n });\n};\n"],"mappings":"AAEA,OAAO,MAAMA,oBAAiC,GAAG;EAC/CC,QAAQ,EAAE,CAAC;EACXC,SAAS,EAAE,CAAC;EACZC,IAAI,EAAE;AACR,CAAC;AAED,MAAMC,QAAQ,GAAG,CAAC;AAClB,MAAMC,QAAQ,GAAG,CAAC;AAElB,MAAMC,KAAK,GAAGA,CAACC,KAAa,EAAEC,GAAW,EAAEC,GAAW,KAAaC,IAAI,CAACF,GAAG,CAACC,GAAG,EAAEC,IAAI,CAACD,GAAG,CAACD,GAAG,EAAED,KAAK,CAAC,CAAC;AAEtG,OAAO,MAAMI,oBAAoB,GAAIC,QAAiC,IAAkB;EACtF,MAAMT,IAAI,GAAGG,KAAK,CAACM,QAAQ,IAAIC,MAAM,CAACC,QAAQ,CAACF,QAAQ,CAACT,IAAI,CAAC,GAAGS,QAAQ,CAACT,IAAI,GAAGC,QAAQ,EAAEA,QAAQ,EAAEC,QAAQ,CAAC;EAC7G,MAAMU,KAAK,GAAG,CAAC,IAAIZ,IAAI;EACvB,MAAMa,aAAa,GAAG,EAAE,GAAG,EAAE,GAAGD,KAAK;EACrC,MAAME,cAAc,GAAG,GAAG,GAAG,GAAG,GAAGF,KAAK;EAExC,OAAO;IACLd,QAAQ,EAAEK,KAAK,CAACM,QAAQ,IAAIC,MAAM,CAACC,QAAQ,CAACF,QAAQ,CAACX,QAAQ,CAAC,GAAGW,QAAQ,CAACX,QAAQ,GAAG,CAAC,EAAE,CAACe,aAAa,EAAEA,aAAa,CAAC;IACtHd,SAAS,EAAEI,KAAK,CAACM,QAAQ,IAAIC,MAAM,CAACC,QAAQ,CAACF,QAAQ,CAACV,SAAS,CAAC,GAAGU,QAAQ,CAACV,SAAS,GAAG,CAAC,EAAE,CAACe,cAAc,EAAEA,cAAc,CAAC;IAC3Hd;EACF,CAAC;AACH,CAAC;AAED,OAAO,MAAMe,eAAe,GAAGA,CAC7BN,QAAqB,EACrBO,KAAa,EACbC,KAAkD,GAAG;EAAEnB,QAAQ,EAAE,EAAE;EAAEC,SAAS,EAAE;AAAG,CAAC,KAEpFS,oBAAoB,CAAC;EACnB,GAAGC,QAAQ;EACX,IAAIA,QAAQ,CAACT,IAAI,KAAK,CAAC,IAAIgB,KAAK,GAAG,CAAC,GAAGC,KAAK,GAAG,CAAC,CAAC,CAAC;EAClDjB,IAAI,EAAES,QAAQ,CAACT,IAAI,GAAGgB;AACxB,CAAC,CAAC;AAEJ,OAAO,MAAME,cAAc,GAAGA,CAACT,QAAqB,EAAEU,MAAc,EAAEC,MAAc,EAAEC,KAAa,EAAEC,MAAc,KAAkB;EACnI,IAAID,KAAK,IAAI,CAAC,IAAIC,MAAM,IAAI,CAAC,EAAE,OAAOd,oBAAoB,CAACC,QAAQ,CAAC;EAEpE,MAAMG,KAAK,GAAG,CAAC,IAAIH,QAAQ,CAACT,IAAI;EAChC,OAAOQ,oBAAoB,CAAC;IAC1BV,QAAQ,EAAEW,QAAQ,CAACX,QAAQ,GAAIsB,MAAM,GAAGE,MAAM,IAAK,GAAG,GAAGV,KAAK,CAAC;IAC/Db,SAAS,EAAEU,QAAQ,CAACV,SAAS,GAAIoB,MAAM,GAAGE,KAAK,IAAK,GAAG,GAAGT,KAAK,CAAC;IAChEZ,IAAI,EAAES,QAAQ,CAACT;EACjB,CAAC,CAAC;AACJ,CAAC","ignoreList":[]}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { escapeXml } from "@k2b/stdlib";
|
|
2
|
+
import { chartRenderHeight, renderChartSvg } from "./Chart";
|
|
3
|
+
import { isChartDatum } from "./chart-inspection";
|
|
4
|
+
|
|
5
|
+
/** Trusted output of prepareChartSnapshot; never accept arbitrary user SVG. */
|
|
6
|
+
|
|
7
|
+
// Matches metadata emitted by our SVG renderer, not arbitrary XML.
|
|
8
|
+
const decodeAttribute = value => value.replace(/"/g, '"').replace(/'|'/g, "'").replace(/</g, "<").replace(/>/g, ">").replace(/&/g, "&");
|
|
9
|
+
|
|
10
|
+
/** Pure SVG preparation for server or browser. Transfer only this output across SSR boundaries. */
|
|
11
|
+
export function prepareChartSnapshot(options, inspection) {
|
|
12
|
+
const width = 480;
|
|
13
|
+
const height = chartRenderHeight(options);
|
|
14
|
+
const svg = renderChartSvg({
|
|
15
|
+
...options,
|
|
16
|
+
interactive: true
|
|
17
|
+
}, width, height);
|
|
18
|
+
const marks = [];
|
|
19
|
+
const keys = new Set();
|
|
20
|
+
for (const match of svg.matchAll(/data-chart-datum="([^"]*)"/g)) {
|
|
21
|
+
const datum = JSON.parse(decodeAttribute(match[1]));
|
|
22
|
+
if (!isChartDatum(datum)) throw new Error("Invalid renderer chart metadata");
|
|
23
|
+
const selection = {
|
|
24
|
+
kind: options.kind,
|
|
25
|
+
datum
|
|
26
|
+
};
|
|
27
|
+
const key = inspection.key(selection);
|
|
28
|
+
if (!key || keys.has(key)) throw new Error("Chart snapshot requires a unique nonempty key for every mark");
|
|
29
|
+
keys.add(key);
|
|
30
|
+
const rowKey = inspection.rowKey?.(selection) ?? key;
|
|
31
|
+
if (!rowKey) throw new Error("Chart marks require a nonempty rowKey");
|
|
32
|
+
marks.push({
|
|
33
|
+
key,
|
|
34
|
+
rowKey,
|
|
35
|
+
datum,
|
|
36
|
+
tooltip: inspection.tooltip(selection),
|
|
37
|
+
...(inspection.reference?.(selection) ? {
|
|
38
|
+
reference: true
|
|
39
|
+
} : {})
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
let markIndex = 0;
|
|
43
|
+
const formattedSvg = svg.replace(/(<g data-chart-role="[^"]*" data-chart-datum="[^"]*"><title>)[\s\S]*?<\/title>/g, (_match, opening, offset) => {
|
|
44
|
+
const mark = marks[markIndex++];
|
|
45
|
+
const tooltip = mark.tooltip;
|
|
46
|
+
const text = [tooltip.title, ...tooltip.rows.map(row => `${row.label}: ${row.value}`)].filter(Boolean).join(" · ");
|
|
47
|
+
if (mark.reference) {
|
|
48
|
+
const children = svg.slice(offset, svg.indexOf("</g>", offset));
|
|
49
|
+
const palette = Number(children.match(/stdlib-chart-series-(\d+)/)?.[1] ?? mark.datum.seriesIndex ?? 0) % 8 + 1;
|
|
50
|
+
opening = opening.replace("<g ", `<g data-chart-reference="true" style="--k2b-chart-reference-color:var(--stdlib-chart-c${palette})" `);
|
|
51
|
+
}
|
|
52
|
+
return `${opening}${escapeXml(text)}</title>`;
|
|
53
|
+
});
|
|
54
|
+
return {
|
|
55
|
+
kind: options.kind,
|
|
56
|
+
svg: formattedSvg,
|
|
57
|
+
width,
|
|
58
|
+
height,
|
|
59
|
+
stretch: !["map", "pie", "donut", "gauge"].includes(options.kind),
|
|
60
|
+
marks
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=chart-snapshot.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["escapeXml","chartRenderHeight","renderChartSvg","isChartDatum","decodeAttribute","value","replace","prepareChartSnapshot","options","inspection","width","height","svg","interactive","marks","keys","Set","match","matchAll","datum","JSON","parse","Error","selection","kind","key","has","add","rowKey","push","tooltip","reference","markIndex","formattedSvg","_match","opening","offset","mark","text","title","rows","map","row","label","filter","Boolean","join","children","slice","indexOf","palette","Number","seriesIndex","stretch","includes"],"sources":["content/chart-snapshot.ts"],"sourcesContent":["import { type ChartDatum, escapeXml } from \"@k2b/stdlib\";\nimport { type ChartKind, type ChartRenderOptions, chartRenderHeight, renderChartSvg } from \"./Chart\";\nimport { type ChartSelection, type ChartTooltip, type ChartTooltipFormatter, isChartDatum } from \"./chart-inspection\";\n\n/** Trusted output of prepareChartSnapshot; never accept arbitrary user SVG. */\nexport type ChartSnapshot = {\n kind: ChartKind;\n svg: string;\n width: number;\n height: number;\n stretch: boolean;\n marks: readonly { key: string; rowKey: string; datum: ChartDatum; tooltip: ChartTooltip; reference?: boolean }[];\n};\n\n// Matches metadata emitted by our SVG renderer, not arbitrary XML.\nconst decodeAttribute = (value: string) =>\n value\n .replace(/"/g, '\"')\n .replace(/'|'/g, \"'\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/&/g, \"&\");\n\n/** Pure SVG preparation for server or browser. Transfer only this output across SSR boundaries. */\nexport function prepareChartSnapshot(\n options: ChartRenderOptions,\n inspection: {\n key: (selection: ChartSelection) => string;\n /** Defaults to the mark key for one-to-one charts. */\n rowKey?: (selection: ChartSelection) => string;\n tooltip: ChartTooltipFormatter;\n reference?: (selection: ChartSelection) => boolean;\n },\n): ChartSnapshot {\n const width = 480;\n const height = chartRenderHeight(options);\n const svg = renderChartSvg({ ...options, interactive: true }, width, height);\n const marks: ChartSnapshot[\"marks\"][number][] = [];\n const keys = new Set<string>();\n for (const match of svg.matchAll(/data-chart-datum=\"([^\"]*)\"/g)) {\n const datum: unknown = JSON.parse(decodeAttribute(match[1]!));\n if (!isChartDatum(datum)) throw new Error(\"Invalid renderer chart metadata\");\n const selection = { kind: options.kind, datum };\n const key = inspection.key(selection);\n if (!key || keys.has(key)) throw new Error(\"Chart snapshot requires a unique nonempty key for every mark\");\n keys.add(key);\n const rowKey = inspection.rowKey?.(selection) ?? key;\n if (!rowKey) throw new Error(\"Chart marks require a nonempty rowKey\");\n marks.push({\n key,\n rowKey,\n datum,\n tooltip: inspection.tooltip(selection),\n ...(inspection.reference?.(selection) ? { reference: true } : {}),\n });\n }\n let markIndex = 0;\n const formattedSvg = svg.replace(\n /(<g data-chart-role=\"[^\"]*\" data-chart-datum=\"[^\"]*\"><title>)[\\s\\S]*?<\\/title>/g,\n (_match, opening: string, offset: number) => {\n const mark = marks[markIndex++]!;\n const tooltip = mark.tooltip;\n const text = [tooltip.title, ...tooltip.rows.map((row) => `${row.label}: ${row.value}`)].filter(Boolean).join(\" · \");\n if (mark.reference) {\n const children = svg.slice(offset, svg.indexOf(\"</g>\", offset));\n const palette = (Number(children.match(/stdlib-chart-series-(\\d+)/)?.[1] ?? mark.datum.seriesIndex ?? 0) % 8) + 1;\n opening = opening.replace(\n \"<g \",\n `<g data-chart-reference=\"true\" style=\"--k2b-chart-reference-color:var(--stdlib-chart-c${palette})\" `,\n );\n }\n return `${opening}${escapeXml(text)}</title>`;\n },\n );\n return { kind: options.kind, svg: formattedSvg, width, height, stretch: ![\"map\", \"pie\", \"donut\", \"gauge\"].includes(options.kind), marks };\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { computeDomain, escapeXml, extendDomainToNice, mapRange, niceStep, svgRoot } from "@k2b/stdlib";
|
|
1
|
+
import { chartDatumSvg, computeDomain, escapeXml, extendDomainToNice, mapRange, niceStep, svgRoot } from "@k2b/stdlib";
|
|
2
2
|
const ROW_HEIGHT = 24;
|
|
3
3
|
const TOP = 38;
|
|
4
4
|
const AXIS_HEIGHT = 28;
|
|
@@ -45,7 +45,7 @@ const interactiveGroup = (body, href, tooltip, ariaLabel) => {
|
|
|
45
45
|
const safe = safeHref(href);
|
|
46
46
|
const attrs = [`aria-label="${escapeXml(ariaLabel)}"`, tooltip ? `data-chart-tooltip="${escapeXml(tooltip)}"` : ""].filter(Boolean).join(" ");
|
|
47
47
|
const title = tooltip ? `<title>${escapeXml(tooltip)}</title>` : "";
|
|
48
|
-
return safe ? `<a href="${escapeXml(safe)}" ${attrs}>${title}${body}</a>` : `<g ${attrs}${tooltip ? '
|
|
48
|
+
return safe ? `<a href="${escapeXml(safe)}" ${attrs}>${title}${body}</a>` : `<g ${attrs}${tooltip ? ' role="img"' : ""}>${title}${body}</g>`;
|
|
49
49
|
};
|
|
50
50
|
export const renderStateTimelineSvg = opts => {
|
|
51
51
|
const {
|
|
@@ -77,7 +77,7 @@ export const renderStateTimelineSvg = opts => {
|
|
|
77
77
|
const label = truncate(row.label, maxLabelChars);
|
|
78
78
|
const labelBody = `<text class="stdlib-chart-state-label" x="${fmt(plotLeft - 8)}" y="${fmt(y + ROW_HEIGHT / 2)}" text-anchor="end" dominant-baseline="middle">${escapeXml(label)}</text>`;
|
|
79
79
|
body.push(interactiveGroup(labelBody, row.href, row.tooltip ?? row.label, row.label));
|
|
80
|
-
for (const interval of row.intervals) {
|
|
80
|
+
for (const [index, interval] of row.intervals.entries()) {
|
|
81
81
|
if (!Number.isFinite(interval.from) || !Number.isFinite(interval.to)) continue;
|
|
82
82
|
const intervalFrom = Math.min(interval.from, interval.to);
|
|
83
83
|
const intervalTo = Math.max(interval.from, interval.to);
|
|
@@ -91,7 +91,33 @@ export const renderStateTimelineSvg = opts => {
|
|
|
91
91
|
const color = style?.color ? ` fill="${escapeXml(style.color)}"` : "";
|
|
92
92
|
const rect = `<rect class="stdlib-chart-state-region stdlib-chart-series-${stateIndex % 8}"${color} x="${fmt(x)}" y="${fmt(y + 3)}" width="${fmt(Math.max(2, x2 - x))}" height="${ROW_HEIGHT - 6}" rx="3"/>`;
|
|
93
93
|
const stateLabel = style?.label ?? interval.state;
|
|
94
|
-
body.push(interactiveGroup(rect,
|
|
94
|
+
body.push(interactiveGroup(chartDatumSvg(rect, {
|
|
95
|
+
index,
|
|
96
|
+
seriesIndex: rowIndex,
|
|
97
|
+
role: "interval",
|
|
98
|
+
label: row.label,
|
|
99
|
+
anchor: [(x + x2) / 2, y + ROW_HEIGHT / 2],
|
|
100
|
+
grid: [index, rowIndex],
|
|
101
|
+
values: [{
|
|
102
|
+
key: "state",
|
|
103
|
+
value: interval.state,
|
|
104
|
+
formatted: stateLabel
|
|
105
|
+
}, {
|
|
106
|
+
key: "from",
|
|
107
|
+
value: intervalFrom,
|
|
108
|
+
formatted: opts.xAxis?.format?.(intervalFrom)
|
|
109
|
+
}, {
|
|
110
|
+
key: "to",
|
|
111
|
+
value: intervalTo,
|
|
112
|
+
formatted: opts.xAxis?.format?.(intervalTo)
|
|
113
|
+
}, {
|
|
114
|
+
key: "duration",
|
|
115
|
+
value: intervalTo - intervalFrom
|
|
116
|
+
}, ...(interval.tooltip ?? interval.label ? [{
|
|
117
|
+
key: "detail",
|
|
118
|
+
value: interval.tooltip ?? interval.label ?? ""
|
|
119
|
+
}] : [])]
|
|
120
|
+
}, opts.interactive), interval.href, interval.tooltip ?? interval.label, [row.label, interval.label, stateLabel].filter(Boolean).join(", ")));
|
|
95
121
|
}
|
|
96
122
|
});
|
|
97
123
|
const tickTarget = Math.max(2, Math.min(8, Math.floor((plotRight - plotLeft) / 110)));
|
|
@@ -106,6 +132,7 @@ export const renderStateTimelineSvg = opts => {
|
|
|
106
132
|
body.push(`<text class="stdlib-chart-axis-label" x="${fmt((plotLeft + plotRight) / 2)}" y="${fmt(rowsBottom + AXIS_HEIGHT - 2)}" text-anchor="middle">${escapeXml(opts.xAxis.label)}</text>`);
|
|
107
133
|
}
|
|
108
134
|
if (showLegend) {
|
|
135
|
+
body.push('<g class="stdlib-chart-legend">');
|
|
109
136
|
let x = plotLeft;
|
|
110
137
|
const y = height - 9;
|
|
111
138
|
for (const [index, state] of (opts.states ?? []).entries()) {
|
|
@@ -114,6 +141,7 @@ export const renderStateTimelineSvg = opts => {
|
|
|
114
141
|
body.push(`<rect class="stdlib-chart-series-${index % 8}"${color} x="${fmt(x)}" y="${y - 8}" width="8" height="8" rx="2"/>`, `<text class="stdlib-chart-heatmap-label" x="${fmt(x + 12)}" y="${y}" text-anchor="start">${escapeXml(label)}</text>`);
|
|
115
142
|
x += 20 + label.length * 6.2;
|
|
116
143
|
}
|
|
144
|
+
body.push("</g>");
|
|
117
145
|
}
|
|
118
146
|
return svgRoot({
|
|
119
147
|
width,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["computeDomain","escapeXml","extendDomainToNice","mapRange","niceStep","svgRoot","ROW_HEIGHT","TOP","AXIS_HEIGHT","LEGEND_HEIGHT","MIN_VIEW_FRACTION","finiteDomain","domain","Number","isFinite","stateTimelineDomain","rows","explicit","flatMap","row","intervals","interval","from","to","normalizeStateTimelineViewport","viewport","fullDomain","full","candidate","span","Math","min","max","zoomStateTimelineViewport","delta","anchor","current","fullSpan","minSpan","factor","nextSpan","safeAnchor","anchorValue","panStateTimelineViewport","pixelDelta","plotWidth","timeDelta","stateTimelineHeight","legend","fmt","value","isInteger","String","toFixed","safeHref","href","startsWith","truncate","maxChars","length","slice","interactiveGroup","body","tooltip","ariaLabel","safe","attrs","filter","Boolean","join","title","renderStateTimelineSvg","opts","width","height","showLegend","states","legendHeight","labels","map","label","idealGutter","gutter","plotLeft","plotRight","rowsBottom","stateStyles","Map","state","index","stateKeys","Set","i","stateIndexes","maxLabelChars","floor","forEach","rowIndex","y","labelBody","push","intervalFrom","intervalTo","x","x2","style","get","stateIndex","color","rect","stateLabel","tickTarget","ticks","format","xAxis","tick","entries","className"],"sources":["content/chart-state-timeline.ts"],"sourcesContent":["import { computeDomain, escapeXml, extendDomainToNice, mapRange, niceStep, svgRoot } from \"@k2b/stdlib\";\n\nexport type StateTimelineDomain = readonly [number, number];\n\nexport type StateTimelineInterval = {\n from: number;\n to: number;\n state: string;\n label?: string;\n href?: string;\n tooltip?: string;\n};\n\nexport type StateTimelineRow = {\n label: string;\n href?: string;\n tooltip?: string;\n intervals: StateTimelineInterval[];\n};\n\nexport type StateTimelineState = {\n state: string;\n label?: string;\n color?: string;\n};\n\nexport type StateTimelineChartOptions = {\n rows: StateTimelineRow[];\n states?: StateTimelineState[];\n domain?: StateTimelineDomain;\n xAxis?: { format?: (value: number) => string; label?: string };\n legend?: boolean;\n interactive?: boolean;\n};\n\nconst ROW_HEIGHT = 24;\nconst TOP = 38;\nconst AXIS_HEIGHT = 28;\nconst LEGEND_HEIGHT = 24;\nconst MIN_VIEW_FRACTION = 1 / 64;\n\nconst finiteDomain = (domain: StateTimelineDomain): StateTimelineDomain | null => {\n if (!Number.isFinite(domain[0]) || !Number.isFinite(domain[1]) || domain[0] === domain[1]) return null;\n return domain[0] < domain[1] ? domain : [domain[1], domain[0]];\n};\n\nexport const stateTimelineDomain = (rows: readonly StateTimelineRow[], domain?: StateTimelineDomain): StateTimelineDomain => {\n const explicit = domain ? finiteDomain(domain) : null;\n if (explicit) return explicit;\n return computeDomain(rows.flatMap((row) => row.intervals.flatMap((interval) => [interval.from, interval.to])));\n};\n\nexport const normalizeStateTimelineViewport = (\n viewport: StateTimelineDomain | undefined,\n fullDomain: StateTimelineDomain,\n): StateTimelineDomain => {\n const full = finiteDomain(fullDomain) ?? [0, 1];\n const candidate = viewport ? finiteDomain(viewport) : null;\n if (!candidate) return full;\n const span = Math.min(candidate[1] - candidate[0], full[1] - full[0]);\n const from = Math.max(full[0], Math.min(candidate[0], full[1] - span));\n return [from, from + span];\n};\n\nexport const zoomStateTimelineViewport = (\n viewport: StateTimelineDomain,\n fullDomain: StateTimelineDomain,\n delta: number,\n anchor = 0.5,\n): StateTimelineDomain => {\n const current = normalizeStateTimelineViewport(viewport, fullDomain);\n const fullSpan = fullDomain[1] - fullDomain[0];\n const minSpan = Math.max(1, fullSpan * MIN_VIEW_FRACTION);\n const factor = delta > 0 ? 0.7 : 1 / 0.7;\n const nextSpan = Math.max(minSpan, Math.min(fullSpan, (current[1] - current[0]) * factor));\n const safeAnchor = Math.max(0, Math.min(1, anchor));\n const anchorValue = current[0] + (current[1] - current[0]) * safeAnchor;\n return normalizeStateTimelineViewport([anchorValue - nextSpan * safeAnchor, anchorValue + nextSpan * (1 - safeAnchor)], fullDomain);\n};\n\nexport const panStateTimelineViewport = (\n viewport: StateTimelineDomain,\n fullDomain: StateTimelineDomain,\n pixelDelta: number,\n plotWidth: number,\n): StateTimelineDomain => {\n if (plotWidth <= 0) return normalizeStateTimelineViewport(viewport, fullDomain);\n const current = normalizeStateTimelineViewport(viewport, fullDomain);\n const timeDelta = (-pixelDelta / plotWidth) * (current[1] - current[0]);\n return normalizeStateTimelineViewport([current[0] + timeDelta, current[1] + timeDelta], fullDomain);\n};\n\nexport const stateTimelineHeight = (rows: number, legend = true): number =>\n Math.max(160, TOP + rows * ROW_HEIGHT + AXIS_HEIGHT + (legend ? LEGEND_HEIGHT : 0));\n\nconst fmt = (value: number): string => (Number.isInteger(value) ? String(value) : value.toFixed(2));\n\nconst safeHref = (href: string | undefined): string | null => (href && href.startsWith(\"/\") && !href.startsWith(\"//\") ? href : null);\n\nconst truncate = (value: string, maxChars: number): string =>\n value.length <= maxChars ? value : `${value.slice(0, Math.max(1, maxChars - 1))}…`;\n\nconst interactiveGroup = (body: string, href: string | undefined, tooltip: string | undefined, ariaLabel: string): string => {\n const safe = safeHref(href);\n const attrs = [`aria-label=\"${escapeXml(ariaLabel)}\"`, tooltip ? `data-chart-tooltip=\"${escapeXml(tooltip)}\"` : \"\"]\n .filter(Boolean)\n .join(\" \");\n const title = tooltip ? `<title>${escapeXml(tooltip)}</title>` : \"\";\n return safe\n ? `<a href=\"${escapeXml(safe)}\" ${attrs}>${title}${body}</a>`\n : `<g ${attrs}${tooltip ? ' tabindex=\"0\" role=\"img\"' : \"\"}>${title}${body}</g>`;\n};\n\nexport const renderStateTimelineSvg = (\n opts: StateTimelineChartOptions & {\n width: number;\n height: number;\n viewport?: StateTimelineDomain;\n className?: string;\n },\n): string => {\n const { width, height, rows } = opts;\n const fullDomain = stateTimelineDomain(rows, opts.domain);\n const viewport = normalizeStateTimelineViewport(opts.viewport, fullDomain);\n const showLegend = opts.legend !== false && (opts.states?.length ?? 0) > 0;\n const legendHeight = showLegend ? LEGEND_HEIGHT : 0;\n const labels = rows.map((row) => row.label);\n const idealGutter = Math.max(72, ...labels.map((label) => label.length * 6.3 + 20));\n const gutter = Math.min(240, width * 0.35, idealGutter);\n const plotLeft = gutter;\n const plotRight = Math.max(plotLeft + 1, width - 16);\n const rowsBottom = Math.min(height - AXIS_HEIGHT - legendHeight, TOP + rows.length * ROW_HEIGHT);\n const stateStyles = new Map((opts.states ?? []).map((state, index) => [state.state, { ...state, index }]));\n const stateKeys = opts.states?.map((state) => state.state) ?? [...new Set(rows.flatMap((row) => row.intervals.map((i) => i.state)))];\n const stateIndexes = new Map(stateKeys.map((state, index) => [state, index]));\n const body: string[] = [];\n const maxLabelChars = Math.max(4, Math.floor((gutter - 18) / 6.3));\n\n rows.forEach((row, rowIndex) => {\n const y = TOP + rowIndex * ROW_HEIGHT;\n if (y + ROW_HEIGHT > rowsBottom + 1) return;\n const label = truncate(row.label, maxLabelChars);\n const labelBody = `<text class=\"stdlib-chart-state-label\" x=\"${fmt(plotLeft - 8)}\" y=\"${fmt(\n y + ROW_HEIGHT / 2,\n )}\" text-anchor=\"end\" dominant-baseline=\"middle\">${escapeXml(label)}</text>`;\n body.push(interactiveGroup(labelBody, row.href, row.tooltip ?? row.label, row.label));\n\n for (const interval of row.intervals) {\n if (!Number.isFinite(interval.from) || !Number.isFinite(interval.to)) continue;\n const intervalFrom = Math.min(interval.from, interval.to);\n const intervalTo = Math.max(interval.from, interval.to);\n if (intervalTo < viewport[0] || intervalFrom > viewport[1]) continue;\n const from = Math.max(viewport[0], intervalFrom);\n const to = Math.min(viewport[1], intervalTo);\n const x = mapRange(from, viewport, [plotLeft, plotRight]);\n const x2 = mapRange(to, viewport, [plotLeft, plotRight]);\n const style = stateStyles.get(interval.state);\n const stateIndex = style?.index ?? stateIndexes.get(interval.state) ?? 0;\n const color = style?.color ? ` fill=\"${escapeXml(style.color)}\"` : \"\";\n const rect = `<rect class=\"stdlib-chart-state-region stdlib-chart-series-${stateIndex % 8}\"${color} x=\"${fmt(\n x,\n )}\" y=\"${fmt(y + 3)}\" width=\"${fmt(Math.max(2, x2 - x))}\" height=\"${ROW_HEIGHT - 6}\" rx=\"3\"/>`;\n const stateLabel = style?.label ?? interval.state;\n body.push(\n interactiveGroup(\n rect,\n interval.href,\n interval.tooltip ?? interval.label,\n [row.label, interval.label, stateLabel].filter(Boolean).join(\", \"),\n ),\n );\n }\n });\n\n const tickTarget = Math.max(2, Math.min(8, Math.floor((plotRight - plotLeft) / 110)));\n const ticks = extendDomainToNice(viewport[0], viewport[1], niceStep(viewport[1] - viewport[0], tickTarget)).ticks;\n const format = opts.xAxis?.format ?? ((value: number) => fmt(value));\n for (const tick of ticks) {\n if (tick < viewport[0] || tick > viewport[1]) continue;\n const x = mapRange(tick, viewport, [plotLeft, plotRight]);\n body.push(\n `<line x1=\"${fmt(x)}\" x2=\"${fmt(x)}\" y1=\"${TOP}\" y2=\"${fmt(rowsBottom)}\" stroke=\"currentColor\" opacity=\"0.08\"/>`,\n `<text class=\"stdlib-chart-heatmap-label\" x=\"${fmt(x)}\" y=\"${fmt(rowsBottom + 17)}\" text-anchor=\"middle\">${escapeXml(\n format(tick),\n )}</text>`,\n );\n }\n\n if (opts.xAxis?.label) {\n body.push(\n `<text class=\"stdlib-chart-axis-label\" x=\"${fmt((plotLeft + plotRight) / 2)}\" y=\"${fmt(\n rowsBottom + AXIS_HEIGHT - 2,\n )}\" text-anchor=\"middle\">${escapeXml(opts.xAxis.label)}</text>`,\n );\n }\n\n if (showLegend) {\n let x = plotLeft;\n const y = height - 9;\n for (const [index, state] of (opts.states ?? []).entries()) {\n const color = state.color ? ` fill=\"${escapeXml(state.color)}\"` : \"\";\n const label = state.label ?? state.state;\n body.push(\n `<rect class=\"stdlib-chart-series-${index % 8}\"${color} x=\"${fmt(x)}\" y=\"${y - 8}\" width=\"8\" height=\"8\" rx=\"2\"/>`,\n `<text class=\"stdlib-chart-heatmap-label\" x=\"${fmt(x + 12)}\" y=\"${y}\" text-anchor=\"start\">${escapeXml(label)}</text>`,\n );\n x += 20 + label.length * 6.2;\n }\n }\n\n return svgRoot({ width, height, className: opts.className }, body.join(\"\"));\n};\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["chartDatumSvg","computeDomain","escapeXml","extendDomainToNice","mapRange","niceStep","svgRoot","ROW_HEIGHT","TOP","AXIS_HEIGHT","LEGEND_HEIGHT","MIN_VIEW_FRACTION","finiteDomain","domain","Number","isFinite","stateTimelineDomain","rows","explicit","flatMap","row","intervals","interval","from","to","normalizeStateTimelineViewport","viewport","fullDomain","full","candidate","span","Math","min","max","zoomStateTimelineViewport","delta","anchor","current","fullSpan","minSpan","factor","nextSpan","safeAnchor","anchorValue","panStateTimelineViewport","pixelDelta","plotWidth","timeDelta","stateTimelineHeight","legend","fmt","value","isInteger","String","toFixed","safeHref","href","startsWith","truncate","maxChars","length","slice","interactiveGroup","body","tooltip","ariaLabel","safe","attrs","filter","Boolean","join","title","renderStateTimelineSvg","opts","width","height","showLegend","states","legendHeight","labels","map","label","idealGutter","gutter","plotLeft","plotRight","rowsBottom","stateStyles","Map","state","index","stateKeys","Set","i","stateIndexes","maxLabelChars","floor","forEach","rowIndex","y","labelBody","push","entries","intervalFrom","intervalTo","x","x2","style","get","stateIndex","color","rect","stateLabel","seriesIndex","role","grid","values","key","formatted","xAxis","format","interactive","tickTarget","ticks","tick","className"],"sources":["content/chart-state-timeline.ts"],"sourcesContent":["import { chartDatumSvg, computeDomain, escapeXml, extendDomainToNice, mapRange, niceStep, svgRoot } from \"@k2b/stdlib\";\n\nexport type StateTimelineDomain = readonly [number, number];\n\nexport type StateTimelineInterval = {\n from: number;\n to: number;\n state: string;\n label?: string;\n href?: string;\n tooltip?: string;\n};\n\nexport type StateTimelineRow = {\n label: string;\n href?: string;\n tooltip?: string;\n intervals: StateTimelineInterval[];\n};\n\nexport type StateTimelineState = {\n state: string;\n label?: string;\n color?: string;\n};\n\nexport type StateTimelineChartOptions = {\n rows: StateTimelineRow[];\n states?: StateTimelineState[];\n domain?: StateTimelineDomain;\n xAxis?: { format?: (value: number) => string; label?: string };\n legend?: boolean;\n interactive?: boolean;\n};\n\nconst ROW_HEIGHT = 24;\nconst TOP = 38;\nconst AXIS_HEIGHT = 28;\nconst LEGEND_HEIGHT = 24;\nconst MIN_VIEW_FRACTION = 1 / 64;\n\nconst finiteDomain = (domain: StateTimelineDomain): StateTimelineDomain | null => {\n if (!Number.isFinite(domain[0]) || !Number.isFinite(domain[1]) || domain[0] === domain[1]) return null;\n return domain[0] < domain[1] ? domain : [domain[1], domain[0]];\n};\n\nexport const stateTimelineDomain = (rows: readonly StateTimelineRow[], domain?: StateTimelineDomain): StateTimelineDomain => {\n const explicit = domain ? finiteDomain(domain) : null;\n if (explicit) return explicit;\n return computeDomain(rows.flatMap((row) => row.intervals.flatMap((interval) => [interval.from, interval.to])));\n};\n\nexport const normalizeStateTimelineViewport = (\n viewport: StateTimelineDomain | undefined,\n fullDomain: StateTimelineDomain,\n): StateTimelineDomain => {\n const full = finiteDomain(fullDomain) ?? [0, 1];\n const candidate = viewport ? finiteDomain(viewport) : null;\n if (!candidate) return full;\n const span = Math.min(candidate[1] - candidate[0], full[1] - full[0]);\n const from = Math.max(full[0], Math.min(candidate[0], full[1] - span));\n return [from, from + span];\n};\n\nexport const zoomStateTimelineViewport = (\n viewport: StateTimelineDomain,\n fullDomain: StateTimelineDomain,\n delta: number,\n anchor = 0.5,\n): StateTimelineDomain => {\n const current = normalizeStateTimelineViewport(viewport, fullDomain);\n const fullSpan = fullDomain[1] - fullDomain[0];\n const minSpan = Math.max(1, fullSpan * MIN_VIEW_FRACTION);\n const factor = delta > 0 ? 0.7 : 1 / 0.7;\n const nextSpan = Math.max(minSpan, Math.min(fullSpan, (current[1] - current[0]) * factor));\n const safeAnchor = Math.max(0, Math.min(1, anchor));\n const anchorValue = current[0] + (current[1] - current[0]) * safeAnchor;\n return normalizeStateTimelineViewport([anchorValue - nextSpan * safeAnchor, anchorValue + nextSpan * (1 - safeAnchor)], fullDomain);\n};\n\nexport const panStateTimelineViewport = (\n viewport: StateTimelineDomain,\n fullDomain: StateTimelineDomain,\n pixelDelta: number,\n plotWidth: number,\n): StateTimelineDomain => {\n if (plotWidth <= 0) return normalizeStateTimelineViewport(viewport, fullDomain);\n const current = normalizeStateTimelineViewport(viewport, fullDomain);\n const timeDelta = (-pixelDelta / plotWidth) * (current[1] - current[0]);\n return normalizeStateTimelineViewport([current[0] + timeDelta, current[1] + timeDelta], fullDomain);\n};\n\nexport const stateTimelineHeight = (rows: number, legend = true): number =>\n Math.max(160, TOP + rows * ROW_HEIGHT + AXIS_HEIGHT + (legend ? LEGEND_HEIGHT : 0));\n\nconst fmt = (value: number): string => (Number.isInteger(value) ? String(value) : value.toFixed(2));\n\nconst safeHref = (href: string | undefined): string | null => (href && href.startsWith(\"/\") && !href.startsWith(\"//\") ? href : null);\n\nconst truncate = (value: string, maxChars: number): string =>\n value.length <= maxChars ? value : `${value.slice(0, Math.max(1, maxChars - 1))}…`;\n\nconst interactiveGroup = (body: string, href: string | undefined, tooltip: string | undefined, ariaLabel: string): string => {\n const safe = safeHref(href);\n const attrs = [`aria-label=\"${escapeXml(ariaLabel)}\"`, tooltip ? `data-chart-tooltip=\"${escapeXml(tooltip)}\"` : \"\"]\n .filter(Boolean)\n .join(\" \");\n const title = tooltip ? `<title>${escapeXml(tooltip)}</title>` : \"\";\n return safe\n ? `<a href=\"${escapeXml(safe)}\" ${attrs}>${title}${body}</a>`\n : `<g ${attrs}${tooltip ? ' role=\"img\"' : \"\"}>${title}${body}</g>`;\n};\n\nexport const renderStateTimelineSvg = (\n opts: StateTimelineChartOptions & {\n width: number;\n height: number;\n viewport?: StateTimelineDomain;\n className?: string;\n },\n): string => {\n const { width, height, rows } = opts;\n const fullDomain = stateTimelineDomain(rows, opts.domain);\n const viewport = normalizeStateTimelineViewport(opts.viewport, fullDomain);\n const showLegend = opts.legend !== false && (opts.states?.length ?? 0) > 0;\n const legendHeight = showLegend ? LEGEND_HEIGHT : 0;\n const labels = rows.map((row) => row.label);\n const idealGutter = Math.max(72, ...labels.map((label) => label.length * 6.3 + 20));\n const gutter = Math.min(240, width * 0.35, idealGutter);\n const plotLeft = gutter;\n const plotRight = Math.max(plotLeft + 1, width - 16);\n const rowsBottom = Math.min(height - AXIS_HEIGHT - legendHeight, TOP + rows.length * ROW_HEIGHT);\n const stateStyles = new Map((opts.states ?? []).map((state, index) => [state.state, { ...state, index }]));\n const stateKeys = opts.states?.map((state) => state.state) ?? [...new Set(rows.flatMap((row) => row.intervals.map((i) => i.state)))];\n const stateIndexes = new Map(stateKeys.map((state, index) => [state, index]));\n const body: string[] = [];\n const maxLabelChars = Math.max(4, Math.floor((gutter - 18) / 6.3));\n\n rows.forEach((row, rowIndex) => {\n const y = TOP + rowIndex * ROW_HEIGHT;\n if (y + ROW_HEIGHT > rowsBottom + 1) return;\n const label = truncate(row.label, maxLabelChars);\n const labelBody = `<text class=\"stdlib-chart-state-label\" x=\"${fmt(plotLeft - 8)}\" y=\"${fmt(\n y + ROW_HEIGHT / 2,\n )}\" text-anchor=\"end\" dominant-baseline=\"middle\">${escapeXml(label)}</text>`;\n body.push(interactiveGroup(labelBody, row.href, row.tooltip ?? row.label, row.label));\n\n for (const [index, interval] of row.intervals.entries()) {\n if (!Number.isFinite(interval.from) || !Number.isFinite(interval.to)) continue;\n const intervalFrom = Math.min(interval.from, interval.to);\n const intervalTo = Math.max(interval.from, interval.to);\n if (intervalTo < viewport[0] || intervalFrom > viewport[1]) continue;\n const from = Math.max(viewport[0], intervalFrom);\n const to = Math.min(viewport[1], intervalTo);\n const x = mapRange(from, viewport, [plotLeft, plotRight]);\n const x2 = mapRange(to, viewport, [plotLeft, plotRight]);\n const style = stateStyles.get(interval.state);\n const stateIndex = style?.index ?? stateIndexes.get(interval.state) ?? 0;\n const color = style?.color ? ` fill=\"${escapeXml(style.color)}\"` : \"\";\n const rect = `<rect class=\"stdlib-chart-state-region stdlib-chart-series-${stateIndex % 8}\"${color} x=\"${fmt(\n x,\n )}\" y=\"${fmt(y + 3)}\" width=\"${fmt(Math.max(2, x2 - x))}\" height=\"${ROW_HEIGHT - 6}\" rx=\"3\"/>`;\n const stateLabel = style?.label ?? interval.state;\n body.push(\n interactiveGroup(\n chartDatumSvg(\n rect,\n {\n index,\n seriesIndex: rowIndex,\n role: \"interval\",\n label: row.label,\n anchor: [(x + x2) / 2, y + ROW_HEIGHT / 2],\n grid: [index, rowIndex],\n values: [\n { key: \"state\", value: interval.state, formatted: stateLabel },\n { key: \"from\", value: intervalFrom, formatted: opts.xAxis?.format?.(intervalFrom) },\n { key: \"to\", value: intervalTo, formatted: opts.xAxis?.format?.(intervalTo) },\n { key: \"duration\", value: intervalTo - intervalFrom },\n ...((interval.tooltip ?? interval.label) ? [{ key: \"detail\", value: interval.tooltip ?? interval.label ?? \"\" }] : []),\n ],\n },\n opts.interactive,\n ),\n interval.href,\n interval.tooltip ?? interval.label,\n [row.label, interval.label, stateLabel].filter(Boolean).join(\", \"),\n ),\n );\n }\n });\n\n const tickTarget = Math.max(2, Math.min(8, Math.floor((plotRight - plotLeft) / 110)));\n const ticks = extendDomainToNice(viewport[0], viewport[1], niceStep(viewport[1] - viewport[0], tickTarget)).ticks;\n const format = opts.xAxis?.format ?? ((value: number) => fmt(value));\n for (const tick of ticks) {\n if (tick < viewport[0] || tick > viewport[1]) continue;\n const x = mapRange(tick, viewport, [plotLeft, plotRight]);\n body.push(\n `<line x1=\"${fmt(x)}\" x2=\"${fmt(x)}\" y1=\"${TOP}\" y2=\"${fmt(rowsBottom)}\" stroke=\"currentColor\" opacity=\"0.08\"/>`,\n `<text class=\"stdlib-chart-heatmap-label\" x=\"${fmt(x)}\" y=\"${fmt(rowsBottom + 17)}\" text-anchor=\"middle\">${escapeXml(\n format(tick),\n )}</text>`,\n );\n }\n\n if (opts.xAxis?.label) {\n body.push(\n `<text class=\"stdlib-chart-axis-label\" x=\"${fmt((plotLeft + plotRight) / 2)}\" y=\"${fmt(\n rowsBottom + AXIS_HEIGHT - 2,\n )}\" text-anchor=\"middle\">${escapeXml(opts.xAxis.label)}</text>`,\n );\n }\n\n if (showLegend) {\n body.push('<g class=\"stdlib-chart-legend\">');\n let x = plotLeft;\n const y = height - 9;\n for (const [index, state] of (opts.states ?? []).entries()) {\n const color = state.color ? ` fill=\"${escapeXml(state.color)}\"` : \"\";\n const label = state.label ?? state.state;\n body.push(\n `<rect class=\"stdlib-chart-series-${index % 8}\"${color} x=\"${fmt(x)}\" y=\"${y - 8}\" width=\"8\" height=\"8\" rx=\"2\"/>`,\n `<text class=\"stdlib-chart-heatmap-label\" x=\"${fmt(x + 12)}\" y=\"${y}\" text-anchor=\"start\">${escapeXml(label)}</text>`,\n );\n x += 20 + label.length * 6.2;\n }\n body.push(\"</g>\");\n }\n\n return svgRoot({ width, height, className: opts.className }, body.join(\"\"));\n};\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/** Give maps a CSS-sized viewport while retaining the renderer's projection.
|
|
2
|
+
* The outer SVG uses pixels for headers/legend; the nested geographic viewport
|
|
3
|
+
* keeps one fitted scale across zoom levels and clips only at the plot edges.
|
|
4
|
+
*/
|
|
5
|
+
export function responsiveMapSvg(svg, width, height, viewport) {
|
|
6
|
+
if (!svg.includes('class="stdlib-chart-map-viewport"')) return svg;
|
|
7
|
+
const zoomScale = 2 ** viewport.zoom;
|
|
8
|
+
return svg.replace(/<text class="stdlib-chart-(title|subtitle|map-empty)"[^>]*>/g, tag => {
|
|
9
|
+
const centered = tag.replace(/x="[^"]*"/, 'x="50%"');
|
|
10
|
+
return tag.includes("map-empty") ? centered.replace(/y="[^"]*"/, 'y="50%"') : centered;
|
|
11
|
+
}).replace(/^(<svg\b[^>]*?) viewBox="[^"]*"/, "$1").replace(/<svg class="stdlib-chart-map-viewport"[^>]*>/, tag => {
|
|
12
|
+
const mapWidth = Number(tag.match(/\bwidth="([^"]+)"/)?.[1]);
|
|
13
|
+
const mapHeight = Number(tag.match(/\bheight="([^"]+)"/)?.[1]);
|
|
14
|
+
const inverse = `calc(max(tan(atan2(${mapWidth}px, ${mapWidth / width * 100}cqw)), tan(atan2(${mapHeight}px, ${mapHeight / height * 100}cqh))) / ${zoomScale})`;
|
|
15
|
+
const translateX = mapWidth / 2 - (viewport.longitude + 180) / 360 * mapWidth * zoomScale;
|
|
16
|
+
const translateY = mapHeight / 2 - (90 - viewport.latitude) / 180 * mapHeight * zoomScale;
|
|
17
|
+
return tag.replace(/\b(x|y|width|height)="([\d.]+)"/g, (_match, name, value) => `${name}="${Number(value) / (name === "x" || name === "width" ? width : height) * 100}%"`).replace(">", ` preserveAspectRatio="xMidYMid meet" style="--k2b-map-inverse-scale:${inverse}"><g class="k2b-chart-map-camera" transform="translate(${translateX} ${translateY}) scale(${zoomScale})">`);
|
|
18
|
+
}).replace("</svg>", "</g></svg>");
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** Adapt our generated SVGs to a CSS-sized box without rebuilding their geometry.
|
|
22
|
+
* Only stdlib and the local timeline renderer supply this markup; this is not a
|
|
23
|
+
* parser for arbitrary SVG. The viewBox remains the interaction coordinate space.
|
|
24
|
+
*/
|
|
25
|
+
export function responsiveChartSvg(svg) {
|
|
26
|
+
return svg.replace("<svg ", '<svg preserveAspectRatio="none" ').replace(/<text\b[^>]*>/g, tag => {
|
|
27
|
+
const x = tag.match(/\bx="(-?[\d.]+)"/)?.[1];
|
|
28
|
+
const y = tag.match(/\by="(-?[\d.]+)"/)?.[1];
|
|
29
|
+
if (x === undefined || y === undefined) return tag;
|
|
30
|
+
const rotation = tag.match(/\btransform="rotate\((-?[\d.]+) [^\"]+\)"/)?.[1];
|
|
31
|
+
// Individual CSS scale precedes rotation. Use the same text anchor as
|
|
32
|
+
// transform-origin, and avoid applying the SVG rotation pivot twice.
|
|
33
|
+
return tag.replace(">", ` style="transform-origin:${x}px ${y}px${rotation ? `;transform:rotate(${rotation}deg)` : ""}">`);
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** Add initial controlled selection to our own renderer metadata during SSR. */
|
|
38
|
+
export function selectedChartSvg(svg, selected) {
|
|
39
|
+
if (!selected) return svg;
|
|
40
|
+
const targets = "role" in selected ? [selected] : selected;
|
|
41
|
+
return svg.replace(/<g\b[^>]*\bdata-chart-datum="([^"]*)"[^>]*>/g, (attribute, encoded, offset) => {
|
|
42
|
+
const raw = encoded.replace(/"/g, '"').replace(/'|'/g, "'").replace(/</g, "<").replace(/>/g, ">").replace(/&/g, "&");
|
|
43
|
+
const value = JSON.parse(raw);
|
|
44
|
+
if (typeof value !== "object" || value === null || !("role" in value) || !("index" in value)) return attribute;
|
|
45
|
+
const matches = targets.find(target => value.role === target.role && value.index === target.index && ("seriesIndex" in value ? value.seriesIndex : undefined) === target.seriesIndex);
|
|
46
|
+
if (!matches) return attribute;
|
|
47
|
+
const children = svg.slice(offset, svg.indexOf("</g>", offset));
|
|
48
|
+
const palette = Number(children.match(/stdlib-chart-series-(\d+)/)?.[1] ?? matches.seriesIndex ?? 0) % 8 + 1;
|
|
49
|
+
const paint = `--k2b-chart-selection-color:color-mix(in srgb,var(--stdlib-chart-c${palette}) 72%,var(--k2b-chart-highlight-mix))`;
|
|
50
|
+
const opening = attribute.includes('style="') ? attribute.replace(/style="([^"]*)"/, (_match, style) => `style="${style};${paint}"`) : attribute.replace(">", ` style="${paint}">`);
|
|
51
|
+
return opening.replace(">", " data-selected>");
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=chart-svg.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["responsiveMapSvg","svg","width","height","viewport","includes","zoomScale","zoom","replace","tag","centered","mapWidth","Number","match","mapHeight","inverse","translateX","longitude","translateY","latitude","_match","name","value","responsiveChartSvg","x","y","undefined","rotation","selectedChartSvg","selected","targets","attribute","encoded","offset","raw","JSON","parse","matches","find","target","role","index","seriesIndex","children","slice","indexOf","palette","paint","opening","style"],"sources":["content/chart-svg.ts"],"sourcesContent":["import type { MapViewport } from \"@k2b/stdlib\";\n\n/** Give maps a CSS-sized viewport while retaining the renderer's projection.\n * The outer SVG uses pixels for headers/legend; the nested geographic viewport\n * keeps one fitted scale across zoom levels and clips only at the plot edges.\n */\nexport function responsiveMapSvg(svg: string, width: number, height: number, viewport: MapViewport): string {\n if (!svg.includes('class=\"stdlib-chart-map-viewport\"')) return svg;\n const zoomScale = 2 ** viewport.zoom;\n return svg\n .replace(/<text class=\"stdlib-chart-(title|subtitle|map-empty)\"[^>]*>/g, (tag) => {\n const centered = tag.replace(/x=\"[^\"]*\"/, 'x=\"50%\"');\n return tag.includes(\"map-empty\") ? centered.replace(/y=\"[^\"]*\"/, 'y=\"50%\"') : centered;\n })\n .replace(/^(<svg\\b[^>]*?) viewBox=\"[^\"]*\"/, \"$1\")\n .replace(/<svg class=\"stdlib-chart-map-viewport\"[^>]*>/, (tag) => {\n const mapWidth = Number(tag.match(/\\bwidth=\"([^\"]+)\"/)?.[1]);\n const mapHeight = Number(tag.match(/\\bheight=\"([^\"]+)\"/)?.[1]);\n const inverse = `calc(max(tan(atan2(${mapWidth}px, ${(mapWidth / width) * 100}cqw)), tan(atan2(${mapHeight}px, ${(mapHeight / height) * 100}cqh))) / ${zoomScale})`;\n const translateX = mapWidth / 2 - ((viewport.longitude + 180) / 360) * mapWidth * zoomScale;\n const translateY = mapHeight / 2 - ((90 - viewport.latitude) / 180) * mapHeight * zoomScale;\n return tag\n .replace(\n /\\b(x|y|width|height)=\"([\\d.]+)\"/g,\n (_match, name: string, value: string) =>\n `${name}=\"${(Number(value) / (name === \"x\" || name === \"width\" ? width : height)) * 100}%\"`,\n )\n .replace(\n \">\",\n ` preserveAspectRatio=\"xMidYMid meet\" style=\"--k2b-map-inverse-scale:${inverse}\"><g class=\"k2b-chart-map-camera\" transform=\"translate(${translateX} ${translateY}) scale(${zoomScale})\">`,\n );\n })\n .replace(\"</svg>\", \"</g></svg>\");\n}\n\n/** Adapt our generated SVGs to a CSS-sized box without rebuilding their geometry.\n * Only stdlib and the local timeline renderer supply this markup; this is not a\n * parser for arbitrary SVG. The viewBox remains the interaction coordinate space.\n */\nexport function responsiveChartSvg(svg: string): string {\n return svg.replace(\"<svg \", '<svg preserveAspectRatio=\"none\" ').replace(/<text\\b[^>]*>/g, (tag) => {\n const x = tag.match(/\\bx=\"(-?[\\d.]+)\"/)?.[1];\n const y = tag.match(/\\by=\"(-?[\\d.]+)\"/)?.[1];\n if (x === undefined || y === undefined) return tag;\n const rotation = tag.match(/\\btransform=\"rotate\\((-?[\\d.]+) [^\\\"]+\\)\"/)?.[1];\n // Individual CSS scale precedes rotation. Use the same text anchor as\n // transform-origin, and avoid applying the SVG rotation pivot twice.\n return tag.replace(\">\", ` style=\"transform-origin:${x}px ${y}px${rotation ? `;transform:rotate(${rotation}deg)` : \"\"}\">`);\n });\n}\n\n/** Add initial controlled selection to our own renderer metadata during SSR. */\nexport function selectedChartSvg(\n svg: string,\n selected:\n | { role: string; index: number; seriesIndex?: number }\n | readonly { role: string; index: number; seriesIndex?: number }[]\n | null\n | undefined,\n): string {\n if (!selected) return svg;\n const targets = \"role\" in selected ? [selected] : selected;\n return svg.replace(/<g\\b[^>]*\\bdata-chart-datum=\"([^\"]*)\"[^>]*>/g, (attribute, encoded: string, offset: number) => {\n const raw = encoded\n .replace(/"/g, '\"')\n .replace(/'|'/g, \"'\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/&/g, \"&\");\n const value: unknown = JSON.parse(raw);\n if (typeof value !== \"object\" || value === null || !(\"role\" in value) || !(\"index\" in value)) return attribute;\n const matches = targets.find(\n (target) =>\n value.role === target.role &&\n value.index === target.index &&\n (\"seriesIndex\" in value ? value.seriesIndex : undefined) === target.seriesIndex,\n );\n if (!matches) return attribute;\n const children = svg.slice(offset, svg.indexOf(\"</g>\", offset));\n const palette = (Number(children.match(/stdlib-chart-series-(\\d+)/)?.[1] ?? matches.seriesIndex ?? 0) % 8) + 1;\n const paint = `--k2b-chart-selection-color:color-mix(in srgb,var(--stdlib-chart-c${palette}) 72%,var(--k2b-chart-highlight-mix))`;\n const opening = attribute.includes('style=\"')\n ? attribute.replace(/style=\"([^\"]*)\"/, (_match: string, style: string) => `style=\"${style};${paint}\"`)\n : attribute.replace(\">\", ` style=\"${paint}\">`);\n return opening.replace(\">\", \" data-selected>\");\n });\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { batch, createEffect, createSignal, onCleanup } from "solid-js";
|
|
2
|
+
/** One selection and focus model shared by alternate presentations of a collection. */
|
|
3
|
+
export function createCollectionSelection(options) {
|
|
4
|
+
const [selected, setSelected] = createSignal(new Set(options.initial ?? []));
|
|
5
|
+
const [focused, setFocused] = createSignal(options.initial?.[0] ?? null);
|
|
6
|
+
let anchor = options.initial?.[0] ?? null;
|
|
7
|
+
const elements = new Map();
|
|
8
|
+
const replace = ids => {
|
|
9
|
+
const allowed = new Set(options.ids());
|
|
10
|
+
const next = new Set(ids.filter(id => allowed.has(id)));
|
|
11
|
+
if (next.size === selected().size && [...next].every(id => selected().has(id))) return;
|
|
12
|
+
setSelected(next);
|
|
13
|
+
options.onChange?.([...next]);
|
|
14
|
+
};
|
|
15
|
+
createEffect(() => {
|
|
16
|
+
const ids = options.ids();
|
|
17
|
+
replace([...selected()]);
|
|
18
|
+
if (!focused() || !ids.includes(focused())) setFocused(ids[0] ?? null);
|
|
19
|
+
if (anchor && !ids.includes(anchor)) anchor = null;
|
|
20
|
+
});
|
|
21
|
+
const toggle = id => {
|
|
22
|
+
const next = new Set(selected());
|
|
23
|
+
next.has(id) ? next.delete(id) : next.add(id);
|
|
24
|
+
batch(() => {
|
|
25
|
+
setFocused(id);
|
|
26
|
+
replace([...next]);
|
|
27
|
+
});
|
|
28
|
+
anchor = id;
|
|
29
|
+
};
|
|
30
|
+
const select = (id, modifiers = {}) => {
|
|
31
|
+
if (!options.ids().includes(id)) return;
|
|
32
|
+
batch(() => {
|
|
33
|
+
setFocused(id);
|
|
34
|
+
if (modifiers.shiftKey && anchor) {
|
|
35
|
+
const ids = options.ids();
|
|
36
|
+
const from = ids.indexOf(anchor);
|
|
37
|
+
const to = ids.indexOf(id);
|
|
38
|
+
const range = ids.slice(Math.min(from, to), Math.max(from, to) + 1);
|
|
39
|
+
replace(modifiers.ctrlKey || modifiers.metaKey ? [...selected(), ...range] : range);
|
|
40
|
+
} else if (modifiers.ctrlKey || modifiers.metaKey) toggle(id);else {
|
|
41
|
+
anchor = id;
|
|
42
|
+
replace([id]);
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
};
|
|
46
|
+
const focus = id => {
|
|
47
|
+
setFocused(id);
|
|
48
|
+
elements.get(id)?.focus({
|
|
49
|
+
preventScroll: true
|
|
50
|
+
});
|
|
51
|
+
elements.get(id)?.scrollIntoView?.({
|
|
52
|
+
block: "nearest",
|
|
53
|
+
inline: "nearest"
|
|
54
|
+
});
|
|
55
|
+
};
|
|
56
|
+
const keyDown = (event, id, columns = 1) => {
|
|
57
|
+
const ids = options.ids();
|
|
58
|
+
const index = ids.indexOf(id);
|
|
59
|
+
let next;
|
|
60
|
+
if (event.key === "ArrowDown") next = index + columns;
|
|
61
|
+
if (event.key === "ArrowUp") next = index - columns;
|
|
62
|
+
if (columns > 1 && event.key === "ArrowRight") next = index + 1;
|
|
63
|
+
if (columns > 1 && event.key === "ArrowLeft") next = index - 1;
|
|
64
|
+
if (event.key === "Home") next = 0;
|
|
65
|
+
if (event.key === "End") next = ids.length - 1;
|
|
66
|
+
if (next !== undefined && ids.length) {
|
|
67
|
+
event.preventDefault();
|
|
68
|
+
const target = ids[Math.max(0, Math.min(next, ids.length - 1))];
|
|
69
|
+
if (event.shiftKey || !event.ctrlKey && !event.metaKey) select(target, event);
|
|
70
|
+
focus(target);
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
if (event.key === " ") {
|
|
74
|
+
event.preventDefault();
|
|
75
|
+
toggle(id);
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a") {
|
|
79
|
+
event.preventDefault();
|
|
80
|
+
replace(ids);
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
if (event.key === "Escape") {
|
|
84
|
+
event.preventDefault();
|
|
85
|
+
replace([]);
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
88
|
+
return false;
|
|
89
|
+
};
|
|
90
|
+
return {
|
|
91
|
+
selected,
|
|
92
|
+
focused,
|
|
93
|
+
select,
|
|
94
|
+
toggle,
|
|
95
|
+
replace,
|
|
96
|
+
focus,
|
|
97
|
+
keyDown,
|
|
98
|
+
clear: () => replace([]),
|
|
99
|
+
all: () => replace(options.ids()),
|
|
100
|
+
markFocused: id => setFocused(id),
|
|
101
|
+
register: (id, element) => {
|
|
102
|
+
elements.set(id, element);
|
|
103
|
+
onCleanup(() => {
|
|
104
|
+
if (elements.get(id) === element) elements.delete(id);
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=collection-selection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["batch","createEffect","createSignal","onCleanup","createCollectionSelection","options","selected","setSelected","Set","initial","focused","setFocused","anchor","elements","Map","replace","ids","allowed","next","filter","id","has","size","every","onChange","includes","toggle","delete","add","select","modifiers","shiftKey","from","indexOf","to","range","slice","Math","min","max","ctrlKey","metaKey","focus","get","preventScroll","scrollIntoView","block","inline","keyDown","event","columns","index","key","length","undefined","preventDefault","target","toLowerCase","clear","all","markFocused","register","element","set"],"sources":["content/collection-selection.ts"],"sourcesContent":["import { batch, createEffect, createSignal, onCleanup } from \"solid-js\";\n\nexport type SelectionModifiers = { shiftKey?: boolean; ctrlKey?: boolean; metaKey?: boolean };\nexport type CollectionSelection = ReturnType<typeof createCollectionSelection>;\n\n/** One selection and focus model shared by alternate presentations of a collection. */\nexport function createCollectionSelection(options: {\n ids: () => readonly string[];\n initial?: readonly string[];\n onChange?: (ids: readonly string[]) => void;\n}) {\n const [selected, setSelected] = createSignal<ReadonlySet<string>>(new Set(options.initial ?? []));\n const [focused, setFocused] = createSignal<string | null>(options.initial?.[0] ?? null);\n let anchor: string | null = options.initial?.[0] ?? null;\n const elements = new Map<string, HTMLElement>();\n const replace = (ids: readonly string[]) => {\n const allowed = new Set(options.ids());\n const next = new Set(ids.filter((id) => allowed.has(id)));\n if (next.size === selected().size && [...next].every((id) => selected().has(id))) return;\n setSelected(next);\n options.onChange?.([...next]);\n };\n createEffect(() => {\n const ids = options.ids();\n replace([...selected()]);\n if (!focused() || !ids.includes(focused()!)) setFocused(ids[0] ?? null);\n if (anchor && !ids.includes(anchor)) anchor = null;\n });\n const toggle = (id: string) => {\n const next = new Set(selected());\n next.has(id) ? next.delete(id) : next.add(id);\n batch(() => {\n setFocused(id);\n replace([...next]);\n });\n anchor = id;\n };\n const select = (id: string, modifiers: SelectionModifiers = {}) => {\n if (!options.ids().includes(id)) return;\n batch(() => {\n setFocused(id);\n if (modifiers.shiftKey && anchor) {\n const ids = options.ids();\n const from = ids.indexOf(anchor);\n const to = ids.indexOf(id);\n const range = ids.slice(Math.min(from, to), Math.max(from, to) + 1);\n replace(modifiers.ctrlKey || modifiers.metaKey ? [...selected(), ...range] : range);\n } else if (modifiers.ctrlKey || modifiers.metaKey) toggle(id);\n else {\n anchor = id;\n replace([id]);\n }\n });\n };\n const focus = (id: string) => {\n setFocused(id);\n elements.get(id)?.focus({ preventScroll: true });\n elements.get(id)?.scrollIntoView?.({ block: \"nearest\", inline: \"nearest\" });\n };\n const keyDown = (event: KeyboardEvent, id: string, columns = 1) => {\n const ids = options.ids();\n const index = ids.indexOf(id);\n let next: number | undefined;\n if (event.key === \"ArrowDown\") next = index + columns;\n if (event.key === \"ArrowUp\") next = index - columns;\n if (columns > 1 && event.key === \"ArrowRight\") next = index + 1;\n if (columns > 1 && event.key === \"ArrowLeft\") next = index - 1;\n if (event.key === \"Home\") next = 0;\n if (event.key === \"End\") next = ids.length - 1;\n if (next !== undefined && ids.length) {\n event.preventDefault();\n const target = ids[Math.max(0, Math.min(next, ids.length - 1))]!;\n if (event.shiftKey || (!event.ctrlKey && !event.metaKey)) select(target, event);\n focus(target);\n return true;\n }\n if (event.key === \" \") {\n event.preventDefault();\n toggle(id);\n return true;\n }\n if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === \"a\") {\n event.preventDefault();\n replace(ids);\n return true;\n }\n if (event.key === \"Escape\") {\n event.preventDefault();\n replace([]);\n return true;\n }\n return false;\n };\n return {\n selected,\n focused,\n select,\n toggle,\n replace,\n focus,\n keyDown,\n clear: () => replace([]),\n all: () => replace(options.ids()),\n markFocused: (id: string) => setFocused(id),\n register: (id: string, element: HTMLElement) => {\n elements.set(id, element);\n onCleanup(() => {\n if (elements.get(id) === element) elements.delete(id);\n });\n },\n };\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/** Persist presentation choices only, never file contents. Ignore stale or corrupt storage. */
|
|
2
|
+
export const readDelimitedPreferences = stored => {
|
|
3
|
+
const defaults = {
|
|
4
|
+
encoding: "utf-8",
|
|
5
|
+
delimiter: "auto",
|
|
6
|
+
view: "table"
|
|
7
|
+
};
|
|
8
|
+
try {
|
|
9
|
+
const value = JSON.parse(stored ?? "null");
|
|
10
|
+
if (!value || typeof value !== "object") return defaults;
|
|
11
|
+
return {
|
|
12
|
+
encoding: "encoding" in value && typeof value.encoding === "string" && ["utf-8", "windows-1252", "utf-16le", "utf-16be"].includes(value.encoding) ? value.encoding : defaults.encoding,
|
|
13
|
+
delimiter: "delimiter" in value && typeof value.delimiter === "string" && ["auto", ",", ";", "\t", "|"].includes(value.delimiter) ? value.delimiter : defaults.delimiter,
|
|
14
|
+
view: "view" in value && value.view === "raw" ? "raw" : "table"
|
|
15
|
+
};
|
|
16
|
+
} catch {
|
|
17
|
+
return defaults;
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
export const decodeDelimitedContent = (content, encoding) => content.encoding === "utf8" ? content.content : new TextDecoder(encoding).decode(Uint8Array.from(atob(content.content), char => char.charCodeAt(0)));
|
|
21
|
+
//# sourceMappingURL=delimited-preferences.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["readDelimitedPreferences","stored","defaults","encoding","delimiter","view","value","JSON","parse","includes","decodeDelimitedContent","content","TextDecoder","decode","Uint8Array","from","atob","char","charCodeAt"],"sources":["content/delimited-preferences.ts"],"sourcesContent":["export type DelimitedPreferences = { encoding: string; delimiter: string; view: \"table\" | \"raw\" };\n\n/** Persist presentation choices only, never file contents. Ignore stale or corrupt storage. */\nexport const readDelimitedPreferences = (stored: string | null): DelimitedPreferences => {\n const defaults: DelimitedPreferences = { encoding: \"utf-8\", delimiter: \"auto\", view: \"table\" };\n try {\n const value: unknown = JSON.parse(stored ?? \"null\");\n if (!value || typeof value !== \"object\") return defaults;\n return {\n encoding:\n \"encoding\" in value &&\n typeof value.encoding === \"string\" &&\n [\"utf-8\", \"windows-1252\", \"utf-16le\", \"utf-16be\"].includes(value.encoding)\n ? value.encoding\n : defaults.encoding,\n delimiter:\n \"delimiter\" in value && typeof value.delimiter === \"string\" && [\"auto\", \",\", \";\", \"\\t\", \"|\"].includes(value.delimiter)\n ? value.delimiter\n : defaults.delimiter,\n view: \"view\" in value && value.view === \"raw\" ? \"raw\" : \"table\",\n };\n } catch {\n return defaults;\n }\n};\n\nexport const decodeDelimitedContent = (content: { encoding: \"utf8\" | \"base64\"; content: string }, encoding: string): string =>\n content.encoding === \"utf8\"\n ? content.content\n : new TextDecoder(encoding).decode(Uint8Array.from(atob(content.content), (char) => char.charCodeAt(0)));\n"],"mappings":"AAEA;AACA,OAAO,MAAMA,wBAAwB,GAAIC,MAAqB,IAA2B;EACvF,MAAMC,QAA8B,GAAG;IAAEC,QAAQ,EAAE,OAAO;IAAEC,SAAS,EAAE,MAAM;IAAEC,IAAI,EAAE;EAAQ,CAAC;EAC9F,IAAI;IACF,MAAMC,KAAc,GAAGC,IAAI,CAACC,KAAK,CAACP,MAAM,IAAI,MAAM,CAAC;IACnD,IAAI,CAACK,KAAK,IAAI,OAAOA,KAAK,KAAK,QAAQ,EAAE,OAAOJ,QAAQ;IACxD,OAAO;MACLC,QAAQ,EACN,UAAU,IAAIG,KAAK,IACnB,OAAOA,KAAK,CAACH,QAAQ,KAAK,QAAQ,IAClC,CAAC,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,UAAU,CAAC,CAACM,QAAQ,CAACH,KAAK,CAACH,QAAQ,CAAC,GACtEG,KAAK,CAACH,QAAQ,GACdD,QAAQ,CAACC,QAAQ;MACvBC,SAAS,EACP,WAAW,IAAIE,KAAK,IAAI,OAAOA,KAAK,CAACF,SAAS,KAAK,QAAQ,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,CAAC,CAACK,QAAQ,CAACH,KAAK,CAACF,SAAS,CAAC,GAClHE,KAAK,CAACF,SAAS,GACfF,QAAQ,CAACE,SAAS;MACxBC,IAAI,EAAE,MAAM,IAAIC,KAAK,IAAIA,KAAK,CAACD,IAAI,KAAK,KAAK,GAAG,KAAK,GAAG;IAC1D,CAAC;EACH,CAAC,CAAC,MAAM;IACN,OAAOH,QAAQ;EACjB;AACF,CAAC;AAED,OAAO,MAAMQ,sBAAsB,GAAGA,CAACC,OAAyD,EAAER,QAAgB,KAChHQ,OAAO,CAACR,QAAQ,KAAK,MAAM,GACvBQ,OAAO,CAACA,OAAO,GACf,IAAIC,WAAW,CAACT,QAAQ,CAAC,CAACU,MAAM,CAACC,UAAU,CAACC,IAAI,CAACC,IAAI,CAACL,OAAO,CAACA,OAAO,CAAC,EAAGM,IAAI,IAAKA,IAAI,CAACC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["parentOf","path","index","lastIndexOf","slice","nameOf","nodesByPath","nodes","result","Map","visit","node","set","entry","child","children","buildTree","entries","previous","byPath","previousByPath","folders","Set","files","filter","kind","map","dir","has","Error","add","childrenByParent","keys","parent","get","push","nodeFor","depth","isFolder","old","name","childrenOf","sort","a","b","localeCompare","flattenVisible","expanded","flatMap","allFolderPaths"],"sources":["content/file-tree.ts"],"sourcesContent":["/**\n * Tree shaping for FileTree — flat paths in, sorted nodes out.\n *\n * Kept beside the component rather than inside it because it is pure: no JSX,\n * no reactivity, nothing that needs a DOM. That is also what makes it testable\n * — a test importing the .tsx pulls the whole component through Bun's JSX\n * transform, which resolves against the root tsconfig and lands on the React\n * runtime. Same reason `file-view-preview.ts` sits next to FileView.\n */\n\nexport type FileTreeEntry = {\n /** Canonical identity, e.g. \"/input/report.csv\". */\n path: string;\n /** Folders are usually implicit from paths — explicit entries model empty dirs. */\n kind?: \"file\" | \"folder\";\n size?: number;\n mediaType?: string;\n updatedAt?: string;\n /** Icon override (tabler class without \"ti \" prefix); default derives from the name. */\n icon?: string;\n /** Small trailing badge, e.g. \"ro\" on read-only mounts. */\n badge?: string;\n};\n\nexport type TreeNode = {\n entry: FileTreeEntry;\n name: string;\n depth: number;\n isFolder: boolean;\n children: TreeNode[];\n};\n\n/** Containing directory of a path; \"/\" for top-level entries. */\nexport const parentOf = (path: string): string => {\n const index = path.lastIndexOf(\"/\");\n return index <= 0 ? \"/\" : path.slice(0, index);\n};\n\nconst nameOf = (path: string): string => path.slice(path.lastIndexOf(\"/\") + 1) || path;\n\nconst nodesByPath = (nodes: TreeNode[]): Map<string, TreeNode> => {\n const result = new Map<string, TreeNode>();\n const visit = (node: TreeNode) => {\n result.set(node.entry.path, node);\n for (const child of node.children) visit(child);\n };\n for (const node of nodes) visit(node);\n return result;\n};\n\n/**\n * Flat paths → sorted tree (folders first, then files, both alphabetical).\n *\n * Passing the previous tree preserves object identity by path while updating\n * the cached node in place. Solid's keyed `<For>` can then keep rows, rename\n * inputs, and focus alive even when a refetch changes metadata.\n */\nexport const buildTree = (entries: FileTreeEntry[], previous: TreeNode[] = []): TreeNode[] => {\n const byPath = new Map<string, FileTreeEntry>();\n const previousByPath = nodesByPath(previous);\n const folders = new Set<string>();\n const files = new Set(entries.filter((entry) => entry.kind !== \"folder\").map((entry) => entry.path));\n for (const entry of entries) {\n for (let dir = parentOf(entry.path); dir !== \"/\"; dir = parentOf(dir)) {\n if (files.has(dir)) {\n throw new Error(`FileTree entry conflict: \"${dir}\" is a file and cannot contain \"${entry.path}\".`);\n }\n }\n }\n for (const entry of entries) {\n byPath.set(entry.path, entry);\n if (entry.kind === \"folder\") folders.add(entry.path);\n // Register all ancestor folders of every entry.\n for (let dir = parentOf(entry.path); dir !== \"/\"; dir = parentOf(dir)) folders.add(dir);\n }\n const childrenByParent = new Map<string, string[]>();\n for (const path of new Set([...byPath.keys(), ...folders])) {\n if (path === \"/\") continue;\n const parent = parentOf(path);\n const children = childrenByParent.get(parent);\n if (children) children.push(path);\n else childrenByParent.set(parent, [path]);\n }\n\n const nodeFor = (path: string, depth: number): TreeNode => {\n const entry = byPath.get(path) ?? { path, kind: \"folder\" as const };\n const isFolder = folders.has(path);\n const old = previousByPath.get(path);\n if (old) {\n old.entry = entry;\n old.name = nameOf(path);\n old.depth = depth;\n old.isFolder = isFolder;\n return old;\n }\n return { entry, name: nameOf(path), depth, isFolder, children: [] };\n };\n\n const childrenOf = (dir: string, depth: number): TreeNode[] => {\n const nodes = (childrenByParent.get(dir) ?? []).map((path) => {\n const node = nodeFor(path, depth);\n if (node.isFolder) node.children = childrenOf(node.entry.path, depth + 1);\n return node;\n });\n return nodes.sort((a, b) => (a.isFolder === b.isFolder ? a.name.localeCompare(b.name) : a.isFolder ? -1 : 1));\n };\n\n return childrenOf(\"/\", 0);\n};\n\nexport const flattenVisible = (nodes: TreeNode[], expanded: Set<string>): TreeNode[] =>\n nodes.flatMap((node) => [node, ...(node.isFolder && expanded.has(node.entry.path) ? flattenVisible(node.children, expanded) : [])]);\n\nexport const allFolderPaths = (nodes: TreeNode[]): string[] =>\n nodes.flatMap((node) => (node.isFolder ? [node.entry.path, ...allFolderPaths(node.children)] : []));\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;
|
|
1
|
+
{"version":3,"names":["parentOf","path","index","lastIndexOf","slice","nameOf","nodesByPath","nodes","result","Map","visit","node","set","entry","child","children","buildTree","entries","previous","byPath","previousByPath","folders","Set","files","filter","kind","map","dir","has","Error","add","childrenByParent","keys","parent","get","push","nodeFor","depth","isFolder","old","name","childrenOf","sort","a","b","localeCompare","flattenVisible","expanded","flatMap","allFolderPaths"],"sources":["content/file-tree.ts"],"sourcesContent":["/**\n * Tree shaping for FileTree — flat paths in, sorted nodes out.\n *\n * Kept beside the component rather than inside it because it is pure: no JSX,\n * no reactivity, nothing that needs a DOM. That is also what makes it testable\n * — a test importing the .tsx pulls the whole component through Bun's JSX\n * transform, which resolves against the root tsconfig and lands on the React\n * runtime. Same reason `file-view-preview.ts` sits next to FileView.\n */\n\nexport type FileTreeEntry = {\n /** Canonical identity, e.g. \"/input/report.csv\". */\n path: string;\n /** Optional presentation label; path remains the identity and rename target. */\n displayName?: string;\n /** Folders are usually implicit from paths — explicit entries model empty dirs. */\n kind?: \"file\" | \"folder\";\n size?: number;\n mediaType?: string;\n updatedAt?: string;\n /** Icon override (tabler class without \"ti \" prefix); default derives from the name. */\n icon?: string;\n /** Small trailing badge, e.g. \"ro\" on read-only mounts. */\n badge?: string;\n};\n\nexport type TreeNode = {\n entry: FileTreeEntry;\n name: string;\n depth: number;\n isFolder: boolean;\n children: TreeNode[];\n};\n\n/** Containing directory of a path; \"/\" for top-level entries. */\nexport const parentOf = (path: string): string => {\n const index = path.lastIndexOf(\"/\");\n return index <= 0 ? \"/\" : path.slice(0, index);\n};\n\nconst nameOf = (path: string): string => path.slice(path.lastIndexOf(\"/\") + 1) || path;\n\nconst nodesByPath = (nodes: TreeNode[]): Map<string, TreeNode> => {\n const result = new Map<string, TreeNode>();\n const visit = (node: TreeNode) => {\n result.set(node.entry.path, node);\n for (const child of node.children) visit(child);\n };\n for (const node of nodes) visit(node);\n return result;\n};\n\n/**\n * Flat paths → sorted tree (folders first, then files, both alphabetical).\n *\n * Passing the previous tree preserves object identity by path while updating\n * the cached node in place. Solid's keyed `<For>` can then keep rows, rename\n * inputs, and focus alive even when a refetch changes metadata.\n */\nexport const buildTree = (entries: FileTreeEntry[], previous: TreeNode[] = []): TreeNode[] => {\n const byPath = new Map<string, FileTreeEntry>();\n const previousByPath = nodesByPath(previous);\n const folders = new Set<string>();\n const files = new Set(entries.filter((entry) => entry.kind !== \"folder\").map((entry) => entry.path));\n for (const entry of entries) {\n for (let dir = parentOf(entry.path); dir !== \"/\"; dir = parentOf(dir)) {\n if (files.has(dir)) {\n throw new Error(`FileTree entry conflict: \"${dir}\" is a file and cannot contain \"${entry.path}\".`);\n }\n }\n }\n for (const entry of entries) {\n byPath.set(entry.path, entry);\n if (entry.kind === \"folder\") folders.add(entry.path);\n // Register all ancestor folders of every entry.\n for (let dir = parentOf(entry.path); dir !== \"/\"; dir = parentOf(dir)) folders.add(dir);\n }\n const childrenByParent = new Map<string, string[]>();\n for (const path of new Set([...byPath.keys(), ...folders])) {\n if (path === \"/\") continue;\n const parent = parentOf(path);\n const children = childrenByParent.get(parent);\n if (children) children.push(path);\n else childrenByParent.set(parent, [path]);\n }\n\n const nodeFor = (path: string, depth: number): TreeNode => {\n const entry = byPath.get(path) ?? { path, kind: \"folder\" as const };\n const isFolder = folders.has(path);\n const old = previousByPath.get(path);\n if (old) {\n old.entry = entry;\n old.name = nameOf(path);\n old.depth = depth;\n old.isFolder = isFolder;\n return old;\n }\n return { entry, name: nameOf(path), depth, isFolder, children: [] };\n };\n\n const childrenOf = (dir: string, depth: number): TreeNode[] => {\n const nodes = (childrenByParent.get(dir) ?? []).map((path) => {\n const node = nodeFor(path, depth);\n if (node.isFolder) node.children = childrenOf(node.entry.path, depth + 1);\n return node;\n });\n return nodes.sort((a, b) => (a.isFolder === b.isFolder ? a.name.localeCompare(b.name) : a.isFolder ? -1 : 1));\n };\n\n return childrenOf(\"/\", 0);\n};\n\nexport const flattenVisible = (nodes: TreeNode[], expanded: Set<string>): TreeNode[] =>\n nodes.flatMap((node) => [node, ...(node.isFolder && expanded.has(node.entry.path) ? flattenVisible(node.children, expanded) : [])]);\n\nexport const allFolderPaths = (nodes: TreeNode[]): string[] =>\n nodes.flatMap((node) => (node.isFolder ? [node.entry.path, ...allFolderPaths(node.children)] : []));\n"],"mappings":"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","ignoreList":[]}
|