@rogieking/figui3 8.9.49 → 8.10.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
@@ -103,14 +103,19 @@ Minimal example:
103
103
  | [Radio](#radio) | `<fig-radio>` | Radio button |
104
104
  | [Switch](#switch) | `<fig-switch>` | Toggle switch |
105
105
  | [Slider](#slider) | `<fig-slider>` | Range, hue, opacity, delta, stepper |
106
- | [Propskit Slider](#propskit-slider) | `<propskit-slider>` | Labeled field + slider combo |
106
+ | [Propskit Slider](#propskit-slider) | `<propskit-slider>` | Labeled slider surface |
107
107
  | [Input Wheel](#input-wheel) | `<fig-input-wheel>` | Standalone SVG tick-and-handle numeric scrubber |
108
108
  | [Propskit Wheel](#propskit-wheel) | `<propskit-wheel>` | Labeled input wheel with optional number field |
109
109
  | [Propskit Color](#propskit-color) | `<propskit-color>` | Full-surface labeled color control |
110
110
  | [Propskit Fill](#propskit-fill) | `<propskit-fill>` | Full-surface labeled fill control |
111
111
  | [Propskit Gradient](#propskit-gradient) | `<propskit-gradient>` | Full-surface labeled gradient control |
112
+ | [Propskit Palette](#propskit-palette) | `<propskit-palette>` | Labeled palette selector |
112
113
  | [Propskit Number](#propskit-number) | `<propskit-number>` | Full-surface labeled number control |
113
114
  | [Propskit Position](#propskit-position) | `<propskit-position>` | Compact X/Y control |
115
+ | [Propskit Joystick](#propskit-joystick) | `<propskit-joystick>` | Labeled two-axis joystick |
116
+ | [Propskit Origin](#propskit-origin) | `<propskit-origin>` | Labeled transform-origin grid |
117
+ | [Propskit Easing](#propskit-easing) | `<propskit-easing>` | Labeled cubic-bezier editor |
118
+ | [Propskit Spring](#propskit-spring) | `<propskit-spring>` | Labeled spring editor |
114
119
  | [Propskit Color Point](#propskit-color-point) | `<propskit-color-point>` | Collapsible color and position group |
115
120
  | [Propskit Point Point](#propskit-point-point) | `<propskit-point-point>` | Collapsible start and end position group |
116
121
  | [Propskit Point Radius](#propskit-point-radius) | `<propskit-point-radius>` | Collapsible position and radius group |
@@ -231,11 +236,12 @@ Custom listbox select with overflow chevrons, grouped options, and sticky separa
231
236
  | `label` | string | — | Closed-state / accessible label |
232
237
  | `options` | string | — | Comma, newline, or JSON options if no authored `fig-select-option` children |
233
238
  | `variant` | string | — | `"ghost"` for a borderless control with secondary hover fill |
239
+ | `subtle` | boolean | `false` | Use the secondary hover/focus fill for every option |
234
240
  | `full` | boolean | `false` | Stretch to available width |
235
241
  | `position` | string | `"bottom left"` | Popup position |
236
242
  | `disabled` | boolean | `false` | Disabled state |
237
243
 
238
- Author options in `<fig-select-options>`, or pass `options`. Use `label` on `<fig-select-option>` when the option content is rich. `fig-separator` with `sticky` pins group labels while scrolling.
244
+ Author options in `<fig-select-options>`, or pass `options`. Add `subtle` to one `<fig-select-option>` for the secondary hover/focus fill, or to `<fig-select>` to apply it to every option. Use `label` on `<fig-select-option>` when the option content is rich. `fig-separator` with `sticky` pins group labels while scrolling.
239
245
 
240
246
  ```html
241
247
  <fig-select value="center" label="Align">
@@ -359,36 +365,45 @@ Author options in `<fig-select-options>`, or pass `options`. Use `label` on `<fi
359
365
 
360
366
  For `type="range"`, omitting `value` follows native range behavior and starts at the midpoint of `min` and `max`. Arrow keys move by `step`; hold Shift to move by a larger step.
361
367
 
362
- Full-surface `propskit-*` controls support `variant="minimal"`. The minimal variant removes vertical row padding and keeps the field background transparent until hover. It is available on switch, color, fill, gradient, select, text, number, slider, position, and wheel controls.
363
-
364
368
  ---
365
369
 
366
370
  #### Propskit Number
367
371
 
368
372
  `<propskit-number>`
369
373
 
370
- Composes a `<fig-field>` and `<fig-input-number>` into a full-surface property control. Number attributes are forwarded to the inner input.
371
-
372
- PropsKit controls use the 40px large layout when `size` is omitted. Set
373
- `size="small"` for the compact 32px row layout. Explicit `size="large"`
374
- remains supported as an alias for the default layout.
374
+ Uses a plain horizontal surface with `<fig-input-number>`. Number attributes are forwarded to the inner input.
375
375
 
376
376
  All PropsKit inputs expose `defaultValue`, `isDefault`, and `resetToDefault()`. A
377
377
  `propskit-group` uses this shared contract to track its `dirty` state and reset
378
- each nested input to its own current `default`. Set `size="small"` on a
379
- `propskit-group` to apply the compact layout to nested controls that do not
380
- define their own size.
378
+ each nested input to its own current `default`.
379
+
380
+ Surface labels default to `"Label"` when omitted; `label=""` removes the visible
381
+ label. PropsKit `input` and `change` events dispatch from the outer control with
382
+ `detail: { control, value, name? }`, and `event.target.value` is the same typed
383
+ value. `name` is included only when a non-empty `name` attribute is authored.
384
+ Switch values are boolean. Number, slider, and wheel values are finite numbers
385
+ or `null`; structured and
386
+ serialized controls expose their exact public `.value`. Select `optionhover`
387
+ uses the same envelope. `openchange` and group `reset` keep their semantic
388
+ details.
389
+
390
+ Shared surface variables are `--propskit-padding-block`,
391
+ `--propskit-padding-inline`, `--propskit-background`, `--propskit-border`,
392
+ `--propskit-color`, `--propskit-hover-background`, `--propskit-hover-border`,
393
+ `--propskit-hover-color`, `--propskit-label-inline-size`, and
394
+ `--propskit-input-inline-size`. Override one component with the matching prefix,
395
+ such as `--propskit-select-background` or
396
+ `--propskit-number-input-inline-size`.
381
397
 
382
398
  | Attribute | Type | Default | Description |
383
399
  |---|---|---|---|
384
400
  | `label` | string | `"Label"` | Field label text; use an empty value to hide it |
385
- | `direction` | string | `"horizontal"` | Field layout direction |
386
- | `size` | string | default | Set to `"small"` for the compact layout |
401
+ | `name` | string | | Optional event payload name |
387
402
  | `default` | number/string | initial `value` | Right-click reset target |
388
403
  | `disabled` | boolean | `false` | Disable interaction |
389
404
  | *number attrs* | — | — | All `<fig-input-number>` attributes are forwarded |
390
405
 
391
- **Events:** `input`, `change` — forwarded from the inner number input.
406
+ **Events:** `input`, `change` — shared PropsKit envelope with `value: number | null`.
392
407
 
393
408
  Right-click and choose **Reset**, or call `resetToDefault()`, to restore `default` (falling back to the initial value).
394
409
 
@@ -402,11 +417,11 @@ Right-click and choose **Reset**, or call `resetToDefault()`, to restore `defaul
402
417
 
403
418
  `<propskit-color>`
404
419
 
405
- Composes a `<fig-field>` and a solid `fig-fill-picker` swatch into a full-surface property control. Clicking the field opens the color picker. There is no hex/opacity text field.
420
+ 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.
406
421
 
407
- **Attributes:** `label`, `value`, `default`, `alpha`, `disabled`, `size`
422
+ **Attributes:** `label`, `value`, `default`, `alpha`, `disabled`
408
423
 
409
- **Events:** `input`, `change` — `{ color, alpha, opacity }` from the fill picker.
424
+ **Events:** `input`, `change` — shared PropsKit envelope; `value` is the public color string.
410
425
 
411
426
  Right-click and choose **Reset**, or call `resetToDefault()`, to restore `default` or the initial color.
412
427
 
@@ -420,11 +435,11 @@ Right-click and choose **Reset**, or call `resetToDefault()`, to restore `defaul
420
435
 
421
436
  `<propskit-fill>`
422
437
 
423
- Composes a `<fig-field>` and a `fig-fill-picker` swatch into a full-surface property control, same chrome as `propskit-color`. Clicking the field opens the fill picker for solid, gradient, image, video, webcam, and custom modes. There is no hex/opacity text field.
438
+ 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.
424
439
 
425
- **Attributes:** `label`, `value` (fill JSON), `default`, `mode`, `alpha`, `webcam-mode`, `default-video`, `disabled`, `size`
440
+ **Attributes:** `label`, `value` (fill JSON), `default`, `mode`, `alpha`, `webcam-mode`, `default-video`, `disabled`
426
441
 
427
- **Events:** `input`, `change` — fill object in `event.detail` (`{ type, ... }`).
442
+ **Events:** `input`, `change` — shared PropsKit envelope; `value` is the host's serialized fill value.
428
443
 
429
444
  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.
430
445
 
@@ -441,7 +456,7 @@ Right-click and choose **Reset**, or call `resetToDefault()`, to restore `defaul
441
456
 
442
457
  `<propskit-gradient>`
443
458
 
444
- Composes a `<fig-field>` and `<fig-input-gradient>` into a full-surface property control. Defaults to `edit="picker"` — click the field to open the fill picker.
459
+ Uses a plain horizontal surface with `<fig-input-gradient>`. Defaults to `edit="picker"` — click the surface to open the fill picker.
445
460
 
446
461
  | Attribute | Type | Default | Description |
447
462
  |---|---|---|---|
@@ -451,9 +466,8 @@ Composes a `<fig-field>` and `<fig-input-gradient>` into a full-surface property
451
466
  | `edit` | boolean/string | `"picker"` | `true` (inline stops), `false`, or `"picker"` |
452
467
  | `mode` | string | `"handle"` | `"handle"` or `"tip"` stop presentation |
453
468
  | `disabled` | boolean | `false` | Disabled state |
454
- | `size` | string | default | Set to `"small"` for the compact layout |
455
469
 
456
- **Events:** `input`, `change` — bubbling, composed events with `{ type: "gradient", gradient }` in `event.detail`.
470
+ **Events:** `input`, `change` — shared PropsKit envelope; `value` is the host's serialized gradient value.
457
471
 
458
472
  **Methods and state:** `defaultValue`, `isDefault`, and `resetToDefault()`. JSON defaults use structural equality, so object key order does not affect dirty state.
459
473
 
@@ -469,15 +483,40 @@ Click the field to open the fill picker. With `edit="true"`, the first stop rece
469
483
 
470
484
  ---
471
485
 
486
+ #### Propskit Palette
487
+
488
+ `<propskit-palette>`
489
+
490
+ 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.
491
+
492
+ `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.
493
+
494
+ **Attributes:** `label`, `name`, `value` (palette JSON), `default` (palette JSON), `options`, `disabled`
495
+
496
+ **Events:** `input`, `change`, `optionhover` — shared PropsKit envelope with a typed `Array<{ color, alpha }>` value. `optionhover` does not change the selection.
497
+
498
+ **Methods and state:** `defaultValue`, `isDefault`, and `resetToDefault()`.
499
+
500
+ ```html
501
+ <propskit-palette
502
+ label="Palette"
503
+ options='[["#0D99FF","#14AE5C"],[{"color":"#FFCD29","alpha":0.5},"#F24822"]]'
504
+ ></propskit-palette>
505
+ ```
506
+
507
+ ---
508
+
472
509
  #### Propskit Switch
473
510
 
474
511
  `<propskit-switch>`
475
512
 
476
- Composes a `<fig-field>` and an Off/On `<fig-segmented-control>` into a full-surface boolean property control.
513
+ Uses a plain horizontal surface with `<fig-switch>` by default. The entire
514
+ surface toggles the switch. Set `variant="segmented-control"` to render an
515
+ Off/On `<fig-segmented-control>` instead.
477
516
 
478
- **Attributes:** `label`, `checked`, `default`, `disabled`, `name`, `value`, `size`
517
+ **Attributes:** `label`, `checked`, `default`, `disabled`, `name`, `value`, `variant` (`switch` | `segmented-control`)
479
518
 
480
- **Events:** `input`, `change` — forwarded from the inner switch.
519
+ **Events:** `input`, `change` — shared PropsKit envelope with the public boolean value.
481
520
 
482
521
  Right-click and choose **Reset**, or call `resetToDefault()`, to restore the default checked state.
483
522
 
@@ -491,11 +530,11 @@ Right-click and choose **Reset**, or call `resetToDefault()`, to restore the def
491
530
 
492
531
  `<propskit-select>`
493
532
 
494
- Composes a `<fig-field>` and `<fig-select>` into a full-surface property control. Requires `fig-editor.js` (which registers `fig-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.
533
+ 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.
495
534
 
496
- **Attributes:** `label`, `value`, `default`, `options`, `disabled`, `size`
535
+ **Attributes:** `label`, `value`, `default`, `options`, `disabled`
497
536
 
498
- **Events:** `input`, `change`, `optionhover` — forwarded from the inner select. `optionhover` fires once when the pointer enters an enabled option, with the option value in `event.detail`, without changing the selection.
537
+ **Events:** `input`, `change`, `optionhover` — shared PropsKit envelope. `optionhover` uses the hovered option as `detail.value` without changing the selection.
499
538
 
500
539
  Right-click and choose **Reset**, or call `resetToDefault()`, to restore `default` or the initial selection.
501
540
 
@@ -519,11 +558,11 @@ Right-click and choose **Reset**, or call `resetToDefault()`, to restore `defaul
519
558
 
520
559
  `<propskit-text>`
521
560
 
522
- Composes a `<fig-field>` and `<fig-input-text>` into a full-surface, single-line property control. Text input attributes and adornment slots are forwarded to the inner control.
561
+ 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.
523
562
 
524
- **Attributes:** `label`, `value`, `default`, `placeholder`, `type`, `disabled`, `readonly`, `autoresize`, `size`
563
+ **Attributes:** `label`, `value`, `default`, `placeholder`, `disabled`, `readonly`, `multiline`, `autoresize`
525
564
 
526
- **Events:** `input`, `change` — forwarded from the inner text input.
565
+ **Events:** `input`, `change` — shared PropsKit envelope with the public string value.
527
566
 
528
567
  Right-click and choose **Reset**, or call `resetToDefault()`, to restore `default` or the initial text.
529
568
 
@@ -537,18 +576,17 @@ Right-click and choose **Reset**, or call `resetToDefault()`, to restore `defaul
537
576
 
538
577
  `<propskit-slider>`
539
578
 
540
- Wraps a `<fig-field>` and `<fig-slider>` into a single labeled control. All slider attributes (except `label`, `direction`) are forwarded to the inner slider.
579
+ Uses a plain horizontal surface with `<fig-slider>`. Slider attributes except host-only PropsKit attributes are forwarded to the inner slider.
541
580
 
542
581
  | Attribute | Type | Default | Description |
543
582
  |---|---|---|---|
544
- | `label` | string | | Field label text |
545
- | `direction` | string | `"column"` | Layout direction |
546
- | `size` | string | default | Set to `"small"` for the compact layout |
583
+ | `label` | string | `"Label"` | Field label text; use an empty value to hide it |
584
+ | `name` | string | | Optional event payload name |
547
585
  | `default` | number/string | initial `value` | Double-click and right-click reset target |
548
586
  | `disabled` | boolean | `false` | Disable interaction |
549
587
  | *slider attrs* | — | — | All `<fig-slider>` attributes except host-only PropsKit attributes are forwarded |
550
588
 
551
- **Events:** `input`, `change` — forwarded from the inner slider.
589
+ **Events:** `input`, `change` — shared PropsKit envelope with `value: number | null`.
552
590
 
553
591
  Double-click or right-click and choose **Reset** to restore `default`, falling back to the initial value.
554
592
 
@@ -593,11 +631,12 @@ The `value`, `min`, `max`, and `step` properties mirror their attributes. `aria-
593
631
 
594
632
  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`.
595
633
 
596
- Omitted `label` renders `"Value"`. If `label` is set, including `label=""`, that exact value is used. 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.
634
+ 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.
597
635
 
598
636
  | Attribute | Type | Default | Description |
599
637
  |---|---|---|---|
600
- | `label` | string | `"Value"` when omitted | Authored values (including blank) are used as-is |
638
+ | `label` | string | `"Label"` | Empty removes the visible label |
639
+ | `name` | string | — | Optional event payload name |
601
640
  | `units` | string | — | Optional arbitrary units. `seconds` / `milliseconds` normalize to `s` / `ms` |
602
641
  | `value` | number | `0` | Numeric value in `units`. Unbounded unless `min`/`max` are set |
603
642
  | `min` | number | — | Inclusive lower bound. Omit for no minimum |
@@ -607,12 +646,10 @@ Omitted `label` renders `"Value"`. If `label` is set, including `label=""`, that
607
646
  | `elastic` | boolean/string | `true` | Stretch the composed row past the wheel edges; set `"false"` to disable row stretch. The handle still pulls |
608
647
  | `spin` | boolean/string | `true` | Keep wheel ticks synchronized to `value`; set `"false"` to update only the value and number field |
609
648
  | `text` | boolean/string | `true` | Include the editable `fig-input-number`; set `"false"` for only `fig-input-wheel` |
610
- | `size` | string | default | Set to `"small"` for the compact layout |
611
649
  | `default` | number/string | initial `value` | Right-click reset target |
612
650
  | `disabled` | boolean | `false` | Disable wheel and number |
613
- | `variant` | string | — | `"minimal"` removes vertical padding |
614
651
 
615
- **Events:** `input` while dragging or typing; `change` on commit. 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`.
652
+ **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`.
616
653
 
617
654
  ```html
618
655
  <propskit-wheel label="Duration" value="1.5" default="0" units="seconds"></propskit-wheel>
@@ -634,14 +671,13 @@ A compact X/Y field with optional percentage units.
634
671
  | `x` | number | `50` | Horizontal value |
635
672
  | `y` | number | `50` | Vertical value |
636
673
  | `default` | JSON string | initial `{ x, y }` | Right-click and group reset target |
637
- | `label` | string | `"Position"` | Field label; empty values use the semantic default |
674
+ | `label` | string | `"Label"` | Field label; empty removes the visible label |
638
675
  | `units` | string | — | `"percent"` shows `%`; omit for no units |
639
- | `size` | string | default | Set to `"small"` for the compact row |
640
676
  | `disabled` | boolean | `false` | Disable both number inputs |
641
677
 
642
678
  **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.
643
679
 
644
- **Events:** `input` and `change` bubble across shadow boundaries with numeric `{ x, y, units }` in `event.detail`.
680
+ **Events:** `input` and `change` use the shared PropsKit envelope with the public `{ x, y, units }` value.
645
681
 
646
682
  ```html
647
683
  <propskit-position
@@ -655,6 +691,87 @@ A compact X/Y field with optional percentage units.
655
691
 
656
692
  ---
657
693
 
694
+ #### Propskit Joystick
695
+
696
+ `<propskit-joystick>`
697
+
698
+ A vertical PropsKit surface with a label above a square `fig-joystick` and its X/Y percentage fields.
699
+
700
+ | Attribute | Type | Default | Description |
701
+ |---|---|---|---|
702
+ | `value` | JSON string | `{"x":50,"y":50}` | Current percentage coordinates |
703
+ | `default` | JSON string | initial value | Right-click and group reset target |
704
+ | `label` | string | `"Label"` | Field label; empty removes the visible label |
705
+ | `axis-labels` | string | — | One, two, or four labels forwarded to the joystick |
706
+ | `coordinates` | string | `"screen"` | `"screen"` or `"math"` coordinate mode |
707
+ | `precision` | number | `3` | X/Y field display precision |
708
+ | `disabled` | boolean | `false` | Disable the joystick and both fields |
709
+
710
+ 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.
711
+
712
+ ```html
713
+ <propskit-joystick
714
+ label="Position"
715
+ value='{"x":35,"y":65}'
716
+ default='{"x":50,"y":50}'
717
+ axis-labels="X Y"
718
+ ></propskit-joystick>
719
+ ```
720
+
721
+ ---
722
+
723
+ #### Propskit Origin
724
+
725
+ `<propskit-origin>`
726
+
727
+ 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"`.
728
+
729
+ 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.
730
+
731
+ ```html
732
+ <propskit-origin
733
+ label="Transform origin"
734
+ value='{"x":50,"y":50}'
735
+ default='{"x":50,"y":50}'
736
+ ></propskit-origin>
737
+ ```
738
+
739
+ ---
740
+
741
+ #### Propskit Easing
742
+
743
+ `<propskit-easing>`
744
+
745
+ 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.
746
+
747
+ ```html
748
+ <propskit-easing
749
+ label="Easing"
750
+ value='{"x1":0.42,"y1":0,"x2":0.58,"y2":1}'
751
+ default='{"x1":0.42,"y1":0,"x2":0.58,"y2":1}'
752
+ ></propskit-easing>
753
+ ```
754
+
755
+ ---
756
+
757
+ #### Propskit Spring
758
+
759
+ `<propskit-spring>`
760
+
761
+ 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.
762
+
763
+ ```html
764
+ <propskit-spring
765
+ label="Spring"
766
+ value='{"stiffness":200,"damping":15,"mass":1}'
767
+ default='{"stiffness":200,"damping":15,"mass":1}'
768
+ ></propskit-spring>
769
+ ```
770
+
771
+ 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.
772
+
773
+ ---
774
+
658
775
  #### Propskit Color Point
659
776
 
660
777
  `<propskit-color-point>`
@@ -667,12 +784,11 @@ A compact `<fig-group>` wrapper that combines `<propskit-color>` and `<propskit-
667
784
  | `value` | JSON string | `{"x":50,"y":50,"color":"#D9D9D9"}` | Current color-point value |
668
785
  | `collapsible` | boolean | `true` | Passed to the internal `fig-group` |
669
786
  | `open` | boolean | `true` | Passed to the internal `fig-group` |
670
- | `size` | string | default | Passed to both internal PropsKit controls |
671
787
  | `disabled` | boolean | `false` | Disable both internal controls |
672
788
 
673
789
  The internal group always has `compact`. `value` uses the same `{ x, y, color }` shape as `<fig-canvas-control type="color">`.
674
790
 
675
- **Events:** `input` and `change` bubble with numeric coordinates and `units` in `event.detail`. `openchange` mirrors the internal group's expanded state.
791
+ **Events:** `input` and `change` use the shared PropsKit envelope with the public color-point value. `openchange` mirrors the internal group's expanded state.
676
792
 
677
793
  ```html
678
794
  <propskit-color-point
@@ -696,12 +812,11 @@ A compact `<fig-group>` wrapper that combines `<propskit-position>` and `<propsk
696
812
  | `collapsible` | boolean | `true` | Passed to the internal `fig-group` |
697
813
  | `open` | boolean | `true` | Passed to the internal `fig-group` |
698
814
  | `units` | string | — | `"percent"` passes percentage units to position and radius; omit for no units |
699
- | `size` | string | default | Passed to both internal PropsKit controls |
700
815
  | `disabled` | boolean | `false` | Disable both internal controls |
701
816
 
702
817
  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 `%`.
703
818
 
704
- **Events:** `input` and `change` bubble with numeric `{ x, y, radius, units }` in `event.detail`. `openchange` mirrors the internal group's expanded state.
819
+ **Events:** `input` and `change` use the shared PropsKit envelope with the public point-radius value. `openchange` mirrors the internal group's expanded state.
705
820
 
706
821
  ```html
707
822
  <propskit-point-radius
@@ -726,12 +841,11 @@ A compact `<fig-group>` wrapper combining `<propskit-position>` with radius and
726
841
  | `collapsible` | boolean | `true` | Passed to the internal `fig-group` |
727
842
  | `open` | boolean | `true` | Passed to the internal `fig-group` |
728
843
  | `units` | string | — | `"percent"` passes percentage units to position and radius; omit for no units |
729
- | `size` | string | default | Passed to every internal PropsKit control |
730
844
  | `disabled` | boolean | `false` | Disable every internal control |
731
845
 
732
846
  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.
733
847
 
734
- **Events:** `input` and `change` bubble with numeric `{ x, y, radius, angle, units }` in `event.detail`. `openchange` mirrors the internal group's expanded state.
848
+ **Events:** `input` and `change` use the shared PropsKit envelope with the public point-radius-angle value. `openchange` mirrors the internal group's expanded state.
735
849
 
736
850
  ```html
737
851
  <propskit-point-radius-angle
@@ -756,12 +870,11 @@ A compact `<fig-group>` wrapper combining start and end `<propskit-position>` co
756
870
  | `collapsible` | boolean | `true` | Passed to the internal `fig-group` |
757
871
  | `open` | boolean | `true` | Passed to the internal `fig-group` |
758
872
  | `units` | string | — | `"percent"` passes percentage units to both positions; omit for no units |
759
- | `size` | string | default | Passed to both position controls |
760
873
  | `disabled` | boolean | `false` | Disable both position controls |
761
874
 
762
875
  The internal group always has `compact`. `value` uses the same `{ x, y, x2, y2 }` shape as `<fig-canvas-control type="point-point">`.
763
876
 
764
- **Events:** `input` and `change` bubble with numeric `{ x, y, x2, y2, units }` in `event.detail`. `openchange` mirrors the internal group's expanded state.
877
+ **Events:** `input` and `change` use the shared PropsKit envelope with the public point-point value. `openchange` mirrors the internal group's expanded state.
765
878
 
766
879
  ```html
767
880
  <propskit-point-point
@@ -858,6 +971,7 @@ Waveform oscillator input with composable wave functions, live SVG waveform prev
858
971
  | Attribute | Type | Default | Description |
859
972
  |---|---|---|---|
860
973
  | `value` | JSON string | — | `{"waves":[{"type":"sine","frequency":1,"amplitude":1,"phase":0,"offset":0}]}` |
974
+ | `name` | string | — | Optional event payload name |
861
975
  | `default` | JSON string | initial `value` | Right-click reset target |
862
976
  | `precision` | number | `2` | Decimal places |
863
977
  | `aspect-ratio` | string | `"2 / 1"` | Editor aspect ratio |
@@ -874,8 +988,8 @@ Right-click and choose **Reset**, or call `resetToDefault()`, to restore the osc
874
988
 
875
989
  | Event | Detail |
876
990
  |---|---|
877
- | `input` | `{ value, data, preset }` while dragging or editing |
878
- | `change` | `{ value, data, preset }` on release or committed edit |
991
+ | `input` | Shared PropsKit `{ control, value, name? }` envelope while dragging or editing |
992
+ | `change` | Shared PropsKit `{ control, value, name? }` envelope on release or committed edit |
879
993
 
880
994
  ```html
881
995
  <propskit-oscillator
@@ -1264,6 +1378,7 @@ An interactive bezier or spring easing curve editor with a preset dropdown and m
1264
1378
  | Attribute | Type | Default | Description |
1265
1379
  |---|---|---|---|
1266
1380
  | `value` | string | — | Bezier: `"0.42, 0, 0.58, 1"` or Spring: `"spring(200, 15, 1)"` |
1381
+ | `mode` | string | — | Optional `"bezier"` or `"spring"` constraint; filters presets and rejects the other value type |
1267
1382
  | `precision` | number | `2` | Decimal places |
1268
1383
  | `aspect-ratio` | string | — | Editor aspect ratio |
1269
1384
  | `edit` | boolean | `true` | Show the editor and custom bezier/spring options; set to `"false"` for preset-only |
package/components.css CHANGED
@@ -212,13 +212,18 @@
212
212
  Inter, AppleSystemUIFont, BlinkMacSystemFont, avenir next, avenir, segoe ui,
213
213
  helvetica neue, helvetica, Cantarell, Ubuntu, roboto, noto, arial, sans-serif;
214
214
  --font-variant-numeric: lining-nums tabular-nums slashed-zero;
215
- --body-medium-fontSize: 0.6875rem;
216
- --body-large-fontSize: 0.8125rem;
215
+ --text-body-medium-font-size: 0.6875rem;
216
+ --text-body-small-font-size: 0.5625rem;
217
+ --text-body-large-font-size: 0.8125rem;
218
+ --body-medium-fontSize: var(--text-body-medium-font-size);
219
+ --font-size-small: var(--text-body-small-font-size);
220
+ --body-small-fontSize: var(--text-body-small-font-size);
221
+ --body-large-fontSize: var(--text-body-large-font-size);
217
222
  --body-letter-spacing: 0.055px;
218
223
  --body-medium-strong-fontWeight: 550;
219
224
  --body-large-strong-fontWeight: 500;
220
225
  --body-medium-fontWeight: 450;
221
- --font-size-small: var(--body-medium-fontSize);
226
+
222
227
  --line-height: 1rem;
223
228
 
224
229
  /* Spacing */
@@ -235,10 +240,12 @@
235
240
  --radius-none: 0;
236
241
  --radius-small: 0.125rem;
237
242
  --radius-medium: 0.3125rem;
243
+ --radius-medium-large: 0.5625rem;
238
244
  --radius-large: 0.8125rem;
239
245
  --figma-radius-none: var(--radius-none);
240
246
  --figma-radius-small: var(--radius-small);
241
247
  --figma-radius-medium: var(--radius-medium);
248
+ --figma-radius-medium-large: var(--radius-medium-large);
242
249
  --figma-radius-large: var(--radius-large);
243
250
 
244
251
  /* Transitions */
@@ -1535,7 +1542,10 @@ input[type="color"] {
1535
1542
  content: "";
1536
1543
  width: calc(var(--width) - var(--padding) * 2);
1537
1544
  height: calc(var(--height) - var(--padding) * 2);
1538
- border-radius: calc(var(--border-radius) - (var(--padding) / 2));
1545
+ border-radius: var(
1546
+ --fig-swatch-border-radius,
1547
+ calc(var(--border-radius) - (var(--padding) / 2))
1548
+ );
1539
1549
  grid-area: 1/1;
1540
1550
  place-self: center;
1541
1551
  pointer-events: none;
@@ -1551,7 +1561,10 @@ input[type="color"] {
1551
1561
  background-size: var(--swatch-bg-size);
1552
1562
  background-position: var(--swatch-bg-position);
1553
1563
  background-repeat: no-repeat;
1554
- border-radius: calc(var(--border-radius) - (var(--padding) / 2));
1564
+ border-radius: var(
1565
+ --fig-swatch-border-radius,
1566
+ calc(var(--border-radius) - (var(--padding) / 2))
1567
+ );
1555
1568
  mask-image: linear-gradient(
1556
1569
  to right,
1557
1570
  black 0%,
@@ -1563,7 +1576,10 @@ input[type="color"] {
1563
1576
  }
1564
1577
  &[size="medium"]::before,
1565
1578
  &[size="large"]::before {
1566
- border-radius: calc(var(--border-radius) - var(--padding));
1579
+ border-radius: var(
1580
+ --fig-swatch-border-radius,
1581
+ calc(var(--border-radius) - var(--padding))
1582
+ );
1567
1583
  }
1568
1584
  &:focus,
1569
1585
  &:active {
@@ -4176,6 +4192,17 @@ fig-input-palette {
4176
4192
  grid-area: inputs;
4177
4193
  min-width: 0;
4178
4194
  width: 100%;
4195
+ position: relative;
4196
+
4197
+ &::after {
4198
+ content: "";
4199
+ position: absolute;
4200
+ inset: 0;
4201
+ border-radius: inherit;
4202
+ box-shadow: inset 0 0 0 1px var(--figma-color-bordertranslucent);
4203
+ pointer-events: none;
4204
+ z-index: 2;
4205
+ }
4179
4206
  }
4180
4207
 
4181
4208
  .palette-add-btn {
@@ -4709,7 +4736,7 @@ fig-joystick {
4709
4736
  pointer-events: none;
4710
4737
  user-select: none;
4711
4738
  color: var(--figma-color-text-tertiary);
4712
- font-size: 10px;
4739
+ font-size: var(--text-body-small-font-size);
4713
4740
  line-height: 1;
4714
4741
  letter-spacing: 0.01em;
4715
4742
  font-weight: 700;
@@ -4737,11 +4764,6 @@ fig-joystick {
4737
4764
  top: 50%;
4738
4765
  transform: translate(-50%, -50%) rotate(-90deg);
4739
4766
  transform-origin: center;
4740
-
4741
- &.no-rotate {
4742
- left: var(--spacer-2);
4743
- transform: translateY(-50%);
4744
- }
4745
4767
  }
4746
4768
 
4747
4769
  &.right {