@rogieking/figui3 8.9.49 → 8.10.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.
@@ -32,9 +32,9 @@ Registered tags:
32
32
 
33
33
  | Tag | Role |
34
34
  |---|---|
35
- | `fig-select` | Trigger + popup listbox |
35
+ | `fig-select` | Trigger + popup listbox (`subtle` applies to all options) |
36
36
  | `fig-select-options` | Scrollable panel (`slot="panel"`), overflow chevrons |
37
- | `fig-select-option` | Option (`value`, `label`, `selected`, `disabled`) |
37
+ | `fig-select-option` | Option (`value`, `label`, `selected`, `disabled`, `subtle`) |
38
38
  | `fig-fill-picker` | Full fill editor dialog (solid, gradient, image, video, webcam, custom modes) |
39
39
  | `fig-interpolation-swatch` | Gradient interpolation preview swatch |
40
40
 
@@ -42,7 +42,7 @@ Registered tags:
42
42
 
43
43
  - `fig-dropdown` (core): native `<select>`.
44
44
  - `fig-select` (this skill): custom listbox. Use this for Figma-style menus.
45
- - `propskit-select` (lab): labeled `fig-field` wrapping `fig-select` (falls back if select is not registered).
45
+ - `propskit-select` (lab): labeled horizontal surface that always renders `fig-select`; this editor bundle is required to register and style it.
46
46
 
47
47
  Author options as React children, or pass `options`. Do not `stopPropagation` on option click. `optionhover` is a native listener.
48
48
 
@@ -29,7 +29,7 @@ Data-driven (no authored options):
29
29
  />
30
30
  ```
31
31
 
32
- - Attrs: `value`, `label`, `options` (comma / newline / JSON), `variant` (`ghost`), `full`, `disabled`, `position` (`bottom left` default, also `bottom right`, `top left`, `top right`, `bottom center`, `top center`), `offset`, `closedby`, `open`
32
+ - Attrs: `value`, `label`, `options` (comma / newline / JSON), `variant` (`ghost`), `subtle` (applies the secondary hover/focus fill to every option), `full`, `disabled`, `position` (`bottom left` default, also `bottom right`, `top left`, `top right`, `bottom center`, `top center`), `offset`, `closedby`, `open`
33
33
  - Events: `input` / `change` on commit; `optionhover` with the option value in `detail` (does not change selection). Use a native listener for `optionhover`.
34
34
  - Do not `stopPropagation` on option click — React light-DOM handlers must run.
35
35
  - Internal popup uses `popover="manual"` so the list works inside `fig-popup variant="popover"`.
@@ -63,7 +63,7 @@ Data-driven (no authored options):
63
63
  </fig-select-option>
64
64
  ```
65
65
 
66
- - Attrs: `value` (falls back to trimmed `textContent`), `label` (closed-trigger text when content is rich), `selected`, `disabled`
66
+ - Attrs: `value` (falls back to trimmed `textContent`), `label` (closed-trigger text when content is rich), `selected`, `disabled`, `subtle` (secondary hover/focus fill)
67
67
  - `role="option"`, `aria-selected`, `aria-disabled`
68
68
 
69
69
  ## `fig-fill-picker`
@@ -8,6 +8,7 @@ Observed: `value`, `disabled`, `selected`, `label`.
8
8
 
9
9
  - `value` falls back to trimmed `textContent` if the attr is omitted
10
10
  - `label` is the closed-trigger string when option content is rich
11
+ - `subtle` uses the secondary hover/focus fill
11
12
  - `role="option"`, `aria-selected`, `aria-disabled`
12
13
 
13
14
  ## `fig-select-options`
@@ -22,6 +23,8 @@ Observed: `value`, `disabled`, `selected`, `label`.
22
23
 
23
24
  `value`, `disabled`, `label`, `options`, `position`, `offset`, `closedby`, `open`, `variant`
24
25
 
26
+ - `subtle` applies the secondary hover/focus fill to every option
27
+
25
28
  Position enum:
26
29
 
