@terra-symposium/docs 0.0.0-stage → 0.1.71
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 +201 -0
- package/README.md +72 -2
- package/lib-dist/assets/fonts/AUTHENTICSans-130.woff +0 -0
- package/lib-dist/assets/fonts/AUTHENTICSans-130.woff2 +0 -0
- package/lib-dist/assets/fonts/AUTHENTICSans-150.woff +0 -0
- package/lib-dist/assets/fonts/AUTHENTICSans-150.woff2 +0 -0
- package/lib-dist/assets/fonts/AUTHENTICSans-90.woff +0 -0
- package/lib-dist/assets/fonts/AUTHENTICSans-90.woff2 +0 -0
- package/lib-dist/assets/fonts/Avara-Bold.woff +0 -0
- package/lib-dist/assets/fonts/Avara-Bold.woff2 +0 -0
- package/lib-dist/assets/fonts/Avara-BoldItalic.woff +0 -0
- package/lib-dist/assets/fonts/Avara-BoldItalic.woff2 +0 -0
- package/lib-dist/assets/fonts/InterVariable-Italic-latin-20260728.woff2 +0 -0
- package/lib-dist/assets/fonts/InterVariable-latin-20260728.woff2 +0 -0
- package/lib-dist/assets/fonts/OFL-1.1.txt +93 -0
- package/lib-dist/assets/fonts/README.md +7 -0
- package/lib-dist/assets/fonts/licenses/Inter-OFL-1.1.txt +92 -0
- package/lib-dist/assets/fonts/licenses/OFL-1.1.txt +93 -0
- package/lib-dist/components/Docs.d.ts +22 -0
- package/lib-dist/components/Docs.d.ts.map +1 -0
- package/lib-dist/components/Docs.js +9 -0
- package/lib-dist/components/Docs.js.map +1 -0
- package/lib-dist/components/LocalDocsWorkspace.d.ts +37 -0
- package/lib-dist/components/LocalDocsWorkspace.d.ts.map +1 -0
- package/lib-dist/components/LocalDocsWorkspace.js +207 -0
- package/lib-dist/components/LocalDocsWorkspace.js.map +1 -0
- package/lib-dist/components/NotFound.d.ts +8 -0
- package/lib-dist/components/NotFound.d.ts.map +1 -0
- package/lib-dist/components/NotFound.js +6 -0
- package/lib-dist/components/NotFound.js.map +1 -0
- package/lib-dist/components/SiteLayout.d.ts +25 -0
- package/lib-dist/components/SiteLayout.d.ts.map +1 -0
- package/lib-dist/components/SiteLayout.js +12 -0
- package/lib-dist/components/SiteLayout.js.map +1 -0
- package/lib-dist/components/StaticWorkspace.d.ts +25 -0
- package/lib-dist/components/StaticWorkspace.d.ts.map +1 -0
- package/lib-dist/components/StaticWorkspace.js +245 -0
- package/lib-dist/components/StaticWorkspace.js.map +1 -0
- package/lib-dist/components/StrictLocalWorkspaceHarness.d.ts +10 -0
- package/lib-dist/components/StrictLocalWorkspaceHarness.d.ts.map +1 -0
- package/lib-dist/components/StrictLocalWorkspaceHarness.js +12 -0
- package/lib-dist/components/StrictLocalWorkspaceHarness.js.map +1 -0
- package/lib-dist/components/blocks.d.ts +23 -0
- package/lib-dist/components/blocks.d.ts.map +1 -0
- package/lib-dist/components/blocks.js +396 -0
- package/lib-dist/components/blocks.js.map +1 -0
- package/lib-dist/components/navigation.d.ts +18 -0
- package/lib-dist/components/navigation.d.ts.map +1 -0
- package/lib-dist/components/navigation.js +9 -0
- package/lib-dist/components/navigation.js.map +1 -0
- package/lib-dist/components/terra/Workspace.d.ts +5 -0
- package/lib-dist/components/terra/Workspace.d.ts.map +1 -0
- package/lib-dist/components/terra/Workspace.js +190 -0
- package/lib-dist/components/terra/Workspace.js.map +1 -0
- package/lib-dist/components/terra/editor/TerraContentEditor.d.ts +15 -0
- package/lib-dist/components/terra/editor/TerraContentEditor.d.ts.map +1 -0
- package/lib-dist/components/terra/editor/TerraContentEditor.js +358 -0
- package/lib-dist/components/terra/editor/TerraContentEditor.js.map +1 -0
- package/lib-dist/components/terra/editor/_blocks.d.ts +70 -0
- package/lib-dist/components/terra/editor/_blocks.d.ts.map +1 -0
- package/lib-dist/components/terra/editor/_blocks.js +120 -0
- package/lib-dist/components/terra/editor/_blocks.js.map +1 -0
- package/lib-dist/components/terra/editor/docs/BlockContext.d.ts +7 -0
- package/lib-dist/components/terra/editor/docs/BlockContext.d.ts.map +1 -0
- package/lib-dist/components/terra/editor/docs/BlockContext.js +60 -0
- package/lib-dist/components/terra/editor/docs/BlockContext.js.map +1 -0
- package/lib-dist/components/terra/editor/docs/DocsAttachmentPicker.d.ts +12 -0
- package/lib-dist/components/terra/editor/docs/DocsAttachmentPicker.d.ts.map +1 -0
- package/lib-dist/components/terra/editor/docs/DocsAttachmentPicker.js +66 -0
- package/lib-dist/components/terra/editor/docs/DocsAttachmentPicker.js.map +1 -0
- package/lib-dist/components/terra/editor/docs/TerraToolbar.d.ts +12 -0
- package/lib-dist/components/terra/editor/docs/TerraToolbar.d.ts.map +1 -0
- package/lib-dist/components/terra/editor/docs/TerraToolbar.js +169 -0
- package/lib-dist/components/terra/editor/docs/TerraToolbar.js.map +1 -0
- package/lib-dist/components/terra/editor/docs/_Callout.d.ts +14 -0
- package/lib-dist/components/terra/editor/docs/_Callout.d.ts.map +1 -0
- package/lib-dist/components/terra/editor/docs/_Callout.js +45 -0
- package/lib-dist/components/terra/editor/docs/_Callout.js.map +1 -0
- package/lib-dist/components/terra/editor/docs/_CodeBlock.d.ts +39 -0
- package/lib-dist/components/terra/editor/docs/_CodeBlock.d.ts.map +1 -0
- package/lib-dist/components/terra/editor/docs/_CodeBlock.js +560 -0
- package/lib-dist/components/terra/editor/docs/_CodeBlock.js.map +1 -0
- package/lib-dist/components/terra/editor/docs/_DocsCode.d.ts +14 -0
- package/lib-dist/components/terra/editor/docs/_DocsCode.d.ts.map +1 -0
- package/lib-dist/components/terra/editor/docs/_DocsCode.js +128 -0
- package/lib-dist/components/terra/editor/docs/_DocsCode.js.map +1 -0
- package/lib-dist/components/terra/editor/docs/_DocsImage.d.ts +18 -0
- package/lib-dist/components/terra/editor/docs/_DocsImage.d.ts.map +1 -0
- package/lib-dist/components/terra/editor/docs/_DocsImage.js +62 -0
- package/lib-dist/components/terra/editor/docs/_DocsImage.js.map +1 -0
- package/lib-dist/components/terra/editor/docs/_Embed.d.ts +17 -0
- package/lib-dist/components/terra/editor/docs/_Embed.d.ts.map +1 -0
- package/lib-dist/components/terra/editor/docs/_Embed.js +73 -0
- package/lib-dist/components/terra/editor/docs/_Embed.js.map +1 -0
- package/lib-dist/components/terra/editor/docs/_Math.d.ts +31 -0
- package/lib-dist/components/terra/editor/docs/_Math.d.ts.map +1 -0
- package/lib-dist/components/terra/editor/docs/_Math.js +138 -0
- package/lib-dist/components/terra/editor/docs/_Math.js.map +1 -0
- package/lib-dist/components/terra/editor/docs/_Nodes.d.ts +15 -0
- package/lib-dist/components/terra/editor/docs/_Nodes.d.ts.map +1 -0
- package/lib-dist/components/terra/editor/docs/_Nodes.js +62 -0
- package/lib-dist/components/terra/editor/docs/_Nodes.js.map +1 -0
- package/lib-dist/components/terra/editor/docs/_Raw.d.ts +15 -0
- package/lib-dist/components/terra/editor/docs/_Raw.d.ts.map +1 -0
- package/lib-dist/components/terra/editor/docs/_Raw.js +31 -0
- package/lib-dist/components/terra/editor/docs/_Raw.js.map +1 -0
- package/lib-dist/components/terra/editor/docs/_Table.d.ts +12 -0
- package/lib-dist/components/terra/editor/docs/_Table.d.ts.map +1 -0
- package/lib-dist/components/terra/editor/docs/_Table.js +99 -0
- package/lib-dist/components/terra/editor/docs/_Table.js.map +1 -0
- package/lib-dist/components/terra/editor/docs/_Tabs.d.ts +14 -0
- package/lib-dist/components/terra/editor/docs/_Tabs.d.ts.map +1 -0
- package/lib-dist/components/terra/editor/docs/_Tabs.js +125 -0
- package/lib-dist/components/terra/editor/docs/_Tabs.js.map +1 -0
- package/lib-dist/components/terra/editor/docs/_TsDocs.d.ts +15 -0
- package/lib-dist/components/terra/editor/docs/_TsDocs.d.ts.map +1 -0
- package/lib-dist/components/terra/editor/docs/_TsDocs.js +83 -0
- package/lib-dist/components/terra/editor/docs/_TsDocs.js.map +1 -0
- package/lib-dist/components/terra/editor/docs/_math_inline.d.ts +14 -0
- package/lib-dist/components/terra/editor/docs/_math_inline.d.ts.map +1 -0
- package/lib-dist/components/terra/editor/docs/_math_inline.js +30 -0
- package/lib-dist/components/terra/editor/docs/_math_inline.js.map +1 -0
- package/lib-dist/components/terra/editor/docs/heading.d.ts +23 -0
- package/lib-dist/components/terra/editor/docs/heading.d.ts.map +1 -0
- package/lib-dist/components/terra/editor/docs/heading.js +63 -0
- package/lib-dist/components/terra/editor/docs/heading.js.map +1 -0
- package/lib-dist/components/terra/editor/docs/index.d.ts +13 -0
- package/lib-dist/components/terra/editor/docs/index.d.ts.map +1 -0
- package/lib-dist/components/terra/editor/docs/index.js +14 -0
- package/lib-dist/components/terra/editor/docs/index.js.map +1 -0
- package/lib-dist/components/terra/editor/terra-content.styles.d.ts +3 -0
- package/lib-dist/components/terra/editor/terra-content.styles.d.ts.map +1 -0
- package/lib-dist/components/terra/editor/terra-content.styles.js +3 -0
- package/lib-dist/components/terra/editor/terra-content.styles.js.map +1 -0
- package/lib-dist/components/terra/editor/types.d.ts +40 -0
- package/lib-dist/components/terra/editor/types.d.ts.map +1 -0
- package/lib-dist/components/terra/editor/types.js +11 -0
- package/lib-dist/components/terra/editor/types.js.map +1 -0
- package/lib-dist/components/terra/flow/Nodes.d.ts +78 -0
- package/lib-dist/components/terra/flow/Nodes.d.ts.map +1 -0
- package/lib-dist/components/terra/flow/Nodes.js +1019 -0
- package/lib-dist/components/terra/flow/Nodes.js.map +1 -0
- package/lib-dist/components/terra/flow/_chrome.d.ts +267 -0
- package/lib-dist/components/terra/flow/_chrome.d.ts.map +1 -0
- package/lib-dist/components/terra/flow/_chrome.js +1009 -0
- package/lib-dist/components/terra/flow/_chrome.js.map +1 -0
- package/lib-dist/components/terra/flow/menuContext.d.ts +13 -0
- package/lib-dist/components/terra/flow/menuContext.d.ts.map +1 -0
- package/lib-dist/components/terra/flow/menuContext.js +10 -0
- package/lib-dist/components/terra/flow/menuContext.js.map +1 -0
- package/lib-dist/components/terra/pages/docs/_attachments.d.ts +20 -0
- package/lib-dist/components/terra/pages/docs/_attachments.d.ts.map +1 -0
- package/lib-dist/components/terra/pages/docs/_attachments.js +1148 -0
- package/lib-dist/components/terra/pages/docs/_attachments.js.map +1 -0
- package/lib-dist/components/terra/pages/docs/_blocks.d.ts +48 -0
- package/lib-dist/components/terra/pages/docs/_blocks.d.ts.map +1 -0
- package/lib-dist/components/terra/pages/docs/_blocks.js +203 -0
- package/lib-dist/components/terra/pages/docs/_blocks.js.map +1 -0
- package/lib-dist/components/terra/pages/docs/_editable.d.ts +61 -0
- package/lib-dist/components/terra/pages/docs/_editable.d.ts.map +1 -0
- package/lib-dist/components/terra/pages/docs/_editable.js +442 -0
- package/lib-dist/components/terra/pages/docs/_editable.js.map +1 -0
- package/lib-dist/components/terra/pages/docs/_export-dialog.d.ts +19 -0
- package/lib-dist/components/terra/pages/docs/_export-dialog.d.ts.map +1 -0
- package/lib-dist/components/terra/pages/docs/_export-dialog.js +78 -0
- package/lib-dist/components/terra/pages/docs/_export-dialog.js.map +1 -0
- package/lib-dist/components/terra/pages/docs/_icons.d.ts +20 -0
- package/lib-dist/components/terra/pages/docs/_icons.d.ts.map +1 -0
- package/lib-dist/components/terra/pages/docs/_icons.js +29 -0
- package/lib-dist/components/terra/pages/docs/_icons.js.map +1 -0
- package/lib-dist/components/terra/pages/docs/_main.d.ts +54 -0
- package/lib-dist/components/terra/pages/docs/_main.d.ts.map +1 -0
- package/lib-dist/components/terra/pages/docs/_main.js +710 -0
- package/lib-dist/components/terra/pages/docs/_main.js.map +1 -0
- package/lib-dist/components/terra/pages/docs/_manage-attachments-dialog.d.ts +10 -0
- package/lib-dist/components/terra/pages/docs/_manage-attachments-dialog.d.ts.map +1 -0
- package/lib-dist/components/terra/pages/docs/_manage-attachments-dialog.js +597 -0
- package/lib-dist/components/terra/pages/docs/_manage-attachments-dialog.js.map +1 -0
- package/lib-dist/components/terra/pages/docs/_sidebar.d.ts +33 -0
- package/lib-dist/components/terra/pages/docs/_sidebar.d.ts.map +1 -0
- package/lib-dist/components/terra/pages/docs/_sidebar.js +1437 -0
- package/lib-dist/components/terra/pages/docs/_sidebar.js.map +1 -0
- package/lib-dist/components/terra/pages/docs/_toc.d.ts +4 -0
- package/lib-dist/components/terra/pages/docs/_toc.d.ts.map +1 -0
- package/lib-dist/components/terra/pages/docs/_toc.js +212 -0
- package/lib-dist/components/terra/pages/docs/_toc.js.map +1 -0
- package/lib-dist/components/terra/pages/docs/_toolbar-find-replace.d.ts +15 -0
- package/lib-dist/components/terra/pages/docs/_toolbar-find-replace.d.ts.map +1 -0
- package/lib-dist/components/terra/pages/docs/_toolbar-find-replace.js +207 -0
- package/lib-dist/components/terra/pages/docs/_toolbar-find-replace.js.map +1 -0
- package/lib-dist/components/terra/pages/docs/_toolbar.d.ts +22 -0
- package/lib-dist/components/terra/pages/docs/_toolbar.d.ts.map +1 -0
- package/lib-dist/components/terra/pages/docs/_toolbar.js +1508 -0
- package/lib-dist/components/terra/pages/docs/_toolbar.js.map +1 -0
- package/lib-dist/components/terra/pages/docs/_tree.d.ts +178 -0
- package/lib-dist/components/terra/pages/docs/_tree.d.ts.map +1 -0
- package/lib-dist/components/terra/pages/docs/_tree.js +1123 -0
- package/lib-dist/components/terra/pages/docs/_tree.js.map +1 -0
- package/lib-dist/components/terra/pages/docs/use-block-nav.d.ts +5 -0
- package/lib-dist/components/terra/pages/docs/use-block-nav.d.ts.map +1 -0
- package/lib-dist/components/terra/pages/docs/use-block-nav.js +1306 -0
- package/lib-dist/components/terra/pages/docs/use-block-nav.js.map +1 -0
- package/lib-dist/components/terra/pages/docs/use-media-paste.d.ts +5 -0
- package/lib-dist/components/terra/pages/docs/use-media-paste.d.ts.map +1 -0
- package/lib-dist/components/terra/pages/docs/use-media-paste.js +391 -0
- package/lib-dist/components/terra/pages/docs/use-media-paste.js.map +1 -0
- package/lib-dist/components/terra/pages/docs/use-render-tripwire.d.ts +2 -0
- package/lib-dist/components/terra/pages/docs/use-render-tripwire.d.ts.map +1 -0
- package/lib-dist/components/terra/pages/docs/use-render-tripwire.js +25 -0
- package/lib-dist/components/terra/pages/docs/use-render-tripwire.js.map +1 -0
- package/lib-dist/components/terra/ui.d.ts +28 -0
- package/lib-dist/components/terra/ui.d.ts.map +1 -0
- package/lib-dist/components/terra/ui.js +20 -0
- package/lib-dist/components/terra/ui.js.map +1 -0
- package/lib-dist/components/workspace-demo-fixture.d.ts +35 -0
- package/lib-dist/components/workspace-demo-fixture.d.ts.map +1 -0
- package/lib-dist/components/workspace-demo-fixture.js +820 -0
- package/lib-dist/components/workspace-demo-fixture.js.map +1 -0
- package/lib-dist/fonts/KaTeX_AMS-Regular.ttf +0 -0
- package/lib-dist/fonts/KaTeX_AMS-Regular.woff +0 -0
- package/lib-dist/fonts/KaTeX_AMS-Regular.woff2 +0 -0
- package/lib-dist/fonts/KaTeX_Caligraphic-Bold.ttf +0 -0
- package/lib-dist/fonts/KaTeX_Caligraphic-Bold.woff +0 -0
- package/lib-dist/fonts/KaTeX_Caligraphic-Bold.woff2 +0 -0
- package/lib-dist/fonts/KaTeX_Caligraphic-Regular.ttf +0 -0
- package/lib-dist/fonts/KaTeX_Caligraphic-Regular.woff +0 -0
- package/lib-dist/fonts/KaTeX_Caligraphic-Regular.woff2 +0 -0
- package/lib-dist/fonts/KaTeX_Fraktur-Bold.ttf +0 -0
- package/lib-dist/fonts/KaTeX_Fraktur-Bold.woff +0 -0
- package/lib-dist/fonts/KaTeX_Fraktur-Bold.woff2 +0 -0
- package/lib-dist/fonts/KaTeX_Fraktur-Regular.ttf +0 -0
- package/lib-dist/fonts/KaTeX_Fraktur-Regular.woff +0 -0
- package/lib-dist/fonts/KaTeX_Fraktur-Regular.woff2 +0 -0
- package/lib-dist/fonts/KaTeX_Main-Bold.ttf +0 -0
- package/lib-dist/fonts/KaTeX_Main-Bold.woff +0 -0
- package/lib-dist/fonts/KaTeX_Main-Bold.woff2 +0 -0
- package/lib-dist/fonts/KaTeX_Main-BoldItalic.ttf +0 -0
- package/lib-dist/fonts/KaTeX_Main-BoldItalic.woff +0 -0
- package/lib-dist/fonts/KaTeX_Main-BoldItalic.woff2 +0 -0
- package/lib-dist/fonts/KaTeX_Main-Italic.ttf +0 -0
- package/lib-dist/fonts/KaTeX_Main-Italic.woff +0 -0
- package/lib-dist/fonts/KaTeX_Main-Italic.woff2 +0 -0
- package/lib-dist/fonts/KaTeX_Main-Regular.ttf +0 -0
- package/lib-dist/fonts/KaTeX_Main-Regular.woff +0 -0
- package/lib-dist/fonts/KaTeX_Main-Regular.woff2 +0 -0
- package/lib-dist/fonts/KaTeX_Math-BoldItalic.ttf +0 -0
- package/lib-dist/fonts/KaTeX_Math-BoldItalic.woff +0 -0
- package/lib-dist/fonts/KaTeX_Math-BoldItalic.woff2 +0 -0
- package/lib-dist/fonts/KaTeX_Math-Italic.ttf +0 -0
- package/lib-dist/fonts/KaTeX_Math-Italic.woff +0 -0
- package/lib-dist/fonts/KaTeX_Math-Italic.woff2 +0 -0
- package/lib-dist/fonts/KaTeX_SansSerif-Bold.ttf +0 -0
- package/lib-dist/fonts/KaTeX_SansSerif-Bold.woff +0 -0
- package/lib-dist/fonts/KaTeX_SansSerif-Bold.woff2 +0 -0
- package/lib-dist/fonts/KaTeX_SansSerif-Italic.ttf +0 -0
- package/lib-dist/fonts/KaTeX_SansSerif-Italic.woff +0 -0
- package/lib-dist/fonts/KaTeX_SansSerif-Italic.woff2 +0 -0
- package/lib-dist/fonts/KaTeX_SansSerif-Regular.ttf +0 -0
- package/lib-dist/fonts/KaTeX_SansSerif-Regular.woff +0 -0
- package/lib-dist/fonts/KaTeX_SansSerif-Regular.woff2 +0 -0
- package/lib-dist/fonts/KaTeX_Script-Regular.ttf +0 -0
- package/lib-dist/fonts/KaTeX_Script-Regular.woff +0 -0
- package/lib-dist/fonts/KaTeX_Script-Regular.woff2 +0 -0
- package/lib-dist/fonts/KaTeX_Size1-Regular.ttf +0 -0
- package/lib-dist/fonts/KaTeX_Size1-Regular.woff +0 -0
- package/lib-dist/fonts/KaTeX_Size1-Regular.woff2 +0 -0
- package/lib-dist/fonts/KaTeX_Size2-Regular.ttf +0 -0
- package/lib-dist/fonts/KaTeX_Size2-Regular.woff +0 -0
- package/lib-dist/fonts/KaTeX_Size2-Regular.woff2 +0 -0
- package/lib-dist/fonts/KaTeX_Size3-Regular.ttf +0 -0
- package/lib-dist/fonts/KaTeX_Size3-Regular.woff +0 -0
- package/lib-dist/fonts/KaTeX_Size3-Regular.woff2 +0 -0
- package/lib-dist/fonts/KaTeX_Size4-Regular.ttf +0 -0
- package/lib-dist/fonts/KaTeX_Size4-Regular.woff +0 -0
- package/lib-dist/fonts/KaTeX_Size4-Regular.woff2 +0 -0
- package/lib-dist/fonts/KaTeX_Typewriter-Regular.ttf +0 -0
- package/lib-dist/fonts/KaTeX_Typewriter-Regular.woff +0 -0
- package/lib-dist/fonts/KaTeX_Typewriter-Regular.woff2 +0 -0
- package/lib-dist/lib/astro.d.ts +8 -0
- package/lib-dist/lib/astro.d.ts.map +1 -0
- package/lib-dist/lib/astro.js +27 -0
- package/lib-dist/lib/astro.js.map +1 -0
- package/lib-dist/lib/docs-catalog.d.ts +5 -0
- package/lib-dist/lib/docs-catalog.d.ts.map +1 -0
- package/lib-dist/lib/docs-catalog.js +75 -0
- package/lib-dist/lib/docs-catalog.js.map +1 -0
- package/lib-dist/lib/docs-theme.d.ts +7 -0
- package/lib-dist/lib/docs-theme.d.ts.map +1 -0
- package/lib-dist/lib/docs-theme.js +51 -0
- package/lib-dist/lib/docs-theme.js.map +1 -0
- package/lib-dist/lib/host-runtime.d.ts +5 -0
- package/lib-dist/lib/host-runtime.d.ts.map +1 -0
- package/lib-dist/lib/host-runtime.js +23 -0
- package/lib-dist/lib/host-runtime.js.map +1 -0
- package/lib-dist/lib/host.d.ts +190 -0
- package/lib-dist/lib/host.d.ts.map +1 -0
- package/lib-dist/lib/host.js +2 -0
- package/lib-dist/lib/host.js.map +1 -0
- package/lib-dist/lib/index.d.ts +34 -0
- package/lib-dist/lib/index.d.ts.map +1 -0
- package/lib-dist/lib/index.js +27 -0
- package/lib-dist/lib/index.js.map +1 -0
- package/lib-dist/lib/markdown-model.d.ts +7 -0
- package/lib-dist/lib/markdown-model.d.ts.map +1 -0
- package/lib-dist/lib/markdown-model.js +2031 -0
- package/lib-dist/lib/markdown-model.js.map +1 -0
- package/lib-dist/lib/markdown.d.ts +3 -0
- package/lib-dist/lib/markdown.d.ts.map +1 -0
- package/lib-dist/lib/markdown.js +222 -0
- package/lib-dist/lib/markdown.js.map +1 -0
- package/lib-dist/lib/schema.d.ts +167 -0
- package/lib-dist/lib/schema.d.ts.map +1 -0
- package/lib-dist/lib/schema.js +63 -0
- package/lib-dist/lib/schema.js.map +1 -0
- package/lib-dist/lib/terra/custom-components.d.ts +5 -0
- package/lib-dist/lib/terra/custom-components.d.ts.map +1 -0
- package/lib-dist/lib/terra/custom-components.js +6 -0
- package/lib-dist/lib/terra/custom-components.js.map +1 -0
- package/lib-dist/lib/terra/docs/archive.d.ts +3 -0
- package/lib-dist/lib/terra/docs/archive.d.ts.map +1 -0
- package/lib-dist/lib/terra/docs/archive.js +654 -0
- package/lib-dist/lib/terra/docs/archive.js.map +1 -0
- package/lib-dist/lib/terra/docs/assets.d.ts +26 -0
- package/lib-dist/lib/terra/docs/assets.d.ts.map +1 -0
- package/lib-dist/lib/terra/docs/assets.js +74 -0
- package/lib-dist/lib/terra/docs/assets.js.map +1 -0
- package/lib-dist/lib/terra/docs/attachments.d.ts +4 -0
- package/lib-dist/lib/terra/docs/attachments.d.ts.map +1 -0
- package/lib-dist/lib/terra/docs/attachments.js +5 -0
- package/lib-dist/lib/terra/docs/attachments.js.map +1 -0
- package/lib-dist/lib/terra/docs/editor-dom.d.ts +50 -0
- package/lib-dist/lib/terra/docs/editor-dom.d.ts.map +1 -0
- package/lib-dist/lib/terra/docs/editor-dom.js +236 -0
- package/lib-dist/lib/terra/docs/editor-dom.js.map +1 -0
- package/lib-dist/lib/terra/docs/mutations.d.ts +10 -0
- package/lib-dist/lib/terra/docs/mutations.d.ts.map +1 -0
- package/lib-dist/lib/terra/docs/mutations.js +105 -0
- package/lib-dist/lib/terra/docs/mutations.js.map +1 -0
- package/lib-dist/lib/terra/docs/navigation.d.ts +6 -0
- package/lib-dist/lib/terra/docs/navigation.d.ts.map +1 -0
- package/lib-dist/lib/terra/docs/navigation.js +21 -0
- package/lib-dist/lib/terra/docs/navigation.js.map +1 -0
- package/lib-dist/lib/terra/docs/state.d.ts +186 -0
- package/lib-dist/lib/terra/docs/state.d.ts.map +1 -0
- package/lib-dist/lib/terra/docs/state.js +255 -0
- package/lib-dist/lib/terra/docs/state.js.map +1 -0
- package/lib-dist/lib/terra/docs/toolbar.d.ts +11 -0
- package/lib-dist/lib/terra/docs/toolbar.d.ts.map +1 -0
- package/lib-dist/lib/terra/docs/toolbar.js +41 -0
- package/lib-dist/lib/terra/docs/toolbar.js.map +1 -0
- package/lib-dist/lib/terra/docs/tree.d.ts +15 -0
- package/lib-dist/lib/terra/docs/tree.d.ts.map +1 -0
- package/lib-dist/lib/terra/docs/tree.js +61 -0
- package/lib-dist/lib/terra/docs/tree.js.map +1 -0
- package/lib-dist/lib/terra/docs/workspace.d.ts +396 -0
- package/lib-dist/lib/terra/docs/workspace.d.ts.map +1 -0
- package/lib-dist/lib/terra/docs/workspace.js +923 -0
- package/lib-dist/lib/terra/docs/workspace.js.map +1 -0
- package/lib-dist/lib/terra/flow/_layout.d.ts +30 -0
- package/lib-dist/lib/terra/flow/_layout.d.ts.map +1 -0
- package/lib-dist/lib/terra/flow/_layout.js +63 -0
- package/lib-dist/lib/terra/flow/_layout.js.map +1 -0
- package/lib-dist/lib/terra/flow/powerSource.d.ts +16 -0
- package/lib-dist/lib/terra/flow/powerSource.d.ts.map +1 -0
- package/lib-dist/lib/terra/flow/powerSource.js +65 -0
- package/lib-dist/lib/terra/flow/powerSource.js.map +1 -0
- package/lib-dist/lib/terra/regex.mjs +403 -0
- package/lib-dist/lib/terra/runtime/action-proxy.d.ts +45 -0
- package/lib-dist/lib/terra/runtime/action-proxy.d.ts.map +1 -0
- package/lib-dist/lib/terra/runtime/action-proxy.js +19 -0
- package/lib-dist/lib/terra/runtime/action-proxy.js.map +1 -0
- package/lib-dist/lib/terra/runtime/content/block-jsx.d.ts +23 -0
- package/lib-dist/lib/terra/runtime/content/block-jsx.d.ts.map +1 -0
- package/lib-dist/lib/terra/runtime/content/block-jsx.js +225 -0
- package/lib-dist/lib/terra/runtime/content/block-jsx.js.map +1 -0
- package/lib-dist/lib/terra/runtime/content/document-markdown.d.ts +41 -0
- package/lib-dist/lib/terra/runtime/content/document-markdown.d.ts.map +1 -0
- package/lib-dist/lib/terra/runtime/content/document-markdown.js +536 -0
- package/lib-dist/lib/terra/runtime/content/document-markdown.js.map +1 -0
- package/lib-dist/lib/terra/runtime/content/markdown.d.ts +109 -0
- package/lib-dist/lib/terra/runtime/content/markdown.d.ts.map +1 -0
- package/lib-dist/lib/terra/runtime/content/markdown.js +428 -0
- package/lib-dist/lib/terra/runtime/content/markdown.js.map +1 -0
- package/lib-dist/lib/terra/runtime/content.d.ts +150 -0
- package/lib-dist/lib/terra/runtime/content.d.ts.map +1 -0
- package/lib-dist/lib/terra/runtime/content.js +1256 -0
- package/lib-dist/lib/terra/runtime/content.js.map +1 -0
- package/lib-dist/lib/terra/runtime/leaf.d.ts +5 -0
- package/lib-dist/lib/terra/runtime/leaf.d.ts.map +1 -0
- package/lib-dist/lib/terra/runtime/leaf.js +13 -0
- package/lib-dist/lib/terra/runtime/leaf.js.map +1 -0
- package/lib-dist/lib/terra/runtime/nodes.d.ts +112 -0
- package/lib-dist/lib/terra/runtime/nodes.d.ts.map +1 -0
- package/lib-dist/lib/terra/runtime/nodes.js +606 -0
- package/lib-dist/lib/terra/runtime/nodes.js.map +1 -0
- package/lib-dist/lib/terra/runtime/runtime.d.ts +31 -0
- package/lib-dist/lib/terra/runtime/runtime.d.ts.map +1 -0
- package/lib-dist/lib/terra/runtime/runtime.js +86 -0
- package/lib-dist/lib/terra/runtime/runtime.js.map +1 -0
- package/lib-dist/lib/terra/runtime/shared.d.ts +35 -0
- package/lib-dist/lib/terra/runtime/shared.d.ts.map +1 -0
- package/lib-dist/lib/terra/runtime/shared.js +124 -0
- package/lib-dist/lib/terra/runtime/shared.js.map +1 -0
- package/lib-dist/lib/terra/runtime/types.d.ts +529 -0
- package/lib-dist/lib/terra/runtime/types.d.ts.map +1 -0
- package/lib-dist/lib/terra/runtime/types.js +44 -0
- package/lib-dist/lib/terra/runtime/types.js.map +1 -0
- package/lib-dist/lib/workspace-types.d.ts +29 -0
- package/lib-dist/lib/workspace-types.d.ts.map +1 -0
- package/lib-dist/lib/workspace-types.js +2 -0
- package/lib-dist/lib/workspace-types.js.map +1 -0
- package/lib-dist/style.css +237 -0
- package/package.json +108 -3
- package/src/components/NotFound.astro +6 -0
- package/src/components/NotFound.tsx +48 -0
- package/src/components/SiteLayout.astro +42 -0
- package/src/components/navigation.tsx +48 -0
|
@@ -0,0 +1,1148 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
// @ts-nocheck -- source-preserving extraction; public host contracts are typed in src/host.ts.
|
|
3
|
+
/**
|
|
4
|
+
* astro/src/pages/docs/_attachments.tsx
|
|
5
|
+
* Docs attachment collection, uploads, and attachment-specific context menus.
|
|
6
|
+
*/
|
|
7
|
+
/*//////////////////////////////////////////////////
|
|
8
|
+
IMPORTS
|
|
9
|
+
//////////////////////////////////////////////////*/
|
|
10
|
+
// API
|
|
11
|
+
import { $surfaceReady, $transition, clearTransition, useAtom, } from '../../../../lib/terra/docs/state.js';
|
|
12
|
+
import { $attachmentFilter } from '../../../../lib/terra/docs/attachments.js';
|
|
13
|
+
import { sanitizeName } from '../../../../lib/terra/docs/tree.js';
|
|
14
|
+
import { uploadAssetChunked } from '../../../../lib/terra/docs/assets.js';
|
|
15
|
+
import { actions } from '../../../../lib/terra/runtime/action-proxy.js';
|
|
16
|
+
import { cn, error as logError, errorLog, isRec, notify, warn, } from '../../../../lib/terra/runtime/runtime.js';
|
|
17
|
+
import { createElement, createElement as __terraQualityCreateElement, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState, } from 'react';
|
|
18
|
+
import { currLeafSrc } from '../../../../lib/terra/runtime/leaf.js';
|
|
19
|
+
import { dirname, docsPath, isDocsPath } from '../../../../lib/terra/runtime/shared.js';
|
|
20
|
+
import { toast } from 'sonner';
|
|
21
|
+
// COMPONENTS
|
|
22
|
+
import * as TerraQualityRegex from '../../../../lib/terra/regex.mjs';
|
|
23
|
+
import { ArrowUpRight as PopOutIcon, Box as BoxIcon, Catalog as CatalogIcon, Copy as CopyIcon, Doc as DocumentIcon, Download as DownloadIcon, Edit as EditIcon, Image as ImageIcon, Link as LinkIcon, LogoYoutube as YouTubeIcon, MagicWand as MagicIcon, TrashCan as TrashIcon, Upload as UploadIcon, } from '@carbon/icons-react';
|
|
24
|
+
import { Button } from '@terra-symposium/styling/ui/terra-original';
|
|
25
|
+
import { Card, CardDescription, CardHeader, CardTitle, } from '@terra-symposium/styling/ui/terra-original';
|
|
26
|
+
import { CodeBlock } from '../../editor/docs/_CodeBlock.js';
|
|
27
|
+
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from '@terra-symposium/styling/ui/terra-original';
|
|
28
|
+
import { ErrorBoundary } from '../../ui.js';
|
|
29
|
+
import { Empty } from '../../ui.js';
|
|
30
|
+
import { Input } from '@terra-symposium/styling/ui/terra-original';
|
|
31
|
+
import { Label } from '@terra-symposium/styling/ui/terra-original';
|
|
32
|
+
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '@terra-symposium/styling/ui/terra-original';
|
|
33
|
+
import { Textarea } from '@terra-symposium/styling/ui/terra-original';
|
|
34
|
+
import { TsDocsSelect } from './_blocks.js';
|
|
35
|
+
// DATA
|
|
36
|
+
import { ATTCH_TYPES } from '../../../../lib/terra/docs/attachments.js';
|
|
37
|
+
/*//////////////////////////////////////////////////
|
|
38
|
+
HELPERS
|
|
39
|
+
//////////////////////////////////////////////////*/
|
|
40
|
+
/**
|
|
41
|
+
* Handles latest content.
|
|
42
|
+
*
|
|
43
|
+
* @param content - Docs content whose attachment references should be collected.
|
|
44
|
+
*/
|
|
45
|
+
const latestContent = (content) => {
|
|
46
|
+
try {
|
|
47
|
+
return currLeafSrc(content, '_attachments.latestContent');
|
|
48
|
+
}
|
|
49
|
+
catch (_err) {
|
|
50
|
+
return typeof content === 'string' ? content : '';
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* Handles text asset.
|
|
55
|
+
*
|
|
56
|
+
* @param sis - Attachment records to normalize for the Docs editor.
|
|
57
|
+
*/
|
|
58
|
+
const textAsset = (sis) => {
|
|
59
|
+
const extension = /\.(?:csv|json|log|md|mdx|text|txt|xml|ya?ml)(?:[?#].*)?$/i;
|
|
60
|
+
return [sis.name, sis.title, sis.path].some((candidate) => typeof candidate === 'string' && extension.test(candidate.trim()));
|
|
61
|
+
};
|
|
62
|
+
const attachmentUrl = (attachmentPath, documentPath) => {
|
|
63
|
+
if (!/^(?:\.\.?(?:\/|$))/.test(attachmentPath))
|
|
64
|
+
return attachmentPath;
|
|
65
|
+
const basePath = documentPath.startsWith('/') ? documentPath : `/${documentPath}`;
|
|
66
|
+
return new URL(attachmentPath, new URL(basePath, window.location.origin)).toString();
|
|
67
|
+
};
|
|
68
|
+
/*//////////////////////////////////////////////////
|
|
69
|
+
COMPONENTS
|
|
70
|
+
//////////////////////////////////////////////////*/
|
|
71
|
+
/**
|
|
72
|
+
* Renders the document attachment manager for filtering, selecting, uploading, and organizing assets.
|
|
73
|
+
*
|
|
74
|
+
* @param props - The document path and current Docs tree used to scope and display its attachments.
|
|
75
|
+
*
|
|
76
|
+
* @return The attachment manager and its upload, selection, and organization controls.
|
|
77
|
+
*/
|
|
78
|
+
export function Attachments({ dPath, tree }) {
|
|
79
|
+
// STATES
|
|
80
|
+
const docId = dPath.split('/').filter(Boolean).at(-1) || dPath;
|
|
81
|
+
const attchFilter = useAtom($attachmentFilter);
|
|
82
|
+
const [sisters, setSisters] = useState([]);
|
|
83
|
+
const [sel, setSel] = useState([]);
|
|
84
|
+
const [loading, setLoading] = useState(true);
|
|
85
|
+
const [uploading, setUploading] = useState(false);
|
|
86
|
+
const [isDragging, setIsDragging] = useState(false);
|
|
87
|
+
const [addDialogOpen, setAddDialogOpen] = useState(false);
|
|
88
|
+
const [dialogMode, setDialogMode] = useState('select');
|
|
89
|
+
const [urlInput, setUrlInput] = useState('');
|
|
90
|
+
const [renameDlg, setRenameDlg] = useState(null);
|
|
91
|
+
const [renameInput, setRenameInput] = useState('');
|
|
92
|
+
const [viewDlg, setViewDlg] = useState(null);
|
|
93
|
+
const fileRef = useRef(null);
|
|
94
|
+
const [transferDlg, setTransferDlg] = useState(null);
|
|
95
|
+
const [transferTgt, setTransferTgt] = useState('');
|
|
96
|
+
const [transferring, setTransferring] = useState(false);
|
|
97
|
+
const [mergePdfState, setMergePdfState] = useState(null);
|
|
98
|
+
const [ctxAttachment, setCtxAttachment] = useState(null);
|
|
99
|
+
const ctxMenuRef = useRef(null);
|
|
100
|
+
const sistersMap = useMemo(() => {
|
|
101
|
+
const map = new Map();
|
|
102
|
+
sisters.forEach((s) => {
|
|
103
|
+
if (s.path)
|
|
104
|
+
map.set(s.path, s);
|
|
105
|
+
if (s.id)
|
|
106
|
+
map.set(s.id, s);
|
|
107
|
+
});
|
|
108
|
+
return map;
|
|
109
|
+
}, [sisters]);
|
|
110
|
+
const selItems = useMemo(() => sel.map((p) => sistersMap.get(p)).filter((s) => Boolean(s)), [sel, sistersMap]);
|
|
111
|
+
useEffect(() => {
|
|
112
|
+
if (!viewDlg)
|
|
113
|
+
return;
|
|
114
|
+
}, [viewDlg]);
|
|
115
|
+
// PROCESS
|
|
116
|
+
const localLeaves = useMemo(() => {
|
|
117
|
+
let tgts = [];
|
|
118
|
+
const groups = [tree];
|
|
119
|
+
while (groups.length > 0) {
|
|
120
|
+
const nodes = groups.pop();
|
|
121
|
+
if (nodes.some((n) => n.type === 'leaf' && n.path === dPath)) {
|
|
122
|
+
tgts = nodes.filter((n) => n.type === 'leaf' && n.path !== dPath);
|
|
123
|
+
break;
|
|
124
|
+
}
|
|
125
|
+
for (let i = nodes.length - 1; i >= 0; i--) {
|
|
126
|
+
const node = nodes[i];
|
|
127
|
+
if (node?.type === 'branch')
|
|
128
|
+
groups.push(node.children || []);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return tgts;
|
|
132
|
+
}, [tree, dPath]);
|
|
133
|
+
const gSisters = useMemo(() => {
|
|
134
|
+
const groups = {};
|
|
135
|
+
for (const s of sisters) {
|
|
136
|
+
let cat = 'other';
|
|
137
|
+
if (s.type === 'youtube')
|
|
138
|
+
cat = 'youtube';
|
|
139
|
+
else if (s.name.toLowerCase().endsWith('.pdf') ||
|
|
140
|
+
s.path.toLowerCase().split('?')[0].endsWith('.pdf') ||
|
|
141
|
+
s.isMd ||
|
|
142
|
+
s.type === 'document')
|
|
143
|
+
cat = 'document';
|
|
144
|
+
else if (s.type === 'website')
|
|
145
|
+
cat = 'website';
|
|
146
|
+
else if (s.type === 'tsdocs')
|
|
147
|
+
cat = 'tsdocs';
|
|
148
|
+
else if (TerraQualityRegex.REGEX_PNG_JPE_G_GIF_WEBP_SVG_AVIF_I_REGEX_2().test(s.name))
|
|
149
|
+
cat = 'image';
|
|
150
|
+
else if (s.type &&
|
|
151
|
+
((val) => ATTCH_TYPES.includes(val))(s.type))
|
|
152
|
+
cat = s.type;
|
|
153
|
+
if (!attchFilter.includes(cat))
|
|
154
|
+
continue;
|
|
155
|
+
(groups[cat] ??= []).push(s);
|
|
156
|
+
}
|
|
157
|
+
for (const arr of Object.values(groups)) {
|
|
158
|
+
arr?.sort((a, b) => (a.title || a.name).localeCompare(b.title || b.name));
|
|
159
|
+
}
|
|
160
|
+
return groups;
|
|
161
|
+
}, [sisters, attchFilter]);
|
|
162
|
+
// SURFACE MOUNT LIFECYCLE
|
|
163
|
+
useEffect(() => {
|
|
164
|
+
$surfaceReady.set(null);
|
|
165
|
+
if (loading)
|
|
166
|
+
return;
|
|
167
|
+
let a = true;
|
|
168
|
+
setTimeout(() => {
|
|
169
|
+
if (a)
|
|
170
|
+
$surfaceReady.set('attachments');
|
|
171
|
+
}, 100);
|
|
172
|
+
return () => {
|
|
173
|
+
a = false;
|
|
174
|
+
if ($surfaceReady.get() === 'attachments')
|
|
175
|
+
$surfaceReady.set(null);
|
|
176
|
+
};
|
|
177
|
+
}, [loading, dPath]);
|
|
178
|
+
// RESOLVE DIRECTORY SISTER FILE ASSETS
|
|
179
|
+
useEffect(() => {
|
|
180
|
+
let a = true;
|
|
181
|
+
setLoading(true);
|
|
182
|
+
if (!dPath)
|
|
183
|
+
warn('Attachments', 'dPath is empty — no fetch will succeed.');
|
|
184
|
+
actions.read.doc
|
|
185
|
+
.attachments({ path: docId })
|
|
186
|
+
.then(async ({ data: d, error: err }) => {
|
|
187
|
+
if (err) {
|
|
188
|
+
errorLog('Attachments', 'Action returned an error', logError(err));
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
if (!a)
|
|
192
|
+
return;
|
|
193
|
+
if (!d) {
|
|
194
|
+
warn('Attachments', 'data is null/undefined — setSisters not called.');
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
setSisters(d);
|
|
198
|
+
})
|
|
199
|
+
.catch((_err) => {
|
|
200
|
+
errorLog('Attachments', 'Fetch threw an exception', logError(_err));
|
|
201
|
+
})
|
|
202
|
+
.finally(() => {
|
|
203
|
+
if (a)
|
|
204
|
+
setLoading(false);
|
|
205
|
+
});
|
|
206
|
+
return () => {
|
|
207
|
+
a = false;
|
|
208
|
+
};
|
|
209
|
+
}, [docId]);
|
|
210
|
+
// ATTACHMENT ACTION HANDLERS
|
|
211
|
+
/**
|
|
212
|
+
* Handles view asset.
|
|
213
|
+
*
|
|
214
|
+
* @param sis - Attachment records being filtered for the active document.
|
|
215
|
+
*/
|
|
216
|
+
const viewAsset = async (sis) => {
|
|
217
|
+
if (!textAsset(sis) || !sis.path || sis.path.startsWith('temp-')) {
|
|
218
|
+
setViewDlg(sis);
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
try {
|
|
222
|
+
const res = await fetch(attachmentUrl(sis.path, dPath));
|
|
223
|
+
if (!res.ok)
|
|
224
|
+
throw new Error(`Attachment preview failed (${res.status}).`);
|
|
225
|
+
setViewDlg({ ...sis, content: await res.text() });
|
|
226
|
+
}
|
|
227
|
+
catch (err) {
|
|
228
|
+
notify({
|
|
229
|
+
error: err instanceof Error ? err : new Error('Attachment preview failed.'),
|
|
230
|
+
fallback: 'Failed to load attachment preview.',
|
|
231
|
+
});
|
|
232
|
+
setViewDlg(sis);
|
|
233
|
+
}
|
|
234
|
+
};
|
|
235
|
+
/**
|
|
236
|
+
* Handles process upload.
|
|
237
|
+
*
|
|
238
|
+
* @param file - File selected for upload or attachment.
|
|
239
|
+
* @param tempId - Temporary identifier assigned before persistence.
|
|
240
|
+
* @param isMdFile - Whether the file should be treated as Markdown content.
|
|
241
|
+
*/
|
|
242
|
+
const processUpload = async (file, tempId, isMdFile) => {
|
|
243
|
+
try {
|
|
244
|
+
const finalAsset = await uploadAssetChunked(file, docId, {
|
|
245
|
+
onProgress: ({ currentChunk: currChunk, totalChunks, message: msg }) => {
|
|
246
|
+
if (msg)
|
|
247
|
+
setSisters((p) => p.map((s) => (s.id === tempId ? { ...s, name: msg } : s)));
|
|
248
|
+
else if (totalChunks > 1)
|
|
249
|
+
setSisters((p) => p.map((s) => s.id === tempId ? { ...s, name: `Uploading (${currChunk}/${totalChunks})...` } : s));
|
|
250
|
+
},
|
|
251
|
+
});
|
|
252
|
+
setSisters((p) => p.map((s) => s.id === tempId
|
|
253
|
+
? {
|
|
254
|
+
...s,
|
|
255
|
+
...(finalAsset.id ? { id: finalAsset.id } : {}),
|
|
256
|
+
path: finalAsset.path || finalAsset.src || tempId,
|
|
257
|
+
name: finalAsset.name || file.name,
|
|
258
|
+
isMd: isMdFile,
|
|
259
|
+
title: file.name,
|
|
260
|
+
}
|
|
261
|
+
: s));
|
|
262
|
+
}
|
|
263
|
+
catch (_err) {
|
|
264
|
+
errorLog('Attachments:Upload', `Failed '${file.name}'`, logError(_err));
|
|
265
|
+
setSisters((p) => p.filter((s) => s.id !== tempId));
|
|
266
|
+
toast.error(_err instanceof Error ? _err.message : `Failed to upload ${file.name}.`);
|
|
267
|
+
notify({
|
|
268
|
+
error: _err instanceof Error ? _err : new Error('Failed to attach.'),
|
|
269
|
+
fallback: `Failed to upload ${file.name}.`,
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
};
|
|
273
|
+
const add = useCallback(async (v) => {
|
|
274
|
+
if ($transition.get() || !v || v.length === 0 || !dPath)
|
|
275
|
+
return;
|
|
276
|
+
const validFiles = [];
|
|
277
|
+
const pdfFiles = [];
|
|
278
|
+
Array.from(v).forEach((f) => {
|
|
279
|
+
validFiles.push(f);
|
|
280
|
+
if (f.name.toLowerCase().endsWith('.pdf') || f.type === 'application/pdf')
|
|
281
|
+
pdfFiles.push(f);
|
|
282
|
+
});
|
|
283
|
+
if (pdfFiles.length > 1) {
|
|
284
|
+
setMergePdfState({
|
|
285
|
+
pdfs: pdfFiles,
|
|
286
|
+
others: validFiles.filter((f) => !pdfFiles.includes(f)),
|
|
287
|
+
});
|
|
288
|
+
if (fileRef.current)
|
|
289
|
+
fileRef.current.value = '';
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
validFiles.forEach((f, i) => {
|
|
293
|
+
const isMdFile = TerraQualityRegex.REGEX_MD_MDX_I_REGEX().test(f.name);
|
|
294
|
+
const tmpId = `temp-${Date.now()}-${i}`;
|
|
295
|
+
setSisters((p) => [...p, { id: tmpId, path: tmpId, name: f.name, isMd: isMdFile }]);
|
|
296
|
+
void processUpload(f, tmpId, isMdFile);
|
|
297
|
+
});
|
|
298
|
+
if (fileRef.current)
|
|
299
|
+
fileRef.current.value = '';
|
|
300
|
+
}, [docId]);
|
|
301
|
+
const addRemote = useCallback(async (v, t) => {
|
|
302
|
+
setAddDialogOpen(false);
|
|
303
|
+
if ($transition.get() || !dPath || !v.trim())
|
|
304
|
+
return;
|
|
305
|
+
const urls = v
|
|
306
|
+
.split(TerraQualityRegex.REGEX_N_S_REGEX())
|
|
307
|
+
.filter((u) => t === 'tsdocs'
|
|
308
|
+
? u.trim().length > 0
|
|
309
|
+
: u.startsWith('http') || isDocsPath(u) || u.startsWith('/tsdocs'));
|
|
310
|
+
if (!urls.length)
|
|
311
|
+
return;
|
|
312
|
+
setUploading(true);
|
|
313
|
+
await Promise.allSettled(urls.map(async (u, i) => {
|
|
314
|
+
let aType = t;
|
|
315
|
+
if (t === 'other') {
|
|
316
|
+
if (u.toLowerCase().split('?')[0].endsWith('.pdf'))
|
|
317
|
+
aType = 'document';
|
|
318
|
+
else if (TerraQualityRegex.REGEX_PNG_JPE_G_GIF_WEBP_SVG_AVIF_I_REGEX_2().test(u.toLowerCase().split('?')[0] ?? ''))
|
|
319
|
+
aType = 'image';
|
|
320
|
+
}
|
|
321
|
+
const tmpId = `temp-${aType}-${Date.now()}-${i}`;
|
|
322
|
+
// prettier-ignore
|
|
323
|
+
setSisters(p => [...p, { id: tmpId, path: tmpId, name: 'Loading...', isMd: aType === 'website', title: aType === 'youtube' ? 'Extracting Transcript...' : aType === 'document' ? 'Downloading Document...' : aType === 'tsdocs' ? 'Linking Reference...' : 'Downloading...', type: aType, sourceUrl: u },]);
|
|
324
|
+
try {
|
|
325
|
+
let item = null;
|
|
326
|
+
if (aType === 'youtube') {
|
|
327
|
+
const { data, error } = await actions.write.attachment.youtube({
|
|
328
|
+
path: docId,
|
|
329
|
+
url: u,
|
|
330
|
+
});
|
|
331
|
+
if (error || !data)
|
|
332
|
+
throw error;
|
|
333
|
+
const { title } = data;
|
|
334
|
+
item = {
|
|
335
|
+
id: tmpId,
|
|
336
|
+
path: u,
|
|
337
|
+
name: `${title} Video`,
|
|
338
|
+
isMd: false,
|
|
339
|
+
title,
|
|
340
|
+
type: 'youtube',
|
|
341
|
+
sourceUrl: u,
|
|
342
|
+
};
|
|
343
|
+
}
|
|
344
|
+
else if (aType === 'website') {
|
|
345
|
+
const { data: webData, error: webErr } = await actions.read.external.website({
|
|
346
|
+
url: u,
|
|
347
|
+
});
|
|
348
|
+
if (webErr || !webData)
|
|
349
|
+
throw webErr;
|
|
350
|
+
const { title, text } = webData;
|
|
351
|
+
const dir = dirname(dPath);
|
|
352
|
+
const nPath = `${dir === '.' ? '' : `${dir}/`}${sanitizeName(title || 'website')}.mdx`;
|
|
353
|
+
const { data: docData, error: wErr } = await actions.write.doc.editor({
|
|
354
|
+
path: nPath,
|
|
355
|
+
source: text,
|
|
356
|
+
title,
|
|
357
|
+
type: 'website',
|
|
358
|
+
sourceUrl: u,
|
|
359
|
+
});
|
|
360
|
+
if (wErr || !docData)
|
|
361
|
+
throw wErr;
|
|
362
|
+
item = {
|
|
363
|
+
id: tmpId,
|
|
364
|
+
path: nPath,
|
|
365
|
+
name: nPath.split('/').pop() || '',
|
|
366
|
+
isMd: true,
|
|
367
|
+
title,
|
|
368
|
+
type: 'website',
|
|
369
|
+
sourceUrl: u,
|
|
370
|
+
source: text,
|
|
371
|
+
};
|
|
372
|
+
}
|
|
373
|
+
else if (aType === 'tsdocs') {
|
|
374
|
+
const fmtUrl = u.startsWith('http')
|
|
375
|
+
? u
|
|
376
|
+
: u.startsWith('/')
|
|
377
|
+
? `${window.location.origin}${u}`
|
|
378
|
+
: `${window.location.origin}${docsPath(`tsdocs/${u}`)}`;
|
|
379
|
+
const { data: linkData, error: linkErr } = await actions.write.attachment.link({
|
|
380
|
+
path: docId,
|
|
381
|
+
url: fmtUrl,
|
|
382
|
+
type: 'tsdocs',
|
|
383
|
+
title: (u
|
|
384
|
+
.split('/')
|
|
385
|
+
.filter(Boolean)
|
|
386
|
+
.pop()
|
|
387
|
+
?.replace(TerraQualityRegex.REGEX_G_REGEX_7(), ' ') || 'TsDocs Reference').replace(TerraQualityRegex.REGEX_B_W_G_REGEX(), (c) => c.toUpperCase()),
|
|
388
|
+
});
|
|
389
|
+
if (linkErr || !linkData)
|
|
390
|
+
throw linkErr;
|
|
391
|
+
const { title } = linkData;
|
|
392
|
+
item = {
|
|
393
|
+
id: tmpId,
|
|
394
|
+
path: fmtUrl,
|
|
395
|
+
name: title,
|
|
396
|
+
isMd: false,
|
|
397
|
+
title,
|
|
398
|
+
type: 'tsdocs',
|
|
399
|
+
sourceUrl: fmtUrl,
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
else {
|
|
403
|
+
const { data, error } = await actions.write.attachment.remoteFile({
|
|
404
|
+
path: docId,
|
|
405
|
+
url: u,
|
|
406
|
+
type: aType,
|
|
407
|
+
});
|
|
408
|
+
if (error || !data)
|
|
409
|
+
throw error;
|
|
410
|
+
const { title, id, path: assetPath, name, } = data;
|
|
411
|
+
item = { id, path: assetPath, name, isMd: false, title, type: aType, sourceUrl: u };
|
|
412
|
+
}
|
|
413
|
+
setSisters((p) => p.map((s) => (s.id === tmpId ? item : s)));
|
|
414
|
+
}
|
|
415
|
+
catch (_err) {
|
|
416
|
+
setSisters((p) => p.filter((s) => s.id !== tmpId));
|
|
417
|
+
toast.error(`Failed to process ${u}`);
|
|
418
|
+
}
|
|
419
|
+
}));
|
|
420
|
+
setUploading(false);
|
|
421
|
+
clearTransition();
|
|
422
|
+
}, [docId]);
|
|
423
|
+
useEffect(() => {
|
|
424
|
+
/**
|
|
425
|
+
* Handles handle paste.
|
|
426
|
+
*
|
|
427
|
+
* @param e - Input event carrying the selected attachment files.
|
|
428
|
+
*/
|
|
429
|
+
const handlePaste = (e) => {
|
|
430
|
+
if (e.target instanceof HTMLInputElement || e.target instanceof HTMLTextAreaElement)
|
|
431
|
+
return;
|
|
432
|
+
const text = e.clipboardData?.getData('text');
|
|
433
|
+
if (text) {
|
|
434
|
+
const urls = text
|
|
435
|
+
.split(TerraQualityRegex.REGEX_N_S_REGEX())
|
|
436
|
+
.filter((u) => u.startsWith('http') || isDocsPath(u) || u.startsWith('/tsdocs'));
|
|
437
|
+
if (urls.length > 0) {
|
|
438
|
+
e.preventDefault();
|
|
439
|
+
const ytUrls = urls.filter((u) => u.includes('youtube.com') || u.includes('youtu.be'));
|
|
440
|
+
const refUrls = urls.filter((u) => u.includes('/tsdocs/'));
|
|
441
|
+
const imgUrls = urls.filter((u) => TerraQualityRegex.REGEX_PNG_JPE_G_GIF_WEBP_SVG_AVIF_I_REGEX_2().test(u.toLowerCase().split('?')[0] ?? ''));
|
|
442
|
+
const docUrls = [
|
|
443
|
+
...urls.filter((u) => u.toLowerCase().split('?')[0].endsWith('.pdf')),
|
|
444
|
+
...urls.filter((u) => u.toLowerCase().split('?')[0].endsWith('.json')),
|
|
445
|
+
];
|
|
446
|
+
const webUrls = urls.filter((u) => !ytUrls.includes(u) &&
|
|
447
|
+
!refUrls.includes(u) &&
|
|
448
|
+
!docUrls.includes(u) &&
|
|
449
|
+
!imgUrls.includes(u));
|
|
450
|
+
if (ytUrls.length > 0)
|
|
451
|
+
void addRemote(ytUrls.join('\n'), 'youtube');
|
|
452
|
+
if (refUrls.length > 0)
|
|
453
|
+
void addRemote(refUrls.join('\n'), 'tsdocs');
|
|
454
|
+
if (docUrls.length > 0)
|
|
455
|
+
void addRemote(docUrls.join('\n'), 'document');
|
|
456
|
+
if (imgUrls.length > 0)
|
|
457
|
+
void addRemote(imgUrls.join('\n'), 'image');
|
|
458
|
+
if (webUrls.length > 0)
|
|
459
|
+
void addRemote(webUrls.join('\n'), 'website');
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
if (e.clipboardData?.files?.length) {
|
|
463
|
+
e.preventDefault();
|
|
464
|
+
void add(e.clipboardData.files);
|
|
465
|
+
}
|
|
466
|
+
};
|
|
467
|
+
document.addEventListener('paste', handlePaste);
|
|
468
|
+
return () => {
|
|
469
|
+
document.removeEventListener('paste', handlePaste);
|
|
470
|
+
};
|
|
471
|
+
}, [addRemote, add]);
|
|
472
|
+
/**
|
|
473
|
+
* Handles rename attch.
|
|
474
|
+
*
|
|
475
|
+
* @param nName - Proposed attachment name displayed in the editor.
|
|
476
|
+
*/
|
|
477
|
+
const renameAttch = async (nName) => {
|
|
478
|
+
if (!renameDlg)
|
|
479
|
+
return;
|
|
480
|
+
try {
|
|
481
|
+
const { path, name, isMd, id } = renameDlg;
|
|
482
|
+
const nFilename = `${sanitizeName(nName)}${name.match(TerraQualityRegex.REGEX_I_REGEX())?.[0] ?? ''}`;
|
|
483
|
+
const nPath = `${dirname(path) === '.' ? '' : `${dirname(path)}/`}${nFilename}`;
|
|
484
|
+
setSisters((p) => p.map((s) => (s.path === path ? { ...s, path: nPath, name: nFilename } : s)));
|
|
485
|
+
if (isMd) {
|
|
486
|
+
const { error: err } = await actions.write.doc.commit({ cur: path, next: nPath });
|
|
487
|
+
if (err)
|
|
488
|
+
throw err;
|
|
489
|
+
}
|
|
490
|
+
else if (id)
|
|
491
|
+
await actions.write.attachment.rename({
|
|
492
|
+
docPath: docId,
|
|
493
|
+
attachmentKey: id,
|
|
494
|
+
newName: nFilename,
|
|
495
|
+
});
|
|
496
|
+
toast.success('Renamed successfully');
|
|
497
|
+
}
|
|
498
|
+
catch (_err) {
|
|
499
|
+
errorLog('Attachments:Rename', 'Rename failed', logError(_err));
|
|
500
|
+
setSisters((p) => p.map((s) => s.path === renameDlg.path ? { ...s, path: renameDlg.path, name: renameDlg.name } : s));
|
|
501
|
+
toast.error('Failed to rename attachment');
|
|
502
|
+
}
|
|
503
|
+
finally {
|
|
504
|
+
setRenameDlg(null);
|
|
505
|
+
setRenameInput('');
|
|
506
|
+
}
|
|
507
|
+
};
|
|
508
|
+
/**
|
|
509
|
+
* Handles remove.
|
|
510
|
+
*
|
|
511
|
+
* @param items - Attachment items rendered by the list.
|
|
512
|
+
*/
|
|
513
|
+
const remove = async (items) => {
|
|
514
|
+
if (!window.confirm(`Are you sure you want to delete ${items.length} items?`))
|
|
515
|
+
return;
|
|
516
|
+
const itemKeys = new Set(items.flatMap((i) => [i.id, i.path].filter(Boolean)));
|
|
517
|
+
setSisters((p) => p.filter((s) => !(s.id && itemKeys.has(s.id)) && !(s.path && itemKeys.has(s.path))));
|
|
518
|
+
try {
|
|
519
|
+
await Promise.allSettled(items.map(async (i) => {
|
|
520
|
+
if (i.isMd)
|
|
521
|
+
await actions.write.doc.rm({ assets: false, path: i.path, type: 'doc' });
|
|
522
|
+
else if (i.id) {
|
|
523
|
+
await actions.write.attachment.rm({ docPath: docId, attachmentKey: i.id });
|
|
524
|
+
if (i.path.startsWith('http'))
|
|
525
|
+
await actions.write.asset.delete({ url: i.path });
|
|
526
|
+
}
|
|
527
|
+
}));
|
|
528
|
+
setSel([]);
|
|
529
|
+
}
|
|
530
|
+
catch (_err) {
|
|
531
|
+
setSisters([...sisters]);
|
|
532
|
+
notify({
|
|
533
|
+
error: _err instanceof Error ? _err : new Error('Deletion failed'),
|
|
534
|
+
fallback: 'Failed to delete some attachments.',
|
|
535
|
+
});
|
|
536
|
+
}
|
|
537
|
+
};
|
|
538
|
+
const isDialogOpen = !!mergePdfState ||
|
|
539
|
+
!!viewDlg ||
|
|
540
|
+
(renameDlg?.open ?? false) ||
|
|
541
|
+
(transferDlg?.open ?? false) ||
|
|
542
|
+
addDialogOpen;
|
|
543
|
+
// GLOBAL KEYBOARD SHORTCUTS
|
|
544
|
+
useEffect(() => {
|
|
545
|
+
/**
|
|
546
|
+
* Handles handle key down.
|
|
547
|
+
*
|
|
548
|
+
* @param e - Keyboard event used to operate the attachment panel.
|
|
549
|
+
*/
|
|
550
|
+
const handleKeyDown = (e) => {
|
|
551
|
+
if (loading || uploading || isDialogOpen || selItems.length === 0)
|
|
552
|
+
return;
|
|
553
|
+
const tgt = e.target;
|
|
554
|
+
if (tgt.tagName === 'INPUT' || tgt.tagName === 'TEXTAREA' || tgt.isContentEditable)
|
|
555
|
+
return;
|
|
556
|
+
if (e.key === 'Backspace' || e.key === 'Delete') {
|
|
557
|
+
e.preventDefault();
|
|
558
|
+
void remove(selItems);
|
|
559
|
+
}
|
|
560
|
+
};
|
|
561
|
+
document.addEventListener('keydown', handleKeyDown);
|
|
562
|
+
return () => {
|
|
563
|
+
document.removeEventListener('keydown', handleKeyDown);
|
|
564
|
+
};
|
|
565
|
+
}, [loading, uploading, isDialogOpen, selItems]);
|
|
566
|
+
useEffect(() => {
|
|
567
|
+
if (!ctxAttachment)
|
|
568
|
+
return;
|
|
569
|
+
/**
|
|
570
|
+
* Closes the attachment context menu when the user presses Escape.
|
|
571
|
+
*
|
|
572
|
+
* @param e - Keyboard event checked for the Escape key.
|
|
573
|
+
*/
|
|
574
|
+
const close = (e) => {
|
|
575
|
+
if (e.key === 'Escape')
|
|
576
|
+
setCtxAttachment(null);
|
|
577
|
+
};
|
|
578
|
+
window.addEventListener('keydown', close);
|
|
579
|
+
return () => window.removeEventListener('keydown', close);
|
|
580
|
+
}, [ctxAttachment]);
|
|
581
|
+
useLayoutEffect(() => {
|
|
582
|
+
const menu = ctxMenuRef.current;
|
|
583
|
+
if (!ctxAttachment || !menu)
|
|
584
|
+
return;
|
|
585
|
+
const { width, height } = menu.getBoundingClientRect();
|
|
586
|
+
const inset = 8;
|
|
587
|
+
const x = Math.max(inset, Math.min(ctxAttachment.x, window.innerWidth - width - inset));
|
|
588
|
+
const y = Math.max(inset, Math.min(ctxAttachment.y, window.innerHeight - height - inset));
|
|
589
|
+
if (x !== ctxAttachment.x || y !== ctxAttachment.y) {
|
|
590
|
+
setCtxAttachment((current) => current?.item.path === ctxAttachment.item.path ? { ...current, x, y } : current);
|
|
591
|
+
}
|
|
592
|
+
}, [ctxAttachment]);
|
|
593
|
+
useEffect(() => {
|
|
594
|
+
/**
|
|
595
|
+
* Opens the attachment context menu for the item under the pointer.
|
|
596
|
+
*
|
|
597
|
+
* @param e - Mouse event used to identify the attachment item and menu position.
|
|
598
|
+
*/
|
|
599
|
+
const open = (e) => {
|
|
600
|
+
const id = (e.target instanceof Element
|
|
601
|
+
? e.target.closest('[data-docs-attachment-id]')
|
|
602
|
+
: null)?.dataset.docsAttachmentId;
|
|
603
|
+
const item = id ? sistersMap.get(id) : undefined;
|
|
604
|
+
if (!(e.target instanceof Element
|
|
605
|
+
? e.target.closest('[data-docs-attachments]')
|
|
606
|
+
: null))
|
|
607
|
+
return;
|
|
608
|
+
e.preventDefault();
|
|
609
|
+
if (item)
|
|
610
|
+
setCtxAttachment({ item, x: e.clientX, y: e.clientY });
|
|
611
|
+
else
|
|
612
|
+
setAddDialogOpen(true);
|
|
613
|
+
};
|
|
614
|
+
document.addEventListener('contextmenu', open, true);
|
|
615
|
+
return () => document.removeEventListener('contextmenu', open, true);
|
|
616
|
+
}, [sistersMap]);
|
|
617
|
+
// RENDER
|
|
618
|
+
return (_jsxs(ErrorBoundary, { name: "Attachments", children: [_jsxs("div", { "data-docs-attachments": true, "data-docs-path": dPath, "data-loading": loading, className: cn('-mx-6 -my-40 flex min-h-[calc(100vh+8rem)] flex-col rounded-xl border-2 px-6 pb-40 transition-colors md:-mx-20 md:px-20', isDragging ? 'border-primary-8 bg-primary-4/20' : 'border-transparent'), onDragOver: (e) => {
|
|
619
|
+
e.preventDefault();
|
|
620
|
+
e.stopPropagation();
|
|
621
|
+
setIsDragging(true);
|
|
622
|
+
}, onDragEnter: (e) => {
|
|
623
|
+
e.preventDefault();
|
|
624
|
+
e.stopPropagation();
|
|
625
|
+
setIsDragging(true);
|
|
626
|
+
}, onDragLeave: (e) => {
|
|
627
|
+
e.preventDefault();
|
|
628
|
+
e.stopPropagation();
|
|
629
|
+
setIsDragging(false);
|
|
630
|
+
}, onDrop: (e) => {
|
|
631
|
+
e.preventDefault();
|
|
632
|
+
e.stopPropagation();
|
|
633
|
+
setIsDragging(false);
|
|
634
|
+
if (e.dataTransfer.files?.length)
|
|
635
|
+
void add(e.dataTransfer.files);
|
|
636
|
+
}, onContextMenu: (e) => {
|
|
637
|
+
if (e.target === e.currentTarget) {
|
|
638
|
+
e.preventDefault();
|
|
639
|
+
setAddDialogOpen(true);
|
|
640
|
+
}
|
|
641
|
+
}, onClick: (e) => {
|
|
642
|
+
if (e.target === e.currentTarget)
|
|
643
|
+
setSel([]);
|
|
644
|
+
}, children: [_jsx("div", { className: "flex flex-col gap-8 py-8", children: loading ? null : Object.keys(gSisters).length === 0 ? (_jsx(Empty, { children: "No attachments found." })) : (ATTCH_TYPES.filter((c) => gSisters[c]).map((c) => (_jsxs("div", { className: "space-y-4", children: [_jsx("h3", { className: "h3 capitalize", children: c }), _jsx("div", { className: "grid grid-cols-1 content-start gap-4 sm:grid-cols-2 md:grid-cols-1 lg:grid-cols-3", children: gSisters[c].map((v) => {
|
|
645
|
+
const isTemp = v.path.startsWith('temp-');
|
|
646
|
+
return (_jsx(Card, { "data-docs-attachment-id": v.id || v.path, role: "button", tabIndex: isTemp ? -1 : 0, "aria-disabled": isTemp ? true : undefined, "aria-selected": sel.includes(v.path), "aria-label": `Attachment ${v.title || v.name}`, className: cn('cursor-pointer transition-colors hover:border-primary-8 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-8', sel.includes(v.path) && 'bg-primary-4/50 ring-2 ring-primary-8', isTemp && 'pointer-events-none opacity-50'), onKeyDown: (e) => {
|
|
647
|
+
if (isTemp)
|
|
648
|
+
return;
|
|
649
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
650
|
+
e.preventDefault();
|
|
651
|
+
if (v.type === 'youtube')
|
|
652
|
+
setViewDlg({
|
|
653
|
+
...v,
|
|
654
|
+
isMd: true,
|
|
655
|
+
content: latestContent(v.content) || 'No transcript text found.',
|
|
656
|
+
});
|
|
657
|
+
else
|
|
658
|
+
void viewAsset(v);
|
|
659
|
+
}
|
|
660
|
+
}, onClick: (e) => {
|
|
661
|
+
if (isTemp)
|
|
662
|
+
return;
|
|
663
|
+
e.stopPropagation();
|
|
664
|
+
if (e.shiftKey && sel.length > 0) {
|
|
665
|
+
const i1 = sisters.findIndex((s) => s.path === sel[sel.length - 1]);
|
|
666
|
+
const i2 = sisters.findIndex((s) => s.path === v.path);
|
|
667
|
+
setSel((p) => Array.from(new Set([
|
|
668
|
+
...(e.metaKey || e.ctrlKey ? p : []),
|
|
669
|
+
...sisters
|
|
670
|
+
.slice(Math.min(i1, i2), Math.max(i1, i2) + 1)
|
|
671
|
+
.map((s) => s.path),
|
|
672
|
+
])));
|
|
673
|
+
}
|
|
674
|
+
else if (e.metaKey || e.ctrlKey) {
|
|
675
|
+
setSel((p) => p.includes(v.path) ? p.filter((x) => x !== v.path) : [...p, v.path]);
|
|
676
|
+
}
|
|
677
|
+
else {
|
|
678
|
+
if (v.type === 'youtube')
|
|
679
|
+
setViewDlg({
|
|
680
|
+
...v,
|
|
681
|
+
isMd: true,
|
|
682
|
+
content: latestContent(v.content) || 'No transcript text found.',
|
|
683
|
+
});
|
|
684
|
+
else
|
|
685
|
+
void viewAsset(v);
|
|
686
|
+
}
|
|
687
|
+
}, onContextMenu: (e) => {
|
|
688
|
+
e.preventDefault();
|
|
689
|
+
setCtxAttachment({ item: v, x: e.clientX, y: e.clientY });
|
|
690
|
+
}, children: _jsxs(CardHeader, { children: [__terraQualityCreateElement(
|
|
691
|
+
/* prettier-ignore */ v.type === 'youtube' ? YouTubeIcon : v.type === 'website' ? LinkIcon : v.type === 'image' ? ImageIcon : v.type === 'tsdocs' ? CatalogIcon : v.type === 'other' ? BoxIcon : DocumentIcon, { className: 'size-6 text-primary-10', 'aria-hidden': 'true' }), _jsx(CardTitle, { className: "truncate text-base", children: v.title || v.name }), _jsx(CardDescription, { className: "truncate", children: v.sourceUrl || v.path })] }) }, v.id || v.path));
|
|
692
|
+
}) })] }, c)))) }), _jsx("input", { "data-testid": "docs-attachment-upload", ref: fileRef, type: "file", className: "hidden", multiple: true, onChange: (e) => void add(e.currentTarget.files), disabled: uploading || loading })] }), ctxAttachment && (_jsx("div", { ref: ctxMenuRef, role: "menu", "data-docs-attachment-menu": true, className: "fixed z-[120] max-h-[calc(100dvh-1rem)] min-w-32 max-w-[calc(100vw-1rem)] overflow-y-auto rounded-md border border-primary-6 bg-white p-1 text-primary-12 shadow-lg dark:bg-black", style: { left: ctxAttachment.x, top: ctxAttachment.y }, onContextMenu: (e) => e.preventDefault(), children: (sel.includes(ctxAttachment.item.path) && sel.length > 1
|
|
693
|
+
? [
|
|
694
|
+
{
|
|
695
|
+
icon: _jsx(CopyIcon, {}),
|
|
696
|
+
label: `Copy ${sel.length} items`,
|
|
697
|
+
onSelect: () => setTransferDlg({ open: true, action: 'copy', items: selItems }),
|
|
698
|
+
},
|
|
699
|
+
{
|
|
700
|
+
icon: _jsx(PopOutIcon, {}),
|
|
701
|
+
label: `Move ${sel.length} items`,
|
|
702
|
+
onSelect: () => setTransferDlg({ open: true, action: 'cut', items: selItems }),
|
|
703
|
+
},
|
|
704
|
+
...(selItems.every((s) => s.path.toLowerCase().split('?')[0].endsWith('.pdf') ||
|
|
705
|
+
s.name.toLowerCase().endsWith('.pdf'))
|
|
706
|
+
? [
|
|
707
|
+
{
|
|
708
|
+
icon: _jsx(DocumentIcon, {}),
|
|
709
|
+
label: `Merge ${sel.length} PDFs`,
|
|
710
|
+
onSelect: () => {
|
|
711
|
+
void (async () => {
|
|
712
|
+
if (!window.confirm(`Merge ${selItems.length} PDFs into a single file?`))
|
|
713
|
+
return;
|
|
714
|
+
setUploading(true);
|
|
715
|
+
const tmpId = `temp-merge-${Date.now()}`;
|
|
716
|
+
const itemKeys = new Set(selItems.flatMap((i) => [i.id, i.path].filter(Boolean)));
|
|
717
|
+
setSisters((p) => [
|
|
718
|
+
...p.filter((s) => !(s.id && itemKeys.has(s.id)) &&
|
|
719
|
+
!(s.path && itemKeys.has(s.path))),
|
|
720
|
+
{
|
|
721
|
+
id: tmpId,
|
|
722
|
+
path: tmpId,
|
|
723
|
+
name: 'Merging PDFs...',
|
|
724
|
+
isMd: false,
|
|
725
|
+
type: 'document',
|
|
726
|
+
},
|
|
727
|
+
]);
|
|
728
|
+
setSel([]);
|
|
729
|
+
try {
|
|
730
|
+
const { PDFDocument } = await import('pdf-lib');
|
|
731
|
+
const mergedPdf = await PDFDocument.create();
|
|
732
|
+
for (let i = 0; i < selItems.length; i++) {
|
|
733
|
+
const item = selItems[i];
|
|
734
|
+
let buf;
|
|
735
|
+
if (item?.path.startsWith('http')) {
|
|
736
|
+
buf = await (await fetch(item.path)).arrayBuffer();
|
|
737
|
+
}
|
|
738
|
+
else {
|
|
739
|
+
const { data, error: err } = await actions.read.asset.get({
|
|
740
|
+
path: item?.path || '',
|
|
741
|
+
});
|
|
742
|
+
if (err || !data)
|
|
743
|
+
throw err || new Error('Failed to read local asset');
|
|
744
|
+
buf = data;
|
|
745
|
+
}
|
|
746
|
+
const pdfDoc = await PDFDocument.load(buf);
|
|
747
|
+
(await mergedPdf.copyPages(pdfDoc, pdfDoc.getPageIndices())).forEach((p) => mergedPdf.addPage(p));
|
|
748
|
+
}
|
|
749
|
+
const mergedFile = new File([(await mergedPdf.save()).buffer], 'Merged-Document.pdf', { type: 'application/pdf' });
|
|
750
|
+
setSisters((p) => p.map((s) => s.id === tmpId ? { ...s, name: 'Uploading Merged PDF...' } : s));
|
|
751
|
+
const finalAsset = await uploadAssetChunked(mergedFile, docId, {
|
|
752
|
+
onProgress: ({ currentChunk: currChunk, totalChunks, message: msg, }) => {
|
|
753
|
+
if (msg)
|
|
754
|
+
setSisters((p) => p.map((s) => (s.id === tmpId ? { ...s, name: msg } : s)));
|
|
755
|
+
else if (totalChunks > 1)
|
|
756
|
+
setSisters((p) => p.map((s) => s.id === tmpId
|
|
757
|
+
? {
|
|
758
|
+
...s,
|
|
759
|
+
name: `Uploading (${currChunk}/${totalChunks})...`,
|
|
760
|
+
}
|
|
761
|
+
: s));
|
|
762
|
+
},
|
|
763
|
+
});
|
|
764
|
+
const fPath = finalAsset.path || finalAsset.src || tmpId;
|
|
765
|
+
setSisters((p) => p.map((s) => s.id === tmpId
|
|
766
|
+
? {
|
|
767
|
+
...s,
|
|
768
|
+
...(finalAsset.id ? { id: finalAsset.id } : {}),
|
|
769
|
+
path: fPath,
|
|
770
|
+
name: fPath.split('/').pop() || mergedFile.name,
|
|
771
|
+
}
|
|
772
|
+
: s));
|
|
773
|
+
await Promise.allSettled(selItems.map(async (i) => {
|
|
774
|
+
if (i.isMd)
|
|
775
|
+
await actions.write.doc.rm({
|
|
776
|
+
assets: false,
|
|
777
|
+
path: i.path,
|
|
778
|
+
type: 'doc',
|
|
779
|
+
});
|
|
780
|
+
else if (i.id) {
|
|
781
|
+
await actions.write.attachment.rm({
|
|
782
|
+
docPath: docId,
|
|
783
|
+
attachmentKey: i.id,
|
|
784
|
+
});
|
|
785
|
+
if (i.path.startsWith('http'))
|
|
786
|
+
await actions.write.asset.delete({ url: i.path });
|
|
787
|
+
}
|
|
788
|
+
}));
|
|
789
|
+
toast.success('PDFs merged successfully.');
|
|
790
|
+
}
|
|
791
|
+
catch (_err) {
|
|
792
|
+
errorLog('Attachments:Merge', 'Fatal exception caught during PDF merge', logError(_err));
|
|
793
|
+
toast.error('Failed to merge PDFs.');
|
|
794
|
+
setSisters([...sisters]);
|
|
795
|
+
}
|
|
796
|
+
finally {
|
|
797
|
+
setUploading(false);
|
|
798
|
+
}
|
|
799
|
+
})();
|
|
800
|
+
},
|
|
801
|
+
},
|
|
802
|
+
]
|
|
803
|
+
: []),
|
|
804
|
+
{ separator: true },
|
|
805
|
+
{
|
|
806
|
+
destructive: true,
|
|
807
|
+
icon: _jsx(TrashIcon, {}),
|
|
808
|
+
label: `Delete ${sel.length} items`,
|
|
809
|
+
onSelect: () => void remove(selItems),
|
|
810
|
+
},
|
|
811
|
+
]
|
|
812
|
+
: [
|
|
813
|
+
...(!ctxAttachment.item.type || ctxAttachment.item.type !== 'youtube'
|
|
814
|
+
? [
|
|
815
|
+
{
|
|
816
|
+
onSelect: () => {
|
|
817
|
+
setRenameInput(ctxAttachment.item.name.replace(TerraQualityRegex.REGEX_I_REGEX(), ''));
|
|
818
|
+
setRenameDlg({
|
|
819
|
+
open: true,
|
|
820
|
+
path: ctxAttachment.item.path,
|
|
821
|
+
name: ctxAttachment.item.name,
|
|
822
|
+
isMd: ctxAttachment.item.isMd || false,
|
|
823
|
+
id: ctxAttachment.item.id,
|
|
824
|
+
});
|
|
825
|
+
},
|
|
826
|
+
icon: _jsx(EditIcon, {}),
|
|
827
|
+
label: 'Rename',
|
|
828
|
+
},
|
|
829
|
+
]
|
|
830
|
+
: []),
|
|
831
|
+
{
|
|
832
|
+
icon: _jsx(CopyIcon, {}),
|
|
833
|
+
label: 'Copy to...',
|
|
834
|
+
onSelect: () => setTransferDlg({ open: true, action: 'copy', items: [ctxAttachment.item] }),
|
|
835
|
+
},
|
|
836
|
+
{
|
|
837
|
+
icon: _jsx(PopOutIcon, {}),
|
|
838
|
+
label: 'Move to...',
|
|
839
|
+
onSelect: () => setTransferDlg({ open: true, action: 'cut', items: [ctxAttachment.item] }),
|
|
840
|
+
},
|
|
841
|
+
...(ctxAttachment.item.isMd
|
|
842
|
+
? [
|
|
843
|
+
{
|
|
844
|
+
onSelect: () => document.dispatchEvent(new CustomEvent('docs:synthesize', {
|
|
845
|
+
detail: {
|
|
846
|
+
path: ctxAttachment.item.path,
|
|
847
|
+
name: ctxAttachment.item.name,
|
|
848
|
+
},
|
|
849
|
+
})),
|
|
850
|
+
icon: _jsx(MagicIcon, {}),
|
|
851
|
+
label: 'Synthesize Content',
|
|
852
|
+
},
|
|
853
|
+
...(!ctxAttachment.item.type || ctxAttachment.item.type !== 'youtube'
|
|
854
|
+
? [
|
|
855
|
+
{
|
|
856
|
+
icon: _jsx(CopyIcon, {}),
|
|
857
|
+
label: 'Duplicate',
|
|
858
|
+
onSelect: () => {
|
|
859
|
+
void (async () => {
|
|
860
|
+
const path = ctxAttachment.item.path;
|
|
861
|
+
if (!path)
|
|
862
|
+
return;
|
|
863
|
+
const name = window.prompt('Duplicate file name', `${path.split('/').at(-1)?.replace(TerraQualityRegex.REGEX_MD_MDX_I_REGEX(), '') ?? ''}-copy`);
|
|
864
|
+
if (!name)
|
|
865
|
+
return;
|
|
866
|
+
try {
|
|
867
|
+
const { data: docData, error: readErr } = await actions.read.doc.get({ path });
|
|
868
|
+
if (readErr || !docData)
|
|
869
|
+
throw readErr || new Error('Failed to read doc.');
|
|
870
|
+
const nPath = `${dirname(path)}/${sanitizeName(name)}.mdx`;
|
|
871
|
+
const { data, error: writeErr } = await actions.write.doc.save({
|
|
872
|
+
path: nPath,
|
|
873
|
+
source: docData
|
|
874
|
+
.source,
|
|
875
|
+
});
|
|
876
|
+
if (writeErr || !data)
|
|
877
|
+
throw writeErr || new Error('Failed to duplicate.');
|
|
878
|
+
const duplicateData = data;
|
|
879
|
+
setSisters((p) => [
|
|
880
|
+
...p,
|
|
881
|
+
{
|
|
882
|
+
path: nPath,
|
|
883
|
+
name: nPath.split('/').pop() || '',
|
|
884
|
+
isMd: true,
|
|
885
|
+
title: duplicateData.title,
|
|
886
|
+
source: duplicateData.source,
|
|
887
|
+
type: duplicateData.type,
|
|
888
|
+
sourceUrl: duplicateData.sourceUrl,
|
|
889
|
+
},
|
|
890
|
+
]);
|
|
891
|
+
}
|
|
892
|
+
catch (_err) {
|
|
893
|
+
errorLog('Attachments:Duplicate', 'Duplicate failed', logError(_err));
|
|
894
|
+
notify({
|
|
895
|
+
error: _err instanceof Error
|
|
896
|
+
? _err
|
|
897
|
+
: new Error('Failed to duplicate.'),
|
|
898
|
+
fallback: 'Failed to duplicate.',
|
|
899
|
+
});
|
|
900
|
+
}
|
|
901
|
+
})();
|
|
902
|
+
},
|
|
903
|
+
},
|
|
904
|
+
]
|
|
905
|
+
: []),
|
|
906
|
+
]
|
|
907
|
+
: []),
|
|
908
|
+
{ separator: true },
|
|
909
|
+
{
|
|
910
|
+
destructive: true,
|
|
911
|
+
onSelect: () => void remove([ctxAttachment.item]),
|
|
912
|
+
icon: _jsx(TrashIcon, {}),
|
|
913
|
+
label: 'Delete',
|
|
914
|
+
},
|
|
915
|
+
]).map((a, i) => a.separator ? (_jsx("div", { role: "separator", className: "mx-1.5 my-1 h-px bg-primary-6/50" }, `separator-${i}`)) : (_jsx("button", { type: "button", role: "menuitem", className: "relative flex w-full cursor-default select-none items-center rounded-sm px-3 py-1 text-left text-sm hover:bg-primary-4", disabled: a.disabled, onClick: () => {
|
|
916
|
+
setCtxAttachment(null);
|
|
917
|
+
a.onSelect?.();
|
|
918
|
+
}, children: a.label }, `${a.label}-${i}`))) })), _jsxs(Dialog, { open: isDialogOpen, onOpenChange: (open) => {
|
|
919
|
+
if (open)
|
|
920
|
+
return;
|
|
921
|
+
if (viewDlg)
|
|
922
|
+
setViewDlg(null);
|
|
923
|
+
if (renameDlg?.open) {
|
|
924
|
+
setRenameDlg(null);
|
|
925
|
+
setRenameInput('');
|
|
926
|
+
}
|
|
927
|
+
if (transferDlg?.open)
|
|
928
|
+
setTransferDlg(null);
|
|
929
|
+
if (mergePdfState)
|
|
930
|
+
setMergePdfState(null);
|
|
931
|
+
if (addDialogOpen) {
|
|
932
|
+
setAddDialogOpen(false);
|
|
933
|
+
setTimeout(() => {
|
|
934
|
+
setDialogMode('select');
|
|
935
|
+
setUrlInput('');
|
|
936
|
+
}, 200);
|
|
937
|
+
}
|
|
938
|
+
}, children: [!!mergePdfState && (_jsxs(DialogContent, { className: "sm:max-w-md", children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { children: "Multiple PDFs Selected" }), _jsxs(DialogDescription, { children: ["Would you like to merge these ", mergePdfState.pdfs.length, " PDFs into a single file, or upload them separately?"] })] }), _jsxs(DialogFooter, { className: "flex gap-2 sm:justify-between", children: [_jsx(Button, { variant: "ghost", onClick: () => {
|
|
939
|
+
[...mergePdfState.pdfs, ...mergePdfState.others].forEach((f, i) => {
|
|
940
|
+
const isMdFile = TerraQualityRegex.REGEX_MD_MDX_I_REGEX().test(f.name);
|
|
941
|
+
const tmpId = `temp-${Date.now()}-${i}`;
|
|
942
|
+
setSisters((p) => [
|
|
943
|
+
...p,
|
|
944
|
+
{ id: tmpId, path: tmpId, name: f.name, isMd: isMdFile, type: 'document' },
|
|
945
|
+
]);
|
|
946
|
+
void processUpload(f, tmpId, isMdFile);
|
|
947
|
+
});
|
|
948
|
+
setMergePdfState(null);
|
|
949
|
+
}, children: "Upload Separately" }), _jsx(Button, { disabled: uploading, loading: uploading, onClick: async () => {
|
|
950
|
+
setUploading(true);
|
|
951
|
+
setMergePdfState(null);
|
|
952
|
+
try {
|
|
953
|
+
const { PDFDocument } = await import('pdf-lib');
|
|
954
|
+
const mergedPdf = await PDFDocument.create();
|
|
955
|
+
for (let i = 0; i < mergePdfState.pdfs.length; i++) {
|
|
956
|
+
const pdfDoc = await PDFDocument.load(await mergePdfState.pdfs[i].arrayBuffer());
|
|
957
|
+
(await mergedPdf.copyPages(pdfDoc, pdfDoc.getPageIndices())).forEach((p) => mergedPdf.addPage(p));
|
|
958
|
+
}
|
|
959
|
+
[
|
|
960
|
+
new File([(await mergedPdf.save()).buffer], 'Merged-Document.pdf', { type: 'application/pdf' }),
|
|
961
|
+
...mergePdfState.others,
|
|
962
|
+
].forEach((f, i) => {
|
|
963
|
+
const isMdFile = TerraQualityRegex.REGEX_MD_MDX_I_REGEX().test(f.name);
|
|
964
|
+
const tmpId = `temp-${Date.now()}-${i}`;
|
|
965
|
+
setSisters((p) => [
|
|
966
|
+
...p,
|
|
967
|
+
{ id: tmpId, path: tmpId, name: f.name, isMd: isMdFile, type: 'document' },
|
|
968
|
+
]);
|
|
969
|
+
void processUpload(f, tmpId, isMdFile);
|
|
970
|
+
});
|
|
971
|
+
}
|
|
972
|
+
catch (_err) {
|
|
973
|
+
errorLog('Attachments:UploadMerge', 'Fatal exception caught during PDF merge', logError(_err));
|
|
974
|
+
toast.error('Failed to merge PDFs.');
|
|
975
|
+
}
|
|
976
|
+
finally {
|
|
977
|
+
setUploading(false);
|
|
978
|
+
}
|
|
979
|
+
}, children: "Merge to Single PDF" })] })] })), !!viewDlg && (_jsxs(DialogContent, { className: "flex max-h-[85vh] flex-col sm:max-w-4xl", children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { children: viewDlg.title || viewDlg.name }), _jsx(DialogDescription, { className: "truncate", children: viewDlg.sourceUrl || viewDlg.path })] }), _jsx("div", { className: "min-h-0 flex-1 overflow-y-auto py-4", children: viewDlg.isMd ? (_jsx(CodeBlock, { docsSource: true, code: typeof viewDlg.content === 'string'
|
|
980
|
+
? viewDlg.content
|
|
981
|
+
: latestContent(viewDlg.content) || '', language: "mdx", tone: "view", className: "my-0 text-xs" })) : textAsset(viewDlg) ? (_jsx(CodeBlock, { code: typeof viewDlg.content === 'string' ? viewDlg.content : '', language: "text", tone: "view", className: "my-0 text-xs" })) : (_jsxs("div", { className: "flex flex-col items-center justify-center gap-4 py-12 text-primary-11", children: [_jsx(DocumentIcon, { className: "size-16 opacity-50", "aria-hidden": "true" }), _jsx("p", { children: "Binary storage entry." }), viewDlg.unavailable ? (_jsx("p", { children: "Source asset is unavailable." })) : (_jsxs(Button, { onClick: () => {
|
|
982
|
+
void (async () => {
|
|
983
|
+
if (!viewDlg)
|
|
984
|
+
return;
|
|
985
|
+
try {
|
|
986
|
+
if (viewDlg.type === 'tsdocs') {
|
|
987
|
+
const scopeMatch = viewDlg.path.match(TerraQualityRegex.REGEX_DOCS_TSDOCS_REGEX());
|
|
988
|
+
const scope = scopeMatch ? scopeMatch[1] : viewDlg.path;
|
|
989
|
+
const { data, error } = await actions.read.tsdocs({ scope });
|
|
990
|
+
if (!error && data?.docs) {
|
|
991
|
+
const url = URL.createObjectURL(new Blob([
|
|
992
|
+
JSON.stringify((Array.isArray(data.docs) ? data.docs : [])
|
|
993
|
+
.filter(isRec)
|
|
994
|
+
.map((d) => ({
|
|
995
|
+
title: d.title,
|
|
996
|
+
slug: d.slug,
|
|
997
|
+
source: d.body,
|
|
998
|
+
})), null, 2),
|
|
999
|
+
], { type: 'application/json' }));
|
|
1000
|
+
const a = document.createElement('a');
|
|
1001
|
+
a.href = url;
|
|
1002
|
+
a.download = `${sanitizeName(scope.replace(TerraQualityRegex.REGEX_G_REGEX_10(), '-'))}.json`;
|
|
1003
|
+
document.body.appendChild(a);
|
|
1004
|
+
a.click();
|
|
1005
|
+
document.body.removeChild(a);
|
|
1006
|
+
URL.revokeObjectURL(url);
|
|
1007
|
+
}
|
|
1008
|
+
else
|
|
1009
|
+
toast.error('Failed to download TSDocs reference.');
|
|
1010
|
+
return;
|
|
1011
|
+
}
|
|
1012
|
+
if (viewDlg.type === 'youtube' || viewDlg.type === 'website') {
|
|
1013
|
+
window.open(viewDlg.sourceUrl || viewDlg.path, '_blank');
|
|
1014
|
+
return;
|
|
1015
|
+
}
|
|
1016
|
+
let dlName = viewDlg.title || viewDlg.name;
|
|
1017
|
+
const extMatch = viewDlg.path
|
|
1018
|
+
.split('?')[0]
|
|
1019
|
+
?.match(TerraQualityRegex.REGEX_A_Z0_9_I_REGEX());
|
|
1020
|
+
if (extMatch &&
|
|
1021
|
+
!dlName.toLowerCase().endsWith(extMatch[0].toLowerCase()))
|
|
1022
|
+
dlName = `${dlName}${extMatch[0]}`;
|
|
1023
|
+
else if (viewDlg.type === 'document' &&
|
|
1024
|
+
!dlName.toLowerCase().endsWith('.pdf'))
|
|
1025
|
+
dlName = `${dlName}.pdf`;
|
|
1026
|
+
const { data, error } = await actions.read.asset.get({
|
|
1027
|
+
path: viewDlg.path,
|
|
1028
|
+
});
|
|
1029
|
+
if (error || !data)
|
|
1030
|
+
throw error;
|
|
1031
|
+
const url = URL.createObjectURL(new Blob([data], {
|
|
1032
|
+
type: viewDlg.type === 'document'
|
|
1033
|
+
? 'application/pdf'
|
|
1034
|
+
: 'application/octet-stream',
|
|
1035
|
+
}));
|
|
1036
|
+
const a = document.createElement('a');
|
|
1037
|
+
a.href = url;
|
|
1038
|
+
a.download = dlName;
|
|
1039
|
+
document.body.appendChild(a);
|
|
1040
|
+
a.click();
|
|
1041
|
+
document.body.removeChild(a);
|
|
1042
|
+
URL.revokeObjectURL(url);
|
|
1043
|
+
}
|
|
1044
|
+
catch (_err) {
|
|
1045
|
+
toast.error('Failed to download asset.');
|
|
1046
|
+
}
|
|
1047
|
+
})();
|
|
1048
|
+
}, children: [_jsx(DownloadIcon, { className: "mr-2 size-4" }), " Download Asset"] }))] })) }), _jsx(DialogFooter, { children: _jsx(Button, { variant: "ghost", onClick: () => {
|
|
1049
|
+
setViewDlg(null);
|
|
1050
|
+
}, children: "Close" }) })] })), renameDlg?.open && (_jsxs(DialogContent, { className: "sm:max-w-md", children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { children: "Rename Attachment" }), _jsx(DialogDescription, { children: "Assign folder-compliant file identity token string parameters." })] }), _jsx("div", { className: "py-4", children: _jsx(Input, { autoFocus: true, value: renameInput, onChange: (e) => {
|
|
1051
|
+
setRenameInput(e.target.value);
|
|
1052
|
+
}, onKeyDown: (e) => e.key === 'Enter' && void renameAttch(renameInput) }) }), _jsxs(DialogFooter, { children: [_jsx(Button, { variant: 'ghost', onClick: () => { setRenameDlg(null); }, children: "Cancel" }), _jsx(Button, { disabled: !renameInput.trim(), onClick: () => void renameAttch(renameInput), children: "Rename" })] })] })), transferDlg?.open &&
|
|
1053
|
+
// prettier-ignore
|
|
1054
|
+
_jsxs(DialogContent, { className: 'sm:max-w-md', children: [_jsxs(DialogHeader, { children: [_jsxs(DialogTitle, { children: [transferDlg.action === 'copy' ? 'Copy' : 'Move', " Asset", transferDlg.items.length > 1 ? 's' : ''] }), _jsx(DialogDescription, { children: "Shift structural components between system documents." })] }), _jsx("div", { className: 'py-4', children: _jsxs(Select, { value: transferTgt, onValueChange: setTransferTgt, children: [_jsx(SelectTrigger, { "aria-label": 'Select destination page', children: _jsx(SelectValue, { placeholder: 'Select destination page' }) }), _jsxs(SelectContent, { className: 'max-h-60', children: [_jsx(SelectItem, { value: '__new__', className: 'font-semibold text-primary-11', children: "\u2728 Move to new page..." }), localLeaves.length ? (localLeaves.map(l => (_jsx(SelectItem, { value: l.path, children: l.title || l.origName }, l.path)))) : (_jsx(SelectItem, { value: 'none', disabled: true, children: "No target layers found" }))] })] }) }), _jsxs(DialogFooter, { children: [_jsx(Button, { variant: 'ghost', onClick: () => { setTransferDlg(null); }, children: "Cancel" }), _jsx(Button, { disabled: !transferTgt || transferTgt === 'none' || transferring, loading: transferring, onClick: () => {
|
|
1055
|
+
void (async () => {
|
|
1056
|
+
if (!transferDlg || !transferTgt || transferTgt === 'none' || transferDlg.items.length === 0)
|
|
1057
|
+
return;
|
|
1058
|
+
setTransferring(true);
|
|
1059
|
+
try {
|
|
1060
|
+
let destPath = transferTgt;
|
|
1061
|
+
if (transferTgt === '__new__') {
|
|
1062
|
+
const title = window.prompt('Enter a title for the new page:');
|
|
1063
|
+
if (!title) {
|
|
1064
|
+
setTransferring(false);
|
|
1065
|
+
return;
|
|
1066
|
+
}
|
|
1067
|
+
const dir = dirname(dPath);
|
|
1068
|
+
const nPath = `${dir === '.' ? '' : `${dir}/`}${sanitizeName(title)}.mdx`;
|
|
1069
|
+
const { data: nDoc, error: createErr } = await actions.write.doc.editor({ path: nPath, title, source: '' });
|
|
1070
|
+
if (createErr || !nDoc)
|
|
1071
|
+
throw createErr || new Error('Failed to create new page.');
|
|
1072
|
+
destPath = nPath;
|
|
1073
|
+
}
|
|
1074
|
+
if (transferDlg.action === 'copy') {
|
|
1075
|
+
await Promise.allSettled(transferDlg.items.map(async (i) => {
|
|
1076
|
+
if (i.isMd) {
|
|
1077
|
+
const { data: docData } = await actions.read.doc.get({ path: i.path });
|
|
1078
|
+
await actions.write.doc.save({
|
|
1079
|
+
path: `${dirname(destPath)}/${`${i.name.replace(TerraQualityRegex.REGEX_I_REGEX(), '')}-copy-${Math.floor(Math.random() * 10000)}${i.name.match(TerraQualityRegex.REGEX_I_REGEX())?.[0] ?? ''}`}`,
|
|
1080
|
+
source: docData.source,
|
|
1081
|
+
});
|
|
1082
|
+
}
|
|
1083
|
+
else if (i.id) {
|
|
1084
|
+
await actions.write.attachment.move({ sourceDocPath: docId, targetDocPath: destPath, attachmentKey: i.id });
|
|
1085
|
+
await actions.write.attachment.add({ files: [{ name: i.name }], path: destPath });
|
|
1086
|
+
}
|
|
1087
|
+
}));
|
|
1088
|
+
}
|
|
1089
|
+
else {
|
|
1090
|
+
await Promise.allSettled(transferDlg.items.map(async (i) => {
|
|
1091
|
+
if (i.isMd) {
|
|
1092
|
+
const { data: docData } = await actions.read.doc.get({ path: i.path });
|
|
1093
|
+
await actions.write.doc.commit({ cur: i.path, next: `${dirname(destPath)}/${i.name}`, source: docData.source });
|
|
1094
|
+
}
|
|
1095
|
+
else if (i.id)
|
|
1096
|
+
await actions.write.attachment.move({ sourceDocPath: docId, targetDocPath: destPath, attachmentKey: i.id });
|
|
1097
|
+
}));
|
|
1098
|
+
const itemKeys = new Set(transferDlg.items.flatMap(i => [i.id, i.path].filter(Boolean)));
|
|
1099
|
+
setSisters(p => p.filter(s => !(s.id && itemKeys.has(s.id)) && !(s.path && itemKeys.has(s.path))));
|
|
1100
|
+
}
|
|
1101
|
+
setSel([]);
|
|
1102
|
+
toast.success(`Successfully ${transferDlg.action === 'copy' ? 'copied' : 'moved'} attachments.`);
|
|
1103
|
+
}
|
|
1104
|
+
catch (_err) {
|
|
1105
|
+
errorLog('Attachments:Transfer', 'Transfer failed', logError(_err));
|
|
1106
|
+
toast.error(`Failed to ${transferDlg.action} attachments.`);
|
|
1107
|
+
}
|
|
1108
|
+
finally {
|
|
1109
|
+
setTransferring(false);
|
|
1110
|
+
setTransferDlg(null);
|
|
1111
|
+
}
|
|
1112
|
+
})();
|
|
1113
|
+
}, children: transferDlg.action === 'copy' ? 'Copy' : 'Move' })] })] }), addDialogOpen && (_jsxs(DialogContent, { className: "flex max-h-[85vh] flex-col overflow-hidden sm:max-w-xl", children: [_jsx(DialogHeader, { children: dialogMode === 'select' ? (_jsxs(_Fragment, { children: [_jsx(DialogTitle, { children: "Add Attachment" }), _jsx(DialogDescription, { children: "Select attachment category." })] })) : (_jsxs(_Fragment, { children: [_jsxs(DialogTitle, { className: 'capitalize', children: ["Add ", dialogMode] }), _jsx(DialogDescription, { children: dialogMode === 'tsdocs' ? 'Select an API reference page or folder to link.' : ['youtube', 'website'].includes(dialogMode) ? `Provide URLs to attach ${dialogMode} content.` : `Upload files or provide URLs to attach remote ${dialogMode}s.` })] })) }), _jsx("div", { className: "flex-1 overflow-y-auto py-4", children: dialogMode === 'select' ? (_jsx("div", { className: "grid grid-cols-2 gap-4 sm:grid-cols-3", children: [
|
|
1114
|
+
{ Icon: DocumentIcon, text: 'Document', type: 'document' },
|
|
1115
|
+
{ Icon: ImageIcon, text: 'Image', type: 'image' },
|
|
1116
|
+
{ Icon: YouTubeIcon, text: 'YouTube', type: 'youtube' },
|
|
1117
|
+
{ Icon: LinkIcon, text: 'Website', type: 'website' },
|
|
1118
|
+
{ Icon: CatalogIcon, text: 'TsDocs', type: 'tsdocs' },
|
|
1119
|
+
{ Icon: BoxIcon, text: 'Other', type: 'other' },
|
|
1120
|
+
].map(({ Icon: i, text: t, type: v }) => (_jsxs("button", { type: "button", "aria-label": `Add ${t} attachment`, className: "flex cursor-pointer flex-col items-center justify-center rounded-xl border border-primary-6 bg-transparent p-6 text-center transition-colors hover:border-primary-8 hover:bg-primary-3/50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-8", onClick: () => {
|
|
1121
|
+
setDialogMode(v);
|
|
1122
|
+
}, children: [createElement(i, {
|
|
1123
|
+
className: 'size-6 text-primary-11',
|
|
1124
|
+
'aria-hidden': 'true',
|
|
1125
|
+
}), _jsx("span", { className: "mt-2 text-sm font-medium text-primary-11", children: t })] }, t))) })) : (_jsxs("div", { className: "flex flex-col gap-4", children: [!['youtube', 'website', 'tsdocs'].includes(dialogMode) && (_jsxs(Button, { variant: "outline", onClick: () => {
|
|
1126
|
+
setAddDialogOpen(false);
|
|
1127
|
+
fileRef.current?.click();
|
|
1128
|
+
}, children: [_jsx(UploadIcon, { className: "mr-2 size-5" }), "Select Files to Upload"] })), _jsxs("div", { className: "space-y-2", children: [_jsx(Label, { children: dialogMode === 'tsdocs'
|
|
1129
|
+
? 'Select Reference'
|
|
1130
|
+
: !['youtube', 'website'].includes(dialogMode)
|
|
1131
|
+
? 'Or Import via URL'
|
|
1132
|
+
: 'Import via URL' }), dialogMode === 'tsdocs' ? (_jsx(TsDocsSelect, { variant: "inline", multiple: true, value: urlInput ? urlInput.split('\n').filter(Boolean) : [], onChange: (v) => {
|
|
1133
|
+
setUrlInput(Array.isArray(v) ? v.join('\n') : v);
|
|
1134
|
+
} })) : (_jsx(Textarea, { autoFocus: true, placeholder: 'https://...\nPaste multiple URLs on new lines', value: urlInput, onChange: (e) => {
|
|
1135
|
+
setUrlInput(e.target.value);
|
|
1136
|
+
}, rows: 4, onKeyDown: (e) => {
|
|
1137
|
+
if (e.key === 'Enter' && !e.shiftKey) {
|
|
1138
|
+
e.preventDefault();
|
|
1139
|
+
void addRemote(urlInput, dialogMode);
|
|
1140
|
+
}
|
|
1141
|
+
} }))] })] })) }), _jsx(DialogFooter, { className: "shrink-0 border-t border-primary-6 pt-4", children: dialogMode === 'select' ? (_jsx(Button, { variant: "ghost", onClick: () => {
|
|
1142
|
+
setAddDialogOpen(false);
|
|
1143
|
+
}, children: "Cancel" })) : (_jsxs(_Fragment, { children: [_jsx(Button, { variant: "ghost", onClick: () => {
|
|
1144
|
+
setDialogMode('select');
|
|
1145
|
+
}, children: "Back" }), _jsx(Button, { disabled: !urlInput.trim() || uploading, loading: uploading, onClick: () => void addRemote(urlInput, dialogMode), children: dialogMode === 'tsdocs' ? 'Attach Reference' : 'Attach URL' })] })) })] }))] })] }));
|
|
1146
|
+
}
|
|
1147
|
+
Attachments.displayName = 'DocsAttachments';
|
|
1148
|
+
//# sourceMappingURL=_attachments.js.map
|