sketchmark 2.0.0 → 2.1.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 (132) hide show
  1. package/ANIMATABLE_MATRIX.md +177 -0
  2. package/KERNEL_SPEC.md +412 -0
  3. package/PACKS.md +81 -0
  4. package/PRESETS.md +182 -0
  5. package/README.md +274 -188
  6. package/bin/editor-ui.cjs +2285 -0
  7. package/bin/preview-ui.cjs +74 -0
  8. package/bin/sketchmark.cjs +648 -2008
  9. package/dist/src/animatable.d.ts +21 -0
  10. package/dist/src/animatable.js +439 -0
  11. package/dist/src/builders/index.d.ts +1 -11
  12. package/dist/src/builders/index.js +1 -19
  13. package/dist/src/diagnostics.js +1 -64
  14. package/dist/src/edit.d.ts +27 -0
  15. package/dist/src/edit.js +162 -0
  16. package/dist/src/index.d.ts +4 -13
  17. package/dist/src/index.js +4 -13
  18. package/dist/src/keyframes.d.ts +48 -0
  19. package/dist/src/keyframes.js +182 -0
  20. package/dist/src/motion.d.ts +4 -0
  21. package/dist/src/motion.js +262 -0
  22. package/dist/src/normalize.js +120 -151
  23. package/dist/src/presets/characters.d.ts +15 -0
  24. package/dist/src/presets/characters.js +113 -0
  25. package/dist/src/presets/compose.d.ts +5 -0
  26. package/dist/src/presets/compose.js +80 -0
  27. package/dist/src/presets/effects.d.ts +40 -0
  28. package/dist/src/presets/effects.js +79 -0
  29. package/dist/src/presets/helpers.d.ts +33 -0
  30. package/dist/src/presets/helpers.js +165 -0
  31. package/dist/src/presets/index.d.ts +9 -0
  32. package/dist/src/presets/index.js +48 -0
  33. package/dist/src/presets/motions.d.ts +33 -0
  34. package/dist/src/presets/motions.js +75 -0
  35. package/dist/src/presets/scenes.d.ts +35 -0
  36. package/dist/src/presets/scenes.js +134 -0
  37. package/dist/src/presets/shapes.d.ts +71 -0
  38. package/dist/src/presets/shapes.js +96 -0
  39. package/dist/src/presets/transitions.d.ts +29 -0
  40. package/dist/src/presets/transitions.js +113 -0
  41. package/dist/src/presets/types.d.ts +34 -0
  42. package/dist/src/presets/types.js +2 -0
  43. package/dist/src/render/html.js +1 -4
  44. package/dist/src/render/svg.d.ts +2 -2
  45. package/dist/src/render/svg.js +86 -82
  46. package/dist/src/render/three-html.js +67 -113
  47. package/dist/src/scenes.js +1 -0
  48. package/dist/src/schema.js +218 -280
  49. package/dist/src/shapes/builtins.js +11 -47
  50. package/dist/src/shapes/common.js +12 -11
  51. package/dist/src/shapes/registry.d.ts +0 -1
  52. package/dist/src/shapes/registry.js +0 -4
  53. package/dist/src/shapes/types.d.ts +1 -3
  54. package/dist/src/types.d.ts +57 -288
  55. package/dist/src/utils.d.ts +2 -11
  56. package/dist/src/utils.js +13 -70
  57. package/dist/src/validate.js +321 -275
  58. package/dist/tests/run.js +576 -510
  59. package/examples/1730642890464.jpg +0 -0
  60. package/examples/app-screen.svg +1 -0
  61. package/examples/app-screen.visual.json +503 -0
  62. package/examples/dashboard-table.svg +1 -0
  63. package/examples/dashboard-table.visual.json +708 -0
  64. package/examples/dev-docs.svg +1 -0
  65. package/examples/dev-docs.visual.json +248 -0
  66. package/examples/explainer.mp4 +0 -0
  67. package/examples/explainer.visual.json +1713 -0
  68. package/examples/group-origin-effects-lab-check.svg +1 -0
  69. package/examples/group-origin-effects-lab.visual.json +1880 -0
  70. package/examples/image-clip-radius.visual.json +271 -0
  71. package/examples/make-app-screen.cjs +368 -0
  72. package/examples/make-dashboard-table.cjs +277 -0
  73. package/examples/make-dev-docs.cjs +233 -0
  74. package/examples/make-explainer.cjs +438 -0
  75. package/examples/make-group-origin-effects-lab.cjs +370 -0
  76. package/examples/make-image-clip-radius.cjs +169 -0
  77. package/examples/make-modal-dialog.cjs +355 -0
  78. package/examples/make-origin-effects-lab.cjs +311 -0
  79. package/examples/make-preset-character-motion.cjs +32 -0
  80. package/examples/make-presets-demo.cjs +30 -0
  81. package/examples/make-pricing.cjs +286 -0
  82. package/examples/make-product-demo.cjs +468 -0
  83. package/examples/make-product-hero.cjs +223 -0
  84. package/examples/make-release-notes.cjs +333 -0
  85. package/examples/make-settings-panel.cjs +435 -0
  86. package/examples/make-split-preview.cjs +248 -0
  87. package/examples/make-storyboard.cjs +215 -0
  88. package/examples/make-transcript.cjs +234 -0
  89. package/examples/make-typography-test.cjs +397 -0
  90. package/examples/make-ui-demo-explainer.cjs +1094 -0
  91. package/examples/make-ui-flow.cjs +762 -0
  92. package/examples/make-walkthrough.cjs +815 -0
  93. package/examples/modal-dialog.svg +1 -0
  94. package/examples/modal-dialog.visual.json +239 -0
  95. package/examples/origin-effects-lab-check.svg +1 -0
  96. package/examples/origin-effects-lab.visual.json +1412 -0
  97. package/examples/preset-character-motion.visual.json +949 -0
  98. package/examples/presets-demo.visual.json +787 -0
  99. package/examples/pricing.svg +1 -0
  100. package/examples/pricing.visual.json +652 -0
  101. package/examples/product-demo.mp4 +0 -0
  102. package/examples/product-demo.visual.json +866 -0
  103. package/examples/product-hero.svg +1 -0
  104. package/examples/product-hero.visual.json +242 -0
  105. package/examples/release-notes.svg +1 -0
  106. package/examples/release-notes.visual.json +467 -0
  107. package/examples/settings-panel.svg +1 -0
  108. package/examples/settings-panel.visual.json +501 -0
  109. package/examples/split-preview.svg +1 -0
  110. package/examples/split-preview.visual.json +124 -0
  111. package/examples/storyboard.svg +1 -0
  112. package/examples/storyboard.visual.json +312 -0
  113. package/examples/transcript.svg +1 -0
  114. package/examples/transcript.visual.json +407 -0
  115. package/examples/typography-indent-check.svg +1 -0
  116. package/examples/typography-lineheight-0.svg +1 -0
  117. package/examples/typography-lineheight-2.svg +1 -0
  118. package/examples/typography-test-check.svg +1 -0
  119. package/examples/typography-test.svg +1 -0
  120. package/examples/typography-test.visual.json +757 -0
  121. package/examples/ui-demo-explainer-billing.svg +1 -0
  122. package/examples/ui-demo-explainer-check.svg +1 -0
  123. package/examples/ui-demo-explainer-save.svg +1 -0
  124. package/examples/ui-demo-explainer-toggle.svg +1 -0
  125. package/examples/ui-demo-explainer.mp4 +0 -0
  126. package/examples/ui-demo-explainer.visual.json +2597 -0
  127. package/examples/ui-flow.mp4 +0 -0
  128. package/examples/ui-flow.visual.json +1211 -0
  129. package/examples/walkthrough.mp4 +0 -0
  130. package/examples/walkthrough.visual.json +1372 -0
  131. package/package.json +52 -52
  132. package/schema/visual.schema.json +1086 -930