27
30
  - `bottom left`, `bottom right`, `top left`, `top right`, `bottom center`, `top center`
@@ -27,33 +27,42 @@ import "@rogieking/figui3/fig-lab.css";
27
27
  import "@rogieking/figui3/fig-lab.js";
28
28
  ```
29
29
 
30
- `propskit-select` prefers `fig-select` (import `fig-editor.js` + `fig-editor.css`). Without editor, it falls back.
30
+ `propskit-select` and `propskit-palette` render `fig-select`; import `fig-editor.js` + `fig-editor.css` to register and style them.
31
31
 
32
32
  `fig-editor.js` already imports `fig-lab.js`; lab **CSS** is still required for lab visuals.
33
33
 
34
34
  ## Shared propskit
35
35
 
36
- - `label`, `direction` (`horizontal` default), `size` (`""` | `small`; `large` remains an alias for the default), `disabled`
37
- - `variant="minimal"` — removes vertical row padding and reveals the field background on hover
36
+ - Plain labeled component surfaces; joystick, origin, easing, and spring use a
37
+ vertical label-above-control layout
38
+ - `label` (omitted renders `"Label"`; `label=""` hides it), `disabled`
39
+ - Optional `name` reflects to the host and appears in event details only when non-empty
38
40
  - `default` — reset target (may differ from initial `value`)
39
41
  - Right-click **Reset** menu; `resetToDefault()` on a ref
40
42
  - `propskit-slider` also double-click resets
41
43
  - Forward remaining attrs to the inner control except where a component note says otherwise
42
- - Rows are large by default; `propskit-group size="small"` applies compact sizing to children without an authored size
44
+ - `input` / `change`: `{ control, value, name? }`, dispatched from the outer host; `event.target.value === event.detail.value`. Select `optionhover` uses the same envelope
45
+ - Switch values are boolean; numeric number/slider/wheel values are finite numbers or `null`; structured and serialized values exactly match the host `.value`
46
+ - Shared style variables use `--propskit-{padding-block,padding-inline,background,border,color,hover-background,hover-border,hover-color,label-inline-size,input-inline-size}`; use a tag prefix such as `--propskit-select-background` for one control
43
47
 
44
48
  ## Control choice
45
49
 
46
50
  | Intent | Use |
47
51
  |---|---|
48
- | Labeled boolean | `propskit-switch` |
52
+ | Labeled boolean | `propskit-switch` (`fig-switch` by default; `variant="segmented-control"` for Off/On choices) |
49
53
  | Labeled continuous number | `propskit-slider` |
50
54
  | Standalone scrubbable number | `fig-input-wheel` |
51
55
  | Labeled scrubbable number or time | `propskit-wheel` |
52
56
  | Labeled exact number | `propskit-number` |
53
57
  | Labeled text | `propskit-text` |
54
58
  | Labeled discrete list | `propskit-select` (not `fig-dropdown`) |
59
+ | Labeled palette choice | `propskit-palette` |
55
60
  | Labeled color / fill / gradient | `propskit-color` / `propskit-fill` / `propskit-gradient` |
56
61
  | X/Y | `propskit-position` |
62
+ | Interactive X/Y plane | `propskit-joystick` |
63
+ | Transform origin | `propskit-origin` |
64
+ | Cubic-bezier easing | `propskit-easing` |
65
+ | Spring motion | `propskit-spring` |
57
66
  | Spatial on a canvas | `fig-canvas-control` |
58
67
  | Angle | `fig-input-angle` |
59
68
  | Section of props | `propskit-group` or core `fig-group` |
@@ -2,17 +2,21 @@
2
2
 
3
3
  Experimental. APIs may change. React contract: [../figui3/react.md](../figui3/react.md). Attrs: [reference.md](reference.md).
4
4
 
5
- Install `fig-lab.css` + `fig-lab.js`. `propskit-select` prefers `fig-select` also import `fig-editor.js` + `fig-editor.css` for rich menus. `fig-editor.js` already imports `fig-lab.js`; lab **CSS** is still required.
5
+ Install `fig-lab.css` + `fig-lab.js`. `propskit-select` and `propskit-palette` use `fig-select`, so also import `fig-editor.js` + `fig-editor.css`. `fig-editor.js` already imports `fig-lab.js`; lab **CSS** is still required.
6
6
 
7
7
  Handlers below assume `onInput` / `onChange` from the React contract.
8
8
 
9
9
  ## Shared propskit
10
10
 
11
- Full-surface `fig-field` wrappers. Prefer these over hand-rolled label+control rows.
11
+ Plain horizontal component surfaces. Prefer these over hand-rolled label+control rows.
12
12
 
13
- Shared attrs: `label`, `direction` (`horizontal` default), `size` (`""` | `small`; `large` is an alias for default), `disabled`, `variant="minimal"` (no vertical padding; field background on hover), `default` (reset target, may differ from initial `value`).
13
+ Shared attrs: `label` (omitted renders `"Label"`; `label=""` hides it), optional `name`, `disabled`, `default` (reset target, may differ from initial `value`).
14
14
 
15
- Right-click **Reset**; `resetToDefault()` on a ref. `propskit-slider` also double-click resets. Remaining attrs forward to the inner control. Rows are large by default; `propskit-group size="small"` applies compact sizing to children without an authored size.
15
+ Right-click **Reset**; `resetToDefault()` on a ref. `propskit-slider` also double-click resets. Remaining attrs forward to the inner control.
16
+
17
+ `input` and `change` dispatch from the outer host with `{ control, value, name? }`; `event.target.value` matches `detail.value`. `optionhover` uses the same envelope. Numeric number/slider/wheel values are finite numbers or `null`.
18
+
19
+ Shared CSS variables: `--propskit-padding-block`, `--propskit-padding-inline`, `--propskit-background`, `--propskit-border`, `--propskit-color`, `--propskit-hover-background`, `--propskit-hover-border`, `--propskit-hover-color`, `--propskit-label-inline-size`, and `--propskit-input-inline-size`. Prefix the control name for one row, for example `--propskit-select-background`.
16
20
 
17
21
  ```tsx
