@rogieking/figui3 8.11.0 → 9.0.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.
package/README.md CHANGED
@@ -58,7 +58,7 @@ import "@rogieking/figui3/fig-editor.css";
58
58
  import "@rogieking/figui3/fig-editor.js";
59
59
  ```
60
60
 
61
- Opt into experimental Lab and PropsKit components after the core imports:
61
+ Opt into experimental Lab components after the core imports:
62
62
 
63
63
  ```js
64
64
  import "@rogieking/figui3/fig-lab.css";
@@ -76,7 +76,6 @@ Agent skills ship in `.cursor/skills/` (included in the npm package):
76
76
 
77
77
  - `figui3` — core `fig.js` components
78
78
  - `fig-editor` — `fig-select` and `fig-fill-picker`
79
- - `fig-lab` — experimental `propskit-*`, canvas, AI, angle, wheel, reorder
80
79
  - `propkit` — `/propskit` property-row composition
81
80
 
82
81
  Minimal example:
@@ -103,32 +102,10 @@ Minimal example:
103
102
  | [Radio](#radio) | `<fig-radio>` | Radio button |
104
103
  | [Switch](#switch) | `<fig-switch>` | Toggle switch |
105
104
  | [Slider](#slider) | `<fig-slider>` | Range, hue, opacity, delta, stepper |
106
- | [Propskit Slider](#propskit-slider) | `<propskit-slider>` | Labeled slider surface |
107
105
  | [Input Wheel](#input-wheel) | `<fig-input-wheel>` | Standalone SVG tick-and-handle numeric scrubber |
108
- | [Propskit Wheel](#propskit-wheel) | `<propskit-wheel>` | Labeled input wheel with optional number field |
109
- | [Propskit Color](#propskit-color) | `<propskit-color>` | Full-surface labeled color control |
110
- | [Propskit Fill](#propskit-fill) | `<propskit-fill>` | Full-surface labeled fill control |
111
- | [Propskit Gradient](#propskit-gradient) | `<propskit-gradient>` | Full-surface labeled gradient control |
112
- | [Propskit Palette](#propskit-palette) | `<propskit-palette>` | Labeled palette selector |
113
- | [Propskit Image](#propskit-image) | `<propskit-image>` | Labeled image chooser with upload |
114
- | [Propskit Number](#propskit-number) | `<propskit-number>` | Full-surface labeled number control |
115
- | [Propskit Position](#propskit-position) | `<propskit-position>` | Compact X/Y control |
116
- | [Propskit Joystick](#propskit-joystick) | `<propskit-joystick>` | Labeled two-axis joystick |
117
- | [Propskit Origin](#propskit-origin) | `<propskit-origin>` | Labeled transform-origin grid |
118
- | [Propskit Easing](#propskit-easing) | `<propskit-easing>` | Labeled cubic-bezier editor |
119
- | [Propskit Spring](#propskit-spring) | `<propskit-spring>` | Labeled spring editor |
120
- | [Propskit Color Point](#propskit-color-point) | `<propskit-color-point>` | Collapsible color and position group |
121
- | [Propskit Point Point](#propskit-point-point) | `<propskit-point-point>` | Collapsible start and end position group |
122
- | [Propskit Point Radius](#propskit-point-radius) | `<propskit-point-radius>` | Collapsible position and radius group |
123
- | [Propskit Point Radius Angle](#propskit-point-radius-angle) | `<propskit-point-radius-angle>` | Collapsible position, radius, and angle group |
124
- | [Propskit Select](#propskit-select) | `<propskit-select>` | Full-surface labeled select control |
125
- | [Propskit Editable Select](#propskit-editable-select) | `<propskit-editable-select>` | Addable and renameable select control |
126
- | [Propskit Switch](#propskit-switch) | `<propskit-switch>` | Full-surface labeled switch control |
127
- | [Propskit Text](#propskit-text) | `<propskit-text>` | Full-surface labeled text control |
128
106
  | [Text Input](#text-input) | `<fig-input-text>` | Styled text/textarea input |
129
107
  | [Number Input](#number-input) | `<fig-input-number>` | Numeric input with units |
130
108
  | [Input Angle](#input-angle) | `<fig-input-angle>` | Angle/rotation dial and text input |
131
- | [Propskit Oscillator](#propskit-oscillator) | `<propskit-oscillator>` | Waveform oscillator editor |
132
109
  | [Swatch](#swatch) | `<fig-swatch>` | Color/gradient/image swatch |
133
110
  | [Color Tip](#color-tip) | `<fig-color-tip>` | Compact color tip with picker |
134
111
  | [Color Input](#color-input) | `<fig-input-color>` | Color picker with hex/alpha |
@@ -369,329 +346,6 @@ For `type="range"`, omitting `value` follows native range behavior and starts at
369
346
 
370
347
  ---
371
348
 
372
- #### Propskit Number
373
-
374
- `<propskit-number>`
375
-
376
- Uses a plain horizontal surface with `<fig-input-number>`. Number attributes are forwarded to the inner input.
377
-
378
- All PropsKit inputs expose `defaultValue`, `isDefault`, and `resetToDefault()`. A
379
- `propskit-group` uses this shared contract to track its `dirty` state and reset
380
- each nested input to its own current `default`.
381
-
382
- Surface labels default to `"Label"` when omitted; `label=""` removes the visible
383
- label. PropsKit `input` and `change` events dispatch from the outer control with
384
- `detail: { control, value, name? }`, and `event.target.value` is the same typed
385
- value. `name` is included only when a non-empty `name` attribute is authored.
386
- Switch values are boolean. Number, slider, and wheel values are finite numbers
387
- or `null`; structured and
388
- serialized controls expose their exact public `.value`. Select `optionhover`
389
- uses the same envelope. `openchange` and group `reset` keep their semantic
390
- details.
391
-
392
- Shared surface variables are `--propskit-padding-block`,
393
- `--propskit-padding-inline`, `--propskit-background`, `--propskit-border`,
394
- `--propskit-color`, `--propskit-hover-background`, `--propskit-hover-border`,
395
- `--propskit-hover-color`, `--propskit-label-inline-size`, and
396
- `--propskit-input-inline-size`. Override one component with the matching prefix,
397
- such as `--propskit-select-background` or
398
- `--propskit-number-input-inline-size`.
399
-
400
- Nested subfields use `--propskit-bg-subfield` and
401
- `--propskit-color-border-subfield`. Secondary `fig-button` controls inside any
402
- PropsKit component use the same borderless subfield background, including
403
- hover and disabled states.
404
-
405
- | Attribute | Type | Default | Description |
406
- |---|---|---|---|
407
- | `label` | string | `"Label"` | Field label text; use an empty value to hide it |
408
- | `name` | string | — | Optional event payload name |
409
- | `default` | number/string | initial `value` | Right-click reset target |
410
- | `disabled` | boolean | `false` | Disable interaction |
411
- | *number attrs* | — | — | All `<fig-input-number>` attributes are forwarded |
412
-
413
- **Events:** `input`, `change` — shared PropsKit envelope with `value: number | null`.
414
-
415
- Right-click and choose **Reset**, or call `resetToDefault()`, to restore `default` (falling back to the initial value).
416
-
417
- ```html
418
- <propskit-number label="Width" value="24" min="0" max="100" units="px"></propskit-number>
419
- ```
420
-
421
- ---
422
-
423
- #### Propskit Color
424
-
425
- `<propskit-color>`
426
-
427
- Uses a plain horizontal surface with a solid `fig-fill-picker` swatch. Clicking the surface opens the color picker. There is no hex/opacity text field.
428
-
429
- **Attributes:** `label`, `value`, `default`, `alpha`, `disabled`
430
-
431
- **Events:** `input`, `change` — shared PropsKit envelope; `value` is the public color string.
432
-
433
- Right-click and choose **Reset**, or call `resetToDefault()`, to restore `default` or the initial color.
434
-
435
- ```html
436
- <propskit-color label="Background" value="#0D99FF" alpha="true"></propskit-color>
437
- ```
438
-
439
- ---
440
-
441
- #### Propskit Fill
442
-
443
- `<propskit-fill>`
444
-
445
- Uses a plain horizontal surface with a `fig-fill-picker` swatch, sharing chrome with `propskit-color`. Clicking the surface opens the fill picker for solid, gradient, image, video, webcam, and custom modes. There is no hex/opacity text field.
446
-
447
- **Attributes:** `label`, `value` (fill JSON), `default`, `mode`, `alpha`, `webcam-mode`, `default-video`, `disabled`
448
-
449
- **Events:** `input`, `change` — shared PropsKit envelope; `value` is the host's serialized fill value.
450
-
451
- Right-click and choose **Reset**, or call `resetToDefault()`, to restore `default` or the initial fill. Slot `mode-*` children onto the host to add custom picker tabs.
452
-
453
- ```html
454
- <propskit-fill
455
- label="Fill"
456
- value='{"type":"solid","color":"#0D99FF","alpha":1}'
457
- ></propskit-fill>
458
- ```
459
-
460
- ---
461
-
462
- #### Propskit Gradient
463
-
464
- `<propskit-gradient>`
465
-
466
- Uses a plain horizontal surface with `<fig-input-gradient>`. Defaults to `edit="picker"` — click the surface to open the fill picker.
467
-
468
- | Attribute | Type | Default | Description |
469
- |---|---|---|---|
470
- | `label` | string | `"Label"` | Field label text; use an empty value to hide it |
471
- | `value` | JSON string | default gradient | Canonical `{ "type": "gradient", "gradient": { ... } }` data |
472
- | `default` | JSON string | initial `value` | Right-click and group reset target |
473
- | `edit` | boolean/string | `"picker"` | `true` (inline stops), `false`, or `"picker"` |
474
- | `mode` | string | `"handle"` | `"handle"` or `"tip"` stop presentation |
475
- | `disabled` | boolean | `false` | Disabled state |
476
-
477
- **Events:** `input`, `change` — shared PropsKit envelope; `value` is the host's serialized gradient value.
478
-
479
- **Methods and state:** `defaultValue`, `isDefault`, and `resetToDefault()`. JSON defaults use structural equality, so object key order does not affect dirty state.
480
-
481
- Click the field to open the fill picker. With `edit="true"`, the first stop receives focus; Arrow keys move the selected stop, Shift+Arrow moves by 5%, Tab cycles stops, and Delete/Backspace removes a stop while preserving the two-stop minimum.
482
-
483
- ```html
484
- <propskit-gradient
485
- label="Fill"
486
- value='{"type":"gradient","gradient":{"type":"linear","angle":90,"interpolationSpace":"srgb","hueInterpolation":"shorter","stops":[{"position":0,"color":"#0D99FF","opacity":100},{"position":100,"color":"#9747FF","opacity":100}]}}'
487
- default='{"type":"gradient","gradient":{"type":"linear","angle":90,"interpolationSpace":"srgb","hueInterpolation":"shorter","stops":[{"position":0,"color":"#0D99FF","opacity":100},{"position":100,"color":"#9747FF","opacity":100}]}}'
488
- ></propskit-gradient>
489
- ```
490
-
491
- ---
492
-
493
- #### Propskit Palette
494
-
495
- `<propskit-palette>`
496
-
497
- Uses a plain horizontal surface with a selection-only `<fig-input-palette>` preview inside `<fig-select>`. Import `fig-editor.js` and `fig-editor.css`. Clicking anywhere on the surface opens the palette menu.
498
-
499
- `options` is a JSON array of palettes. Each palette accepts color strings or `{ "color", "alpha" }` objects. The first palette is selected when `value` is omitted.
500
-
501
- **Attributes:** `label`, `name`, `value` (palette JSON), `default` (palette JSON), `options`, `disabled`
502
-
503
- **Events:** `input`, `change`, `optionhover` — shared PropsKit envelope with a typed `Array<{ color, alpha }>` value. `optionhover` does not change the selection.
504
-
505
- **Methods and state:** `defaultValue`, `isDefault`, and `resetToDefault()`.
506
-
507
- ```html
508
- <propskit-palette
509
- label="Palette"
510
- options='[["#0D99FF","#14AE5C"],[{"color":"#FFCD29","alpha":0.5},"#F24822"]]'
511
- ></propskit-palette>
512
- ```
513
-
514
- ---
515
-
516
- #### Propskit Image
517
-
518
- `<propskit-image>`
519
-
520
- A vertical PropsKit surface with a label and permanent ghost upload button in
521
- the header. When images exist, it renders a two-column `fig-chooser`; every
522
- choice contains a square, cover-fit `fig-image` and an attachment-style remove
523
- control.
524
-
525
- `options` is an optional JSON array of image URLs. `.options` returns the
526
- normalized URL array, while `.value`, `defaultValue`, and event values are the
527
- selected URL string. An omitted or unmatched value falls back to the first
528
- image.
529
-
530
- Selecting files appends browser object URLs to `options` and selects the first
531
- new image. The component previews local files; applications remain responsible
532
- for uploading and replacing object URLs with durable URLs. Removing an image
533
- updates the reflected `options` array and revokes its object URL when needed.
534
- Removing the selected image falls back to the first remaining image and emits
535
- `input` and `change`; focused choices also support Delete and Backspace.
536
-
537
- **Attributes:** `label`, `name`, `value`, `default`, `options`, `disabled`,
538
- `variant="minimal"`
539
-
540
- **Events:** `input`, `change` — shared PropsKit envelope with the selected URL.
541
-
542
- **Methods and state:** `defaultValue`, `isDefault`, `resetToDefault()`, and
543
- focus delegation to the current choice or upload input.
544
-
545
- ```html
546
- <propskit-image
547
- label="Image"
548
- name="image"
549
- options='["/images/one.webp","/images/two.webp"]'
550
- default="/images/one.webp"
551
- ></propskit-image>
552
- ```
553
-
554
- ---
555
-
556
- #### Propskit Switch
557
-
558
- `<propskit-switch>`
559
-
560
- Uses a plain horizontal surface with `<fig-switch>` by default. The entire
561
- surface toggles the switch. Set `variant="segmented-control"` to render an
562
- Off/On `<fig-segmented-control>` instead.
563
-
564
- **Attributes:** `label`, `checked`, `default`, `disabled`, `name`, `value`, `variant` (`switch` | `segmented-control`)
565
-
566
- **Events:** `input`, `change` — shared PropsKit envelope with the public boolean value.
567
-
568
- Right-click and choose **Reset**, or call `resetToDefault()`, to restore the default checked state.
569
-
570
- ```html
571
- <propskit-switch label="Visible" checked></propskit-switch>
572
- ```
573
-
574
- ---
575
-
576
- #### Propskit Select
577
-
578
- `<propskit-select>`
579
-
580
- Uses a plain horizontal surface and always composes `<fig-select>`. Import `fig-editor.js` and `fig-editor.css`; delayed registration upgrades the authored select. Options can come from the `options` attribute (same formats as `fig-options`: comma-separated, newline-delimited, or a JSON array), or from an authored `<fig-select-options>` child for rich option content.
581
-
582
- **Attributes:** `label`, `value`, `default`, `options`, `disabled`
583
-
584
- **Events:** `input`, `change`, `optionhover` — shared PropsKit envelope. `optionhover` uses the hovered option as `detail.value` without changing the selection.
585
-
586
- Right-click and choose **Reset**, or call `resetToDefault()`, to restore `default` or the initial selection.
587
-
588
- ```html
589
- <propskit-select label="Alignment" value="Center" options="Left,Center,Right"></propskit-select>
590
- ```
591
-
592
- ```html
593
- <propskit-select label="Interpolation" value="srgb">
594
- <fig-select-options slot="panel">
595
- <fig-select-option value="srgb" label="Classic — sRGB Linear">
596
- <div><h3>Classic</h3><span>sRGB Linear</span></div>
597
- </fig-select-option>
598
- </fig-select-options>
599
- </propskit-select>
600
- ```
601
-
602
- ---
603
-
604
- #### Propskit Editable Select
605
-
606
- `<propskit-editable-select>`
607
-
608
- A compact, label-free, subtle `fig-select` aligned to the left at its intrinsic
609
- width inside one full-row PropsKit surface. Default-size secondary edit and add
610
- buttons sit on the right within the same row.
611
- Clicking anywhere on the host opens the select, except the edit and add actions.
612
- The options menu spans and aligns to the full PropsKit row.
613
- Edit replaces the select with a default-size, full-width `fig-input-text`; the
614
- checkmark, Enter, or moving focus outside the input saves, while Escape cancels.
615
- Add creates a choice with an `item-{index}` value using its zero-based array
616
- index and a `"New item"` label, selects it, and immediately
617
- opens rename mode. Every menu
618
- option includes an appended ghost trash action. Delete removes the item;
619
- keyboard users can press Delete or Backspace while its option is focused.
620
- Edit/save, add, and delete icon buttons include descriptive tooltips.
621
-
622
- `options` accepts the same comma, newline, and JSON formats as `fig-select`.
623
- `.options` returns normalized `{ value, label }[]` entries. Add, rename, and
624
- delete mutations reflect this normalized JSON back to `options`. Renaming
625
- changes only the label, preserving the stable selected value. Deleting the
626
- selected item falls forward to the next option, then backward at the end. With
627
- one item remaining, the select and trash action are disabled so the final item
628
- cannot be deleted; edit and add remain available.
629
-
630
- **Attributes:** `name`, `value`, `default`, `options`, `aria-label`, `disabled`
631
-
632
- **Events:** `input`, `change`, `optionhover` — the shared PropsKit envelope is
633
- extended to `{ control, name?, value, label }`. `value` is the stable option
634
- value and `label` is its current display label. Add, delete, and successful
635
- rename actions emit `input` and `change`.
636
-
637
- **Methods and state:** `.options`, `defaultValue`, `isDefault`, `editing`,
638
- `resetToDefault()`, and focus delegation.
639
-
640
- ```html
641
- <propskit-editable-select
642
- aria-label="Layer style"
643
- name="style"
644
- value="primary"
645
- options='[{"value":"primary","label":"Primary"},{"value":"secondary","label":"Secondary"}]'
646
- ></propskit-editable-select>
647
- ```
648
-
649
- ---
650
-
651
- #### Propskit Text
652
-
653
- `<propskit-text>`
654
-
655
- Uses a plain horizontal surface with `<fig-input-text type="text">`. The inner input defaults to `multiline` and `autoresize`, starts at one line, and grows to a maximum of four lines. Set either attribute to `"false"` to disable that behavior. Other text input attributes and adornment slots are forwarded to the inner control; `type` is not forwarded.
656
-
657
- **Attributes:** `label`, `value`, `default`, `placeholder`, `disabled`, `readonly`, `multiline`, `autoresize`
658
-
659
- **Events:** `input`, `change` — shared PropsKit envelope with the public string value.
660
-
661
- Right-click and choose **Reset**, or call `resetToDefault()`, to restore `default` or the initial text.
662
-
663
- ```html
664
- <propskit-text label="Name" value="Layer 1" placeholder="Enter a name"></propskit-text>
665
- ```
666
-
667
- ---
668
-
669
- #### Propskit Slider
670
-
671
- `<propskit-slider>`
672
-
673
- Uses a plain horizontal surface with `<fig-slider>`. Slider attributes except host-only PropsKit attributes are forwarded to the inner slider.
674
-
675
- | Attribute | Type | Default | Description |
676
- |---|---|---|---|
677
- | `label` | string | `"Label"` | Field label text; use an empty value to hide it |
678
- | `name` | string | — | Optional event payload name |
679
- | `default` | number/string | initial `value` | Double-click and right-click reset target |
680
- | `disabled` | boolean | `false` | Disable interaction |
681
- | *slider attrs* | — | — | All `<fig-slider>` attributes except host-only PropsKit attributes are forwarded |
682
-
683
- **Events:** `input`, `change` — shared PropsKit envelope with `value: number | null`.
684
-
685
- Double-click or right-click and choose **Reset** to restore `default`, falling back to the initial value.
686
-
687
- **Methods:** `resetToDefault()` triggers the same reset behavior.
688
-
689
- ```html
690
- <propskit-slider label="Opacity" min="0" max="100" value="75" units="%"></propskit-slider>
691
- ```
692
-
693
- ---
694
-
695
349
  #### Input Wheel
696
350
 
697
351
  `<fig-input-wheel>`
@@ -719,267 +373,6 @@ The `value`, `min`, `max`, and `step` properties mirror their attributes. `aria-
719
373
 
720
374
  ---
721
375
 
722
- #### Propskit Wheel
723
-
724
- `<propskit-wheel>`
725
-
726
- A labeled numeric scrubber that composes `<fig-input-wheel>` with an optional `<fig-input-number>`. The host provides row chrome and reset behavior; there is no `fig-field` or `fig-slider`.
727
-
728
- Omitted `label` renders `"Label"`; `label=""` removes the visible label. Units are omitted by default and arbitrary values such as `px` pass through unchanged. Units remain wrapper and number-field behavior: time aliases receive time-focused defaults, and the effective step is applied to the child wheel without setting a child `units` attribute.
729
-
730
- | Attribute | Type | Default | Description |
731
- |---|---|---|---|
732
- | `label` | string | `"Label"` | Empty removes the visible label |
733
- | `name` | string | — | Optional event payload name |
734
- | `units` | string | — | Optional arbitrary units. `seconds` / `milliseconds` normalize to `s` / `ms` |
735
- | `value` | number | `0` | Numeric value in `units`. Unbounded unless `min`/`max` are set |
736
- | `min` | number | — | Inclusive lower bound. Omit for no minimum |
737
- | `max` | number | — | Inclusive upper bound. Omit for no maximum |
738
- | `step` | number | `1`; `0.1` (`s`) / `100` (`ms`) | Drag, keyboard, and mouse wheel increment |
739
- | `precision` | number | `0`; `2` (`s`) / `0` (`ms`) | Displayed decimal places on the optional number field |
740
- | `elastic` | boolean/string | `true` | Stretch the composed row past the wheel edges; set `"false"` to disable row stretch. The handle still pulls |
741
- | `spin` | boolean/string | `true` | Keep wheel ticks synchronized to `value`; set `"false"` to update only the value and number field |
742
- | `text` | boolean/string | `true` | Include the editable `fig-input-number`; set `"false"` for only `fig-input-wheel` |
743
- | `default` | number/string | initial `value` | Right-click reset target |
744
- | `disabled` | boolean | `false` | Disable wheel and number |
745
-
746
- **Events:** `input` while dragging or typing; `change` on commit. Both use the shared PropsKit envelope with `value: number | null`. Dragging moves by `step` on every `input`; hold Shift to scrub at `10× step`. `precision` only formats the displayed number. Arrow keys on the focused wheel move by `step`; Shift+arrow moves by `10× step`.
747
-
748
- ```html
749
- <propskit-wheel label="Duration" value="1.5" default="0" units="seconds"></propskit-wheel>
750
- <propskit-wheel label="Delay" value="240" default="0" min="0" max="1000" units="ms"></propskit-wheel>
751
- <propskit-wheel label="Frames" value="12" text="false"></propskit-wheel>
752
- <propskit-wheel label="Amount" value="12" spin="false"></propskit-wheel>
753
- ```
754
-
755
- ---
756
-
757
- #### Propskit Position
758
-
759
- `<propskit-position>`
760
-
761
- A compact X/Y field with optional percentage units.
762
-
763
- | Attribute | Type | Default | Description |
764
- |---|---|---|---|
765
- | `x` | number | `50` | Horizontal value |
766
- | `y` | number | `50` | Vertical value |
767
- | `default` | JSON string | initial `{ x, y }` | Right-click and group reset target |
768
- | `label` | string | `"Label"` | Field label; empty removes the visible label |
769
- | `units` | string | — | `"percent"` shows `%`; omit for no units |
770
- | `disabled` | boolean | `false` | Disable both number inputs |
771
-
772
- **Properties and methods:** `x`, `y`, and `value` expose the current coordinates; `defaultValue` returns the normalized reset object; `isDefault` compares both coordinates; `resetToDefault()` restores both values.
773
-
774
- **Events:** `input` and `change` use the shared PropsKit envelope with the public `{ x, y, units }` value.
775
-
776
- ```html
777
- <propskit-position
778
- label="Position"
779
- x="50"
780
- y="50"
781
- units="percent"
782
- default='{"x":50,"y":50}'
783
- ></propskit-position>
784
- ```
785
-
786
- ---
787
-
788
- #### Propskit Joystick
789
-
790
- `<propskit-joystick>`
791
-
792
- A vertical PropsKit surface with a label above a square `fig-joystick` and its X/Y percentage fields.
793
-
794
- | Attribute | Type | Default | Description |
795
- |---|---|---|---|
796
- | `value` | JSON string | `{"x":50,"y":50}` | Current percentage coordinates |
797
- | `default` | JSON string | initial value | Right-click and group reset target |
798
- | `label` | string | `"Label"` | Field label; empty removes the visible label |
799
- | `axis-labels` | string | — | One, two, or four labels forwarded to the joystick |
800
- | `coordinates` | string | `"screen"` | `"screen"` or `"math"` coordinate mode |
801
- | `precision` | number | `3` | X/Y field display precision |
802
- | `disabled` | boolean | `false` | Disable the joystick and both fields |
803
-
804
- The inner joystick always uses `fields="true"` and `aspect-ratio="1 / 1"`. The `.value`, `defaultValue`, and event values are typed `{ x, y }` percentage objects. `isDefault` compares both axes and `resetToDefault()` restores the reset value.
805
-
806
- ```html
807
- <propskit-joystick
808
- label="Position"
809
- value='{"x":35,"y":65}'
810
- default='{"x":50,"y":50}'
811
- axis-labels="X Y"
812
- ></propskit-joystick>
813
- ```
814
-
815
- ---
816
-
817
- #### Propskit Origin
818
-
819
- `<propskit-origin>`
820
-
821
- A vertical PropsKit surface with a label above a square `fig-origin-grid` and its X/Y percentage fields. The inner grid always uses `fields="true"` and `aspect-ratio="1 / 1"`.
822
-
823
- Its `.value`, `defaultValue`, and event values are typed `{ x, y }` objects. The `value` and `default` attributes serialize that shape as JSON. `precision` and `drag` pass through to the grid.
824
-
825
- ```html
826
- <propskit-origin
827
- label="Transform origin"
828
- value='{"x":50,"y":50}'
829
- default='{"x":50,"y":50}'
830
- ></propskit-origin>
831
- ```
832
-
833
- ---
834
-
835
- #### Propskit Easing
836
-
837
- `<propskit-easing>`
838
-
839
- A vertical PropsKit surface around `fig-easing-curve`, constrained to cubic-bezier presets. Its typed value is `{ x1, y1, x2, y2 }`; `value` and `default` serialize that shape as JSON.
840
-
841
- ```html
842
- <propskit-easing
843
- label="Easing"
844
- value='{"x1":0.42,"y1":0,"x2":0.58,"y2":1}'
845
- default='{"x1":0.42,"y1":0,"x2":0.58,"y2":1}'
846
- ></propskit-easing>
847
- ```
848
-
849
- ---
850
-
851
- #### Propskit Spring
852
-
853
- `<propskit-spring>`
854
-
855
- A vertical PropsKit surface around `fig-easing-curve`, constrained to spring presets. Its typed value is `{ stiffness, damping, mass }`; `value` and `default` serialize that shape as JSON.
856
-
857
- ```html
858
- <propskit-spring
859
- label="Spring"
860
- value='{"stiffness":200,"damping":15,"mass":1}'
861
- default='{"stiffness":200,"damping":15,"mass":1}'
862
- ></propskit-spring>
863
- ```
864
-
865
- Both curve controls forward `precision` and `edit`, support `disabled` and `variant="minimal"`, expose `isDefault`, and implement `resetToDefault()`. Their `input` and `change` events use the shared PropsKit envelope.
866
-
867
- ---
868
-
869
- #### Propskit Color Point
870
-
871
- `<propskit-color-point>`
872
-
873
- A compact `<fig-group>` wrapper that combines `<propskit-color>` and `<propskit-position>`. The group is collapsible and open by default.
874
-
875
- | Attribute | Type | Default | Description |
876
- |---|---|---|---|
877
- | `label` | string | — | Passed to the internal `fig-group` as `name` |
878
- | `value` | JSON string | `{"x":50,"y":50,"color":"#D9D9D9"}` | Current color-point value |
879
- | `collapsible` | boolean | `true` | Passed to the internal `fig-group` |
880
- | `open` | boolean | `true` | Passed to the internal `fig-group` |
881
- | `disabled` | boolean | `false` | Disable both internal controls |
882
-
883
- The internal group always has `compact`. `value` uses the same `{ x, y, color }` shape as `<fig-canvas-control type="color">`.
884
-
885
- **Events:** `input` and `change` use the shared PropsKit envelope with the public color-point value. `openchange` mirrors the internal group's expanded state.
886
-
887
- ```html
888
- <propskit-color-point
889
- label="Light"
890
- value='{"x":50,"y":50,"color":"#FF00BF"}'
891
- ></propskit-color-point>
892
- ```
893
-
894
- ---
895
-
896
- #### Propskit Point Radius
897
-
898
- `<propskit-point-radius>`
899
-
900
- A compact `<fig-group>` wrapper that combines `<propskit-position>` and `<propskit-number>` for point-radius values. The group is collapsible and open by default.
901
-
902
- | Attribute | Type | Default | Description |
903
- |---|---|---|---|
904
- | `label` | string | — | Passed to the internal `fig-group` as `name` |
905
- | `value` | JSON string | `{"x":50,"y":50,"radius":0}` | Current point-radius value |
906
- | `collapsible` | boolean | `true` | Passed to the internal `fig-group` |
907
- | `open` | boolean | `true` | Passed to the internal `fig-group` |
908
- | `units` | string | — | `"percent"` passes percentage units to position and radius; omit for no units |
909
- | `disabled` | boolean | `false` | Disable both internal controls |
910
-
911
- The internal group always has `compact`. `value` uses the same `{ x, y, radius }` shape as `<fig-canvas-control type="point-radius">`. Numeric radius values use pixels; percentage strings preserve `%`.
912
-
913
- **Events:** `input` and `change` use the shared PropsKit envelope with the public point-radius value. `openchange` mirrors the internal group's expanded state.
914
-
915
- ```html
916
- <propskit-point-radius
917
- label="Blur"
918
- units="percent"
919
- value='{"x":50,"y":50,"radius":"25%"}'
920
- ></propskit-point-radius>
921
- ```
922
-
923
- ---
924
-
925
- #### Propskit Point Radius Angle
926
-
927
- `<propskit-point-radius-angle>`
928
-
929
- A compact `<fig-group>` wrapper combining `<propskit-position>` with radius and angle `<propskit-number>` controls. The group is collapsible and open by default.
930
-
931
- | Attribute | Type | Default | Description |
932
- |---|---|---|---|
933
- | `label` | string | — | Passed to the internal `fig-group` as `name` |
934
- | `value` | JSON string | `{"x":50,"y":50,"radius":0,"angle":0}` | Current point-radius-angle value |
935
- | `collapsible` | boolean | `true` | Passed to the internal `fig-group` |
936
- | `open` | boolean | `true` | Passed to the internal `fig-group` |
937
- | `units` | string | — | `"percent"` passes percentage units to position and radius; omit for no units |
938
- | `disabled` | boolean | `false` | Disable every internal control |
939
-
940
- The internal group always has `compact`. `value` uses the same `{ x, y, radius, angle }` shape as `<fig-canvas-control type="point-radius-angle">`. Numeric radius values use pixels; percentage strings preserve `%`. Angles are degrees.
941
-
942
- **Events:** `input` and `change` use the shared PropsKit envelope with the public point-radius-angle value. `openchange` mirrors the internal group's expanded state.
943
-
944
- ```html
945
- <propskit-point-radius-angle
946
- label="Gradient"
947
- units="percent"
948
- value='{"x":50,"y":50,"radius":"25%","angle":45}'
949
- ></propskit-point-radius-angle>
950
- ```
951
-
952
- ---
953
-
954
- #### Propskit Point Point
955
-
956
- `<propskit-point-point>`
957
-
958
- A compact `<fig-group>` wrapper combining start and end `<propskit-position>` controls. The group is collapsible and open by default.
959
-
960
- | Attribute | Type | Default | Description |
961
- |---|---|---|---|
962
- | `label` | string | — | Passed to the internal `fig-group` as `name` |
963
- | `value` | JSON string | `{"x":50,"y":50,"x2":75,"y2":75}` | Current point-point value |
964
- | `collapsible` | boolean | `true` | Passed to the internal `fig-group` |
965
- | `open` | boolean | `true` | Passed to the internal `fig-group` |
966
- | `units` | string | — | `"percent"` passes percentage units to both positions; omit for no units |
967
- | `disabled` | boolean | `false` | Disable both position controls |
968
-
969
- The internal group always has `compact`. `value` uses the same `{ x, y, x2, y2 }` shape as `<fig-canvas-control type="point-point">`.
970
-
971
- **Events:** `input` and `change` use the shared PropsKit envelope with the public point-point value. `openchange` mirrors the internal group's expanded state.
972
-
973
- ```html
974
- <propskit-point-point
975
- label="Gradient"
976
- units="percent"
977
- value='{"x":25,"y":25,"x2":75,"y2":75}'
978
- ></propskit-point-point>
979
- ```
980
-
981
- ---
982
-
983
376
  #### Text Input
984
377
 
985
378
  `<fig-input-text>` — [demo](https://rog.ie/figui3/#text-input)
@@ -1058,43 +451,6 @@ Angle/rotation input with circular dial, optional text input, multi-unit support
1058
451
 
1059
452
  ---
1060
453
 
1061
- #### Propskit Oscillator
1062
-
1063
- `<propskit-oscillator>`
1064
-
1065
- Waveform oscillator input with composable wave functions, live SVG waveform preview, draggable parameter handles, and direct numeric controls.
1066
-
1067
- | Attribute | Type | Default | Description |
1068
- |---|---|---|---|
1069
- | `value` | JSON string | — | `{"waves":[{"type":"sine","frequency":1,"amplitude":1,"phase":0,"offset":0}]}` |
1070
- | `name` | string | — | Optional event payload name |
1071
- | `default` | JSON string | initial `value` | Right-click reset target |
1072
- | `precision` | number | `2` | Decimal places |
1073
- | `aspect-ratio` | string | `"2 / 1"` | Editor aspect ratio |
1074
- | `edit` | boolean | `true` | Show editor and number fields; set to `"false"` for preview only |
1075
- | `disabled` | boolean | `false` | Disable interaction |
1076
-
1077
- Supported `type` values: `"sine"`, `"square"`, `"sawtooth"`, `"triangle"`.
1078
-
1079
- **Properties:** `value` returns a normalized JSON string. `data` returns `{ waves }`. Single-wave JSON values are still accepted and normalized into `waves`.
1080
-
1081
- Right-click and choose **Reset**, or call `resetToDefault()`, to restore the oscillator value.
1082
-
1083
- **Events:**
1084
-
1085
- | Event | Detail |
1086
- |---|---|
1087
- | `input` | Shared PropsKit `{ control, value, name? }` envelope while dragging or editing |
1088
- | `change` | Shared PropsKit `{ control, value, name? }` envelope on release or committed edit |
1089
-
1090
- ```html
1091
- <propskit-oscillator
1092
- value='{"waves":[{"type":"sine","frequency":1,"amplitude":1,"phase":0,"offset":0},{"type":"triangle","frequency":2,"amplitude":0.5,"phase":0,"offset":0}]}'
1093
- ></propskit-oscillator>
1094
- ```
1095
-
1096
- ---
1097
-
1098
454
  ### Color & Fill
1099
455
 
1100
456
  #### Swatch