@agent-native/core 0.42.0 → 0.43.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 (110) hide show
  1. package/README.md +17 -56
  2. package/dist/cli/recap.d.ts.map +1 -1
  3. package/dist/cli/recap.js +24 -13
  4. package/dist/cli/recap.js.map +1 -1
  5. package/dist/cli/skills.d.ts +2 -6
  6. package/dist/cli/skills.d.ts.map +1 -1
  7. package/dist/cli/skills.js +8 -66
  8. package/dist/cli/skills.js.map +1 -1
  9. package/dist/client/blocks/index.d.ts +11 -0
  10. package/dist/client/blocks/index.d.ts.map +1 -1
  11. package/dist/client/blocks/index.js +11 -0
  12. package/dist/client/blocks/index.js.map +1 -1
  13. package/dist/client/blocks/library/AnnotatedCodeBlock.d.ts.map +1 -1
  14. package/dist/client/blocks/library/AnnotatedCodeBlock.js +2 -2
  15. package/dist/client/blocks/library/AnnotatedCodeBlock.js.map +1 -1
  16. package/dist/client/blocks/library/DiffBlock.d.ts.map +1 -1
  17. package/dist/client/blocks/library/DiffBlock.js +86 -21
  18. package/dist/client/blocks/library/DiffBlock.js.map +1 -1
  19. package/dist/client/blocks/library/FileTreeBlock.d.ts.map +1 -1
  20. package/dist/client/blocks/library/FileTreeBlock.js +27 -4
  21. package/dist/client/blocks/library/FileTreeBlock.js.map +1 -1
  22. package/dist/client/blocks/library/JsonExplorerBlock.js +1 -1
  23. package/dist/client/blocks/library/JsonExplorerBlock.js.map +1 -1
  24. package/dist/client/blocks/library/MermaidBlock.js +1 -1
  25. package/dist/client/blocks/library/MermaidBlock.js.map +1 -1
  26. package/dist/client/blocks/library/annotation-rail.d.ts +19 -0
  27. package/dist/client/blocks/library/annotation-rail.d.ts.map +1 -1
  28. package/dist/client/blocks/library/annotation-rail.js +19 -0
  29. package/dist/client/blocks/library/annotation-rail.js.map +1 -1
  30. package/dist/client/blocks/library/callout.config.d.ts +29 -0
  31. package/dist/client/blocks/library/callout.config.d.ts.map +1 -0
  32. package/dist/client/blocks/library/callout.config.js +33 -0
  33. package/dist/client/blocks/library/callout.config.js.map +1 -0
  34. package/dist/client/blocks/library/callout.d.ts +20 -0
  35. package/dist/client/blocks/library/callout.d.ts.map +1 -0
  36. package/dist/client/blocks/library/callout.js +61 -0
  37. package/dist/client/blocks/library/callout.js.map +1 -0
  38. package/dist/client/blocks/library/checklist.d.ts.map +1 -1
  39. package/dist/client/blocks/library/checklist.js +3 -3
  40. package/dist/client/blocks/library/checklist.js.map +1 -1
  41. package/dist/client/blocks/library/decision.config.d.ts +37 -0
  42. package/dist/client/blocks/library/decision.config.d.ts.map +1 -0
  43. package/dist/client/blocks/library/decision.config.js +32 -0
  44. package/dist/client/blocks/library/decision.config.js.map +1 -0
  45. package/dist/client/blocks/library/decision.d.ts +19 -0
  46. package/dist/client/blocks/library/decision.d.ts.map +1 -0
  47. package/dist/client/blocks/library/decision.js +119 -0
  48. package/dist/client/blocks/library/decision.js.map +1 -0
  49. package/dist/client/blocks/library/diagram.config.d.ts +64 -0
  50. package/dist/client/blocks/library/diagram.config.d.ts.map +1 -0
  51. package/dist/client/blocks/library/diagram.config.js +111 -0
  52. package/dist/client/blocks/library/diagram.config.js.map +1 -0
  53. package/dist/client/blocks/library/diagram.d.ts +16 -0
  54. package/dist/client/blocks/library/diagram.d.ts.map +1 -0
  55. package/dist/client/blocks/library/diagram.js +261 -0
  56. package/dist/client/blocks/library/diagram.js.map +1 -0
  57. package/dist/client/blocks/library/question-form.config.d.ts +69 -0
  58. package/dist/client/blocks/library/question-form.config.d.ts.map +1 -0
  59. package/dist/client/blocks/library/question-form.config.js +58 -0
  60. package/dist/client/blocks/library/question-form.config.js.map +1 -0
  61. package/dist/client/blocks/library/question-form.d.ts +20 -0
  62. package/dist/client/blocks/library/question-form.d.ts.map +1 -0
  63. package/dist/client/blocks/library/question-form.js +286 -0
  64. package/dist/client/blocks/library/question-form.js.map +1 -0
  65. package/dist/client/blocks/library/sanitize-html.d.ts +5 -0
  66. package/dist/client/blocks/library/sanitize-html.d.ts.map +1 -0
  67. package/dist/client/blocks/library/sanitize-html.js +240 -0
  68. package/dist/client/blocks/library/sanitize-html.js.map +1 -0
  69. package/dist/client/blocks/library/server-specs.d.ts.map +1 -1
  70. package/dist/client/blocks/library/server-specs.js +59 -0
  71. package/dist/client/blocks/library/server-specs.js.map +1 -1
  72. package/dist/client/blocks/library/specs.d.ts.map +1 -1
  73. package/dist/client/blocks/library/specs.js +11 -0
  74. package/dist/client/blocks/library/specs.js.map +1 -1
  75. package/dist/client/blocks/library/tabs.d.ts.map +1 -1
  76. package/dist/client/blocks/library/tabs.js +12 -12
  77. package/dist/client/blocks/library/tabs.js.map +1 -1
  78. package/dist/client/blocks/library/wireframe-kit.d.ts +260 -0
  79. package/dist/client/blocks/library/wireframe-kit.d.ts.map +1 -0
  80. package/dist/client/blocks/library/wireframe-kit.js +920 -0
  81. package/dist/client/blocks/library/wireframe-kit.js.map +1 -0
  82. package/dist/client/blocks/library/wireframe.config.d.ts +123 -0
  83. package/dist/client/blocks/library/wireframe.config.d.ts.map +1 -0
  84. package/dist/client/blocks/library/wireframe.config.js +294 -0
  85. package/dist/client/blocks/library/wireframe.config.js.map +1 -0
  86. package/dist/client/blocks/library/wireframe.d.ts +15 -0
  87. package/dist/client/blocks/library/wireframe.d.ts.map +1 -0
  88. package/dist/client/blocks/library/wireframe.js +206 -0
  89. package/dist/client/blocks/library/wireframe.js.map +1 -0
  90. package/dist/client/blocks/registry.d.ts +9 -0
  91. package/dist/client/blocks/registry.d.ts.map +1 -1
  92. package/dist/client/blocks/registry.js +12 -5
  93. package/dist/client/blocks/registry.js.map +1 -1
  94. package/dist/client/blocks/server.d.ts +1 -0
  95. package/dist/client/blocks/server.d.ts.map +1 -1
  96. package/dist/client/blocks/server.js +1 -0
  97. package/dist/client/blocks/server.js.map +1 -1
  98. package/dist/client/blocks/types.d.ts +8 -0
  99. package/dist/client/blocks/types.d.ts.map +1 -1
  100. package/dist/client/blocks/types.js.map +1 -1
  101. package/dist/client/rich-markdown-editor/DragHandle.d.ts.map +1 -1
  102. package/dist/client/rich-markdown-editor/DragHandle.js +77 -12
  103. package/dist/client/rich-markdown-editor/DragHandle.js.map +1 -1
  104. package/dist/styles/agent-native.css +1 -0
  105. package/dist/styles/blocks.css +1380 -0
  106. package/docs/content/plan-plugin.md +8 -8
  107. package/docs/content/pr-visual-recap.md +2 -2
  108. package/docs/content/template-plan.md +94 -17
  109. package/package.json +2 -1
  110. package/docs/content/visual-plans.md +0 -82