18
22
  const rowRef = useRef<HTMLElement>(null);
@@ -26,13 +30,14 @@ rowRef.current?.resetToDefault();
26
30
  ```tsx
27
31
  <propskit-switch
28
32
  label="Visible"
33
+ variant="switch"
29
34
  checked={on ? "true" : undefined}
30
35
  default="true"
31
36
  onInput={onInput}
32
37
  />
33
38
  ```
34
39
 
35
- - Inner: `fig-switch`. `checked` / `default` boolean.
40
+ - Inner: `fig-switch` by default. `variant="segmented-control"` renders the Off/On `fig-segmented-control`. The full surface toggles either control. `checked`, `default`, `.value`, and event values are boolean.
36
41
 
37
42
  ### `propskit-color`
38
43
 
@@ -46,7 +51,7 @@ rowRef.current?.resetToDefault();
46
51
  />
47
52
  ```
48
53
 
49
- - Inner: `fig-fill-picker` + `fig-swatch`. Clicking the field opens the picker anchored to the host. Focus ring on the field, not the swatch.
54
+ - Inner: `fig-fill-picker` + `fig-swatch`. Clicking the surface opens the picker anchored to the host. Focus ring on the surface, not the swatch.
50
55
 
51
56
  ### `propskit-fill`
52
57
 
@@ -76,7 +81,22 @@ rowRef.current?.resetToDefault();
76
81
  />
77
82
  ```
78
83
 
