@keboola/design 10.1.0 → 11.0.1
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/AGENTS.md +2 -0
- package/dist/AIKit-Dre37SJr.js +1320 -0
- package/dist/AIKit-Dre37SJr.js.map +1 -0
- package/dist/Alert-DfZq9kGe.js +133 -0
- package/dist/Alert-DfZq9kGe.js.map +1 -0
- package/dist/AlertModal-BUC4Es8o.js +222 -0
- package/dist/AlertModal-BUC4Es8o.js.map +1 -0
- package/dist/AppShell-B5GQN6Zs.js +143 -0
- package/dist/AppShell-B5GQN6Zs.js.map +1 -0
- package/dist/AutoSaveTextarea-BeuWuszr.js +58 -0
- package/dist/AutoSaveTextarea-BeuWuszr.js.map +1 -0
- package/dist/Badge-Ch26CXoP.js +195 -0
- package/dist/Badge-Ch26CXoP.js.map +1 -0
- package/dist/BrandEditor-B8o9zdZO.js +903 -0
- package/dist/BrandEditor-B8o9zdZO.js.map +1 -0
- package/dist/BrandLogo-CJkRd0F8.js +46 -0
- package/dist/BrandLogo-CJkRd0F8.js.map +1 -0
- package/dist/Breadcrumb-DJp7WwSv.js +330 -0
- package/dist/Breadcrumb-DJp7WwSv.js.map +1 -0
- package/dist/Button-nzmDNS2q.js +391 -0
- package/dist/Button-nzmDNS2q.js.map +1 -0
- package/dist/Calendar-cG5NIJ4O.js +6768 -0
- package/dist/Calendar-cG5NIJ4O.js.map +1 -0
- package/dist/Card-BAoZ35CV.js +105 -0
- package/dist/Card-BAoZ35CV.js.map +1 -0
- package/dist/Checkbox-GJ8-srt4.js +97 -0
- package/dist/Checkbox-GJ8-srt4.js.map +1 -0
- package/dist/Clipboard-CBJZiviP.js +58 -0
- package/dist/Clipboard-CBJZiviP.js.map +1 -0
- package/dist/ClipboardButton-ez5V3fkk.js +43 -0
- package/dist/ClipboardButton-ez5V3fkk.js.map +1 -0
- package/dist/CodeEditor-BfQJfbhL.js +952 -0
- package/dist/CodeEditor-BfQJfbhL.js.map +1 -0
- package/dist/Collapsible-BQXWEOBC.js +34 -0
- package/dist/Collapsible-BQXWEOBC.js.map +1 -0
- package/dist/ColorInput-Dx8Dsv7Y.js +180 -0
- package/dist/ColorInput-Dx8Dsv7Y.js.map +1 -0
- package/dist/ColorModeSwitch-CCqj7tjE.js +77 -0
- package/dist/ColorModeSwitch-CCqj7tjE.js.map +1 -0
- package/dist/Combobox-c_xBjf0P.js +439 -0
- package/dist/Combobox-c_xBjf0P.js.map +1 -0
- package/dist/Command-CQ_bQsJp.js +102 -0
- package/dist/Command-CQ_bQsJp.js.map +1 -0
- package/dist/CopyField-BJ96zvXs.js +322 -0
- package/dist/CopyField-BJ96zvXs.js.map +1 -0
- package/dist/DateInput-CMD3dY-T.js +141 -0
- package/dist/DateInput-CMD3dY-T.js.map +1 -0
- package/dist/DatePicker-BbFbmsGl.js +24 -0
- package/dist/DatePicker-BbFbmsGl.js.map +1 -0
- package/dist/DateRangeInput-D3BhiKyk.js +139 -0
- package/dist/DateRangeInput-D3BhiKyk.js.map +1 -0
- package/dist/DateRangePicker-BiUgtt_M.js +159 -0
- package/dist/DateRangePicker-BiUgtt_M.js.map +1 -0
- package/dist/DiagramSkeleton-lwBS2YBa.js +11 -0
- package/dist/DiagramSkeleton-lwBS2YBa.js.map +1 -0
- package/dist/DiffView-ppTIzh2h.js +429 -0
- package/dist/DiffView-ppTIzh2h.js.map +1 -0
- package/dist/DropdownMenu-B6ZbYvaM.js +327 -0
- package/dist/DropdownMenu-B6ZbYvaM.js.map +1 -0
- package/dist/FieldBox-D7DYtX_m.js +70 -0
- package/dist/FieldBox-D7DYtX_m.js.map +1 -0
- package/dist/FileUpload-sXRv7JiY.js +2527 -0
- package/dist/FileUpload-sXRv7JiY.js.map +1 -0
- package/dist/Form-BDCef6O9.js +371 -0
- package/dist/Form-BDCef6O9.js.map +1 -0
- package/dist/FormGroup-S9mPNHKH.js +124 -0
- package/dist/FormGroup-S9mPNHKH.js.map +1 -0
- package/dist/FullScreenModal-CJa2VkJ2.js +96 -0
- package/dist/FullScreenModal-CJa2VkJ2.js.map +1 -0
- package/dist/HoverCard-WfDkLK1s.js +31 -0
- package/dist/HoverCard-WfDkLK1s.js.map +1 -0
- package/dist/InputGroup-BJWsI35s.js +292 -0
- package/dist/InputGroup-BJWsI35s.js.map +1 -0
- package/dist/Kbd-CxHAo1oo.js +111 -0
- package/dist/Kbd-CxHAo1oo.js.map +1 -0
- package/dist/MarkedText-Ckbft5mw.js +44 -0
- package/dist/MarkedText-Ckbft5mw.js.map +1 -0
- package/dist/MermaidDiagram-BB06gymm.js +399 -0
- package/dist/MermaidDiagram-BB06gymm.js.map +1 -0
- package/dist/Modal-BA5Wc3sx.js +185 -0
- package/dist/Modal-BA5Wc3sx.js.map +1 -0
- package/dist/ModalTitle-C76ke2eo.js +28 -0
- package/dist/ModalTitle-C76ke2eo.js.map +1 -0
- package/dist/MultiActionButtonGroup-CiBHxsSk.js +33 -0
- package/dist/MultiActionButtonGroup-CiBHxsSk.js.map +1 -0
- package/dist/Navbar-t16usFZQ.js +322 -0
- package/dist/Navbar-t16usFZQ.js.map +1 -0
- package/dist/OtpInput-CbbymqYs.js +93 -0
- package/dist/OtpInput-CbbymqYs.js.map +1 -0
- package/dist/PageHeader-Q3IpCnQd.js +177 -0
- package/dist/PageHeader-Q3IpCnQd.js.map +1 -0
- package/dist/PageLayout-DSVM-ASz.js +176 -0
- package/dist/PageLayout-DSVM-ASz.js.map +1 -0
- package/dist/PageToolbar-0_1OBzaZ.js +153 -0
- package/dist/PageToolbar-0_1OBzaZ.js.map +1 -0
- package/dist/Pagination-CM_Rszz-.js +70 -0
- package/dist/Pagination-CM_Rszz-.js.map +1 -0
- package/dist/Popconfirm-BGe1jLov.js +170 -0
- package/dist/Popconfirm-BGe1jLov.js.map +1 -0
- package/dist/Popover-Ca0V6AD1.js +92 -0
- package/dist/Popover-Ca0V6AD1.js.map +1 -0
- package/dist/RadioGroup-sIveSsNa.js +233 -0
- package/dist/RadioGroup-sIveSsNa.js.map +1 -0
- package/dist/Resizable-D3vYToZH.js +52 -0
- package/dist/Resizable-D3vYToZH.js.map +1 -0
- package/dist/Search-3UiqNZRj.js +184 -0
- package/dist/Search-3UiqNZRj.js.map +1 -0
- package/dist/SearchInput-D2fcOv7E.js +102 -0
- package/dist/SearchInput-D2fcOv7E.js.map +1 -0
- package/dist/SectionNav--7bw2b6u.js +276 -0
- package/dist/SectionNav--7bw2b6u.js.map +1 -0
- package/dist/Select-4YX38G5h.js +181 -0
- package/dist/Select-4YX38G5h.js.map +1 -0
- package/dist/Sheet-BQrX8-h5.js +169 -0
- package/dist/Sheet-BQrX8-h5.js.map +1 -0
- package/dist/Sidebar-ROaR_AqC.js +799 -0
- package/dist/Sidebar-ROaR_AqC.js.map +1 -0
- package/dist/Slider-Da_3mS5v.js +127 -0
- package/dist/Slider-Da_3mS5v.js.map +1 -0
- package/dist/Stepper-C8sm9ZFM.js +325 -0
- package/dist/Stepper-C8sm9ZFM.js.map +1 -0
- package/dist/Switch-CX2A0v50.js +201 -0
- package/dist/Switch-CX2A0v50.js.map +1 -0
- package/dist/Table-CvYuTuNU.js +104 -0
- package/dist/Table-CvYuTuNU.js.map +1 -0
- package/dist/Tabs-EAihyqCt.js +74 -0
- package/dist/Tabs-EAihyqCt.js.map +1 -0
- package/dist/TextInput-BGed-V13.js +110 -0
- package/dist/TextInput-BGed-V13.js.map +1 -0
- package/dist/ThemeProvider-QncUrfJn.js +203 -0
- package/dist/ThemeProvider-QncUrfJn.js.map +1 -0
- package/dist/TimePicker-B_NegL-7.js +98 -0
- package/dist/TimePicker-B_NegL-7.js.map +1 -0
- package/dist/Timeline-6btyJl4D.js +154 -0
- package/dist/Timeline-6btyJl4D.js.map +1 -0
- package/dist/Toast-DQSbs3oA.js +49 -0
- package/dist/Toast-DQSbs3oA.js.map +1 -0
- package/dist/ToggleGroup-Cy_10Mvu.js +47 -0
- package/dist/ToggleGroup-Cy_10Mvu.js.map +1 -0
- package/dist/Workbench-BzE-Vvd9.js +293 -0
- package/dist/Workbench-BzE-Vvd9.js.map +1 -0
- package/dist/ZoomableSvg-DG9PnAm8.js +248 -0
- package/dist/ZoomableSvg-DG9PnAm8.js.map +1 -0
- package/dist/charts.d.ts +124 -111
- package/dist/charts.js +303 -249
- package/dist/charts.js.map +1 -1
- package/dist/classNames-BzrkDnOD.js +9 -0
- package/dist/classNames-BzrkDnOD.js.map +1 -0
- package/dist/constants-D6JcsD4_.d.ts +41 -0
- package/dist/context-KxxeMHbR.js +62 -0
- package/dist/context-KxxeMHbR.js.map +1 -0
- package/dist/editors.d.ts +180 -173
- package/dist/editors.js +747 -420
- package/dist/editors.js.map +1 -1
- package/dist/escapeStringRegexp-8MxP2knR.js +6 -0
- package/dist/escapeStringRegexp-8MxP2knR.js.map +1 -0
- package/dist/icons-Cek151jC.js +640 -0
- package/dist/icons-Cek151jC.js.map +1 -0
- package/dist/icons.d.ts +2 -41
- package/dist/icons.js +2 -4
- package/dist/index-m-kQEWiY.d.ts +54 -0
- package/dist/index.d.ts +6192 -9904
- package/dist/index.js +112 -15803
- package/dist/internal/blocks/AIKit.js +2 -0
- package/dist/internal/blocks/AppShell.js +2 -0
- package/dist/internal/blocks/AutoSaveTextarea.js +2 -0
- package/dist/internal/blocks/BrandEditor.js +2 -0
- package/dist/internal/blocks/ChartPanel.js +46 -0
- package/dist/internal/blocks/ChartPanel.js.map +1 -0
- package/dist/internal/blocks/ClipboardButton.js +2 -0
- package/dist/internal/blocks/ColorInput.js +2 -0
- package/dist/internal/blocks/ColorModeSwitch.js +2 -0
- package/dist/internal/blocks/Command.js +2 -0
- package/dist/internal/blocks/CopyField.js +2 -0
- package/dist/internal/blocks/DashboardHero.js +59 -0
- package/dist/internal/blocks/DashboardHero.js.map +1 -0
- package/dist/internal/blocks/DateInput.js +2 -0
- package/dist/internal/blocks/DateRangeInput.js +2 -0
- package/dist/internal/blocks/EmptyConfigurationActionCard.js +16 -0
- package/dist/internal/blocks/EmptyConfigurationActionCard.js.map +1 -0
- package/dist/internal/blocks/EmptyState.js +142 -0
- package/dist/internal/blocks/EmptyState.js.map +1 -0
- package/dist/internal/blocks/ErrorState.js +179 -0
- package/dist/internal/blocks/ErrorState.js.map +1 -0
- package/dist/internal/blocks/ExportMenu.js +41 -0
- package/dist/internal/blocks/ExportMenu.js.map +1 -0
- package/dist/internal/blocks/Form.js +2 -0
- package/dist/internal/blocks/FormGroup.js +2 -0
- package/dist/internal/blocks/GoogleButton.js +95 -0
- package/dist/internal/blocks/GoogleButton.js.map +1 -0
- package/dist/internal/blocks/MicrosoftButton.js +64 -0
- package/dist/internal/blocks/MicrosoftButton.js.map +1 -0
- package/dist/internal/blocks/MultiActionButtonGroup.js +2 -0
- package/dist/internal/blocks/MultiCombobox.js +188 -0
- package/dist/internal/blocks/MultiCombobox.js.map +1 -0
- package/dist/internal/blocks/NumberInput.js +44 -0
- package/dist/internal/blocks/NumberInput.js.map +1 -0
- package/dist/internal/blocks/OtpInput.js +2 -0
- package/dist/internal/blocks/PageHeader.js +2 -0
- package/dist/internal/blocks/PageLayout.js +2 -0
- package/dist/internal/blocks/PageToolbar.js +2 -0
- package/dist/internal/blocks/PasswordInput.js +97 -0
- package/dist/internal/blocks/PasswordInput.js.map +1 -0
- package/dist/internal/blocks/SearchInput.js +2 -0
- package/dist/internal/blocks/SearchInputWithNavigation.js +65 -0
- package/dist/internal/blocks/SearchInputWithNavigation.js.map +1 -0
- package/dist/internal/blocks/SectionNav.js +2 -0
- package/dist/internal/blocks/SplitButton.js +46 -0
- package/dist/internal/blocks/SplitButton.js.map +1 -0
- package/dist/internal/blocks/StatCard.js +97 -0
- package/dist/internal/blocks/StatCard.js.map +1 -0
- package/dist/internal/blocks/TextInput.js +2 -0
- package/dist/internal/blocks/Textarea.js +32 -0
- package/dist/internal/blocks/Textarea.js.map +1 -0
- package/dist/internal/blocks/TimeInput.js +77 -0
- package/dist/internal/blocks/TimeInput.js.map +1 -0
- package/dist/internal/components/Alert.js +2 -0
- package/dist/internal/components/AlertModal.js +2 -0
- package/dist/internal/components/Avatar.js +53 -0
- package/dist/internal/components/Avatar.js.map +1 -0
- package/dist/internal/components/Badge.js +2 -0
- package/dist/internal/components/BrandLogo.js +2 -0
- package/dist/internal/components/Breadcrumb.js +2 -0
- package/dist/internal/components/Button.js +2 -0
- package/dist/internal/components/ButtonGroup.js +66 -0
- package/dist/internal/components/ButtonGroup.js.map +1 -0
- package/dist/internal/components/Calendar.js +2 -0
- package/dist/internal/components/Card.js +2 -0
- package/dist/internal/components/Checkbox.js +2 -0
- package/dist/internal/components/Clipboard.js +2 -0
- package/dist/internal/components/Collapsible.js +2 -0
- package/dist/internal/components/CollapsiblePanel.js +87 -0
- package/dist/internal/components/CollapsiblePanel.js.map +1 -0
- package/dist/internal/components/Combobox.js +2 -0
- package/dist/internal/components/DatePicker.js +2 -0
- package/dist/internal/components/DateRangePicker.js +2 -0
- package/dist/internal/components/DiffView.js +2 -0
- package/dist/internal/components/DotsLoader.js +18 -0
- package/dist/internal/components/DotsLoader.js.map +1 -0
- package/dist/internal/components/DropdownMenu.js +2 -0
- package/dist/internal/components/EmptySearchContent.js +12 -0
- package/dist/internal/components/EmptySearchContent.js.map +1 -0
- package/dist/internal/components/FileUpload.js +2 -0
- package/dist/internal/components/FullScreenModal.js +2 -0
- package/dist/internal/components/HelpBlock.js +25 -0
- package/dist/internal/components/HelpBlock.js.map +1 -0
- package/dist/internal/components/HoverCard.js +2 -0
- package/dist/internal/components/InputGroup.js +2 -0
- package/dist/internal/components/Kbd.js +2 -0
- package/dist/internal/components/Label.js +39 -0
- package/dist/internal/components/Label.js.map +1 -0
- package/dist/internal/components/Link.js +22 -0
- package/dist/internal/components/Link.js.map +1 -0
- package/dist/internal/components/MarkedText.js +2 -0
- package/dist/internal/components/MergeEditor/ConflictStatus/ConflictStatusIndicator.js +20 -0
- package/dist/internal/components/MergeEditor/ConflictStatus/ConflictStatusIndicator.js.map +1 -0
- package/dist/internal/components/MergeEditor/PaneHeader.js +13 -0
- package/dist/internal/components/MergeEditor/PaneHeader.js.map +1 -0
- package/dist/internal/components/MergeEditor/constants.js +18 -0
- package/dist/internal/components/MergeEditor/constants.js.map +1 -0
- package/dist/internal/components/MergeEditor/useMergeDiff.js +2 -0
- package/dist/internal/components/Modal.js +2 -0
- package/dist/internal/components/Navbar.js +2 -0
- package/dist/internal/components/Pagination.js +2 -0
- package/dist/internal/components/PanelWithDetails.js +31 -0
- package/dist/internal/components/PanelWithDetails.js.map +1 -0
- package/dist/internal/components/Popconfirm.js +2 -0
- package/dist/internal/components/Popover.js +2 -0
- package/dist/internal/components/Progress.js +47 -0
- package/dist/internal/components/Progress.js.map +1 -0
- package/dist/internal/components/RadioGroup.js +2 -0
- package/dist/internal/components/Resizable.js +2 -0
- package/dist/internal/components/ScrollArea.js +42 -0
- package/dist/internal/components/ScrollArea.js.map +1 -0
- package/dist/internal/components/Search.js +2 -0
- package/dist/internal/components/Select.js +2 -0
- package/dist/internal/components/Separator.js +84 -0
- package/dist/internal/components/Separator.js.map +1 -0
- package/dist/internal/components/Sheet.js +2 -0
- package/dist/internal/components/Sidebar.js +2 -0
- package/dist/internal/components/Skeleton/Skeleton.js +39 -0
- package/dist/internal/components/Skeleton/Skeleton.js.map +1 -0
- package/dist/internal/components/Skeleton/SkeletonList.js +41 -0
- package/dist/internal/components/Skeleton/SkeletonList.js.map +1 -0
- package/dist/internal/components/Slider.js +2 -0
- package/dist/internal/components/SpotlightBackdrop.js +132 -0
- package/dist/internal/components/SpotlightBackdrop.js.map +1 -0
- package/dist/internal/components/Stepper.js +2 -0
- package/dist/internal/components/Switch.js +2 -0
- package/dist/internal/components/Table.js +2 -0
- package/dist/internal/components/Tabs.js +2 -0
- package/dist/internal/components/ThemeProvider.js +3 -0
- package/dist/internal/components/TimePicker.js +2 -0
- package/dist/internal/components/Timeline.js +2 -0
- package/dist/internal/components/Toast.js +3 -0
- package/dist/internal/components/Toggle.js +169 -0
- package/dist/internal/components/Toggle.js.map +1 -0
- package/dist/internal/components/ToggleGroup.js +2 -0
- package/dist/internal/components/Tooltip.js +2 -0
- package/dist/internal/components/Truncated.js +45 -0
- package/dist/internal/components/Truncated.js.map +1 -0
- package/dist/internal/components/Workbench.js +2 -0
- package/dist/internal/components/ZoomableSvg.js +2 -0
- package/dist/internal/hooks/useAutosizeInput.js +77 -0
- package/dist/internal/hooks/useAutosizeInput.js.map +1 -0
- package/dist/internal/hooks/useScrollbarPosition.js +45 -0
- package/dist/internal/hooks/useScrollbarPosition.js.map +1 -0
- package/dist/internal/hooks/useStableCallback.js +29 -0
- package/dist/internal/hooks/useStableCallback.js.map +1 -0
- package/dist/internal/utils/mergeRefs.js +20 -0
- package/dist/internal/utils/mergeRefs.js.map +1 -0
- package/dist/internal/utils.js +5 -0
- package/dist/markdown-editor.d.ts +72 -72
- package/dist/markdown-editor.js +1122 -1193
- package/dist/markdown-editor.js.map +1 -1
- package/dist/mermaid.d.ts +12 -12
- package/dist/mermaid.js +2 -10
- package/dist/rjsf.d.ts +33 -34
- package/dist/rjsf.js +1543 -1600
- package/dist/rjsf.js.map +1 -1
- package/dist/rolldown-runtime-Bdc48AWt.js +33 -0
- package/dist/styles-DSUP_-9Z.js +158 -0
- package/dist/styles-DSUP_-9Z.js.map +1 -0
- package/dist/styles.css +1 -1
- package/dist/testing.d.ts +8 -7
- package/dist/testing.js +36 -16
- package/dist/testing.js.map +1 -1
- package/dist/themeTokens-BNg98Mu9.js +85 -0
- package/dist/themeTokens-BNg98Mu9.js.map +1 -0
- package/dist/toast-CjkURw0M.js +184 -0
- package/dist/toast-CjkURw0M.js.map +1 -0
- package/dist/useColorSchemeState-CYqcUfSH.js +61 -0
- package/dist/useColorSchemeState-CYqcUfSH.js.map +1 -0
- package/dist/useControllableState-M6494mCT.js +31 -0
- package/dist/useControllableState-M6494mCT.js.map +1 -0
- package/dist/useElement-DkF6esWL.js +15 -0
- package/dist/useElement-DkF6esWL.js.map +1 -0
- package/dist/useMergeDiff-CvowEXJ1.js +465 -0
- package/dist/useMergeDiff-CvowEXJ1.js.map +1 -0
- package/dist/utils-D0c5VAyF.js +308 -0
- package/dist/utils-D0c5VAyF.js.map +1 -0
- package/package.json +10 -9
- package/src/styles.css +35 -7
- package/src/theme.css +64 -0
- package/dist/MermaidDiagram-EOKJHQQV.js +0 -10
- package/dist/MermaidDiagram-EOKJHQQV.js.map +0 -1
- package/dist/chunk-63NSN2VL.js +0 -274
- package/dist/chunk-63NSN2VL.js.map +0 -1
- package/dist/chunk-6FPEI4EM.js +0 -6683
- package/dist/chunk-6FPEI4EM.js.map +0 -1
- package/dist/chunk-7PUUHEJQ.js +0 -1313
- package/dist/chunk-7PUUHEJQ.js.map +0 -1
- package/dist/chunk-BOHNXTMM.js +0 -606
- package/dist/chunk-BOHNXTMM.js.map +0 -1
- package/dist/chunk-C3L3TBBT.js +0 -242
- package/dist/chunk-C3L3TBBT.js.map +0 -1
- package/dist/chunk-CTCFYWJC.js +0 -407
- package/dist/chunk-CTCFYWJC.js.map +0 -1
- package/dist/chunk-ESBL3IPF.js +0 -23
- package/dist/chunk-ESBL3IPF.js.map +0 -1
- package/dist/chunk-IJTHFNNJ.js +0 -261
- package/dist/chunk-IJTHFNNJ.js.map +0 -1
- package/dist/chunk-JP7PNHLH.js +0 -40
- package/dist/chunk-JP7PNHLH.js.map +0 -1
- package/dist/chunk-KPNAW5MU.js +0 -229
- package/dist/chunk-KPNAW5MU.js.map +0 -1
- package/dist/chunk-L37JJ6MR.js +0 -152
- package/dist/chunk-L37JJ6MR.js.map +0 -1
- package/dist/chunk-Q7NWXLCT.js +0 -90
- package/dist/chunk-Q7NWXLCT.js.map +0 -1
- package/dist/chunk-SYIEF644.js +0 -1016
- package/dist/chunk-SYIEF644.js.map +0 -1
- package/dist/chunk-VMFSRV5H.js +0 -16
- package/dist/chunk-VMFSRV5H.js.map +0 -1
- package/dist/chunk-VPPM7UUQ.js +0 -47
- package/dist/chunk-VPPM7UUQ.js.map +0 -1
- package/dist/chunk-XV3UUOYF.js +0 -845
- package/dist/chunk-XV3UUOYF.js.map +0 -1
- package/dist/constants-D3gaMY-W.d.ts +0 -39
- package/dist/icons.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/mermaid.js.map +0 -1
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
import { cn } from "./classNames-BzrkDnOD.js";
|
|
2
|
+
import { useControllableState } from "./useControllableState-M6494mCT.js";
|
|
3
|
+
import { Collapsible } from "./Collapsible-BQXWEOBC.js";
|
|
4
|
+
import { Slot } from "@radix-ui/react-slot";
|
|
5
|
+
import { createContext, use, useEffect, useMemo, useRef, useState } from "react";
|
|
6
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
//#region src/components/Workbench/constants.ts
|
|
8
|
+
const DEFAULT_WORKBENCH_BAR_HEIGHT_IN_REM = 2.75;
|
|
9
|
+
const DEFAULT_WORKBENCH_PANEL_HEIGHT_IN_PX = 320;
|
|
10
|
+
const MIN_WORKBENCH_PANEL_HEIGHT_IN_PX = 120;
|
|
11
|
+
const WORKBENCH_PANEL_FULL_SCREEN_EXIT_RATIO = .8;
|
|
12
|
+
//#endregion
|
|
13
|
+
//#region src/components/Workbench/context.ts
|
|
14
|
+
const createWorkbenchActions = (setState) => ({
|
|
15
|
+
expand: () => setState((state) => state === "collapsed" ? "expanded" : state),
|
|
16
|
+
collapse: () => setState("collapsed"),
|
|
17
|
+
toggleExpanded: () => setState((state) => state === "collapsed" ? "expanded" : "collapsed"),
|
|
18
|
+
enterFullScreen: () => setState("full-screen"),
|
|
19
|
+
exitFullScreen: () => setState((state) => state === "full-screen" ? "expanded" : state),
|
|
20
|
+
toggleFullScreen: () => setState((state) => state === "full-screen" ? "expanded" : "full-screen")
|
|
21
|
+
});
|
|
22
|
+
const WorkbenchContext = createContext(null);
|
|
23
|
+
/**
|
|
24
|
+
* The parts sit at arbitrary depth under `<Workbench>` — a trigger lives inside the panel header,
|
|
25
|
+
* three levels down — so the state travels by context rather than props.
|
|
26
|
+
*/
|
|
27
|
+
const useWorkbench = () => {
|
|
28
|
+
const context = use(WorkbenchContext);
|
|
29
|
+
if (context === null) throw new Error("Workbench compound components must be rendered inside <Workbench>.");
|
|
30
|
+
return context;
|
|
31
|
+
};
|
|
32
|
+
//#endregion
|
|
33
|
+
//#region src/components/Workbench/WorkbenchBar/WorkbenchBarEnd.tsx
|
|
34
|
+
const WorkbenchBarEnd = ({ className, ...props }) => /* @__PURE__ */ jsx("div", {
|
|
35
|
+
...props,
|
|
36
|
+
"data-slot": "workbench-bar-end",
|
|
37
|
+
className: cn("tw:col-start-3", "tw:row-start-1", "tw:flex", "tw:items-center", "tw:justify-end", "tw:gap-2", className)
|
|
38
|
+
});
|
|
39
|
+
//#endregion
|
|
40
|
+
//#region src/components/Workbench/WorkbenchBar/WorkbenchBarMiddle.tsx
|
|
41
|
+
const WorkbenchBarMiddle = ({ className, ...props }) => /* @__PURE__ */ jsx("div", {
|
|
42
|
+
...props,
|
|
43
|
+
"data-slot": "workbench-bar-middle",
|
|
44
|
+
className: cn("tw:col-start-2", "tw:row-start-1", "tw:flex", "tw:items-center", "tw:justify-center", "tw:gap-2", className)
|
|
45
|
+
});
|
|
46
|
+
//#endregion
|
|
47
|
+
//#region src/components/Workbench/WorkbenchBar/WorkbenchBarStart.tsx
|
|
48
|
+
const WorkbenchBarStart = ({ className, ...props }) => /* @__PURE__ */ jsx("div", {
|
|
49
|
+
...props,
|
|
50
|
+
"data-slot": "workbench-bar-start",
|
|
51
|
+
className: cn("tw:col-start-1", "tw:row-start-1", "tw:flex", "tw:items-center", "tw:gap-2", className)
|
|
52
|
+
});
|
|
53
|
+
//#endregion
|
|
54
|
+
//#region src/components/Workbench/WorkbenchBar/WorkbenchBar.tsx
|
|
55
|
+
const WorkbenchBar = ({ className, children, ...props }) => /* @__PURE__ */ jsx("div", {
|
|
56
|
+
className: cn("tw:grid", "tw:grid-cols-[auto_1fr_auto]", "tw:items-center", "tw:gap-x-2", "tw:h-(--workbench-bar-height)", "tw:shrink-0", "tw:pointer-events-auto", "tw:border-t", "tw:border-sidebar-border", "tw:bg-sidebar", "tw:px-3", "tw:text-xs", className),
|
|
57
|
+
...props,
|
|
58
|
+
children
|
|
59
|
+
});
|
|
60
|
+
WorkbenchBar.Start = WorkbenchBarStart;
|
|
61
|
+
WorkbenchBar.Middle = WorkbenchBarMiddle;
|
|
62
|
+
WorkbenchBar.End = WorkbenchBarEnd;
|
|
63
|
+
//#endregion
|
|
64
|
+
//#region src/components/Workbench/WorkbenchFullScreenTrigger.tsx
|
|
65
|
+
const WorkbenchFullScreenTrigger = ({ asChild = false, onClick, ...props }) => {
|
|
66
|
+
const { state, toggleFullScreen } = useWorkbench();
|
|
67
|
+
const isFullScreen = state === "full-screen";
|
|
68
|
+
const Comp = asChild ? Slot : "button";
|
|
69
|
+
const handleClick = (event) => {
|
|
70
|
+
onClick?.(event);
|
|
71
|
+
if (!event.defaultPrevented) toggleFullScreen();
|
|
72
|
+
};
|
|
73
|
+
return /* @__PURE__ */ jsx(Comp, {
|
|
74
|
+
...asChild ? {} : { type: "button" },
|
|
75
|
+
...props,
|
|
76
|
+
"data-slot": "workbench-full-screen-trigger",
|
|
77
|
+
"data-state": isFullScreen ? "on" : "off",
|
|
78
|
+
onClick: handleClick
|
|
79
|
+
});
|
|
80
|
+
};
|
|
81
|
+
//#endregion
|
|
82
|
+
//#region src/components/Workbench/WorkbenchPanel/WorkbenchPanelResizeHandle.tsx
|
|
83
|
+
const getMaxHeight = (panel) => {
|
|
84
|
+
const hostTop = panel.offsetParent?.getBoundingClientRect().top ?? 0;
|
|
85
|
+
return Math.max(panel.getBoundingClientRect().bottom - hostTop, 120);
|
|
86
|
+
};
|
|
87
|
+
const clampHeight = (height, panel) => Math.min(Math.max(height, 120), getMaxHeight(panel));
|
|
88
|
+
const WorkbenchPanelResizeHandle = ({ panelRef }) => {
|
|
89
|
+
const { state, panelHeight, setPanelHeight, isResizing, setIsResizing, enterFullScreen, exitFullScreen } = useWorkbench();
|
|
90
|
+
const grabOffsetRef = useRef(0);
|
|
91
|
+
const previousStateRef = useRef(state);
|
|
92
|
+
const isFullScreenRequestedRef = useRef(state === "full-screen");
|
|
93
|
+
const enteredFullScreenByDragRef = useRef(false);
|
|
94
|
+
const exitedFullScreenByDragRef = useRef(false);
|
|
95
|
+
useEffect(() => {
|
|
96
|
+
if (!isResizing) return;
|
|
97
|
+
const { body } = document;
|
|
98
|
+
const { cursor, userSelect } = body.style;
|
|
99
|
+
body.style.cursor = "ns-resize";
|
|
100
|
+
body.style.userSelect = "none";
|
|
101
|
+
return () => {
|
|
102
|
+
body.style.cursor = cursor;
|
|
103
|
+
body.style.userSelect = userSelect;
|
|
104
|
+
};
|
|
105
|
+
}, [isResizing]);
|
|
106
|
+
useEffect(() => {
|
|
107
|
+
const previous = previousStateRef.current;
|
|
108
|
+
const panel = panelRef.current;
|
|
109
|
+
previousStateRef.current = state;
|
|
110
|
+
isFullScreenRequestedRef.current = state === "full-screen";
|
|
111
|
+
if (previous !== "full-screen" || state !== "expanded" || !panel) return;
|
|
112
|
+
const draggedIntoFullScreen = enteredFullScreenByDragRef.current;
|
|
113
|
+
const draggedOutOfFullScreen = exitedFullScreenByDragRef.current;
|
|
114
|
+
enteredFullScreenByDragRef.current = false;
|
|
115
|
+
exitedFullScreenByDragRef.current = false;
|
|
116
|
+
if (!draggedIntoFullScreen || draggedOutOfFullScreen) return;
|
|
117
|
+
setPanelHeight(clampHeight(getMaxHeight(panel) * WORKBENCH_PANEL_FULL_SCREEN_EXIT_RATIO, panel));
|
|
118
|
+
}, [
|
|
119
|
+
state,
|
|
120
|
+
panelRef,
|
|
121
|
+
setPanelHeight
|
|
122
|
+
]);
|
|
123
|
+
const applyHeight = (height, panel) => {
|
|
124
|
+
const isFullScreen = isFullScreenRequestedRef.current;
|
|
125
|
+
if (height >= getMaxHeight(panel)) {
|
|
126
|
+
if (!isFullScreen) {
|
|
127
|
+
isFullScreenRequestedRef.current = true;
|
|
128
|
+
enteredFullScreenByDragRef.current = true;
|
|
129
|
+
enterFullScreen();
|
|
130
|
+
}
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
if (isFullScreen) {
|
|
134
|
+
isFullScreenRequestedRef.current = false;
|
|
135
|
+
exitedFullScreenByDragRef.current = true;
|
|
136
|
+
exitFullScreen();
|
|
137
|
+
}
|
|
138
|
+
setPanelHeight(Math.max(height, 120));
|
|
139
|
+
};
|
|
140
|
+
const handlePointerDown = (event) => {
|
|
141
|
+
const panel = panelRef.current;
|
|
142
|
+
if (event.button !== 0 || !panel) return;
|
|
143
|
+
event.preventDefault();
|
|
144
|
+
event.currentTarget.setPointerCapture(event.pointerId);
|
|
145
|
+
grabOffsetRef.current = panel.getBoundingClientRect().top - event.clientY;
|
|
146
|
+
setIsResizing(true);
|
|
147
|
+
};
|
|
148
|
+
const handlePointerMove = (event) => {
|
|
149
|
+
const panel = panelRef.current;
|
|
150
|
+
if (!panel || !event.currentTarget.hasPointerCapture(event.pointerId)) return;
|
|
151
|
+
const top = event.clientY + grabOffsetRef.current;
|
|
152
|
+
applyHeight(panel.getBoundingClientRect().bottom - top, panel);
|
|
153
|
+
};
|
|
154
|
+
const handleKeyDown = (event) => {
|
|
155
|
+
const panel = panelRef.current;
|
|
156
|
+
if (!panel) return;
|
|
157
|
+
const step = event.shiftKey ? 96 : 24;
|
|
158
|
+
const delta = event.key === "ArrowUp" ? step : event.key === "ArrowDown" ? -step : 0;
|
|
159
|
+
if (delta === 0) return;
|
|
160
|
+
event.preventDefault();
|
|
161
|
+
applyHeight((isFullScreenRequestedRef.current ? getMaxHeight(panel) : panelHeight) + delta, panel);
|
|
162
|
+
};
|
|
163
|
+
return /* @__PURE__ */ jsx("div", {
|
|
164
|
+
role: "separator",
|
|
165
|
+
"aria-orientation": "horizontal",
|
|
166
|
+
"aria-label": "Resize panel",
|
|
167
|
+
"aria-valuenow": Math.round(panelHeight),
|
|
168
|
+
"aria-valuemin": 120,
|
|
169
|
+
tabIndex: 0,
|
|
170
|
+
onPointerDown: handlePointerDown,
|
|
171
|
+
onPointerMove: handlePointerMove,
|
|
172
|
+
onLostPointerCapture: () => setIsResizing(false),
|
|
173
|
+
onKeyDown: handleKeyDown,
|
|
174
|
+
className: cn("tw:group/workbench-resize", "tw:absolute", "tw:inset-x-0", "tw:top-0", "tw:z-10", "tw:h-2", "tw:flex", "tw:justify-center", "tw:cursor-ns-resize", "tw:touch-none", "tw:outline-none"),
|
|
175
|
+
children: /* @__PURE__ */ jsx("span", {
|
|
176
|
+
className: cn("tw:flex", "tw:h-3", "tw:w-16", "tw:items-end", "tw:justify-center"),
|
|
177
|
+
children: /* @__PURE__ */ jsx("span", { className: cn("tw:h-1.5", "tw:w-16", "tw:rounded-full", "tw:bg-input", "tw:transition-colors", "tw:group-hover/workbench-resize:bg-muted-foreground", "tw:group-focus-visible/workbench-resize:bg-muted-foreground", "tw:group-data-[workbench-resizing=true]/workbench:bg-muted-foreground") })
|
|
178
|
+
})
|
|
179
|
+
});
|
|
180
|
+
};
|
|
181
|
+
//#endregion
|
|
182
|
+
//#region src/components/Workbench/WorkbenchPanel/WorkbenchPanel.tsx
|
|
183
|
+
const clearRadixMeasurementTransitionBlock = (panel) => {
|
|
184
|
+
if (panel) panel.style.transitionDuration = "";
|
|
185
|
+
};
|
|
186
|
+
const WorkbenchPanel = ({ className, children, ...props }) => {
|
|
187
|
+
const panelRef = useRef(null);
|
|
188
|
+
useEffect(() => clearRadixMeasurementTransitionBlock(panelRef.current), []);
|
|
189
|
+
return /* @__PURE__ */ jsxs(Collapsible.Content, {
|
|
190
|
+
ref: panelRef,
|
|
191
|
+
style: { "--workbench-panel-shadow": "0 -8px 24px -6px rgb(0 0 0 / 0.08)" },
|
|
192
|
+
className: cn("tw:absolute", "tw:inset-x-0", "tw:bottom-(--workbench-bar-height)", "tw:pointer-events-auto", "tw:h-(--workbench-panel-height)", "tw:max-h-[calc(100%-var(--workbench-bar-height))]", "tw:group-data-[workbench-state=full-screen]/workbench:h-[calc(100%-var(--workbench-bar-height))]", "tw:transition-[height]", "tw:duration-200", "tw:ease-out", "tw:group-data-[workbench-resizing=true]/workbench:transition-none", "tw:border-x", "tw:border-t", "tw:border-border", "tw:overflow-hidden", "tw:group-not-data-[workbench-state=full-screen]/workbench:rounded-t-2xl", "tw:group-not-data-[workbench-state=full-screen]/workbench:shadow-(--workbench-panel-shadow)"),
|
|
193
|
+
children: [/* @__PURE__ */ jsx(WorkbenchPanelResizeHandle, { panelRef }), /* @__PURE__ */ jsx("div", {
|
|
194
|
+
className: cn("tw:flex", "tw:flex-col", "tw:h-full", "tw:bg-background", className),
|
|
195
|
+
...props,
|
|
196
|
+
children
|
|
197
|
+
})]
|
|
198
|
+
});
|
|
199
|
+
};
|
|
200
|
+
//#endregion
|
|
201
|
+
//#region src/components/Workbench/WorkbenchPanel/WorkbenchPanelActions.tsx
|
|
202
|
+
const WorkbenchPanelActions = ({ className, asChild = false, ...props }) => {
|
|
203
|
+
return /* @__PURE__ */ jsx(asChild ? Slot : "div", {
|
|
204
|
+
...props,
|
|
205
|
+
"data-slot": "workbench-panel-actions",
|
|
206
|
+
className: cn("tw:col-start-2", "tw:row-start-1", "tw:flex", "tw:items-center", "tw:gap-2", className)
|
|
207
|
+
});
|
|
208
|
+
};
|
|
209
|
+
//#endregion
|
|
210
|
+
//#region src/components/Workbench/WorkbenchPanel/WorkbenchPanelContent.tsx
|
|
211
|
+
const WorkbenchPanelContent = ({ className, children, ...props }) => /* @__PURE__ */ jsx("div", {
|
|
212
|
+
className: cn("tw:min-h-0", "tw:flex-1", "tw:overflow-auto", className),
|
|
213
|
+
...props,
|
|
214
|
+
children
|
|
215
|
+
});
|
|
216
|
+
//#endregion
|
|
217
|
+
//#region src/components/Workbench/WorkbenchPanel/WorkbenchPanelHeader.tsx
|
|
218
|
+
const WorkbenchPanelHeader = ({ className, children, ...props }) => /* @__PURE__ */ jsx("div", {
|
|
219
|
+
className: cn("tw:grid", "tw:grid-cols-[1fr_auto]", "tw:items-center", "tw:gap-x-2", "tw:shrink-0", "tw:bg-sidebar", "tw:px-3", "tw:py-2", "tw:text-xs", className),
|
|
220
|
+
...props,
|
|
221
|
+
children
|
|
222
|
+
});
|
|
223
|
+
//#endregion
|
|
224
|
+
//#region src/components/Workbench/WorkbenchPanel/WorkbenchPanelTitle.tsx
|
|
225
|
+
const WorkbenchPanelTitle = ({ className, ...props }) => /* @__PURE__ */ jsx("div", {
|
|
226
|
+
...props,
|
|
227
|
+
"data-slot": "workbench-panel-title",
|
|
228
|
+
className: cn("tw:col-start-1", "tw:flex", "tw:items-center", "tw:text-sm", "tw:font-semibold", "tw:text-foreground", className)
|
|
229
|
+
});
|
|
230
|
+
//#endregion
|
|
231
|
+
//#region src/components/Workbench/Workbench.tsx
|
|
232
|
+
const Workbench = ({ className, children, state: stateProp, defaultState = "collapsed", onStateChange, barHeight = DEFAULT_WORKBENCH_BAR_HEIGHT_IN_REM, panelHeight: panelHeightProp, defaultPanelHeight = 320, onPanelHeightChange }) => {
|
|
233
|
+
const [state, setState] = useControllableState({
|
|
234
|
+
prop: stateProp,
|
|
235
|
+
defaultProp: defaultState,
|
|
236
|
+
onChange: onStateChange
|
|
237
|
+
});
|
|
238
|
+
const [panelHeight, setPanelHeight] = useControllableState({
|
|
239
|
+
prop: panelHeightProp,
|
|
240
|
+
defaultProp: defaultPanelHeight,
|
|
241
|
+
onChange: onPanelHeightChange
|
|
242
|
+
});
|
|
243
|
+
const [isResizing, setIsResizing] = useState(false);
|
|
244
|
+
const actions = useMemo(() => createWorkbenchActions(setState), [setState]);
|
|
245
|
+
const value = useMemo(() => ({
|
|
246
|
+
state,
|
|
247
|
+
setState,
|
|
248
|
+
panelHeight,
|
|
249
|
+
setPanelHeight,
|
|
250
|
+
isResizing,
|
|
251
|
+
setIsResizing,
|
|
252
|
+
...actions
|
|
253
|
+
}), [
|
|
254
|
+
state,
|
|
255
|
+
setState,
|
|
256
|
+
panelHeight,
|
|
257
|
+
setPanelHeight,
|
|
258
|
+
isResizing,
|
|
259
|
+
actions
|
|
260
|
+
]);
|
|
261
|
+
const clampedBarHeight = Math.max(barHeight, 1);
|
|
262
|
+
const clampedPanelHeight = Math.max(panelHeight, 120);
|
|
263
|
+
return /* @__PURE__ */ jsx(WorkbenchContext, {
|
|
264
|
+
value,
|
|
265
|
+
children: /* @__PURE__ */ jsx(Collapsible, {
|
|
266
|
+
open: state !== "collapsed",
|
|
267
|
+
onOpenChange: (open) => setState(open ? "expanded" : "collapsed"),
|
|
268
|
+
"data-workbench-state": state,
|
|
269
|
+
"data-workbench-resizing": isResizing ? "true" : void 0,
|
|
270
|
+
style: {
|
|
271
|
+
"--workbench-bar-height": `${clampedBarHeight}rem`,
|
|
272
|
+
"--workbench-panel-height": `${clampedPanelHeight}px`
|
|
273
|
+
},
|
|
274
|
+
className: cn("tailwindcss-preflight", "tw:group/workbench", "tw:z-[52]", "tw:shrink-0", className),
|
|
275
|
+
children
|
|
276
|
+
})
|
|
277
|
+
});
|
|
278
|
+
};
|
|
279
|
+
Workbench.Bar = WorkbenchBar;
|
|
280
|
+
Workbench.BarStart = WorkbenchBarStart;
|
|
281
|
+
Workbench.BarMiddle = WorkbenchBarMiddle;
|
|
282
|
+
Workbench.BarEnd = WorkbenchBarEnd;
|
|
283
|
+
Workbench.Panel = WorkbenchPanel;
|
|
284
|
+
Workbench.PanelHeader = WorkbenchPanelHeader;
|
|
285
|
+
Workbench.PanelTitle = WorkbenchPanelTitle;
|
|
286
|
+
Workbench.PanelActions = WorkbenchPanelActions;
|
|
287
|
+
Workbench.PanelContent = WorkbenchPanelContent;
|
|
288
|
+
Workbench.Trigger = Collapsible.Trigger;
|
|
289
|
+
Workbench.FullScreenTrigger = WorkbenchFullScreenTrigger;
|
|
290
|
+
//#endregion
|
|
291
|
+
export { DEFAULT_WORKBENCH_BAR_HEIGHT_IN_REM, DEFAULT_WORKBENCH_PANEL_HEIGHT_IN_PX, MIN_WORKBENCH_PANEL_HEIGHT_IN_PX, Workbench, useWorkbench };
|
|
292
|
+
|
|
293
|
+
//# sourceMappingURL=Workbench-BzE-Vvd9.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Workbench-BzE-Vvd9.js","names":[],"sources":["../src/components/Workbench/constants.ts","../src/components/Workbench/context.ts","../src/components/Workbench/WorkbenchBar/WorkbenchBarEnd.tsx","../src/components/Workbench/WorkbenchBar/WorkbenchBarMiddle.tsx","../src/components/Workbench/WorkbenchBar/WorkbenchBarStart.tsx","../src/components/Workbench/WorkbenchBar/WorkbenchBar.tsx","../src/components/Workbench/WorkbenchFullScreenTrigger.tsx","../src/components/Workbench/WorkbenchPanel/WorkbenchPanelResizeHandle.tsx","../src/components/Workbench/WorkbenchPanel/WorkbenchPanel.tsx","../src/components/Workbench/WorkbenchPanel/WorkbenchPanelActions.tsx","../src/components/Workbench/WorkbenchPanel/WorkbenchPanelContent.tsx","../src/components/Workbench/WorkbenchPanel/WorkbenchPanelHeader.tsx","../src/components/Workbench/WorkbenchPanel/WorkbenchPanelTitle.tsx","../src/components/Workbench/Workbench.tsx"],"sourcesContent":["export const DEFAULT_WORKBENCH_BAR_HEIGHT_IN_REM = 2.75;\n\nexport const MIN_WORKBENCH_BAR_HEIGHT_IN_REM = 1;\n\nexport const DEFAULT_WORKBENCH_PANEL_HEIGHT_IN_PX = 320;\n\nexport const MIN_WORKBENCH_PANEL_HEIGHT_IN_PX = 120;\n\nexport const WORKBENCH_PANEL_RESIZE_STEP_IN_PX = 24;\n\nexport const WORKBENCH_PANEL_FULL_SCREEN_EXIT_RATIO = 0.8;\n","import { createContext, use } from 'react';\nimport type { Dispatch, SetStateAction } from 'react';\n\n/**\n * Full screen is a mode of the open panel, not a flag beside it — as two booleans the fourth\n * combination (collapsed *and* full screen) is expressible but meaningless.\n */\nexport type WorkbenchState = 'collapsed' | 'expanded' | 'full-screen';\n\ntype WorkbenchActions = {\n expand: () => void;\n collapse: () => void;\n toggleExpanded: () => void;\n enterFullScreen: () => void;\n exitFullScreen: () => void;\n toggleFullScreen: () => void;\n};\n\ntype WorkbenchContextValue = WorkbenchActions & {\n state: WorkbenchState;\n setState: Dispatch<SetStateAction<WorkbenchState>>;\n panelHeight: number;\n setPanelHeight: Dispatch<SetStateAction<number>>;\n isResizing: boolean;\n setIsResizing: (isResizing: boolean) => void;\n};\n\nexport const createWorkbenchActions = (\n setState: Dispatch<SetStateAction<WorkbenchState>>,\n): WorkbenchActions => ({\n // Opening an already-open panel leaves full screen alone.\n expand: () => setState((state) => (state === 'collapsed' ? 'expanded' : state)),\n collapse: () => setState('collapsed'),\n toggleExpanded: () => setState((state) => (state === 'collapsed' ? 'expanded' : 'collapsed')),\n\n enterFullScreen: () => setState('full-screen'),\n // Exiting returns to the open panel, never to a closed one — this is a restore, not a collapse.\n exitFullScreen: () => setState((state) => (state === 'full-screen' ? 'expanded' : state)),\n toggleFullScreen: () =>\n setState((state) => (state === 'full-screen' ? 'expanded' : 'full-screen')),\n});\n\nexport const WorkbenchContext = createContext<WorkbenchContextValue | null>(null);\n\n/**\n * The parts sit at arbitrary depth under `<Workbench>` — a trigger lives inside the panel header,\n * three levels down — so the state travels by context rather than props.\n */\nexport const useWorkbench = (): WorkbenchContextValue => {\n const context = use(WorkbenchContext);\n\n if (context === null) {\n throw new Error('Workbench compound components must be rendered inside <Workbench>.');\n }\n\n return context;\n};\n","import type { ComponentProps } from 'react';\n\nimport { cn } from '../../../utils';\n\ntype Props = ComponentProps<'div'>;\n\nexport const WorkbenchBarEnd = ({ className, ...props }: Props) => (\n <div\n {...props}\n data-slot=\"workbench-bar-end\"\n className={cn(\n // grid placement\n 'tw:col-start-3',\n 'tw:row-start-1',\n\n // layout\n 'tw:flex',\n 'tw:items-center',\n 'tw:justify-end',\n 'tw:gap-2',\n\n className,\n )}\n />\n);\n","import type { ComponentProps } from 'react';\n\nimport { cn } from '../../../utils';\n\ntype Props = ComponentProps<'div'>;\n\nexport const WorkbenchBarMiddle = ({ className, ...props }: Props) => (\n <div\n {...props}\n data-slot=\"workbench-bar-middle\"\n className={cn(\n // grid placement\n 'tw:col-start-2',\n 'tw:row-start-1',\n\n // layout\n 'tw:flex',\n 'tw:items-center',\n 'tw:justify-center',\n 'tw:gap-2',\n\n className,\n )}\n />\n);\n","import type { ComponentProps } from 'react';\n\nimport { cn } from '../../../utils';\n\ntype Props = ComponentProps<'div'>;\n\nexport const WorkbenchBarStart = ({ className, ...props }: Props) => (\n <div\n {...props}\n data-slot=\"workbench-bar-start\"\n className={cn(\n // grid placement\n 'tw:col-start-1',\n 'tw:row-start-1',\n\n // layout\n 'tw:flex',\n 'tw:items-center',\n 'tw:gap-2',\n\n className,\n )}\n />\n);\n","import type { ComponentProps } from 'react';\n\nimport { cn } from '../../../utils';\n\nimport { WorkbenchBarEnd } from './WorkbenchBarEnd';\nimport { WorkbenchBarMiddle } from './WorkbenchBarMiddle';\nimport { WorkbenchBarStart } from './WorkbenchBarStart';\n\ntype Props = ComponentProps<'div'>;\n\nexport const WorkbenchBar = ({ className, children, ...props }: Props) => (\n <div\n className={cn(\n // layout\n 'tw:grid',\n 'tw:grid-cols-[auto_1fr_auto]',\n 'tw:items-center',\n 'tw:gap-x-2',\n\n // sizing\n 'tw:h-(--workbench-bar-height)',\n 'tw:shrink-0',\n 'tw:pointer-events-auto',\n\n // surface\n 'tw:border-t',\n 'tw:border-sidebar-border',\n 'tw:bg-sidebar',\n\n // spacing\n 'tw:px-3',\n\n // typography\n 'tw:text-xs',\n\n className,\n )}\n {...props}\n >\n {children}\n </div>\n);\n\nWorkbenchBar.Start = WorkbenchBarStart;\nWorkbenchBar.Middle = WorkbenchBarMiddle;\nWorkbenchBar.End = WorkbenchBarEnd;\n","import type { ComponentProps, MouseEvent } from 'react';\nimport { Slot } from '@radix-ui/react-slot';\n\nimport { useWorkbench } from './context';\n\ntype Props = ComponentProps<'button'> & {\n asChild?: boolean;\n};\n\nexport const WorkbenchFullScreenTrigger = ({ asChild = false, onClick, ...props }: Props) => {\n const { state, toggleFullScreen } = useWorkbench();\n const isFullScreen = state === 'full-screen';\n const Comp = asChild ? Slot : 'button';\n\n const handleClick = (event: MouseEvent<HTMLButtonElement>) => {\n onClick?.(event);\n\n if (!event.defaultPrevented) {\n toggleFullScreen();\n }\n };\n\n return (\n <Comp\n {...(asChild ? {} : { type: 'button' as const })}\n {...props}\n data-slot=\"workbench-full-screen-trigger\"\n data-state={isFullScreen ? 'on' : 'off'}\n onClick={handleClick}\n />\n );\n};\n","import { useEffect, useRef } from 'react';\nimport type { KeyboardEvent, PointerEvent, RefObject } from 'react';\n\nimport { cn } from '../../../utils';\nimport {\n MIN_WORKBENCH_PANEL_HEIGHT_IN_PX,\n WORKBENCH_PANEL_FULL_SCREEN_EXIT_RATIO,\n WORKBENCH_PANEL_RESIZE_STEP_IN_PX,\n} from '../constants';\nimport { useWorkbench } from '../context';\n\ntype Props = {\n panelRef: RefObject<HTMLDivElement | null>;\n};\n\nconst getMaxHeight = (panel: HTMLDivElement) => {\n const hostTop = panel.offsetParent?.getBoundingClientRect().top ?? 0;\n\n return Math.max(panel.getBoundingClientRect().bottom - hostTop, MIN_WORKBENCH_PANEL_HEIGHT_IN_PX);\n};\n\nconst clampHeight = (height: number, panel: HTMLDivElement) =>\n Math.min(Math.max(height, MIN_WORKBENCH_PANEL_HEIGHT_IN_PX), getMaxHeight(panel));\n\nexport const WorkbenchPanelResizeHandle = ({ panelRef }: Props) => {\n const {\n state,\n panelHeight,\n setPanelHeight,\n isResizing,\n setIsResizing,\n enterFullScreen,\n exitFullScreen,\n } = useWorkbench();\n const grabOffsetRef = useRef(0);\n const previousStateRef = useRef(state);\n const isFullScreenRequestedRef = useRef(state === 'full-screen');\n const enteredFullScreenByDragRef = useRef(false);\n const exitedFullScreenByDragRef = useRef(false);\n\n useEffect(() => {\n if (!isResizing) return;\n\n const { body } = document;\n const { cursor, userSelect } = body.style;\n\n body.style.cursor = 'ns-resize';\n body.style.userSelect = 'none';\n\n return () => {\n body.style.cursor = cursor;\n body.style.userSelect = userSelect;\n };\n }, [isResizing]);\n\n useEffect(() => {\n const previous = previousStateRef.current;\n const panel = panelRef.current;\n\n previousStateRef.current = state;\n isFullScreenRequestedRef.current = state === 'full-screen';\n\n if (previous !== 'full-screen' || state !== 'expanded' || !panel) return;\n\n const draggedIntoFullScreen = enteredFullScreenByDragRef.current;\n const draggedOutOfFullScreen = exitedFullScreenByDragRef.current;\n\n enteredFullScreenByDragRef.current = false;\n exitedFullScreenByDragRef.current = false;\n\n if (!draggedIntoFullScreen || draggedOutOfFullScreen) return;\n\n setPanelHeight(\n clampHeight(getMaxHeight(panel) * WORKBENCH_PANEL_FULL_SCREEN_EXIT_RATIO, panel),\n );\n }, [state, panelRef, setPanelHeight]);\n\n const applyHeight = (height: number, panel: HTMLDivElement) => {\n const isFullScreen = isFullScreenRequestedRef.current;\n\n if (height >= getMaxHeight(panel)) {\n if (!isFullScreen) {\n isFullScreenRequestedRef.current = true;\n enteredFullScreenByDragRef.current = true;\n enterFullScreen();\n }\n\n return;\n }\n\n if (isFullScreen) {\n isFullScreenRequestedRef.current = false;\n exitedFullScreenByDragRef.current = true;\n exitFullScreen();\n }\n\n setPanelHeight(Math.max(height, MIN_WORKBENCH_PANEL_HEIGHT_IN_PX));\n };\n\n const handlePointerDown = (event: PointerEvent<HTMLDivElement>) => {\n const panel = panelRef.current;\n\n if (event.button !== 0 || !panel) return;\n\n event.preventDefault();\n event.currentTarget.setPointerCapture(event.pointerId);\n grabOffsetRef.current = panel.getBoundingClientRect().top - event.clientY;\n setIsResizing(true);\n };\n\n const handlePointerMove = (event: PointerEvent<HTMLDivElement>) => {\n const panel = panelRef.current;\n\n if (!panel || !event.currentTarget.hasPointerCapture(event.pointerId)) return;\n\n const top = event.clientY + grabOffsetRef.current;\n\n applyHeight(panel.getBoundingClientRect().bottom - top, panel);\n };\n\n const handleKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {\n const panel = panelRef.current;\n\n if (!panel) return;\n\n const step = event.shiftKey\n ? WORKBENCH_PANEL_RESIZE_STEP_IN_PX * 4\n : WORKBENCH_PANEL_RESIZE_STEP_IN_PX;\n const delta = event.key === 'ArrowUp' ? step : event.key === 'ArrowDown' ? -step : 0;\n\n if (delta === 0) return;\n\n event.preventDefault();\n applyHeight(\n (isFullScreenRequestedRef.current ? getMaxHeight(panel) : panelHeight) + delta,\n panel,\n );\n };\n\n return (\n <div\n role=\"separator\"\n aria-orientation=\"horizontal\"\n aria-label=\"Resize panel\"\n aria-valuenow={Math.round(panelHeight)}\n aria-valuemin={MIN_WORKBENCH_PANEL_HEIGHT_IN_PX}\n tabIndex={0}\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n onLostPointerCapture={() => setIsResizing(false)}\n onKeyDown={handleKeyDown}\n className={cn(\n // group\n 'tw:group/workbench-resize',\n\n // positioning — the panel is the positioned ancestor\n 'tw:absolute',\n 'tw:inset-x-0',\n 'tw:top-0',\n 'tw:z-10',\n\n // sizing\n 'tw:h-2',\n\n // layout — the whole strip grabs, only the pill shows\n 'tw:flex',\n 'tw:justify-center',\n\n // affordance\n 'tw:cursor-ns-resize',\n 'tw:touch-none',\n\n // focus\n 'tw:outline-none',\n )}\n >\n <span\n className={cn(\n // layout — hangs below the strip so the pill sits clear of the top edge, and\n // grabs there too since the events bubble to the strip\n 'tw:flex',\n 'tw:h-3',\n 'tw:w-16',\n 'tw:items-end',\n 'tw:justify-center',\n )}\n >\n <span\n className={cn(\n // sizing\n 'tw:h-1.5',\n 'tw:w-16',\n\n // surface\n 'tw:rounded-full',\n 'tw:bg-input',\n 'tw:transition-colors',\n 'tw:group-hover/workbench-resize:bg-muted-foreground',\n 'tw:group-focus-visible/workbench-resize:bg-muted-foreground',\n 'tw:group-data-[workbench-resizing=true]/workbench:bg-muted-foreground',\n )}\n />\n </span>\n </div>\n );\n};\n","import { useEffect, useRef } from 'react';\nimport type { ComponentProps, CSSProperties } from 'react';\n\nimport { cn } from '../../../utils';\nimport { Collapsible } from '../../Collapsible';\n\nimport { WorkbenchPanelResizeHandle } from './WorkbenchPanelResizeHandle';\n\ntype Props = ComponentProps<'div'>;\n\nconst clearRadixMeasurementTransitionBlock = (panel: HTMLDivElement | null) => {\n if (panel) panel.style.transitionDuration = '';\n};\n\nexport const WorkbenchPanel = ({ className, children, ...props }: Props) => {\n const panelRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => clearRadixMeasurementTransitionBlock(panelRef.current), []);\n\n return (\n <Collapsible.Content\n ref={panelRef}\n style={{ '--workbench-panel-shadow': '0 -8px 24px -6px rgb(0 0 0 / 0.08)' } as CSSProperties}\n className={cn(\n // positioning — against the host, which must be a positioned element\n 'tw:absolute',\n 'tw:inset-x-0',\n 'tw:bottom-(--workbench-bar-height)',\n 'tw:pointer-events-auto',\n\n // height — the drag-controlled var, capped at the space above the bar so the panel\n // never covers it, whatever height was dragged or restored\n 'tw:h-(--workbench-panel-height)',\n 'tw:max-h-[calc(100%-var(--workbench-bar-height))]',\n 'tw:group-data-[workbench-state=full-screen]/workbench:h-[calc(100%-var(--workbench-bar-height))]',\n\n // height transition\n 'tw:transition-[height]',\n 'tw:duration-200',\n 'tw:ease-out',\n 'tw:group-data-[workbench-resizing=true]/workbench:transition-none',\n\n // surface\n 'tw:border-x',\n 'tw:border-t',\n 'tw:border-border',\n\n // clipping\n 'tw:overflow-hidden',\n\n // raised edge\n 'tw:group-not-data-[workbench-state=full-screen]/workbench:rounded-t-2xl',\n 'tw:group-not-data-[workbench-state=full-screen]/workbench:shadow-(--workbench-panel-shadow)',\n )}\n >\n <WorkbenchPanelResizeHandle panelRef={panelRef} />\n\n <div\n className={cn(\n // layout\n 'tw:flex',\n 'tw:flex-col',\n 'tw:h-full',\n\n // surface\n 'tw:bg-background',\n\n className,\n )}\n {...props}\n >\n {children}\n </div>\n </Collapsible.Content>\n );\n};\n","import type { ComponentProps } from 'react';\nimport { Slot } from '@radix-ui/react-slot';\n\nimport { cn } from '../../../utils';\n\ntype Props = ComponentProps<'div'> & {\n asChild?: boolean;\n};\n\nexport const WorkbenchPanelActions = ({ className, asChild = false, ...props }: Props) => {\n const Comp = asChild ? Slot : 'div';\n\n return (\n <Comp\n {...props}\n data-slot=\"workbench-panel-actions\"\n className={cn(\n // grid placement\n 'tw:col-start-2',\n 'tw:row-start-1',\n\n // layout\n 'tw:flex',\n 'tw:items-center',\n 'tw:gap-2',\n\n className,\n )}\n />\n );\n};\n","import type { ComponentProps } from 'react';\n\nimport { cn } from '../../../utils';\n\ntype Props = ComponentProps<'div'>;\n\nexport const WorkbenchPanelContent = ({ className, children, ...props }: Props) => (\n <div\n className={cn(\n // layout\n 'tw:min-h-0',\n 'tw:flex-1',\n 'tw:overflow-auto',\n\n className,\n )}\n {...props}\n >\n {children}\n </div>\n);\n","import type { ComponentProps } from 'react';\n\nimport { cn } from '../../../utils';\n\ntype Props = ComponentProps<'div'>;\n\nexport const WorkbenchPanelHeader = ({ className, children, ...props }: Props) => (\n <div\n className={cn(\n // layout\n 'tw:grid',\n 'tw:grid-cols-[1fr_auto]',\n 'tw:items-center',\n 'tw:gap-x-2',\n\n // sizing\n 'tw:shrink-0',\n\n // surface\n 'tw:bg-sidebar',\n\n // spacing\n 'tw:px-3',\n 'tw:py-2',\n\n // typography\n 'tw:text-xs',\n\n className,\n )}\n {...props}\n >\n {children}\n </div>\n);\n","import type { ComponentProps } from 'react';\n\nimport { cn } from '../../../utils';\n\ntype Props = ComponentProps<'div'>;\n\nexport const WorkbenchPanelTitle = ({ className, ...props }: Props) => (\n <div\n {...props}\n data-slot=\"workbench-panel-title\"\n className={cn(\n // grid placement\n 'tw:col-start-1',\n\n // layout\n 'tw:flex',\n 'tw:items-center',\n\n // typography\n 'tw:text-sm',\n 'tw:font-semibold',\n 'tw:text-foreground',\n\n className,\n )}\n />\n);\n","import { useMemo, useState } from 'react';\nimport type { CSSProperties, ReactNode } from 'react';\n\nimport { useControllableState } from '../../hooks/useControllableState';\nimport { cn } from '../../utils';\nimport { Collapsible } from '../Collapsible';\n\nimport {\n DEFAULT_WORKBENCH_BAR_HEIGHT_IN_REM,\n DEFAULT_WORKBENCH_PANEL_HEIGHT_IN_PX,\n MIN_WORKBENCH_BAR_HEIGHT_IN_REM,\n MIN_WORKBENCH_PANEL_HEIGHT_IN_PX,\n} from './constants';\nimport type { WorkbenchState } from './context';\nimport { createWorkbenchActions, WorkbenchContext } from './context';\nimport {\n WorkbenchBar,\n WorkbenchBarEnd,\n WorkbenchBarMiddle,\n WorkbenchBarStart,\n} from './WorkbenchBar';\nimport { WorkbenchFullScreenTrigger } from './WorkbenchFullScreenTrigger';\nimport {\n WorkbenchPanel,\n WorkbenchPanelActions,\n WorkbenchPanelContent,\n WorkbenchPanelHeader,\n WorkbenchPanelTitle,\n} from './WorkbenchPanel';\n\ntype Props = {\n className?: string;\n children: ReactNode;\n state?: WorkbenchState;\n defaultState?: WorkbenchState;\n onStateChange?: (state: WorkbenchState) => void;\n barHeight?: number;\n panelHeight?: number;\n defaultPanelHeight?: number;\n onPanelHeightChange?: (panelHeight: number) => void;\n};\n\nexport const Workbench = ({\n className,\n children,\n state: stateProp,\n defaultState = 'collapsed',\n onStateChange,\n barHeight = DEFAULT_WORKBENCH_BAR_HEIGHT_IN_REM,\n panelHeight: panelHeightProp,\n defaultPanelHeight = DEFAULT_WORKBENCH_PANEL_HEIGHT_IN_PX,\n onPanelHeightChange,\n}: Props) => {\n const [state, setState] = useControllableState<WorkbenchState>({\n prop: stateProp,\n defaultProp: defaultState,\n onChange: onStateChange,\n });\n const [panelHeight, setPanelHeight] = useControllableState<number>({\n prop: panelHeightProp,\n defaultProp: defaultPanelHeight,\n onChange: onPanelHeightChange,\n });\n const [isResizing, setIsResizing] = useState(false);\n\n const actions = useMemo(() => createWorkbenchActions(setState), [setState]);\n const value = useMemo(\n () => ({\n state,\n setState,\n panelHeight,\n setPanelHeight,\n isResizing,\n setIsResizing,\n ...actions,\n }),\n [state, setState, panelHeight, setPanelHeight, isResizing, actions],\n );\n\n const clampedBarHeight = Math.max(barHeight, MIN_WORKBENCH_BAR_HEIGHT_IN_REM);\n const clampedPanelHeight = Math.max(panelHeight, MIN_WORKBENCH_PANEL_HEIGHT_IN_PX);\n\n return (\n <WorkbenchContext value={value}>\n <Collapsible\n open={state !== 'collapsed'}\n onOpenChange={(open) => setState(open ? 'expanded' : 'collapsed')}\n data-workbench-state={state}\n data-workbench-resizing={isResizing ? 'true' : undefined}\n style={\n {\n '--workbench-bar-height': `${clampedBarHeight}rem`,\n '--workbench-panel-height': `${clampedPanelHeight}px`,\n } as CSSProperties\n }\n className={cn(\n // reset\n 'tailwindcss-preflight',\n\n // group\n 'tw:group/workbench',\n\n // positioning — above the chrome layer (`z-50`) *and* above a `Sidebar` in\n // `expand-on-hover`, which takes `z-51` to float over content; the dock outranks both.\n // Overlays (Modal / Sheet / Popover / Tooltip) live at 1051+, so they still win.\n 'tw:z-[52]',\n\n // layout\n 'tw:shrink-0',\n\n className,\n )}\n >\n {children}\n </Collapsible>\n </WorkbenchContext>\n );\n};\n\nWorkbench.Bar = WorkbenchBar;\nWorkbench.BarStart = WorkbenchBarStart;\nWorkbench.BarMiddle = WorkbenchBarMiddle;\nWorkbench.BarEnd = WorkbenchBarEnd;\n\nWorkbench.Panel = WorkbenchPanel;\nWorkbench.PanelHeader = WorkbenchPanelHeader;\nWorkbench.PanelTitle = WorkbenchPanelTitle;\nWorkbench.PanelActions = WorkbenchPanelActions;\nWorkbench.PanelContent = WorkbenchPanelContent;\n\nWorkbench.Trigger = Collapsible.Trigger;\nWorkbench.FullScreenTrigger = WorkbenchFullScreenTrigger;\n"],"mappings":"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"}
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
import { cn } from "./classNames-BzrkDnOD.js";
|
|
2
|
+
import { Tooltip } from "./utils-D0c5VAyF.js";
|
|
3
|
+
import { Maximize2, Minimize2 } from "./icons-Cek151jC.js";
|
|
4
|
+
import { Button } from "./Button-nzmDNS2q.js";
|
|
5
|
+
import { ClipboardButton } from "./ClipboardButton-ez5V3fkk.js";
|
|
6
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
7
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
+
import { createPortal } from "react-dom";
|
|
9
|
+
import DOMPurify from "dompurify";
|
|
10
|
+
//#region src/components/ZoomableSvg/ZoomableSvg.tsx
|
|
11
|
+
const MIN_SCALE = .5;
|
|
12
|
+
const MAX_SCALE = 3;
|
|
13
|
+
const ZOOM_STEP = .1;
|
|
14
|
+
const ZoomableSvg = ({ html, copyText, className, allowForeignObject, renderActions }) => {
|
|
15
|
+
const safeHtml = useMemo(() => DOMPurify.sanitize(html, {
|
|
16
|
+
USE_PROFILES: {
|
|
17
|
+
svg: true,
|
|
18
|
+
svgFilters: true
|
|
19
|
+
},
|
|
20
|
+
...allowForeignObject ? { ADD_TAGS: ["foreignObject"] } : {}
|
|
21
|
+
}), [html, allowForeignObject]);
|
|
22
|
+
const containerRef = useRef(null);
|
|
23
|
+
const [scale, setScale] = useState(1);
|
|
24
|
+
const [translate, setTranslate] = useState({
|
|
25
|
+
x: 0,
|
|
26
|
+
y: 0
|
|
27
|
+
});
|
|
28
|
+
const [isFullscreen, setIsFullscreen] = useState(false);
|
|
29
|
+
useEffect(() => {
|
|
30
|
+
if (!isFullscreen) return;
|
|
31
|
+
const onKeyDown = (e) => {
|
|
32
|
+
if (e.key === "Escape") {
|
|
33
|
+
e.stopPropagation();
|
|
34
|
+
setIsFullscreen(false);
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
document.addEventListener("keydown", onKeyDown, { capture: true });
|
|
38
|
+
return () => document.removeEventListener("keydown", onKeyDown, { capture: true });
|
|
39
|
+
}, [isFullscreen]);
|
|
40
|
+
const dragRef = useRef(null);
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
const el = containerRef.current;
|
|
43
|
+
if (!el) return;
|
|
44
|
+
const onWheel = (e) => {
|
|
45
|
+
if (!e.ctrlKey && !e.metaKey) return;
|
|
46
|
+
e.preventDefault();
|
|
47
|
+
const delta = e.deltaY > 0 ? -.1 : ZOOM_STEP;
|
|
48
|
+
setScale((s) => Math.min(MAX_SCALE, Math.max(MIN_SCALE, s + delta)));
|
|
49
|
+
};
|
|
50
|
+
el.addEventListener("wheel", onWheel, { passive: false });
|
|
51
|
+
return () => el.removeEventListener("wheel", onWheel);
|
|
52
|
+
}, [isFullscreen]);
|
|
53
|
+
const didDragRef = useRef(false);
|
|
54
|
+
const handleMouseDown = useCallback((e) => {
|
|
55
|
+
if (e.button !== 0) return;
|
|
56
|
+
e.preventDefault();
|
|
57
|
+
didDragRef.current = false;
|
|
58
|
+
dragRef.current = {
|
|
59
|
+
startX: e.clientX,
|
|
60
|
+
startY: e.clientY,
|
|
61
|
+
startTx: translate.x,
|
|
62
|
+
startTy: translate.y
|
|
63
|
+
};
|
|
64
|
+
}, [translate]);
|
|
65
|
+
const handleMouseMove = useCallback((e) => {
|
|
66
|
+
if (!dragRef.current) return;
|
|
67
|
+
didDragRef.current = true;
|
|
68
|
+
setTranslate({
|
|
69
|
+
x: dragRef.current.startTx + e.clientX - dragRef.current.startX,
|
|
70
|
+
y: dragRef.current.startTy + e.clientY - dragRef.current.startY
|
|
71
|
+
});
|
|
72
|
+
}, []);
|
|
73
|
+
const handleMouseUp = useCallback(() => {
|
|
74
|
+
dragRef.current = null;
|
|
75
|
+
}, []);
|
|
76
|
+
const handleReset = useCallback(() => {
|
|
77
|
+
setScale(1);
|
|
78
|
+
setTranslate({
|
|
79
|
+
x: 0,
|
|
80
|
+
y: 0
|
|
81
|
+
});
|
|
82
|
+
}, []);
|
|
83
|
+
const isZoomed = Math.abs(scale - 1) > .001 || translate.x !== 0 || translate.y !== 0;
|
|
84
|
+
const handleClick = useCallback((e) => {
|
|
85
|
+
if (didDragRef.current) e.stopPropagation();
|
|
86
|
+
}, []);
|
|
87
|
+
const stopPropagation = useCallback((e) => {
|
|
88
|
+
e.stopPropagation();
|
|
89
|
+
}, []);
|
|
90
|
+
const diagramContent = /* @__PURE__ */ jsxs("div", {
|
|
91
|
+
role: "presentation",
|
|
92
|
+
className: cn("tw:group/zoom tw:relative", isFullscreen && "tw:h-full"),
|
|
93
|
+
onClick: handleClick,
|
|
94
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
95
|
+
role: "presentation",
|
|
96
|
+
ref: containerRef,
|
|
97
|
+
className: cn("tw:overflow-hidden tw:cursor-grab tw:active:cursor-grabbing tw:p-3", isFullscreen && "tw:h-full"),
|
|
98
|
+
onMouseDown: handleMouseDown,
|
|
99
|
+
onMouseMove: handleMouseMove,
|
|
100
|
+
onMouseUp: handleMouseUp,
|
|
101
|
+
onMouseLeave: handleMouseUp,
|
|
102
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
103
|
+
className: cn("tw:flex tw:justify-center tw:origin-center", isFullscreen && "tw:h-full tw:[&>svg]:h-full"),
|
|
104
|
+
style: { transform: `translate(${translate.x}px, ${translate.y}px) scale(${scale})` },
|
|
105
|
+
dangerouslySetInnerHTML: { __html: safeHtml }
|
|
106
|
+
})
|
|
107
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
108
|
+
role: "presentation",
|
|
109
|
+
className: "tw:absolute tw:right-1 tw:top-1 tw:flex tw:gap-1 tw:opacity-0 tw:transition-opacity tw:focus-within:opacity-100 tw:group-hover/zoom:opacity-100",
|
|
110
|
+
onClick: stopPropagation,
|
|
111
|
+
children: [
|
|
112
|
+
isZoomed && /* @__PURE__ */ jsx(Tooltip, {
|
|
113
|
+
tooltip: "Reset zoom",
|
|
114
|
+
placement: "top",
|
|
115
|
+
triggerAsChild: true,
|
|
116
|
+
children: /* @__PURE__ */ jsx(Button, {
|
|
117
|
+
size: "small",
|
|
118
|
+
variant: "outline",
|
|
119
|
+
onClick: handleReset,
|
|
120
|
+
children: "Reset"
|
|
121
|
+
})
|
|
122
|
+
}),
|
|
123
|
+
copyText && /* @__PURE__ */ jsx(ClipboardButton, {
|
|
124
|
+
text: copyText,
|
|
125
|
+
tooltip: "Copy code",
|
|
126
|
+
size: "icon-sm",
|
|
127
|
+
variant: "outline"
|
|
128
|
+
}),
|
|
129
|
+
renderActions?.(safeHtml),
|
|
130
|
+
/* @__PURE__ */ jsx(Tooltip, {
|
|
131
|
+
tooltip: isFullscreen ? "Exit fullscreen" : "Fullscreen",
|
|
132
|
+
placement: "top",
|
|
133
|
+
triggerAsChild: true,
|
|
134
|
+
children: /* @__PURE__ */ jsx(Button, {
|
|
135
|
+
size: "icon-sm",
|
|
136
|
+
variant: "outline",
|
|
137
|
+
"aria-label": isFullscreen ? "Exit fullscreen" : "Fullscreen",
|
|
138
|
+
onClick: () => setIsFullscreen((f) => !f),
|
|
139
|
+
children: isFullscreen ? /* @__PURE__ */ jsx(Minimize2, { className: "tw:size-4" }) : /* @__PURE__ */ jsx(Maximize2, { className: "tw:size-4" })
|
|
140
|
+
})
|
|
141
|
+
})
|
|
142
|
+
]
|
|
143
|
+
})]
|
|
144
|
+
});
|
|
145
|
+
if (isFullscreen) return createPortal(/* @__PURE__ */ jsx("div", {
|
|
146
|
+
role: "presentation",
|
|
147
|
+
"data-testid": "zoomable-svg-fullscreen",
|
|
148
|
+
/**
|
|
149
|
+
* Stacking contract for this overlay, which portals to `document.body`.
|
|
150
|
+
*
|
|
151
|
+
* - Sits at z-1051, the Modal/Sheet band: above page chrome.
|
|
152
|
+
* - Stays *below* the floating-panel layer (z-1055: DropdownMenu,
|
|
153
|
+
* Popover, Select, Combobox), which portals to `document.body` too —
|
|
154
|
+
* an overlay above it hides any menu opened from the toolbar.
|
|
155
|
+
* - `Tooltip` (z-1060) renders above, as it does over a Modal.
|
|
156
|
+
* - `SpotlightBackdrop` (z-1056) dims this overlay rather than sitting
|
|
157
|
+
* under it — by design, since it deliberately covers the portalled
|
|
158
|
+
* surface tier so a tour's dim can't be punched through.
|
|
159
|
+
* - An app may clamp poppers into this same band, making it a tie that
|
|
160
|
+
* DOM order settles; Radix mounts its portal after this one.
|
|
161
|
+
*/
|
|
162
|
+
className: "tw:fixed tw:inset-0 tw:z-[1051] tw:bg-muted tw:p-4 tailwindcss-preflight",
|
|
163
|
+
onClick: stopPropagation,
|
|
164
|
+
children: diagramContent
|
|
165
|
+
}), document.body);
|
|
166
|
+
return /* @__PURE__ */ jsx("div", {
|
|
167
|
+
className: cn("tw:overflow-hidden tw:rounded-md tw:border tw:border-border tw:bg-muted", className),
|
|
168
|
+
children: diagramContent
|
|
169
|
+
});
|
|
170
|
+
};
|
|
171
|
+
//#endregion
|
|
172
|
+
//#region src/components/ZoomableSvg/exportSvg.ts
|
|
173
|
+
const PNG_SCALE = 2;
|
|
174
|
+
const ROOT_SVG_TAG = /^<svg\b[^>]*>/i;
|
|
175
|
+
const HAS_DEFAULT_NAMESPACE = /\bxmlns\s*=/i;
|
|
176
|
+
const withSvgNamespace = (svg) => {
|
|
177
|
+
const trimmed = svg.trim();
|
|
178
|
+
const rootTag = trimmed.match(ROOT_SVG_TAG)?.[0];
|
|
179
|
+
if (!rootTag || HAS_DEFAULT_NAMESPACE.test(rootTag)) return trimmed;
|
|
180
|
+
return trimmed.replace(/^<svg\b/i, "<svg xmlns=\"http://www.w3.org/2000/svg\"");
|
|
181
|
+
};
|
|
182
|
+
const toSvgFileContent = (svg) => `<?xml version="1.0" encoding="UTF-8"?>\n${withSvgNamespace(svg).trim()}\n`;
|
|
183
|
+
const NUMBER = String.raw`\d+(?:\.\d+)?|\.\d+`;
|
|
184
|
+
const PIXEL_LENGTH = new RegExp(String.raw`^\s*(?:${NUMBER})(?:px)?\s*$`, "i");
|
|
185
|
+
const parsePixelLength = (value) => {
|
|
186
|
+
if (!PIXEL_LENGTH.test(value ?? "")) return null;
|
|
187
|
+
const parsed = Number.parseFloat(value ?? "");
|
|
188
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : null;
|
|
189
|
+
};
|
|
190
|
+
const parseSvgSize = (svg) => {
|
|
191
|
+
const element = new DOMParser().parseFromString(withSvgNamespace(svg), "image/svg+xml").documentElement;
|
|
192
|
+
const viewBox = element.getAttribute("viewBox")?.split(/[\s,]+/).map(Number);
|
|
193
|
+
if (viewBox?.length === 4 && viewBox.every((value) => Number.isFinite(value))) {
|
|
194
|
+
const [, , width, height] = viewBox;
|
|
195
|
+
if (width !== void 0 && height !== void 0 && width > 0 && height > 0) return {
|
|
196
|
+
width,
|
|
197
|
+
height
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
const width = parsePixelLength(element.getAttribute("width"));
|
|
201
|
+
const height = parsePixelLength(element.getAttribute("height"));
|
|
202
|
+
return width !== null && height !== null ? {
|
|
203
|
+
width,
|
|
204
|
+
height
|
|
205
|
+
} : null;
|
|
206
|
+
};
|
|
207
|
+
const CHANNEL_TRIPLET = new RegExp(String.raw`^(?:${NUMBER})\s+(?:${NUMBER})\s+(?:${NUMBER})$`);
|
|
208
|
+
const toCanvasColor = (token) => {
|
|
209
|
+
const trimmed = token.trim();
|
|
210
|
+
if (!trimmed) return "white";
|
|
211
|
+
return CHANNEL_TRIPLET.test(trimmed) ? `rgb(${trimmed})` : trimmed;
|
|
212
|
+
};
|
|
213
|
+
const resolveBackground = () => toCanvasColor(getComputedStyle(document.documentElement).getPropertyValue("--color-background"));
|
|
214
|
+
/**
|
|
215
|
+
* Rasterize SVG markup to a PNG blob at 2x for legible text.
|
|
216
|
+
*
|
|
217
|
+
* The SVG is loaded as a data URL rather than a blob URL: an <img> loading SVG
|
|
218
|
+
* is treated as a foreign resource, so a blob URL would taint the canvas and
|
|
219
|
+
* make toBlob throw a SecurityError. A background is painted first because a
|
|
220
|
+
* transparent PNG reads as unusable when pasted into a slide deck.
|
|
221
|
+
*/
|
|
222
|
+
const svgToPngBlob = async (svg, background) => {
|
|
223
|
+
const size = parseSvgSize(svg);
|
|
224
|
+
if (!size) throw new Error("Cannot determine diagram dimensions.");
|
|
225
|
+
const encoded = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(toSvgFileContent(svg))}`;
|
|
226
|
+
const image = new Image();
|
|
227
|
+
image.decoding = "sync";
|
|
228
|
+
await new Promise((resolve, reject) => {
|
|
229
|
+
image.onload = () => resolve();
|
|
230
|
+
image.onerror = () => reject(/* @__PURE__ */ new Error("Failed to load the diagram for export."));
|
|
231
|
+
image.src = encoded;
|
|
232
|
+
});
|
|
233
|
+
const canvas = document.createElement("canvas");
|
|
234
|
+
canvas.width = Math.round(size.width * PNG_SCALE);
|
|
235
|
+
canvas.height = Math.round(size.height * PNG_SCALE);
|
|
236
|
+
const context = canvas.getContext("2d");
|
|
237
|
+
if (!context) throw new Error("Canvas is unavailable in this browser.");
|
|
238
|
+
context.fillStyle = background ?? resolveBackground();
|
|
239
|
+
context.fillRect(0, 0, canvas.width, canvas.height);
|
|
240
|
+
context.drawImage(image, 0, 0, canvas.width, canvas.height);
|
|
241
|
+
return new Promise((resolve, reject) => {
|
|
242
|
+
canvas.toBlob((blob) => blob ? resolve(blob) : reject(/* @__PURE__ */ new Error("Failed to encode the PNG.")), "image/png");
|
|
243
|
+
});
|
|
244
|
+
};
|
|
245
|
+
//#endregion
|
|
246
|
+
export { ZoomableSvg, svgToPngBlob, toSvgFileContent };
|
|
247
|
+
|
|
248
|
+
//# sourceMappingURL=ZoomableSvg-DG9PnAm8.js.map
|