@inkandswitch/patchwork-pkg-base 0.0.99 → 0.0.101

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.
Files changed (58) hide show
  1. package/module-settings-url +1 -1
  2. package/package.json +1 -1
  3. package/packages/chat/dist/index.js +1 -1
  4. package/packages/comments-view/dist/assets/{main-51fB7vpU.js → main-wSSvAVfi.js} +22 -4
  5. package/packages/comments-view/dist/assets/main-wSSvAVfi.js.map +1 -0
  6. package/packages/comments-view/dist/index.js +3 -3
  7. package/packages/drafts/dist/assets/main-CG9HOCai.js +11 -0
  8. package/packages/embed/dist/assets/{tool-Cg7zrpH9.js → tool-D58NGTZ7.js} +4 -2
  9. package/packages/embed/dist/assets/tool-D58NGTZ7.js.map +1 -0
  10. package/packages/embed/dist/index.js +1 -1
  11. package/packages/folder/dist/index.js +1 -1
  12. package/packages/folder/dist/{tool-JSQNX2I6.js → tool-WAWTPB4A.js} +2 -2
  13. package/packages/folder/dist/{tool-JSQNX2I6.js.map → tool-WAWTPB4A.js.map} +1 -1
  14. package/packages/history-view/dist/assets/{HistoryTimeline-OAiVykO2.js → HistoryTimeline-COYNGORP.js} +4 -4
  15. package/packages/history-view/dist/assets/{HistoryTimeline-OAiVykO2.js.map → HistoryTimeline-COYNGORP.js.map} +1 -1
  16. package/packages/history-view/dist/assets/{index-CWHr7XoV.js → index-C1gYt7m5.js} +2 -2
  17. package/packages/history-view/dist/assets/{index-CWHr7XoV.js.map → index-C1gYt7m5.js.map} +1 -1
  18. package/packages/history-view/dist/index.js +1 -1
  19. package/packages/llm-host/dist/LlmConfigTray-DdZHZT4F.js +615 -0
  20. package/packages/llm-host/dist/index.js +1 -1
  21. package/packages/packages/dist/index.js +17 -0
  22. package/packages/patternwitch/tool.js +21 -0
  23. package/packages/sideboard/dist/{chunk-QLI3ZN4W.js → chunk-73XN2I2U.js} +3 -3
  24. package/packages/sideboard/dist/chunk-NS3ADG2Z.js +2 -0
  25. package/packages/sideboard/dist/chunk-NS3ADG2Z.js.map +7 -0
  26. package/packages/sideboard/dist/{chunk-3HE5SPGR.js → chunk-OFWMAVKQ.js} +2 -2
  27. package/packages/sideboard/dist/{create-new-menu-PDAHMB7O.js → create-new-menu-4VNS2UFI.js} +2 -2
  28. package/packages/sideboard/dist/document-list-panel-SCICIJCF.js +2 -0
  29. package/packages/sideboard/dist/index.css +1 -1
  30. package/packages/sideboard/dist/index.css.map +2 -2
  31. package/packages/sideboard/dist/index.js +1 -1
  32. package/packages/sideboard/dist/{item-menu-VIMMKF26.js → item-menu-3JUJN3MS.js} +2 -2
  33. package/packages/sideboard/dist/sideboard/sideboard.js +1 -1
  34. package/packages/sync-indicator/dist/assets/SyncIndicator-B2ag1OoZ.js +1 -1
  35. package/packages/theming/dist/{active-theme-ZEJCS5RM.js → active-theme-BMSIQXBV.js} +2 -2
  36. package/packages/theming/dist/{chunk-FLDRNDLY.js → chunk-Z3JB7ERH.js} +2 -2
  37. package/packages/theming/dist/main.js +3 -3
  38. package/packages/theming/dist/{theme-L3L6DYF3.css → theme-7OG2K56L.css} +2 -0
  39. package/packages/theming/dist/{theme-titlebar-HAEXLVMW.js → theme-titlebar-YIFJINPJ.js} +2 -2
  40. package/packages/theming/dist/{theme-tray-XYB4LGZ6.js → theme-tray-7J247NRY.js} +33 -13
  41. package/packages/theming/dist/theme-tray-7J247NRY.js.map +7 -0
  42. package/packages/theming/dist/tool.js +1 -1
  43. package/plugin-registry-url +1 -1
  44. package/packages/comments-view/dist/assets/main-51fB7vpU.js.map +0 -1
  45. package/packages/embed/dist/assets/tool-Cg7zrpH9.js.map +0 -1
  46. package/packages/llm-host/dist/LlmConfigTray-CkM9XUX1.js +0 -600
  47. package/packages/sideboard/dist/chunk-6LWWNFKU.js +0 -2
  48. package/packages/sideboard/dist/chunk-6LWWNFKU.js.map +0 -7
  49. package/packages/sideboard/dist/document-list-panel-C7R2SL7S.js +0 -2
  50. package/packages/theming/dist/theme-tray-XYB4LGZ6.js.map +0 -7
  51. /package/packages/sideboard/dist/{chunk-QLI3ZN4W.js.map → chunk-73XN2I2U.js.map} +0 -0
  52. /package/packages/sideboard/dist/{chunk-3HE5SPGR.js.map → chunk-OFWMAVKQ.js.map} +0 -0
  53. /package/packages/sideboard/dist/{create-new-menu-PDAHMB7O.js.map → create-new-menu-4VNS2UFI.js.map} +0 -0
  54. /package/packages/sideboard/dist/{document-list-panel-C7R2SL7S.js.map → document-list-panel-SCICIJCF.js.map} +0 -0
  55. /package/packages/sideboard/dist/{item-menu-VIMMKF26.js.map → item-menu-3JUJN3MS.js.map} +0 -0
  56. /package/packages/theming/dist/{active-theme-ZEJCS5RM.js.map → active-theme-BMSIQXBV.js.map} +0 -0
  57. /package/packages/theming/dist/{chunk-FLDRNDLY.js.map → chunk-Z3JB7ERH.js.map} +0 -0
  58. /package/packages/theming/dist/{theme-titlebar-HAEXLVMW.js.map → theme-titlebar-YIFJINPJ.js.map} +0 -0