79
- - Inner: `fig-input-gradient`. Default `edit="picker"`. `mode="handle|tip"` for inline edit. Clicking the field opens the picker anchored to the host.
84
+ - Inner: `fig-input-gradient`. Default `edit="picker"`. `mode="handle|tip"` for inline edit. Clicking the surface opens the picker anchored to the host.
85
+
86
+ ### `propskit-palette`
87
+
88
+ ```tsx
89
+ <propskit-palette
90
+ label="Palette"
91
+ options='[["#0D99FF","#14AE5C"],[{"color":"#FFCD29","alpha":0.5},"#F24822"]]'
92
+ onInput={onInput}
93
+ onChange={onChange}
94
+ />
95
+ ```
96
+
97
+ - Inner: `fig-select` with fixed, disabled `fig-input-palette` previews. Requires the editor bundle.
98
+ - `options` is an array of palette arrays. Public and event values are typed `{ color, alpha }[]`; omission of `value` selects the first palette.
99
+ - Supports `optionhover`, typed `defaultValue`, `isDefault`, and `resetToDefault()`.
80
100
 
81
101
  ### `propskit-select`
82
102
 
@@ -101,7 +121,7 @@ Rich options (requires editor):
101
121
  </propskit-select>
102
122
  ```
103
123
 
104
- - Inner: `fig-select` when registered; otherwise a fallback. Authored `fig-select-options slot="panel"` wins. Options stay in light DOM.
124
+ - Inner: always `fig-select`; editor registration is required. Authored `fig-select-options slot="panel"` wins. Options stay in light DOM.
105
125
 
106
126
  ### `propskit-text`
107
127
 
@@ -114,7 +134,10 @@ Rich options (requires editor):
114
134
  />
115
135
  ```
116
136
 
117
- - Inner: `fig-input-text`. `type`, `readonly`.
137
+ - Inner: `fig-input-text` with `multiline` and `autoresize` enabled by default.
138
+ It starts at one line and grows through four lines. Use `"false"` to disable
139
+ either default. The inner control is always `type="text"`; the host `type`
140
+ attribute is not forwarded. `readonly` is forwarded.
118
141
 
119
142
  ### `propskit-number`
120
143
 
@@ -138,7 +161,6 @@ Rich options (requires editor):
138
161
  ```tsx
139
162
  <propskit-slider
140
163
  label="Opacity"
141
- direction="horizontal"
142
164
  type="opacity"
143
165
  value="100"
144
166
  default="100"
@@ -163,7 +185,7 @@ Rich options (requires editor):
163
185
  />
164
186
  ```
165
187
 
166
- - Inner: `fig-input-wheel` + optional `fig-input-number`. Attrs: `label`, `text`, `spin`, `elastic` (row stretch, default true), `precision`, `units`, `default`, `size`, `variant`. Units stay on the wrapper; effective step is applied to the wheel. `spin="false"` updates value without moving ticks.
188
+ - Inner: `fig-input-wheel` + optional `fig-input-number`. Attrs: `label`, `text`, `spin`, `elastic` (row stretch, default true), `precision`, `units`, `default`. Units stay on the wrapper; effective step is applied to the wheel. `spin="false"` updates value without moving ticks.
167
189
 
168
190
  ### `propskit-position`
169
191
 
@@ -173,6 +195,62 @@ Rich options (requires editor):
173
195
 
174
196
  - Two numbers. Attrs: `x`, `y`, `units`.
175
197
 
