sketchmark 2.1.0 → 2.1.1

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 (77) hide show
  1. package/package.json +1 -7
  2. package/ANIMATABLE_MATRIX.md +0 -177
  3. package/KERNEL_SPEC.md +0 -412
  4. package/PACKS.md +0 -81
  5. package/PRESETS.md +0 -182
  6. package/examples/1730642890464.jpg +0 -0
  7. package/examples/app-screen.svg +0 -1
  8. package/examples/app-screen.visual.json +0 -503
  9. package/examples/dashboard-table.svg +0 -1
  10. package/examples/dashboard-table.visual.json +0 -708
  11. package/examples/dev-docs.svg +0 -1
  12. package/examples/dev-docs.visual.json +0 -248
  13. package/examples/explainer.mp4 +0 -0
  14. package/examples/explainer.visual.json +0 -1713
  15. package/examples/group-origin-effects-lab-check.svg +0 -1
  16. package/examples/group-origin-effects-lab.visual.json +0 -1880
  17. package/examples/image-clip-radius.visual.json +0 -271
  18. package/examples/make-app-screen.cjs +0 -368
  19. package/examples/make-dashboard-table.cjs +0 -277
  20. package/examples/make-dev-docs.cjs +0 -233
  21. package/examples/make-explainer.cjs +0 -438
  22. package/examples/make-group-origin-effects-lab.cjs +0 -370
  23. package/examples/make-image-clip-radius.cjs +0 -169
  24. package/examples/make-modal-dialog.cjs +0 -355
  25. package/examples/make-origin-effects-lab.cjs +0 -311
  26. package/examples/make-preset-character-motion.cjs +0 -32
  27. package/examples/make-presets-demo.cjs +0 -30
  28. package/examples/make-pricing.cjs +0 -286
  29. package/examples/make-product-demo.cjs +0 -468
  30. package/examples/make-product-hero.cjs +0 -223
  31. package/examples/make-release-notes.cjs +0 -333
  32. package/examples/make-settings-panel.cjs +0 -435
  33. package/examples/make-split-preview.cjs +0 -248
  34. package/examples/make-storyboard.cjs +0 -215
  35. package/examples/make-transcript.cjs +0 -234
  36. package/examples/make-typography-test.cjs +0 -397
  37. package/examples/make-ui-demo-explainer.cjs +0 -1094
  38. package/examples/make-ui-flow.cjs +0 -762
  39. package/examples/make-walkthrough.cjs +0 -815
  40. package/examples/modal-dialog.svg +0 -1
  41. package/examples/modal-dialog.visual.json +0 -239
  42. package/examples/origin-effects-lab-check.svg +0 -1
  43. package/examples/origin-effects-lab.visual.json +0 -1412
  44. package/examples/preset-character-motion.visual.json +0 -949
  45. package/examples/presets-demo.visual.json +0 -787
  46. package/examples/pricing.svg +0 -1
  47. package/examples/pricing.visual.json +0 -652
  48. package/examples/product-demo.mp4 +0 -0
  49. package/examples/product-demo.visual.json +0 -866
  50. package/examples/product-hero.svg +0 -1
  51. package/examples/product-hero.visual.json +0 -242
  52. package/examples/release-notes.svg +0 -1
  53. package/examples/release-notes.visual.json +0 -467
  54. package/examples/settings-panel.svg +0 -1
  55. package/examples/settings-panel.visual.json +0 -501
  56. package/examples/split-preview.svg +0 -1
  57. package/examples/split-preview.visual.json +0 -124
  58. package/examples/storyboard.svg +0 -1
  59. package/examples/storyboard.visual.json +0 -312
  60. package/examples/transcript.svg +0 -1
  61. package/examples/transcript.visual.json +0 -407
  62. package/examples/typography-indent-check.svg +0 -1
  63. package/examples/typography-lineheight-0.svg +0 -1
  64. package/examples/typography-lineheight-2.svg +0 -1
  65. package/examples/typography-test-check.svg +0 -1
  66. package/examples/typography-test.svg +0 -1
  67. package/examples/typography-test.visual.json +0 -757
  68. package/examples/ui-demo-explainer-billing.svg +0 -1
  69. package/examples/ui-demo-explainer-check.svg +0 -1
  70. package/examples/ui-demo-explainer-save.svg +0 -1
  71. package/examples/ui-demo-explainer-toggle.svg +0 -1
  72. package/examples/ui-demo-explainer.mp4 +0 -0
  73. package/examples/ui-demo-explainer.visual.json +0 -2597
  74. package/examples/ui-flow.mp4 +0 -0
  75. package/examples/ui-flow.visual.json +0 -1211
  76. package/examples/walkthrough.mp4 +0 -0
  77. package/examples/walkthrough.visual.json +0 -1372