@@ -0,0 +1,920 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { createContext, useContext, useEffect, useRef, useState, useSyncExternalStore, } from "react";
3
+ import rough from "roughjs";
4
+ const STYLE_STORAGE_KEY = "plan-wireframe-style";
5
+ const styleListeners = new Set();
6
+ function readStoredStyle() {
7
+ if (typeof localStorage === "undefined")
8
+ return "sketchy";
9
+ try {
10
+ return localStorage.getItem(STYLE_STORAGE_KEY) === "clean"
11
+ ? "clean"
12
+ : "sketchy";
13
+ }
14
+ catch {
15
+ return "sketchy";
16
+ }
17
+ }
18
+ let currentStyle = readStoredStyle();
19
+ export function setWireframeStyle(style) {
20
+ if (style === currentStyle)
21
+ return;
22
+ currentStyle = style;
23
+ try {
24
+ localStorage.setItem(STYLE_STORAGE_KEY, style);
25
+ }
26
+ catch {
27
+ // ignore (private mode / disabled storage)
28
+ }
29
+ for (const listener of styleListeners)
30
+ listener();
31
+ }
32
+ export function toggleWireframeStyle() {
33
+ setWireframeStyle(currentStyle === "sketchy" ? "clean" : "sketchy");
34
+ }
35
+ function subscribeStyle(callback) {
36
+ styleListeners.add(callback);
37
+ const onStorage = (event) => {
38
+ if (event.key === STYLE_STORAGE_KEY) {
39
+ currentStyle = readStoredStyle();
40
+ callback();
41
+ }
42
+ };
43
+ if (typeof window !== "undefined") {
44
+ window.addEventListener("storage", onStorage);
45
+ }
46
+ return () => {
47
+ styleListeners.delete(callback);
48
+ if (typeof window !== "undefined") {
49
+ window.removeEventListener("storage", onStorage);
50
+ }
51
+ };
52
+ }
53
+ export function useWireframeStyle() {
54
+ return useSyncExternalStore(subscribeStyle, () => currentStyle, () => "sketchy");
55
+ }
56
+ /** Read the live dark-mode flag from the document root (next-themes-free). */
57
+ export function useIsDark() {
58
+ const [isDark, setIsDark] = useState(false);
59
+ useEffect(() => {
60
+ if (typeof document === "undefined")
61
+ return;
62
+ const root = document.documentElement;
63
+ const read = () => setIsDark(root.classList.contains("dark"));
64
+ read();
65
+ const observer = new MutationObserver(read);
66
+ observer.observe(root, { attributes: true, attributeFilter: ["class"] });
67
+ return () => observer.disconnect();
68
+ }, []);
69
+ return isDark;
70
+ }
71
+ /* ========================================================================== */
72
+ /* Primitives (ported from kit/primitives.tsx) */
73
+ /* ========================================================================== */
74
+ /**
75
+ * Frame-level config threaded to every Screen so skeleton / theme / sketch-vs-
76
+ * clean reach the kit no matter which path renders the root Screen.
77
+ */
78
+ export const KitConfigContext = createContext({});
79
+ const V = {
80
+ ink: "var(--ink)",
81
+ soft: "var(--ink-soft)",
82
+ line: "var(--line)",
83
+ paper: "var(--paper)",
84
+ card: "var(--card)",
85
+ accent: "var(--accent)",
86
+ accentSoft: "var(--accent-soft)",
87
+ warn: "var(--warn)",
88
+ warnSoft: "var(--warn-soft)",
89
+ ok: "var(--ok)",
90
+ okSoft: "var(--ok-soft)",
91
+ stroke: "var(--stroke)",
92
+ radius: "var(--radius)",
93
+ gap: "var(--gap)",
94
+ pad: "var(--pad)",
95
+ fs: "var(--fs)",
96
+ hand: "var(--font-hand)",
97
+ script: "var(--font-script)",
98
+ };
99
+ function toneColors(tone = "default") {
100
+ switch (tone) {
101
+ case "accent":
102
+ return { fg: V.accent, bg: V.accentSoft, bd: V.accent };
103
+ case "warn":
104
+ return { fg: V.warn, bg: V.warnSoft, bd: V.warn };
105
+ case "ok":
106
+ return { fg: V.ok, bg: V.okSoft, bd: V.ok };
107
+ case "muted":
108
+ return { fg: V.soft, bg: "transparent", bd: V.soft };
109
+ default:
110
+ return { fg: V.ink, bg: "transparent", bd: V.ink };
111
+ }
112
+ }
113
+ function toneInk(tone) {
114
+ return toneColors(tone).fg;
115
+ }
116
+ function fontWeight(weight) {
117
+ if (weight === "bold")
118
+ return 700;
119
+ if (weight === "medium")
120
+ return 600;
121
+ return 400;
122
+ }
123
+ export function Screen({ children, pad = 0, sketch, density, theme, skeleton = false, style = {}, }) {
124
+ const cfg = useContext(KitConfigContext);
125
+ const isSkeleton = skeleton || Boolean(cfg.skeleton);
126
+ const wfStyle = cfg.style ?? "sketchy";
127
+ const wfTheme = theme ?? cfg.theme ?? "light";
128
+ void sketch;
129
+ return (_jsx("div", { className: "plan-wf", "data-density": density ?? "regular", "data-theme": wfTheme, "data-skeleton": isSkeleton ? "true" : undefined, "data-style": wfStyle, style: {
130
+ position: "relative",
131
+ width: "100%",
132
+ // `minHeight` (not a fixed `height: 100%`) so the screen fills an
133
+ // auto-height artboard's floor yet grows with its content instead of
134
+ // clipping. The frame shell (`ArtboardFrame`) owns the height policy; a
135
+ // caller can still override via `style.height` for a fixed canvas.
136
+ minHeight: "100%",
137
+ background: V.paper,
138
+ color: V.ink,
139
+ fontFamily: V.hand,
140
+ fontSize: V.fs,
141
+ lineHeight: 1.25,
142
+ display: "flex",
143
+ flexDirection: "column",
144
+ padding: pad,
145
+ boxSizing: "border-box",
146
+ overflow: "hidden",
147
+ ...style,
148
+ }, children: children }));
149
+ }
150
+ export function Hand({ children, size, weight = 400, color = V.ink, script = false, style = {}, }) {
151
+ return (_jsx("span", { style: {
152
+ fontFamily: script ? V.script : V.hand,
153
+ fontSize: size ?? V.fs,
154
+ fontWeight: weight,
155
+ color,
156
+ minWidth: 0,
157
+ overflowWrap: "break-word",
158
+ ...style,
159
+ }, children: children }));
160
+ }
161
+ export function Bar({ w = 80, h, color = V.line, r = 4, style = {}, }) {
162
+ return (_jsx("div", { style: {
163
+ width: w,
164
+ height: h ?? "calc(var(--fs) * 0.72)",
165
+ background: color,
166
+ borderRadius: r,
167
+ flex: "0 0 auto",
168
+ ...style,
169
+ } }));
170
+ }
171
+ export function Lines({ n = 2, gap = 6, widths, color = V.line, style = {}, }) {
172
+ const ws = widths ??
173
+ Array.from({ length: n }, (_, i) => (i === n - 1 ? "55%" : "100%"));
174
+ return (_jsx("div", { style: { display: "flex", flexDirection: "column", gap, ...style }, children: ws.map((w, i) => (_jsx(Bar, { w: typeof w === "number" ? `${w}%` : w, color: color }, i))) }));
175
+ }
176
+ export function Box({ children, pad = V.pad, fill = V.card, dashed = false, style = {}, }) {
177
+ return (_jsx("div", { "data-rough": "rect", style: {
178
+ ["--rough-stroke"]: V.ink,
179
+ border: `${V.stroke} ${dashed ? "dashed" : "solid"} ${V.ink}`,
180
+ borderRadius: V.radius,
181
+ background: fill,
182
+ padding: pad,
183
+ boxSizing: "border-box",
184
+ minWidth: 0,
185
+ ...style,
186
+ }, children: children }));
187
+ }
188
+ export function Check({ done = false, shape = "square", size = 18, }) {
189
+ const r = shape === "circle" ? "50%" : "calc(var(--radius) * 0.5)";
190
+ return (_jsx("div", { "data-rough": shape === "circle" ? "ellipse" : "rect", style: {
191
+ ["--rough-stroke"]: done ? V.accent : V.ink,
192
+ width: size,
193
+ height: size,
194
+ flex: "0 0 auto",
195
+ borderRadius: r,
196
+ border: `${V.stroke} solid ${done ? V.accent : V.ink}`,
197
+ background: done ? V.accent : "transparent",
198
+ display: "flex",
199
+ alignItems: "center",
200
+ justifyContent: "center",
201
+ }, children: done && (_jsx("svg", { width: size * 0.6, height: size * 0.6, viewBox: "0 0 12 12", fill: "none", stroke: "#fff", strokeWidth: "2.2", strokeLinecap: "round", strokeLinejoin: "round", children: _jsx("path", { d: "M2 6.5l2.5 2.5L10 3" }) })) }));
202
+ }
203
+ export function Pill({ children, tone = "default", style = {}, }) {
204
+ const c = toneColors(tone);
205
+ return (_jsx("span", { style: {
206
+ display: "inline-flex",
207
+ alignItems: "center",
208
+ gap: 4,
209
+ border: `${V.stroke} solid ${c.bd}`,
210
+ background: c.bg,
211
+ color: c.fg,
212
+ borderRadius: 999,
213
+ padding: "2px 9px",
214
+ fontSize: "calc(var(--fs) * 0.82)",
215
+ fontFamily: V.hand,
216
+ maxWidth: "100%",
217
+ minWidth: 0,
218
+ whiteSpace: "normal",
219
+ overflowWrap: "anywhere",
220
+ lineHeight: 1.3,
221
+ ...style,
222
+ }, children: children }));
223
+ }
224
+ export function Prio({ level = 2, label }) {
225
+ const fill = level === 1 ? V.warn : level === 2 ? V.soft : "transparent";
226
+ const bd = level === 3 ? V.soft : "transparent";
227
+ return (_jsxs("span", { style: { display: "inline-flex", alignItems: "center", gap: 5 }, children: [_jsx("span", { style: {
228
+ width: 9,
229
+ height: 9,
230
+ borderRadius: "50%",
231
+ background: fill,
232
+ border: `${V.stroke} solid ${bd}`,
233
+ flex: "0 0 auto",
234
+ } }), label && (_jsx(Hand, { size: "calc(var(--fs) * 0.82)", color: V.soft, children: label }))] }));
235
+ }
236
+ export function Btn({ children, solid = false, full = false, size = "md", tone = "default", style = {}, }) {
237
+ const pad = size === "sm" ? "4px 10px" : size === "lg" ? "10px 18px" : "7px 14px";
238
+ const c = toneColors(tone === "default" ? "accent" : tone);
239
+ return (_jsx("div", { "data-rough": "rect", style: {
240
+ ["--rough-stroke"]: solid ? c.bd : V.ink,
241
+ display: full ? "flex" : "inline-flex",
242
+ alignItems: "center",
243
+ justifyContent: "center",
244
+ gap: 6,
245
+ border: `${V.stroke} solid ${solid ? c.bd : V.ink}`,
246
+ background: solid ? c.bd : "transparent",
247
+ color: solid ? "#fff" : V.ink,
248
+ borderRadius: V.radius,
249
+ padding: pad,
250
+ fontFamily: V.hand,
251
+ fontSize: V.fs,
252
+ fontWeight: 700,
253
+ width: full ? "100%" : "auto",
254
+ maxWidth: "100%",
255
+ minWidth: 0,
256
+ boxSizing: "border-box",
257
+ whiteSpace: "normal",
258
+ overflowWrap: "anywhere",
259
+ textAlign: "center",
260
+ ...style,
261
+ }, children: children }));
262
+ }
263
+ export function Chip({ children, active = false, style = {}, }) {
264
+ return (_jsx("span", { style: {
265
+ display: "inline-flex",
266
+ alignItems: "center",
267
+ gap: 5,
268
+ border: `${V.stroke} solid ${active ? V.accent : V.ink}`,
269
+ background: active ? V.accentSoft : "transparent",
270
+ color: active ? V.accent : V.ink,
271
+ borderRadius: 999,
272
+ padding: "4px 12px",
273
+ fontSize: "calc(var(--fs) * 0.88)",
274
+ fontFamily: V.hand,
275
+ fontWeight: active ? 700 : 400,
276
+ maxWidth: "100%",
277
+ minWidth: 0,
278
+ whiteSpace: "normal",
279
+ overflowWrap: "anywhere",
280
+ ...style,
281
+ }, children: children }));
282
+ }
283
+ export function Field({ label, value, placeholder, h, area = false, right, style = {}, }) {
284
+ return (_jsxs("div", { style: { display: "flex", flexDirection: "column", gap: 5, ...style }, children: [label && (_jsx(Hand, { size: "calc(var(--fs) * 0.86)", color: V.soft, weight: 700, children: label })), _jsxs("div", { "data-rough": "rect", style: {
285
+ ["--rough-stroke"]: V.ink,
286
+ border: `${V.stroke} solid ${V.ink}`,
287
+ borderRadius: V.radius,
288
+ background: V.card,
289
+ padding: "calc(var(--pad) * 0.8)",
290
+ minHeight: h ?? (area ? 64 : "auto"),
291
+ display: "flex",
292
+ alignItems: area ? "flex-start" : "center",
293
+ justifyContent: "space-between",
294
+ minWidth: 0,
295
+ gap: 8,
296
+ }, children: [value ? (_jsx(Hand, { style: { minWidth: 0, overflowWrap: "anywhere" }, children: value })) : area ? (_jsx(Lines, { n: 2, widths: ["85%", "60%"] })) : (_jsx(Bar, { w: placeholder ?? 110 })), right] })] }));
297
+ }
298
+ export function StatusBar() {
299
+ return (_jsxs("div", { style: {
300
+ display: "flex",
301
+ alignItems: "center",
302
+ justifyContent: "space-between",
303
+ padding: "9px 18px 2px",
304
+ flex: "0 0 auto",
305
+ }, children: [_jsx(Hand, { size: "calc(var(--fs) * 0.82)", weight: 700, children: "9:41" }), _jsxs("div", { style: { display: "flex", gap: 5, alignItems: "center" }, children: [_jsx(Bar, { w: 16, h: 8, color: V.soft, r: 2 }), _jsx(Bar, { w: 12, h: 8, color: V.soft, r: 2 }), _jsx(Bar, { w: 20, h: 9, color: V.soft, r: 2 })] })] }));
306
+ }
307
+ export function Fab({ icon = "+" }) {
308
+ return (_jsx("div", { "data-rough": "ellipse", style: {
309
+ ["--rough-stroke"]: V.accent,
310
+ position: "absolute",
311
+ right: 18,
312
+ bottom: 22,
313
+ width: 52,
314
+ height: 52,
315
+ borderRadius: "50%",
316
+ border: `${V.stroke} solid ${V.accent}`,
317
+ background: V.accent,
318
+ color: "#fff",
319
+ display: "flex",
320
+ alignItems: "center",
321
+ justifyContent: "center",
322
+ fontFamily: V.hand,
323
+ fontSize: 28,
324
+ fontWeight: 700,
325
+ lineHeight: 1,
326
+ boxShadow: "0 4px 12px rgba(0,0,0,0.16)",
327
+ zIndex: 4,
328
+ }, children: icon }));
329
+ }
330
+ export function BrowserBar({ title = "todo", children, }) {
331
+ return (_jsxs("div", { "data-rough": "line:bottom", style: {
332
+ ["--rough-stroke"]: V.ink,
333
+ display: "flex",
334
+ alignItems: "center",
335
+ gap: 10,
336
+ padding: "9px 14px",
337
+ borderBottom: `${V.stroke} solid ${V.ink}`,
338
+ flex: "0 0 auto",
339
+ background: V.card,
340
+ }, children: [_jsx("div", { style: { display: "flex", gap: 6 }, children: [0, 1, 2].map((i) => (_jsx("span", { "data-rough": "ellipse", style: {
341
+ ["--rough-stroke"]: V.ink,
342
+ width: 11,
343
+ height: 11,
344
+ borderRadius: "50%",
345
+ border: `${V.stroke} solid ${V.ink}`,
346
+ } }, i))) }), _jsxs("div", { style: {
347
+ flex: 1,
348
+ border: `${V.stroke} solid ${V.soft}`,
349
+ borderRadius: 999,
350
+ padding: "3px 12px",
351
+ display: "flex",
352
+ alignItems: "center",
353
+ gap: 6,
354
+ }, children: [_jsx(Bar, { w: 12, h: 10, color: V.soft, r: 3 }), _jsxs(Hand, { size: "calc(var(--fs) * 0.82)", color: V.soft, children: [title, ".app"] })] }), children] }));
355
+ }
356
+ export function SectionLabel({ children, right, tone = "muted", }) {
357
+ return (_jsxs("div", { style: {
358
+ display: "flex",
359
+ alignItems: "baseline",
360
+ justifyContent: "space-between",
361
+ minWidth: 0,
362
+ gap: 8,
363
+ }, children: [_jsx(Hand, { size: "calc(var(--fs) * 0.9)", weight: 700, color: toneInk(tone), style: {
364
+ letterSpacing: 0.3,
365
+ minWidth: 0,
366
+ overflowWrap: "anywhere",
367
+ }, children: children }), right] }));
368
+ }
369
+ export function Avatar({ size = 26 }) {
370
+ return (_jsx("div", { "data-rough": "ellipse", style: {
371
+ ["--rough-stroke"]: V.ink,
372
+ width: size,
373
+ height: size,
374
+ borderRadius: "50%",
375
+ border: `${V.stroke} solid ${V.ink}`,
376
+ background: V.accentSoft,
377
+ flex: "0 0 auto",
378
+ } }));
379
+ }
380
+ export function IconSquare({ size = 18, active = false, }) {
381
+ return (_jsx("div", { "data-rough": "rect", style: {
382
+ ["--rough-stroke"]: active ? V.accent : V.soft,
383
+ width: size,
384
+ height: size,
385
+ flex: "0 0 auto",
386
+ borderRadius: "calc(var(--radius) * 0.5)",
387
+ border: `${V.stroke} solid ${active ? V.accent : V.soft}`,
388
+ display: "flex",
389
+ alignItems: "center",
390
+ justifyContent: "center",
391
+ }, children: _jsx("div", { style: {
392
+ width: "55%",
393
+ height: "55%",
394
+ borderRadius: 2,
395
+ background: active ? V.accent : V.line,
396
+ } }) }));
397
+ }
398
+ export function NavItem({ label, count, active = false, dot = false, tone = "accent", }) {
399
+ const dotColor = toneInk(tone);
400
+ return (_jsxs("div", { style: {
401
+ display: "flex",
402
+ alignItems: "center",
403
+ gap: 9,
404
+ padding: "5px 8px",
405
+ borderRadius: V.radius,
406
+ background: active ? V.accentSoft : "transparent",
407
+ minWidth: 0,
408
+ }, children: [dot ? (_jsx("span", { style: {
409
+ width: 10,
410
+ height: 10,
411
+ borderRadius: "50%",
412
+ border: `${V.stroke} solid ${dotColor}`,
413
+ background: dotColor,
414
+ flex: "0 0 auto",
415
+ } })) : (_jsx(IconSquare, { size: 15, active: active })), _jsx(Hand, { color: active ? V.accent : V.ink, weight: active ? 700 : 400, style: { flex: 1, minWidth: 0 }, children: label }), count != null && (_jsx(Hand, { size: "calc(var(--fs) * 0.82)", color: V.soft, children: count }))] }));
416
+ }
417
+ export function Sidebar({ children, width = 196, style = {}, }) {
418
+ return (_jsx("div", { "data-rough": "line:right", style: {
419
+ ["--rough-stroke"]: V.ink,
420
+ width,
421
+ flex: "0 0 auto",
422
+ borderRight: `${V.stroke} solid ${V.ink}`,
423
+ background: V.card,
424
+ padding: V.pad,
425
+ display: "flex",
426
+ flexDirection: "column",
427
+ gap: V.gap,
428
+ minHeight: 0,
429
+ minWidth: 0,
430
+ alignSelf: "stretch",
431
+ overflow: "hidden",
432
+ ...style,
433
+ }, children: children }));
434
+ }
435
+ export function Main({ children, style = {}, }) {
436
+ return (_jsx("div", { style: {
437
+ flex: 1,
438
+ minWidth: 0,
439
+ minHeight: 0,
440
+ padding: "18px 24px",
441
+ display: "flex",
442
+ flexDirection: "column",
443
+ gap: V.gap,
444
+ overflow: "hidden",
445
+ ...style,
446
+ }, children: children }));
447
+ }
448
+ export function Row({ children, full = false, style = {}, }) {
449
+ return (_jsx("div", { style: {
450
+ display: "flex",
451
+ flexDirection: "row",
452
+ alignItems: "stretch",
453
+ gap: V.gap,
454
+ minWidth: 0,
455
+ minHeight: 0,
456
+ maxWidth: "100%",
457
+ flex: full ? 1 : undefined,
458
+ ...style,
459
+ }, children: children }));
460
+ }
461
+ export function Col({ children, full = false, style = {}, }) {
462
+ return (_jsx("div", { style: {
463
+ display: "flex",
464
+ flexDirection: "column",
465
+ gap: V.gap,
466
+ minWidth: 0,
467
+ minHeight: 0,
468
+ flex: full ? 1 : undefined,
469
+ ...style,
470
+ }, children: children }));
471
+ }
472
+ export function TaskRow({ title, note, due, dueTone = "default", prio, done = false, }) {
473
+ return (_jsxs("div", { style: {
474
+ display: "flex",
475
+ alignItems: "flex-start",
476
+ gap: V.gap,
477
+ padding: "calc(var(--pad) * 0.55) 0",
478
+ minWidth: 0,
479
+ }, children: [_jsx("div", { style: { marginTop: 1 }, children: _jsx(Check, { done: done }) }), _jsxs("div", { style: {
480
+ flex: 1,
481
+ minWidth: 0,
482
+ display: "flex",
483
+ flexDirection: "column",
484
+ gap: 4,
485
+ }, children: [_jsx(Hand, { color: done ? V.soft : V.ink, style: done ? { textDecoration: "line-through" } : undefined, children: title }), note && (_jsx(Hand, { size: "calc(var(--fs) * 0.85)", color: V.soft, children: note }))] }), _jsxs("div", { style: {
486
+ display: "flex",
487
+ alignItems: "center",
488
+ flexWrap: "wrap",
489
+ justifyContent: "flex-end",
490
+ gap: 8,
491
+ flex: "0 0 auto",
492
+ }, children: [due && _jsx(Pill, { tone: dueTone, children: due }), prio ? _jsx(Prio, { level: prio }) : null] })] }));
493
+ }
494
+ export function Card({ children, style = {}, }) {
495
+ return (_jsx(Box, { pad: "calc(var(--pad) * 0.9)", style: {
496
+ display: "flex",
497
+ flexDirection: "column",
498
+ gap: 8,
499
+ background: V.card,
500
+ minWidth: 0,
501
+ maxWidth: "100%",
502
+ ...style,
503
+ }, children: children }));
504
+ }
505
+ export function Column({ title, count, tone = "muted", width = 232, children, }) {
506
+ return (_jsxs("div", { style: {
507
+ width,
508
+ flex: "0 0 auto",
509
+ display: "flex",
510
+ flexDirection: "column",
511
+ gap: V.gap,
512
+ }, children: [_jsxs("div", { style: { display: "flex", alignItems: "center", gap: 8 }, children: [_jsx("span", { style: {
513
+ width: 9,
514
+ height: 9,
515
+ borderRadius: "50%",
516
+ background: toneInk(tone),
517
+ flex: "0 0 auto",
518
+ } }), _jsx(Hand, { weight: 700, style: { whiteSpace: "nowrap" }, children: title }), count != null && (_jsx(Hand, { size: "calc(var(--fs) * 0.82)", color: V.soft, children: count })), _jsx("div", { style: { flex: 1 } }), _jsx(Hand, { color: V.soft, weight: 700, children: "+" })] }), children] }));
519
+ }
520
+ export function Toolbar({ children, style = {}, }) {
521
+ return (_jsx("div", { "data-rough": "line:bottom", style: {
522
+ ["--rough-stroke"]: V.ink,
523
+ display: "flex",
524
+ alignItems: "center",
525
+ justifyContent: "space-between",
526
+ gap: V.gap,
527
+ padding: "12px 22px",
528
+ borderBottom: `${V.stroke} solid ${V.ink}`,
529
+ background: V.card,
530
+ flex: "0 0 auto",
531
+ minWidth: 0,
532
+ flexWrap: "wrap",
533
+ ...style,
534
+ }, children: children }));
535
+ }
536
+ export function Tabs({ items = [], }) {
537
+ return (_jsx("div", { style: { display: "flex", gap: 7, flexWrap: "wrap" }, children: items.map((item, i) => (_jsx(Chip, { active: item.active, children: item.label }, i))) }));
538
+ }
539
+ export function KV({ rows = [] }) {
540
+ return (_jsx("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: rows.map((row, i) => (_jsxs("div", { style: {
541
+ display: "flex",
542
+ alignItems: "baseline",
543
+ justifyContent: "space-between",
544
+ gap: 12,
545
+ }, children: [_jsx(Hand, { size: "calc(var(--fs) * 0.88)", color: V.soft, children: row.k }), _jsx(Hand, { style: { textAlign: "right", minWidth: 0, wordBreak: "break-word" }, children: row.v })] }, i))) }));
546
+ }
547
+ export function SearchBar({ placeholder = "Search", }) {
548
+ return (_jsxs("div", { style: {
549
+ display: "flex",
550
+ alignItems: "center",
551
+ gap: 6,
552
+ border: `${V.stroke} solid ${V.soft}`,
553
+ borderRadius: 999,
554
+ padding: "5px 11px",
555
+ background: V.card,
556
+ }, children: [_jsx(Bar, { w: 11, h: 11, color: V.soft, r: 3 }), _jsx(Hand, { size: "calc(var(--fs) * 0.85)", color: V.soft, children: placeholder })] }));
557
+ }
558
+ export function Divider({ style = {} }) {
559
+ return (_jsx("div", { style: {
560
+ height: V.stroke,
561
+ background: V.line,
562
+ flex: "0 0 auto",
563
+ margin: "3px 0",
564
+ ...style,
565
+ } }));
566
+ }
567
+ export function Title({ text, script = false, size = "calc(var(--fs) * 2)", color = V.ink, }) {
568
+ return (_jsx(Hand, { script: script, size: size, weight: 700, color: color, children: text }));
569
+ }
570
+ export function Text({ value, color, weight, script = false, }) {
571
+ return (_jsx(Hand, { color: toneInk(color), weight: fontWeight(weight), script: script, children: value }));
572
+ }
573
+ const REGISTRY = {
574
+ // --- Frame / structure -------------------------------------------------
575
+ screen: (n) => {
576
+ const kids = n.children ?? [];
577
+ const lead = kids[0]?.el;
578
+ if (lead === "browserBar") {
579
+ return (_jsxs(Screen, { pad: 0, children: [renderNode(kids[0], kids[0].id ?? "browserbar"), renderScreenBodyNodes(kids.slice(1))] }));
580
+ }
581
+ if (lead === "statusBar") {
582
+ return (_jsxs(Screen, { pad: 0, children: [renderNode(kids[0], kids[0].id ?? "statusbar"), _jsx("div", { style: {
583
+ flex: 1,
584
+ minHeight: 0,
585
+ display: "flex",
586
+ flexDirection: "column",
587
+ gap: "var(--gap)",
588
+ padding: "calc(var(--pad) * 1.1)",
589
+ }, children: renderScreenBodyNodes(kids.slice(1)) })] }));
590
+ }
591
+ return (_jsx(Screen, { pad: "calc(var(--pad) * 1.35)", children: renderScreenBodyNodes(kids) }));
592
+ },
593
+ browserBar: (n, children) => (_jsx(BrowserBar, { title: n.title ?? n.text, children: children })),
594
+ statusBar: () => _jsx(StatusBar, {}),
595
+ toolbar: (_n, children) => _jsx(Toolbar, { children: children }),
596
+ row: (n, children) => _jsx(Row, { full: n.full, children: children }),
597
+ col: (n, children) => _jsx(Col, { full: n.full, children: children }),
598
+ sidebar: (_n, children) => _jsx(Sidebar, { children: children }),
599
+ main: (_n, children) => _jsx(Main, { children: children }),
600
+ box: (n, children) => _jsx(Box, { dashed: n.dashed, children: children }),
601
+ card: (_n, children) => _jsx(Card, { children: children }),
602
+ column: (n, children) => (_jsx(Column, { title: n.title ?? n.text, count: n.count, tone: n.tone, children: children })),
603
+ divider: () => _jsx(Divider, {}),
604
+ // --- Text --------------------------------------------------------------
605
+ title: (n) => _jsx(Title, { text: n.text, script: n.script }),
606
+ text: (n) => (_jsx(Text, { value: n.value ?? n.text, color: n.color, weight: n.weight, script: n.script })),
607
+ lines: (n) => _jsx(Lines, { n: n.n, widths: n.widths }),
608
+ section: (n) => (_jsx(SectionLabel, { tone: n.tone, children: n.label ?? n.text })),
609
+ // --- List / task -------------------------------------------------------
610
+ navItem: (n) => (_jsx(NavItem, { label: n.label ?? n.text, count: n.count, active: n.active, dot: n.dot, tone: n.tone })),
611
+ taskRow: (n) => (_jsx(TaskRow, { title: n.title ?? n.text, note: n.note, due: n.due, dueTone: n.dueTone, prio: n.prio, done: n.done })),
612
+ // --- Controls ----------------------------------------------------------
613
+ chips: (n) => _jsx(Tabs, { items: n.items ?? [] }),
614
+ chip: (n) => _jsx(Chip, { active: n.active, children: n.label ?? n.text }),
615
+ pill: (n) => _jsx(Pill, { tone: n.tone, children: n.label ?? n.text }),
616
+ check: (n) => _jsx(Check, { done: n.done, shape: n.shape }),
617
+ field: (n) => (_jsx(Field, { label: n.label, value: n.value, placeholder: n.placeholder, area: n.area })),
618
+ btn: (n) => (_jsx(Btn, { solid: n.solid, full: n.full, tone: n.tone, children: n.label ?? n.text })),
619
+ fab: (n) => _jsx(Fab, { icon: n.icon }),
620
+ searchBar: (n) => _jsx(SearchBar, { placeholder: n.placeholder }),
621
+ // --- Atoms -------------------------------------------------------------
622
+ avatar: () => _jsx(Avatar, {}),
623
+ iconSquare: (n) => _jsx(IconSquare, { active: n.active }),
624
+ kv: (n) => _jsx(KV, { rows: n.rows ?? [] }),
625
+ };
626
+ function renderScreenBodyNode(node, key) {
627
+ const shouldFill = node.full !== false &&
628
+ (node.el === "row" || node.el === "col" || node.el === "main");
629
+ return renderNode(shouldFill ? { ...node, full: true } : node, key);
630
+ }
631
+ function renderScreenBodyNodes(nodes) {
632
+ return nodes.map((node, i) => renderScreenBodyNode(node, node.id ?? `screen-body-${i}`));
633
+ }
634
+ /** Render a single kit-tree node (and its children, recursively). */
635
+ export function renderNode(node, key) {
636
+ const renderer = REGISTRY[node.el];
637
+ const children = node.children?.length ? renderNodes(node.children) : null;
638
+ if (!renderer) {
639
+ return children ? _jsx("div", { children: children }, key) : null;
640
+ }
641
+ const rendered = renderer(node, children);
642
+ return _jsx(KeyedNode, { children: rendered }, key ?? node.id);
643
+ }
644
+ /** Render an array of nodes. */
645
+ export function renderNodes(nodes) {
646
+ return nodes.map((node, i) => renderNode(node, node.id ?? i));
647
+ }
648
+ /** Lightweight keyed wrapper that does not introduce extra DOM. */
649
+ function KeyedNode({ children }) {
650
+ return _jsx(_Fragment, { children: children });
651
+ }
652
+ /** Whether an `el` name has a registered renderer. */
653
+ export function hasRenderer(el) {
654
+ return el in REGISTRY;
655
+ }
656
+ export { REGISTRY as NODE_REGISTRY, V as WFV, toneColors, toneInk, fontWeight };
657
+ /* ========================================================================== */
658
+ /* Rough overlay (ported from kit/rough.tsx) */
659
+ /* ========================================================================== */
660
+ const gen = rough.generator();
661
+ /** The default selector used for HTML mockups: bordered/box-like elements. */
662
+ export const HTML_ROUGH_SELECTOR = "[data-rough],button,input,textarea,select,.wf-card,.wf-box,hr,.wf-frame-target";
663
+ /** Stable per-element seed so a frame doesn't re-wobble on every measure. */
664
+ function seedFrom(...parts) {
665
+ const value = parts.join(":");
666
+ let hash = 2166136261;
667
+ for (let i = 0; i < value.length; i++) {
668
+ hash ^= value.charCodeAt(i);
669
+ hash = Math.imul(hash, 16777619);
670
+ }
671
+ return ((hash >>> 0) % 2147483646) + 1;
672
+ }
673
+ /** Map the 0–100 sketch slider to a rough.js roughness (calm + legible). */
674
+ export function sketchRoughness(sketch) {
675
+ const s = Math.max(0, Math.min(100, Number.isFinite(sketch) ? sketch : 0));
676
+ return Number((0.32 + (s / 100) * 1.15).toFixed(2));
677
+ }
678
+ function sketchBowing(sketch) {
679
+ const s = Math.max(0, Math.min(100, Number.isFinite(sketch) ? sketch : 0));
680
+ return Number((0.4 + (s / 100) * 0.5).toFixed(2));
681
+ }
682
+ function readVar(el, name) {
683
+ return getComputedStyle(el).getPropertyValue(name).trim();
684
+ }
685
+ /** Normalize a CSS color (hex or rgb[a]) to "r,g,b" for equality comparison. */
686
+ function toRgbKey(color) {
687
+ const c = color.trim();
688
+ const hex = c.match(/^#([0-9a-f]{3}|[0-9a-f]{6})$/i);
689
+ if (hex) {
690
+ const h = hex[1];
691
+ const full = h.length === 3
692
+ ? h
693
+ .split("")
694
+ .map((d) => d + d)
695
+ .join("")
696
+ : h;
697
+ const n = parseInt(full, 16);
698
+ return `${(n >> 16) & 255},${(n >> 8) & 255},${n & 255}`;
699
+ }
700
+ const rgb = c.match(/rgba?\(([^)]+)\)/i);
701
+ if (rgb) {
702
+ const [r, g, b] = rgb[1].split(",").map((v) => parseInt(v.trim(), 10));
703
+ return `${r},${g},${b}`;
704
+ }
705
+ return null;
706
+ }
707
+ /** True when two CSS colors resolve to the same RGB (hex vs rgb tolerant). */
708
+ function sameColor(a, b) {
709
+ const ka = toRgbKey(a);
710
+ const kb = toRgbKey(b);
711
+ return ka !== null && ka === kb;
712
+ }
713
+ /** A rounded-rect SVG path (so the frame stroke follows the artboard radius). */
714
+ function roundedRectPath(x, y, w, h, r) {
715
+ const rad = Math.max(0, Math.min(r, w / 2, h / 2));
716
+ return [
717
+ `M${x + rad},${y}`,
718
+ `H${x + w - rad}`,
719
+ `A${rad},${rad} 0 0 1 ${x + w},${y + rad}`,
720
+ `V${y + h - rad}`,
721
+ `A${rad},${rad} 0 0 1 ${x + w - rad},${y + h}`,
722
+ `H${x + rad}`,
723
+ `A${rad},${rad} 0 0 1 ${x},${y + h - rad}`,
724
+ `V${y + rad}`,
725
+ `A${rad},${rad} 0 0 1 ${x + rad},${y}`,
726
+ "Z",
727
+ ].join(" ");
728
+ }
729
+ function elementStroke(node, fallback) {
730
+ const explicit = readVar(node, "--rough-stroke");
731
+ if (explicit)
732
+ return explicit;
733
+ const cs = getComputedStyle(node);
734
+ for (const side of [
735
+ "borderTopColor",
736
+ "borderLeftColor",
737
+ "borderBottomColor",
738
+ "borderRightColor",
739
+ ]) {
740
+ const width = parseFloat(cs.getPropertyValue(side.replace("Color", "Width")));
741
+ const color = cs[side];
742
+ if (width > 0 && color && color !== "rgba(0, 0, 0, 0)")
743
+ return color;
744
+ }
745
+ return fallback;
746
+ }
747
+ function build(scope, opts) {
748
+ const base = scope.getBoundingClientRect();
749
+ const layoutW = scope.offsetWidth;
750
+ const layoutH = scope.offsetHeight;
751
+ if (!layoutW || !layoutH)
752
+ return { paths: [], w: 0, h: 0 };
753
+ const zoom = base.width / layoutW || 1;
754
+ const themed = (scope.matches(".plan-wf, .plan-html-frame, .plan-diagram-frame")
755
+ ? scope
756
+ : scope.querySelector(".plan-wf, .plan-html-frame, .plan-diagram-frame")) ?? scope;
757
+ const ink = readVar(themed, "--ink") || readVar(themed, "--wf-ink") || "#34322e";
758
+ const sketch = readVar(themed, "--wf-sketch") || ink;
759
+ const line = readVar(themed, "--wf-line") || readVar(themed, "--line") || "";
760
+ const paths = [];
761
+ let index = 0;
762
+ const push = (drawable, stroke, sw) => {
763
+ for (const p of gen.toPaths(drawable)) {
764
+ paths.push({
765
+ d: p.d,
766
+ stroke: p.stroke && p.stroke !== "none" ? p.stroke : stroke,
767
+ strokeWidth: p.strokeWidth || sw,
768
+ });
769
+ }
770
+ };
771
+ const makeOpts = (stroke, sw, seed) => ({
772
+ seed,
773
+ roughness: opts.roughness,
774
+ bowing: opts.bowing,
775
+ stroke,
776
+ strokeWidth: sw,
777
+ preserveVertices: true,
778
+ });
779
+ if (opts.drawFrame) {
780
+ const sw = 2;
781
+ push(gen.path(roundedRectPath(2, 2, layoutW - 4, layoutH - 4, opts.frameRadius), {
782
+ ...makeOpts(sketch, sw, seedFrom("frame", layoutW, layoutH)),
783
+ roughness: opts.roughness + 0.35,
784
+ bowing: opts.bowing + 0.18,
785
+ }), sketch, sw);
786
+ }
787
+ scope.querySelectorAll(opts.selector).forEach((node) => {
788
+ const r = node.getBoundingClientRect();
789
+ const x = (r.left - base.left) / zoom;
790
+ const y = (r.top - base.top) / zoom;
791
+ const w = r.width / zoom;
792
+ const h = r.height / zoom;
793
+ if (w < 2 || h < 2)
794
+ return;
795
+ const kind = node.getAttribute("data-rough") || "rect";
796
+ const rawStroke = elementStroke(node, sketch);
797
+ const stroke = sameColor(rawStroke, ink) || (line !== "" && sameColor(rawStroke, line))
798
+ ? sketch
799
+ : rawStroke;
800
+ const sw = Number(readVar(node, "--rough-w")) || 1.4;
801
+ const seed = seedFrom(kind, Math.round(x), Math.round(y), Math.round(w), Math.round(h), index++);
802
+ const o = makeOpts(stroke, sw, seed);
803
+ let drawable;
804
+ if (kind === "ellipse") {
805
+ drawable = gen.ellipse(x + w / 2, y + h / 2, w, h, o);
806
+ }
807
+ else if (kind === "line:right") {
808
+ drawable = gen.line(x + w, y, x + w, y + h, o);
809
+ }
810
+ else if (kind === "line:bottom") {
811
+ drawable = gen.line(x, y + h, x + w, y + h, o);
812
+ }
813
+ else if (kind === "line:top" || node.tagName === "HR") {
814
+ drawable = gen.line(x, y + h / 2, x + w, y + h / 2, o);
815
+ }
816
+ else {
817
+ const cr = parseFloat(getComputedStyle(node).borderTopLeftRadius) || 0;
818
+ const radius = Math.min(cr / zoom, w / 2, h / 2);
819
+ drawable =
820
+ radius > 1
821
+ ? gen.path(roundedRectPath(x + 1, y + 1, w - 2, h - 2, radius), o)
822
+ : gen.rectangle(x + 1, y + 1, w - 2, h - 2, o);
823
+ }
824
+ push(drawable, stroke, sw);
825
+ });
826
+ return { paths, w: layoutW, h: layoutH };
827
+ }
828
+ /**
829
+ * Renders the rough overlay for a frame. `scopeRef` points at the frame root.
830
+ * When `enabled` is false (skeleton / clean register) it renders nothing and the
831
+ * crisp CSS borders stay visible.
832
+ */
833
+ export function RoughOverlay({ scopeRef, sketch = 52, enabled = true, drawFrame = true, frameRadius = 14, selector = "[data-rough]", }) {
834
+ const [state, setState] = useState({ paths: [], w: 0, h: 0 });
835
+ const rafRef = useRef(0);
836
+ useEffect(() => {
837
+ const el = scopeRef.current;
838
+ if (!el || !enabled) {
839
+ el?.removeAttribute("data-rough-ready");
840
+ el?.querySelector(".plan-wf, .plan-html-frame, .plan-diagram-frame")?.removeAttribute("data-rough-ready");
841
+ setState({ paths: [], w: 0, h: 0 });
842
+ return;
843
+ }
844
+ const roughness = sketchRoughness(sketch);
845
+ const bowing = sketchBowing(sketch);
846
+ const measure = () => {
847
+ clearTimeout(rafRef.current);
848
+ rafRef.current = window.setTimeout(() => {
849
+ const next = build(el, {
850
+ roughness,
851
+ bowing,
852
+ frameRadius,
853
+ drawFrame,
854
+ selector,
855
+ });
856
+ if (next.w && next.h) {
857
+ el.setAttribute("data-rough-ready", "true");
858
+ (el.querySelector(".plan-wf, .plan-html-frame, .plan-diagram-frame") ?? el).setAttribute("data-rough-ready", "true");
859
+ setState(next);
860
+ }
861
+ }, 0);
862
+ };
863
+ measure();
864
+ const ro = new ResizeObserver(measure);
865
+ ro.observe(el);
866
+ el.querySelectorAll(selector).forEach((node) => ro.observe(node));
867
+ const mo = new MutationObserver((mutations) => {
868
+ if (mutations.every(isRoughOverlayMutation))
869
+ return;
870
+ measure();
871
+ });
872
+ mo.observe(el, {
873
+ attributes: true,
874
+ childList: true,
875
+ characterData: true,
876
+ subtree: true,
877
+ });
878
+ el.addEventListener("plan-prototype-runtime:rendered", measure);
879
+ let cancelled = false;
880
+ if (typeof document !== "undefined" && "fonts" in document) {
881
+ void document.fonts.ready.then(() => {
882
+ if (!cancelled)
883
+ measure();
884
+ });
885
+ }
886
+ return () => {
887
+ cancelled = true;
888
+ ro.disconnect();
889
+ mo.disconnect();
890
+ el.removeEventListener("plan-prototype-runtime:rendered", measure);
891
+ clearTimeout(rafRef.current);
892
+ el.removeAttribute("data-rough-ready");
893
+ el.querySelector(".plan-wf, .plan-html-frame, .plan-diagram-frame")?.removeAttribute("data-rough-ready");
894
+ };
895
+ }, [scopeRef, sketch, enabled, drawFrame, frameRadius, selector]);
896
+ if (!enabled || !state.paths.length)
897
+ return null;
898
+ return (_jsx("svg", { "aria-hidden": true, className: "plan-rough-overlay", width: "100%", height: "100%", viewBox: `0 0 ${state.w} ${state.h}`, preserveAspectRatio: "none", style: {
899
+ position: "absolute",
900
+ inset: 0,
901
+ pointerEvents: "none",
902
+ overflow: "hidden",
903
+ zIndex: 3,
904
+ }, children: state.paths.map((p, i) => (_jsx("path", { d: p.d, fill: "none", stroke: p.stroke, strokeWidth: p.strokeWidth, strokeLinecap: "round", strokeLinejoin: "round" }, i))) }));
905
+ }
906
+ function isRoughOverlayMutation(mutation) {
907
+ if (nodeIsRoughOverlay(mutation.target))
908
+ return true;
909
+ const changedNodes = [
910
+ ...Array.from(mutation.addedNodes),
911
+ ...Array.from(mutation.removedNodes),
912
+ ];
913
+ return changedNodes.length > 0 && changedNodes.every(nodeIsRoughOverlay);
914
+ }
915
+ function nodeIsRoughOverlay(node) {
916
+ const element = node instanceof Element ? node : node.parentElement;
917
+ return Boolean(element?.classList.contains("plan-rough-overlay") ||
918
+ element?.closest(".plan-rough-overlay"));
919
+ }
920
+ //# sourceMappingURL=wireframe-kit.js.map