198
+ ### `propskit-joystick`
199
+
200
+ ```tsx
201
+ <propskit-joystick
202
+ label="Position"
203
+ value='{"x":35,"y":65}'
204
+ default='{"x":50,"y":50}'
205
+ axis-labels="X Y"
206
+ onInput={onInput}
207
+ onChange={onChange}
208
+ />
209
+ ```
210
+
211
+ - Inner: `fig-joystick` with forced `fields="true"` and `aspect-ratio="1 / 1"`.
212
+ - `.value`, `defaultValue`, and event values are typed `{ x, y }` percentage objects.
213
+
214
+ ### `propskit-origin`
215
+
216
+ ```tsx
217
+ <propskit-origin
218
+ label="Transform origin"
219
+ value='{"x":50,"y":50}'
220
+ default='{"x":50,"y":50}'
221
+ onInput={onInput}
222
+ />
223
+ ```
224
+
225
+ - Inner: `fig-origin-grid` with forced `fields="true"` and `aspect-ratio="1 / 1"`.
226
+ - `.value`, `defaultValue`, and event values are typed `{ x, y }` percentage objects.
227
+
228
+ ### `propskit-easing`
229
+
230
+ ```tsx
231
+ <propskit-easing
232
+ label="Easing"
233
+ value='{"x1":0.42,"y1":0,"x2":0.58,"y2":1}'
234
+ onChange={onChange}
235
+ />
236
+ ```
237
+
238
+ - Inner: `fig-easing-curve` constrained to bezier mode.
239
+ - Typed value: `{ x1, y1, x2, y2 }`.
240
+
241
+ ### `propskit-spring`
242
+
243
+ ```tsx
244
+ <propskit-spring
245
+ label="Spring"
246
+ value='{"stiffness":200,"damping":15,"mass":1}'
247
+ onChange={onChange}
248
+ />
249
+ ```
250
+
251
+ - Inner: `fig-easing-curve` constrained to spring mode.
252
+ - Typed value: `{ stiffness, damping, mass }`.
253
+
176
254
  ### `propskit-color-point`
177
255
 
178
256
  ```tsx
@@ -221,7 +299,7 @@ Rich options (requires editor):
221
299
  </propskit-group>
222
300
  ```
223
301
 
224
- - Attrs: `name`, `open`, `show-reset`, `size`. Children are React nodes.
302
+ - Attrs: `name`, `open`, `show-reset`. Children are React nodes.
225
303
 
226
304
  ### `propskit-oscillator`
227
305
 
@@ -10,28 +10,65 @@ React recipes: [components.md](components.md).
10
10
  - Slider: double-click also resets
11
11
  - Equality helpers treat booleans and JSON objects
12
12
 
13
- ## Propskit variants
13
+ ## Propskit switch variants
14
14
 
15
- `variant="minimal"` is available on switch, color, fill, gradient, select, text, number, slider, position, and wheel controls. It removes vertical host padding, keeps the inner field transparent at rest, and restores the secondary field background on hover.
15
+ `propskit-switch` accepts `variant="switch|segmented-control"`.
16
+ `switch` is the default and renders `fig-switch`; `segmented-control` renders
17
+ explicit Off/On choices. The full surface toggles either variant. Its `.value`
18
+ and `input` / `change` event values are boolean.
16
19
 
17
- ## Propskit sizes
20
+ ## Propskit surfaces and events
18
21
 
19
- PropsKit rows are large by default; explicit `size="large"` remains supported.
20
- `propskit-group size="small"` applies `size="small"` to nested controls that do
21
- not define their own size and removes generated sizes when the group returns to
22
- the default size.
22
+ Surface controls are horizontal and do not compose `fig-field`. Omitted `label`
23
+ renders `"Label"` and `label=""` hides the visible label. Optional non-empty
24
+ `name` reflects on the host.
25
+
26
+ `input` and `change` dispatch from the outer host with
27
+ `{ control, value, name? }`; `event.target.value` equals `detail.value`.
28
+ `propskit-select` and `propskit-palette` use the same envelope for
29
+ `optionhover`. Switch values are boolean. Number, slider, and wheel values are
30
+ finite numbers or `null`. Structured and serialized values are exactly the
31
+ host's public `.value`.
32
+
33
+ Shared style variables use the suffixes `padding-block`, `padding-inline`,
34
+ `background`, `border`, `color`, `hover-background`, `hover-border`,
35
+ `hover-color`, `label-inline-size`, and `input-inline-size` under the
36
+ `--propskit-*` prefix. A per-control prefix, such as
37
+ `--propskit-select-background`, overrides the shared value.
38
+
39
+ ## `propskit-palette`
40
+
41
+ Observed: `label`, `aria-label`, `options`, `value`, `disabled`.
42
+
43
+ Always renders `fig-select` with fixed, disabled `fig-input-palette` previews.
44
+ Import `fig-editor.js` and `fig-editor.css`.
45
+
46
+ - `options`: JSON array of palette arrays
47
+ - Palette entries: color strings or `{ "color": string, "alpha": number }`
48
+ - `.value`, `defaultValue`, and event `detail.value`: typed `{ color, alpha }[]`
49
+ - First option is the fallback when `value` is omitted or does not match
50
+ - `input`, `change`, and `optionhover` use the shared PropsKit envelope
51
+ - `isDefault` uses structural equality; `resetToDefault()` restores `default`
23
52
 
