capture-flow 0.0.0-stage → 0.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 (104) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +238 -2
  3. package/bin/capture-flow.mjs +12 -0
  4. package/package.json +55 -4
  5. package/src/build.ts +186 -0
  6. package/src/capture.ts +77 -0
  7. package/src/cli.ts +139 -0
  8. package/src/index.ts +11 -0
  9. package/src/manifest.ts +98 -0
  10. package/src/render.ts +75 -0
  11. package/src/verify.ts +90 -0
  12. package/vendor/wajha/LICENSE +21 -0
  13. package/vendor/wajha/NOTICE +21 -0
  14. package/vendor/wajha/engine/background.ts +55 -0
  15. package/vendor/wajha/engine/bidi.ts +589 -0
  16. package/vendor/wajha/engine/cache.ts +96 -0
  17. package/vendor/wajha/engine/color.ts +125 -0
  18. package/vendor/wajha/engine/devices/android.ts +53 -0
  19. package/vendor/wajha/engine/devices/browser.ts +170 -0
  20. package/vendor/wajha/engine/devices/finish.ts +154 -0
  21. package/vendor/wajha/engine/devices/geometry.ts +326 -0
  22. package/vendor/wajha/engine/devices/index.ts +143 -0
  23. package/vendor/wajha/engine/devices/ipad.ts +21 -0
  24. package/vendor/wajha/engine/devices/iphone.ts +55 -0
  25. package/vendor/wajha/engine/devices/macbook.ts +187 -0
  26. package/vendor/wajha/engine/devices/mock/apps/calendar.ts +145 -0
  27. package/vendor/wajha/engine/devices/mock/apps/chat.ts +213 -0
  28. package/vendor/wajha/engine/devices/mock/apps/finance.ts +164 -0
  29. package/vendor/wajha/engine/devices/mock/apps/fitness.ts +145 -0
  30. package/vendor/wajha/engine/devices/mock/apps/index.ts +14 -0
  31. package/vendor/wajha/engine/devices/mock/apps/meditation.ts +167 -0
  32. package/vendor/wajha/engine/devices/mock/apps/music.ts +152 -0
  33. package/vendor/wajha/engine/devices/mock/apps/shop.ts +116 -0
  34. package/vendor/wajha/engine/devices/mock/apps/social.ts +152 -0
  35. package/vendor/wajha/engine/devices/mock/apps/tasks.ts +131 -0
  36. package/vendor/wajha/engine/devices/mock/apps/travel.ts +121 -0
  37. package/vendor/wajha/engine/devices/mock/art.ts +557 -0
  38. package/vendor/wajha/engine/devices/mock/chrome.ts +337 -0
  39. package/vendor/wajha/engine/devices/mock/icons.ts +614 -0
  40. package/vendor/wajha/engine/devices/mock/kit.ts +213 -0
  41. package/vendor/wajha/engine/devices/mock/rng.ts +40 -0
  42. package/vendor/wajha/engine/devices/mock/theme.ts +133 -0
  43. package/vendor/wajha/engine/devices/mock/widgets.ts +231 -0
  44. package/vendor/wajha/engine/devices/paths.ts +113 -0
  45. package/vendor/wajha/engine/devices/screen.ts +75 -0
  46. package/vendor/wajha/engine/devices/shadow.ts +124 -0
  47. package/vendor/wajha/engine/devices/slab.ts +200 -0
  48. package/vendor/wajha/engine/devices/vision.ts +43 -0
  49. package/vendor/wajha/engine/devices/watch.ts +14 -0
  50. package/vendor/wajha/engine/geometry.ts +152 -0
  51. package/vendor/wajha/engine/images.ts +96 -0
  52. package/vendor/wajha/engine/index.ts +20 -0
  53. package/vendor/wajha/engine/linebreak.ts +226 -0
  54. package/vendor/wajha/engine/markup.ts +84 -0
  55. package/vendor/wajha/engine/mock.ts +158 -0
  56. package/vendor/wajha/engine/paint.ts +474 -0
  57. package/vendor/wajha/engine/patterns.ts +263 -0
  58. package/vendor/wajha/engine/render.ts +364 -0
  59. package/vendor/wajha/engine/shapes.ts +260 -0
  60. package/vendor/wajha/engine/testing/canvasNode.ts +121 -0
  61. package/vendor/wajha/engine/testing/fakeDevices.ts +85 -0
  62. package/vendor/wajha/engine/text.ts +694 -0
  63. package/vendor/wajha/engine/types.ts +190 -0
  64. package/vendor/wajha/export/paths.ts +197 -0
  65. package/vendor/wajha/export/png.ts +223 -0
  66. package/vendor/wajha/export/types.ts +60 -0
  67. package/vendor/wajha/model/adapt.ts +889 -0
  68. package/vendor/wajha/model/catalog.ts +369 -0
  69. package/vendor/wajha/model/clone.ts +58 -0
  70. package/vendor/wajha/model/colorMath.ts +128 -0
  71. package/vendor/wajha/model/defaults.ts +386 -0
  72. package/vendor/wajha/model/geometry.ts +95 -0
  73. package/vendor/wajha/model/ids.ts +13 -0
  74. package/vendor/wajha/model/instantiate.ts +280 -0
  75. package/vendor/wajha/model/mirror.ts +43 -0
  76. package/vendor/wajha/model/resolve.ts +87 -0
  77. package/vendor/wajha/model/rules.ts +249 -0
  78. package/vendor/wajha/model/stub.ts +4 -0
  79. package/vendor/wajha/model/types.ts +456 -0
  80. package/vendor/wajha/model/typography.ts +28 -0
  81. package/vendor/wajha/model/validate.ts +917 -0
  82. package/vendor/wajha/templates/builtin/aurora.ts +163 -0
  83. package/vendor/wajha/templates/builtin/bubblegum.ts +132 -0
  84. package/vendor/wajha/templates/builtin/citrusPop.ts +124 -0
  85. package/vendor/wajha/templates/builtin/clayGarden.ts +114 -0
  86. package/vendor/wajha/templates/builtin/desertDune.ts +97 -0
  87. package/vendor/wajha/templates/builtin/glassPrism.ts +139 -0
  88. package/vendor/wajha/templates/builtin/launchpad.ts +140 -0
  89. package/vendor/wajha/templates/builtin/loudAndClear.ts +109 -0
  90. package/vendor/wajha/templates/builtin/midnightNeon.ts +108 -0
  91. package/vendor/wajha/templates/builtin/monoSwiss.ts +149 -0
  92. package/vendor/wajha/templates/builtin/noirGold.ts +149 -0
  93. package/vendor/wajha/templates/builtin/noor.ts +107 -0
  94. package/vendor/wajha/templates/builtin/obsidian.ts +137 -0
  95. package/vendor/wajha/templates/builtin/panoramaPeaks.ts +145 -0
  96. package/vendor/wajha/templates/builtin/panoramaRibbon.ts +138 -0
  97. package/vendor/wajha/templates/builtin/panoramaWaves.ts +138 -0
  98. package/vendor/wajha/templates/builtin/paperAndInk.ts +98 -0
  99. package/vendor/wajha/templates/builtin/sage.ts +94 -0
  100. package/vendor/wajha/templates/builtin/splitTone.ts +129 -0
  101. package/vendor/wajha/templates/builtin/sunsetBoulevard.ts +127 -0
  102. package/vendor/wajha/templates/index.ts +55 -0
  103. package/vendor/wajha/templates/kit.ts +761 -0
  104. package/vendor/wajha/ui/sortShots.ts +239 -0
