@cychien/ezdesign 0.9.2 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/README.md +209 -550
  2. package/dist/cli.mjs +2640 -655
  3. package/dist/constants.d.ts +8 -4
  4. package/dist/extension/g/0.11.0-75c3fbebc3/dialog.js +1 -0
  5. package/dist/extension/g/0.11.0-75c3fbebc3/media.js +1 -0
  6. package/dist/extension/g/0.11.0-75c3fbebc3/page.js +44 -0
  7. package/dist/extension/g/0.11.0-75c3fbebc3/worker.js +57 -0
  8. package/dist/extension/manifest.json +15 -12
  9. package/dist/home.css +4706 -0
  10. package/dist/home.js +440 -0
  11. package/dist/native-host.mjs +33804 -115
  12. package/dist/overlay.css +5 -1
  13. package/dist/overlay.js +73 -22
  14. package/dist/shell.css +297 -1
  15. package/dist/shell.js +1230 -358
  16. package/dist/video-digest.js +16388 -0
  17. package/dist/vite.mjs +5 -1
  18. package/package.json +4 -3
  19. package/skills/ezdesign/SKILL.md +7 -3
  20. package/skills/ezdesign/reference/start.md +2 -1
  21. package/dist/extension/g/0.9.2-d9aee83dae/dialog.js +0 -1
  22. package/dist/extension/g/0.9.2-d9aee83dae/media.js +0 -1
  23. package/dist/extension/g/0.9.2-d9aee83dae/page.js +0 -39
  24. package/dist/extension/g/0.9.2-d9aee83dae/worker.js +0 -57
  25. /package/dist/extension/g/{0.9.2-d9aee83dae → 0.11.0-75c3fbebc3}/dialog.css +0 -0
  26. /package/dist/extension/g/{0.9.2-d9aee83dae → 0.11.0-75c3fbebc3}/dialog.html +0 -0
  27. /package/dist/extension/g/{0.9.2-d9aee83dae → 0.11.0-75c3fbebc3}/icon-128.png +0 -0
  28. /package/dist/extension/g/{0.9.2-d9aee83dae → 0.11.0-75c3fbebc3}/icon-16.png +0 -0
  29. /package/dist/extension/g/{0.9.2-d9aee83dae → 0.11.0-75c3fbebc3}/icon-32.png +0 -0
  30. /package/dist/extension/g/{0.9.2-d9aee83dae → 0.11.0-75c3fbebc3}/icon-48.png +0 -0
  31. /package/dist/extension/g/{0.9.2-d9aee83dae → 0.11.0-75c3fbebc3}/media.html +0 -0
  32. /package/dist/extension/g/{0.9.2-d9aee83dae → 0.11.0-75c3fbebc3}/setup.css +0 -0
  33. /package/dist/extension/g/{0.9.2-d9aee83dae → 0.11.0-75c3fbebc3}/setup.html +0 -0
  34. /package/dist/extension/g/{0.9.2-d9aee83dae → 0.11.0-75c3fbebc3}/setup.js +0 -0