@@ -0,0 +1,30 @@
1
+ const fs = require("node:fs");
2
+ const path = require("node:path");
3
+
4
+ const { applyPresetFragments, effects, motions, scenes, shapes, transitions } = require("../dist/src/presets");
5
+
6
+ const outputPath = path.join(__dirname, "presets-demo.visual.json");
7
+
8
+ const doc = {
9
+ version: 1,
10
+ canvas: { width: 960, height: 540, background: "#f8fafc", duration: 3, fps: 30 },
11
+ elements: []
12
+ };
13
+
14
+ const visual = applyPresetFragments(doc, [
15
+ scenes.gridBackground({ id: "bg.grid", x: 0, y: 0, width: 960, height: 540, step: 40 }),
16
+ scenes.titleCard({ id: "hero.card", x: 80, y: 56, width: 360, height: 180, title: "Presets", subtitle: "compile to kernel" }),
17
+ shapes.roundedRect({ id: "cta.panel", x: 560, y: 78, width: 260, height: 96, radius: 18, fill: "#ffffff", stroke: "#2563eb", strokeWidth: 3 }),
18
+ shapes.star({ id: "hero.star", cx: 690, cy: 280, outerRadius: 54, fill: "#fde68a", stroke: "#92400e", strokeWidth: 3 }),
19
+ shapes.arrow({ id: "flow.arrow", from: [455, 150], to: [555, 126], stroke: "#0f172a", strokeWidth: 4 }),
20
+ shapes.speechBubble({ id: "note.bubble", x: 520, y: 350, width: 300, height: 92, text: "No preset fields in JSON", fill: "#ffffff", stroke: "#94a3b8" }),
21
+ effects.dropShadow({ id: "hero.card", dy: 12, blur: 24, opacity: 0.2 }),
22
+ effects.glow({ id: "hero.star", color: "#f59e0b", blur: 18, opacity: 0.4 }),
23
+ motions.riseIn({ id: "hero.card", from: [80, 92], to: [80, 56], start: 0, duration: 0.55 }),
24
+ motions.fadeIn({ id: "cta.panel", start: 0.25, duration: 0.4 }),
25
+ motions.pulse({ id: "hero.star", start: 0.8, duration: 1.1, amount: 0.12 }),
26
+ transitions.irisIn({ id: "note.bubble", x: 520, y: 350, width: 300, height: 92, start: 0.45, duration: 0.7 })
27
+ ]);
28
+
29
+ fs.writeFileSync(outputPath, JSON.stringify(visual, null, 2));
30
+ console.log(`Wrote ${outputPath}`);
@@ -0,0 +1,286 @@
1
+ const fs = require("fs");
2
+ const path = require("path");
3
+
4
+ const width = 1280;
5
+ const height = 820;
6
+ const bg = "#f9fafb";
7
+ const font = "Inter, system-ui, sans-serif";
8
+
9
+ const colors = {
10
+ text: "#111827",
11
+ muted: "#6b7280",
12
+ border: "#e5e7eb",
13
+ accent: "#2563eb",
14
+ accentLight: "#eff6ff",
15
+ white: "#ffffff",
16
+ pillBg: "#2563eb",
17
+ pillText: "#ffffff",
18
+ pillOutlineBg: "#ffffff",
19
+ pillOutlineText: "#2563eb",
20
+ pillOutlineBorder: "#2563eb"
21
+ };
22
+
23
+ const colW = 340;
24
+ const colGap = 32;
25
+ const totalW = colW * 3 + colGap * 2;
26
+ const startX = (width - totalW) / 2;
27
+
28
+ const plans = [
29
+ {
30
+ id: "starter",
31
+ name: "Starter",
32
+ price: "$0",
33
+ period: "/month",
34
+ pill: null,
35
+ features: [
36
+ "Up to 3 projects",
37
+ "Basic analytics",
38
+ "Community support",
39
+ "1 GB storage",
40
+ "Single user"
41
+ ]
42
+ },
43
+ {
44
+ id: "pro",
45
+ name: "Pro",
46
+ price: "$29",
47
+ period: "/month",
48
+ pill: { label: "Most popular", filled: true },
49
+ features: [
50
+ "Unlimited projects",
51
+ "Advanced analytics",
52
+ "Priority email support",
53
+ "50 GB storage",
54
+ "Up to 10 team members",
55
+ "Custom integrations"
56
+ ]
57
+ },
58
+ {
59
+ id: "enterprise",
60
+ name: "Enterprise",
61
+ price: "Custom",
62
+ period: "",
63
+ pill: { label: "Contact sales", filled: false },
64
+ features: [
65
+ "Everything in Pro",
66
+ "Dedicated account manager",
67
+ "99.99% uptime SLA",
68
+ "Unlimited storage",
69
+ "SSO & SAML",
70
+ "On-premise deployment",
71
+ "Custom contracts"
72
+ ]
73
+ }
74
+ ];
75
+
76
+ const elements = [];
77
+
78
+ // Page title
79
+ elements.push({
80
+ id: "page-title",
81
+ type: "text",
82
+ x: width / 2,
83
+ y: 48,
84
+ text: "Choose Your Plan",
85
+ align: "center",
86
+ valign: "top",
87
+ fontSize: 32,
88
+ fontFamily: font,
89
+ weight: 700,
90
+ fill: colors.text
91
+ });
92
+
93
+ elements.push({
94
+ id: "page-subtitle",
95
+ type: "text",
96
+ x: width / 2,
97
+ y: 92,
98
+ text: "Simple, transparent pricing that grows with you.",
99
+ align: "center",
100
+ valign: "top",
101
+ fontSize: 16,
102
+ fontFamily: font,
103
+ weight: 400,
104
+ fill: colors.muted
105
+ });
106
+
107
+ const cardTop = 148;
108
+
109
+ plans.forEach((plan, col) => {
110
+ const cx = startX + col * (colW + colGap);
111
+ const centerX = cx + colW / 2;
112
+ const isPro = plan.id === "pro";
113
+ const cardH = 620;
114
+ const r = 12;
115
+
116
+ // Card background
117
+ elements.push({
118
+ id: `${plan.id}-card`,
119
+ type: "path",
120
+ d: roundedRect(cx, cardTop, colW, cardH, r),
121
+ fill: colors.white,
122
+ stroke: isPro ? colors.accent : colors.border,
123
+ strokeWidth: isPro ? 2 : 1,
124
+ effects: isPro ? { shadow: { dx: 0, dy: 4, blur: 24, color: "#2563eb", opacity: 0.1 } } : undefined
125
+ });
126
+
127
+ let y = cardTop + 32;
128
+
129
+ // Pill (if any)
130
+ if (plan.pill) {
131
+ const pillW = plan.pill.label.length * 8 + 24;
132
+ const pillH = 26;
133
+ const pillX = centerX - pillW / 2;
134
+ const pillR = 13;
135
+
136
+ elements.push({
137
+ id: `${plan.id}-pill-bg`,
138
+ type: "path",
139
+ d: roundedRect(pillX, y, pillW, pillH, pillR),
140
+ fill: plan.pill.filled ? colors.pillBg : colors.pillOutlineBg,
141
+ stroke: plan.pill.filled ? "none" : colors.pillOutlineBorder,
142
+ strokeWidth: plan.pill.filled ? 0 : 1.5
143
+ });
144
+
145
+ elements.push({
146
+ id: `${plan.id}-pill-text`,
147
+ type: "text",
148
+ x: centerX,
149
+ y: y + pillH / 2,
150
+ text: plan.pill.label,
151
+ align: "center",
152
+ valign: "middle",
153
+ fontSize: 12,
154
+ fontFamily: font,
155
+ weight: 600,
156
+ fill: plan.pill.filled ? colors.pillText : colors.pillOutlineText
157
+ });
158
+
159
+ y += pillH + 20;
160
+ } else {
161
+ y += 46;
162
+ }
163
+
164
+ // Plan name (centered)
165
+ elements.push({
166
+ id: `${plan.id}-name`,
167
+ type: "text",
168
+ x: centerX,
169
+ y: y,
170
+ text: plan.name,
171
+ align: "center",
172
+ valign: "top",
173
+ fontSize: 22,
174
+ fontFamily: font,
175
+ weight: 600,
176
+ fill: colors.text
177
+ });
178
+ y += 40;
179
+
180
+ // Price (centered)
181
+ elements.push({
182
+ id: `${plan.id}-price`,
183
+ type: "text",
184
+ x: centerX,
185
+ y: y,
186
+ text: plan.price,
187
+ align: "center",
188
+ valign: "top",
189
+ fontSize: 42,
190
+ fontFamily: font,
191
+ weight: 700,
192
+ fill: colors.text
193
+ });
194
+ y += 56;
195
+
196
+ // Period (centered)
197
+ if (plan.period) {
198
+ elements.push({
199
+ id: `${plan.id}-period`,
200
+ type: "text",
201
+ x: centerX,
202
+ y: y,
203
+ text: plan.period,
204
+ align: "center",
205
+ valign: "top",
206
+ fontSize: 14,
207
+ fontFamily: font,
208
+ weight: 400,
209
+ fill: colors.muted
210
+ });
211
+ }
212
+ y += 32;
213
+
214
+ // Divider
215
+ elements.push({
216
+ id: `${plan.id}-divider`,
217
+ type: "path",
218
+ d: `M ${cx + 24} ${y} L ${cx + colW - 24} ${y}`,
219
+ stroke: colors.border,
220
+ strokeWidth: 1,
221
+ fill: "none"
222
+ });
223
+ y += 24;
224
+
225
+ // Feature list (left-aligned)
226
+ const listX = cx + 32;
227
+ plan.features.forEach((feat, i) => {
228
+ const fy = y + i * 32;
229
+
230
+ // Checkmark
231
+ elements.push({
232
+ id: `${plan.id}-check-${i}`,
233
+ type: "path",
234
+ d: `M ${listX} ${fy + 7} L ${listX + 5} ${fy + 12} L ${listX + 12} ${fy + 3}`,
235
+ stroke: colors.accent,
236
+ strokeWidth: 2,
237
+ strokeCap: "round",
238
+ strokeJoin: "round",
239
+ fill: "none"
240
+ });
241
+
242
+ elements.push({
243
+ id: `${plan.id}-feat-${i}`,
244
+ type: "text",
245
+ x: listX + 22,
246
+ y: fy,
247
+ text: feat,
248
+ align: "left",
249
+ valign: "top",
250
+ fontSize: 14,
251
+ fontFamily: font,
252
+ weight: 400,
253
+ fill: colors.text
254
+ });
255
+ });
256
+ });
257
+
258
+ function roundedRect(x, y, w, h, r) {
259
+ return [
260
+ `M ${x + r} ${y}`,
261
+ `L ${x + w - r} ${y}`,
262
+ `Q ${x + w} ${y} ${x + w} ${y + r}`,
263
+ `L ${x + w} ${y + h - r}`,
264
+ `Q ${x + w} ${y + h} ${x + w - r} ${y + h}`,
265
+ `L ${x + r} ${y + h}`,
266
+ `Q ${x} ${y + h} ${x} ${y + h - r}`,
267
+ `L ${x} ${y + r}`,
268
+ `Q ${x} ${y} ${x + r} ${y}`,
269
+ "Z"
270
+ ].join(" ");
271
+ }
272
+
273
+ const doc = {
274
+ version: 1,
275
+ canvas: { width, height, background: bg },
276
+ elements: elements.map(el => {
277
+ const cleaned = { ...el };
278
+ if (cleaned.effects === undefined) delete cleaned.effects;
279
+ if (cleaned.strokeWidth === 0) delete cleaned.strokeWidth;
280
+ return cleaned;
281
+ })
282
+ };
283
+
284
+ const outPath = path.join(__dirname, "pricing.visual.json");
285
+ fs.writeFileSync(outPath, JSON.stringify(doc, null, 2));
286
+ console.log("Written:", outPath);