@@ -1,370 +0,0 @@
1
- const fs = require("node:fs");
2
- const path = require("node:path");
3
-
4
- const width = 1280;
5
- const height = 760;
6
- const duration = 6;
7
- const fps = 30;
8
- const bg = "#07111f";
9
- const font = "Roboto, Arial, sans-serif";
10
-
11
- const colors = {
12
- panel: "#0d1a2e",
13
- panelStroke: "#193252",
14
- title: "#f8fafc",
15
- body: "#94a3b8",
16
- marker: "#fde047",
17
- markerStroke: "#0f172a",
18
- grid: "#173054",
19
- rowLabel: "#7dd3fc",
20
- frame: "#31537f",
21
- fills: ["#818cf8", "#38bdf8", "#22c55e", "#f59e0b"]
22
- };
23
-
24
- const curves = {
25
- ease: { type: "cubicBezier", x1: 0.25, y1: 0.1, x2: 0.25, y2: 1 },
26
- easeOut: { type: "cubicBezier", x1: 0, y1: 0, x2: 0.2, y2: 1 }
27
- };
28
-
29
- const groupW = 180;
30
- const groupH = 120;
31
- const cellW = 270;
32
- const cellH = 240;
33
- const gridX = 70;
34
- const gridGap = 25;
35
- const scaleRowY = 150;
36
- const rotateRowY = 435;
37
- const groupOffsetX = 50;
38
- const groupOffsetY = 92;
39
-
40
- const originVariants = [
41
- { key: "top_left", title: "Top-left origin", note: "[0, 0]", local: [0, 0] },
42
- { key: "center", title: "Center origin", note: "[90, 60]", local: [groupW / 2, groupH / 2] },
43
- { key: "bottom_right", title: "Bottom-right origin", note: "[180, 120]", local: [groupW, groupH] },
44
- { key: "outside_right", title: "Outside-right origin", note: "[220, 60]", local: [groupW + 40, groupH / 2] }
45
- ];
46
-
47
- const elements = [];
48
-
49
- elements.push({
50
- id: "lab_title",
51
- type: "text",
52
- x: 70,
53
- y: 52,
54
- text: "Group Origin Transform Lab",
55
- fontSize: 38,
56
- fontFamily: font,
57
- weight: 700,
58
- fill: colors.title
59
- });
60
-
61
- elements.push({
62
- id: "lab_body",
63
- type: "text",
64
- x: 70,
65
- y: 96,
66
- text: "Same multi-child group, same motion, different origins.",
67
- fontSize: 16,
68
- fontFamily: font,
69
- weight: 400,
70
- fill: colors.body
71
- });
72
-
73
- elements.push({
74
- id: "scale_row_label",
75
- type: "text",
76
- x: 70,
77
- y: scaleRowY - 38,
78
- text: "Scale tests",
79
- fontSize: 18,
80
- fontFamily: font,
81
- weight: 700,
82
- fill: colors.rowLabel
83
- });
84
-
85
- elements.push({
86
- id: "rotate_row_label",
87
- type: "text",
88
- x: 70,
89
- y: rotateRowY - 38,
90
- text: "Rotation tests",
91
- fontSize: 18,
92
- fontFamily: font,
93
- weight: 700,
94
- fill: colors.rowLabel
95
- });
96
-
97
- originVariants.forEach((variant, index) => {
98
- const cellX = gridX + index * (cellW + gridGap);
99
- const fill = colors.fills[index % colors.fills.length];
100
- addPanel(cellX, scaleRowY, `scale_${variant.key}`, variant.title, variant.note);
101
- addScaleDemo(cellX, scaleRowY, variant, fill);
102
- addPanel(cellX, rotateRowY, `rotate_${variant.key}`, variant.title, variant.note);
103
- addRotateDemo(cellX, rotateRowY, variant, fill);
104
- });
105
-
106
- const doc = {
107
- version: 1,
108
- canvas: { width, height, background: bg, duration, fps },
109
- elements
110
- };
111
-
112
- const outPath = path.join(__dirname, "group-origin-effects-lab.visual.json");
113
- fs.writeFileSync(outPath, JSON.stringify(doc, null, 2));
114
- console.log("Written:", outPath);
115
-
116
- function addPanel(x, y, id, title, note) {
117
- elements.push({
118
- id: `${id}_panel`,
119
- type: "path",
120
- d: roundedRect(x, y, cellW, cellH, 22),
121
- fill: colors.panel,
122
- stroke: colors.panelStroke,
123
- strokeWidth: 1.5
124
- });
125
-
126
- elements.push({
127
- id: `${id}_title`,
128
- type: "text",
129
- x: x + 20,
130
- y: y + 18,
131
- text: title,
132
- fontSize: 16,
133
- fontFamily: font,
134
- weight: 700,
135
- fill: colors.title
136
- });
137
-
138
- elements.push({
139
- id: `${id}_note`,
140
- type: "text",
141
- x: x + 20,
142
- y: y + 42,
143
- text: note,
144
- fontSize: 12,
145
- fontFamily: font,
146
- weight: 500,
147
- fill: colors.body
148
- });
149
-
150
- elements.push({
151
- id: `${id}_guide_h`,
152
- type: "path",
153
- d: `M ${x + 20} ${y + groupOffsetY + groupH / 2} L ${x + cellW - 20} ${y + groupOffsetY + groupH / 2}`,
154
- fill: "none",
155
- stroke: colors.grid,
156
- strokeWidth: 1,
157
- dashArray: [6, 6]
158
- });
159
-
160
- elements.push({
161
- id: `${id}_guide_v`,
162
- type: "path",
163
- d: `M ${x + groupOffsetX + groupW / 2} ${y + 68} L ${x + groupOffsetX + groupW / 2} ${y + cellH - 20}`,
164
- fill: "none",
165
- stroke: colors.grid,
166
- strokeWidth: 1,
167
- dashArray: [6, 6]
168
- });
169
- }
170
-
171
- function addScaleDemo(cellX, cellY, variant, fill) {
172
- const groupX = cellX + groupOffsetX;
173
- const groupY = cellY + groupOffsetY;
174
- const originAbs = absoluteOrigin(groupX, groupY, variant.local);
175
-
176
- elements.push(groupFrame(`scale_${variant.key}_frame`, groupX, groupY));
177
- elements.push(originMarker(`scale_${variant.key}_origin`, originAbs[0], originAbs[1]));
178
-
179
- elements.push({
180
- id: `scale_${variant.key}_group`,
181
- type: "group",
182
- x: groupX,
183
- y: groupY,
184
- width: groupW,
185
- height: groupH,
186
- origin: originAbs,
187
- children: buildDemoGroup(`scale_${variant.key}`, fill),
188
- timeline: {
189
- tracks: {
190
- scale: {
191
- keyframes: [
192
- { time: 0, value: 1, out: curves.easeOut },
193
- { time: 1.3, value: 1.45, out: curves.ease },
194
- { time: 2.6, value: 0.72, out: curves.ease },
195
- { time: 4, value: 1.18, out: curves.ease },
196
- { time: 5.4, value: 1 }
197
- ]
198
- }
199
- }
200
- }
201
- });
202
- }
203
-
204
- function addRotateDemo(cellX, cellY, variant, fill) {
205
- const groupX = cellX + groupOffsetX;
206
- const groupY = cellY + groupOffsetY;
207
- const originAbs = absoluteOrigin(groupX, groupY, variant.local);
208
-
209
- elements.push(groupFrame(`rotate_${variant.key}_frame`, groupX, groupY));
210
- elements.push(originMarker(`rotate_${variant.key}_origin`, originAbs[0], originAbs[1]));
211
-
212
- elements.push({
213
- id: `rotate_${variant.key}_group`,
214
- type: "group",
215
- x: groupX,
216
- y: groupY,
217
- width: groupW,
218
- height: groupH,
219
- origin: originAbs,
220
- children: buildDemoGroup(`rotate_${variant.key}`, fill),
221
- timeline: {
222
- tracks: {
223
- rotation: {
224
- keyframes: [
225
- { time: 0, value: 0, out: curves.easeOut },
226
- { time: 1.5, value: 42, out: curves.ease },
227
- { time: 3, value: -28, out: curves.ease },
228
- { time: 4.5, value: 18, out: curves.ease },
229
- { time: 5.8, value: 0 }
230
- ]
231
- }
232
- }
233
- }
234
- });
235
- }
236
-
237
- function buildDemoGroup(prefix, fill) {
238
- return [
239
- {
240
- id: `${prefix}_main`,
241
- type: "path",
242
- d: roundedRect(0, 18, groupW, 102, 18),
243
- fill,
244
- stroke: "#dbeafe",
245
- strokeWidth: 2
246
- },
247
- {
248
- id: `${prefix}_tag`,
249
- type: "path",
250
- d: roundedRect(12, 0, 66, 20, 10),
251
- fill: "#0f172a",
252
- stroke: "#7dd3fc",
253
- strokeWidth: 1.5
254
- },
255
- {
256
- id: `${prefix}_tag_text`,
257
- type: "text",
258
- x: 45,
259
- y: 10,
260
- text: "GROUP",
261
- align: "center",
262
- valign: "middle",
263
- fontSize: 10,
264
- fontFamily: font,
265
- weight: 700,
266
- fill: "#7dd3fc"
267
- },
268
- {
269
- id: `${prefix}_accent`,
270
- type: "path",
271
- d: roundedRect(128, 38, 34, 34, 10),
272
- fill: "#0f172a",
273
- stroke: "#ffffff",
274
- strokeWidth: 1.5
275
- },
276
- {
277
- id: `${prefix}_bar_1`,
278
- type: "path",
279
- d: roundedRect(16, 50, 78, 10, 5),
280
- fill: "rgba(255,255,255,0.9)",
281
- stroke: "none"
282
- },
283
- {
284
- id: `${prefix}_bar_2`,
285
- type: "path",
286
- d: roundedRect(16, 70, 112, 10, 5),
287
- fill: "rgba(255,255,255,0.65)",
288
- stroke: "none"
289
- },
290
- {
291
- id: `${prefix}_footer`,
292
- type: "path",
293
- d: roundedRect(16, 92, 92, 12, 6),
294
- fill: "rgba(255,255,255,0.35)",
295
- stroke: "none"
296
- }
297
- ];
298
- }
299
-
300
- function groupFrame(id, x, y) {
301
- return {
302
- id,
303
- type: "path",
304
- d: roundedRect(x, y, groupW, groupH, 18),
305
- fill: "none",
306
- stroke: colors.frame,
307
- strokeWidth: 1,
308
- dashArray: [8, 6]
309
- };
310
- }
311
-
312
- function originMarker(id, x, y) {
313
- return {
314
- id,
315
- type: "group",
316
- x: x - 16,
317
- y: y - 16,
318
- children: [
319
- {
320
- id: `${id}_cross_h`,
321
- type: "path",
322
- d: "M 0 16 L 32 16",
323
- fill: "none",
324
- stroke: colors.marker,
325
- strokeWidth: 2,
326
- strokeCap: "round"
327
- },
328
- {
329
- id: `${id}_cross_v`,
330
- type: "path",
331
- d: "M 16 0 L 16 32",
332
- fill: "none",
333
- stroke: colors.marker,
334
- strokeWidth: 2,
335
- strokeCap: "round"
336
- },
337
- {
338
- id: `${id}_dot`,
339
- type: "path",
340
- d: circlePath(16, 16, 6),
341
- fill: colors.marker,
342
- stroke: colors.markerStroke,
343
- strokeWidth: 1.5
344
- }
345
- ]
346
- };
347
- }
348
-
349
- function absoluteOrigin(groupX, groupY, localOrigin) {
350
- return [groupX + localOrigin[0], groupY + localOrigin[1]];
351
- }
352
-
353
- function circlePath(cx, cy, r) {
354
- return `M ${cx - r} ${cy} a ${r} ${r} 0 1 0 ${r * 2} 0 a ${r} ${r} 0 1 0 ${-r * 2} 0`;
355
- }
356
-
357
- function roundedRect(x, y, w, h, r) {
358
- return [
359
- `M ${x + r} ${y}`,
360
- `L ${x + w - r} ${y}`,
361
- `Q ${x + w} ${y} ${x + w} ${y + r}`,
362
- `L ${x + w} ${y + h - r}`,
363
- `Q ${x + w} ${y + h} ${x + w - r} ${y + h}`,
364
- `L ${x + r} ${y + h}`,
365
- `Q ${x} ${y + h} ${x} ${y + h - r}`,
366
- `L ${x} ${y + r}`,
367
- `Q ${x} ${y} ${x + r} ${y}`,
368
- "Z"
369
- ].join(" ");
370
- }
@@ -1,169 +0,0 @@
1
- const fs = require("fs");
2
- const path = require("path");
3
-
4
- const width = 960;
5
- const height = 540;
6
- const duration = 4;
7
- const fps = 30;
8
-
9
- const image = {
10
- id: "photo",
11
- type: "image",
12
- src: svgDataUri(`
13
- <svg xmlns="http://www.w3.org/2000/svg" width="900" height="560" viewBox="0 0 900 560">
14
- <defs>
15
- <linearGradient id="bg" x1="0" y1="0" x2="1" y2="1">
16
- <stop offset="0" stop-color="#0f766e"/>
17
- <stop offset="0.52" stop-color="#2563eb"/>
18
- <stop offset="1" stop-color="#7c3aed"/>
19
- </linearGradient>
20
- </defs>
21
- <rect width="900" height="560" fill="url(#bg)"/>
22
- <circle cx="180" cy="150" r="86" fill="#fef3c7" opacity="0.9"/>
23
- <circle cx="710" cy="120" r="120" fill="#bae6fd" opacity="0.42"/>
24
- <circle cx="640" cy="415" r="180" fill="#f0abfc" opacity="0.35"/>
25
- <path d="M 0 410 C 160 340 260 470 430 390 C 590 315 720 395 900 330 L 900 560 L 0 560 Z" fill="#022c22" opacity="0.45"/>
26
- <path d="M 0 450 C 170 390 330 510 500 425 C 660 350 760 470 900 405 L 900 560 L 0 560 Z" fill="#020617" opacity="0.38"/>
27
- <text x="60" y="488" font-family="Arial, sans-serif" font-size="48" font-weight="800" fill="#ffffff">clip.d radius animation</text>
28
- </svg>
29
- `),
30
- x: 210,
31
- y: 116,
32
- width: 540,
33
- height: 336,
34
- clip: {
35
- type: "path",
36
- d: roundedRectClipPath(210, 116, 540, 336, 0)
37
- },
38
- timeline: {
39
- tracks: {
40
- "clip.d": {
41
- keyframes: sampledRadiusKeyframes({
42
- x: 210,
43
- y: 116,
44
- width: 540,
45
- height: 336,
46
- duration,
47
- fps: 12,
48
- radiusAt: (time) => {
49
- const loop = pingPong(time / duration);
50
- return 120 * easeInOut(loop);
51
- }
52
- })
53
- },
54
- opacity: {
55
- keyframes: [
56
- { time: 0, value: 0, out: curve("ease-out") },
57
- { time: 0.35, value: 1 }
58
- ]
59
- }
60
- }
61
- }
62
- };
63
-
64
- const doc = {
65
- version: 1,
66
- canvas: {
67
- width,
68
- height,
69
- background: "#f8fafc",
70
- duration,
71
- fps
72
- },
73
- elements: [
74
- {
75
- id: "title",
76
- type: "text",
77
- text: "Image radius is compiled to clip.d keyframes",
78
- x: width / 2,
79
- y: 54,
80
- align: "center",
81
- valign: "middle",
82
- fontSize: 30,
83
- weight: 800,
84
- fill: "#0f172a"
85
- },
86
- {
87
- id: "note",
88
- type: "text",
89
- text: "The kernel only sees an image plus animated clip path data.",
90
- x: width / 2,
91
- y: 494,
92
- align: "center",
93
- valign: "middle",
94
- fontSize: 18,
95
- fill: "#475569"
96
- },
97
- image
98
- ]
99
- };
100
-
101
- const outPath = path.join(__dirname, "image-clip-radius.visual.json");
102
- fs.writeFileSync(outPath, JSON.stringify(doc, null, 2) + "\n", "utf8");
103
- console.log(`Wrote ${outPath}`);
104
-
105
- function sampledRadiusKeyframes({ x, y, width, height, duration, fps, radiusAt }) {
106
- const frameCount = Math.max(1, Math.round(duration * fps));
107
- const frames = [];
108
- for (let index = 0; index <= frameCount; index += 1) {
109
- const time = Number(((index / frameCount) * duration).toFixed(4));
110
- const radius = radiusAt(time);
111
- frames.push({
112
- time,
113
- value: roundedRectClipPath(x, y, width, height, radius)
114
- });
115
- }
116
- return frames;
117
- }
118
-
119
- function roundedRectClipPath(x, y, width, height, radius) {
120
- const left = finite(x);
121
- const top = finite(y);
122
- const w = Math.max(0, finite(width));
123
- const h = Math.max(0, finite(height));
124
- const r = Math.min(Math.max(0, finite(radius)), w / 2, h / 2);
125
- const right = left + w;
126
- const bottom = top + h;
127
-
128
- if (r <= 0) return `M ${left} ${top} H ${right} V ${bottom} H ${left} Z`;
129
-
130
- return [
131
- `M ${round(left + r)} ${top}`,
132
- `H ${round(right - r)}`,
133
- `Q ${right} ${top} ${right} ${round(top + r)}`,
134
- `V ${round(bottom - r)}`,
135
- `Q ${right} ${bottom} ${round(right - r)} ${bottom}`,
136
- `H ${round(left + r)}`,
137
- `Q ${left} ${bottom} ${left} ${round(bottom - r)}`,
138
- `V ${round(top + r)}`,
139
- `Q ${left} ${top} ${round(left + r)} ${top}`,
140
- "Z"
141
- ].join(" ");
142
- }
143
-
144
- function pingPong(value) {
145
- const t = Math.max(0, Math.min(1, value));
146
- return t <= 0.5 ? t * 2 : (1 - t) * 2;
147
- }
148
-
149
- function easeInOut(t) {
150
- return t < 0.5 ? 2 * t * t : 1 - Math.pow(-2 * t + 2, 2) / 2;
151
- }
152
-
153
- function curve(name) {
154
- if (name === "ease-out") return { type: "cubicBezier", x1: 0, y1: 0, x2: 0.58, y2: 1 };
155
- return { type: "graph", points: [[0, 0], [1, 1]] };
156
- }
157
-
158
- function svgDataUri(svg) {
159
- return `data:image/svg+xml,${encodeURIComponent(svg.replace(/\s+/g, " ").trim())}`;
160
- }
161
-
162
- function finite(value) {
163
- const number = Number(value);
164
- return Number.isFinite(number) ? number : 0;
165
- }
166
-
167
- function round(value) {
168
- return Number(value.toFixed(2));
169
- }