package/dist/home.js ADDED
@@ -0,0 +1,440 @@
1
+ "use strict";
2
+ (() => {
3
+ // node_modules/.pnpm/@hugeicons+core-free-icons@4.3.5/node_modules/@hugeicons/core-free-icons/dist/esm/ArrowReloadHorizontalIcon.js
4
+ var ArrowReloadHorizontalIcon = [
5
+ ["path", { d: "M20.5 5.5H9.5C5.78672 5.5 3 8.18503 3 12", stroke: "currentColor", strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "1.5", key: "0" }],
6
+ ["path", { d: "M3.5 18.5H14.5C18.2133 18.5 21 15.815 21 12", stroke: "currentColor", strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "1.5", key: "1" }],
7
+ ["path", { d: "M18.5 3C18.5 3 21 4.84122 21 5.50002C21 6.15882 18.5 8 18.5 8", stroke: "currentColor", strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "1.5", key: "2" }],
8
+ ["path", { d: "M5.49998 16C5.49998 16 3.00001 17.8412 3 18.5C2.99999 19.1588 5.5 21 5.5 21", stroke: "currentColor", strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "1.5", key: "3" }]
9
+ ];
10
+
11
+ // node_modules/.pnpm/@hugeicons+core-free-icons@4.3.5/node_modules/@hugeicons/core-free-icons/dist/esm/Cancel01Icon.js
12
+ var Cancel01Icon = [
13
+ ["path", { d: "M18 6L6.00081 17.9992M17.9992 18L6 6.00085", stroke: "currentColor", strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "1.5", key: "0" }]
14
+ ];
15
+
16
+ // node_modules/.pnpm/@hugeicons+core-free-icons@4.3.5/node_modules/@hugeicons/core-free-icons/dist/esm/Download04Icon.js
17
+ var Download04Icon = [
18
+ ["path", { d: "M16.9504 12.1817C17.1981 12.814 16.5076 13.5726 15.1267 15.0899C13.6702 16.6902 12.9201 17.4904 12 17.5C11.0799 17.4904 10.3298 16.6902 8.87331 15.0899C7.49239 13.5726 6.80193 12.814 7.04964 12.1817C7.05868 12.1586 7.06851 12.1359 7.0791 12.1135C7.34928 11.542 8.24477 11.5029 10 11.5002V4.99998C10 4.53501 10 4.30253 10.0511 4.11179C10.1898 3.59414 10.5941 3.1898 11.1118 3.05111C11.3025 3 11.535 3 12 3C12.4649 3 12.6974 3 12.8882 3.05111C13.4058 3.1898 13.8102 3.59414 13.9489 4.11179C14 4.30253 14 4.53501 14 4.99998V11.5002C15.7552 11.5029 16.6507 11.542 16.9209 12.1135C16.9315 12.1359 16.9413 12.1586 16.9504 12.1817Z", stroke: "currentColor", strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "1.5", key: "0" }],
19
+ ["path", { d: "M5.00006 21H19.0001", stroke: "currentColor", strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "1.5", key: "1" }]
20
+ ];
21
+
22
+ // node_modules/.pnpm/@hugeicons+core-free-icons@4.3.5/node_modules/@hugeicons/core-free-icons/dist/esm/Folder01Icon.js
23
+ var Folder01Icon = [
24
+ ["path", { d: "M8 7H16.75C18.8567 7 19.91 7 20.6667 7.50559C20.9943 7.72447 21.2755 8.00572 21.4944 8.33329C22 9.08996 22 10.1433 22 12.25C22 15.7612 22 17.5167 21.1573 18.7779C20.7926 19.3238 20.3238 19.7926 19.7779 20.1573C18.5167 21 16.7612 21 13.25 21H12C7.28595 21 4.92893 21 3.46447 19.5355C2 18.0711 2 15.714 2 11V7.94427C2 6.1278 2 5.21956 2.38032 4.53806C2.65142 4.05227 3.05227 3.65142 3.53806 3.38032C4.21956 3 5.1278 3 6.94427 3C8.10802 3 8.6899 3 9.19926 3.19101C10.3622 3.62712 10.8418 4.68358 11.3666 5.73313L12 7", stroke: "currentColor", strokeLinecap: "round", strokeWidth: "1.5", key: "0" }]
25
+ ];
26
+
27
+ // node_modules/.pnpm/@hugeicons+core-free-icons@4.3.5/node_modules/@hugeicons/core-free-icons/dist/esm/FolderAddIcon.js
28
+ var FolderAddIcon = [
29
+ ["path", { d: "M13 21H12C7.28595 21 4.92893 21 3.46447 19.5355C2 18.0711 2 15.714 2 11V7.94427C2 6.1278 2 5.21956 2.38032 4.53806C2.65142 4.05227 3.05227 3.65142 3.53806 3.38032C4.21956 3 5.1278 3 6.94427 3C8.10802 3 8.6899 3 9.19926 3.19101C10.3622 3.62712 10.8418 4.68358 11.3666 5.73313L12 7M8 7H16.75C18.8567 7 19.91 7 20.6667 7.50559C20.9943 7.72447 21.2755 8.00572 21.4944 8.33329C21.9796 9.05942 21.9992 10.0588 22 12", stroke: "currentColor", strokeLinecap: "round", strokeWidth: "1.5", key: "0" }],
30
+ ["path", { d: "M18 13V21M22 17H14", stroke: "currentColor", strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "1.5", key: "1" }]
31
+ ];
32
+
33
+ // node_modules/.pnpm/@hugeicons+core-free-icons@4.3.5/node_modules/@hugeicons/core-free-icons/dist/esm/Logout01Icon.js
34
+ var Logout01Icon = [
35
+ ["path", { d: "M15.5 8.04045C15.4588 6.87972 15.3216 6.15451 14.8645 5.58671C14.2114 4.77536 13.0944 4.52064 10.8605 4.01121L9.85915 3.78286C6.4649 3.00882 4.76777 2.6218 3.63388 3.51317C2.5 4.40454 2.5 6.1257 2.5 9.56803V14.432C2.5 17.8743 2.5 19.5955 3.63388 20.4868C4.76777 21.3782 6.4649 20.9912 9.85915 20.2171L10.8605 19.9888C13.0944 19.4794 14.2114 19.2246 14.8645 18.4133C15.3216 17.8455 15.4588 17.1203 15.5 15.9595", stroke: "currentColor", strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "1.5", key: "0" }],
36
+ ["path", { d: "M18.5 9.01172C18.5 9.01172 21.5 11.2212 21.5 12.0117C21.5 12.8023 18.5 15.0117 18.5 15.0117M21 12.0117H8.49998", stroke: "currentColor", strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "1.5", key: "1" }]
37
+ ];
38
+
39
+ // node_modules/.pnpm/@hugeicons+core-free-icons@4.3.5/node_modules/@hugeicons/core-free-icons/dist/esm/PlusSignIcon.js
40
+ var PlusSignIcon = [
41
+ ["path", { d: "M12 4V20M20 12H4", stroke: "currentColor", strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "1.5", key: "0" }]
42
+ ];
43
+
44
+ // node_modules/.pnpm/@hugeicons+core-free-icons@4.3.5/node_modules/@hugeicons/core-free-icons/dist/esm/SidebarLeftIcon.js
45
+ var SidebarLeftIcon = [
46
+ ["path", { d: "M2 12C2 8.31087 2 6.4663 2.81382 5.15877C3.1149 4.67502 3.48891 4.25427 3.91891 3.91554C5.08116 3 6.72077 3 10 3H14C17.2792 3 18.9188 3 20.0811 3.91554C20.5111 4.25427 20.8851 4.67502 21.1862 5.15877C22 6.4663 22 8.31087 22 12C22 15.6891 22 17.5337 21.1862 18.8412C20.8851 19.325 20.5111 19.7457 20.0811 20.0845C18.9188 21 17.2792 21 14 21H10C6.72077 21 5.08116 21 3.91891 20.0845C3.48891 19.7457 3.1149 19.325 2.81382 18.8412C2 17.5337 2 15.6891 2 12Z", stroke: "currentColor", strokeWidth: "1.5", key: "0" }],
47
+ ["path", { d: "M9.5 3L9.5 21", stroke: "currentColor", strokeLinejoin: "round", strokeWidth: "1.5", key: "1" }],
48
+ ["path", { d: "M5 7H6M5 10H6", stroke: "currentColor", strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "1.5", key: "2" }]
49
+ ];
50
+
51
+ // node_modules/.pnpm/@hugeicons+core-free-icons@4.3.5/node_modules/@hugeicons/core-free-icons/dist/esm/StopIcon.js
52
+ var StopIcon = [
53
+ ["path", { d: "M4 12C4 8.72077 4 7.08116 4.81382 5.91891C5.1149 5.48891 5.48891 5.1149 5.91891 4.81382C7.08116 4 8.72077 4 12 4C15.2792 4 16.9188 4 18.0811 4.81382C18.5111 5.1149 18.8851 5.48891 19.1862 5.91891C20 7.08116 20 8.72077 20 12C20 15.2792 20 16.9188 19.1862 18.0811C18.8851 18.5111 18.5111 18.8851 18.0811 19.1862C16.9188 20 15.2792 20 12 20C8.72077 20 7.08116 20 5.91891 19.1862C5.48891 18.8851 5.1149 18.5111 4.81382 18.0811C4 16.9188 4 15.2792 4 12Z", stroke: "currentColor", strokeWidth: "1.5", key: "0" }]
54
+ ];
55
+
56
+ // node_modules/.pnpm/@hugeicons+core-free-icons@4.3.5/node_modules/@hugeicons/core-free-icons/dist/esm/UserCircleIcon.js
57
+ var UserCircleIcon = [
58
+ ["path", { d: "M18.4984 19.1511C17.3377 17.4018 15.2947 16.2009 12.9313 16.0569L11.9984 16C11.6652 16.0083 11.3547 16.0194 11.0617 16.0325C8.71722 16.1376 6.66598 17.3796 5.5 19.1511", stroke: "currentColor", strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "1.5", key: "0" }],
59
+ ["path", { d: "M14.9961 10C14.9961 11.6569 13.6529 13 11.9961 13C10.3392 13 8.99609 11.6569 8.99609 10C8.99609 8.34315 10.3392 7 11.9961 7C13.6529 7 14.9961 8.34315 14.9961 10Z", stroke: "currentColor", strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "1.5", key: "1" }],
60
+ ["path", { d: "M22 12C22 17.5228 17.5228 22 12 22C6.47715 22 2 17.5228 2 12C2 6.47715 6.47715 2 12 2C17.5228 2 22 6.47715 22 12Z", stroke: "currentColor", strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "1.5", key: "2" }]
61
+ ];
62
+
63
+ // src/brand-wordmark.ts
64
+ var WORDMARK_VIEWBOX = { x: 4.3, y: -71, width: 393.5, height: 87.2 };
65
+ var WORDMARK_PATH = "M4.3-26.5C4.3-9.65 14.5 1.2 30.05 1.2C41.2 1.2 50.65-5.1 53.8-15.25L41.6-16.15C39.55-11.35 35.05-8.5 30.05-8.5C22.15-8.5 17.35-13.95 16.75-23.2L54.55-23.2L54.5-26.55C54.1-45.4 43.15-54.2 30.05-54.2C14.5-54.2 4.3-43.35 4.3-26.5ZM16.9-31.55C18-39.65 22.7-44.5 30.05-44.5C35.8-44.5 41.05-41.05 42.2-31.55ZM104.75-42.4L104.75-53L60.85-53L60.85-43.55L91.15-43.55L59.55-10.6L59.55 0L105.55 0L105.55-9.45L73-9.45ZM160.7-71L148.8-71L148.8-45.95C145.8-51.1 139.8-54.2 132.9-54.2C119.1-54.2 110.5-43.5 110.5-26.5C110.5-9.5 119.1 1.2 132.9 1.2C140.15 1.2 146.3-2.1 149.25-7.5L149.55 0L160.7 0ZM122.7-26.5C122.7-37.65 127.95-44.65 136.2-44.65C144.4-44.65 149.65-37.65 149.65-26.5C149.65-15.6 144.45-8.65 136.2-8.65C128.05-8.65 122.7-15.6 122.7-26.5ZM167.25-26.5C167.25-9.65 177.45 1.2 193 1.2C204.15 1.2 213.6-5.1 216.75-15.25L204.55-16.15C202.5-11.35 198-8.5 193-8.5C185.1-8.5 180.3-13.95 179.7-23.2L217.5-23.2L217.45-26.55C217.05-45.4 206.1-54.2 193-54.2C177.45-54.2 167.25-43.35 167.25-26.5ZM179.85-31.55C180.95-39.65 185.65-44.5 193-44.5C198.75-44.5 204-41.05 205.15-31.55ZM255.1-36.2L267.2-36.8C265.45-47.5 256.6-54.25 244.6-54.25C230.95-54.25 222.4-47.9 222.4-37.5C222.4-27.4 231.7-24.25 243.8-21.75C249.35-20.5 255.6-19.8 255.65-14.4C255.65-9.8 250-8.2 245.6-8.2C238.6-8.2 234.25-11.75 233.25-17.45L221.15-16.75C221.95-5.6 231.7 1.2 245.75 1.2C257.55 1.2 267.9-3.55 267.9-14C267.9-24.3 259.6-28 245.8-30.4C240.5-31.35 234.8-33.25 234.7-37.8C234.6-42.2 238.7-44.85 243.85-44.85C249.05-44.85 254.1-41.6 255.1-36.2ZM274.5-53L274.5 0L286.4 0L286.4-53ZM274.3-60.6L286.6-60.6L286.6-71L274.3-71ZM316.15-2.65C322.75-2.65 328.6-5.95 331.15-11.2L331.15-4C331.15 3.15 326.35 6.85 318.15 6.85C312.45 6.85 308.4 4.35 306.6 0.2L294.4 1C297.2 10.2 306.2 16.2 318.05 16.2C332.8 16.2 343.05 8.25 343.05-5.8L343.05-53L331.5-53L331.5-44.85C328.9-50.7 323.05-54.2 316.05-54.2C302.35-54.2 292.95-43.6 292.95-28.05C292.95-12.95 302.4-2.65 316.15-2.65ZM305.2-28.15C305.2-38.15 310.25-44.4 318.4-44.4C326.55-44.4 331.65-38.15 331.5-28.15C331.4-18.15 326.35-11.9 318.4-11.9C310.35-11.9 305.2-18.15 305.2-28.15ZM352.6-53L352.6 0L364.5 0L364.5-30.4C364.5-39.45 368.9-44.4 376.3-44.4C383.35-44.4 385.9-39.45 385.9-30.4L385.9 0L397.75 0L397.75-34.1C397.75-45.85 391.5-54.2 379.65-54.2C372.5-54.2 366.45-51.25 363.6-44.15L363.3-53Z";
66
+
67
+ // src/brand.ts
68
+ var PIN = "M3 26V16A13 13 0 1 1 16 29H6A3 3 0 0 1 3 26Z";
69
+ var BRAND_SUNSET = ["#f7a160", "#e56d41", "#cf4a2c"];
70
+ function brandMarkSvg(id = "ez-sunset") {
71
+ return `<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'>${markShapes(id)}</svg>`;
72
+ }
73
+ var LOCKUP = { markSize: 16, gap: 5, wordmarkHeight: 13 };
74
+ function brandLockupSvg({ fill = "currentColor", id = "ez-sunset", height = LOCKUP.markSize } = {}) {
75
+ const { markSize, gap, wordmarkHeight } = LOCKUP;
76
+ const scale = wordmarkHeight / WORDMARK_VIEWBOX.height;
77
+ const wordmarkWidth = round(WORDMARK_VIEWBOX.width * scale);
78
+ const wordmarkY = round(markSize / 2 + WORDMARK_VIEWBOX.y / 2 * scale);
79
+ const width = markSize + gap + wordmarkWidth;
80
+ const size = height === markSize ? "" : ` width='${round(width * height / markSize)}' height='${height}'`;
81
+ return `<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 ${width} ${markSize}'${size}><svg width='${markSize}' height='${markSize}' viewBox='0 0 32 32'>${markShapes(id)}</svg><svg x='${markSize + gap}' y='${wordmarkY}' width='${wordmarkWidth}' height='${wordmarkHeight}' viewBox='${wordmarkViewBox()}'>${wordmarkShape(fill)}</svg></svg>`;
82
+ }
83
+ function markShapes(id) {
84
+ const [from, mid, to] = BRAND_SUNSET;
85
+ return `<defs><linearGradient id='${id}' x1='0.15' y1='0.05' x2='0.85' y2='1'><stop offset='0' stop-color='${from}'/><stop offset='.55' stop-color='${mid}'/><stop offset='1' stop-color='${to}'/></linearGradient></defs><path d='${PIN}' fill='url(#${id})'/><circle cx='16' cy='16' r='4.4' fill='#fff'/>`;
86
+ }
87
+ function wordmarkViewBox() {
88
+ const { x, y, width, height } = WORDMARK_VIEWBOX;
89
+ return `${x} ${y} ${width} ${height}`;
90
+ }
91
+ function wordmarkShape(fill) {
92
+ return `<path fill='${fill}' d='${WORDMARK_PATH}'/>`;
93
+ }
94
+ var round = (n) => Math.round(n * 100) / 100;
95
+
96
+ // src/desktop-wire.ts
97
+ var DESKTOP_BRIDGE = "ezdesignDesktop";
98
+
99
+ // src/client/host.ts
100
+ var bridge = window[DESKTOP_BRIDGE];
101
+ var host = bridge ? {
102
+ kind: "desktop",
103
+ showProject: (opened) => bridge.showProject(opened),
104
+ pickFolder: () => bridge.pickFolder(),
105
+ pathForFile: (file) => bridge.pathForFile(file),
106
+ toggleSidebar: () => bridge.toggleSidebar(),
107
+ onLayout: (listener) => bridge.onLayout(listener),
108
+ onUpdate: (listener) => bridge.onUpdate?.(listener),
109
+ takeUpdate: () => bridge.takeUpdate?.()
110
+ } : { kind: "browser", showProject: (opened) => location.assign(opened.shellUrl) };
111
+ if (bridge) {
112
+ const root = document.documentElement;
113
+ root.dataset.host = "desktop";
114
+ root.style.setProperty("--sidebar-width", `${bridge.sidebarWidth}px`);
115
+ root.style.setProperty("--pane-inset", `${bridge.paneInset}px`);
116
+ root.style.setProperty("--pane-radius", `${bridge.paneRadius}px`);
117
+ bridge.onLayout(({ sidebar }) => {
118
+ root.dataset.sidebar = sidebar ? "open" : "closed";
119
+ root.style.setProperty("--traffic-light-room", sidebar ? "0px" : `${bridge.trafficLightRoom}px`);
120
+ });
121
+ }
122
+
123
+ // src/client/icon.ts
124
+ var SVG_NS = "http://www.w3.org/2000/svg";
125
+ var kebab = (key) => key.replace(/[A-Z]/g, (c) => `-${c.toLowerCase()}`);
126
+ function icon(node, size = 16) {
127
+ const svg = document.createElementNS(SVG_NS, "svg");
128
+ svg.setAttribute("viewBox", "0 0 24 24");
129
+ svg.setAttribute("width", String(size));
130
+ svg.setAttribute("height", String(size));
131
+ svg.setAttribute("fill", "none");
132
+ svg.setAttribute("aria-hidden", "true");
133
+ svg.setAttribute("data-ez-ui", "");
134
+ for (const [tag, attrs] of node) {
135
+ const child = document.createElementNS(SVG_NS, tag);
136
+ for (const [key, value] of Object.entries(attrs)) {
137
+ if (key === "key") continue;
138
+ child.setAttribute(kebab(key), String(value));
139
+ }
140
+ svg.appendChild(child);
141
+ }
142
+ return svg;
143
+ }
144
+
145
+ // src/version-header.ts
146
+ var VERSION_HEADER = "x-ezdesign-version";
147
+
148
+ // src/client/projects.ts
149
+ function projectsClient(api2, version) {
150
+ async function request(path, body) {
151
+ const res = await fetch(`${api2}/projects${path}`, {
152
+ method: body === void 0 ? "GET" : "POST",
153
+ headers: { [VERSION_HEADER]: version, "content-type": "application/json" },
154
+ ...body === void 0 ? {} : { body: JSON.stringify(body) }
155
+ });
156
+ if (res.status === 409) {
157
+ location.reload();
158
+ throw new Error("ezdesign was updated; reloading");
159
+ }
160
+ if (!res.ok) throw new Error((await res.json().catch(() => null))?.error ?? `${res.status}`);
161
+ return await res.json();
162
+ }
163
+ return {
164
+ list: () => request(""),
165
+ async go(project) {
166
+ host.showProject(await request("/open", { project, host: host.kind }));
167
+ },
168
+ stop: async (project) => void await request("/stop", { project }),
169
+ add: (path) => request("", { path }),
170
+ hide: async (project) => void await request("/hide", { project }),
171
+ watch(onList) {
172
+ const source = new EventSource(`${api2}/projects/events`);
173
+ source.onmessage = (e) => {
174
+ const list = JSON.parse(e.data);
175
+ if (list.version !== version) return location.reload();
176
+ onList(list);
177
+ };
178
+ return () => source.close();
179
+ }
180
+ };
181
+ }
182
+ function devServerStatus(project) {
183
+ const server = project.session?.devServer;
184
+ if (!server || server.phase === "idle") return null;
185
+ const where = server.origin?.replace(/^https?:\/\//, "");
186
+ const text = {
187
+ idle: "",
188
+ starting: "\u555F\u52D5\u4E2D",
189
+ running: where ? `\u57F7\u884C\u4E2D \xB7 ${where}` : "\u57F7\u884C\u4E2D",
190
+ external: where ? `\u4F60\u81EA\u5DF1\u7684 server \xB7 ${where}` : "\u4F60\u81EA\u5DF1\u7684 server",
191
+ stopped: "\u5DF2\u505C\u6B62",
192
+ crashed: "\u505C\u6B62\u904B\u4F5C\u4E86",
193
+ blocked: "\u7F3A\u5C11\u5DE5\u5177",
194
+ "needs-command": "\u9700\u8981\u555F\u52D5\u6307\u4EE4"
195
+ };
196
+ return { phase: server.phase, text: text[server.phase] };
197
+ }
198
+
199
+ // src/client/home.ts
200
+ var LIST_SHOWN_MARK = "ez:list-shown";
201
+ var HOME_TEST_IDS = {
202
+ list: "ez-side-list",
203
+ row: "ez-side-row",
204
+ add: "ez-side-add"
205
+ };
206
+ function h(tag, className, text) {
207
+ const node = document.createElement(tag);
208
+ if (className) node.className = className;
209
+ if (text !== void 0) node.textContent = text;
210
+ return node;
211
+ }
212
+ function iconButton(glyph, label, className = "ez-side-icon") {
213
+ const b = h("button", className);
214
+ b.type = "button";
215
+ b.title = label;
216
+ b.setAttribute("aria-label", label);
217
+ b.append(icon(glyph, 15));
218
+ return b;
219
+ }
220
+ function appOnlyNote() {
221
+ const page = h("main", "ez-home");
222
+ const head = h("header", "ez-home-head");
223
+ const brand = h("div", "ez-logo");
224
+ brand.setAttribute("role", "img");
225
+ brand.setAttribute("aria-label", "ezdesign");
226
+ brand.innerHTML = brandLockupSvg();
227
+ head.append(brand);
228
+ page.append(
229
+ head,
230
+ h("p", "ez-home-lead ez-home-app-only", "\u5C08\u6848\u5217\u8868\u5728 ezdesign \u7684 Mac app \u88E1\u4F7F\u7528\u3002\u8981 review \u4E00\u500B\u5C08\u6848\uFF0C\u8ACB\u5728\u5B83\u7684\u8CC7\u6599\u593E\u88E1\u57F7\u884C npx -y @cychien/ezdesign\u3002")
231
+ );
232
+ return page;
233
+ }
234
+ function bootHome(root, api2, version) {
235
+ if (host.kind !== "desktop") return void root.replaceChildren(appOnlyNote());
236
+ const pane = new URLSearchParams(location.search).get("pane");
237
+ if (pane === "empty") return void root.replaceChildren(emptyPane(host, api2, version));
238
+ bootSidebar(root, host, api2, version);
239
+ }
240
+ function addAndOpen(client, path) {
241
+ return client.add(path).then((added) => client.go(added.project));
242
+ }
243
+ function emptyPane(desktop, api2, version) {
244
+ const client = projectsClient(api2, version);
245
+ const page = h("main", "ez-empty");
246
+ const mark = h("div", "ez-empty-mark");
247
+ mark.innerHTML = brandMarkSvg("ez-empty-sunset");
248
+ const error = h("p", "ez-empty-error");
249
+ const add = h("button", "ez-home-add-go ez-home-pick");
250
+ add.type = "button";
251
+ add.append(icon(FolderAddIcon, 16), h("span", void 0, "\u52A0\u5165\u65B0\u5C08\u6848"));
252
+ add.onclick = () => void desktop.pickFolder().then((path) => path && addAndOpen(client, path).catch((e) => error.textContent = e.message));
253
+ page.append(
254
+ mark,
255
+ h("h1", "ez-empty-title", "\u9078\u4E00\u500B\u5C08\u6848\u958B\u59CB\u8A2D\u8A08"),
256
+ h("p", "ez-empty-lead", "\u5F9E\u5DE6\u908A\u9078\u5C08\u6848\uFF0C\u6216\u52A0\u5165\u65B0\u5C08\u6848"),
257
+ add,
258
+ error
259
+ );
260
+ return page;
261
+ }
262
+ function bootSidebar(root, desktop, api2, version) {
263
+ const client = projectsClient(api2, version);
264
+ let list = null;
265
+ let shown = null;
266
+ const unseen = /* @__PURE__ */ new Set();
267
+ let error = null;
268
+ const side = h("nav", "ez-side");
269
+ side.setAttribute("aria-label", "\u5C08\u6848");
270
+ const top = h("header", "ez-side-top");
271
+ const collapse = iconButton(SidebarLeftIcon, "\u6536\u5408\u5074\u908A\u6B04\uFF08\u2303\u2318S\uFF09");
272
+ collapse.onclick = () => desktop.toggleSidebar();
273
+ top.append(collapse);
274
+ const section = h("div", "ez-side-section");
275
+ const add = iconButton(PlusSignIcon, "\u52A0\u5165\u65B0\u5C08\u6848\uFF08\u2318O\uFF09");
276
+ add.dataset.testid = HOME_TEST_IDS.add;
277
+ add.onclick = () => void desktop.pickFolder().then((path) => path && open(() => addAndOpen(client, path)));
278
+ section.append(h("span", "ez-side-label", "\u5C08\u6848"), add);
279
+ const rows = h("ul", "ez-side-list");
280
+ rows.dataset.testid = HOME_TEST_IDS.list;
281
+ const errorLine = h("p", "ez-side-error");
282
+ errorLine.setAttribute("role", "alert");
283
+ const account = accountFooter(api2);
284
+ side.append(top, section, rows, errorLine, updateRow(desktop), account.el);
285
+ root.replaceChildren(side, h("div", "ez-side-grip"));
286
+ function open(go) {
287
+ error = null;
288
+ paint();
289
+ go().catch((e) => error = e.message).finally(paint);
290
+ }
291
+ function row(project) {
292
+ const item = h("li", "ez-side-row");
293
+ item.dataset.testid = HOME_TEST_IDS.row;
294
+ item.toggleAttribute("data-current", project.project === shown);
295
+ item.toggleAttribute("data-missing", !project.exists);
296
+ const pick = h("button", "ez-side-open");
297
+ pick.type = "button";
298
+ pick.title = project.exists ? project.project : `${project.project}\uFF08\u8CC7\u6599\u593E\u4E0D\u898B\u4E86\uFF09`;
299
+ pick.disabled = !project.exists;
300
+ pick.append(icon(Folder01Icon, 15), h("span", "ez-side-name", project.name));
301
+ const agent = project.session?.agentWorking ? "working" : unseen.has(project.project) ? "done" : null;
302
+ if (agent) {
303
+ const dot = h("span", "ez-side-agent");
304
+ dot.dataset.state = agent;
305
+ dot.title = agent === "working" ? "Agent \u5DE5\u4F5C\u4E2D" : "Agent \u505A\u5B8C\u4E86";
306
+ pick.append(dot);
307
+ }
308
+ pick.onclick = () => open(() => client.go(project.project));
309
+ item.append(pick);
310
+ const actions = h("span", "ez-side-actions");
311
+ const status = devServerStatus(project);
312
+ if (status && (status.phase === "running" || status.phase === "starting")) {
313
+ const stop = iconButton(StopIcon, `\u505C\u6B62 ${project.name} \u7684 dev server`);
314
+ stop.onclick = () => void client.stop(project.project).catch((e) => (error = e.message, paint()));
315
+ actions.append(stop);
316
+ }
317
+ const hide = iconButton(Cancel01Icon, `\u5F9E\u5217\u8868\u79FB\u9664 ${project.name}\uFF08\u8CC7\u6599\u593E\u548C .ezdesign \u90FD\u6703\u4FDD\u7559\uFF09`);
318
+ hide.onclick = () => void client.hide(project.project).catch((e) => (error = e.message, paint()));
319
+ actions.append(hide);
320
+ item.append(actions);
321
+ return item;
322
+ }
323
+ function paint() {
324
+ errorLine.textContent = error ?? "";
325
+ errorLine.hidden = !error;
326
+ if (!list) return;
327
+ if (!list.projects.length) {
328
+ const empty = h("li", "ez-side-empty", "\u6309 + \u6216\u628A\u5C08\u6848\u8CC7\u6599\u593E\u62D6\u9032\u4F86\u3002");
329
+ rows.replaceChildren(empty);
330
+ return;
331
+ }
332
+ rows.replaceChildren(...list.projects.map(row));
333
+ }
334
+ document.addEventListener("dragover", (e) => {
335
+ e.preventDefault();
336
+ side.toggleAttribute("data-dragging", true);
337
+ });
338
+ document.addEventListener("dragleave", (e) => {
339
+ if (!e.relatedTarget) side.toggleAttribute("data-dragging", false);
340
+ });
341
+ document.addEventListener("drop", (e) => {
342
+ e.preventDefault();
343
+ side.toggleAttribute("data-dragging", false);
344
+ const file = e.dataTransfer?.files[0];
345
+ const path = file ? desktop.pathForFile(file) : "";
346
+ if (path) open(() => addAndOpen(client, path));
347
+ });
348
+ desktop.onLayout((layout) => {
349
+ shown = layout.shown;
350
+ if (shown) unseen.delete(shown);
351
+ paint();
352
+ });
353
+ client.watch((next) => {
354
+ for (const project of next.projects) {
355
+ const before = list?.projects.find((p) => p.project === project.project)?.session?.agentWorking;
356
+ if (before && !project.session?.agentWorking && project.project !== shown) unseen.add(project.project);
357
+ }
358
+ list = next;
359
+ account.paint(next.account);
360
+ paint();
361
+ if (!performance.getEntriesByName(LIST_SHOWN_MARK).length) performance.mark(LIST_SHOWN_MARK);
362
+ });
363
+ paint();
364
+ }
365
+ function accountFooter(api2) {
366
+ const el = h("div", "ez-side-account");
367
+ const button = h("button", "ez-side-open ez-side-account-btn");
368
+ button.type = "button";
369
+ const menu = h("div", "ez-menu");
370
+ menu.setAttribute("role", "menu");
371
+ const who = h("div", "ez-account-who");
372
+ const signOut = h("button", "ez-menu-item");
373
+ signOut.type = "button";
374
+ signOut.setAttribute("role", "menuitem");
375
+ signOut.append(icon(Logout01Icon, 14), h("span", "ez-menu-name", "\u767B\u51FA"));
376
+ menu.append(who, signOut);
377
+ el.append(menu, button);
378
+ let email;
379
+ const setOpen = (open) => {
380
+ el.toggleAttribute("data-open", open && !!email);
381
+ if (email) button.setAttribute("aria-expanded", String(el.hasAttribute("data-open")));
382
+ };
383
+ button.onclick = () => email ? setOpen(!el.hasAttribute("data-open")) : void window.open(`${api2}/account/login`, "_blank");
384
+ signOut.onclick = () => {
385
+ setOpen(false);
386
+ void fetch(`${api2}/account/logout`, { method: "POST", headers: { "content-type": "application/json" } });
387
+ };
388
+ document.addEventListener("click", (e) => {
389
+ if (e.target instanceof Node && !el.contains(e.target)) setOpen(false);
390
+ });
391
+ el.addEventListener("keydown", (e) => {
392
+ if (e.key !== "Escape" || !el.hasAttribute("data-open")) return;
393
+ setOpen(false);
394
+ button.focus();
395
+ });
396
+ return {
397
+ el,
398
+ paint(account) {
399
+ if (account.email === email) return;
400
+ email = account.email;
401
+ setOpen(false);
402
+ if (email) {
403
+ button.setAttribute("aria-haspopup", "menu");
404
+ button.title = email;
405
+ button.replaceChildren(h("span", "ez-avatar", email.charAt(0).toUpperCase()), h("span", "ez-side-name", email));
406
+ who.replaceChildren(h("span", "ez-account-label", "\u5DF2\u767B\u5165"), h("span", "ez-account-email", email));
407
+ } else {
408
+ button.removeAttribute("aria-haspopup");
409
+ button.removeAttribute("aria-expanded");
410
+ button.title = "\u767B\u5165 ezdesign";
411
+ button.replaceChildren(icon(UserCircleIcon, 15), h("span", "ez-side-name", "\u767B\u5165"));
412
+ }
413
+ }
414
+ };
415
+ }
416
+ function updateRow(desktop) {
417
+ const el = h("div", "ez-side-update");
418
+ el.hidden = true;
419
+ const button = h("button", "ez-side-open ez-side-update-btn");
420
+ button.type = "button";
421
+ button.onclick = () => desktop.takeUpdate();
422
+ el.append(button);
423
+ desktop.onUpdate((offer) => {
424
+ el.hidden = !offer;
425
+ if (!offer) return;
426
+ const restart = offer.by === "restart";
427
+ button.title = restart ? `\u91CD\u65B0\u555F\u52D5 ezdesign\uFF0C\u63DB\u6210 ${offer.version}` : `\u4E0B\u8F09 ezdesign ${offer.version}`;
428
+ button.replaceChildren(
429
+ icon(restart ? ArrowReloadHorizontalIcon : Download04Icon, 15),
430
+ h("span", "ez-side-name", restart ? `\u91CD\u65B0\u555F\u52D5\u4EE5\u66F4\u65B0\u5230 ${offer.version}` : `\u4E0B\u8F09\u65B0\u7248 ${offer.version}`)
431
+ );
432
+ });
433
+ return el;
434
+ }
435
+
436
+ // src/client/home-entry.ts
437
+ var script = document.currentScript;
438
+ var api = `${new URL(script?.src ?? location.href).pathname.replace(/\/home\.js$/, "")}/api`;
439
+ bootHome(document.getElementById("ez-home") ?? document.body, api, script?.dataset.version ?? "");
440
+ })();