@@ -0,0 +1,614 @@
1
+ /**
2
+ * A small outline icon set (24-unit grid, 2-unit strokes, round caps), in
3
+ * the spirit of SF Symbols / Lucide. Drawn as vectors so they stay crisp
4
+ * at any size and need no assets.
5
+ */
6
+ import type { Ctx2D } from '../../types';
7
+
8
+ export type IconName =
9
+ | 'home'
10
+ | 'search'
11
+ | 'heart'
12
+ | 'user'
13
+ | 'users'
14
+ | 'bell'
15
+ | 'chart'
16
+ | 'calendar'
17
+ | 'plus'
18
+ | 'chat'
19
+ | 'settings'
20
+ | 'grid'
21
+ | 'play'
22
+ | 'pause'
23
+ | 'next'
24
+ | 'prev'
25
+ | 'shuffle'
26
+ | 'repeat'
27
+ | 'pin'
28
+ | 'bag'
29
+ | 'star'
30
+ | 'check'
31
+ | 'chevronLeft'
32
+ | 'chevronRight'
33
+ | 'chevronDown'
34
+ | 'arrowUp'
35
+ | 'arrowDown'
36
+ | 'arrowUpRight'
37
+ | 'more'
38
+ | 'send'
39
+ | 'camera'
40
+ | 'bookmark'
41
+ | 'phone'
42
+ | 'video'
43
+ | 'mic'
44
+ | 'filter'
45
+ | 'card'
46
+ | 'clock'
47
+ | 'flame'
48
+ | 'list'
49
+ | 'compass'
50
+ | 'share'
51
+ | 'moon'
52
+ | 'music'
53
+ | 'image'
54
+ | 'folder'
55
+ | 'inbox'
56
+ | 'layers'
57
+ | 'activity'
58
+ | 'leaf'
59
+ | 'map'
60
+ | 'close'
61
+ | 'menu'
62
+ | 'edit'
63
+ | 'sparkle'
64
+ | 'wave'
65
+ | 'drop';
66
+
67
+ type Draw = (ctx: Ctx2D) => void;
68
+
69
+ interface IconDef {
70
+ /** Outline parts. */
71
+ stroke?: Draw;
72
+ /** Solid parts (dots, play triangles). */
73
+ fill?: Draw;
74
+ }
75
+
76
+ const TAU = Math.PI * 2;
77
+
78
+ function poly(ctx: Ctx2D, pts: number[], close = false): void {
79
+ ctx.moveTo(pts[0], pts[1]);
80
+ for (let i = 2; i < pts.length; i += 2) ctx.lineTo(pts[i], pts[i + 1]);
81
+ if (close) ctx.closePath();
82
+ }
83
+
84
+ function rrect(ctx: Ctx2D, x: number, y: number, w: number, h: number, r: number): void {
85
+ ctx.moveTo(x + r, y);
86
+ ctx.arcTo(x + w, y, x + w, y + h, r);
87
+ ctx.arcTo(x + w, y + h, x, y + h, r);
88
+ ctx.arcTo(x, y + h, x, y, r);
89
+ ctx.arcTo(x, y, x + w, y, r);
90
+ ctx.closePath();
91
+ }
92
+
93
+ function circ(ctx: Ctx2D, cx: number, cy: number, r: number): void {
94
+ ctx.moveTo(cx + r, cy);
95
+ ctx.arc(cx, cy, r, 0, TAU);
96
+ }
97
+
98
+ function heart(ctx: Ctx2D): void {
99
+ ctx.moveTo(12, 20.3);
100
+ ctx.bezierCurveTo(12, 20.3, 3, 14.8, 3, 9.1);
101
+ ctx.bezierCurveTo(3, 6.2, 5.2, 4, 8, 4);
102
+ ctx.bezierCurveTo(9.8, 4, 11.2, 5, 12, 6.3);
103
+ ctx.bezierCurveTo(12.8, 5, 14.2, 4, 16, 4);
104
+ ctx.bezierCurveTo(18.8, 4, 21, 6.2, 21, 9.1);
105
+ ctx.bezierCurveTo(21, 14.8, 12, 20.3, 12, 20.3);
106
+ ctx.closePath();
107
+ }
108
+
109
+ function star(ctx: Ctx2D): void {
110
+ for (let i = 0; i < 10; i++) {
111
+ const r = i % 2 === 0 ? 9.6 : 4.3;
112
+ const a = -Math.PI / 2 + (i * Math.PI) / 5;
113
+ const x = 12 + Math.cos(a) * r;
114
+ const y = 12.8 + Math.sin(a) * r;
115
+ if (i === 0) ctx.moveTo(x, y);
116
+ else ctx.lineTo(x, y);
117
+ }
118
+ ctx.closePath();
119
+ }
120
+
121
+ /** Crescent between circle A and an offset circle B. */
122
+ function crescent(ctx: Ctx2D): void {
123
+ const ax = 12, ay = 12, ar = 8.6;
124
+ const bx = 16.6, by = 7.6, br = 7.4;
125
+ const dx = bx - ax, dy = by - ay;
126
+ const d = Math.hypot(dx, dy);
127
+ const a = (ar * ar - br * br + d * d) / (2 * d);
128
+ const h = Math.sqrt(Math.max(0, ar * ar - a * a));
129
+ const px = ax + (a * dx) / d, py = ay + (a * dy) / d;
130
+ const i1x = px + (h * -dy) / d, i1y = py + (h * dx) / d;
131
+ const i2x = px - (h * -dy) / d, i2y = py - (h * dx) / d;
132
+ const a1 = Math.atan2(i1y - ay, i1x - ax);
133
+ const a2 = Math.atan2(i2y - ay, i2x - ax);
134
+ const b1 = Math.atan2(i2y - by, i2x - bx);
135
+ const b2 = Math.atan2(i1y - by, i1x - bx);
136
+ ctx.moveTo(i1x, i1y);
137
+ ctx.arc(ax, ay, ar, a1, a2, false);
138
+ ctx.arc(bx, by, br, b1, b2, true);
139
+ ctx.closePath();
140
+ }
141
+
142
+ const ICONS: Record<IconName, IconDef> = {
143
+ home: { stroke: (c) => poly(c, [3.5, 10.5, 12, 3.5, 20.5, 10.5, 20.5, 20.5, 14.5, 20.5, 14.5, 14.5, 9.5, 14.5, 9.5, 20.5, 3.5, 20.5], true) },
144
+ search: {
145
+ stroke: (c) => {
146
+ circ(c, 11, 11, 6.8);
147
+ c.moveTo(16, 16);
148
+ c.lineTo(20.5, 20.5);
149
+ },
150
+ },
151
+ heart: { stroke: heart },
152
+ user: {
153
+ stroke: (c) => {
154
+ circ(c, 12, 8.2, 4);
155
+ c.moveTo(4.5, 20.5);
156
+ c.bezierCurveTo(4.5, 16.4, 7.8, 14, 12, 14);
157
+ c.bezierCurveTo(16.2, 14, 19.5, 16.4, 19.5, 20.5);
158
+ },
159
+ },
160
+ users: {
161
+ stroke: (c) => {
162
+ circ(c, 9, 8.5, 3.6);
163
+ c.moveTo(2.8, 20);
164
+ c.bezierCurveTo(2.8, 16.5, 5.6, 14.3, 9, 14.3);
165
+ c.bezierCurveTo(12.4, 14.3, 15.2, 16.5, 15.2, 20);
166
+ c.moveTo(15.5, 5.2);
167
+ c.arc(16, 8.5, 3.3, -Math.PI * 0.55, Math.PI * 0.5);
168
+ c.moveTo(17.6, 14.4);
169
+ c.bezierCurveTo(19.7, 15, 21.2, 16.9, 21.2, 19.6);
170
+ },
171
+ },
172
+ bell: {
173
+ stroke: (c) => {
174
+ c.moveTo(6, 16.5);
175
+ c.lineTo(6, 11);
176
+ c.arc(12, 11, 6, Math.PI, 0);
177
+ c.lineTo(18, 16.5);
178
+ c.lineTo(19.5, 18.2);
179
+ c.lineTo(4.5, 18.2);
180
+ c.closePath();
181
+ c.moveTo(10, 21);
182
+ c.lineTo(14, 21);
183
+ },
184
+ },
185
+ chart: {
186
+ stroke: (c) => {
187
+ c.moveTo(5, 20);
188
+ c.lineTo(5, 13);
189
+ c.moveTo(12, 20);
190
+ c.lineTo(12, 5);
191
+ c.moveTo(19, 20);
192
+ c.lineTo(19, 10);
193
+ },
194
+ },
195
+ calendar: {
196
+ stroke: (c) => {
197
+ rrect(c, 3.5, 5, 17, 15.5, 3);
198
+ c.moveTo(3.5, 10);
199
+ c.lineTo(20.5, 10);
200
+ c.moveTo(8, 3);
201
+ c.lineTo(8, 6.5);
202
+ c.moveTo(16, 3);
203
+ c.lineTo(16, 6.5);
204
+ },
205
+ },
206
+ plus: {
207
+ stroke: (c) => {
208
+ c.moveTo(12, 5);
209
+ c.lineTo(12, 19);
210
+ c.moveTo(5, 12);
211
+ c.lineTo(19, 12);
212
+ },
213
+ },
214
+ chat: {
215
+ stroke: (c) => {
216
+ c.moveTo(7.5, 17.5);
217
+ c.lineTo(4.5, 20.5);
218
+ c.lineTo(4.5, 7.5);
219
+ c.arcTo(4.5, 4, 8, 4, 3.5);
220
+ c.lineTo(16.5, 4);
221
+ c.arcTo(20, 4, 20, 7.5, 3.5);
222
+ c.lineTo(20, 14);
223
+ c.arcTo(20, 17.5, 16.5, 17.5, 3.5);
224
+ c.closePath();
225
+ },
226
+ },
227
+ settings: {
228
+ stroke: (c) => {
229
+ for (let i = 0; i <= 16; i++) {
230
+ const a = (i / 16) * TAU;
231
+ const r = i % 2 === 0 ? 9 : 7;
232
+ const x = 12 + Math.cos(a) * r;
233
+ const y = 12 + Math.sin(a) * r;
234
+ if (i === 0) c.moveTo(x, y);
235
+ else c.lineTo(x, y);
236
+ }
237
+ c.closePath();
238
+ circ(c, 12, 12, 3);
239
+ },
240
+ },
241
+ grid: {
242
+ stroke: (c) => {
243
+ rrect(c, 4, 4, 6.5, 6.5, 1.8);
244
+ rrect(c, 13.5, 4, 6.5, 6.5, 1.8);
245
+ rrect(c, 4, 13.5, 6.5, 6.5, 1.8);
246
+ rrect(c, 13.5, 13.5, 6.5, 6.5, 1.8);
247
+ },
248
+ },
249
+ play: { fill: (c) => poly(c, [8, 5, 19, 12, 8, 19], true), stroke: (c) => poly(c, [8, 5, 19, 12, 8, 19], true) },
250
+ pause: {
251
+ fill: (c) => {
252
+ rrect(c, 6.5, 4.5, 4, 15, 1.4);
253
+ rrect(c, 13.5, 4.5, 4, 15, 1.4);
254
+ },
255
+ },
256
+ next: {
257
+ fill: (c) => poly(c, [5, 6, 15, 12, 5, 18], true),
258
+ stroke: (c) => {
259
+ poly(c, [5, 6, 15, 12, 5, 18], true);
260
+ c.moveTo(18.5, 6);
261
+ c.lineTo(18.5, 18);
262
+ },
263
+ },
264
+ prev: {
265
+ fill: (c) => poly(c, [19, 6, 9, 12, 19, 18], true),
266
+ stroke: (c) => {
267
+ poly(c, [19, 6, 9, 12, 19, 18], true);
268
+ c.moveTo(5.5, 6);
269
+ c.lineTo(5.5, 18);
270
+ },
271
+ },
272
+ shuffle: {
273
+ stroke: (c) => {
274
+ c.moveTo(3.5, 7);
275
+ c.lineTo(7, 7);
276
+ c.bezierCurveTo(12, 7, 12, 17, 17, 17);
277
+ c.lineTo(20.5, 17);
278
+ c.moveTo(3.5, 17);
279
+ c.lineTo(7, 17);
280
+ c.bezierCurveTo(12, 17, 12, 7, 17, 7);
281
+ c.lineTo(20.5, 7);
282
+ poly(c, [18, 4.5, 20.5, 7, 18, 9.5]);
283
+ poly(c, [18, 14.5, 20.5, 17, 18, 19.5]);
284
+ },
285
+ },
286
+ repeat: {
287
+ stroke: (c) => {
288
+ c.moveTo(4, 12);
289
+ c.lineTo(4, 10);
290
+ c.arcTo(4, 6.5, 7.5, 6.5, 3.5);
291
+ c.lineTo(20, 6.5);
292
+ poly(c, [17, 3.5, 20, 6.5, 17, 9.5]);
293
+ c.moveTo(20, 12);
294
+ c.lineTo(20, 14);
295
+ c.arcTo(20, 17.5, 16.5, 17.5, 3.5);
296
+ c.lineTo(4, 17.5);
297
+ poly(c, [7, 14.5, 4, 17.5, 7, 20.5]);
298
+ },
299
+ },
300
+ pin: {
301
+ stroke: (c) => {
302
+ c.moveTo(12, 21.5);
303
+ c.bezierCurveTo(12, 21.5, 5, 15.2, 5, 10);
304
+ c.arc(12, 10, 7, Math.PI, 0);
305
+ c.bezierCurveTo(19, 15.2, 12, 21.5, 12, 21.5);
306
+ c.closePath();
307
+ circ(c, 12, 10, 2.5);
308
+ },
309
+ },
310
+ bag: {
311
+ stroke: (c) => {
312
+ rrect(c, 4, 8, 16, 13, 2.8);
313
+ c.moveTo(8.5, 8);
314
+ c.lineTo(8.5, 7);
315
+ c.arc(12, 7, 3.5, Math.PI, 0);
316
+ c.lineTo(15.5, 8);
317
+ },
318
+ },
319
+ star: { stroke: star },
320
+ check: { stroke: (c) => poly(c, [5, 12.5, 10, 17.5, 19.5, 7]) },
321
+ chevronLeft: { stroke: (c) => poly(c, [15, 5, 8, 12, 15, 19]) },
322
+ chevronRight: { stroke: (c) => poly(c, [9, 5, 16, 12, 9, 19]) },
323
+ chevronDown: { stroke: (c) => poly(c, [6, 9, 12, 15, 18, 9]) },
324
+ arrowUp: {
325
+ stroke: (c) => {
326
+ c.moveTo(12, 19);
327
+ c.lineTo(12, 5);
328
+ poly(c, [6, 11, 12, 5, 18, 11]);
329
+ },
330
+ },
331
+ arrowDown: {
332
+ stroke: (c) => {
333
+ c.moveTo(12, 5);
334
+ c.lineTo(12, 19);
335
+ poly(c, [6, 13, 12, 19, 18, 13]);
336
+ },
337
+ },
338
+ arrowUpRight: {
339
+ stroke: (c) => {
340
+ c.moveTo(7, 17);
341
+ c.lineTo(17, 7);
342
+ poly(c, [8.5, 7, 17, 7, 17, 15.5]);
343
+ },
344
+ },
345
+ more: {
346
+ fill: (c) => {
347
+ circ(c, 5.5, 12, 1.8);
348
+ circ(c, 12, 12, 1.8);
349
+ circ(c, 18.5, 12, 1.8);
350
+ },
351
+ },
352
+ send: {
353
+ stroke: (c) => {
354
+ poly(c, [20.5, 3.5, 3.5, 10.5, 10.5, 13.5, 13.5, 20.5], true);
355
+ c.moveTo(20.5, 3.5);
356
+ c.lineTo(10.5, 13.5);
357
+ },
358
+ },
359
+ camera: {
360
+ stroke: (c) => {
361
+ c.moveTo(3.5, 9.5);
362
+ c.arcTo(3.5, 7, 6, 7, 2.5);
363
+ c.lineTo(8, 7);
364
+ c.lineTo(9.5, 4.5);
365
+ c.lineTo(14.5, 4.5);
366
+ c.lineTo(16, 7);
367
+ c.lineTo(18, 7);
368
+ c.arcTo(20.5, 7, 20.5, 9.5, 2.5);
369
+ c.lineTo(20.5, 17.5);
370
+ c.arcTo(20.5, 20, 18, 20, 2.5);
371
+ c.lineTo(6, 20);
372
+ c.arcTo(3.5, 20, 3.5, 17.5, 2.5);
373
+ c.closePath();
374
+ circ(c, 12, 13.2, 3.6);
375
+ },
376
+ },
377
+ bookmark: { stroke: (c) => poly(c, [6.5, 3.5, 17.5, 3.5, 17.5, 20.5, 12, 16.3, 6.5, 20.5], true) },
378
+ phone: {
379
+ stroke: (c) => {
380
+ rrect(c, 7, 2.5, 10, 19, 2.6);
381
+ c.moveTo(11, 18.3);
382
+ c.lineTo(13, 18.3);
383
+ },
384
+ },
385
+ video: {
386
+ stroke: (c) => {
387
+ rrect(c, 2.5, 6.5, 13, 11, 2.6);
388
+ poly(c, [15.5, 10.3, 21.5, 7, 21.5, 17, 15.5, 13.7]);
389
+ },
390
+ },
391
+ mic: {
392
+ stroke: (c) => {
393
+ rrect(c, 9, 3, 6, 11, 3);
394
+ c.moveTo(5.5, 11);
395
+ c.arc(12, 11, 6.5, Math.PI, 0, true);
396
+ c.moveTo(12, 17.5);
397
+ c.lineTo(12, 21);
398
+ },
399
+ },
400
+ filter: {
401
+ stroke: (c) => {
402
+ c.moveTo(4, 7);
403
+ c.lineTo(12, 7);
404
+ c.moveTo(18, 7);
405
+ c.lineTo(20, 7);
406
+ circ(c, 15, 7, 2.8);
407
+ c.moveTo(4, 17);
408
+ c.lineTo(6, 17);
409
+ c.moveTo(12, 17);
410
+ c.lineTo(20, 17);
411
+ circ(c, 9, 17, 2.8);
412
+ },
413
+ },
414
+ card: {
415
+ stroke: (c) => {
416
+ rrect(c, 2.5, 5, 19, 14, 3);
417
+ c.moveTo(2.5, 10);
418
+ c.lineTo(21.5, 10);
419
+ c.moveTo(6, 15);
420
+ c.lineTo(10, 15);
421
+ },
422
+ },
423
+ clock: {
424
+ stroke: (c) => {
425
+ circ(c, 12, 12, 8.8);
426
+ poly(c, [12, 7, 12, 12, 15.5, 14]);
427
+ },
428
+ },
429
+ flame: {
430
+ stroke: (c) => {
431
+ c.moveTo(12, 21.5);
432
+ c.bezierCurveTo(7.6, 21.5, 5, 18.5, 5, 15.2);
433
+ c.bezierCurveTo(5, 10.8, 9, 8.8, 9.5, 3.5);
434
+ c.bezierCurveTo(12.6, 5.6, 14.2, 8.3, 14, 11);
435
+ c.bezierCurveTo(15, 10.2, 15.7, 9, 16, 7.8);
436
+ c.bezierCurveTo(18, 9.8, 19, 12.4, 19, 15.2);
437
+ c.bezierCurveTo(19, 18.8, 16.4, 21.5, 12, 21.5);
438
+ c.closePath();
439
+ },
440
+ },
441
+ list: {
442
+ stroke: (c) => {
443
+ for (const y of [6, 12, 18]) {
444
+ c.moveTo(9, y);
445
+ c.lineTo(20, y);
446
+ }
447
+ },
448
+ fill: (c) => {
449
+ for (const y of [6, 12, 18]) circ(c, 4.5, y, 1.5);
450
+ },
451
+ },
452
+ compass: {
453
+ stroke: (c) => {
454
+ circ(c, 12, 12, 8.8);
455
+ poly(c, [15.6, 8.4, 13.6, 13.6, 8.4, 15.6, 10.4, 10.4], true);
456
+ },
457
+ },
458
+ share: {
459
+ stroke: (c) => {
460
+ poly(c, [8.5, 9, 6, 9, 6, 20.5, 18, 20.5, 18, 9, 15.5, 9]);
461
+ c.moveTo(12, 14);
462
+ c.lineTo(12, 3.5);
463
+ poly(c, [8.5, 7, 12, 3.5, 15.5, 7]);
464
+ },
465
+ },
466
+ moon: { stroke: crescent },
467
+ music: {
468
+ stroke: (c) => {
469
+ circ(c, 7, 17.5, 2.8);
470
+ circ(c, 17, 15.5, 2.8);
471
+ poly(c, [9.8, 17.5, 9.8, 5.5, 19.8, 3.5, 19.8, 15.5]);
472
+ },
473
+ },
474
+ image: {
475
+ stroke: (c) => {
476
+ rrect(c, 3, 4, 18, 16, 3);
477
+ circ(c, 8.5, 9.5, 1.8);
478
+ poly(c, [3.5, 17.5, 9, 12.5, 13, 16, 16, 13, 20.5, 17]);
479
+ },
480
+ },
481
+ folder: {
482
+ stroke: (c) => {
483
+ c.moveTo(3.5, 7);
484
+ c.arcTo(3.5, 5, 5.5, 5, 2);
485
+ c.lineTo(9.5, 5);
486
+ c.lineTo(11.5, 7.5);
487
+ c.lineTo(18.5, 7.5);
488
+ c.arcTo(20.5, 7.5, 20.5, 9.5, 2);
489
+ c.lineTo(20.5, 18);
490
+ c.arcTo(20.5, 20, 18.5, 20, 2);
491
+ c.lineTo(5.5, 20);
492
+ c.arcTo(3.5, 20, 3.5, 18, 2);
493
+ c.closePath();
494
+ },
495
+ },
496
+ inbox: {
497
+ stroke: (c) => {
498
+ poly(c, [3.5, 13, 6.5, 5, 17.5, 5, 20.5, 13, 20.5, 19.5, 3.5, 19.5], true);
499
+ poly(c, [3.5, 13, 8.5, 13, 10, 15.5, 14, 15.5, 15.5, 13, 20.5, 13]);
500
+ },
501
+ },
502
+ layers: {
503
+ stroke: (c) => {
504
+ poly(c, [12, 3.5, 21, 8.2, 12, 13, 3, 8.2], true);
505
+ poly(c, [3, 12.3, 12, 17, 21, 12.3]);
506
+ poly(c, [3, 16.3, 12, 21, 21, 16.3]);
507
+ },
508
+ },
509
+ activity: { stroke: (c) => poly(c, [3, 12, 7, 12, 10, 4.5, 14, 19.5, 17, 12, 21, 12]) },
510
+ leaf: {
511
+ stroke: (c) => {
512
+ c.moveTo(5, 19);
513
+ c.bezierCurveTo(5, 10, 10, 5, 20, 4);
514
+ c.bezierCurveTo(19, 14, 14, 19, 5, 19);
515
+ c.closePath();
516
+ c.moveTo(5, 19);
517
+ c.lineTo(12.5, 11.5);
518
+ },
519
+ },
520
+ map: {
521
+ stroke: (c) => {
522
+ poly(c, [3.5, 6, 9, 4, 15, 6, 20.5, 4, 20.5, 18, 15, 20, 9, 18, 3.5, 20], true);
523
+ c.moveTo(9, 4);
524
+ c.lineTo(9, 18);
525
+ c.moveTo(15, 6);
526
+ c.lineTo(15, 20);
527
+ },
528
+ },
529
+ close: {
530
+ stroke: (c) => {
531
+ c.moveTo(6, 6);
532
+ c.lineTo(18, 18);
533
+ c.moveTo(18, 6);
534
+ c.lineTo(6, 18);
535
+ },
536
+ },
537
+ menu: {
538
+ stroke: (c) => {
539
+ c.moveTo(4, 7);
540
+ c.lineTo(20, 7);
541
+ c.moveTo(4, 12);
542
+ c.lineTo(20, 12);
543
+ c.moveTo(4, 17);
544
+ c.lineTo(14, 17);
545
+ },
546
+ },
547
+ edit: {
548
+ stroke: (c) => {
549
+ poly(c, [4, 20, 4.6, 16.4, 16, 5, 19, 8, 7.6, 19.4], true);
550
+ c.moveTo(13.5, 7.5);
551
+ c.lineTo(16.5, 10.5);
552
+ },
553
+ },
554
+ sparkle: {
555
+ fill: (c) => {
556
+ c.moveTo(12, 3);
557
+ c.quadraticCurveTo(12.8, 11.2, 21, 12);
558
+ c.quadraticCurveTo(12.8, 12.8, 12, 21);
559
+ c.quadraticCurveTo(11.2, 12.8, 3, 12);
560
+ c.quadraticCurveTo(11.2, 11.2, 12, 3);
561
+ c.closePath();
562
+ },
563
+ },
564
+ wave: {
565
+ stroke: (c) => {
566
+ const hs = [4, 9, 14, 7, 11, 5];
567
+ hs.forEach((h, i) => {
568
+ const x = 4 + i * 3.2;
569
+ c.moveTo(x, 12 - h / 2);
570
+ c.lineTo(x, 12 + h / 2);
571
+ });
572
+ },
573
+ },
574
+ drop: {
575
+ stroke: (c) => {
576
+ c.moveTo(12, 3.5);
577
+ c.bezierCurveTo(12, 3.5, 5.5, 10.5, 5.5, 14.5);
578
+ c.arc(12, 14.5, 6.5, Math.PI, 0, true);
579
+ c.bezierCurveTo(18.5, 10.5, 12, 3.5, 12, 3.5);
580
+ c.closePath();
581
+ },
582
+ },
583
+ };
584
+
585
+ export const ICON_NAMES = Object.keys(ICONS) as IconName[];
586
+
587
+ /**
588
+ * Draws an icon centred at (cx, cy), `size` points wide. `filled` paints
589
+ * outline icons solid (selected tab, liked heart).
590
+ */
591
+ export function icon(ctx: Ctx2D, name: IconName, cx: number, cy: number, size: number, color: string | CanvasGradient, filled = false, weight = 2): void {
592
+ const def = ICONS[name];
593
+ if (!def || !(size > 0)) return;
594
+ ctx.save();
595
+ ctx.translate(cx - size / 2, cy - size / 2);
596
+ ctx.scale(size / 24, size / 24);
597
+ ctx.lineCap = 'round';
598
+ ctx.lineJoin = 'round';
599
+ ctx.lineWidth = weight;
600
+ ctx.strokeStyle = color;
601
+ ctx.fillStyle = color;
602
+ if (def.fill) {
603
+ ctx.beginPath();
604
+ def.fill(ctx);
605
+ ctx.fill();
606
+ }
607
+ if (def.stroke) {
608
+ ctx.beginPath();
609
+ def.stroke(ctx);
610
+ if (filled) ctx.fill();
611
+ ctx.stroke();
612
+ }
613
+ ctx.restore();
614
+ }