24
53
  ## `propskit-select`
25
54
 
26
- Observed: `label`, `direction`, `aria-label`, `options`, `value`.
55
+ Observed: `label`, `aria-label`, `options`, `value`.
27
56
 
28
- Uses `fig-select` when `fig-select`, `fig-select-options`, and `fig-select-option` are registered; otherwise a fallback control.
57
+ Always renders `fig-select`. Import `fig-editor.js` and `fig-editor.css`; delayed registration upgrades the authored element.
29
58
 
30
59
  Options attr: JSON array, comma, or newline. Authored `fig-select-options slot="panel"` wins for rich menus.
31
60
 
61
+ ## `propskit-text`
62
+
63
+ Composes `fig-input-text` with `multiline` and `autoresize` enabled by default.
64
+ The textarea starts at one line, grows with its content, and scrolls after four
65
+ lines. Set `multiline="false"` or `autoresize="false"` to disable either
66
+ default. The inner control is always `type="text"`; a host `type` attribute is
67
+ ignored rather than forwarded.
68
+
32
69
  ## `propskit-slider`
33
70
 
34
- Attrs: `type` (`range`, `hue`, `delta`, `stepper`, `opacity`), `color`, `label`, `default`, `units`, `elastic` (default true), `size`, `steppers`, `disabled`.
71
+ Attrs: `type` (`range`, `hue`, `delta`, `stepper`, `opacity`), `color`, `label`, `default`, `units`, `elastic` (default true), `steppers`, `disabled`.
35
72
 
36
73
  Inner `fig-slider` still needs `min` / `max` / `step` / `value` as forwarded attrs.
37
74
 
@@ -53,13 +90,72 @@ Standalone interactive SVG tick + handle scrubber in the lab bundle.
53
90
 
54
91
  ## `propskit-wheel`
55
92
 
56
- Composes `fig-input-wheel` with an optional `fig-input-number`. It retains `label`, `text`, `spin`, `precision`, `units`, `default`/reset, `size`, and `variant`. `elastic` defaults to true and controls stretching of the composed row; the child wheel's handle pull remains active when row stretching is disabled. Set `spin="false"` to update the value and number field while leaving wheel ticks stationary. Units and time aliases are wrapper/number-field behavior: normalized `s` defaults to step `0.1` and precision `2`, normalized `ms` defaults to step `100` and precision `0`, and other units default to step `1` and precision `0`. The wrapper applies the effective step and unit-aware `aria-valuetext` to the child wheel, but never sets child `units`.
93
+ Composes `fig-input-wheel` with an optional `fig-input-number`. It retains `label`, `text`, `spin`, `precision`, `units`, and `default`/reset. `elastic` defaults to true and controls stretching of the composed row; the child wheel's handle pull remains active when row stretching is disabled. Set `spin="false"` to update the value and number field while leaving wheel ticks stationary. Units and time aliases are wrapper/number-field behavior: normalized `s` defaults to step `0.1` and precision `2`, normalized `ms` defaults to step `100` and precision `0`, and other units default to step `1` and precision `0`. The wrapper applies the effective step and unit-aware `aria-valuetext` to the child wheel, but never sets child `units`.
57
94
 
58
95
  ```html
59
96
  <propskit-wheel label="Duration" value="1.5" units="seconds"></propskit-wheel>
60
97
  <propskit-wheel label="Frames" value="12" text="false"></propskit-wheel>
61
98
  ```
62
99
 