@@ -3,7 +3,7 @@
3
3
  try {
4
4
  if (typeof document != "undefined") {
5
5
  var elementStyle = document.createElement("style");
6
- elementStyle.appendChild(document.createTextNode("@layer package {\n :root,\n :host,\n [theme] {\n --embed-frame-bg: var(--editor-fill, white);\n --embed-frame-fg: var(--editor-line, black);\n --embed-frame-muted: var(--editor-line-offset-30, #666);\n --embed-frame-border: var(--editor-fill-offset-20, #ddd);\n --embed-frame-hover: var(--editor-fill-offset-10, #f4f4f4);\n --embed-frame-highlight: var(--editor-fill-offset-10, #f0f0f0);\n --embed-frame-family: var(--editor-family-sans, system-ui, sans-serif);\n }\n}\n\n.embed-frame {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--embed-frame-bg);\n color: var(--embed-frame-fg);\n font-family: var(--embed-frame-family);\n}\n\n.embed-frame .header {\n display: flex;\n align-items: center;\n gap: var(--studio-space-sm, 0.5rem);\n padding: var(--studio-space-2xs, 0.25rem) var(--studio-space-sm, 0.5rem);\n border-bottom: 1px solid var(--embed-frame-border);\n flex-shrink: 0;\n}\n\n.embed-frame .title {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-weight: 500;\n font-size: 0.85em;\n cursor: default;\n}\n\n.embed-frame .title[data-renamable] {\n cursor: text;\n}\n\n.embed-frame .rename-input {\n flex: 1;\n min-width: 0;\n font: inherit;\n font-size: 0.85em;\n color: inherit;\n background: none;\n border: 1px solid var(--embed-frame-border);\n border-radius: var(--studio-radius-sm, 4px);\n padding: 0 var(--studio-space-2xs, 0.25rem);\n outline: none;\n}\n\n.embed-frame .version {\n font-size: 0.7em;\n color: var(--embed-frame-muted);\n flex-shrink: 0;\n}\n\n.embed-frame .tool-btn {\n display: inline-flex;\n align-items: center;\n height: 20px;\n padding: 0 var(--studio-space-sm, 0.5rem);\n border: 1px solid var(--embed-frame-border);\n border-radius: var(--studio-radius-round, 9999px);\n background: none;\n color: var(--embed-frame-muted);\n font: inherit;\n font-size: 0.75em;\n font-weight: 500;\n cursor: pointer;\n white-space: nowrap;\n max-width: 10rem;\n overflow: hidden;\n text-overflow: ellipsis;\n flex-shrink: 0;\n transition: background var(--studio-transition-fast, 0.1s ease);\n}\n\n.embed-frame .tool-btn:hover {\n background: var(--embed-frame-hover);\n color: var(--embed-frame-fg);\n}\n\n.embed-frame .open-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 20px;\n height: 20px;\n border: none;\n background: none;\n color: inherit;\n padding: 0;\n cursor: pointer;\n opacity: 0.7;\n flex-shrink: 0;\n}\n\n.embed-frame .open-btn:hover {\n opacity: 1;\n}\n\n.embed-frame .content {\n flex: 1;\n min-height: 0;\n position: relative;\n}\n\n.embed-frame .content > patchwork-view {\n display: block;\n width: 100%;\n height: 100%;\n}\n\n.embed-frame .tool-menu[popover] {\n position: fixed;\n inset: unset;\n margin: 0;\n padding: 0;\n min-width: 180px;\n border: 1px solid var(--embed-frame-border);\n border-radius: var(--studio-radius-sm, 4px);\n background: var(--embed-frame-bg);\n color: var(--embed-frame-fg);\n box-shadow: var(--studio-shadow-sm, 0 2px 8px rgba(0, 0, 0, 0.08));\n overflow: hidden;\n font-family: var(--embed-frame-family);\n font-size: 0.85em;\n}\n\n.embed-frame .tool-menu .list {\n max-height: 200px;\n overflow-y: auto;\n padding: var(--studio-space-2xs, 0.25rem);\n}\n\n.embed-frame .tool-menu .item {\n display: block;\n width: 100%;\n padding: var(--studio-space-2xs, 0.25rem) var(--studio-space-sm, 0.5rem);\n border: none;\n border-radius: var(--studio-radius-sm, 4px);\n background: none;\n color: inherit;\n font: inherit;\n text-align: left;\n cursor: pointer;\n white-space: nowrap;\n}\n\n.embed-frame .tool-menu .item:hover {\n background: var(--embed-frame-highlight);\n}\n\n.embed-frame .tool-menu .item[data-current] {\n font-weight: 600;\n}"));
6
+ elementStyle.appendChild(document.createTextNode("@layer package {\n :root,\n :host,\n [theme] {\n --embed-frame-bg: var(--editor-fill, white);\n --embed-frame-fg: var(--editor-line, black);\n --embed-frame-muted: var(--editor-line-offset-30, #666);\n --embed-frame-border: var(--editor-fill-offset-20, #ddd);\n --embed-frame-hover: var(--editor-fill-offset-10, #f4f4f4);\n --embed-frame-highlight: var(--editor-fill-offset-10, #f0f0f0);\n --embed-frame-family: var(--editor-family-sans, system-ui, sans-serif);\n }\n}\n\n.embed-frame {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--embed-frame-bg);\n color: var(--embed-frame-fg);\n font-family: var(--embed-frame-family);\n}\n\n.embed-frame .header {\n display: flex;\n align-items: center;\n gap: var(--studio-space-sm, 0.5rem);\n padding: var(--studio-space-2xs, 0.25rem) var(--studio-space-sm, 0.5rem);\n border-bottom: 1px solid var(--embed-frame-border);\n flex-shrink: 0;\n}\n\n.embed-frame .title {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-weight: 500;\n font-size: 0.85em;\n cursor: default;\n}\n\n.embed-frame .title[data-renamable] {\n cursor: text;\n}\n\n.embed-frame .rename-input {\n flex: 1;\n min-width: 0;\n font: inherit;\n font-size: 0.85em;\n color: inherit;\n background: none;\n border: 1px solid var(--embed-frame-border);\n border-radius: var(--studio-radius-sm, 4px);\n padding: 0 var(--studio-space-2xs, 0.25rem);\n outline: none;\n}\n\n.embed-frame .version {\n font-size: 0.7em;\n color: var(--embed-frame-muted);\n flex-shrink: 0;\n}\n\n.embed-frame .tool-btn {\n display: inline-flex;\n align-items: center;\n height: 20px;\n padding: 0 var(--studio-space-sm, 0.5rem);\n border: 1px solid var(--embed-frame-border);\n border-radius: var(--studio-radius-round, 9999px);\n background: none;\n color: var(--embed-frame-muted);\n font: inherit;\n font-size: 0.75em;\n font-weight: 500;\n cursor: pointer;\n white-space: nowrap;\n max-width: 10rem;\n overflow: hidden;\n text-overflow: ellipsis;\n flex-shrink: 0;\n transition: background var(--studio-transition-fast, 0.1s ease);\n}\n\n.embed-frame .tool-btn:hover {\n background: var(--embed-frame-hover);\n color: var(--embed-frame-fg);\n}\n\n.embed-frame .open-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 20px;\n height: 20px;\n border: none;\n background: none;\n color: inherit;\n padding: 0;\n cursor: pointer;\n opacity: 0.7;\n flex-shrink: 0;\n}\n\n.embed-frame .open-btn:hover {\n opacity: 1;\n}\n\n.embed-frame .content {\n flex: 1;\n min-height: 0;\n position: relative;\n}\n\n.embed-frame .content > patchwork-view {\n display: block;\n width: 100%;\n height: 100%;\n}\n\n.embed-frame .tool-menu[popover] {\n position: fixed;\n inset: unset;\n margin: 0;\n padding: 0;\n min-width: 180px;\n border: 1px solid var(--embed-frame-border);\n border-radius: var(--studio-radius-sm, 4px);\n background: var(--embed-frame-bg);\n color: var(--embed-frame-fg);\n box-shadow: var(--studio-shadow-sm, 0 2px 8px rgba(0, 0, 0, 0.08));\n overflow: hidden;\n font-family: var(--embed-frame-family);\n font-size: 0.85em;\n /* Grows out of the tool button (origin set in tool.tsx). Closing is instant. */\n transition:\n opacity 150ms var(--studio-ease-out, cubic-bezier(0.23, 1, 0.32, 1)),\n transform 150ms var(--studio-ease-out, cubic-bezier(0.23, 1, 0.32, 1));\n}\n@starting-style {\n .embed-frame .tool-menu[popover]:popover-open {\n opacity: 0;\n transform: scale(0.97);\n }\n}\n\n.embed-frame .tool-menu .list {\n max-height: 200px;\n overflow-y: auto;\n padding: var(--studio-space-2xs, 0.25rem);\n}\n\n.embed-frame .tool-menu .item {\n display: block;\n width: 100%;\n padding: var(--studio-space-2xs, 0.25rem) var(--studio-space-sm, 0.5rem);\n border: none;\n border-radius: var(--studio-radius-sm, 4px);\n background: none;\n color: inherit;\n font: inherit;\n text-align: left;\n cursor: pointer;\n white-space: nowrap;\n}\n\n.embed-frame .tool-menu .item:hover {\n background: var(--embed-frame-highlight);\n}\n\n.embed-frame .tool-menu .item[data-current] {\n font-weight: 600;\n}"));
7
7
  document.head.appendChild(elementStyle);
8
8
  }
9
9
  } catch (e) {
@@ -102,9 +102,11 @@ function Frame(props) {
102
102
  if (rect.left + menuWidth > window.innerWidth - 8) {
103
103
  menuEl.style.left = "";
104
104
  menuEl.style.right = `${window.innerWidth - rect.right}px`;
105
+ menuEl.style.transformOrigin = "top right";
105
106
  } else {
106
107
  menuEl.style.right = "";
107
108
  menuEl.style.left = `${rect.left}px`;
109
+ menuEl.style.transformOrigin = "top left";
108
110
  }
109
111
  menuEl.showPopover();
110
112
  }
@@ -233,4 +235,4 @@ delegateEvents(["click", "keydown"]);
233
235
  export {
234
236
  EmbedFrame as default
235
237
  };
236
- //# sourceMappingURL=tool-Cg7zrpH9.js.map
238
+ //# sourceMappingURL=tool-D58NGTZ7.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-D58NGTZ7.js","sources":["../../src/tool.tsx"],"sourcesContent":["// Embed frame: chrome (title, tool picker, open button) around a nested\n// <patchwork-view>. Hosts mount it via <patchwork-view tool-id=\"embed\">, pin\n// the inner tool with the `embed-tool-id` attribute, and persist picks by\n// listening for the bubbling `patchwork:embed-tool-changed` event.\n\nimport {\n getFallbackTool,\n getRegistry,\n getSupportedToolsForType,\n isLoadedPlugin,\n type DatatypeImplementation,\n type ToolDescription,\n type ToolImplementation,\n} from \"@inkandswitch/patchwork-plugins\";\nimport { getType } from \"@inkandswitch/patchwork-filesystem\";\nimport { openDocument } from \"@inkandswitch/patchwork-elements\";\nimport type { DocHandle } from \"@automerge/automerge-repo\";\nimport { createEffect, createSignal, For, onCleanup, Show } from \"solid-js\";\nimport { render } from \"solid-js/web\";\nimport { version } from \"../package.json\";\nimport \"./embed.css\";\n\nconst EMBED_TOOL_ID = \"embed\";\n\nconst EmbedFrame: ToolImplementation<any> = (handle, element) =>\n render(() => <Frame handle={handle} element={element} />, element);\n\nexport default EmbedFrame;\n\ntype FrameProps = {\n handle: DocHandle<any>;\n element: HTMLElement;\n};\n\nfunction Frame(props: FrameProps) {\n // Static per mount (the render contract passes them once); safe to unwrap.\n const { handle, element } = props;\n\n // `element` is the inner <patchwork-view-legacy>; hosts set `embed-tool-id`\n // on the outer <patchwork-view>, so check there too.\n const [pinnedToolId, setPinnedToolId] = createSignal(\n element.getAttribute(\"embed-tool-id\") ||\n element.closest(\"patchwork-view\")?.getAttribute(\"embed-tool-id\") ||\n null\n );\n const [doc, setDoc] = createSignal<any>(handle.doc(), { equals: false });\n const [datatype, setDatatype] =\n createSignal<DatatypeImplementation<any> | null>(null);\n const [renaming, setRenaming] = createSignal(false);\n const [menuOpen, setMenuOpen] = createSignal(false);\n\n const onDocChange = () => setDoc(handle.doc());\n handle.on(\"change\", onDocChange);\n onCleanup(() => handle.off(\"change\", onDocChange));\n void loadDatatype();\n\n let menuEl!: HTMLDivElement;\n let toolButtonEl!: HTMLButtonElement;\n\n const title = () => {\n try {\n return datatype()?.getTitle(doc()) || \"Untitled\";\n } catch {\n // getTitle throws on unexpected doc shapes\n return \"Untitled\";\n }\n };\n\n const canRename = () => Boolean(datatype()?.setTitle);\n\n // With no pinned tool the nested view renders the doc's fallback tool, so\n // surface that as the selection rather than a special \"unselected\" state.\n const effectiveToolId = () => {\n datatype(); // re-check once the datatype (and the tools it ships) loaded\n if (pinnedToolId()) return pinnedToolId();\n try {\n return getFallbackTool(doc())?.id ?? null;\n } catch {\n return null;\n }\n };\n\n const toolName = () => {\n const toolId = effectiveToolId();\n if (!toolId) return \"\";\n const tool = getRegistry<ToolDescription>(\"patchwork:tool\").get(toolId);\n return tool?.name ?? toolId;\n };\n\n function setTool(toolId: string): void {\n if (!toolId || toolId === pinnedToolId()) return;\n setPinnedToolId(toolId);\n element.dispatchEvent(\n new CustomEvent(\"patchwork:embed-tool-changed\", {\n detail: { url: handle.url, toolId },\n bubbles: true,\n composed: true,\n })\n );\n }\n\n function finishRename(commit: boolean, value: string): void {\n if (!renaming()) return;\n setRenaming(false);\n const trimmed = value.trim();\n if (commit && trimmed && trimmed !== title()) {\n handle.change((d: any) => datatype()!.setTitle!(d, trimmed));\n }\n }\n\n function toggleMenu(): void {\n if (menuEl.matches(\":popover-open\")) {\n menuEl.hidePopover();\n return;\n }\n setMenuOpen(true);\n const rect = toolButtonEl.getBoundingClientRect();\n const menuWidth = Math.max(rect.width, 180);\n menuEl.style.top = `${rect.bottom + 2}px`;\n menuEl.style.minWidth = `${menuWidth}px`;\n if (rect.left + menuWidth > window.innerWidth - 8) {\n menuEl.style.left = \"\";\n menuEl.style.right = `${window.innerWidth - rect.right}px`;\n menuEl.style.transformOrigin = \"top right\";\n } else {\n menuEl.style.right = \"\";\n menuEl.style.left = `${rect.left}px`;\n menuEl.style.transformOrigin = \"top left\";\n }\n menuEl.showPopover();\n }\n\n function listTools(): ToolDescription[] {\n const d = doc();\n const type = d && getType(d);\n if (!type) return [];\n const list = getSupportedToolsForType(type).filter(\n (t) => !t.unlisted && !t.forTitleBar && t.id !== EMBED_TOOL_ID\n );\n // Datatype-specific tools before the generic wildcard ones.\n list.sort((a, b) => Number(isWildcard(a)) - Number(isWildcard(b)));\n return list;\n }\n\n // Built imperatively rather than as JSX so we don't have to teach Solid's\n // JSX types about the custom element.\n const nestedView = document.createElement(\"patchwork-view\");\n nestedView.setAttribute(\"doc-url\", handle.url);\n createEffect(() => {\n const toolId = pinnedToolId();\n if (toolId) nestedView.setAttribute(\"tool-id\", toolId);\n else nestedView.removeAttribute(\"tool-id\");\n });\n\n // Load the datatype (for getTitle/setTitle and its tools).\n async function loadDatatype(): Promise<void> {\n const d = handle.doc();\n const type = d && getType(d);\n if (!type) return;\n const registry = getRegistry(\"patchwork:datatype\");\n try {\n await registry.load(type);\n } catch {\n // datatype unavailable; keep the fallbacks\n }\n const loaded = registry.get(type);\n if (loaded && isLoadedPlugin(loaded)) {\n setDatatype(() => loaded.module as DatatypeImplementation<any>);\n }\n }\n\n return (\n <div class=\"embed-frame\">\n <div class=\"header\">\n <Show\n when={!renaming()}\n fallback={\n <input\n class=\"rename-input\"\n value={title()}\n ref={(el) =>\n queueMicrotask(() => {\n el.focus();\n el.select();\n })\n }\n onKeyDown={(e) => {\n e.stopPropagation();\n if (e.key === \"Enter\") finishRename(true, e.currentTarget.value);\n if (e.key === \"Escape\")\n finishRename(false, e.currentTarget.value);\n }}\n onBlur={(e) => finishRename(true, e.currentTarget.value)}\n />\n }\n >\n <span\n class=\"title\"\n data-renamable={canRename() ? \"\" : undefined}\n title={canRename() ? \"Click to rename\" : undefined}\n onClick={() => canRename() && setRenaming(true)}\n >\n {title()}\n </span>\n </Show>\n {/* Deploy check: which build is actually running. */}\n <span class=\"version\">v{version}</span>\n <button\n class=\"tool-btn\"\n title={\"Open with\\u2026\"}\n ref={toolButtonEl}\n onClick={toggleMenu}\n >\n {toolName()}\n </button>\n <button\n class=\"open-btn\"\n title=\"Open document\"\n innerHTML={openIcon}\n onClick={() =>\n openDocument(element, handle.url, pinnedToolId() || undefined)\n }\n />\n </div>\n <div class=\"content\">{nestedView}</div>\n <div\n class=\"tool-menu\"\n popover=\"auto\"\n ref={(el) => {\n menuEl = el;\n // Unrender the item list while closed.\n el.addEventListener(\"toggle\", (e) => {\n if ((e as { newState?: string }).newState === \"closed\") {\n setMenuOpen(false);\n }\n });\n }}\n >\n <Show when={menuOpen()}>\n <div class=\"list\">\n <For each={listTools()}>\n {(tool) => (\n <button\n class=\"item\"\n data-current={tool.id === effectiveToolId() ? \"\" : undefined}\n onClick={() => {\n menuEl.hidePopover();\n setTool(tool.id);\n }}\n >\n {tool.name || tool.id}\n </button>\n )}\n </For>\n </div>\n </Show>\n </div>\n </div>\n );\n}\n\nfunction isWildcard(tool: ToolDescription): boolean {\n return (\n tool.supportedDatatypes === \"*\" ||\n (Array.isArray(tool.supportedDatatypes) &&\n tool.supportedDatatypes.includes(\"*\"))\n );\n}\n\nconst openIcon = `<svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n\t<path d=\"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6\"></path>\n\t<polyline points=\"15 3 21 3 21 9\"></polyline>\n\t<line x1=\"10\" y1=\"14\" x2=\"21\" y2=\"3\"></line>\n</svg>`;\n"],"names":["EMBED_TOOL_ID","EmbedFrame","handle","element","render","_$createComponent","Frame","props","pinnedToolId","setPinnedToolId","createSignal","getAttribute","closest","doc","setDoc","equals","datatype","setDatatype","renaming","setRenaming","menuOpen","setMenuOpen","onDocChange","on","onCleanup","off","loadDatatype","menuEl","toolButtonEl","title","getTitle","canRename","Boolean","setTitle","effectiveToolId","getFallbackTool","id","toolName","toolId","tool","getRegistry","get","name","setTool","dispatchEvent","CustomEvent","detail","url","bubbles","composed","finishRename","commit","value","trimmed","trim","change","d","toggleMenu","matches","hidePopover","rect","getBoundingClientRect","menuWidth","Math","max","width","style","top","bottom","minWidth","left","window","innerWidth","right","transformOrigin","showPopover","listTools","type","getType","list","getSupportedToolsForType","filter","t","unlisted","forTitleBar","sort","a","b","Number","isWildcard","nestedView","document","createElement","setAttribute","createEffect","removeAttribute","registry","load","loaded","isLoadedPlugin","module","_el$","_tmpl$3","_el$2","firstChild","_el$4","_el$6","nextSibling","_el$7","_el$8","_el$9","_$insert","Show","when","fallback","_el$1","_tmpl$4","addEventListener","e","currentTarget","$$keydown","stopPropagation","key","_$use","el","queueMicrotask","focus","select","_$effect","children","_el$3","_tmpl$","$$click","_p$","_v$","undefined","_v$2","_$setAttribute","version","_ref$","openDocument","innerHTML","openIcon","newState","_el$0","_tmpl$2","For","each","_el$10","_tmpl$5","supportedDatatypes","Array","isArray","includes","_$delegateEvents"],"mappings":"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"}
@@ -82,7 +82,7 @@ const plugins = [
82
82
  unlisted: true,
83
83
  async load() {
84
84
  return (await __vitePreload(async () => {
85
- const { default: __vite_default__ } = await import("./assets/tool-Cg7zrpH9.js");
85
+ const { default: __vite_default__ } = await import("./assets/tool-D58NGTZ7.js");
86
86
  return { default: __vite_default__ };
87
87
  }, true ? [] : void 0, import.meta.url)).default;
88
88
  }
@@ -27,7 +27,7 @@ var plugins = [
27
27
  name: "Folder Viewer",
28
28
  supportedDatatypes: ["folder", "directory"],
29
29
  async load() {
30
- const { FolderTool } = await import("./tool-JSQNX2I6.js");
30
+ const { FolderTool } = await import("./tool-WAWTPB4A.js");
31
31
  return FolderTool;
32
32
  }
33
33
  }
@@ -17,7 +17,7 @@ import {
17
17
  } from "@inkandswitch/patchwork-plugins";
18
18
 
19
19
  // src/styles.css
20
- var styles_default = "@layer package {\n:root,\n:host,\n[theme] {\n /* The well the cards sit in \u2014 slightly recessed surface. */\n --folder-view-well: var(--editor-fill-offset-10, #f2f2f2);\n --folder-view-well-edge: var(--editor-fill-offset-30, #d6d6d6);\n --folder-view-fg: var(--editor-line, black);\n --folder-view-muted: var(--editor-line-offset-50, #999);\n --folder-view-border: var(--editor-fill-offset-20, #e5e5e5);\n\n /* A card = a raised surface sitting on the well. */\n --folder-view-card: var(--editor-fill, white);\n --folder-view-card-border: var(--editor-fill-offset-20, #e5e5e5);\n\n --folder-view-accent: var(--studio-primary-fill, var(--studio-primary, #35f7ca));\n --folder-view-accent-line: var(--studio-primary-line, var(--editor-fill, white));\n --folder-view-accent-text: var(--editor-primary-text, var(--studio-primary-text, var(--studio-primary, #35f7ca)));\n --folder-view-hover: var(--editor-fill-offset-10, #f2f2f2);\n\n /* Layered drop shadow so a card reads as a solid object resting on the\n well \u2014 a tight contact shadow plus a softer cast one. Derived from the\n theme line colour so it inverts in dark themes. */\n --folder-view-card-shadow: 0 1px 2px\n color-mix(in oklch, var(--editor-line, black), transparent 94%),\n 0 2px 8px color-mix(in oklch, var(--editor-line, black), transparent 96%);\n --folder-view-card-shadow-hover: 0 2px 4px\n color-mix(in oklch, var(--editor-line, black), transparent 90%),\n 0 8px 20px color-mix(in oklch, var(--editor-line, black), transparent 93%);\n\n --folder-view-family: var(--editor-family-sans, system-ui, sans-serif);\n}\n}\n\n/* Block: the whole tool. A sunken well with an inset edge. */\n.folder-view {\n height: 100%;\n overflow: auto;\n padding: var(--studio-space-md, 1rem);\n display: flex;\n flex-direction: column;\n gap: var(--studio-space-md, 1rem);\n font-family: var(--folder-view-family);\n color: var(--folder-view-fg);\n background: var(--folder-view-well);\n /* No outer border: the host frame already draws the lines around the pane, so\n the well reads as flush rather than double-edged. */\n}\n\n/* State: a document is being dragged in from the sidebar. Outline the well\n with the accent colour so it reads as an active drop target. */\n.folder-view[data-drop-active] {\n border-color: var(--folder-view-accent);\n box-shadow: inset 0 0 0 2px var(--folder-view-accent);\n}\n\n/* Composition: header row. New-doc button on the left, count on the right. */\n.folder-view .folder-view-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--studio-space-sm, 0.5rem);\n padding-bottom: var(--studio-space-sm, 0.5rem);\n border-bottom: 1px solid var(--folder-view-border);\n}\n\n/* Composition: where we are inside a pushwork directory doc, in place of the\n create-new control (pushwork owns those entries). */\n.folder-view .folder-view-crumbs:not([hidden]) {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: var(--studio-space-2xs, 0.25rem);\n min-width: 0;\n font-size: 0.85rem;\n}\n\n.folder-view .folder-view-crumb {\n font: inherit;\n color: var(--folder-view-fg);\n background: none;\n border: none;\n padding: var(--studio-space-2xs, 0.25rem);\n border-radius: var(--studio-radius-sm, 4px);\n}\n\n.folder-view button.folder-view-crumb {\n color: var(--folder-view-accent-text);\n cursor: pointer;\n}\n\n.folder-view button.folder-view-crumb:hover {\n background: var(--folder-view-hover);\n}\n\n.folder-view .folder-view-crumb-sep {\n color: var(--folder-view-muted);\n}\n\n/* Composition: the create-new control \u2014 a button anchoring a type-picker. */\n.folder-view .folder-create {\n position: relative;\n}\n\n.folder-view .folder-create-button {\n display: inline-flex;\n align-items: center;\n gap: var(--studio-space-2xs, 0.25rem);\n font: inherit;\n font-size: 0.8rem;\n color: var(--folder-view-accent-line);\n background: var(--folder-view-accent);\n border: 1px solid transparent;\n border-radius: var(--studio-radius-sm, 4px);\n padding: var(--studio-space-2xs, 0.25rem) var(--studio-space-sm, 0.5rem);\n cursor: pointer;\n transition: filter var(--studio-transition-fast, 0.1s ease);\n}\n\n.folder-view .folder-create-button:hover {\n filter: brightness(0.96);\n}\n\n.folder-view .folder-create-icon {\n font-size: 1rem;\n line-height: 1;\n}\n\n/* The type-picker popover, anchored under the button. */\n.folder-view .folder-create-menu {\n position: absolute;\n top: calc(100% + var(--studio-space-2xs, 0.25rem));\n left: 0;\n z-index: 10;\n min-width: 12rem;\n max-height: 16rem;\n overflow: auto;\n display: flex;\n flex-direction: column;\n padding: var(--studio-space-3xs, 0.125rem);\n background: var(--folder-view-card);\n border: 1px solid var(--folder-view-card-border);\n border-radius: var(--studio-radius-md, 8px);\n box-shadow: var(--folder-view-card-shadow-hover);\n}\n\n.folder-view .folder-create-menu[hidden] {\n display: none;\n}\n\n.folder-view .folder-create-item {\n text-align: left;\n font: inherit;\n font-size: 0.85rem;\n color: var(--folder-view-fg);\n background: transparent;\n border: 0;\n border-radius: var(--studio-radius-sm, 4px);\n padding: var(--studio-space-2xs, 0.25rem) var(--studio-space-sm, 0.5rem);\n cursor: pointer;\n}\n\n.folder-view .folder-create-item:hover {\n background: var(--folder-view-hover);\n}\n\n.folder-view .folder-create-empty {\n padding: var(--studio-space-sm, 0.5rem);\n font-size: 0.8rem;\n color: var(--folder-view-muted);\n}\n\n.folder-view .folder-view-count {\n font-size: 0.8rem;\n color: var(--folder-view-muted);\n padding: var(--studio-space-2xs, 0.25rem) var(--studio-space-sm, 0.5rem);\n border-radius: var(--studio-radius-round, 9999px);\n background: var(--folder-view-card);\n border: 1px solid var(--folder-view-border);\n}\n\n/* Composition: the list of cards. */\n.folder-view .folder-view-list {\n display: flex;\n flex-direction: column;\n gap: var(--studio-space-md, 1rem);\n padding-bottom: var(--studio-space-md, 1rem);\n}\n\n.folder-view .folder-view-empty {\n text-align: center;\n color: var(--folder-view-muted);\n padding: var(--studio-space-xl, 2rem) 0;\n}\n\n.folder-view-loading {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 100%;\n padding: var(--studio-space-md, 1rem);\n font-family: var(--folder-view-family);\n color: var(--folder-view-muted);\n background: var(--folder-view-card);\n}\n\n/* Block: one rendered file/folder card \u2014 sitting on the well. */\n.folder-view .folder-entry {\n background: var(--folder-view-card);\n border: 1px solid var(--folder-view-card-border);\n border-radius: var(--studio-radius-lg, 12px);\n box-shadow: var(--folder-view-card-shadow);\n overflow: hidden;\n transition: box-shadow var(--studio-transition, 0.15s ease),\n transform var(--studio-transition, 0.15s ease);\n}\n\n.folder-view .folder-entry:hover {\n box-shadow: var(--folder-view-card-shadow-hover);\n /* Lift slightly so the card feels like it peels up off the well. */\n transform: translateY(-1px);\n}\n\n.folder-view .folder-entry-head {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--studio-space-sm, 0.5rem);\n padding: var(--studio-space-sm, 0.5rem) var(--studio-space-md, 1rem);\n}\n\n.folder-view .folder-entry-title {\n display: flex;\n align-items: baseline;\n gap: var(--studio-space-sm, 0.5rem);\n min-width: 0;\n}\n\n.folder-view .folder-entry-name {\n font-weight: 600;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.folder-view .folder-entry-type {\n font-size: 0.7rem;\n color: var(--folder-view-muted);\n padding: var(--studio-space-3xs, 0.125rem) var(--studio-space-2xs, 0.25rem);\n border: 1px solid var(--folder-view-border);\n border-radius: var(--studio-radius-sm, 4px);\n flex-shrink: 0;\n}\n\n.folder-view .folder-entry-open {\n font: inherit;\n font-size: 0.8rem;\n background: none;\n border: none;\n cursor: pointer;\n color: var(--folder-view-accent-text);\n text-decoration: none;\n padding: var(--studio-space-2xs, 0.25rem) var(--studio-space-sm, 0.5rem);\n border-radius: var(--studio-radius-sm, 4px);\n flex-shrink: 0;\n transition: background var(--studio-transition-fast, 0.1s ease);\n}\n\n.folder-view .folder-entry-open:hover {\n background: var(--folder-view-hover);\n}\n\n.folder-view .folder-entry-hint {\n margin: 0;\n padding: 0 var(--studio-space-md, 1rem) var(--studio-space-md, 1rem);\n font-size: 0.85rem;\n color: var(--folder-view-muted);\n}\n\n/* Block: embedded preview body. */\n.folder-view .folder-entry-body {\n flex: 1 1 auto;\n min-height: 0;\n max-height: 300px;\n display: flex;\n flex-direction: column;\n border-top: 1px solid var(--folder-view-border);\n}\n\n.folder-view .folder-entry-scroll {\n height: 100%;\n overflow: auto;\n}\n\n.folder-view .folder-entry-scroll patchwork-view {\n display: block;\n height: 100%;\n}\n";
20
+ var styles_default = "@layer package {\n:root,\n:host,\n[theme] {\n /* The well the cards sit in \u2014 slightly recessed surface. */\n --folder-view-well: var(--editor-fill-offset-10, #f2f2f2);\n --folder-view-well-edge: var(--editor-fill-offset-30, #d6d6d6);\n --folder-view-fg: var(--editor-line, black);\n --folder-view-muted: var(--editor-line-offset-50, #999);\n --folder-view-border: var(--editor-fill-offset-20, #e5e5e5);\n\n /* A card = a raised surface sitting on the well. */\n --folder-view-card: var(--editor-fill, white);\n --folder-view-card-border: var(--editor-fill-offset-20, #e5e5e5);\n\n --folder-view-accent: var(--studio-primary-fill, var(--studio-primary, #35f7ca));\n --folder-view-accent-line: var(--studio-primary-line, var(--editor-fill, white));\n --folder-view-accent-text: var(--editor-primary-text, var(--studio-primary-text, var(--studio-primary, #35f7ca)));\n --folder-view-hover: var(--editor-fill-offset-10, #f2f2f2);\n\n /* Layered drop shadow so a card reads as a solid object resting on the\n well \u2014 a tight contact shadow plus a softer cast one. Derived from the\n theme line colour so it inverts in dark themes. */\n --folder-view-card-shadow: 0 1px 2px\n color-mix(in oklch, var(--editor-line, black), transparent 94%),\n 0 2px 8px color-mix(in oklch, var(--editor-line, black), transparent 96%);\n --folder-view-card-shadow-hover: 0 2px 4px\n color-mix(in oklch, var(--editor-line, black), transparent 90%),\n 0 8px 20px color-mix(in oklch, var(--editor-line, black), transparent 93%);\n\n --folder-view-family: var(--editor-family-sans, system-ui, sans-serif);\n}\n}\n\n/* Block: the whole tool. A sunken well with an inset edge. */\n.folder-view {\n height: 100%;\n overflow: auto;\n padding: var(--studio-space-md, 1rem);\n display: flex;\n flex-direction: column;\n gap: var(--studio-space-md, 1rem);\n font-family: var(--folder-view-family);\n color: var(--folder-view-fg);\n background: var(--folder-view-well);\n /* No outer border: the host frame already draws the lines around the pane, so\n the well reads as flush rather than double-edged. */\n}\n\n/* State: a document is being dragged in from the sidebar. Outline the well\n with the accent colour so it reads as an active drop target. */\n.folder-view[data-drop-active] {\n border-color: var(--folder-view-accent);\n box-shadow: inset 0 0 0 2px var(--folder-view-accent);\n}\n\n/* Composition: header row. New-doc button on the left, count on the right. */\n.folder-view .folder-view-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--studio-space-sm, 0.5rem);\n padding-bottom: var(--studio-space-sm, 0.5rem);\n border-bottom: 1px solid var(--folder-view-border);\n}\n\n/* Composition: where we are inside a pushwork directory doc, in place of the\n create-new control (pushwork owns those entries). */\n.folder-view .folder-view-crumbs:not([hidden]) {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: var(--studio-space-2xs, 0.25rem);\n min-width: 0;\n font-size: 0.85rem;\n}\n\n.folder-view .folder-view-crumb {\n font: inherit;\n color: var(--folder-view-fg);\n background: none;\n border: none;\n padding: var(--studio-space-2xs, 0.25rem);\n border-radius: var(--studio-radius-sm, 4px);\n}\n\n.folder-view button.folder-view-crumb {\n color: var(--folder-view-accent-text);\n cursor: pointer;\n}\n\n.folder-view button.folder-view-crumb:hover {\n background: var(--folder-view-hover);\n}\n\n.folder-view .folder-view-crumb-sep {\n color: var(--folder-view-muted);\n}\n\n/* Composition: the create-new control \u2014 a button anchoring a type-picker. */\n.folder-view .folder-create {\n position: relative;\n}\n\n.folder-view .folder-create-button {\n display: inline-flex;\n align-items: center;\n gap: var(--studio-space-2xs, 0.25rem);\n font: inherit;\n font-size: 0.8rem;\n color: var(--folder-view-accent-line);\n background: var(--folder-view-accent);\n border: 1px solid transparent;\n border-radius: var(--studio-radius-sm, 4px);\n padding: var(--studio-space-2xs, 0.25rem) var(--studio-space-sm, 0.5rem);\n cursor: pointer;\n transition: filter var(--studio-transition-fast, 0.1s ease);\n}\n\n.folder-view .folder-create-button:hover {\n filter: brightness(0.96);\n}\n\n.folder-view .folder-create-icon {\n font-size: 1rem;\n line-height: 1;\n}\n\n/* The type-picker popover, anchored under the button. */\n.folder-view .folder-create-menu {\n position: absolute;\n top: calc(100% + var(--studio-space-2xs, 0.25rem));\n left: 0;\n z-index: 10;\n min-width: 12rem;\n max-height: 16rem;\n overflow: auto;\n display: flex;\n flex-direction: column;\n padding: var(--studio-space-3xs, 0.125rem);\n background: var(--folder-view-card);\n border: 1px solid var(--folder-view-card-border);\n border-radius: var(--studio-radius-md, 8px);\n box-shadow: var(--folder-view-card-shadow-hover);\n /* Grows out of its button. Closing is instant. */\n transform-origin: top left;\n transition:\n opacity 150ms var(--studio-ease-out, cubic-bezier(0.23, 1, 0.32, 1)),\n transform 150ms var(--studio-ease-out, cubic-bezier(0.23, 1, 0.32, 1));\n}\n@starting-style {\n .folder-view .folder-create-menu {\n opacity: 0;\n transform: scale(0.97);\n }\n}\n\n.folder-view .folder-create-menu[hidden] {\n display: none;\n}\n\n.folder-view .folder-create-item {\n text-align: left;\n font: inherit;\n font-size: 0.85rem;\n color: var(--folder-view-fg);\n background: transparent;\n border: 0;\n border-radius: var(--studio-radius-sm, 4px);\n padding: var(--studio-space-2xs, 0.25rem) var(--studio-space-sm, 0.5rem);\n cursor: pointer;\n}\n\n.folder-view .folder-create-item:hover {\n background: var(--folder-view-hover);\n}\n\n.folder-view .folder-create-empty {\n padding: var(--studio-space-sm, 0.5rem);\n font-size: 0.8rem;\n color: var(--folder-view-muted);\n}\n\n.folder-view .folder-view-count {\n font-size: 0.8rem;\n color: var(--folder-view-muted);\n padding: var(--studio-space-2xs, 0.25rem) var(--studio-space-sm, 0.5rem);\n border-radius: var(--studio-radius-round, 9999px);\n background: var(--folder-view-card);\n border: 1px solid var(--folder-view-border);\n}\n\n/* Composition: the list of cards. */\n.folder-view .folder-view-list {\n display: flex;\n flex-direction: column;\n gap: var(--studio-space-md, 1rem);\n padding-bottom: var(--studio-space-md, 1rem);\n}\n\n.folder-view .folder-view-empty {\n text-align: center;\n color: var(--folder-view-muted);\n padding: var(--studio-space-xl, 2rem) 0;\n}\n\n.folder-view-loading {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 100%;\n padding: var(--studio-space-md, 1rem);\n font-family: var(--folder-view-family);\n color: var(--folder-view-muted);\n background: var(--folder-view-card);\n}\n\n/* Block: one rendered file/folder card \u2014 sitting on the well. */\n.folder-view .folder-entry {\n background: var(--folder-view-card);\n border: 1px solid var(--folder-view-card-border);\n border-radius: var(--studio-radius-lg, 12px);\n box-shadow: var(--folder-view-card-shadow);\n overflow: hidden;\n transition: box-shadow var(--studio-transition, 0.15s ease),\n transform var(--studio-transition, 0.15s ease);\n}\n\n.folder-view .folder-entry:hover {\n box-shadow: var(--folder-view-card-shadow-hover);\n /* Lift slightly so the card feels like it peels up off the well. */\n transform: translateY(-1px);\n}\n\n.folder-view .folder-entry-head {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--studio-space-sm, 0.5rem);\n padding: var(--studio-space-sm, 0.5rem) var(--studio-space-md, 1rem);\n}\n\n.folder-view .folder-entry-title {\n display: flex;\n align-items: baseline;\n gap: var(--studio-space-sm, 0.5rem);\n min-width: 0;\n}\n\n.folder-view .folder-entry-name {\n font-weight: 600;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.folder-view .folder-entry-type {\n font-size: 0.7rem;\n color: var(--folder-view-muted);\n padding: var(--studio-space-3xs, 0.125rem) var(--studio-space-2xs, 0.25rem);\n border: 1px solid var(--folder-view-border);\n border-radius: var(--studio-radius-sm, 4px);\n flex-shrink: 0;\n}\n\n.folder-view .folder-entry-open {\n font: inherit;\n font-size: 0.8rem;\n background: none;\n border: none;\n cursor: pointer;\n color: var(--folder-view-accent-text);\n text-decoration: none;\n padding: var(--studio-space-2xs, 0.25rem) var(--studio-space-sm, 0.5rem);\n border-radius: var(--studio-radius-sm, 4px);\n flex-shrink: 0;\n transition: background var(--studio-transition-fast, 0.1s ease);\n}\n\n.folder-view .folder-entry-open:hover {\n background: var(--folder-view-hover);\n}\n\n.folder-view .folder-entry-hint {\n margin: 0;\n padding: 0 var(--studio-space-md, 1rem) var(--studio-space-md, 1rem);\n font-size: 0.85rem;\n color: var(--folder-view-muted);\n}\n\n/* Block: embedded preview body. */\n.folder-view .folder-entry-body {\n flex: 1 1 auto;\n min-height: 0;\n max-height: 300px;\n display: flex;\n flex-direction: column;\n border-top: 1px solid var(--folder-view-border);\n}\n\n.folder-view .folder-entry-scroll {\n height: 100%;\n overflow: auto;\n}\n\n.folder-view .folder-entry-scroll patchwork-view {\n display: block;\n height: 100%;\n}\n";
21
21
 
22
22
  // src/tool.js
23
23
  var DND_DATA_TYPES = [
@@ -427,4 +427,4 @@ var FolderTool = (handle, element) => {
427
427
  export {
428
428
  FolderTool
429
429
  };
430
- //# sourceMappingURL=tool-JSQNX2I6.js.map
430
+ //# sourceMappingURL=tool-WAWTPB4A.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/tool.js", "../src/styles.css"],
4
- "sourcesContent": ["import {\n parseAutomergeUrl,\n isValidAutomergeUrl,\n} from \"@automerge/automerge-repo/slim\";\nimport { openDocument } from \"@inkandswitch/patchwork-elements\";\nimport {\n getRegistry,\n createDocOfDatatype2,\n} from \"@inkandswitch/patchwork-plugins\";\nimport {\n asString,\n directoryLinks,\n folderLinks,\n isDirectoryDoc,\n} from \"./links.js\";\nimport styles from \"./styles.css\";\n\n// MIME types we can extract document drags from, in order of preference.\n// These mirror what the sideboard sets on dragstart so dropping a sidebar\n// item into the folder view adds it to the folder.\nconst DND_DATA_TYPES = [\n \"text/x-patchwork-dnd\",\n \"text/x-patchwork-urls\",\n \"text/uri-list\",\n \"text/plain\",\n];\n\nfunction hasDocumentDrag(dataTransfer) {\n return Boolean(\n dataTransfer &&\n DND_DATA_TYPES.some((type) => dataTransfer.types.includes(type))\n );\n}\n\nfunction urlFromText(text) {\n const trimmed = text.trim();\n if (isValidAutomergeUrl(trimmed)) return trimmed;\n // patchwork web links carry the document id in the fragment: #doc=<documentId>\n const docId = trimmed.match(/#doc=([^&\\s]+)/)?.[1];\n if (docId && isValidAutomergeUrl(`automerge:${docId}`)) {\n return `automerge:${docId}`;\n }\n return null;\n}\n\n// Extract the dragged documents from a drop event. Returns an array of\n// { url, name?, type? } items, or an empty array if there's nothing droppable.\nfunction getDndItems(event) {\n const data = event.dataTransfer;\n if (!data) return [];\n\n const dndData = data.getData(\"text/x-patchwork-dnd\");\n if (dndData) {\n try {\n const parsed = JSON.parse(dndData);\n if (Array.isArray(parsed?.items) && parsed.items.length > 0) {\n return parsed.items.filter((item) => isValidAutomergeUrl(item?.url));\n }\n } catch {\n // fall through to the other types\n }\n }\n\n const urlData = data.getData(\"text/x-patchwork-urls\");\n if (urlData) {\n try {\n const urls = JSON.parse(urlData);\n const items = (Array.isArray(urls) ? urls : [])\n .filter((url) => isValidAutomergeUrl(url))\n .map((url) => ({ url }));\n if (items.length > 0) return items;\n } catch {\n // fall through to the other types\n }\n }\n\n const text = data.getData(\"text/uri-list\") || data.getData(\"text/plain\");\n return text\n .split(/\\r?\\n/)\n .map(urlFromText)\n .filter((url) => url !== null)\n .map((url) => ({ url }));\n}\n\nfunction el(tag, attrs, ...children) {\n const node = document.createElement(tag);\n if (attrs) {\n for (const [key, value] of Object.entries(attrs)) {\n if (value == null || value === false) continue;\n if (key === \"className\") {\n node.className = value;\n } else if (key.startsWith(\"on\") && typeof value === \"function\") {\n node.addEventListener(key.slice(2).toLowerCase(), value);\n } else {\n node.setAttribute(key, value);\n }\n }\n }\n for (const child of children.flat()) {\n if (child == null || child === false) continue;\n node.appendChild(\n typeof child === \"string\" ? document.createTextNode(child) : child\n );\n }\n return node;\n}\n\nfunction entryHref(docLink) {\n return `#doc=${parseAutomergeUrl(docLink.url).documentId}&type=${docLink.type}`;\n}\n\n// A link is keyed by its doc, or, for a pushwork subdirectory with no doc of\n// its own, by its path.\nfunction entryKey(docLink) {\n return docLink.url ?? `path:${docLink.path}`;\n}\n\nfunction renderLoading() {\n return el(\"div\", { className: \"folder-view-loading\" }, \"Loading\u2026\");\n}\n\n// `enter(path)` opens a pushwork subdirectory in place.\nfunction buildEntry(docLink, enter) {\n const isFolder = docLink.type === \"folder\";\n const nameEl = el(\"span\", { className: \"folder-entry-name\" }, docLink.name);\n const typeEl = el(\"span\", { className: \"folder-entry-type\" }, docLink.type);\n const openEl = docLink.url\n ? el(\n \"a\",\n { className: \"folder-entry-open\", href: entryHref(docLink) },\n \"Open\"\n )\n : el(\n \"button\",\n {\n className: \"folder-entry-open\",\n type: \"button\",\n onClick: () => enter(docLink.path),\n },\n \"Open\"\n );\n\n // The nested view names the doc without heads; resolution (the drafts\n // `repo:handle-descriptor` answer) pins it to the active checkpoint when one\n // is checked out, so the entry freezes with the folder it lives in.\n const node = el(\n \"div\",\n { className: \"folder-entry\", \"data-type\": docLink.type },\n el(\n \"div\",\n { className: \"folder-entry-head\" },\n el(\"div\", { className: \"folder-entry-title\" }, nameEl, typeEl),\n openEl\n ),\n isFolder\n ? el(\n \"p\",\n { className: \"folder-entry-hint\" },\n 'Click \"Open\" to view folder contents'\n )\n : el(\n \"div\",\n { className: \"folder-entry-body\" },\n el(\n \"div\",\n { className: \"folder-entry-scroll\" },\n el(\"patchwork-view\", { \"doc-url\": docLink.url })\n )\n )\n );\n\n return {\n node,\n nameEl,\n typeEl,\n openEl,\n isFolder,\n url: docLink.url,\n };\n}\n\nfunction updateEntry(entry, docLink) {\n if (entry.nameEl.textContent !== docLink.name) {\n entry.nameEl.textContent = docLink.name;\n }\n if (entry.typeEl.textContent !== docLink.type) {\n entry.typeEl.textContent = docLink.type;\n }\n if (entry.node.getAttribute(\"data-type\") !== docLink.type) {\n entry.node.setAttribute(\"data-type\", docLink.type);\n }\n if (!docLink.url) return;\n const href = entryHref(docLink);\n if (entry.openEl.getAttribute(\"href\") !== href) {\n entry.openEl.setAttribute(\"href\", href);\n }\n}\n\n// The listable document types, sorted by name. `file` and other unlisted\n// datatypes are hidden \u2014 you can't create an empty File, for instance.\nfunction listableDatatypes() {\n return getRegistry(\"patchwork:datatype\")\n .all()\n .filter((datatype) => !datatype.unlisted)\n .sort((a, b) => a.name.localeCompare(b.name));\n}\n\n// Create a fresh document of the given datatype and return a DocLink for it.\n// Mirrors the sideboard's createNew: load the plugin on demand, create the doc,\n// then read its title.\nasync function createDocLink(repo, datatype) {\n const loaded = await getRegistry(\"patchwork:datatype\").load(datatype.id);\n if (!loaded) throw new Error(`couldn't load datatype \"${datatype.id}\"`);\n const docHandle = await createDocOfDatatype2(loaded, repo);\n return {\n url: docHandle.url,\n name: loaded.module.getTitle(docHandle.doc()),\n type: datatype.id,\n };\n}\n\n// The \"New\" button plus its type-picker popover. Creating a doc appends a\n// DocLink to the folder and opens it. Returns { node, dispose }.\nfunction buildCreateNew(handle, element) {\n const menu = el(\"div\", { className: \"folder-create-menu\", hidden: \"\" });\n const button = el(\n \"button\",\n {\n className: \"folder-create-button\",\n type: \"button\",\n \"aria-label\": \"Create new document\",\n },\n el(\"span\", { className: \"folder-create-icon\" }, \"+\"),\n \"New\"\n );\n const node = el(\"div\", { className: \"folder-create\" }, button, menu);\n\n let open = false;\n\n function setOpen(next) {\n open = next;\n if (open) {\n renderMenu();\n menu.removeAttribute(\"hidden\");\n node.setAttribute(\"data-open\", \"\");\n } else {\n menu.setAttribute(\"hidden\", \"\");\n node.removeAttribute(\"data-open\");\n }\n }\n\n function renderMenu() {\n const datatypes = listableDatatypes();\n if (datatypes.length === 0) {\n menu.replaceChildren(\n el(\n \"div\",\n { className: \"folder-create-empty\" },\n \"No document types available\"\n )\n );\n return;\n }\n menu.replaceChildren(\n ...datatypes.map((datatype) =>\n el(\n \"button\",\n {\n className: \"folder-create-item\",\n type: \"button\",\n onClick: () => pick(datatype),\n },\n datatype.name\n )\n )\n );\n }\n\n async function pick(datatype) {\n setOpen(false);\n const repo = element.repo;\n if (!repo) return;\n try {\n const link = await createDocLink(repo, datatype);\n handle.change((doc) => {\n doc.docs.push(link);\n });\n openDocument(element, link.url);\n } catch (error) {\n console.error(\"folder: couldn't create document\", error);\n }\n }\n\n button.addEventListener(\"click\", (event) => {\n event.stopPropagation();\n setOpen(!open);\n });\n\n // Dismiss the menu on an outside click or Escape.\n const onPointerDown = (event) => {\n if (open && !node.contains(event.target)) setOpen(false);\n };\n const onKeyDown = (event) => {\n if (open && event.key === \"Escape\") setOpen(false);\n };\n document.addEventListener(\"pointerdown\", onPointerDown);\n document.addEventListener(\"keydown\", onKeyDown);\n\n const dispose = () => {\n document.removeEventListener(\"pointerdown\", onPointerDown);\n document.removeEventListener(\"keydown\", onKeyDown);\n };\n\n return { node, dispose };\n}\n\nexport const FolderTool = (handle, element) => {\n const entries = new Map();\n\n const styleEl = el(\"style\");\n styleEl.textContent = styles;\n\n // Where we are inside a pushwork directory doc, which keeps its whole tree\n // in one doc. \"\" is the top.\n let path = \"\";\n\n function enter(next) {\n path = next;\n render();\n }\n\n const countEl = el(\"span\", { className: \"folder-view-count\" });\n const listEl = el(\"div\", { className: \"folder-view-list\" });\n const crumbsEl = el(\"nav\", { className: \"folder-view-crumbs\", hidden: \"\" });\n const createNew = buildCreateNew(handle, element);\n const shell = el(\n \"div\",\n { className: \"folder-view\" },\n el(\n \"div\",\n { className: \"folder-view-header\" },\n createNew.node,\n crumbsEl,\n countEl\n ),\n listEl\n );\n\n function renderCrumbs(title) {\n const parts = path ? path.split(\"/\") : [];\n const crumbs = [{ name: title, path: \"\" }].concat(\n parts.map((name, i) => ({ name, path: parts.slice(0, i + 1).join(\"/\") }))\n );\n crumbsEl.replaceChildren(\n ...crumbs.flatMap((crumb, i) => {\n const last = i === crumbs.length - 1;\n const node = last\n ? el(\"span\", { className: \"folder-view-crumb\" }, crumb.name)\n : el(\n \"button\",\n {\n className: \"folder-view-crumb\",\n type: \"button\",\n onClick: () => enter(crumb.path),\n },\n crumb.name\n );\n return i === 0\n ? [node]\n : [el(\"span\", { className: \"folder-view-crumb-sep\" }, \"/\"), node];\n })\n );\n }\n\n element.append(styleEl);\n\n // --- drag-and-drop: accept documents dragged in from the sidebar ---\n\n // dragenter/dragleave fire for every descendant, so track nesting depth to\n // know when the pointer has actually left the folder view.\n let dragDepth = 0;\n\n function endDrag() {\n dragDepth = 0;\n shell.removeAttribute(\"data-drop-active\");\n }\n\n function addDroppedDocs(event) {\n const folder = handle.doc();\n if (!folder || isDirectoryDoc(folder)) return;\n\n const existing = new Set(folderLinks(folder).map((docLink) => docLink.url));\n const selfUrl = handle.url;\n\n const links = [];\n for (const item of getDndItems(event)) {\n if (item.url === selfUrl) continue; // don't nest a folder inside itself\n if (existing.has(item.url)) continue; // already here\n existing.add(item.url); // de-dupe within a single drop too\n links.push({\n url: item.url,\n name: item.name || \"Untitled\",\n type: item.type || \"\",\n });\n }\n\n if (links.length === 0) return;\n\n handle.change((doc) => {\n if (!Array.isArray(doc.docs)) doc.docs = [];\n doc.docs.push(...links);\n });\n }\n\n // pushwork owns a directory doc's entries, so it's read-only here.\n function acceptsDrops(event) {\n return hasDocumentDrag(event.dataTransfer) && !isDirectoryDoc(handle.doc());\n }\n\n shell.addEventListener(\"dragenter\", (event) => {\n if (!acceptsDrops(event)) return;\n event.preventDefault();\n dragDepth++;\n shell.setAttribute(\"data-drop-active\", \"\");\n });\n\n shell.addEventListener(\"dragover\", (event) => {\n if (!acceptsDrops(event)) return;\n event.preventDefault();\n // \"link\": dropping here adds a new DocLink to the same automerge url \u2014 the\n // doc isn't moved or cloned. Requires the source's effectAllowed to permit\n // link (the sideboard sets \"all\").\n event.dataTransfer.dropEffect = \"link\";\n });\n\n shell.addEventListener(\"dragleave\", (event) => {\n if (!acceptsDrops(event)) return;\n dragDepth--;\n if (dragDepth <= 0) endDrag();\n });\n\n shell.addEventListener(\"drop\", (event) => {\n if (!acceptsDrops(event)) return;\n event.preventDefault();\n endDrag();\n addDroppedDocs(event);\n });\n\n let mounted = null;\n\n function show(node) {\n if (mounted !== node) {\n // keep the injected <style>, swap the rendered tree\n if (mounted) mounted.remove();\n element.append(node);\n mounted = node;\n }\n }\n\n function render() {\n const folder = handle.doc();\n if (!folder) {\n show(renderLoading());\n return;\n }\n\n show(shell);\n\n const directory = isDirectoryDoc(folder);\n let links;\n if (directory) {\n links = directoryLinks(folder, path);\n renderCrumbs(\n asString(folder[\"@patchwork\"].title) || \"Directory\"\n );\n } else {\n path = \"\";\n links = folderLinks(folder);\n }\n createNew.node.hidden = directory;\n crumbsEl.hidden = !directory;\n\n countEl.textContent = `${links.length} ${\n links.length === 1 ? \"document\" : \"documents\"\n }`;\n\n if (links.length === 0) {\n entries.clear();\n listEl.replaceChildren(\n el(\"div\", { className: \"folder-view-empty\" }, \"This folder is empty\")\n );\n return;\n }\n\n const seen = new Set();\n const ordered = [];\n for (const docLink of links) {\n const key = entryKey(docLink);\n seen.add(key);\n const isFolder = docLink.type === \"folder\";\n let entry = entries.get(key);\n // Rebuild only if folder/non-folder shape flipped \u2014 that's the one\n // case where the body structure differs.\n if (!entry || entry.isFolder !== isFolder) {\n entry = buildEntry(docLink, enter);\n entries.set(key, entry);\n } else {\n updateEntry(entry, docLink);\n }\n ordered.push(entry.node);\n }\n\n for (const key of [...entries.keys()]) {\n if (seen.has(key)) continue;\n entries.delete(key);\n }\n\n listEl.replaceChildren(...ordered);\n }\n\n const onChange = () => render();\n handle.on(\"change\", onChange);\n render();\n\n return () => {\n handle.off(\"change\", onChange);\n createNew.dispose();\n element.replaceChildren();\n entries.clear();\n mounted = null;\n };\n};\n", "@layer package {\n:root,\n:host,\n[theme] {\n /* The well the cards sit in \u2014 slightly recessed surface. */\n --folder-view-well: var(--editor-fill-offset-10, #f2f2f2);\n --folder-view-well-edge: var(--editor-fill-offset-30, #d6d6d6);\n --folder-view-fg: var(--editor-line, black);\n --folder-view-muted: var(--editor-line-offset-50, #999);\n --folder-view-border: var(--editor-fill-offset-20, #e5e5e5);\n\n /* A card = a raised surface sitting on the well. */\n --folder-view-card: var(--editor-fill, white);\n --folder-view-card-border: var(--editor-fill-offset-20, #e5e5e5);\n\n --folder-view-accent: var(--studio-primary-fill, var(--studio-primary, #35f7ca));\n --folder-view-accent-line: var(--studio-primary-line, var(--editor-fill, white));\n --folder-view-accent-text: var(--editor-primary-text, var(--studio-primary-text, var(--studio-primary, #35f7ca)));\n --folder-view-hover: var(--editor-fill-offset-10, #f2f2f2);\n\n /* Layered drop shadow so a card reads as a solid object resting on the\n well \u2014 a tight contact shadow plus a softer cast one. Derived from the\n theme line colour so it inverts in dark themes. */\n --folder-view-card-shadow: 0 1px 2px\n color-mix(in oklch, var(--editor-line, black), transparent 94%),\n 0 2px 8px color-mix(in oklch, var(--editor-line, black), transparent 96%);\n --folder-view-card-shadow-hover: 0 2px 4px\n color-mix(in oklch, var(--editor-line, black), transparent 90%),\n 0 8px 20px color-mix(in oklch, var(--editor-line, black), transparent 93%);\n\n --folder-view-family: var(--editor-family-sans, system-ui, sans-serif);\n}\n}\n\n/* Block: the whole tool. A sunken well with an inset edge. */\n.folder-view {\n height: 100%;\n overflow: auto;\n padding: var(--studio-space-md, 1rem);\n display: flex;\n flex-direction: column;\n gap: var(--studio-space-md, 1rem);\n font-family: var(--folder-view-family);\n color: var(--folder-view-fg);\n background: var(--folder-view-well);\n /* No outer border: the host frame already draws the lines around the pane, so\n the well reads as flush rather than double-edged. */\n}\n\n/* State: a document is being dragged in from the sidebar. Outline the well\n with the accent colour so it reads as an active drop target. */\n.folder-view[data-drop-active] {\n border-color: var(--folder-view-accent);\n box-shadow: inset 0 0 0 2px var(--folder-view-accent);\n}\n\n/* Composition: header row. New-doc button on the left, count on the right. */\n.folder-view .folder-view-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--studio-space-sm, 0.5rem);\n padding-bottom: var(--studio-space-sm, 0.5rem);\n border-bottom: 1px solid var(--folder-view-border);\n}\n\n/* Composition: where we are inside a pushwork directory doc, in place of the\n create-new control (pushwork owns those entries). */\n.folder-view .folder-view-crumbs:not([hidden]) {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: var(--studio-space-2xs, 0.25rem);\n min-width: 0;\n font-size: 0.85rem;\n}\n\n.folder-view .folder-view-crumb {\n font: inherit;\n color: var(--folder-view-fg);\n background: none;\n border: none;\n padding: var(--studio-space-2xs, 0.25rem);\n border-radius: var(--studio-radius-sm, 4px);\n}\n\n.folder-view button.folder-view-crumb {\n color: var(--folder-view-accent-text);\n cursor: pointer;\n}\n\n.folder-view button.folder-view-crumb:hover {\n background: var(--folder-view-hover);\n}\n\n.folder-view .folder-view-crumb-sep {\n color: var(--folder-view-muted);\n}\n\n/* Composition: the create-new control \u2014 a button anchoring a type-picker. */\n.folder-view .folder-create {\n position: relative;\n}\n\n.folder-view .folder-create-button {\n display: inline-flex;\n align-items: center;\n gap: var(--studio-space-2xs, 0.25rem);\n font: inherit;\n font-size: 0.8rem;\n color: var(--folder-view-accent-line);\n background: var(--folder-view-accent);\n border: 1px solid transparent;\n border-radius: var(--studio-radius-sm, 4px);\n padding: var(--studio-space-2xs, 0.25rem) var(--studio-space-sm, 0.5rem);\n cursor: pointer;\n transition: filter var(--studio-transition-fast, 0.1s ease);\n}\n\n.folder-view .folder-create-button:hover {\n filter: brightness(0.96);\n}\n\n.folder-view .folder-create-icon {\n font-size: 1rem;\n line-height: 1;\n}\n\n/* The type-picker popover, anchored under the button. */\n.folder-view .folder-create-menu {\n position: absolute;\n top: calc(100% + var(--studio-space-2xs, 0.25rem));\n left: 0;\n z-index: 10;\n min-width: 12rem;\n max-height: 16rem;\n overflow: auto;\n display: flex;\n flex-direction: column;\n padding: var(--studio-space-3xs, 0.125rem);\n background: var(--folder-view-card);\n border: 1px solid var(--folder-view-card-border);\n border-radius: var(--studio-radius-md, 8px);\n box-shadow: var(--folder-view-card-shadow-hover);\n}\n\n.folder-view .folder-create-menu[hidden] {\n display: none;\n}\n\n.folder-view .folder-create-item {\n text-align: left;\n font: inherit;\n font-size: 0.85rem;\n color: var(--folder-view-fg);\n background: transparent;\n border: 0;\n border-radius: var(--studio-radius-sm, 4px);\n padding: var(--studio-space-2xs, 0.25rem) var(--studio-space-sm, 0.5rem);\n cursor: pointer;\n}\n\n.folder-view .folder-create-item:hover {\n background: var(--folder-view-hover);\n}\n\n.folder-view .folder-create-empty {\n padding: var(--studio-space-sm, 0.5rem);\n font-size: 0.8rem;\n color: var(--folder-view-muted);\n}\n\n.folder-view .folder-view-count {\n font-size: 0.8rem;\n color: var(--folder-view-muted);\n padding: var(--studio-space-2xs, 0.25rem) var(--studio-space-sm, 0.5rem);\n border-radius: var(--studio-radius-round, 9999px);\n background: var(--folder-view-card);\n border: 1px solid var(--folder-view-border);\n}\n\n/* Composition: the list of cards. */\n.folder-view .folder-view-list {\n display: flex;\n flex-direction: column;\n gap: var(--studio-space-md, 1rem);\n padding-bottom: var(--studio-space-md, 1rem);\n}\n\n.folder-view .folder-view-empty {\n text-align: center;\n color: var(--folder-view-muted);\n padding: var(--studio-space-xl, 2rem) 0;\n}\n\n.folder-view-loading {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 100%;\n padding: var(--studio-space-md, 1rem);\n font-family: var(--folder-view-family);\n color: var(--folder-view-muted);\n background: var(--folder-view-card);\n}\n\n/* Block: one rendered file/folder card \u2014 sitting on the well. */\n.folder-view .folder-entry {\n background: var(--folder-view-card);\n border: 1px solid var(--folder-view-card-border);\n border-radius: var(--studio-radius-lg, 12px);\n box-shadow: var(--folder-view-card-shadow);\n overflow: hidden;\n transition: box-shadow var(--studio-transition, 0.15s ease),\n transform var(--studio-transition, 0.15s ease);\n}\n\n.folder-view .folder-entry:hover {\n box-shadow: var(--folder-view-card-shadow-hover);\n /* Lift slightly so the card feels like it peels up off the well. */\n transform: translateY(-1px);\n}\n\n.folder-view .folder-entry-head {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--studio-space-sm, 0.5rem);\n padding: var(--studio-space-sm, 0.5rem) var(--studio-space-md, 1rem);\n}\n\n.folder-view .folder-entry-title {\n display: flex;\n align-items: baseline;\n gap: var(--studio-space-sm, 0.5rem);\n min-width: 0;\n}\n\n.folder-view .folder-entry-name {\n font-weight: 600;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.folder-view .folder-entry-type {\n font-size: 0.7rem;\n color: var(--folder-view-muted);\n padding: var(--studio-space-3xs, 0.125rem) var(--studio-space-2xs, 0.25rem);\n border: 1px solid var(--folder-view-border);\n border-radius: var(--studio-radius-sm, 4px);\n flex-shrink: 0;\n}\n\n.folder-view .folder-entry-open {\n font: inherit;\n font-size: 0.8rem;\n background: none;\n border: none;\n cursor: pointer;\n color: var(--folder-view-accent-text);\n text-decoration: none;\n padding: var(--studio-space-2xs, 0.25rem) var(--studio-space-sm, 0.5rem);\n border-radius: var(--studio-radius-sm, 4px);\n flex-shrink: 0;\n transition: background var(--studio-transition-fast, 0.1s ease);\n}\n\n.folder-view .folder-entry-open:hover {\n background: var(--folder-view-hover);\n}\n\n.folder-view .folder-entry-hint {\n margin: 0;\n padding: 0 var(--studio-space-md, 1rem) var(--studio-space-md, 1rem);\n font-size: 0.85rem;\n color: var(--folder-view-muted);\n}\n\n/* Block: embedded preview body. */\n.folder-view .folder-entry-body {\n flex: 1 1 auto;\n min-height: 0;\n max-height: 300px;\n display: flex;\n flex-direction: column;\n border-top: 1px solid var(--folder-view-border);\n}\n\n.folder-view .folder-entry-scroll {\n height: 100%;\n overflow: auto;\n}\n\n.folder-view .folder-entry-scroll patchwork-view {\n display: block;\n height: 100%;\n}\n"],
4
+ "sourcesContent": ["import {\n parseAutomergeUrl,\n isValidAutomergeUrl,\n} from \"@automerge/automerge-repo/slim\";\nimport { openDocument } from \"@inkandswitch/patchwork-elements\";\nimport {\n getRegistry,\n createDocOfDatatype2,\n} from \"@inkandswitch/patchwork-plugins\";\nimport {\n asString,\n directoryLinks,\n folderLinks,\n isDirectoryDoc,\n} from \"./links.js\";\nimport styles from \"./styles.css\";\n\n// MIME types we can extract document drags from, in order of preference.\n// These mirror what the sideboard sets on dragstart so dropping a sidebar\n// item into the folder view adds it to the folder.\nconst DND_DATA_TYPES = [\n \"text/x-patchwork-dnd\",\n \"text/x-patchwork-urls\",\n \"text/uri-list\",\n \"text/plain\",\n];\n\nfunction hasDocumentDrag(dataTransfer) {\n return Boolean(\n dataTransfer &&\n DND_DATA_TYPES.some((type) => dataTransfer.types.includes(type))\n );\n}\n\nfunction urlFromText(text) {\n const trimmed = text.trim();\n if (isValidAutomergeUrl(trimmed)) return trimmed;\n // patchwork web links carry the document id in the fragment: #doc=<documentId>\n const docId = trimmed.match(/#doc=([^&\\s]+)/)?.[1];\n if (docId && isValidAutomergeUrl(`automerge:${docId}`)) {\n return `automerge:${docId}`;\n }\n return null;\n}\n\n// Extract the dragged documents from a drop event. Returns an array of\n// { url, name?, type? } items, or an empty array if there's nothing droppable.\nfunction getDndItems(event) {\n const data = event.dataTransfer;\n if (!data) return [];\n\n const dndData = data.getData(\"text/x-patchwork-dnd\");\n if (dndData) {\n try {\n const parsed = JSON.parse(dndData);\n if (Array.isArray(parsed?.items) && parsed.items.length > 0) {\n return parsed.items.filter((item) => isValidAutomergeUrl(item?.url));\n }\n } catch {\n // fall through to the other types\n }\n }\n\n const urlData = data.getData(\"text/x-patchwork-urls\");\n if (urlData) {\n try {\n const urls = JSON.parse(urlData);\n const items = (Array.isArray(urls) ? urls : [])\n .filter((url) => isValidAutomergeUrl(url))\n .map((url) => ({ url }));\n if (items.length > 0) return items;\n } catch {\n // fall through to the other types\n }\n }\n\n const text = data.getData(\"text/uri-list\") || data.getData(\"text/plain\");\n return text\n .split(/\\r?\\n/)\n .map(urlFromText)\n .filter((url) => url !== null)\n .map((url) => ({ url }));\n}\n\nfunction el(tag, attrs, ...children) {\n const node = document.createElement(tag);\n if (attrs) {\n for (const [key, value] of Object.entries(attrs)) {\n if (value == null || value === false) continue;\n if (key === \"className\") {\n node.className = value;\n } else if (key.startsWith(\"on\") && typeof value === \"function\") {\n node.addEventListener(key.slice(2).toLowerCase(), value);\n } else {\n node.setAttribute(key, value);\n }\n }\n }\n for (const child of children.flat()) {\n if (child == null || child === false) continue;\n node.appendChild(\n typeof child === \"string\" ? document.createTextNode(child) : child\n );\n }\n return node;\n}\n\nfunction entryHref(docLink) {\n return `#doc=${parseAutomergeUrl(docLink.url).documentId}&type=${docLink.type}`;\n}\n\n// A link is keyed by its doc, or, for a pushwork subdirectory with no doc of\n// its own, by its path.\nfunction entryKey(docLink) {\n return docLink.url ?? `path:${docLink.path}`;\n}\n\nfunction renderLoading() {\n return el(\"div\", { className: \"folder-view-loading\" }, \"Loading\u2026\");\n}\n\n// `enter(path)` opens a pushwork subdirectory in place.\nfunction buildEntry(docLink, enter) {\n const isFolder = docLink.type === \"folder\";\n const nameEl = el(\"span\", { className: \"folder-entry-name\" }, docLink.name);\n const typeEl = el(\"span\", { className: \"folder-entry-type\" }, docLink.type);\n const openEl = docLink.url\n ? el(\n \"a\",\n { className: \"folder-entry-open\", href: entryHref(docLink) },\n \"Open\"\n )\n : el(\n \"button\",\n {\n className: \"folder-entry-open\",\n type: \"button\",\n onClick: () => enter(docLink.path),\n },\n \"Open\"\n );\n\n // The nested view names the doc without heads; resolution (the drafts\n // `repo:handle-descriptor` answer) pins it to the active checkpoint when one\n // is checked out, so the entry freezes with the folder it lives in.\n const node = el(\n \"div\",\n { className: \"folder-entry\", \"data-type\": docLink.type },\n el(\n \"div\",\n { className: \"folder-entry-head\" },\n el(\"div\", { className: \"folder-entry-title\" }, nameEl, typeEl),\n openEl\n ),\n isFolder\n ? el(\n \"p\",\n { className: \"folder-entry-hint\" },\n 'Click \"Open\" to view folder contents'\n )\n : el(\n \"div\",\n { className: \"folder-entry-body\" },\n el(\n \"div\",\n { className: \"folder-entry-scroll\" },\n el(\"patchwork-view\", { \"doc-url\": docLink.url })\n )\n )\n );\n\n return {\n node,\n nameEl,\n typeEl,\n openEl,\n isFolder,\n url: docLink.url,\n };\n}\n\nfunction updateEntry(entry, docLink) {\n if (entry.nameEl.textContent !== docLink.name) {\n entry.nameEl.textContent = docLink.name;\n }\n if (entry.typeEl.textContent !== docLink.type) {\n entry.typeEl.textContent = docLink.type;\n }\n if (entry.node.getAttribute(\"data-type\") !== docLink.type) {\n entry.node.setAttribute(\"data-type\", docLink.type);\n }\n if (!docLink.url) return;\n const href = entryHref(docLink);\n if (entry.openEl.getAttribute(\"href\") !== href) {\n entry.openEl.setAttribute(\"href\", href);\n }\n}\n\n// The listable document types, sorted by name. `file` and other unlisted\n// datatypes are hidden \u2014 you can't create an empty File, for instance.\nfunction listableDatatypes() {\n return getRegistry(\"patchwork:datatype\")\n .all()\n .filter((datatype) => !datatype.unlisted)\n .sort((a, b) => a.name.localeCompare(b.name));\n}\n\n// Create a fresh document of the given datatype and return a DocLink for it.\n// Mirrors the sideboard's createNew: load the plugin on demand, create the doc,\n// then read its title.\nasync function createDocLink(repo, datatype) {\n const loaded = await getRegistry(\"patchwork:datatype\").load(datatype.id);\n if (!loaded) throw new Error(`couldn't load datatype \"${datatype.id}\"`);\n const docHandle = await createDocOfDatatype2(loaded, repo);\n return {\n url: docHandle.url,\n name: loaded.module.getTitle(docHandle.doc()),\n type: datatype.id,\n };\n}\n\n// The \"New\" button plus its type-picker popover. Creating a doc appends a\n// DocLink to the folder and opens it. Returns { node, dispose }.\nfunction buildCreateNew(handle, element) {\n const menu = el(\"div\", { className: \"folder-create-menu\", hidden: \"\" });\n const button = el(\n \"button\",\n {\n className: \"folder-create-button\",\n type: \"button\",\n \"aria-label\": \"Create new document\",\n },\n el(\"span\", { className: \"folder-create-icon\" }, \"+\"),\n \"New\"\n );\n const node = el(\"div\", { className: \"folder-create\" }, button, menu);\n\n let open = false;\n\n function setOpen(next) {\n open = next;\n if (open) {\n renderMenu();\n menu.removeAttribute(\"hidden\");\n node.setAttribute(\"data-open\", \"\");\n } else {\n menu.setAttribute(\"hidden\", \"\");\n node.removeAttribute(\"data-open\");\n }\n }\n\n function renderMenu() {\n const datatypes = listableDatatypes();\n if (datatypes.length === 0) {\n menu.replaceChildren(\n el(\n \"div\",\n { className: \"folder-create-empty\" },\n \"No document types available\"\n )\n );\n return;\n }\n menu.replaceChildren(\n ...datatypes.map((datatype) =>\n el(\n \"button\",\n {\n className: \"folder-create-item\",\n type: \"button\",\n onClick: () => pick(datatype),\n },\n datatype.name\n )\n )\n );\n }\n\n async function pick(datatype) {\n setOpen(false);\n const repo = element.repo;\n if (!repo) return;\n try {\n const link = await createDocLink(repo, datatype);\n handle.change((doc) => {\n doc.docs.push(link);\n });\n openDocument(element, link.url);\n } catch (error) {\n console.error(\"folder: couldn't create document\", error);\n }\n }\n\n button.addEventListener(\"click\", (event) => {\n event.stopPropagation();\n setOpen(!open);\n });\n\n // Dismiss the menu on an outside click or Escape.\n const onPointerDown = (event) => {\n if (open && !node.contains(event.target)) setOpen(false);\n };\n const onKeyDown = (event) => {\n if (open && event.key === \"Escape\") setOpen(false);\n };\n document.addEventListener(\"pointerdown\", onPointerDown);\n document.addEventListener(\"keydown\", onKeyDown);\n\n const dispose = () => {\n document.removeEventListener(\"pointerdown\", onPointerDown);\n document.removeEventListener(\"keydown\", onKeyDown);\n };\n\n return { node, dispose };\n}\n\nexport const FolderTool = (handle, element) => {\n const entries = new Map();\n\n const styleEl = el(\"style\");\n styleEl.textContent = styles;\n\n // Where we are inside a pushwork directory doc, which keeps its whole tree\n // in one doc. \"\" is the top.\n let path = \"\";\n\n function enter(next) {\n path = next;\n render();\n }\n\n const countEl = el(\"span\", { className: \"folder-view-count\" });\n const listEl = el(\"div\", { className: \"folder-view-list\" });\n const crumbsEl = el(\"nav\", { className: \"folder-view-crumbs\", hidden: \"\" });\n const createNew = buildCreateNew(handle, element);\n const shell = el(\n \"div\",\n { className: \"folder-view\" },\n el(\n \"div\",\n { className: \"folder-view-header\" },\n createNew.node,\n crumbsEl,\n countEl\n ),\n listEl\n );\n\n function renderCrumbs(title) {\n const parts = path ? path.split(\"/\") : [];\n const crumbs = [{ name: title, path: \"\" }].concat(\n parts.map((name, i) => ({ name, path: parts.slice(0, i + 1).join(\"/\") }))\n );\n crumbsEl.replaceChildren(\n ...crumbs.flatMap((crumb, i) => {\n const last = i === crumbs.length - 1;\n const node = last\n ? el(\"span\", { className: \"folder-view-crumb\" }, crumb.name)\n : el(\n \"button\",\n {\n className: \"folder-view-crumb\",\n type: \"button\",\n onClick: () => enter(crumb.path),\n },\n crumb.name\n );\n return i === 0\n ? [node]\n : [el(\"span\", { className: \"folder-view-crumb-sep\" }, \"/\"), node];\n })\n );\n }\n\n element.append(styleEl);\n\n // --- drag-and-drop: accept documents dragged in from the sidebar ---\n\n // dragenter/dragleave fire for every descendant, so track nesting depth to\n // know when the pointer has actually left the folder view.\n let dragDepth = 0;\n\n function endDrag() {\n dragDepth = 0;\n shell.removeAttribute(\"data-drop-active\");\n }\n\n function addDroppedDocs(event) {\n const folder = handle.doc();\n if (!folder || isDirectoryDoc(folder)) return;\n\n const existing = new Set(folderLinks(folder).map((docLink) => docLink.url));\n const selfUrl = handle.url;\n\n const links = [];\n for (const item of getDndItems(event)) {\n if (item.url === selfUrl) continue; // don't nest a folder inside itself\n if (existing.has(item.url)) continue; // already here\n existing.add(item.url); // de-dupe within a single drop too\n links.push({\n url: item.url,\n name: item.name || \"Untitled\",\n type: item.type || \"\",\n });\n }\n\n if (links.length === 0) return;\n\n handle.change((doc) => {\n if (!Array.isArray(doc.docs)) doc.docs = [];\n doc.docs.push(...links);\n });\n }\n\n // pushwork owns a directory doc's entries, so it's read-only here.\n function acceptsDrops(event) {\n return hasDocumentDrag(event.dataTransfer) && !isDirectoryDoc(handle.doc());\n }\n\n shell.addEventListener(\"dragenter\", (event) => {\n if (!acceptsDrops(event)) return;\n event.preventDefault();\n dragDepth++;\n shell.setAttribute(\"data-drop-active\", \"\");\n });\n\n shell.addEventListener(\"dragover\", (event) => {\n if (!acceptsDrops(event)) return;\n event.preventDefault();\n // \"link\": dropping here adds a new DocLink to the same automerge url \u2014 the\n // doc isn't moved or cloned. Requires the source's effectAllowed to permit\n // link (the sideboard sets \"all\").\n event.dataTransfer.dropEffect = \"link\";\n });\n\n shell.addEventListener(\"dragleave\", (event) => {\n if (!acceptsDrops(event)) return;\n dragDepth--;\n if (dragDepth <= 0) endDrag();\n });\n\n shell.addEventListener(\"drop\", (event) => {\n if (!acceptsDrops(event)) return;\n event.preventDefault();\n endDrag();\n addDroppedDocs(event);\n });\n\n let mounted = null;\n\n function show(node) {\n if (mounted !== node) {\n // keep the injected <style>, swap the rendered tree\n if (mounted) mounted.remove();\n element.append(node);\n mounted = node;\n }\n }\n\n function render() {\n const folder = handle.doc();\n if (!folder) {\n show(renderLoading());\n return;\n }\n\n show(shell);\n\n const directory = isDirectoryDoc(folder);\n let links;\n if (directory) {\n links = directoryLinks(folder, path);\n renderCrumbs(\n asString(folder[\"@patchwork\"].title) || \"Directory\"\n );\n } else {\n path = \"\";\n links = folderLinks(folder);\n }\n createNew.node.hidden = directory;\n crumbsEl.hidden = !directory;\n\n countEl.textContent = `${links.length} ${\n links.length === 1 ? \"document\" : \"documents\"\n }`;\n\n if (links.length === 0) {\n entries.clear();\n listEl.replaceChildren(\n el(\"div\", { className: \"folder-view-empty\" }, \"This folder is empty\")\n );\n return;\n }\n\n const seen = new Set();\n const ordered = [];\n for (const docLink of links) {\n const key = entryKey(docLink);\n seen.add(key);\n const isFolder = docLink.type === \"folder\";\n let entry = entries.get(key);\n // Rebuild only if folder/non-folder shape flipped \u2014 that's the one\n // case where the body structure differs.\n if (!entry || entry.isFolder !== isFolder) {\n entry = buildEntry(docLink, enter);\n entries.set(key, entry);\n } else {\n updateEntry(entry, docLink);\n }\n ordered.push(entry.node);\n }\n\n for (const key of [...entries.keys()]) {\n if (seen.has(key)) continue;\n entries.delete(key);\n }\n\n listEl.replaceChildren(...ordered);\n }\n\n const onChange = () => render();\n handle.on(\"change\", onChange);\n render();\n\n return () => {\n handle.off(\"change\", onChange);\n createNew.dispose();\n element.replaceChildren();\n entries.clear();\n mounted = null;\n };\n};\n", "@layer package {\n:root,\n:host,\n[theme] {\n /* The well the cards sit in \u2014 slightly recessed surface. */\n --folder-view-well: var(--editor-fill-offset-10, #f2f2f2);\n --folder-view-well-edge: var(--editor-fill-offset-30, #d6d6d6);\n --folder-view-fg: var(--editor-line, black);\n --folder-view-muted: var(--editor-line-offset-50, #999);\n --folder-view-border: var(--editor-fill-offset-20, #e5e5e5);\n\n /* A card = a raised surface sitting on the well. */\n --folder-view-card: var(--editor-fill, white);\n --folder-view-card-border: var(--editor-fill-offset-20, #e5e5e5);\n\n --folder-view-accent: var(--studio-primary-fill, var(--studio-primary, #35f7ca));\n --folder-view-accent-line: var(--studio-primary-line, var(--editor-fill, white));\n --folder-view-accent-text: var(--editor-primary-text, var(--studio-primary-text, var(--studio-primary, #35f7ca)));\n --folder-view-hover: var(--editor-fill-offset-10, #f2f2f2);\n\n /* Layered drop shadow so a card reads as a solid object resting on the\n well \u2014 a tight contact shadow plus a softer cast one. Derived from the\n theme line colour so it inverts in dark themes. */\n --folder-view-card-shadow: 0 1px 2px\n color-mix(in oklch, var(--editor-line, black), transparent 94%),\n 0 2px 8px color-mix(in oklch, var(--editor-line, black), transparent 96%);\n --folder-view-card-shadow-hover: 0 2px 4px\n color-mix(in oklch, var(--editor-line, black), transparent 90%),\n 0 8px 20px color-mix(in oklch, var(--editor-line, black), transparent 93%);\n\n --folder-view-family: var(--editor-family-sans, system-ui, sans-serif);\n}\n}\n\n/* Block: the whole tool. A sunken well with an inset edge. */\n.folder-view {\n height: 100%;\n overflow: auto;\n padding: var(--studio-space-md, 1rem);\n display: flex;\n flex-direction: column;\n gap: var(--studio-space-md, 1rem);\n font-family: var(--folder-view-family);\n color: var(--folder-view-fg);\n background: var(--folder-view-well);\n /* No outer border: the host frame already draws the lines around the pane, so\n the well reads as flush rather than double-edged. */\n}\n\n/* State: a document is being dragged in from the sidebar. Outline the well\n with the accent colour so it reads as an active drop target. */\n.folder-view[data-drop-active] {\n border-color: var(--folder-view-accent);\n box-shadow: inset 0 0 0 2px var(--folder-view-accent);\n}\n\n/* Composition: header row. New-doc button on the left, count on the right. */\n.folder-view .folder-view-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--studio-space-sm, 0.5rem);\n padding-bottom: var(--studio-space-sm, 0.5rem);\n border-bottom: 1px solid var(--folder-view-border);\n}\n\n/* Composition: where we are inside a pushwork directory doc, in place of the\n create-new control (pushwork owns those entries). */\n.folder-view .folder-view-crumbs:not([hidden]) {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: var(--studio-space-2xs, 0.25rem);\n min-width: 0;\n font-size: 0.85rem;\n}\n\n.folder-view .folder-view-crumb {\n font: inherit;\n color: var(--folder-view-fg);\n background: none;\n border: none;\n padding: var(--studio-space-2xs, 0.25rem);\n border-radius: var(--studio-radius-sm, 4px);\n}\n\n.folder-view button.folder-view-crumb {\n color: var(--folder-view-accent-text);\n cursor: pointer;\n}\n\n.folder-view button.folder-view-crumb:hover {\n background: var(--folder-view-hover);\n}\n\n.folder-view .folder-view-crumb-sep {\n color: var(--folder-view-muted);\n}\n\n/* Composition: the create-new control \u2014 a button anchoring a type-picker. */\n.folder-view .folder-create {\n position: relative;\n}\n\n.folder-view .folder-create-button {\n display: inline-flex;\n align-items: center;\n gap: var(--studio-space-2xs, 0.25rem);\n font: inherit;\n font-size: 0.8rem;\n color: var(--folder-view-accent-line);\n background: var(--folder-view-accent);\n border: 1px solid transparent;\n border-radius: var(--studio-radius-sm, 4px);\n padding: var(--studio-space-2xs, 0.25rem) var(--studio-space-sm, 0.5rem);\n cursor: pointer;\n transition: filter var(--studio-transition-fast, 0.1s ease);\n}\n\n.folder-view .folder-create-button:hover {\n filter: brightness(0.96);\n}\n\n.folder-view .folder-create-icon {\n font-size: 1rem;\n line-height: 1;\n}\n\n/* The type-picker popover, anchored under the button. */\n.folder-view .folder-create-menu {\n position: absolute;\n top: calc(100% + var(--studio-space-2xs, 0.25rem));\n left: 0;\n z-index: 10;\n min-width: 12rem;\n max-height: 16rem;\n overflow: auto;\n display: flex;\n flex-direction: column;\n padding: var(--studio-space-3xs, 0.125rem);\n background: var(--folder-view-card);\n border: 1px solid var(--folder-view-card-border);\n border-radius: var(--studio-radius-md, 8px);\n box-shadow: var(--folder-view-card-shadow-hover);\n /* Grows out of its button. Closing is instant. */\n transform-origin: top left;\n transition:\n opacity 150ms var(--studio-ease-out, cubic-bezier(0.23, 1, 0.32, 1)),\n transform 150ms var(--studio-ease-out, cubic-bezier(0.23, 1, 0.32, 1));\n}\n@starting-style {\n .folder-view .folder-create-menu {\n opacity: 0;\n transform: scale(0.97);\n }\n}\n\n.folder-view .folder-create-menu[hidden] {\n display: none;\n}\n\n.folder-view .folder-create-item {\n text-align: left;\n font: inherit;\n font-size: 0.85rem;\n color: var(--folder-view-fg);\n background: transparent;\n border: 0;\n border-radius: var(--studio-radius-sm, 4px);\n padding: var(--studio-space-2xs, 0.25rem) var(--studio-space-sm, 0.5rem);\n cursor: pointer;\n}\n\n.folder-view .folder-create-item:hover {\n background: var(--folder-view-hover);\n}\n\n.folder-view .folder-create-empty {\n padding: var(--studio-space-sm, 0.5rem);\n font-size: 0.8rem;\n color: var(--folder-view-muted);\n}\n\n.folder-view .folder-view-count {\n font-size: 0.8rem;\n color: var(--folder-view-muted);\n padding: var(--studio-space-2xs, 0.25rem) var(--studio-space-sm, 0.5rem);\n border-radius: var(--studio-radius-round, 9999px);\n background: var(--folder-view-card);\n border: 1px solid var(--folder-view-border);\n}\n\n/* Composition: the list of cards. */\n.folder-view .folder-view-list {\n display: flex;\n flex-direction: column;\n gap: var(--studio-space-md, 1rem);\n padding-bottom: var(--studio-space-md, 1rem);\n}\n\n.folder-view .folder-view-empty {\n text-align: center;\n color: var(--folder-view-muted);\n padding: var(--studio-space-xl, 2rem) 0;\n}\n\n.folder-view-loading {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 100%;\n padding: var(--studio-space-md, 1rem);\n font-family: var(--folder-view-family);\n color: var(--folder-view-muted);\n background: var(--folder-view-card);\n}\n\n/* Block: one rendered file/folder card \u2014 sitting on the well. */\n.folder-view .folder-entry {\n background: var(--folder-view-card);\n border: 1px solid var(--folder-view-card-border);\n border-radius: var(--studio-radius-lg, 12px);\n box-shadow: var(--folder-view-card-shadow);\n overflow: hidden;\n transition: box-shadow var(--studio-transition, 0.15s ease),\n transform var(--studio-transition, 0.15s ease);\n}\n\n.folder-view .folder-entry:hover {\n box-shadow: var(--folder-view-card-shadow-hover);\n /* Lift slightly so the card feels like it peels up off the well. */\n transform: translateY(-1px);\n}\n\n.folder-view .folder-entry-head {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--studio-space-sm, 0.5rem);\n padding: var(--studio-space-sm, 0.5rem) var(--studio-space-md, 1rem);\n}\n\n.folder-view .folder-entry-title {\n display: flex;\n align-items: baseline;\n gap: var(--studio-space-sm, 0.5rem);\n min-width: 0;\n}\n\n.folder-view .folder-entry-name {\n font-weight: 600;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.folder-view .folder-entry-type {\n font-size: 0.7rem;\n color: var(--folder-view-muted);\n padding: var(--studio-space-3xs, 0.125rem) var(--studio-space-2xs, 0.25rem);\n border: 1px solid var(--folder-view-border);\n border-radius: var(--studio-radius-sm, 4px);\n flex-shrink: 0;\n}\n\n.folder-view .folder-entry-open {\n font: inherit;\n font-size: 0.8rem;\n background: none;\n border: none;\n cursor: pointer;\n color: var(--folder-view-accent-text);\n text-decoration: none;\n padding: var(--studio-space-2xs, 0.25rem) var(--studio-space-sm, 0.5rem);\n border-radius: var(--studio-radius-sm, 4px);\n flex-shrink: 0;\n transition: background var(--studio-transition-fast, 0.1s ease);\n}\n\n.folder-view .folder-entry-open:hover {\n background: var(--folder-view-hover);\n}\n\n.folder-view .folder-entry-hint {\n margin: 0;\n padding: 0 var(--studio-space-md, 1rem) var(--studio-space-md, 1rem);\n font-size: 0.85rem;\n color: var(--folder-view-muted);\n}\n\n/* Block: embedded preview body. */\n.folder-view .folder-entry-body {\n flex: 1 1 auto;\n min-height: 0;\n max-height: 300px;\n display: flex;\n flex-direction: column;\n border-top: 1px solid var(--folder-view-border);\n}\n\n.folder-view .folder-entry-scroll {\n height: 100%;\n overflow: auto;\n}\n\n.folder-view .folder-entry-scroll patchwork-view {\n display: block;\n height: 100%;\n}\n"],
5
5
  "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -3,7 +3,7 @@
3
3
  try {
4
4
  if (typeof document != "undefined") {
5
5
  var elementStyle = document.createElement("style");
6
- elementStyle.appendChild(document.createTextNode("@keyframes spin {\n from { transform: rotate(0deg); }\n to { transform: rotate(360deg); }\n}\n\n@layer package {\n:root,\n:host,\n[theme] {\n /* Accent — selected card background, border, and timeline dot */\n --history-accent: var(--studio-secondary, #33ccf8);\n --history-accent-fg: var(--studio-fill, white);\n\n /* Unselected cards */\n --history-card-bg: var(--studio-fill, white);\n --history-card-border: var(--studio-fill-offset-20, #ccc);\n --history-card-hover-bg: var(--studio-fill-offset-10, #e5e5e5);\n\n /* Date section header */\n --history-section-bg: var(--studio-fill-offset-10, #e5e5e5);\n --history-section-divider: color-mix(in oklch, var(--studio-fill-offset-30, #b3b3b3) 50%, transparent);\n\n /* Text */\n --history-fg: var(--studio-line, black);\n --history-secondary-fg: var(--studio-line-offset-40, #666);\n --history-muted-fg: var(--studio-line-offset-50, #999);\n\n /* Fonts */\n --history-family: var(--studio-family-sans, system-ui, sans-serif);\n --history-family-code: var(--studio-family-code, ui-monospace, monospace);\n\n /* Diff indicators */\n --history-addition: #22c55e;\n --history-addition-fg: #16a34a;\n --history-deletion: #f87171;\n --history-deletion-fg: #ef4444;\n\n /* Borders & interactive */\n --history-border: var(--studio-fill-offset-20, #ccc);\n --history-hover: var(--studio-fill-offset-10, #e5e5e5);\n --history-active-bg: var(--studio-fill-offset-10, #e5e5e5);\n --history-active-border: var(--studio-fill-offset-30, #b3b3b3);\n}\n}\n\n/* Hide timeline line on last item in each date group */\n.last-timeline-item .timeline-line {\n display: none;\n}\n\n/* History timeline components */\n.history-panel {\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow: hidden;\n font-family: var(--history-family);\n color: var(--history-fg);\n}\n\n.history-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: var(--studio-space-sm, 0.5rem) var(--studio-space-md, 1rem);\n border-bottom: 1px solid var(--history-border);\n}\n\n.history-header-title {\n font-size: 1rem;\n font-weight: 600;\n}\n\n.history-header-actions {\n display: flex;\n align-items: center;\n gap: var(--studio-space-xs, 0.375rem);\n}\n\n.history-list {\n flex: 1;\n overflow-y: auto;\n padding: var(--studio-space-sm, 0.5rem);\n}\n\n.history-date-header {\n position: sticky;\n top: 0;\n z-index: 1;\n padding: var(--studio-space-2xs, 0.25rem) var(--studio-space-sm, 0.5rem);\n font-size: 0.75rem;\n font-weight: 600;\n color: var(--history-secondary-fg);\n background: var(--history-section-bg);\n border-bottom: 1px solid var(--history-section-divider);\n}\n\n.history-item {\n display: flex;\n gap: var(--studio-space-sm, 0.5rem);\n padding: var(--studio-space-xs, 0.375rem) var(--studio-space-sm, 0.5rem);\n border-radius: var(--studio-radius-sm, 4px);\n cursor: pointer;\n transition: background var(--studio-transition-fast, 0.1s ease);\n}\n\n.history-item:hover {\n background: var(--history-card-hover-bg);\n}\n\n.history-item[data-selected] {\n background: var(--history-accent);\n color: var(--history-accent-fg);\n}\n\n.history-item-dot {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n background: var(--history-accent);\n flex-shrink: 0;\n margin-top: 6px;\n}\n\n.history-item-content {\n flex: 1;\n min-width: 0;\n}\n\n.history-item-time {\n font-size: 0.75rem;\n color: var(--history-muted-fg);\n}\n\n.history-item-description {\n font-size: 0.8125rem;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.timeline-line {\n width: 2px;\n background: var(--history-border);\n margin-left: 3px;\n flex-shrink: 0;\n}\n\n.history-computing {\n display: flex;\n align-items: center;\n gap: var(--studio-space-xs, 0.375rem);\n padding: var(--studio-space-sm, 0.5rem);\n font-size: 0.8125rem;\n color: var(--history-muted-fg);\n}\n\n.history-labeled-field {\n display: flex;\n flex-direction: column;\n gap: var(--studio-space-3xs, 0.125rem);\n}\n\n.history-labeled-field-label {\n font-size: 0.6875rem;\n font-weight: 500;\n color: var(--history-secondary-fg);\n text-transform: uppercase;\n letter-spacing: 0.03em;\n}\n\n.history-grouping-selector {\n display: flex;\n gap: var(--studio-space-2xs, 0.25rem);\n}\n\n.history-grouping-btn {\n padding: var(--studio-space-3xs, 0.125rem) var(--studio-space-xs, 0.375rem);\n border-radius: var(--studio-radius-sm, 4px);\n border: 1px solid var(--history-border);\n background: none;\n font-size: 0.75rem;\n cursor: pointer;\n color: var(--history-secondary-fg);\n}\n\n.history-grouping-btn[data-active] {\n background: var(--history-active-bg);\n color: var(--history-fg);\n border-color: var(--history-active-border);\n}\n\n.history-copy-btn {\n display: inline-flex;\n align-items: center;\n gap: var(--studio-space-3xs, 0.125rem);\n padding: var(--studio-space-3xs, 0.125rem) var(--studio-space-2xs, 0.25rem);\n border-radius: var(--studio-radius-sm, 4px);\n border: none;\n background: none;\n font-size: 0.6875rem;\n font-family: var(--history-family-code);\n color: var(--history-secondary-fg);\n cursor: pointer;\n}\n\n.history-copy-btn:hover {\n background: var(--history-hover);\n}\n\n.timeline-card {\n border: 1px solid var(--history-card-border);\n border-radius: var(--studio-radius-md, 8px);\n padding: var(--studio-space-sm, 0.5rem);\n background: var(--history-card-bg);\n}\n\n.timeline-card[data-selected] {\n border-color: var(--history-accent);\n background: color-mix(in oklch, var(--history-accent) 10%, var(--history-card-bg));\n}"));
6
+ elementStyle.appendChild(document.createTextNode("@keyframes spin {\n from { transform: rotate(0deg); }\n to { transform: rotate(360deg); }\n}\n\n@layer package {\n:root,\n:host,\n[theme] {\n /* Accent — selected card background, border, and timeline dot */\n --history-accent: var(--studio-secondary, #33ccf8);\n --history-accent-fg: var(--studio-fill, white);\n\n /* Unselected cards */\n --history-card-bg: var(--studio-fill, white);\n --history-card-border: var(--studio-fill-offset-20, #ccc);\n --history-card-hover-bg: var(--studio-fill-offset-10, #e5e5e5);\n\n /* Date section header */\n --history-section-bg: var(--studio-fill-offset-10, #e5e5e5);\n --history-section-divider: color-mix(in oklch, var(--studio-fill-offset-30, #b3b3b3) 50%, transparent);\n\n /* Text */\n --history-fg: var(--studio-line, black);\n --history-secondary-fg: var(--studio-line-offset-40, #666);\n --history-muted-fg: var(--studio-line-offset-50, #999);\n\n /* Fonts */\n --history-family: var(--studio-family-sans, system-ui, sans-serif);\n --history-family-code: var(--studio-family-code, ui-monospace, monospace);\n\n /* Diff indicators */\n --history-addition: #22c55e;\n --history-addition-fg: #16a34a;\n --history-deletion: #f87171;\n --history-deletion-fg: #ef4444;\n\n /* Borders & interactive */\n --history-border: var(--studio-fill-offset-20, #ccc);\n --history-hover: var(--studio-fill-offset-10, #e5e5e5);\n --history-active-bg: var(--studio-fill-offset-10, #e5e5e5);\n --history-active-border: var(--studio-fill-offset-30, #b3b3b3);\n}\n}\n\n/* Hide timeline line on last item in each date group */\n.last-timeline-item .timeline-line {\n display: none;\n}\n\n/* History timeline components */\n.history-panel {\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow: hidden;\n font-family: var(--history-family);\n color: var(--history-fg);\n}\n\n.history-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: var(--studio-space-sm, 0.5rem) var(--studio-space-md, 1rem);\n border-bottom: 1px solid var(--history-border);\n}\n\n.history-header-title {\n font-size: 1rem;\n font-weight: 600;\n}\n\n.history-header-actions {\n display: flex;\n align-items: center;\n gap: var(--studio-space-xs, 0.375rem);\n}\n\n.history-list {\n flex: 1;\n overflow-y: auto;\n padding: var(--studio-space-sm, 0.5rem);\n}\n\n.history-date-header {\n position: sticky;\n top: 0;\n z-index: 1;\n padding: var(--studio-space-2xs, 0.25rem) var(--studio-space-sm, 0.5rem);\n font-size: 0.75rem;\n font-weight: 600;\n color: var(--history-secondary-fg);\n background: var(--history-section-bg);\n border-bottom: 1px solid var(--history-section-divider);\n}\n\n.history-item {\n display: flex;\n gap: var(--studio-space-sm, 0.5rem);\n padding: var(--studio-space-xs, 0.375rem) var(--studio-space-sm, 0.5rem);\n border-radius: var(--studio-radius-sm, 4px);\n cursor: pointer;\n transition: background var(--studio-transition-fast, 0.1s ease);\n}\n\n.history-item:hover {\n background: var(--history-card-hover-bg);\n}\n\n.history-item[data-selected] {\n background: var(--history-accent);\n color: var(--history-accent-fg);\n}\n\n.history-item-dot {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n background: var(--history-accent);\n flex-shrink: 0;\n margin-top: 6px;\n}\n\n.history-item-content {\n flex: 1;\n min-width: 0;\n}\n\n.history-item-time {\n font-size: 0.75rem;\n color: var(--history-muted-fg);\n}\n\n.history-item-description {\n font-size: 0.8125rem;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.timeline-line {\n width: 2px;\n background: var(--history-border);\n margin-left: 3px;\n flex-shrink: 0;\n}\n\n.history-computing {\n display: flex;\n align-items: center;\n gap: var(--studio-space-xs, 0.375rem);\n padding: var(--studio-space-sm, 0.5rem);\n font-size: 0.8125rem;\n color: var(--history-muted-fg);\n}\n\n.history-labeled-field {\n display: flex;\n flex-direction: column;\n gap: var(--studio-space-3xs, 0.125rem);\n}\n\n.history-labeled-field-label {\n font-size: 0.6875rem;\n font-weight: 500;\n color: var(--history-secondary-fg);\n text-transform: uppercase;\n letter-spacing: 0.03em;\n}\n\n.history-grouping-selector {\n display: flex;\n gap: var(--studio-space-2xs, 0.25rem);\n}\n\n.history-grouping-btn {\n padding: var(--studio-space-3xs, 0.125rem) var(--studio-space-xs, 0.375rem);\n border-radius: var(--studio-radius-sm, 4px);\n border: 1px solid var(--history-border);\n background: none;\n font-size: 0.75rem;\n cursor: pointer;\n color: var(--history-secondary-fg);\n}\n\n.history-grouping-btn[data-active] {\n background: var(--history-active-bg);\n color: var(--history-fg);\n border-color: var(--history-active-border);\n}\n\n.history-copy-btn {\n display: inline-flex;\n align-items: center;\n gap: var(--studio-space-3xs, 0.125rem);\n padding: var(--studio-space-3xs, 0.125rem) var(--studio-space-2xs, 0.25rem);\n border-radius: var(--studio-radius-sm, 4px);\n border: none;\n background: none;\n font-size: 0.6875rem;\n font-family: var(--history-family-code);\n color: var(--history-secondary-fg);\n cursor: pointer;\n}\n\n.history-copy-btn:hover {\n background: var(--history-hover);\n}\n\n.timeline-card {\n border: 1px solid var(--history-card-border);\n border-radius: var(--studio-radius-md, 8px);\n padding: var(--studio-space-sm, 0.5rem);\n background: var(--history-card-bg);\n}\n\n.timeline-card[data-selected] {\n border-color: var(--history-accent);\n background: color-mix(in oklch, var(--history-accent) 10%, var(--history-card-bg));\n}\n\n/* A group's sub-items when it's expanded. Fade and settle only: the rows below\n still jump to make room, since animating height in a list people are reading\n slows the reading down. Collapsing is instant. */\n.history-subitems {\n transition:\n opacity 150ms var(--studio-ease-out, cubic-bezier(0.23, 1, 0.32, 1)),\n transform 150ms var(--studio-ease-out, cubic-bezier(0.23, 1, 0.32, 1));\n}\n@starting-style {\n .history-subitems {\n opacity: 0;\n transform: translateY(-4px);\n }\n}"));
7
7
  document.head.appendChild(elementStyle);
8
8
  }
9
9
  } catch (e) {
@@ -14,7 +14,7 @@ import { insert, createComponent, effect, setAttribute, style, template, delegat
14
14
  import { createSignal, onMount, onCleanup, createMemo, createContext, useContext, createResource, createEffect, Show, For } from "solid-js";
15
15
  import { createStore, reconcile, produce } from "solid-js/store";
16
16
  import * as Providers from "@inkandswitch/patchwork-providers";
17
- import { _ as __vitePreload } from "./index-CWHr7XoV.js";
17
+ import { _ as __vitePreload } from "./index-C1gYt7m5.js";
18
18
  import * as Automerge from "@automerge/automerge/slim";
19
19
  import { getType } from "@inkandswitch/patchwork-filesystem";
20
20
  import { getRegistry } from "@inkandswitch/patchwork-plugins";
@@ -1275,7 +1275,7 @@ function TimelineCard(props) {
1275
1275
  })();
1276
1276
  }
1277
1277
  delegateEvents(["click"]);
1278
- var _tmpl$$5 = /* @__PURE__ */ template(`<div style=margin-left:-4px;font-size:7px;width:18px;height:18px;border-radius:50%;background:var(--history-muted-fg);display:flex;align-items:center;justify-content:center;color:white;position:relative;flex-shrink:0>+`), _tmpl$2$1 = /* @__PURE__ */ template(`<input style="flex:1;min-width:0;background:transparent;border:none;border-bottom:1px solid currentColor;outline:none;padding:0;line-height:1;font:inherit;color:inherit">`), _tmpl$3$1 = /* @__PURE__ */ template(`<div style=display:flex;align-items:center;gap:0.125rem><div style=height:6px;border-radius:2px;background:var(--history-addition)></div><span style=color:var(--history-addition-fg);font-size:11px;font-weight:300>+`), _tmpl$4 = /* @__PURE__ */ template(`<div style=display:flex;align-items:center;gap:0.125rem><div style=height:6px;border-radius:2px;background:var(--history-deletion)></div><span style=color:var(--history-deletion-fg);font-size:11px;font-weight:300>-`), _tmpl$5 = /* @__PURE__ */ template(`<div style=display:flex;align-items:center;gap:0.5rem><div style=display:flex;align-items:center;flex-shrink:0></div><div style=display:flex;align-items:center;gap:0.375rem;flex-shrink:0></div><span style=color:var(--history-muted-fg);font-size:11px;font-weight:300;flex-shrink:0;width:3.5rem;text-align:right>`), _tmpl$6 = /* @__PURE__ */ template(`<div style=margin-left:1rem;margin-top:0.25rem;display:flex;flex-direction:column;gap:0.25rem>`), _tmpl$7 = /* @__PURE__ */ template(`<div>`), _tmpl$8 = /* @__PURE__ */ template(`<div style=font-size:9px;position:relative;width:18px;height:18px;border-radius:50%;display:flex;align-items:center;justify-content:center;color:white;font-weight:300;user-select:none;flex-shrink:0>`), _tmpl$9 = /* @__PURE__ */ template(`<em>Making changes...`), _tmpl$0 = /* @__PURE__ */ template(`<div title="Double-click to rename"style=display:flex;align-items:center;gap:0.25rem;cursor:text;min-width:0;overflow:hidden;flex-shrink:1><span style=overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--history-secondary-fg)></span><svg xmlns=http://www.w3.org/2000/svg viewBox="0 0 16 16"fill=currentColor aria-label="Edit label"style="flex-shrink:0;width:12px;height:12px;opacity:0;cursor:pointer;color:inherit;transition:opacity 0.15s"><path d="M11.013 1.427a1.75 1.75 0 0 1 2.474 0l1.086 1.086a1.75 1.75 0 0 1 0 2.474l-8.61 8.61c-.21.21-.47.364-.756.445l-3.251.93a.75.75 0 0 1-.927-.928l.929-3.25c.081-.286.235-.547.445-.758l8.61-8.61Z">`), _tmpl$1 = /* @__PURE__ */ template(`<div style=flex:1>`), _tmpl$10 = /* @__PURE__ */ template(`<div style=display:flex;align-items:center;gap:0.5rem><div style=font-size:9px;width:18px;height:18px;border-radius:50%;display:flex;align-items:center;justify-content:center;color:white;font-weight:300;user-select:none;flex-shrink:0></div><span style=flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--history-secondary-fg)></span><div style=display:flex;align-items:center;gap:0.375rem;flex-shrink:0></div><span style=color:var(--history-muted-fg);font-size:11px;font-weight:300;flex-shrink:0;width:3.5rem;text-align:right>`);
1278
+ var _tmpl$$5 = /* @__PURE__ */ template(`<div style=margin-left:-4px;font-size:7px;width:18px;height:18px;border-radius:50%;background:var(--history-muted-fg);display:flex;align-items:center;justify-content:center;color:white;position:relative;flex-shrink:0>+`), _tmpl$2$1 = /* @__PURE__ */ template(`<input style="flex:1;min-width:0;background:transparent;border:none;border-bottom:1px solid currentColor;outline:none;padding:0;line-height:1;font:inherit;color:inherit">`), _tmpl$3$1 = /* @__PURE__ */ template(`<div style=display:flex;align-items:center;gap:0.125rem><div style=height:6px;border-radius:2px;background:var(--history-addition)></div><span style=color:var(--history-addition-fg);font-size:11px;font-weight:300>+`), _tmpl$4 = /* @__PURE__ */ template(`<div style=display:flex;align-items:center;gap:0.125rem><div style=height:6px;border-radius:2px;background:var(--history-deletion)></div><span style=color:var(--history-deletion-fg);font-size:11px;font-weight:300>-`), _tmpl$5 = /* @__PURE__ */ template(`<div style=display:flex;align-items:center;gap:0.5rem><div style=display:flex;align-items:center;flex-shrink:0></div><div style=display:flex;align-items:center;gap:0.375rem;flex-shrink:0></div><span style=color:var(--history-muted-fg);font-size:11px;font-weight:300;flex-shrink:0;width:3.5rem;text-align:right>`), _tmpl$6 = /* @__PURE__ */ template(`<div class=history-subitems style=margin-left:1rem;margin-top:0.25rem;display:flex;flex-direction:column;gap:0.25rem>`), _tmpl$7 = /* @__PURE__ */ template(`<div>`), _tmpl$8 = /* @__PURE__ */ template(`<div style=font-size:9px;position:relative;width:18px;height:18px;border-radius:50%;display:flex;align-items:center;justify-content:center;color:white;font-weight:300;user-select:none;flex-shrink:0>`), _tmpl$9 = /* @__PURE__ */ template(`<em>Making changes...`), _tmpl$0 = /* @__PURE__ */ template(`<div title="Double-click to rename"style=display:flex;align-items:center;gap:0.25rem;cursor:text;min-width:0;overflow:hidden;flex-shrink:1><span style=overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--history-secondary-fg)></span><svg xmlns=http://www.w3.org/2000/svg viewBox="0 0 16 16"fill=currentColor aria-label="Edit label"style="flex-shrink:0;width:12px;height:12px;opacity:0;cursor:pointer;color:inherit;transition:opacity 0.15s"><path d="M11.013 1.427a1.75 1.75 0 0 1 2.474 0l1.086 1.086a1.75 1.75 0 0 1 0 2.474l-8.61 8.61c-.21.21-.47.364-.756.445l-3.251.93a.75.75 0 0 1-.927-.928l.929-3.25c.081-.286.235-.547.445-.758l8.61-8.61Z">`), _tmpl$1 = /* @__PURE__ */ template(`<div style=flex:1>`), _tmpl$10 = /* @__PURE__ */ template(`<div style=display:flex;align-items:center;gap:0.5rem><div style=font-size:9px;width:18px;height:18px;border-radius:50%;display:flex;align-items:center;justify-content:center;color:white;font-weight:300;user-select:none;flex-shrink:0></div><span style=flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--history-secondary-fg)></span><div style=display:flex;align-items:center;gap:0.375rem;flex-shrink:0></div><span style=color:var(--history-muted-fg);font-size:11px;font-weight:300;flex-shrink:0;width:3.5rem;text-align:right>`);
1279
1279
  function authorColor(authorId) {
1280
1280
  let hash = 0;
1281
1281
  for (let i = 0; i < authorId.length; i++) {
@@ -1740,4 +1740,4 @@ export {
1740
1740
  HistoryTimeline,
1741
1741
  renderHistoryTimeline
1742
1742
  };
1743
- //# sourceMappingURL=HistoryTimeline-OAiVykO2.js.map
1743
+ //# sourceMappingURL=HistoryTimeline-COYNGORP.js.map