@inkandswitch/patchwork-pkg-base 0.0.98 → 0.0.100
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/module-settings-url +1 -1
- package/package.json +1 -1
- package/packages/chat/dist/index.js +1 -1
- package/packages/comments-view/dist/assets/{main-51fB7vpU.js → main-wSSvAVfi.js} +22 -4
- package/packages/comments-view/dist/assets/main-wSSvAVfi.js.map +1 -0
- package/packages/comments-view/dist/index.js +3 -3
- package/packages/drafts/dist/assets/main-CG9HOCai.js +11 -0
- package/packages/embed/dist/assets/{tool-Cg7zrpH9.js → tool-D58NGTZ7.js} +4 -2
- package/packages/embed/dist/assets/tool-D58NGTZ7.js.map +1 -0
- package/packages/embed/dist/index.js +1 -1
- package/packages/file/dist/index.js +24 -25
- package/packages/file/dist/index.js.map +1 -1
- package/packages/file/dist/{tool-D5jQjo2l.js → tool-UKWDK93W.js} +1740 -1742
- package/packages/file/dist/{tool-D5jQjo2l.js.map → tool-UKWDK93W.js.map} +1 -1
- package/packages/file/dist/{typescript-language-server-BOT6JPPD.js → typescript-language-server-BgBx0vSF.js} +2 -2
- package/packages/file/dist/{typescript-language-server-BOT6JPPD.js.map → typescript-language-server-BgBx0vSF.js.map} +1 -1
- package/packages/folder/dist/index.js +1 -1
- package/packages/folder/dist/{tool-JSQNX2I6.js → tool-WAWTPB4A.js} +2 -2
- package/packages/folder/dist/{tool-JSQNX2I6.js.map → tool-WAWTPB4A.js.map} +1 -1
- package/packages/history-view/dist/assets/{HistoryTimeline-OAiVykO2.js → HistoryTimeline-COYNGORP.js} +4 -4
- package/packages/history-view/dist/assets/{HistoryTimeline-OAiVykO2.js.map → HistoryTimeline-COYNGORP.js.map} +1 -1
- package/packages/history-view/dist/assets/{index-CWHr7XoV.js → index-C1gYt7m5.js} +2 -2
- package/packages/history-view/dist/assets/{index-CWHr7XoV.js.map → index-C1gYt7m5.js.map} +1 -1
- package/packages/history-view/dist/index.js +1 -1
- package/packages/llm-host/dist/LlmConfigTray-DdZHZT4F.js +615 -0
- package/packages/llm-host/dist/index.js +1 -1
- package/packages/packages/dist/index.js +17 -0
- package/packages/sideboard/dist/{chunk-QLI3ZN4W.js → chunk-73XN2I2U.js} +3 -3
- package/packages/sideboard/dist/chunk-NS3ADG2Z.js +2 -0
- package/packages/sideboard/dist/chunk-NS3ADG2Z.js.map +7 -0
- package/packages/sideboard/dist/{chunk-3HE5SPGR.js → chunk-OFWMAVKQ.js} +2 -2
- package/packages/sideboard/dist/{create-new-menu-PDAHMB7O.js → create-new-menu-4VNS2UFI.js} +2 -2
- package/packages/sideboard/dist/document-list-panel-SCICIJCF.js +2 -0
- package/packages/sideboard/dist/index.css +1 -1
- package/packages/sideboard/dist/index.css.map +2 -2
- package/packages/sideboard/dist/index.js +1 -1
- package/packages/sideboard/dist/{item-menu-VIMMKF26.js → item-menu-3JUJN3MS.js} +2 -2
- package/packages/sideboard/dist/sideboard/sideboard.js +1 -1
- package/packages/sync-indicator/dist/assets/SyncIndicator-B2ag1OoZ.js +1 -1
- package/packages/theming/dist/{active-theme-ZEJCS5RM.js → active-theme-BMSIQXBV.js} +2 -2
- package/packages/theming/dist/{chunk-FLDRNDLY.js → chunk-Z3JB7ERH.js} +2 -2
- package/packages/theming/dist/main.js +3 -3
- package/packages/theming/dist/{theme-L3L6DYF3.css → theme-7OG2K56L.css} +2 -0
- package/packages/theming/dist/{theme-titlebar-HAEXLVMW.js → theme-titlebar-YIFJINPJ.js} +2 -2
- package/packages/theming/dist/{theme-tray-XYB4LGZ6.js → theme-tray-7J247NRY.js} +33 -13
- package/packages/theming/dist/theme-tray-7J247NRY.js.map +7 -0
- package/packages/theming/dist/tool.js +1 -1
- package/plugin-registry-url +1 -1
- package/packages/comments-view/dist/assets/main-51fB7vpU.js.map +0 -1
- package/packages/embed/dist/assets/tool-Cg7zrpH9.js.map +0 -1
- package/packages/llm-host/dist/LlmConfigTray-CkM9XUX1.js +0 -600
- package/packages/sideboard/dist/chunk-6LWWNFKU.js +0 -2
- package/packages/sideboard/dist/chunk-6LWWNFKU.js.map +0 -7
- package/packages/sideboard/dist/document-list-panel-C7R2SL7S.js +0 -2
- package/packages/theming/dist/theme-tray-XYB4LGZ6.js.map +0 -7
- /package/packages/sideboard/dist/{chunk-QLI3ZN4W.js.map → chunk-73XN2I2U.js.map} +0 -0
- /package/packages/sideboard/dist/{chunk-3HE5SPGR.js.map → chunk-OFWMAVKQ.js.map} +0 -0
- /package/packages/sideboard/dist/{create-new-menu-PDAHMB7O.js.map → create-new-menu-4VNS2UFI.js.map} +0 -0
- /package/packages/sideboard/dist/{document-list-panel-C7R2SL7S.js.map → document-list-panel-SCICIJCF.js.map} +0 -0
- /package/packages/sideboard/dist/{item-menu-VIMMKF26.js.map → item-menu-3JUJN3MS.js.map} +0 -0
- /package/packages/theming/dist/{active-theme-ZEJCS5RM.js.map → active-theme-BMSIQXBV.js.map} +0 -0
- /package/packages/theming/dist/{chunk-FLDRNDLY.js.map → chunk-Z3JB7ERH.js.map} +0 -0
- /package/packages/theming/dist/{theme-titlebar-HAEXLVMW.js.map → theme-titlebar-YIFJINPJ.js.map} +0 -0
|
@@ -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-
|
|
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-
|
|
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-
|
|
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-
|
|
1743
|
+
//# sourceMappingURL=HistoryTimeline-COYNGORP.js.map
|