100
+ ## `propskit-joystick`
101
+
102
+ Composes a PropsKit label above `fig-joystick`. The plane always uses
103
+ `aspect-ratio="1 / 1"` and the X/Y fields are always enabled.
104
+
105
+ - Observed: `value`, `default`, `label`, `aria-label`, `axis-labels`,
106
+ `coordinates`, `precision`, `disabled`
107
+ - `value` and `default`: serialized `{ "x": number, "y": number }` percentages
108
+ - `.value`, `defaultValue`, and event `detail.value`: typed `{ x, y }`
109
+ - `input` and `change` use the shared PropsKit envelope
110
+ - `isDefault` compares both axes; `resetToDefault()` restores `default`
111
+
112
+ ```html
113
+ <propskit-joystick
114
+ label="Position"
115
+ value='{"x":35,"y":65}'
116
+ default='{"x":50,"y":50}'
117
+ axis-labels="X Y"
118
+ ></propskit-joystick>
119
+ ```
120
+
121
+ ## `propskit-origin`
122
+
123
+ Composes a PropsKit label above `fig-origin-grid`. The grid always uses
124
+ `aspect-ratio="1 / 1"` and its X/Y fields are always enabled.
125
+
126
+ - Observed: `value`, `default`, `label`, `aria-label`, `precision`, `drag`,
127
+ `disabled`
128
+ - `value` and `default`: serialized `{ "x": number, "y": number }` percentages
129
+ - `.value`, `defaultValue`, and event `detail.value`: typed `{ x, y }`
130
+ - `input` and `change` use the shared PropsKit envelope
131
+
132
+ ## `propskit-easing`
133
+
134
+ Composes a PropsKit label above `fig-easing-curve`, constrained to bezier mode.
135
+
136
+ - Observed: `value`, `default`, `label`, `aria-label`, `precision`, `edit`,
137
+ `disabled`
138
+ - `value` and `default`: serialized `{ "x1", "y1", "x2", "y2" }` objects
139
+ - `.value`, `defaultValue`, and event `detail.value`: typed
140
+ `{ x1, y1, x2, y2 }`
141
+ - X coordinates are clamped to `0–1`; Y coordinates may overshoot
142
+
143
+ ## `propskit-spring`
144
+
145
+ Composes a PropsKit label above `fig-easing-curve`, constrained to spring mode.
146
+
147
+ - Observed: `value`, `default`, `label`, `aria-label`, `precision`, `edit`,
148
+ `disabled`
149
+ - `value` and `default`: serialized `{ "stiffness", "damping", "mass" }`
150
+ objects
151
+ - `.value`, `defaultValue`, and event `detail.value`: typed
152
+ `{ stiffness, damping, mass }`
153
+ - Spring values must be positive
154
+
155
+ All three controls force a square primitive, support `variant="minimal"`,
156
+ participate in PropsKit group reset, and delegate focus to their first
157
+ interactive descendant.
158
+
63
159
  ## Point JSON shapes
64
160
 
65
161
  ```json
@@ -562,6 +562,9 @@ toastRef.current?.showToast();
562
562
  <fig-easing-curve value="ease-in-out" onInput={onInput} onChange={onChange} />
563
563
  ```
564
564
 
565
+ Set `mode="bezier"` or `mode="spring"` to constrain the editor and preset list
566
+ to one curve type.
567
+
565
568
  ### `fig-3d-rotate`
566
569
 
567
570
  ```tsx
@@ -117,14 +117,18 @@ type FigTag =
117
117
  | "propskit-fill"
118
118
  | "propskit-gradient"
119
119
  | "propskit-group"
120
+ | "propskit-easing"
120
121
  | "propskit-number"
121
122
  | "propskit-oscillator"
122
123
  | "propskit-point-point"
123
124
  | "propskit-point-radius"
124
125
  | "propskit-point-radius-angle"
125
126
  | "propskit-position"
127
+ | "propskit-joystick"
128
+ | "propskit-origin"
126
129
  | "propskit-select"
127
130
  | "propskit-slider"
131
+ | "propskit-spring"
128
132
  | "propskit-switch"
129
133
  | "propskit-text"
130
134
  | "propskit-wheel";