@rogieking/figui3 1.5.9 → 1.6.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.
package/components.css CHANGED
@@ -1129,7 +1129,9 @@ fig-chit {
1129
1129
  height: 0.875rem;
1130
1130
  background-image: var(--src);
1131
1131
  border-radius: 0.125rem;
1132
- background-size: cover;
1132
+ background-size: contain;
1133
+ background-position: center center;
1134
+ background-repeat: no-repeat;
1133
1135
  box-shadow: inset 0 0 0 1px var(--figma-color-bordertranslucent);
1134
1136
  }
1135
1137
  &::after,
package/fig.js CHANGED
@@ -1686,6 +1686,7 @@ class FigCheckbox extends HTMLElement {
1686
1686
  this.input.indeterminate = false;
1687
1687
  this.input.removeAttribute("indeterminate");
1688
1688
  this.value = this.input.value;
1689
+ this.checked = this.input.checked;
1689
1690
  }
1690
1691
  }
1691
1692
  window.customElements.define("fig-checkbox", FigCheckbox);
@@ -1939,7 +1940,7 @@ class FigImage extends HTMLElement {
1939
1940
  });
1940
1941
  //emit event for loaded
1941
1942
  this.dispatchEvent(
1942
- new CustomEvent("load", {
1943
+ new CustomEvent("loaded", {
1943
1944
  bubbles: true,
1944
1945
  cancelable: true,
1945
1946
  detail: {
@@ -1948,6 +1949,13 @@ class FigImage extends HTMLElement {
1948
1949
  },
1949
1950
  })
1950
1951
  );
1952
+ //emit for change too
1953
+ this.dispatchEvent(
1954
+ new CustomEvent("change", {
1955
+ bubbles: true,
1956
+ cancelable: true,
1957
+ })
1958
+ );
1951
1959
  this.src = this.blob;
1952
1960
  this.setAttribute("src", this.src);
1953
1961
  this.chit.setAttribute("src", this.src);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rogieking/figui3",
3
- "version": "1.5.9",
3
+ "version": "1.6.1",
4
4
  "module": "index.ts",
5
5
  "type": "module",
6
6
  "devDependencies": {
package/tracer.html ADDED
@@ -0,0 +1,569 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <meta name="viewport"
7
+ content="width=device-width, initial-scale=1.0">
8
+ <title>Figma UI3 Web Components</title>
9
+ <link rel="stylesheet"
10
+ type="text/css"
11
+ href="fig.css">
12
+ <script src="fig.js"></script>
13
+ <style>
14
+ body {
15
+ margin: 0 auto;
16
+ padding: 1rem;
17
+ display: flex;
18
+ gap: 1rem;
19
+ }
20
+
21
+ #svg {
22
+ width: 100%;
23
+ height: calc(100vh - 2rem);
24
+ border: 1px solid #000;
25
+ overflow: scroll;
26
+
27
+ svg {
28
+ width: 100%;
29
+ height: 100%;
30
+ object-fit: contain;
31
+ }
32
+ }
33
+
34
+ .controls {
35
+ width: 16rem;
36
+ flex-shrink: 0;
37
+ max-height: calc(100vh - 2rem);
38
+ overflow-y: auto;
39
+ padding: 1rem;
40
+ background: #f5f5f5;
41
+ border-radius: 8px;
42
+ }
43
+
44
+ .section {
45
+ margin-bottom: 1.5rem;
46
+ }
47
+
48
+ .section h3 {
49
+ margin: 0 0 0.5rem 0;
50
+ font-size: 0.9rem;
51
+ font-weight: bold;
52
+ color: #333;
53
+ border-bottom: 1px solid #ddd;
54
+ padding-bottom: 0.25rem;
55
+ }
56
+
57
+ .option {
58
+ margin-bottom: 0.75rem;
59
+ }
60
+
61
+ .option label {
62
+ display: block;
63
+ font-size: 0.8rem;
64
+ margin-bottom: 0.25rem;
65
+ color: #666;
66
+ }
67
+
68
+ .option fig-slider {
69
+ width: 100%;
70
+ margin-bottom: 0.25rem;
71
+ }
72
+
73
+ .option fig-checkbox {
74
+ margin-right: 0.5rem;
75
+ }
76
+
77
+ .option fig-dropdown {
78
+ width: 100%;
79
+ margin-top: 0.25rem;
80
+ }
81
+
82
+ .value-display {
83
+ font-size: 0.75rem;
84
+ color: #888;
85
+ }
86
+
87
+ .checkbox-option {
88
+ display: flex;
89
+ align-items: center;
90
+ }
91
+
92
+ fig-image {
93
+ --image-size: 14rem !important;
94
+ width: 100%;
95
+ margin-bottom: 1rem;
96
+ position: sticky;
97
+ top: 0;
98
+ z-index: 100;
99
+ background: #f5f5f5;
100
+ }
101
+ </style>
102
+ </head>
103
+
104
+ <body>
105
+ <div class="controls">
106
+ <fig-image upload="true"
107
+ label="Upload image"
108
+ size="large"></fig-image>
109
+
110
+ <div class="section">
111
+ <h3>Presets</h3>
112
+ <div class="option">
113
+ <label for="preset">Select Preset:</label>
114
+ <fig-dropdown id="preset"
115
+ name="preset"
116
+ value="default">
117
+ <option value="default">Default</option>
118
+ <option value="posterized1">Posterized 1</option>
119
+ <option value="posterized2">Posterized 2</option>
120
+ <option value="posterized3">Posterized 3</option>
121
+ <option value="curvy">Curvy</option>
122
+ <option value="sharp">Sharp</option>
123
+ <option value="detailed">Detailed</option>
124
+ <option value="smoothed">Smoothed</option>
125
+ <option value="grayscale">Grayscale</option>
126
+ <option value="fixedpalette">Fixed Palette</option>
127
+ <option value="randomsampling1">Random Sampling 1</option>
128
+ <option value="randomsampling2">Random Sampling 2</option>
129
+ <option value="artistic1">Artistic 1</option>
130
+ <option value="artistic2">Artistic 2</option>
131
+ <option value="artistic3">Artistic 3</option>
132
+ <option value="artistic4">Artistic 4</option>
133
+ </fig-dropdown>
134
+ </div>
135
+ </div>
136
+
137
+ <div class="section">
138
+ <h3>Tracing</h3>
139
+
140
+ <div class="option checkbox-option">
141
+ <fig-checkbox id="corsenabled"
142
+ name="corsenabled"
143
+ label="CORS Enabled"></fig-checkbox>
144
+ </div>
145
+
146
+ <div class="option">
147
+ <label for="ltres">Line Threshold (ltres): <span class="value-display"
148
+ id="ltres-value">1</span></label>
149
+ <fig-slider min="0"
150
+ max="10"
151
+ value="1"
152
+ step="0.01"
153
+ id="ltres"
154
+ name="ltres"></fig-slider>
155
+ </div>
156
+
157
+ <div class="option">
158
+ <label for="qtres">Quadratic Threshold (qtres): <span class="value-display"
159
+ id="qtres-value">1</span></label>
160
+ <fig-slider min="0"
161
+ max="10"
162
+ value="1"
163
+ step="0.01"
164
+ id="qtres"
165
+ name="qtres"></fig-slider>
166
+ </div>
167
+
168
+ <div class="option">
169
+ <label for="pathomit">Path Omit (pathomit): <span class="value-display"
170
+ id="pathomit-value">8</span></label>
171
+ <fig-slider min="0"
172
+ max="100"
173
+ value="8"
174
+ step="1"
175
+ id="pathomit"
176
+ name="pathomit"></fig-slider>
177
+ </div>
178
+
179
+ <div class="option checkbox-option">
180
+ <fig-checkbox id="rightangleenhance"
181
+ name="rightangleenhance"
182
+ checked
183
+ label="Right Angle Enhance"></fig-checkbox>
184
+ </div>
185
+ </div>
186
+
187
+ <div class="section">
188
+ <h3>Color Quantization</h3>
189
+
190
+ <div class="option">
191
+ <label for="colorsampling">Color Sampling: <span class="value-display"
192
+ id="colorsampling-value">2</span></label>
193
+ <fig-slider min="0"
194
+ max="3"
195
+ value="2"
196
+ step="1"
197
+ id="colorsampling"
198
+ name="colorsampling"></fig-slider>
199
+ </div>
200
+
201
+ <div class="option">
202
+ <label for="numberofcolors">Number of Colors: <span class="value-display"
203
+ id="numberofcolors-value">16</span></label>
204
+ <fig-slider min="2"
205
+ max="256"
206
+ value="16"
207
+ step="1"
208
+ id="numberofcolors"
209
+ name="numberofcolors"></fig-slider>
210
+ </div>
211
+
212
+ <div class="option">
213
+ <label for="mincolorratio">Min Color Ratio: <span class="value-display"
214
+ id="mincolorratio-value">0</span></label>
215
+ <fig-slider min="0"
216
+ max="1"
217
+ value="0"
218
+ step="0.01"
219
+ id="mincolorratio"
220
+ name="mincolorratio"></fig-slider>
221
+ </div>
222
+
223
+ <div class="option">
224
+ <label for="colorquantcycles">Color Quant Cycles: <span class="value-display"
225
+ id="colorquantcycles-value">3</span></label>
226
+ <fig-slider min="1"
227
+ max="10"
228
+ value="3"
229
+ step="1"
230
+ id="colorquantcycles"
231
+ name="colorquantcycles"></fig-slider>
232
+ </div>
233
+ </div>
234
+
235
+ <div class="section">
236
+ <h3>SVG Rendering</h3>
237
+
238
+ <div class="option">
239
+ <label for="strokewidth">Stroke Width: <span class="value-display"
240
+ id="strokewidth-value">1</span></label>
241
+ <fig-slider min="0"
242
+ max="10"
243
+ value="1"
244
+ step="0.1"
245
+ id="strokewidth"
246
+ name="strokewidth"></fig-slider>
247
+ </div>
248
+
249
+ <div class="option checkbox-option">
250
+ <fig-checkbox id="linefilter"
251
+ name="linefilter"
252
+ label="Line Filter"></fig-checkbox>
253
+ </div>
254
+
255
+ <div class="option">
256
+ <label for="scale">Scale: <span class="value-display"
257
+ id="scale-value">1</span></label>
258
+ <fig-slider min="0.1"
259
+ max="5"
260
+ value="1"
261
+ step="0.1"
262
+ id="scale"
263
+ name="scale"></fig-slider>
264
+ </div>
265
+
266
+ <div class="option">
267
+ <label for="roundcoords">Round Coords: <span class="value-display"
268
+ id="roundcoords-value">1</span></label>
269
+ <fig-slider min="0"
270
+ max="3"
271
+ value="1"
272
+ step="1"
273
+ id="roundcoords"
274
+ name="roundcoords"></fig-slider>
275
+ </div>
276
+
277
+ <div class="option checkbox-option">
278
+ <fig-checkbox id="viewbox"
279
+ name="viewbox"
280
+ checked
281
+ label="Viewbox"></fig-checkbox>
282
+ </div>
283
+
284
+ <div class="option checkbox-option">
285
+ <fig-checkbox id="desc"
286
+ name="desc"
287
+ label="Description"></fig-checkbox>
288
+ </div>
289
+
290
+ <div class="option">
291
+ <label for="lcpr">LCPR: <span class="value-display"
292
+ id="lcpr-value">0</span></label>
293
+ <fig-slider min="0"
294
+ max="10"
295
+ value="0"
296
+ step="0.1"
297
+ id="lcpr"
298
+ name="lcpr"></fig-slider>
299
+ </div>
300
+
301
+ <div class="option">
302
+ <label for="qcpr">QCPR: <span class="value-display"
303
+ id="qcpr-value">0</span></label>
304
+ <fig-slider min="0"
305
+ max="10"
306
+ value="0"
307
+ step="0.1"
308
+ id="qcpr"
309
+ name="qcpr"></fig-slider>
310
+ </div>
311
+ </div>
312
+
313
+ <div class="section">
314
+ <h3>Blur</h3>
315
+
316
+ <div class="option">
317
+ <label for="blurradius">Blur Radius: <span class="value-display"
318
+ id="blurradius-value">0</span></label>
319
+ <fig-slider min="0"
320
+ max="20"
321
+ value="0"
322
+ step="0.1"
323
+ id="blurradius"
324
+ name="blurradius"></fig-slider>
325
+ </div>
326
+
327
+ <div class="option">
328
+ <label for="blurdelta">Blur Delta: <span class="value-display"
329
+ id="blurdelta-value">20</span></label>
330
+ <fig-slider min="1"
331
+ max="256"
332
+ value="20"
333
+ step="1"
334
+ id="blurdelta"
335
+ name="blurdelta"></fig-slider>
336
+ </div>
337
+ </div>
338
+
339
+ <div class="section">
340
+ <h3>Layering</h3>
341
+
342
+ <div class="option">
343
+ <label for="layering">Layering Method: <span class="value-display"
344
+ id="layering-value">0</span></label>
345
+ <fig-slider min="0"
346
+ max="2"
347
+ value="0"
348
+ step="1"
349
+ id="layering"
350
+ name="layering"></fig-slider>
351
+ </div>
352
+ </div>
353
+ </div>
354
+
355
+ <div id="svg">
356
+ <fig-spinner></fig-spinner>
357
+ </div>
358
+
359
+ <script type="module">
360
+ let options = {
361
+ 'default': {
362
+ // Tracing
363
+ corsenabled: false,
364
+ ltres: 1,
365
+ qtres: 1,
366
+ pathomit: 8,
367
+ rightangleenhance: true,
368
+
369
+ // Color quantization
370
+ colorsampling: 2,
371
+ numberofcolors: 16,
372
+ mincolorratio: 0,
373
+ colorquantcycles: 3,
374
+
375
+ // Layering method
376
+ layering: 0,
377
+
378
+ // SVG rendering
379
+ strokewidth: 1,
380
+ linefilter: false,
381
+ scale: 1,
382
+ roundcoords: 1,
383
+ viewbox: true,
384
+ desc: false,
385
+ lcpr: 0,
386
+ qcpr: 0,
387
+
388
+ // Blur
389
+ blurradius: 0,
390
+ blurdelta: 20
391
+ },
392
+ 'posterized1': { colorsampling: 0, numberofcolors: 2 },
393
+ 'posterized2': { numberofcolors: 4, blurradius: 5 },
394
+ 'curvy': { ltres: 0.01, linefilter: true, rightangleenhance: false },
395
+ 'sharp': { qtres: 0.01, linefilter: false },
396
+ 'detailed': { pathomit: 0, roundcoords: 2, ltres: 0.5, qtres: 0.5, numberofcolors: 64 },
397
+ 'smoothed': { blurradius: 5, blurdelta: 64 },
398
+ 'grayscale': { colorsampling: 0, colorquantcycles: 1, numberofcolors: 7 },
399
+ 'fixedpalette': { colorsampling: 0, colorquantcycles: 1, numberofcolors: 27 },
400
+ 'randomsampling1': { colorsampling: 1, numberofcolors: 8 },
401
+ 'randomsampling2': { colorsampling: 1, numberofcolors: 64 },
402
+ 'artistic1': { colorsampling: 0, colorquantcycles: 1, pathomit: 0, blurradius: 5, blurdelta: 64, ltres: 0.01, linefilter: true, numberofcolors: 16, strokewidth: 2 },
403
+ 'artistic2': { qtres: 0.01, colorsampling: 0, colorquantcycles: 1, numberofcolors: 4, strokewidth: 0 },
404
+ 'artistic3': { qtres: 10, ltres: 10, numberofcolors: 8 },
405
+ 'artistic4': { qtres: 10, ltres: 10, numberofcolors: 64, blurradius: 5, blurdelta: 256, strokewidth: 2 },
406
+ 'posterized3': {
407
+ ltres: 1, qtres: 1, pathomit: 20, rightangleenhance: true, colorsampling: 0, numberofcolors: 3,
408
+ mincolorratio: 0, colorquantcycles: 3, blurradius: 3, blurdelta: 20, strokewidth: 0, linefilter: false,
409
+ roundcoords: 1, pal: [{ r: 0, g: 0, b: 100, a: 255 }, { r: 255, g: 255, b: 255, a: 255 }]
410
+ }
411
+ }
412
+
413
+ // Import imagetracerjs
414
+ import ImageTracer from "https://esm.sh/imagetracerjs";
415
+
416
+ let figImage = document.querySelector("fig-image");
417
+ let currentImageBlob = null;
418
+ let currentOptions = { ...options.default };
419
+
420
+ // Function to update current options from form controls
421
+ function updateCurrentOptions() {
422
+ // Get all form controls - now they are fig.js components
423
+ const sliders = document.querySelectorAll('fig-slider');
424
+ const checkboxes = document.querySelectorAll('fig-checkbox');
425
+
426
+ // Handle sliders
427
+ sliders.forEach(slider => {
428
+ const name = slider.getAttribute('name');
429
+ if (name && currentOptions.hasOwnProperty(name)) {
430
+ currentOptions[name] = parseFloat(slider.value);
431
+ }
432
+ });
433
+
434
+ // Handle checkboxes
435
+ checkboxes.forEach(checkbox => {
436
+ const name = checkbox.getAttribute('name');
437
+ if (name && currentOptions.hasOwnProperty(name)) {
438
+ currentOptions[name] = checkbox.input.checked;
439
+ }
440
+ });
441
+ }
442
+
443
+ // Function to update form controls from current options
444
+ function updateFormControlsFromOptions() {
445
+ const sliders = document.querySelectorAll('fig-slider');
446
+ const checkboxes = document.querySelectorAll('fig-checkbox');
447
+
448
+ // Handle sliders
449
+ sliders.forEach(slider => {
450
+ const name = slider.getAttribute('name');
451
+ if (name && currentOptions.hasOwnProperty(name)) {
452
+ slider.setAttribute('value', currentOptions[name]);
453
+ }
454
+ });
455
+
456
+ // Handle checkboxes
457
+ checkboxes.forEach(checkbox => {
458
+ const name = checkbox.getAttribute('name');
459
+ if (name && currentOptions.hasOwnProperty(name)) {
460
+ if (currentOptions[name]) {
461
+ checkbox.setAttribute('checked', 'true');
462
+ } else {
463
+ checkbox.removeAttribute('checked');
464
+ }
465
+ }
466
+ });
467
+
468
+ updateValueDisplays();
469
+ }
470
+
471
+ // Function to apply a preset
472
+ function applyPreset(presetName) {
473
+ if (!options[presetName]) return;
474
+
475
+ // Reset to default first
476
+ currentOptions = { ...options.default };
477
+
478
+ // Apply preset values
479
+ const preset = options[presetName];
480
+ Object.assign(currentOptions, preset);
481
+
482
+ // Update form controls to reflect new values
483
+ updateFormControlsFromOptions();
484
+
485
+ // Update the preset dropdown
486
+ document.getElementById('preset').setAttribute('value', presetName);
487
+
488
+ // Perform tracing with new options
489
+ performTracing();
490
+ }
491
+
492
+ // Function to update value displays
493
+ function updateValueDisplays() {
494
+ const sliders = document.querySelectorAll('fig-slider');
495
+ sliders.forEach(slider => {
496
+ const valueDisplay = document.getElementById(slider.id + '-value');
497
+ if (valueDisplay) {
498
+ valueDisplay.textContent = slider.value;
499
+ }
500
+ });
501
+ }
502
+
503
+ // Function to perform tracing
504
+ function performTracing() {
505
+ if (!currentImageBlob) return;
506
+
507
+ // Clear existing SVG
508
+ document.getElementById('svg').innerHTML = '';
509
+
510
+ let appendImg = function (svgstr) {
511
+ console.log('SVG generated, updating display');
512
+ document.getElementById('svg').innerHTML = svgstr;
513
+ };
514
+
515
+ console.log('Tracing with options:', currentOptions);
516
+ ImageTracer.imageToSVG(currentImageBlob, appendImg, currentOptions);
517
+ }
518
+
519
+ // Set up event listeners for all controls
520
+ function setupControlListeners() {
521
+ const sliders = document.querySelectorAll('fig-slider');
522
+ const checkboxes = document.querySelectorAll('fig-checkbox');
523
+
524
+ // Handle slider events
525
+ sliders.forEach(slider => {
526
+ slider.addEventListener('input', (e) => {
527
+ updateValueDisplays();
528
+ updateCurrentOptions();
529
+
530
+ // Debounce the tracing to avoid too many calls
531
+ clearTimeout(slider.tracingTimeout);
532
+ slider.tracingTimeout = setTimeout(performTracing, 300);
533
+ });
534
+ });
535
+
536
+ // Handle checkbox events
537
+ checkboxes.forEach(checkbox => {
538
+ checkbox.addEventListener('change', (e) => {
539
+ updateCurrentOptions();
540
+
541
+ // Debounce the tracing to avoid too many calls
542
+ clearTimeout(checkbox.tracingTimeout);
543
+ checkbox.tracingTimeout = setTimeout(performTracing, 300);
544
+ });
545
+ });
546
+
547
+ // Set up preset dropdown listener
548
+ const presetSelect = document.getElementById('preset');
549
+ presetSelect.addEventListener('input', (e) => {
550
+ const selectedPreset = e.target.value;
551
+ applyPreset(selectedPreset);
552
+ });
553
+ }
554
+
555
+ // Initial setup
556
+ updateValueDisplays();
557
+ setupControlListeners();
558
+
559
+ // Handle image upload
560
+ figImage.addEventListener("change", e => {
561
+ console.log('Image uploaded:', figImage.blob);
562
+ currentImageBlob = figImage.blob;
563
+ updateCurrentOptions();
564
+ performTracing();
565
+ });
566
+ </script>
567
+ </body>
568
+
569
+ </html>