@k2b/ui 0.1.0-rc.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/LICENSE +661 -0
- package/README.md +343 -0
- package/dist/.build-complete +0 -0
- package/dist/browser/actions/Button.js +236 -0
- package/dist/browser/actions/Button.js.map +1 -0
- package/dist/browser/actions/ContextMenu.js +199 -0
- package/dist/browser/actions/ContextMenu.js.map +1 -0
- package/dist/browser/actions/CopyButton.js +97 -0
- package/dist/browser/actions/CopyButton.js.map +1 -0
- package/dist/browser/actions/Disclosure.js +83 -0
- package/dist/browser/actions/Disclosure.js.map +1 -0
- package/dist/browser/actions/Dropdown.js +669 -0
- package/dist/browser/actions/Dropdown.js.map +1 -0
- package/dist/browser/actions/FilterChip.js +149 -0
- package/dist/browser/actions/FilterChip.js.map +1 -0
- package/dist/browser/actions/RemoveButton.js +47 -0
- package/dist/browser/actions/RemoveButton.js.map +1 -0
- package/dist/browser/actions/SegmentedControl.js +138 -0
- package/dist/browser/actions/SegmentedControl.js.map +1 -0
- package/dist/browser/actions/SplitButton.js +76 -0
- package/dist/browser/actions/SplitButton.js.map +1 -0
- package/dist/browser/actions/SpotlightSearch.js +87 -0
- package/dist/browser/actions/SpotlightSearch.js.map +1 -0
- package/dist/browser/actions/Tabs.js +185 -0
- package/dist/browser/actions/Tabs.js.map +1 -0
- package/dist/browser/actions/Toolbar.js +87 -0
- package/dist/browser/actions/Toolbar.js.map +1 -0
- package/dist/browser/actions/index.js +13 -0
- package/dist/browser/actions/index.js.map +1 -0
- package/dist/browser/chat/ChatComposer.js +760 -0
- package/dist/browser/chat/ChatComposer.js.map +1 -0
- package/dist/browser/chat/ChatPrimitives.js +688 -0
- package/dist/browser/chat/ChatPrimitives.js.map +1 -0
- package/dist/browser/chat/ChatRoot.js +27 -0
- package/dist/browser/chat/ChatRoot.js.map +1 -0
- package/dist/browser/chat/ChatTimeline.js +404 -0
- package/dist/browser/chat/ChatTimeline.js.map +1 -0
- package/dist/browser/chat/chat-behavior.js +53 -0
- package/dist/browser/chat/chat-behavior.js.map +1 -0
- package/dist/browser/chat/index.js +17 -0
- package/dist/browser/chat/index.js.map +1 -0
- package/dist/browser/chat/types.js +2 -0
- package/dist/browser/chat/types.js.map +1 -0
- package/dist/browser/content/Calendar.js +2168 -0
- package/dist/browser/content/Calendar.js.map +1 -0
- package/dist/browser/content/Chart.js +680 -0
- package/dist/browser/content/Chart.js.map +1 -0
- package/dist/browser/content/CodeDisplay.js +104 -0
- package/dist/browser/content/CodeDisplay.js.map +1 -0
- package/dist/browser/content/DataTable.js +724 -0
- package/dist/browser/content/DataTable.js.map +1 -0
- package/dist/browser/content/Docs.js +227 -0
- package/dist/browser/content/Docs.js.map +1 -0
- package/dist/browser/content/FileBrowser.js +462 -0
- package/dist/browser/content/FileBrowser.js.map +1 -0
- package/dist/browser/content/FileTree.js +453 -0
- package/dist/browser/content/FileTree.js.map +1 -0
- package/dist/browser/content/FileView.js +842 -0
- package/dist/browser/content/FileView.js.map +1 -0
- package/dist/browser/content/Lightbox.js +285 -0
- package/dist/browser/content/Lightbox.js.map +1 -0
- package/dist/browser/content/LogEntriesTable.js +139 -0
- package/dist/browser/content/LogEntriesTable.js.map +1 -0
- package/dist/browser/content/MarkdownView.js +138 -0
- package/dist/browser/content/MarkdownView.js.map +1 -0
- package/dist/browser/content/Pagination.js +182 -0
- package/dist/browser/content/Pagination.js.map +1 -0
- package/dist/browser/content/PdfPreview.js +204 -0
- package/dist/browser/content/PdfPreview.js.map +1 -0
- package/dist/browser/content/RangePicker.js +83 -0
- package/dist/browser/content/RangePicker.js.map +1 -0
- package/dist/browser/content/StructuredDataPreview.js +194 -0
- package/dist/browser/content/StructuredDataPreview.js.map +1 -0
- package/dist/browser/content/calendar-event-layout.js +92 -0
- package/dist/browser/content/calendar-event-layout.js.map +1 -0
- package/dist/browser/content/calendar-pointer.js +114 -0
- package/dist/browser/content/calendar-pointer.js.map +1 -0
- package/dist/browser/content/chart-map-viewport.js +33 -0
- package/dist/browser/content/chart-map-viewport.js.map +1 -0
- package/dist/browser/content/chart-state-timeline.js +124 -0
- package/dist/browser/content/chart-state-timeline.js.map +1 -0
- package/dist/browser/content/code-highlight.js +144 -0
- package/dist/browser/content/code-highlight.js.map +1 -0
- package/dist/browser/content/file-tree.js +93 -0
- package/dist/browser/content/file-tree.js.map +1 -0
- package/dist/browser/content/file-view-preview.js +112 -0
- package/dist/browser/content/file-view-preview.js.map +1 -0
- package/dist/browser/content/index.js +16 -0
- package/dist/browser/content/index.js.map +1 -0
- package/dist/browser/feedback/InlineGuidance.js +46 -0
- package/dist/browser/feedback/InlineGuidance.js.map +1 -0
- package/dist/browser/feedback/Tooltip.js +189 -0
- package/dist/browser/feedback/Tooltip.js.map +1 -0
- package/dist/browser/feedback/dialog-core.js +207 -0
- package/dist/browser/feedback/dialog-core.js.map +1 -0
- package/dist/browser/feedback/index.js +6 -0
- package/dist/browser/feedback/index.js.map +1 -0
- package/dist/browser/feedback/prompts.js +991 -0
- package/dist/browser/feedback/prompts.js.map +1 -0
- package/dist/browser/feedback/toast.js +271 -0
- package/dist/browser/feedback/toast.js.map +1 -0
- package/dist/browser/feedback/tooltip-position.js +25 -0
- package/dist/browser/feedback/tooltip-position.js.map +1 -0
- package/dist/browser/index.js +11 -0
- package/dist/browser/index.js.map +1 -0
- package/dist/browser/inputs/AutocompleteEditor.js +610 -0
- package/dist/browser/inputs/AutocompleteEditor.js.map +1 -0
- package/dist/browser/inputs/AutocompleteSelect.js +632 -0
- package/dist/browser/inputs/AutocompleteSelect.js.map +1 -0
- package/dist/browser/inputs/Checkbox.js +137 -0
- package/dist/browser/inputs/Checkbox.js.map +1 -0
- package/dist/browser/inputs/CheckboxCard.js +130 -0
- package/dist/browser/inputs/CheckboxCard.js.map +1 -0
- package/dist/browser/inputs/ChoiceGroups.js +174 -0
- package/dist/browser/inputs/ChoiceGroups.js.map +1 -0
- package/dist/browser/inputs/ChoiceInputs.js +400 -0
- package/dist/browser/inputs/ChoiceInputs.js.map +1 -0
- package/dist/browser/inputs/Combobox.js +274 -0
- package/dist/browser/inputs/Combobox.js.map +1 -0
- package/dist/browser/inputs/DatePicker.js +923 -0
- package/dist/browser/inputs/DatePicker.js.map +1 -0
- package/dist/browser/inputs/FileInputs.js +736 -0
- package/dist/browser/inputs/FileInputs.js.map +1 -0
- package/dist/browser/inputs/MultiSelectInput.js +565 -0
- package/dist/browser/inputs/MultiSelectInput.js.map +1 -0
- package/dist/browser/inputs/NumberInput.js +288 -0
- package/dist/browser/inputs/NumberInput.js.map +1 -0
- package/dist/browser/inputs/Select.js +507 -0
- package/dist/browser/inputs/Select.js.map +1 -0
- package/dist/browser/inputs/SelectChip.js +151 -0
- package/dist/browser/inputs/SelectChip.js.map +1 -0
- package/dist/browser/inputs/SpecialInputs.js +117 -0
- package/dist/browser/inputs/SpecialInputs.js.map +1 -0
- package/dist/browser/inputs/Switch.js +117 -0
- package/dist/browser/inputs/Switch.js.map +1 -0
- package/dist/browser/inputs/TagEditor.js +358 -0
- package/dist/browser/inputs/TagEditor.js.map +1 -0
- package/dist/browser/inputs/TagsInput.js +195 -0
- package/dist/browser/inputs/TagsInput.js.map +1 -0
- package/dist/browser/inputs/TemplateEditor.js +190 -0
- package/dist/browser/inputs/TemplateEditor.js.map +1 -0
- package/dist/browser/inputs/TextInput.js +318 -0
- package/dist/browser/inputs/TextInput.js.map +1 -0
- package/dist/browser/inputs/choice.js +188 -0
- package/dist/browser/inputs/choice.js.map +1 -0
- package/dist/browser/inputs/completion/behaviors.js +108 -0
- package/dist/browser/inputs/completion/behaviors.js.map +1 -0
- package/dist/browser/inputs/completion/engine.js +103 -0
- package/dist/browser/inputs/completion/engine.js.map +1 -0
- package/dist/browser/inputs/completion/index.js +4 -0
- package/dist/browser/inputs/completion/index.js.map +1 -0
- package/dist/browser/inputs/completion/overlay.js +25 -0
- package/dist/browser/inputs/completion/overlay.js.map +1 -0
- package/dist/browser/inputs/date-picker.js +123 -0
- package/dist/browser/inputs/date-picker.js.map +1 -0
- package/dist/browser/inputs/editor-dom.js +26 -0
- package/dist/browser/inputs/editor-dom.js.map +1 -0
- package/dist/browser/inputs/field-contract.js +9 -0
- package/dist/browser/inputs/field-contract.js.map +1 -0
- package/dist/browser/inputs/icon-options.js +46 -0
- package/dist/browser/inputs/icon-options.js.map +1 -0
- package/dist/browser/inputs/image-crop.js +145 -0
- package/dist/browser/inputs/image-crop.js.map +1 -0
- package/dist/browser/inputs/index.js +23 -0
- package/dist/browser/inputs/index.js.map +1 -0
- package/dist/browser/inputs/markdown/MarkdownEditor.js +725 -0
- package/dist/browser/inputs/markdown/MarkdownEditor.js.map +1 -0
- package/dist/browser/inputs/markdown/Toolbar.js +172 -0
- package/dist/browser/inputs/markdown/Toolbar.js.map +1 -0
- package/dist/browser/inputs/markdown/actions.js +140 -0
- package/dist/browser/inputs/markdown/actions.js.map +1 -0
- package/dist/browser/inputs/markdown/active-formats.js +36 -0
- package/dist/browser/inputs/markdown/active-formats.js.map +1 -0
- package/dist/browser/inputs/markdown/behaviors.js +63 -0
- package/dist/browser/inputs/markdown/behaviors.js.map +1 -0
- package/dist/browser/inputs/markdown/code-zone.js +8 -0
- package/dist/browser/inputs/markdown/code-zone.js.map +1 -0
- package/dist/browser/internal/color.js +18 -0
- package/dist/browser/internal/color.js.map +1 -0
- package/dist/browser/internal/field.js +158 -0
- package/dist/browser/internal/field.js.map +1 -0
- package/dist/browser/internal/portal.js +17 -0
- package/dist/browser/internal/portal.js.map +1 -0
- package/dist/browser/intl/Format.js +273 -0
- package/dist/browser/intl/Format.js.map +1 -0
- package/dist/browser/intl/index.js +3 -0
- package/dist/browser/intl/index.js.map +1 -0
- package/dist/browser/intl/locale.js +63 -0
- package/dist/browser/intl/locale.js.map +1 -0
- package/dist/browser/intl/messages.js +753 -0
- package/dist/browser/intl/messages.js.map +1 -0
- package/dist/browser/layout/AppOverview.js +151 -0
- package/dist/browser/layout/AppOverview.js.map +1 -0
- package/dist/browser/layout/AppWorkspace.js +1502 -0
- package/dist/browser/layout/AppWorkspace.js.map +1 -0
- package/dist/browser/layout/DataPanel.js +122 -0
- package/dist/browser/layout/DataPanel.js.map +1 -0
- package/dist/browser/layout/DetailPanel.js +484 -0
- package/dist/browser/layout/DetailPanel.js.map +1 -0
- package/dist/browser/layout/Discussion.js +511 -0
- package/dist/browser/layout/Discussion.js.map +1 -0
- package/dist/browser/layout/FloatingWindow.js +332 -0
- package/dist/browser/layout/FloatingWindow.js.map +1 -0
- package/dist/browser/layout/PanelDialog.js +236 -0
- package/dist/browser/layout/PanelDialog.js.map +1 -0
- package/dist/browser/layout/PanelHeader.js +91 -0
- package/dist/browser/layout/PanelHeader.js.map +1 -0
- package/dist/browser/layout/Panes.js +978 -0
- package/dist/browser/layout/Panes.js.map +1 -0
- package/dist/browser/layout/ScrollArea.js +29 -0
- package/dist/browser/layout/ScrollArea.js.map +1 -0
- package/dist/browser/layout/Settings.js +381 -0
- package/dist/browser/layout/Settings.js.map +1 -0
- package/dist/browser/layout/SettingsCollection.js +212 -0
- package/dist/browser/layout/SettingsCollection.js.map +1 -0
- package/dist/browser/layout/SettingsModal.js +281 -0
- package/dist/browser/layout/SettingsModal.js.map +1 -0
- package/dist/browser/layout/app-workspace-controller.js +419 -0
- package/dist/browser/layout/app-workspace-controller.js.map +1 -0
- package/dist/browser/layout/app-workspace-state.js +125 -0
- package/dist/browser/layout/app-workspace-state.js.map +1 -0
- package/dist/browser/layout/floating-window-geometry.js +15 -0
- package/dist/browser/layout/floating-window-geometry.js.map +1 -0
- package/dist/browser/layout/index.js +17 -0
- package/dist/browser/layout/index.js.map +1 -0
- package/dist/browser/layout/panes-layout.js +436 -0
- package/dist/browser/layout/panes-layout.js.map +1 -0
- package/dist/browser/layout/stable-id.js +17 -0
- package/dist/browser/layout/stable-id.js.map +1 -0
- package/dist/browser/semantics.js +2 -0
- package/dist/browser/semantics.js.map +1 -0
- package/dist/browser/surfaces/Avatar.js +97 -0
- package/dist/browser/surfaces/Avatar.js.map +1 -0
- package/dist/browser/surfaces/DescriptionList.js +66 -0
- package/dist/browser/surfaces/DescriptionList.js.map +1 -0
- package/dist/browser/surfaces/LinkCard.js +40 -0
- package/dist/browser/surfaces/LinkCard.js.map +1 -0
- package/dist/browser/surfaces/NotFoundState.js +85 -0
- package/dist/browser/surfaces/NotFoundState.js.map +1 -0
- package/dist/browser/surfaces/NoticeCard.js +145 -0
- package/dist/browser/surfaces/NoticeCard.js.map +1 -0
- package/dist/browser/surfaces/Paper.js +33 -0
- package/dist/browser/surfaces/Paper.js.map +1 -0
- package/dist/browser/surfaces/Placeholder.js +90 -0
- package/dist/browser/surfaces/Placeholder.js.map +1 -0
- package/dist/browser/surfaces/ProgressBar.js +58 -0
- package/dist/browser/surfaces/ProgressBar.js.map +1 -0
- package/dist/browser/surfaces/StatCell.js +172 -0
- package/dist/browser/surfaces/StatCell.js.map +1 -0
- package/dist/browser/surfaces/StatGrid.js +80 -0
- package/dist/browser/surfaces/StatGrid.js.map +1 -0
- package/dist/browser/surfaces/StatusBadge.js +70 -0
- package/dist/browser/surfaces/StatusBadge.js.map +1 -0
- package/dist/browser/surfaces/Tag.js +94 -0
- package/dist/browser/surfaces/Tag.js.map +1 -0
- package/dist/browser/surfaces/index.js +13 -0
- package/dist/browser/surfaces/index.js.map +1 -0
- package/dist/browser/widgets/Widget.js +89 -0
- package/dist/browser/widgets/Widget.js.map +1 -0
- package/dist/browser/widgets/WidgetHero.js +47 -0
- package/dist/browser/widgets/WidgetHero.js.map +1 -0
- package/dist/browser/widgets/WidgetList.js +125 -0
- package/dist/browser/widgets/WidgetList.js.map +1 -0
- package/dist/browser/widgets/WidgetPills.js +78 -0
- package/dist/browser/widgets/WidgetPills.js.map +1 -0
- package/dist/browser/widgets/WidgetStat.js +114 -0
- package/dist/browser/widgets/WidgetStat.js.map +1 -0
- package/dist/browser/widgets/WidgetStatus.js +54 -0
- package/dist/browser/widgets/WidgetStatus.js.map +1 -0
- package/dist/browser/widgets/index.js +7 -0
- package/dist/browser/widgets/index.js.map +1 -0
- package/dist/global.css +3 -0
- package/dist/licenses/ibm-plex-mono.txt +93 -0
- package/dist/licenses/ibm-plex-sans.txt +93 -0
- package/dist/licenses/tabler-icons.txt +21 -0
- package/dist/plex.css +1 -0
- package/dist/ssr/actions/Button.js +203 -0
- package/dist/ssr/actions/Button.js.map +1 -0
- package/dist/ssr/actions/ContextMenu.js +128 -0
- package/dist/ssr/actions/ContextMenu.js.map +1 -0
- package/dist/ssr/actions/CopyButton.js +79 -0
- package/dist/ssr/actions/CopyButton.js.map +1 -0
- package/dist/ssr/actions/Disclosure.js +26 -0
- package/dist/ssr/actions/Disclosure.js.map +1 -0
- package/dist/ssr/actions/Dropdown.js +443 -0
- package/dist/ssr/actions/Dropdown.js.map +1 -0
- package/dist/ssr/actions/FilterChip.js +132 -0
- package/dist/ssr/actions/FilterChip.js.map +1 -0
- package/dist/ssr/actions/RemoveButton.js +45 -0
- package/dist/ssr/actions/RemoveButton.js.map +1 -0
- package/dist/ssr/actions/SegmentedControl.js +57 -0
- package/dist/ssr/actions/SegmentedControl.js.map +1 -0
- package/dist/ssr/actions/SplitButton.js +74 -0
- package/dist/ssr/actions/SplitButton.js.map +1 -0
- package/dist/ssr/actions/SpotlightSearch.js +38 -0
- package/dist/ssr/actions/SpotlightSearch.js.map +1 -0
- package/dist/ssr/actions/Tabs.js +91 -0
- package/dist/ssr/actions/Tabs.js.map +1 -0
- package/dist/ssr/actions/Toolbar.js +33 -0
- package/dist/ssr/actions/Toolbar.js.map +1 -0
- package/dist/ssr/actions/index.js +13 -0
- package/dist/ssr/actions/index.js.map +1 -0
- package/dist/ssr/chat/ChatComposer.js +392 -0
- package/dist/ssr/chat/ChatComposer.js.map +1 -0
- package/dist/ssr/chat/ChatPrimitives.js +377 -0
- package/dist/ssr/chat/ChatPrimitives.js.map +1 -0
- package/dist/ssr/chat/ChatRoot.js +10 -0
- package/dist/ssr/chat/ChatRoot.js.map +1 -0
- package/dist/ssr/chat/ChatTimeline.js +301 -0
- package/dist/ssr/chat/ChatTimeline.js.map +1 -0
- package/dist/ssr/chat/chat-behavior.js +53 -0
- package/dist/ssr/chat/chat-behavior.js.map +1 -0
- package/dist/ssr/chat/index.js +17 -0
- package/dist/ssr/chat/index.js.map +1 -0
- package/dist/ssr/chat/types.js +2 -0
- package/dist/ssr/chat/types.js.map +1 -0
- package/dist/ssr/content/Calendar.js +1542 -0
- package/dist/ssr/content/Calendar.js.map +1 -0
- package/dist/ssr/content/Chart.js +552 -0
- package/dist/ssr/content/Chart.js.map +1 -0
- package/dist/ssr/content/CodeDisplay.js +55 -0
- package/dist/ssr/content/CodeDisplay.js.map +1 -0
- package/dist/ssr/content/DataTable.js +470 -0
- package/dist/ssr/content/DataTable.js.map +1 -0
- package/dist/ssr/content/Docs.js +108 -0
- package/dist/ssr/content/Docs.js.map +1 -0
- package/dist/ssr/content/FileBrowser.js +422 -0
- package/dist/ssr/content/FileBrowser.js.map +1 -0
- package/dist/ssr/content/FileTree.js +299 -0
- package/dist/ssr/content/FileTree.js.map +1 -0
- package/dist/ssr/content/FileView.js +612 -0
- package/dist/ssr/content/FileView.js.map +1 -0
- package/dist/ssr/content/Lightbox.js +164 -0
- package/dist/ssr/content/Lightbox.js.map +1 -0
- package/dist/ssr/content/LogEntriesTable.js +106 -0
- package/dist/ssr/content/LogEntriesTable.js.map +1 -0
- package/dist/ssr/content/MarkdownView.js +119 -0
- package/dist/ssr/content/MarkdownView.js.map +1 -0
- package/dist/ssr/content/Pagination.js +141 -0
- package/dist/ssr/content/Pagination.js.map +1 -0
- package/dist/ssr/content/PdfPreview.js +126 -0
- package/dist/ssr/content/PdfPreview.js.map +1 -0
- package/dist/ssr/content/RangePicker.js +35 -0
- package/dist/ssr/content/RangePicker.js.map +1 -0
- package/dist/ssr/content/StructuredDataPreview.js +127 -0
- package/dist/ssr/content/StructuredDataPreview.js.map +1 -0
- package/dist/ssr/content/calendar-event-layout.js +92 -0
- package/dist/ssr/content/calendar-event-layout.js.map +1 -0
- package/dist/ssr/content/calendar-pointer.js +114 -0
- package/dist/ssr/content/calendar-pointer.js.map +1 -0
- package/dist/ssr/content/chart-map-viewport.js +33 -0
- package/dist/ssr/content/chart-map-viewport.js.map +1 -0
- package/dist/ssr/content/chart-state-timeline.js +124 -0
- package/dist/ssr/content/chart-state-timeline.js.map +1 -0
- package/dist/ssr/content/code-highlight.js +144 -0
- package/dist/ssr/content/code-highlight.js.map +1 -0
- package/dist/ssr/content/file-tree.js +93 -0
- package/dist/ssr/content/file-tree.js.map +1 -0
- package/dist/ssr/content/file-view-preview.js +112 -0
- package/dist/ssr/content/file-view-preview.js.map +1 -0
- package/dist/ssr/content/index.js +16 -0
- package/dist/ssr/content/index.js.map +1 -0
- package/dist/ssr/feedback/InlineGuidance.js +26 -0
- package/dist/ssr/feedback/InlineGuidance.js.map +1 -0
- package/dist/ssr/feedback/Tooltip.js +156 -0
- package/dist/ssr/feedback/Tooltip.js.map +1 -0
- package/dist/ssr/feedback/dialog-core.js +207 -0
- package/dist/ssr/feedback/dialog-core.js.map +1 -0
- package/dist/ssr/feedback/index.js +6 -0
- package/dist/ssr/feedback/index.js.map +1 -0
- package/dist/ssr/feedback/prompts.js +703 -0
- package/dist/ssr/feedback/prompts.js.map +1 -0
- package/dist/ssr/feedback/toast.js +271 -0
- package/dist/ssr/feedback/toast.js.map +1 -0
- package/dist/ssr/feedback/tooltip-position.js +25 -0
- package/dist/ssr/feedback/tooltip-position.js.map +1 -0
- package/dist/ssr/index.js +11 -0
- package/dist/ssr/index.js.map +1 -0
- package/dist/ssr/inputs/AutocompleteEditor.js +463 -0
- package/dist/ssr/inputs/AutocompleteEditor.js.map +1 -0
- package/dist/ssr/inputs/AutocompleteSelect.js +420 -0
- package/dist/ssr/inputs/AutocompleteSelect.js.map +1 -0
- package/dist/ssr/inputs/Checkbox.js +75 -0
- package/dist/ssr/inputs/Checkbox.js.map +1 -0
- package/dist/ssr/inputs/CheckboxCard.js +69 -0
- package/dist/ssr/inputs/CheckboxCard.js.map +1 -0
- package/dist/ssr/inputs/ChoiceGroups.js +101 -0
- package/dist/ssr/inputs/ChoiceGroups.js.map +1 -0
- package/dist/ssr/inputs/ChoiceInputs.js +250 -0
- package/dist/ssr/inputs/ChoiceInputs.js.map +1 -0
- package/dist/ssr/inputs/Combobox.js +177 -0
- package/dist/ssr/inputs/Combobox.js.map +1 -0
- package/dist/ssr/inputs/DatePicker.js +629 -0
- package/dist/ssr/inputs/DatePicker.js.map +1 -0
- package/dist/ssr/inputs/FileInputs.js +543 -0
- package/dist/ssr/inputs/FileInputs.js.map +1 -0
- package/dist/ssr/inputs/MultiSelectInput.js +347 -0
- package/dist/ssr/inputs/MultiSelectInput.js.map +1 -0
- package/dist/ssr/inputs/NumberInput.js +177 -0
- package/dist/ssr/inputs/NumberInput.js.map +1 -0
- package/dist/ssr/inputs/Select.js +308 -0
- package/dist/ssr/inputs/Select.js.map +1 -0
- package/dist/ssr/inputs/SelectChip.js +129 -0
- package/dist/ssr/inputs/SelectChip.js.map +1 -0
- package/dist/ssr/inputs/SpecialInputs.js +116 -0
- package/dist/ssr/inputs/SpecialInputs.js.map +1 -0
- package/dist/ssr/inputs/Switch.js +62 -0
- package/dist/ssr/inputs/Switch.js.map +1 -0
- package/dist/ssr/inputs/TagEditor.js +280 -0
- package/dist/ssr/inputs/TagEditor.js.map +1 -0
- package/dist/ssr/inputs/TagsInput.js +122 -0
- package/dist/ssr/inputs/TagsInput.js.map +1 -0
- package/dist/ssr/inputs/TemplateEditor.js +164 -0
- package/dist/ssr/inputs/TemplateEditor.js.map +1 -0
- package/dist/ssr/inputs/TextInput.js +211 -0
- package/dist/ssr/inputs/TextInput.js.map +1 -0
- package/dist/ssr/inputs/choice.js +188 -0
- package/dist/ssr/inputs/choice.js.map +1 -0
- package/dist/ssr/inputs/completion/behaviors.js +108 -0
- package/dist/ssr/inputs/completion/behaviors.js.map +1 -0
- package/dist/ssr/inputs/completion/engine.js +103 -0
- package/dist/ssr/inputs/completion/engine.js.map +1 -0
- package/dist/ssr/inputs/completion/index.js +4 -0
- package/dist/ssr/inputs/completion/index.js.map +1 -0
- package/dist/ssr/inputs/completion/overlay.js +25 -0
- package/dist/ssr/inputs/completion/overlay.js.map +1 -0
- package/dist/ssr/inputs/date-picker.js +123 -0
- package/dist/ssr/inputs/date-picker.js.map +1 -0
- package/dist/ssr/inputs/editor-dom.js +26 -0
- package/dist/ssr/inputs/editor-dom.js.map +1 -0
- package/dist/ssr/inputs/field-contract.js +9 -0
- package/dist/ssr/inputs/field-contract.js.map +1 -0
- package/dist/ssr/inputs/icon-options.js +46 -0
- package/dist/ssr/inputs/icon-options.js.map +1 -0
- package/dist/ssr/inputs/image-crop.js +145 -0
- package/dist/ssr/inputs/image-crop.js.map +1 -0
- package/dist/ssr/inputs/index.js +23 -0
- package/dist/ssr/inputs/index.js.map +1 -0
- package/dist/ssr/inputs/markdown/MarkdownEditor.js +516 -0
- package/dist/ssr/inputs/markdown/MarkdownEditor.js.map +1 -0
- package/dist/ssr/inputs/markdown/Toolbar.js +115 -0
- package/dist/ssr/inputs/markdown/Toolbar.js.map +1 -0
- package/dist/ssr/inputs/markdown/actions.js +140 -0
- package/dist/ssr/inputs/markdown/actions.js.map +1 -0
- package/dist/ssr/inputs/markdown/active-formats.js +36 -0
- package/dist/ssr/inputs/markdown/active-formats.js.map +1 -0
- package/dist/ssr/inputs/markdown/behaviors.js +63 -0
- package/dist/ssr/inputs/markdown/behaviors.js.map +1 -0
- package/dist/ssr/inputs/markdown/code-zone.js +8 -0
- package/dist/ssr/inputs/markdown/code-zone.js.map +1 -0
- package/dist/ssr/internal/color.js +18 -0
- package/dist/ssr/internal/color.js.map +1 -0
- package/dist/ssr/internal/field.js +90 -0
- package/dist/ssr/internal/field.js.map +1 -0
- package/dist/ssr/internal/portal.js +17 -0
- package/dist/ssr/internal/portal.js.map +1 -0
- package/dist/ssr/intl/Format.js +192 -0
- package/dist/ssr/intl/Format.js.map +1 -0
- package/dist/ssr/intl/index.js +3 -0
- package/dist/ssr/intl/index.js.map +1 -0
- package/dist/ssr/intl/locale.js +63 -0
- package/dist/ssr/intl/locale.js.map +1 -0
- package/dist/ssr/intl/messages.js +753 -0
- package/dist/ssr/intl/messages.js.map +1 -0
- package/dist/ssr/layout/AppOverview.js +85 -0
- package/dist/ssr/layout/AppOverview.js.map +1 -0
- package/dist/ssr/layout/AppWorkspace.js +976 -0
- package/dist/ssr/layout/AppWorkspace.js.map +1 -0
- package/dist/ssr/layout/DataPanel.js +101 -0
- package/dist/ssr/layout/DataPanel.js.map +1 -0
- package/dist/ssr/layout/DetailPanel.js +284 -0
- package/dist/ssr/layout/DetailPanel.js.map +1 -0
- package/dist/ssr/layout/Discussion.js +319 -0
- package/dist/ssr/layout/Discussion.js.map +1 -0
- package/dist/ssr/layout/FloatingWindow.js +259 -0
- package/dist/ssr/layout/FloatingWindow.js.map +1 -0
- package/dist/ssr/layout/PanelDialog.js +136 -0
- package/dist/ssr/layout/PanelDialog.js.map +1 -0
- package/dist/ssr/layout/PanelHeader.js +45 -0
- package/dist/ssr/layout/PanelHeader.js.map +1 -0
- package/dist/ssr/layout/Panes.js +678 -0
- package/dist/ssr/layout/Panes.js.map +1 -0
- package/dist/ssr/layout/ScrollArea.js +18 -0
- package/dist/ssr/layout/ScrollArea.js.map +1 -0
- package/dist/ssr/layout/Settings.js +219 -0
- package/dist/ssr/layout/Settings.js.map +1 -0
- package/dist/ssr/layout/SettingsCollection.js +150 -0
- package/dist/ssr/layout/SettingsCollection.js.map +1 -0
- package/dist/ssr/layout/SettingsModal.js +156 -0
- package/dist/ssr/layout/SettingsModal.js.map +1 -0
- package/dist/ssr/layout/app-workspace-controller.js +419 -0
- package/dist/ssr/layout/app-workspace-controller.js.map +1 -0
- package/dist/ssr/layout/app-workspace-state.js +125 -0
- package/dist/ssr/layout/app-workspace-state.js.map +1 -0
- package/dist/ssr/layout/floating-window-geometry.js +15 -0
- package/dist/ssr/layout/floating-window-geometry.js.map +1 -0
- package/dist/ssr/layout/index.js +17 -0
- package/dist/ssr/layout/index.js.map +1 -0
- package/dist/ssr/layout/panes-layout.js +436 -0
- package/dist/ssr/layout/panes-layout.js.map +1 -0
- package/dist/ssr/layout/stable-id.js +17 -0
- package/dist/ssr/layout/stable-id.js.map +1 -0
- package/dist/ssr/semantics.js +2 -0
- package/dist/ssr/semantics.js.map +1 -0
- package/dist/ssr/surfaces/Avatar.js +43 -0
- package/dist/ssr/surfaces/Avatar.js.map +1 -0
- package/dist/ssr/surfaces/DescriptionList.js +25 -0
- package/dist/ssr/surfaces/DescriptionList.js.map +1 -0
- package/dist/ssr/surfaces/LinkCard.js +25 -0
- package/dist/ssr/surfaces/LinkCard.js.map +1 -0
- package/dist/ssr/surfaces/NotFoundState.js +38 -0
- package/dist/ssr/surfaces/NotFoundState.js.map +1 -0
- package/dist/ssr/surfaces/NoticeCard.js +83 -0
- package/dist/ssr/surfaces/NoticeCard.js.map +1 -0
- package/dist/ssr/surfaces/Paper.js +32 -0
- package/dist/ssr/surfaces/Paper.js.map +1 -0
- package/dist/ssr/surfaces/Placeholder.js +76 -0
- package/dist/ssr/surfaces/Placeholder.js.map +1 -0
- package/dist/ssr/surfaces/ProgressBar.js +13 -0
- package/dist/ssr/surfaces/ProgressBar.js.map +1 -0
- package/dist/ssr/surfaces/StatCell.js +80 -0
- package/dist/ssr/surfaces/StatCell.js.map +1 -0
- package/dist/ssr/surfaces/StatGrid.js +62 -0
- package/dist/ssr/surfaces/StatGrid.js.map +1 -0
- package/dist/ssr/surfaces/StatusBadge.js +38 -0
- package/dist/ssr/surfaces/StatusBadge.js.map +1 -0
- package/dist/ssr/surfaces/Tag.js +32 -0
- package/dist/ssr/surfaces/Tag.js.map +1 -0
- package/dist/ssr/surfaces/index.js +13 -0
- package/dist/ssr/surfaces/index.js.map +1 -0
- package/dist/ssr/widgets/Widget.js +54 -0
- package/dist/ssr/widgets/Widget.js.map +1 -0
- package/dist/ssr/widgets/WidgetHero.js +23 -0
- package/dist/ssr/widgets/WidgetHero.js.map +1 -0
- package/dist/ssr/widgets/WidgetList.js +73 -0
- package/dist/ssr/widgets/WidgetList.js.map +1 -0
- package/dist/ssr/widgets/WidgetPills.js +40 -0
- package/dist/ssr/widgets/WidgetPills.js.map +1 -0
- package/dist/ssr/widgets/WidgetStat.js +45 -0
- package/dist/ssr/widgets/WidgetStat.js.map +1 -0
- package/dist/ssr/widgets/WidgetStatus.js +23 -0
- package/dist/ssr/widgets/WidgetStatus.js.map +1 -0
- package/dist/ssr/widgets/index.js +7 -0
- package/dist/ssr/widgets/index.js.map +1 -0
- package/dist/styles.css +1 -0
- package/dist/tabler-icons-q30jt7jk.woff2 +0 -0
- package/dist/tabler.css +4 -0
- package/package.json +77 -0
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { computeDomain, escapeXml, extendDomainToNice, mapRange, niceStep, svgRoot } from "@k2b/stdlib";
|
|
2
|
+
const ROW_HEIGHT = 24;
|
|
3
|
+
const TOP = 38;
|
|
4
|
+
const AXIS_HEIGHT = 28;
|
|
5
|
+
const LEGEND_HEIGHT = 24;
|
|
6
|
+
const MIN_VIEW_FRACTION = 1 / 64;
|
|
7
|
+
const finiteDomain = domain => {
|
|
8
|
+
if (!Number.isFinite(domain[0]) || !Number.isFinite(domain[1]) || domain[0] === domain[1]) return null;
|
|
9
|
+
return domain[0] < domain[1] ? domain : [domain[1], domain[0]];
|
|
10
|
+
};
|
|
11
|
+
export const stateTimelineDomain = (rows, domain) => {
|
|
12
|
+
const explicit = domain ? finiteDomain(domain) : null;
|
|
13
|
+
if (explicit) return explicit;
|
|
14
|
+
return computeDomain(rows.flatMap(row => row.intervals.flatMap(interval => [interval.from, interval.to])));
|
|
15
|
+
};
|
|
16
|
+
export const normalizeStateTimelineViewport = (viewport, fullDomain) => {
|
|
17
|
+
const full = finiteDomain(fullDomain) ?? [0, 1];
|
|
18
|
+
const candidate = viewport ? finiteDomain(viewport) : null;
|
|
19
|
+
if (!candidate) return full;
|
|
20
|
+
const span = Math.min(candidate[1] - candidate[0], full[1] - full[0]);
|
|
21
|
+
const from = Math.max(full[0], Math.min(candidate[0], full[1] - span));
|
|
22
|
+
return [from, from + span];
|
|
23
|
+
};
|
|
24
|
+
export const zoomStateTimelineViewport = (viewport, fullDomain, delta, anchor = 0.5) => {
|
|
25
|
+
const current = normalizeStateTimelineViewport(viewport, fullDomain);
|
|
26
|
+
const fullSpan = fullDomain[1] - fullDomain[0];
|
|
27
|
+
const minSpan = Math.max(1, fullSpan * MIN_VIEW_FRACTION);
|
|
28
|
+
const factor = delta > 0 ? 0.7 : 1 / 0.7;
|
|
29
|
+
const nextSpan = Math.max(minSpan, Math.min(fullSpan, (current[1] - current[0]) * factor));
|
|
30
|
+
const safeAnchor = Math.max(0, Math.min(1, anchor));
|
|
31
|
+
const anchorValue = current[0] + (current[1] - current[0]) * safeAnchor;
|
|
32
|
+
return normalizeStateTimelineViewport([anchorValue - nextSpan * safeAnchor, anchorValue + nextSpan * (1 - safeAnchor)], fullDomain);
|
|
33
|
+
};
|
|
34
|
+
export const panStateTimelineViewport = (viewport, fullDomain, pixelDelta, plotWidth) => {
|
|
35
|
+
if (plotWidth <= 0) return normalizeStateTimelineViewport(viewport, fullDomain);
|
|
36
|
+
const current = normalizeStateTimelineViewport(viewport, fullDomain);
|
|
37
|
+
const timeDelta = -pixelDelta / plotWidth * (current[1] - current[0]);
|
|
38
|
+
return normalizeStateTimelineViewport([current[0] + timeDelta, current[1] + timeDelta], fullDomain);
|
|
39
|
+
};
|
|
40
|
+
export const stateTimelineHeight = (rows, legend = true) => Math.max(160, TOP + rows * ROW_HEIGHT + AXIS_HEIGHT + (legend ? LEGEND_HEIGHT : 0));
|
|
41
|
+
const fmt = value => Number.isInteger(value) ? String(value) : value.toFixed(2);
|
|
42
|
+
const safeHref = href => href && href.startsWith("/") && !href.startsWith("//") ? href : null;
|
|
43
|
+
const truncate = (value, maxChars) => value.length <= maxChars ? value : `${value.slice(0, Math.max(1, maxChars - 1))}…`;
|
|
44
|
+
const interactiveGroup = (body, href, tooltip, ariaLabel) => {
|
|
45
|
+
const safe = safeHref(href);
|
|
46
|
+
const attrs = [`aria-label="${escapeXml(ariaLabel)}"`, tooltip ? `data-chart-tooltip="${escapeXml(tooltip)}"` : ""].filter(Boolean).join(" ");
|
|
47
|
+
const title = tooltip ? `<title>${escapeXml(tooltip)}</title>` : "";
|
|
48
|
+
return safe ? `<a href="${escapeXml(safe)}" ${attrs}>${title}${body}</a>` : `<g ${attrs}${tooltip ? ' tabindex="0" role="img"' : ""}>${title}${body}</g>`;
|
|
49
|
+
};
|
|
50
|
+
export const renderStateTimelineSvg = opts => {
|
|
51
|
+
const {
|
|
52
|
+
width,
|
|
53
|
+
height,
|
|
54
|
+
rows
|
|
55
|
+
} = opts;
|
|
56
|
+
const fullDomain = stateTimelineDomain(rows, opts.domain);
|
|
57
|
+
const viewport = normalizeStateTimelineViewport(opts.viewport, fullDomain);
|
|
58
|
+
const showLegend = opts.legend !== false && (opts.states?.length ?? 0) > 0;
|
|
59
|
+
const legendHeight = showLegend ? LEGEND_HEIGHT : 0;
|
|
60
|
+
const labels = rows.map(row => row.label);
|
|
61
|
+
const idealGutter = Math.max(72, ...labels.map(label => label.length * 6.3 + 20));
|
|
62
|
+
const gutter = Math.min(240, width * 0.35, idealGutter);
|
|
63
|
+
const plotLeft = gutter;
|
|
64
|
+
const plotRight = Math.max(plotLeft + 1, width - 16);
|
|
65
|
+
const rowsBottom = Math.min(height - AXIS_HEIGHT - legendHeight, TOP + rows.length * ROW_HEIGHT);
|
|
66
|
+
const stateStyles = new Map((opts.states ?? []).map((state, index) => [state.state, {
|
|
67
|
+
...state,
|
|
68
|
+
index
|
|
69
|
+
}]));
|
|
70
|
+
const stateKeys = opts.states?.map(state => state.state) ?? [...new Set(rows.flatMap(row => row.intervals.map(i => i.state)))];
|
|
71
|
+
const stateIndexes = new Map(stateKeys.map((state, index) => [state, index]));
|
|
72
|
+
const body = [];
|
|
73
|
+
const maxLabelChars = Math.max(4, Math.floor((gutter - 18) / 6.3));
|
|
74
|
+
rows.forEach((row, rowIndex) => {
|
|
75
|
+
const y = TOP + rowIndex * ROW_HEIGHT;
|
|
76
|
+
if (y + ROW_HEIGHT > rowsBottom + 1) return;
|
|
77
|
+
const label = truncate(row.label, maxLabelChars);
|
|
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
|
+
body.push(interactiveGroup(labelBody, row.href, row.tooltip ?? row.label, row.label));
|
|
80
|
+
for (const interval of row.intervals) {
|
|
81
|
+
if (!Number.isFinite(interval.from) || !Number.isFinite(interval.to)) continue;
|
|
82
|
+
const intervalFrom = Math.min(interval.from, interval.to);
|
|
83
|
+
const intervalTo = Math.max(interval.from, interval.to);
|
|
84
|
+
if (intervalTo < viewport[0] || intervalFrom > viewport[1]) continue;
|
|
85
|
+
const from = Math.max(viewport[0], intervalFrom);
|
|
86
|
+
const to = Math.min(viewport[1], intervalTo);
|
|
87
|
+
const x = mapRange(from, viewport, [plotLeft, plotRight]);
|
|
88
|
+
const x2 = mapRange(to, viewport, [plotLeft, plotRight]);
|
|
89
|
+
const style = stateStyles.get(interval.state);
|
|
90
|
+
const stateIndex = style?.index ?? stateIndexes.get(interval.state) ?? 0;
|
|
91
|
+
const color = style?.color ? ` fill="${escapeXml(style.color)}"` : "";
|
|
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
|
+
const stateLabel = style?.label ?? interval.state;
|
|
94
|
+
body.push(interactiveGroup(rect, interval.href, interval.tooltip ?? interval.label, [row.label, interval.label, stateLabel].filter(Boolean).join(", ")));
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
const tickTarget = Math.max(2, Math.min(8, Math.floor((plotRight - plotLeft) / 110)));
|
|
98
|
+
const ticks = extendDomainToNice(viewport[0], viewport[1], niceStep(viewport[1] - viewport[0], tickTarget)).ticks;
|
|
99
|
+
const format = opts.xAxis?.format ?? (value => fmt(value));
|
|
100
|
+
for (const tick of ticks) {
|
|
101
|
+
if (tick < viewport[0] || tick > viewport[1]) continue;
|
|
102
|
+
const x = mapRange(tick, viewport, [plotLeft, plotRight]);
|
|
103
|
+
body.push(`<line x1="${fmt(x)}" x2="${fmt(x)}" y1="${TOP}" y2="${fmt(rowsBottom)}" stroke="currentColor" opacity="0.08"/>`, `<text class="stdlib-chart-heatmap-label" x="${fmt(x)}" y="${fmt(rowsBottom + 17)}" text-anchor="middle">${escapeXml(format(tick))}</text>`);
|
|
104
|
+
}
|
|
105
|
+
if (opts.xAxis?.label) {
|
|
106
|
+
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
|
+
}
|
|
108
|
+
if (showLegend) {
|
|
109
|
+
let x = plotLeft;
|
|
110
|
+
const y = height - 9;
|
|
111
|
+
for (const [index, state] of (opts.states ?? []).entries()) {
|
|
112
|
+
const color = state.color ? ` fill="${escapeXml(state.color)}"` : "";
|
|
113
|
+
const label = state.label ?? state.state;
|
|
114
|
+
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
|
+
x += 20 + label.length * 6.2;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return svgRoot({
|
|
119
|
+
width,
|
|
120
|
+
height,
|
|
121
|
+
className: opts.className
|
|
122
|
+
}, body.join(""));
|
|
123
|
+
};
|
|
124
|
+
//# sourceMappingURL=chart-state-timeline.js.map
|
|
@@ -0,0 +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":"AAAA,SAASA,aAAa,EAAEC,SAAS,EAAEC,kBAAkB,EAAEC,QAAQ,EAAEC,QAAQ,EAAEC,OAAO,QAAQ,aAAa;AAmCvG,MAAMC,UAAU,GAAG,EAAE;AACrB,MAAMC,GAAG,GAAG,EAAE;AACd,MAAMC,WAAW,GAAG,EAAE;AACtB,MAAMC,aAAa,GAAG,EAAE;AACxB,MAAMC,iBAAiB,GAAG,CAAC,GAAG,EAAE;AAEhC,MAAMC,YAAY,GAAIC,MAA2B,IAAiC;EAChF,IAAI,CAACC,MAAM,CAACC,QAAQ,CAACF,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAACC,MAAM,CAACC,QAAQ,CAACF,MAAM,CAAC,CAAC,CAAC,CAAC,IAAIA,MAAM,CAAC,CAAC,CAAC,KAAKA,MAAM,CAAC,CAAC,CAAC,EAAE,OAAO,IAAI;EACtG,OAAOA,MAAM,CAAC,CAAC,CAAC,GAAGA,MAAM,CAAC,CAAC,CAAC,GAAGA,MAAM,GAAG,CAACA,MAAM,CAAC,CAAC,CAAC,EAAEA,MAAM,CAAC,CAAC,CAAC,CAAC;AAChE,CAAC;AAED,OAAO,MAAMG,mBAAmB,GAAGA,CAACC,IAAiC,EAAEJ,MAA4B,KAA0B;EAC3H,MAAMK,QAAQ,GAAGL,MAAM,GAAGD,YAAY,CAACC,MAAM,CAAC,GAAG,IAAI;EACrD,IAAIK,QAAQ,EAAE,OAAOA,QAAQ;EAC7B,OAAOjB,aAAa,CAACgB,IAAI,CAACE,OAAO,CAAEC,GAAG,IAAKA,GAAG,CAACC,SAAS,CAACF,OAAO,CAAEG,QAAQ,IAAK,CAACA,QAAQ,CAACC,IAAI,EAAED,QAAQ,CAACE,EAAE,CAAC,CAAC,CAAC,CAAC;AAChH,CAAC;AAED,OAAO,MAAMC,8BAA8B,GAAGA,CAC5CC,QAAyC,EACzCC,UAA+B,KACP;EACxB,MAAMC,IAAI,GAAGhB,YAAY,CAACe,UAAU,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC;EAC/C,MAAME,SAAS,GAAGH,QAAQ,GAAGd,YAAY,CAACc,QAAQ,CAAC,GAAG,IAAI;EAC1D,IAAI,CAACG,SAAS,EAAE,OAAOD,IAAI;EAC3B,MAAME,IAAI,GAAGC,IAAI,CAACC,GAAG,CAACH,SAAS,CAAC,CAAC,CAAC,GAAGA,SAAS,CAAC,CAAC,CAAC,EAAED,IAAI,CAAC,CAAC,CAAC,GAAGA,IAAI,CAAC,CAAC,CAAC,CAAC;EACrE,MAAML,IAAI,GAAGQ,IAAI,CAACE,GAAG,CAACL,IAAI,CAAC,CAAC,CAAC,EAAEG,IAAI,CAACC,GAAG,CAACH,SAAS,CAAC,CAAC,CAAC,EAAED,IAAI,CAAC,CAAC,CAAC,GAAGE,IAAI,CAAC,CAAC;EACtE,OAAO,CAACP,IAAI,EAAEA,IAAI,GAAGO,IAAI,CAAC;AAC5B,CAAC;AAED,OAAO,MAAMI,yBAAyB,GAAGA,CACvCR,QAA6B,EAC7BC,UAA+B,EAC/BQ,KAAa,EACbC,MAAM,GAAG,GAAG,KACY;EACxB,MAAMC,OAAO,GAAGZ,8BAA8B,CAACC,QAAQ,EAAEC,UAAU,CAAC;EACpE,MAAMW,QAAQ,GAAGX,UAAU,CAAC,CAAC,CAAC,GAAGA,UAAU,CAAC,CAAC,CAAC;EAC9C,MAAMY,OAAO,GAAGR,IAAI,CAACE,GAAG,CAAC,CAAC,EAAEK,QAAQ,GAAG3B,iBAAiB,CAAC;EACzD,MAAM6B,MAAM,GAAGL,KAAK,GAAG,CAAC,GAAG,GAAG,GAAG,CAAC,GAAG,GAAG;EACxC,MAAMM,QAAQ,GAAGV,IAAI,CAACE,GAAG,CAACM,OAAO,EAAER,IAAI,CAACC,GAAG,CAACM,QAAQ,EAAE,CAACD,OAAO,CAAC,CAAC,CAAC,GAAGA,OAAO,CAAC,CAAC,CAAC,IAAIG,MAAM,CAAC,CAAC;EAC1F,MAAME,UAAU,GAAGX,IAAI,CAACE,GAAG,CAAC,CAAC,EAAEF,IAAI,CAACC,GAAG,CAAC,CAAC,EAAEI,MAAM,CAAC,CAAC;EACnD,MAAMO,WAAW,GAAGN,OAAO,CAAC,CAAC,CAAC,GAAG,CAACA,OAAO,CAAC,CAAC,CAAC,GAAGA,OAAO,CAAC,CAAC,CAAC,IAAIK,UAAU;EACvE,OAAOjB,8BAA8B,CAAC,CAACkB,WAAW,GAAGF,QAAQ,GAAGC,UAAU,EAAEC,WAAW,GAAGF,QAAQ,IAAI,CAAC,GAAGC,UAAU,CAAC,CAAC,EAAEf,UAAU,CAAC;AACrI,CAAC;AAED,OAAO,MAAMiB,wBAAwB,GAAGA,CACtClB,QAA6B,EAC7BC,UAA+B,EAC/BkB,UAAkB,EAClBC,SAAiB,KACO;EACxB,IAAIA,SAAS,IAAI,CAAC,EAAE,OAAOrB,8BAA8B,CAACC,QAAQ,EAAEC,UAAU,CAAC;EAC/E,MAAMU,OAAO,GAAGZ,8BAA8B,CAACC,QAAQ,EAAEC,UAAU,CAAC;EACpE,MAAMoB,SAAS,GAAI,CAACF,UAAU,GAAGC,SAAS,IAAKT,OAAO,CAAC,CAAC,CAAC,GAAGA,OAAO,CAAC,CAAC,CAAC,CAAC;EACvE,OAAOZ,8BAA8B,CAAC,CAACY,OAAO,CAAC,CAAC,CAAC,GAAGU,SAAS,EAAEV,OAAO,CAAC,CAAC,CAAC,GAAGU,SAAS,CAAC,EAAEpB,UAAU,CAAC;AACrG,CAAC;AAED,OAAO,MAAMqB,mBAAmB,GAAGA,CAAC/B,IAAY,EAAEgC,MAAM,GAAG,IAAI,KAC7DlB,IAAI,CAACE,GAAG,CAAC,GAAG,EAAEzB,GAAG,GAAGS,IAAI,GAAGV,UAAU,GAAGE,WAAW,IAAIwC,MAAM,GAAGvC,aAAa,GAAG,CAAC,CAAC,CAAC;AAErF,MAAMwC,GAAG,GAAIC,KAAa,IAAcrC,MAAM,CAACsC,SAAS,CAACD,KAAK,CAAC,GAAGE,MAAM,CAACF,KAAK,CAAC,GAAGA,KAAK,CAACG,OAAO,CAAC,CAAC,CAAE;AAEnG,MAAMC,QAAQ,GAAIC,IAAwB,IAAqBA,IAAI,IAAIA,IAAI,CAACC,UAAU,CAAC,GAAG,CAAC,IAAI,CAACD,IAAI,CAACC,UAAU,CAAC,IAAI,CAAC,GAAGD,IAAI,GAAG,IAAK;AAEpI,MAAME,QAAQ,GAAGA,CAACP,KAAa,EAAEQ,QAAgB,KAC/CR,KAAK,CAACS,MAAM,IAAID,QAAQ,GAAGR,KAAK,GAAG,GAAGA,KAAK,CAACU,KAAK,CAAC,CAAC,EAAE9B,IAAI,CAACE,GAAG,CAAC,CAAC,EAAE0B,QAAQ,GAAG,CAAC,CAAC,CAAC,GAAG;AAEpF,MAAMG,gBAAgB,GAAGA,CAACC,IAAY,EAAEP,IAAwB,EAAEQ,OAA2B,EAAEC,SAAiB,KAAa;EAC3H,MAAMC,IAAI,GAAGX,QAAQ,CAACC,IAAI,CAAC;EAC3B,MAAMW,KAAK,GAAG,CAAC,eAAejE,SAAS,CAAC+D,SAAS,CAAC,GAAG,EAAED,OAAO,GAAG,uBAAuB9D,SAAS,CAAC8D,OAAO,CAAC,GAAG,GAAG,EAAE,CAAC,CAChHI,MAAM,CAACC,OAAO,CAAC,CACfC,IAAI,CAAC,GAAG,CAAC;EACZ,MAAMC,KAAK,GAAGP,OAAO,GAAG,UAAU9D,SAAS,CAAC8D,OAAO,CAAC,UAAU,GAAG,EAAE;EACnE,OAAOE,IAAI,GACP,YAAYhE,SAAS,CAACgE,IAAI,CAAC,KAAKC,KAAK,IAAII,KAAK,GAAGR,IAAI,MAAM,GAC3D,MAAMI,KAAK,GAAGH,OAAO,GAAG,0BAA0B,GAAG,EAAE,IAAIO,KAAK,GAAGR,IAAI,MAAM;AACnF,CAAC;AAED,OAAO,MAAMS,sBAAsB,GACjCC,IAKC,IACU;EACX,MAAM;IAAEC,KAAK;IAAEC,MAAM;IAAE1D;EAAK,CAAC,GAAGwD,IAAI;EACpC,MAAM9C,UAAU,GAAGX,mBAAmB,CAACC,IAAI,EAAEwD,IAAI,CAAC5D,MAAM,CAAC;EACzD,MAAMa,QAAQ,GAAGD,8BAA8B,CAACgD,IAAI,CAAC/C,QAAQ,EAAEC,UAAU,CAAC;EAC1E,MAAMiD,UAAU,GAAGH,IAAI,CAACxB,MAAM,KAAK,KAAK,IAAI,CAACwB,IAAI,CAACI,MAAM,EAAEjB,MAAM,IAAI,CAAC,IAAI,CAAC;EAC1E,MAAMkB,YAAY,GAAGF,UAAU,GAAGlE,aAAa,GAAG,CAAC;EACnD,MAAMqE,MAAM,GAAG9D,IAAI,CAAC+D,GAAG,CAAE5D,GAAG,IAAKA,GAAG,CAAC6D,KAAK,CAAC;EAC3C,MAAMC,WAAW,GAAGnD,IAAI,CAACE,GAAG,CAAC,EAAE,EAAE,GAAG8C,MAAM,CAACC,GAAG,CAAEC,KAAK,IAAKA,KAAK,CAACrB,MAAM,GAAG,GAAG,GAAG,EAAE,CAAC,CAAC;EACnF,MAAMuB,MAAM,GAAGpD,IAAI,CAACC,GAAG,CAAC,GAAG,EAAE0C,KAAK,GAAG,IAAI,EAAEQ,WAAW,CAAC;EACvD,MAAME,QAAQ,GAAGD,MAAM;EACvB,MAAME,SAAS,GAAGtD,IAAI,CAACE,GAAG,CAACmD,QAAQ,GAAG,CAAC,EAAEV,KAAK,GAAG,EAAE,CAAC;EACpD,MAAMY,UAAU,GAAGvD,IAAI,CAACC,GAAG,CAAC2C,MAAM,GAAGlE,WAAW,GAAGqE,YAAY,EAAEtE,GAAG,GAAGS,IAAI,CAAC2C,MAAM,GAAGrD,UAAU,CAAC;EAChG,MAAMgF,WAAW,GAAG,IAAIC,GAAG,CAAC,CAACf,IAAI,CAACI,MAAM,IAAI,EAAE,EAAEG,GAAG,CAAC,CAACS,KAAK,EAAEC,KAAK,KAAK,CAACD,KAAK,CAACA,KAAK,EAAE;IAAE,GAAGA,KAAK;IAAEC;EAAM,CAAC,CAAC,CAAC,CAAC;EAC1G,MAAMC,SAAS,GAAGlB,IAAI,CAACI,MAAM,EAAEG,GAAG,CAAES,KAAK,IAAKA,KAAK,CAACA,KAAK,CAAC,IAAI,CAAC,GAAG,IAAIG,GAAG,CAAC3E,IAAI,CAACE,OAAO,CAAEC,GAAG,IAAKA,GAAG,CAACC,SAAS,CAAC2D,GAAG,CAAEa,CAAC,IAAKA,CAAC,CAACJ,KAAK,CAAC,CAAC,CAAC,CAAC;EACpI,MAAMK,YAAY,GAAG,IAAIN,GAAG,CAACG,SAAS,CAACX,GAAG,CAAC,CAACS,KAAK,EAAEC,KAAK,KAAK,CAACD,KAAK,EAAEC,KAAK,CAAC,CAAC,CAAC;EAC7E,MAAM3B,IAAc,GAAG,EAAE;EACzB,MAAMgC,aAAa,GAAGhE,IAAI,CAACE,GAAG,CAAC,CAAC,EAAEF,IAAI,CAACiE,KAAK,CAAC,CAACb,MAAM,GAAG,EAAE,IAAI,GAAG,CAAC,CAAC;EAElElE,IAAI,CAACgF,OAAO,CAAC,CAAC7E,GAAG,EAAE8E,QAAQ,KAAK;IAC9B,MAAMC,CAAC,GAAG3F,GAAG,GAAG0F,QAAQ,GAAG3F,UAAU;IACrC,IAAI4F,CAAC,GAAG5F,UAAU,GAAG+E,UAAU,GAAG,CAAC,EAAE;IACrC,MAAML,KAAK,GAAGvB,QAAQ,CAACtC,GAAG,CAAC6D,KAAK,EAAEc,aAAa,CAAC;IAChD,MAAMK,SAAS,GAAG,6CAA6ClD,GAAG,CAACkC,QAAQ,GAAG,CAAC,CAAC,QAAQlC,GAAG,CACzFiD,CAAC,GAAG5F,UAAU,GAAG,CACnB,CAAC,kDAAkDL,SAAS,CAAC+E,KAAK,CAAC,SAAS;IAC5ElB,IAAI,CAACsC,IAAI,CAACvC,gBAAgB,CAACsC,SAAS,EAAEhF,GAAG,CAACoC,IAAI,EAAEpC,GAAG,CAAC4C,OAAO,IAAI5C,GAAG,CAAC6D,KAAK,EAAE7D,GAAG,CAAC6D,KAAK,CAAC,CAAC;IAErF,KAAK,MAAM3D,QAAQ,IAAIF,GAAG,CAACC,SAAS,EAAE;MACpC,IAAI,CAACP,MAAM,CAACC,QAAQ,CAACO,QAAQ,CAACC,IAAI,CAAC,IAAI,CAACT,MAAM,CAACC,QAAQ,CAACO,QAAQ,CAACE,EAAE,CAAC,EAAE;MACtE,MAAM8E,YAAY,GAAGvE,IAAI,CAACC,GAAG,CAACV,QAAQ,CAACC,IAAI,EAAED,QAAQ,CAACE,EAAE,CAAC;MACzD,MAAM+E,UAAU,GAAGxE,IAAI,CAACE,GAAG,CAACX,QAAQ,CAACC,IAAI,EAAED,QAAQ,CAACE,EAAE,CAAC;MACvD,IAAI+E,UAAU,GAAG7E,QAAQ,CAAC,CAAC,CAAC,IAAI4E,YAAY,GAAG5E,QAAQ,CAAC,CAAC,CAAC,EAAE;MAC5D,MAAMH,IAAI,GAAGQ,IAAI,CAACE,GAAG,CAACP,QAAQ,CAAC,CAAC,CAAC,EAAE4E,YAAY,CAAC;MAChD,MAAM9E,EAAE,GAAGO,IAAI,CAACC,GAAG,CAACN,QAAQ,CAAC,CAAC,CAAC,EAAE6E,UAAU,CAAC;MAC5C,MAAMC,CAAC,GAAGpG,QAAQ,CAACmB,IAAI,EAAEG,QAAQ,EAAE,CAAC0D,QAAQ,EAAEC,SAAS,CAAC,CAAC;MACzD,MAAMoB,EAAE,GAAGrG,QAAQ,CAACoB,EAAE,EAAEE,QAAQ,EAAE,CAAC0D,QAAQ,EAAEC,SAAS,CAAC,CAAC;MACxD,MAAMqB,KAAK,GAAGnB,WAAW,CAACoB,GAAG,CAACrF,QAAQ,CAACmE,KAAK,CAAC;MAC7C,MAAMmB,UAAU,GAAGF,KAAK,EAAEhB,KAAK,IAAII,YAAY,CAACa,GAAG,CAACrF,QAAQ,CAACmE,KAAK,CAAC,IAAI,CAAC;MACxE,MAAMoB,KAAK,GAAGH,KAAK,EAAEG,KAAK,GAAG,UAAU3G,SAAS,CAACwG,KAAK,CAACG,KAAK,CAAC,GAAG,GAAG,EAAE;MACrE,MAAMC,IAAI,GAAG,8DAA8DF,UAAU,GAAG,CAAC,IAAIC,KAAK,OAAO3D,GAAG,CAC1GsD,CACF,CAAC,QAAQtD,GAAG,CAACiD,CAAC,GAAG,CAAC,CAAC,YAAYjD,GAAG,CAACnB,IAAI,CAACE,GAAG,CAAC,CAAC,EAAEwE,EAAE,GAAGD,CAAC,CAAC,CAAC,aAAajG,UAAU,GAAG,CAAC,YAAY;MAC9F,MAAMwG,UAAU,GAAGL,KAAK,EAAEzB,KAAK,IAAI3D,QAAQ,CAACmE,KAAK;MACjD1B,IAAI,CAACsC,IAAI,CACPvC,gBAAgB,CACdgD,IAAI,EACJxF,QAAQ,CAACkC,IAAI,EACblC,QAAQ,CAAC0C,OAAO,IAAI1C,QAAQ,CAAC2D,KAAK,EAClC,CAAC7D,GAAG,CAAC6D,KAAK,EAAE3D,QAAQ,CAAC2D,KAAK,EAAE8B,UAAU,CAAC,CAAC3C,MAAM,CAACC,OAAO,CAAC,CAACC,IAAI,CAAC,IAAI,CACnE,CACF,CAAC;IACH;EACF,CAAC,CAAC;EAEF,MAAM0C,UAAU,GAAGjF,IAAI,CAACE,GAAG,CAAC,CAAC,EAAEF,IAAI,CAACC,GAAG,CAAC,CAAC,EAAED,IAAI,CAACiE,KAAK,CAAC,CAACX,SAAS,GAAGD,QAAQ,IAAI,GAAG,CAAC,CAAC,CAAC;EACrF,MAAM6B,KAAK,GAAG9G,kBAAkB,CAACuB,QAAQ,CAAC,CAAC,CAAC,EAAEA,QAAQ,CAAC,CAAC,CAAC,EAAErB,QAAQ,CAACqB,QAAQ,CAAC,CAAC,CAAC,GAAGA,QAAQ,CAAC,CAAC,CAAC,EAAEsF,UAAU,CAAC,CAAC,CAACC,KAAK;EACjH,MAAMC,MAAM,GAAGzC,IAAI,CAAC0C,KAAK,EAAED,MAAM,KAAM/D,KAAa,IAAKD,GAAG,CAACC,KAAK,CAAC,CAAC;EACpE,KAAK,MAAMiE,IAAI,IAAIH,KAAK,EAAE;IACxB,IAAIG,IAAI,GAAG1F,QAAQ,CAAC,CAAC,CAAC,IAAI0F,IAAI,GAAG1F,QAAQ,CAAC,CAAC,CAAC,EAAE;IAC9C,MAAM8E,CAAC,GAAGpG,QAAQ,CAACgH,IAAI,EAAE1F,QAAQ,EAAE,CAAC0D,QAAQ,EAAEC,SAAS,CAAC,CAAC;IACzDtB,IAAI,CAACsC,IAAI,CACP,aAAanD,GAAG,CAACsD,CAAC,CAAC,SAAStD,GAAG,CAACsD,CAAC,CAAC,SAAShG,GAAG,SAAS0C,GAAG,CAACoC,UAAU,CAAC,0CAA0C,EAChH,+CAA+CpC,GAAG,CAACsD,CAAC,CAAC,QAAQtD,GAAG,CAACoC,UAAU,GAAG,EAAE,CAAC,0BAA0BpF,SAAS,CAClHgH,MAAM,CAACE,IAAI,CACb,CAAC,SACH,CAAC;EACH;EAEA,IAAI3C,IAAI,CAAC0C,KAAK,EAAElC,KAAK,EAAE;IACrBlB,IAAI,CAACsC,IAAI,CACP,4CAA4CnD,GAAG,CAAC,CAACkC,QAAQ,GAAGC,SAAS,IAAI,CAAC,CAAC,QAAQnC,GAAG,CACpFoC,UAAU,GAAG7E,WAAW,GAAG,CAC7B,CAAC,0BAA0BP,SAAS,CAACuE,IAAI,CAAC0C,KAAK,CAAClC,KAAK,CAAC,SACxD,CAAC;EACH;EAEA,IAAIL,UAAU,EAAE;IACd,IAAI4B,CAAC,GAAGpB,QAAQ;IAChB,MAAMe,CAAC,GAAGxB,MAAM,GAAG,CAAC;IACpB,KAAK,MAAM,CAACe,KAAK,EAAED,KAAK,CAAC,IAAI,CAAChB,IAAI,CAACI,MAAM,IAAI,EAAE,EAAEwC,OAAO,CAAC,CAAC,EAAE;MAC1D,MAAMR,KAAK,GAAGpB,KAAK,CAACoB,KAAK,GAAG,UAAU3G,SAAS,CAACuF,KAAK,CAACoB,KAAK,CAAC,GAAG,GAAG,EAAE;MACpE,MAAM5B,KAAK,GAAGQ,KAAK,CAACR,KAAK,IAAIQ,KAAK,CAACA,KAAK;MACxC1B,IAAI,CAACsC,IAAI,CACP,oCAAoCX,KAAK,GAAG,CAAC,IAAImB,KAAK,OAAO3D,GAAG,CAACsD,CAAC,CAAC,QAAQL,CAAC,GAAG,CAAC,iCAAiC,EACjH,+CAA+CjD,GAAG,CAACsD,CAAC,GAAG,EAAE,CAAC,QAAQL,CAAC,yBAAyBjG,SAAS,CAAC+E,KAAK,CAAC,SAC9G,CAAC;MACDuB,CAAC,IAAI,EAAE,GAAGvB,KAAK,CAACrB,MAAM,GAAG,GAAG;IAC9B;EACF;EAEA,OAAOtD,OAAO,CAAC;IAAEoE,KAAK;IAAEC,MAAM;IAAE2C,SAAS,EAAE7C,IAAI,CAAC6C;EAAU,CAAC,EAAEvD,IAAI,CAACO,IAAI,CAAC,EAAE,CAAC,CAAC;AAC7E,CAAC","ignoreList":[]}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Small safe highlighters for CodeDisplay.
|
|
3
|
+
*
|
|
4
|
+
* These are display-only highlighters: no AST, no runtime parser, no
|
|
5
|
+
* dependency. Every input character is HTML-escaped before being wrapped
|
|
6
|
+
* in token spans, so the returned strings are safe to inject with
|
|
7
|
+
* `innerHTML`.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const KEYWORDS = new Set(["const", "let", "var", "function", "return", "if", "else", "for", "while", "import", "from", "export", "default", "async", "await", "new", "true", "false", "null", "undefined", "as", "type", "interface", "void", "this", "typeof", "in", "of"]);
|
|
11
|
+
export const escapeCodeHtml = s => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
12
|
+
const isIdStart = c => /[A-Za-z_$]/.test(c);
|
|
13
|
+
const isIdCont = c => /[\w$]/.test(c);
|
|
14
|
+
const isDigit = c => /[0-9]/.test(c);
|
|
15
|
+
const wrap = (cls, raw) => `<span class="${cls}">${escapeCodeHtml(raw)}</span>`;
|
|
16
|
+
const isCodeLanguage = language => language === "script" || language === "js" || language === "jsx" || language === "ts" || language === "tsx";
|
|
17
|
+
export const highlightCode = code => {
|
|
18
|
+
let out = "";
|
|
19
|
+
let i = 0;
|
|
20
|
+
const n = code.length;
|
|
21
|
+
while (i < n) {
|
|
22
|
+
const c = code[i];
|
|
23
|
+
if (c === "/" && code[i + 1] === "/") {
|
|
24
|
+
const nl = code.indexOf("\n", i);
|
|
25
|
+
const end = nl === -1 ? n : nl;
|
|
26
|
+
out += wrap("cd-c", code.slice(i, end));
|
|
27
|
+
i = end;
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
if (c === "/" && code[i + 1] === "*") {
|
|
31
|
+
const close = code.indexOf("*/", i + 2);
|
|
32
|
+
const end = close === -1 ? n : close + 2;
|
|
33
|
+
out += wrap("cd-c", code.slice(i, end));
|
|
34
|
+
i = end;
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
if (c === '"' || c === "'" || c === "`") {
|
|
38
|
+
const quote = c;
|
|
39
|
+
let j = i + 1;
|
|
40
|
+
while (j < n) {
|
|
41
|
+
if (code[j] === "\\") {
|
|
42
|
+
j += 2;
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
if (code[j] === quote) {
|
|
46
|
+
j++;
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
j++;
|
|
50
|
+
}
|
|
51
|
+
out += wrap("cd-s", code.slice(i, j));
|
|
52
|
+
i = j;
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
if (isDigit(c)) {
|
|
56
|
+
let j = i;
|
|
57
|
+
while (j < n && (isDigit(code[j]) || code[j] === ".")) j++;
|
|
58
|
+
out += wrap("cd-n", code.slice(i, j));
|
|
59
|
+
i = j;
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
if (isIdStart(c)) {
|
|
63
|
+
let j = i;
|
|
64
|
+
while (j < n && isIdCont(code[j])) j++;
|
|
65
|
+
const word = code.slice(i, j);
|
|
66
|
+
let cls = "";
|
|
67
|
+
if (KEYWORDS.has(word)) cls = "cd-k";else if (/^[A-Z]/.test(word)) cls = "cd-p";else {
|
|
68
|
+
let k = j;
|
|
69
|
+
while (k < n && code[k] === " ") k++;
|
|
70
|
+
const next = code[k];
|
|
71
|
+
const prev = i > 0 ? code[i - 1] : "";
|
|
72
|
+
const assignment = next === "=" && code[k + 1] !== "=" && code[k + 1] !== ">";
|
|
73
|
+
const objectKey = next === ":";
|
|
74
|
+
const functionCall = next === "(";
|
|
75
|
+
const property = prev === ".";
|
|
76
|
+
if (assignment || objectKey) cls = "cd-a";else if (functionCall || property) cls = "cd-f";
|
|
77
|
+
}
|
|
78
|
+
out += cls ? wrap(cls, word) : escapeCodeHtml(word);
|
|
79
|
+
i = j;
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
out += escapeCodeHtml(c);
|
|
83
|
+
i++;
|
|
84
|
+
}
|
|
85
|
+
return out;
|
|
86
|
+
};
|
|
87
|
+
const highlightMarkdownLine = line => {
|
|
88
|
+
const escaped = escapeCodeHtml(line);
|
|
89
|
+
const heading = /^(#{1,6})(\s.*)$/.exec(escaped);
|
|
90
|
+
if (heading) return `<span class="cd-md-syntax">${heading[1]}</span>${highlightMarkdownInline(heading[2] ?? "")}`;
|
|
91
|
+
const ref = /^(@[A-Za-z][\w-]*)$/.exec(escaped);
|
|
92
|
+
if (ref) return `<span class="cd-md-ref">${ref[1]}</span>`;
|
|
93
|
+
const directive = /^(\s*:::)([A-Za-z][\w-]*)?(.*)$/.exec(escaped);
|
|
94
|
+
if (directive) {
|
|
95
|
+
const name = directive[2] ? `<span class="cd-md-directive">${directive[2]}</span>` : "";
|
|
96
|
+
return `${directive[1] ? `<span class="cd-md-syntax">${directive[1]}</span>` : ""}${name}${highlightMarkdownInline(directive[3] ?? "")}`;
|
|
97
|
+
}
|
|
98
|
+
const fence = /^(```)(.*)$/.exec(escaped);
|
|
99
|
+
if (fence) {
|
|
100
|
+
const language = fence[2] ? `<span class="cd-md-ref">${fence[2]}</span>` : "";
|
|
101
|
+
return `<span class="cd-md-syntax">${fence[1]}</span>${language}`;
|
|
102
|
+
}
|
|
103
|
+
const table = /^(\s*\|)(.*)(\|\s*)$/.exec(escaped);
|
|
104
|
+
if (table) return `<span class="cd-md-syntax">${table[1]}</span>${table[2]}<span class="cd-md-syntax">${table[3]}</span>`;
|
|
105
|
+
const task = /^(\s*(?:[-*+]|\d+\.)\s+)(\[[ xX]\])(\s+.*)$/.exec(escaped);
|
|
106
|
+
if (task) {
|
|
107
|
+
return `<span class="cd-md-syntax">${task[1]}</span><span class="cd-md-checkbox">${task[2]}</span>${highlightMarkdownInline(task[3] ?? "")}`;
|
|
108
|
+
}
|
|
109
|
+
const list = /^(\s*(?:[-*+]|\d+\.)\s+)(.*)$/.exec(escaped);
|
|
110
|
+
if (list) return `<span class="cd-md-syntax">${list[1]}</span>${highlightMarkdownInline(list[2] ?? "")}`;
|
|
111
|
+
return highlightMarkdownInline(escaped);
|
|
112
|
+
};
|
|
113
|
+
const highlightMarkdownInline = escaped => escaped.replace(/(`)([^`\n]+?)(`)/g, '<span class="cd-md-syntax">$1</span><span class="cd-md-code">$2</span><span class="cd-md-syntax">$3</span>').replace(/(\*\*)([^*\n]+?)(\*\*)/g, '<span class="cd-md-syntax">$1</span>$2<span class="cd-md-syntax">$3</span>').replace(/(\[[^\]\n]+?\])(\([^)]+\))/g, '<span class="cd-md-link">$1</span><span class="cd-md-syntax">$2</span>').replace(/(^|\s)(@[A-Za-z][\w-]*)/g, '$1<span class="cd-md-ref">$2</span>').replace(/(#[A-Za-z][\w/-]*)/g, '<span class="cd-md-tag">$1</span>').replace(/(=[A-Z][A-Z0-9_]*\([^)\n]*\))/g, '<span class="cd-md-formula">$1</span>');
|
|
114
|
+
export const highlightMarkdownDisplay = code => code.split("\n").map(highlightMarkdownLine).join("\n");
|
|
115
|
+
export const highlightCodeDisplayLines = (code, language = "text") => {
|
|
116
|
+
const lines = code.split("\n");
|
|
117
|
+
if (language === "text") return lines.map(line => escapeCodeHtml(line || " "));
|
|
118
|
+
if (language === "markdown" || language === "md") {
|
|
119
|
+
let fencedLanguage;
|
|
120
|
+
return lines.map(line => {
|
|
121
|
+
const fence = /^(```)(\w+)?(.*)$/.exec(line);
|
|
122
|
+
if (fence) {
|
|
123
|
+
const highlightedFence = highlightMarkdownLine(line);
|
|
124
|
+
fencedLanguage = fencedLanguage ? undefined : fence[2];
|
|
125
|
+
return highlightedFence;
|
|
126
|
+
}
|
|
127
|
+
return isCodeLanguage(fencedLanguage) ? highlightCode(line || " ") : highlightMarkdownLine(line || " ");
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
if (lines.length >= 2 && /^```\w+/.test(lines[0] ?? "") && /^```\s*$/.test(lines[lines.length - 1] ?? "")) {
|
|
131
|
+
return lines.map((line, index) => {
|
|
132
|
+
if (index === 0 || index === lines.length - 1) return highlightMarkdownLine(line || " ");
|
|
133
|
+
return highlightCode(line || " ");
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
return lines.map(line => highlightCode(line || " "));
|
|
137
|
+
};
|
|
138
|
+
export const highlightCodeDisplay = (code, language = "text") => {
|
|
139
|
+
if (code.includes("\n")) return highlightCodeDisplayLines(code, language).join("\n");
|
|
140
|
+
if (language === "markdown" || language === "md") return highlightMarkdownDisplay(code);
|
|
141
|
+
if (language === "text") return escapeCodeHtml(code);
|
|
142
|
+
return highlightCode(code);
|
|
143
|
+
};
|
|
144
|
+
//# sourceMappingURL=code-highlight.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["KEYWORDS","Set","escapeCodeHtml","s","replace","isIdStart","c","test","isIdCont","isDigit","wrap","cls","raw","isCodeLanguage","language","highlightCode","code","out","i","n","length","nl","indexOf","end","slice","close","quote","j","word","has","k","next","prev","assignment","objectKey","functionCall","property","highlightMarkdownLine","line","escaped","heading","exec","highlightMarkdownInline","ref","directive","name","fence","table","task","list","highlightMarkdownDisplay","split","map","join","highlightCodeDisplayLines","lines","fencedLanguage","highlightedFence","undefined","index","highlightCodeDisplay","includes"],"sources":["content/code-highlight.ts"],"sourcesContent":["/**\n * Small safe highlighters for CodeDisplay.\n *\n * These are display-only highlighters: no AST, no runtime parser, no\n * dependency. Every input character is HTML-escaped before being wrapped\n * in token spans, so the returned strings are safe to inject with\n * `innerHTML`.\n */\n\nconst KEYWORDS = new Set([\n \"const\",\n \"let\",\n \"var\",\n \"function\",\n \"return\",\n \"if\",\n \"else\",\n \"for\",\n \"while\",\n \"import\",\n \"from\",\n \"export\",\n \"default\",\n \"async\",\n \"await\",\n \"new\",\n \"true\",\n \"false\",\n \"null\",\n \"undefined\",\n \"as\",\n \"type\",\n \"interface\",\n \"void\",\n \"this\",\n \"typeof\",\n \"in\",\n \"of\",\n]);\n\nexport type CodeDisplayLanguage = \"ts\" | \"tsx\" | \"js\" | \"jsx\" | \"script\" | \"markdown\" | \"md\" | \"text\";\n\nexport const escapeCodeHtml = (s: string): string => s.replace(/&/g, \"&\").replace(/</g, \"<\").replace(/>/g, \">\");\n\nconst isIdStart = (c: string): boolean => /[A-Za-z_$]/.test(c);\nconst isIdCont = (c: string): boolean => /[\\w$]/.test(c);\nconst isDigit = (c: string): boolean => /[0-9]/.test(c);\nconst wrap = (cls: string, raw: string): string => `<span class=\"${cls}\">${escapeCodeHtml(raw)}</span>`;\nconst isCodeLanguage = (language: string | undefined): boolean =>\n language === \"script\" || language === \"js\" || language === \"jsx\" || language === \"ts\" || language === \"tsx\";\n\nexport const highlightCode = (code: string): string => {\n let out = \"\";\n let i = 0;\n const n = code.length;\n\n while (i < n) {\n const c = code[i]!;\n\n if (c === \"/\" && code[i + 1] === \"/\") {\n const nl = code.indexOf(\"\\n\", i);\n const end = nl === -1 ? n : nl;\n out += wrap(\"cd-c\", code.slice(i, end));\n i = end;\n continue;\n }\n\n if (c === \"/\" && code[i + 1] === \"*\") {\n const close = code.indexOf(\"*/\", i + 2);\n const end = close === -1 ? n : close + 2;\n out += wrap(\"cd-c\", code.slice(i, end));\n i = end;\n continue;\n }\n\n if (c === '\"' || c === \"'\" || c === \"`\") {\n const quote = c;\n let j = i + 1;\n while (j < n) {\n if (code[j] === \"\\\\\") {\n j += 2;\n continue;\n }\n if (code[j] === quote) {\n j++;\n break;\n }\n j++;\n }\n out += wrap(\"cd-s\", code.slice(i, j));\n i = j;\n continue;\n }\n\n if (isDigit(c)) {\n let j = i;\n while (j < n && (isDigit(code[j]!) || code[j] === \".\")) j++;\n out += wrap(\"cd-n\", code.slice(i, j));\n i = j;\n continue;\n }\n\n if (isIdStart(c)) {\n let j = i;\n while (j < n && isIdCont(code[j]!)) j++;\n const word = code.slice(i, j);\n let cls = \"\";\n if (KEYWORDS.has(word)) cls = \"cd-k\";\n else if (/^[A-Z]/.test(word)) cls = \"cd-p\";\n else {\n let k = j;\n while (k < n && code[k] === \" \") k++;\n const next = code[k];\n const prev = i > 0 ? code[i - 1] : \"\";\n const assignment = next === \"=\" && code[k + 1] !== \"=\" && code[k + 1] !== \">\";\n const objectKey = next === \":\";\n const functionCall = next === \"(\";\n const property = prev === \".\";\n if (assignment || objectKey) cls = \"cd-a\";\n else if (functionCall || property) cls = \"cd-f\";\n }\n out += cls ? wrap(cls, word) : escapeCodeHtml(word);\n i = j;\n continue;\n }\n\n out += escapeCodeHtml(c);\n i++;\n }\n\n return out;\n};\n\nconst highlightMarkdownLine = (line: string): string => {\n const escaped = escapeCodeHtml(line);\n\n const heading = /^(#{1,6})(\\s.*)$/.exec(escaped);\n if (heading) return `<span class=\"cd-md-syntax\">${heading[1]}</span>${highlightMarkdownInline(heading[2] ?? \"\")}`;\n\n const ref = /^(@[A-Za-z][\\w-]*)$/.exec(escaped);\n if (ref) return `<span class=\"cd-md-ref\">${ref[1]}</span>`;\n\n const directive = /^(\\s*:::)([A-Za-z][\\w-]*)?(.*)$/.exec(escaped);\n if (directive) {\n const name = directive[2] ? `<span class=\"cd-md-directive\">${directive[2]}</span>` : \"\";\n return `${directive[1] ? `<span class=\"cd-md-syntax\">${directive[1]}</span>` : \"\"}${name}${highlightMarkdownInline(directive[3] ?? \"\")}`;\n }\n\n const fence = /^(```)(.*)$/.exec(escaped);\n if (fence) {\n const language = fence[2] ? `<span class=\"cd-md-ref\">${fence[2]}</span>` : \"\";\n return `<span class=\"cd-md-syntax\">${fence[1]}</span>${language}`;\n }\n\n const table = /^(\\s*\\|)(.*)(\\|\\s*)$/.exec(escaped);\n if (table) return `<span class=\"cd-md-syntax\">${table[1]}</span>${table[2]}<span class=\"cd-md-syntax\">${table[3]}</span>`;\n\n const task = /^(\\s*(?:[-*+]|\\d+\\.)\\s+)(\\[[ xX]\\])(\\s+.*)$/.exec(escaped);\n if (task) {\n return `<span class=\"cd-md-syntax\">${task[1]}</span><span class=\"cd-md-checkbox\">${task[2]}</span>${highlightMarkdownInline(task[3] ?? \"\")}`;\n }\n\n const list = /^(\\s*(?:[-*+]|\\d+\\.)\\s+)(.*)$/.exec(escaped);\n if (list) return `<span class=\"cd-md-syntax\">${list[1]}</span>${highlightMarkdownInline(list[2] ?? \"\")}`;\n\n return highlightMarkdownInline(escaped);\n};\n\nconst highlightMarkdownInline = (escaped: string): string =>\n escaped\n .replace(\n /(`)([^`\\n]+?)(`)/g,\n '<span class=\"cd-md-syntax\">$1</span><span class=\"cd-md-code\">$2</span><span class=\"cd-md-syntax\">$3</span>',\n )\n .replace(/(\\*\\*)([^*\\n]+?)(\\*\\*)/g, '<span class=\"cd-md-syntax\">$1</span>$2<span class=\"cd-md-syntax\">$3</span>')\n .replace(/(\\[[^\\]\\n]+?\\])(\\([^)]+\\))/g, '<span class=\"cd-md-link\">$1</span><span class=\"cd-md-syntax\">$2</span>')\n .replace(/(^|\\s)(@[A-Za-z][\\w-]*)/g, '$1<span class=\"cd-md-ref\">$2</span>')\n .replace(/(#[A-Za-z][\\w/-]*)/g, '<span class=\"cd-md-tag\">$1</span>')\n .replace(/(=[A-Z][A-Z0-9_]*\\([^)\\n]*\\))/g, '<span class=\"cd-md-formula\">$1</span>');\n\nexport const highlightMarkdownDisplay = (code: string): string => code.split(\"\\n\").map(highlightMarkdownLine).join(\"\\n\");\n\nexport const highlightCodeDisplayLines = (code: string, language: CodeDisplayLanguage = \"text\"): string[] => {\n const lines = code.split(\"\\n\");\n\n if (language === \"text\") return lines.map((line) => escapeCodeHtml(line || \" \"));\n\n if (language === \"markdown\" || language === \"md\") {\n let fencedLanguage: string | undefined;\n return lines.map((line) => {\n const fence = /^(```)(\\w+)?(.*)$/.exec(line);\n if (fence) {\n const highlightedFence = highlightMarkdownLine(line);\n fencedLanguage = fencedLanguage ? undefined : fence[2];\n return highlightedFence;\n }\n return isCodeLanguage(fencedLanguage) ? highlightCode(line || \" \") : highlightMarkdownLine(line || \" \");\n });\n }\n\n if (lines.length >= 2 && /^```\\w+/.test(lines[0] ?? \"\") && /^```\\s*$/.test(lines[lines.length - 1] ?? \"\")) {\n return lines.map((line, index) => {\n if (index === 0 || index === lines.length - 1) return highlightMarkdownLine(line || \" \");\n return highlightCode(line || \" \");\n });\n }\n\n return lines.map((line) => highlightCode(line || \" \"));\n};\n\nexport const highlightCodeDisplay = (code: string, language: CodeDisplayLanguage = \"text\"): string => {\n if (code.includes(\"\\n\")) return highlightCodeDisplayLines(code, language).join(\"\\n\");\n if (language === \"markdown\" || language === \"md\") return highlightMarkdownDisplay(code);\n if (language === \"text\") return escapeCodeHtml(code);\n return highlightCode(code);\n};\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tree shaping for FileTree — flat paths in, sorted nodes out.
|
|
3
|
+
*
|
|
4
|
+
* Kept beside the component rather than inside it because it is pure: no JSX,
|
|
5
|
+
* no reactivity, nothing that needs a DOM. That is also what makes it testable
|
|
6
|
+
* — a test importing the .tsx pulls the whole component through Bun's JSX
|
|
7
|
+
* transform, which resolves against the root tsconfig and lands on the React
|
|
8
|
+
* runtime. Same reason `file-view-preview.ts` sits next to FileView.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/** Containing directory of a path; "/" for top-level entries. */
|
|
12
|
+
export const parentOf = path => {
|
|
13
|
+
const index = path.lastIndexOf("/");
|
|
14
|
+
return index <= 0 ? "/" : path.slice(0, index);
|
|
15
|
+
};
|
|
16
|
+
const nameOf = path => path.slice(path.lastIndexOf("/") + 1) || path;
|
|
17
|
+
const nodesByPath = nodes => {
|
|
18
|
+
const result = new Map();
|
|
19
|
+
const visit = node => {
|
|
20
|
+
result.set(node.entry.path, node);
|
|
21
|
+
for (const child of node.children) visit(child);
|
|
22
|
+
};
|
|
23
|
+
for (const node of nodes) visit(node);
|
|
24
|
+
return result;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Flat paths → sorted tree (folders first, then files, both alphabetical).
|
|
29
|
+
*
|
|
30
|
+
* Passing the previous tree preserves object identity by path while updating
|
|
31
|
+
* the cached node in place. Solid's keyed `<For>` can then keep rows, rename
|
|
32
|
+
* inputs, and focus alive even when a refetch changes metadata.
|
|
33
|
+
*/
|
|
34
|
+
export const buildTree = (entries, previous = []) => {
|
|
35
|
+
const byPath = new Map();
|
|
36
|
+
const previousByPath = nodesByPath(previous);
|
|
37
|
+
const folders = new Set();
|
|
38
|
+
const files = new Set(entries.filter(entry => entry.kind !== "folder").map(entry => entry.path));
|
|
39
|
+
for (const entry of entries) {
|
|
40
|
+
for (let dir = parentOf(entry.path); dir !== "/"; dir = parentOf(dir)) {
|
|
41
|
+
if (files.has(dir)) {
|
|
42
|
+
throw new Error(`FileTree entry conflict: "${dir}" is a file and cannot contain "${entry.path}".`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
for (const entry of entries) {
|
|
47
|
+
byPath.set(entry.path, entry);
|
|
48
|
+
if (entry.kind === "folder") folders.add(entry.path);
|
|
49
|
+
// Register all ancestor folders of every entry.
|
|
50
|
+
for (let dir = parentOf(entry.path); dir !== "/"; dir = parentOf(dir)) folders.add(dir);
|
|
51
|
+
}
|
|
52
|
+
const childrenByParent = new Map();
|
|
53
|
+
for (const path of new Set([...byPath.keys(), ...folders])) {
|
|
54
|
+
if (path === "/") continue;
|
|
55
|
+
const parent = parentOf(path);
|
|
56
|
+
const children = childrenByParent.get(parent);
|
|
57
|
+
if (children) children.push(path);else childrenByParent.set(parent, [path]);
|
|
58
|
+
}
|
|
59
|
+
const nodeFor = (path, depth) => {
|
|
60
|
+
const entry = byPath.get(path) ?? {
|
|
61
|
+
path,
|
|
62
|
+
kind: "folder"
|
|
63
|
+
};
|
|
64
|
+
const isFolder = folders.has(path);
|
|
65
|
+
const old = previousByPath.get(path);
|
|
66
|
+
if (old) {
|
|
67
|
+
old.entry = entry;
|
|
68
|
+
old.name = nameOf(path);
|
|
69
|
+
old.depth = depth;
|
|
70
|
+
old.isFolder = isFolder;
|
|
71
|
+
return old;
|
|
72
|
+
}
|
|
73
|
+
return {
|
|
74
|
+
entry,
|
|
75
|
+
name: nameOf(path),
|
|
76
|
+
depth,
|
|
77
|
+
isFolder,
|
|
78
|
+
children: []
|
|
79
|
+
};
|
|
80
|
+
};
|
|
81
|
+
const childrenOf = (dir, depth) => {
|
|
82
|
+
const nodes = (childrenByParent.get(dir) ?? []).map(path => {
|
|
83
|
+
const node = nodeFor(path, depth);
|
|
84
|
+
if (node.isFolder) node.children = childrenOf(node.entry.path, depth + 1);
|
|
85
|
+
return node;
|
|
86
|
+
});
|
|
87
|
+
return nodes.sort((a, b) => a.isFolder === b.isFolder ? a.name.localeCompare(b.name) : a.isFolder ? -1 : 1);
|
|
88
|
+
};
|
|
89
|
+
return childrenOf("/", 0);
|
|
90
|
+
};
|
|
91
|
+
export const flattenVisible = (nodes, expanded) => nodes.flatMap(node => [node, ...(node.isFolder && expanded.has(node.entry.path) ? flattenVisible(node.children, expanded) : [])]);
|
|
92
|
+
export const allFolderPaths = nodes => nodes.flatMap(node => node.isFolder ? [node.entry.path, ...allFolderPaths(node.children)] : []);
|
|
93
|
+
//# sourceMappingURL=file-tree.js.map
|
|
@@ -0,0 +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":"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","ignoreList":[]}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
const MEBIBYTE = 1024 * 1024;
|
|
2
|
+
const maxPreviewBytes = {
|
|
3
|
+
markdown: 2 * MEBIBYTE,
|
|
4
|
+
image: 25 * MEBIBYTE,
|
|
5
|
+
pdf: 50 * MEBIBYTE,
|
|
6
|
+
json: 2 * MEBIBYTE,
|
|
7
|
+
"delimited-text": 2 * MEBIBYTE,
|
|
8
|
+
audio: 50 * MEBIBYTE,
|
|
9
|
+
video: 50 * MEBIBYTE,
|
|
10
|
+
text: 2 * MEBIBYTE
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
// SVG remains inert because FileView renders every image through <img>; never inject its markup into the DOM.
|
|
14
|
+
const imageMediaTypes = new Set(["image/avif", "image/bmp", "image/gif", "image/jpeg", "image/png", "image/svg+xml", "image/webp", "image/x-icon"]);
|
|
15
|
+
const audioMediaTypes = new Set(["audio/aac", "audio/flac", "audio/mp4", "audio/mpeg", "audio/ogg", "audio/wav", "audio/webm", "audio/x-wav"]);
|
|
16
|
+
const videoMediaTypes = new Set(["video/mp4", "video/ogg", "video/webm"]);
|
|
17
|
+
const markdownExtensions = new Set(["md", "markdown"]);
|
|
18
|
+
const imageExtensions = new Set(["avif", "bmp", "gif", "ico", "jpeg", "jpg", "png", "svg", "webp"]);
|
|
19
|
+
const audioExtensions = new Set(["aac", "flac", "m4a", "mp3", "oga", "ogg", "wav", "weba"]);
|
|
20
|
+
const videoExtensions = new Set(["m4v", "mp4", "ogv", "webm"]);
|
|
21
|
+
const textExtensions = new Set(["c", "conf", "cpp", "css", "env", "go", "h", "html", "ini", "java", "js", "jsx", "log", "mjs", "php", "py", "rb", "rs", "sh", "sql", "toml", "ts", "tsx", "txt", "xml", "yaml", "yml"]);
|
|
22
|
+
export const fileViewExtension = path => {
|
|
23
|
+
const cleanPath = path.split(/[?#]/, 1)[0] ?? path;
|
|
24
|
+
const name = cleanPath.slice(cleanPath.lastIndexOf("/") + 1);
|
|
25
|
+
const dot = name.lastIndexOf(".");
|
|
26
|
+
return dot > 0 ? name.slice(dot + 1).toLowerCase() : "";
|
|
27
|
+
};
|
|
28
|
+
const normalizedMediaType = mediaType => mediaType?.split(";", 1)[0]?.trim().toLowerCase() ?? "";
|
|
29
|
+
const previewKindByType = file => {
|
|
30
|
+
const extension = fileViewExtension(file.path);
|
|
31
|
+
const mediaType = normalizedMediaType(file.mediaType);
|
|
32
|
+
if (mediaType === "text/markdown" || markdownExtensions.has(extension)) return "markdown";
|
|
33
|
+
if (mediaType === "application/json" || mediaType.endsWith("+json") || extension === "json") return "json";
|
|
34
|
+
if (mediaType === "text/csv" || mediaType === "text/tab-separated-values" || extension === "csv" || extension === "tsv") {
|
|
35
|
+
return "delimited-text";
|
|
36
|
+
}
|
|
37
|
+
if (mediaType === "application/pdf" || extension === "pdf") return "pdf";
|
|
38
|
+
if (imageMediaTypes.has(mediaType) || imageExtensions.has(extension)) return "image";
|
|
39
|
+
if (audioMediaTypes.has(mediaType) || audioExtensions.has(extension)) return "audio";
|
|
40
|
+
if (videoMediaTypes.has(mediaType) || videoExtensions.has(extension)) return "video";
|
|
41
|
+
if (mediaType.startsWith("text/") || mediaType === "application/javascript" || mediaType === "application/sql" || mediaType === "application/xml" || textExtensions.has(extension)) {
|
|
42
|
+
return "text";
|
|
43
|
+
}
|
|
44
|
+
return null;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Returns the built-in preview kind when FileView can render the file within
|
|
49
|
+
* its bounded client-side limits. Custom renderers remain registry-driven.
|
|
50
|
+
*/
|
|
51
|
+
export const getFileViewPreviewKind = file => {
|
|
52
|
+
const kind = previewKindByType(file);
|
|
53
|
+
if (!kind) return null;
|
|
54
|
+
if (file.size !== undefined && (!Number.isFinite(file.size) || file.size < 0 || file.size > maxPreviewBytes[kind])) {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
return kind;
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
/** Use this to expose preview actions only for files FileView can render. */
|
|
61
|
+
export const canPreviewFile = file => getFileViewPreviewKind(file) !== null;
|
|
62
|
+
export const parseDelimitedText = (input, delimiter, limits = {}) => {
|
|
63
|
+
const maxRows = Math.max(1, limits.rows ?? 201);
|
|
64
|
+
const maxColumns = Math.max(1, limits.columns ?? 50);
|
|
65
|
+
const rows = [];
|
|
66
|
+
let row = [];
|
|
67
|
+
let field = "";
|
|
68
|
+
let quoted = false;
|
|
69
|
+
let truncated = false;
|
|
70
|
+
const pushField = () => {
|
|
71
|
+
if (row.length < maxColumns) row.push(field);else truncated = true;
|
|
72
|
+
field = "";
|
|
73
|
+
};
|
|
74
|
+
const pushRow = () => {
|
|
75
|
+
if (rows.length < maxRows) rows.push(row);else truncated = true;
|
|
76
|
+
row = [];
|
|
77
|
+
};
|
|
78
|
+
for (let index = 0; index < input.length; index += 1) {
|
|
79
|
+
const character = input[index];
|
|
80
|
+
if (quoted) {
|
|
81
|
+
if (character === '"' && input[index + 1] === '"') {
|
|
82
|
+
field += '"';
|
|
83
|
+
index += 1;
|
|
84
|
+
} else if (character === '"') {
|
|
85
|
+
quoted = false;
|
|
86
|
+
} else {
|
|
87
|
+
field += character;
|
|
88
|
+
}
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
if (character === '"' && field.length === 0) quoted = true;else if (character === delimiter) pushField();else if (character === "\n" || character === "\r") {
|
|
92
|
+
pushField();
|
|
93
|
+
pushRow();
|
|
94
|
+
if (character === "\r" && input[index + 1] === "\n") index += 1;
|
|
95
|
+
if (rows.length >= maxRows && index < input.length - 1) {
|
|
96
|
+
truncated = true;
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
99
|
+
} else {
|
|
100
|
+
field += character;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
if (field.length > 0 || row.length > 0) {
|
|
104
|
+
pushField();
|
|
105
|
+
pushRow();
|
|
106
|
+
}
|
|
107
|
+
return {
|
|
108
|
+
rows,
|
|
109
|
+
truncated
|
|
110
|
+
};
|
|
111
|
+
};
|
|
112
|
+
//# sourceMappingURL=file-view-preview.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["MEBIBYTE","maxPreviewBytes","markdown","image","pdf","json","audio","video","text","imageMediaTypes","Set","audioMediaTypes","videoMediaTypes","markdownExtensions","imageExtensions","audioExtensions","videoExtensions","textExtensions","fileViewExtension","path","cleanPath","split","name","slice","lastIndexOf","dot","toLowerCase","normalizedMediaType","mediaType","trim","previewKindByType","file","extension","has","endsWith","startsWith","getFileViewPreviewKind","kind","size","undefined","Number","isFinite","canPreviewFile","parseDelimitedText","input","delimiter","limits","maxRows","Math","max","rows","maxColumns","columns","row","field","quoted","truncated","pushField","length","push","pushRow","index","character"],"sources":["content/file-view-preview.ts"],"sourcesContent":["export type FileViewFile = {\n path: string;\n mediaType?: string;\n size?: number;\n};\n\nexport type FileViewPreviewKind = \"markdown\" | \"image\" | \"pdf\" | \"json\" | \"delimited-text\" | \"audio\" | \"video\" | \"text\";\n\nconst MEBIBYTE = 1024 * 1024;\n\nconst maxPreviewBytes: Record<FileViewPreviewKind, number> = {\n markdown: 2 * MEBIBYTE,\n image: 25 * MEBIBYTE,\n pdf: 50 * MEBIBYTE,\n json: 2 * MEBIBYTE,\n \"delimited-text\": 2 * MEBIBYTE,\n audio: 50 * MEBIBYTE,\n video: 50 * MEBIBYTE,\n text: 2 * MEBIBYTE,\n};\n\n// SVG remains inert because FileView renders every image through <img>; never inject its markup into the DOM.\nconst imageMediaTypes = new Set([\n \"image/avif\",\n \"image/bmp\",\n \"image/gif\",\n \"image/jpeg\",\n \"image/png\",\n \"image/svg+xml\",\n \"image/webp\",\n \"image/x-icon\",\n]);\nconst audioMediaTypes = new Set([\n \"audio/aac\",\n \"audio/flac\",\n \"audio/mp4\",\n \"audio/mpeg\",\n \"audio/ogg\",\n \"audio/wav\",\n \"audio/webm\",\n \"audio/x-wav\",\n]);\nconst videoMediaTypes = new Set([\"video/mp4\", \"video/ogg\", \"video/webm\"]);\n\nconst markdownExtensions = new Set([\"md\", \"markdown\"]);\nconst imageExtensions = new Set([\"avif\", \"bmp\", \"gif\", \"ico\", \"jpeg\", \"jpg\", \"png\", \"svg\", \"webp\"]);\nconst audioExtensions = new Set([\"aac\", \"flac\", \"m4a\", \"mp3\", \"oga\", \"ogg\", \"wav\", \"weba\"]);\nconst videoExtensions = new Set([\"m4v\", \"mp4\", \"ogv\", \"webm\"]);\nconst textExtensions = new Set([\n \"c\",\n \"conf\",\n \"cpp\",\n \"css\",\n \"env\",\n \"go\",\n \"h\",\n \"html\",\n \"ini\",\n \"java\",\n \"js\",\n \"jsx\",\n \"log\",\n \"mjs\",\n \"php\",\n \"py\",\n \"rb\",\n \"rs\",\n \"sh\",\n \"sql\",\n \"toml\",\n \"ts\",\n \"tsx\",\n \"txt\",\n \"xml\",\n \"yaml\",\n \"yml\",\n]);\n\nexport const fileViewExtension = (path: string): string => {\n const cleanPath = path.split(/[?#]/, 1)[0] ?? path;\n const name = cleanPath.slice(cleanPath.lastIndexOf(\"/\") + 1);\n const dot = name.lastIndexOf(\".\");\n return dot > 0 ? name.slice(dot + 1).toLowerCase() : \"\";\n};\n\nconst normalizedMediaType = (mediaType?: string): string => mediaType?.split(\";\", 1)[0]?.trim().toLowerCase() ?? \"\";\n\nconst previewKindByType = (file: FileViewFile): FileViewPreviewKind | null => {\n const extension = fileViewExtension(file.path);\n const mediaType = normalizedMediaType(file.mediaType);\n\n if (mediaType === \"text/markdown\" || markdownExtensions.has(extension)) return \"markdown\";\n if (mediaType === \"application/json\" || mediaType.endsWith(\"+json\") || extension === \"json\") return \"json\";\n if (mediaType === \"text/csv\" || mediaType === \"text/tab-separated-values\" || extension === \"csv\" || extension === \"tsv\") {\n return \"delimited-text\";\n }\n if (mediaType === \"application/pdf\" || extension === \"pdf\") return \"pdf\";\n if (imageMediaTypes.has(mediaType) || imageExtensions.has(extension)) return \"image\";\n if (audioMediaTypes.has(mediaType) || audioExtensions.has(extension)) return \"audio\";\n if (videoMediaTypes.has(mediaType) || videoExtensions.has(extension)) return \"video\";\n if (\n mediaType.startsWith(\"text/\") ||\n mediaType === \"application/javascript\" ||\n mediaType === \"application/sql\" ||\n mediaType === \"application/xml\" ||\n textExtensions.has(extension)\n ) {\n return \"text\";\n }\n return null;\n};\n\n/**\n * Returns the built-in preview kind when FileView can render the file within\n * its bounded client-side limits. Custom renderers remain registry-driven.\n */\nexport const getFileViewPreviewKind = (file: FileViewFile): FileViewPreviewKind | null => {\n const kind = previewKindByType(file);\n if (!kind) return null;\n if (file.size !== undefined && (!Number.isFinite(file.size) || file.size < 0 || file.size > maxPreviewBytes[kind])) {\n return null;\n }\n return kind;\n};\n\n/** Use this to expose preview actions only for files FileView can render. */\nexport const canPreviewFile = (file: FileViewFile): boolean => getFileViewPreviewKind(file) !== null;\n\nexport type DelimitedTextPreview = {\n rows: string[][];\n truncated: boolean;\n};\n\nexport const parseDelimitedText = (\n input: string,\n delimiter: \",\" | \"\\t\",\n limits: { rows?: number; columns?: number } = {},\n): DelimitedTextPreview => {\n const maxRows = Math.max(1, limits.rows ?? 201);\n const maxColumns = Math.max(1, limits.columns ?? 50);\n const rows: string[][] = [];\n let row: string[] = [];\n let field = \"\";\n let quoted = false;\n let truncated = false;\n\n const pushField = () => {\n if (row.length < maxColumns) row.push(field);\n else truncated = true;\n field = \"\";\n };\n const pushRow = () => {\n if (rows.length < maxRows) rows.push(row);\n else truncated = true;\n row = [];\n };\n\n for (let index = 0; index < input.length; index += 1) {\n const character = input[index]!;\n if (quoted) {\n if (character === '\"' && input[index + 1] === '\"') {\n field += '\"';\n index += 1;\n } else if (character === '\"') {\n quoted = false;\n } else {\n field += character;\n }\n continue;\n }\n\n if (character === '\"' && field.length === 0) quoted = true;\n else if (character === delimiter) pushField();\n else if (character === \"\\n\" || character === \"\\r\") {\n pushField();\n pushRow();\n if (character === \"\\r\" && input[index + 1] === \"\\n\") index += 1;\n if (rows.length >= maxRows && index < input.length - 1) {\n truncated = true;\n break;\n }\n } else {\n field += character;\n }\n }\n\n if (field.length > 0 || row.length > 0) {\n pushField();\n pushRow();\n }\n\n return { rows, truncated };\n};\n"],"mappings":"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","ignoreList":[]}
|