@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.
@@ -2,129 +2,6 @@
2
2
 
3
3
  React recipes: [components.md](components.md).
4
4
 
5
- ## Propskit reset
6
-
7
- - `default` attr stores the reset value
8
- - `resetToDefault()` on the host
9
- - Context menu item `reset-default`
10
- - Slider: double-click also resets
11
- - Equality helpers treat booleans and JSON objects
12
-
13
- ## Propskit switch variants
14
-
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.
19
-
20
- ## Propskit surfaces and events
21
-
22
- Surface controls do not compose `fig-field`. Most are horizontal; spatial,
23
- curve, and image controls use vertical layouts. Omitted `label` renders
24
- `"Label"` and `label=""` hides the visible label. Optional non-empty `name`
25
- reflects on the host.
26
-
27
- `input` and `change` dispatch from the outer host with
28
- `{ control, value, name? }`; `event.target.value` equals `detail.value`.
29
- `propskit-select` and `propskit-palette` use the same envelope for
30
- `optionhover`. Switch values are boolean. Number, slider, and wheel values are
31
- finite numbers or `null`. Structured and serialized values are exactly the
32
- host's public `.value`.
33
-
34
- Shared style variables use the suffixes `padding-block`, `padding-inline`,
35
- `background`, `border`, `color`, `hover-background`, `hover-border`,
36
- `hover-color`, `label-inline-size`, and `input-inline-size` under the
37
- `--propskit-*` prefix. A per-control prefix, such as
38
- `--propskit-select-background`, overrides the shared value.
39
-
40
- ## `propskit-palette`
41
-
42
- Observed: `label`, `aria-label`, `options`, `value`, `disabled`.
43
-
44
- Always renders `fig-select` with fixed, disabled `fig-input-palette` previews.
45
- Import `fig-editor.js` and `fig-editor.css`.
46
-
47
- - `options`: JSON array of palette arrays
48
- - Palette entries: color strings or `{ "color": string, "alpha": number }`
49
- - `.value`, `defaultValue`, and event `detail.value`: typed `{ color, alpha }[]`
50
- - First option is the fallback when `value` is omitted or does not match
51
- - `input`, `change`, and `optionhover` extend the shared PropsKit envelope with
52
- `label`; `value` remains the stable option value
53
- - `isDefault` uses structural equality; `resetToDefault()` restores `default`
54
-
55
- ## `propskit-image`
56
-
57
- Observed: `options`, `value`, `default`, `label`, `aria-label`, `disabled`.
58
-
59
- Renders a label and permanent ghost upload button above a conditional
60
- `fig-chooser`. The chooser always uses `layout="grid"` and `columns="2"`;
61
- each `fig-choice` contains a square, cover-fit `fig-image` and an
62
- attachment-style remove control.
63
-
64
- - `options`: optional JSON string array of image URLs
65
- - `.options`: normalized, de-duplicated URL array
66
- - `.value`, `defaultValue`, and event `detail.value`: selected URL string
67
- - First option is the fallback when `value` is omitted or does not match
68
- - Selecting one or more image files appends object URLs and selects the first
69
- new image; applications own durable upload and URL replacement
70
- - Removing a choice reflects the reduced `options` array and revokes an object
71
- URL when needed; removing the selected choice falls back to the first option
72
- and emits `input` and `change`
73
- - Delete and Backspace remove the focused choice
74
- - `input` and `change` use the shared PropsKit envelope
75
- - Supports `variant="minimal"`, `isDefault`, `resetToDefault()`, and focus
76
- delegation
77
-
78
- ## `propskit-select`
79
-
80
- Observed: `label`, `aria-label`, `options`, `value`.
81
-
82
- Always renders `fig-select`. Import `fig-editor.js` and `fig-editor.css`; delayed registration upgrades the authored element.
83
-
84
- Options attr: JSON array, comma, or newline. Authored `fig-select-options slot="panel"` wins for rich menus.
85
-
86
- ## `propskit-editable-select`
87
-
88
- Observed: `options`, `value`, `default`, `aria-label`, `disabled`.
89
-
90
- Renders a label-free, always-subtle, content-width `fig-select` on the left,
91
- with default-size secondary edit and add buttons on the right inside one
92
- full-row PropsKit surface. The row uses the standard PropsKit padding,
93
- background, border, color, hover, and focus variables.
94
-
95
- - `options` accepts comma, newline, or JSON values supported by `fig-select`
96
- - `.options` returns normalized `{ value, label }[]` entries
97
- - Clicking the host opens the select except when edit or add is clicked
98
- - The options menu is positioned and sized to the full PropsKit row
99
- - Add creates an `item-{index}` value using its zero-based array index with the
100
- label `"New item"`, selects it, and opens rename mode
101
- - Edit replaces the select with a default-size, full-width `fig-input-text`;
102
- checkmark, Enter, or moving focus outside the input commits, while Escape
103
- cancels
104
- - Each menu option has an appended ghost trash action; Delete or Backspace
105
- removes the focused option
106
- - Edit/save, add, and trash icon buttons include descriptive tooltips
107
- - At one remaining item, the select and trash action are disabled; add and edit
108
- remain available
109
- - Renaming updates the reflected options JSON while preserving the option value
110
- - `input`, `change`, and `optionhover` use the shared PropsKit envelope
111
- - Supports `defaultValue`, `isDefault`, `editing`, `resetToDefault()`, disabled
112
- state propagation, and focus delegation
113
-
114
- ## `propskit-text`
115
-
116
- Composes `fig-input-text` with `multiline` and `autoresize` enabled by default.
117
- The textarea starts at one line, grows with its content, and scrolls after four
118
- lines. Set `multiline="false"` or `autoresize="false"` to disable either
119
- default. The inner control is always `type="text"`; a host `type` attribute is
120
- ignored rather than forwarded.
121
-
122
- ## `propskit-slider`
123
-
124
- Attrs: `type` (`range`, `hue`, `delta`, `stepper`, `opacity`), `color`, `label`, `default`, `units`, `elastic` (default true), `steppers`, `disabled`.
125
-
126
- Inner `fig-slider` still needs `min` / `max` / `step` / `value` as forwarded attrs.
127
-
128
5
  ## `fig-input-wheel`
129
6
 
130
7
  Standalone interactive SVG tick + handle scrubber in the lab bundle.
@@ -141,74 +18,6 @@ Standalone interactive SVG tick + handle scrubber in the lab bundle.
141
18
  <fig-input-wheel value="1.5" step="0.25"></fig-input-wheel>
142
19
  ```
143
20
 
144
- ## `propskit-wheel`
145
-
146
- 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`.
147
-
148
- ```html
149
- <propskit-wheel label="Duration" value="1.5" units="seconds"></propskit-wheel>
150
- <propskit-wheel label="Frames" value="12" text="false"></propskit-wheel>
151
- ```
152
-
153
- ## `propskit-joystick`
154
-
155
- Composes a PropsKit label above `fig-joystick`. The plane always uses
156
- `aspect-ratio="1 / 1"` and the X/Y fields are always enabled.
157
-
158
- - Observed: `value`, `default`, `label`, `aria-label`, `axis-labels`,
159
- `coordinates`, `precision`, `disabled`
160
- - `value` and `default`: serialized `{ "x": number, "y": number }` percentages
161
- - `.value`, `defaultValue`, and event `detail.value`: typed `{ x, y }`
162
- - `input` and `change` use the shared PropsKit envelope
163
- - `isDefault` compares both axes; `resetToDefault()` restores `default`
164
-
165
- ```html
166
- <propskit-joystick
167
- label="Position"
168
- value='{"x":35,"y":65}'
169
- default='{"x":50,"y":50}'
170
- axis-labels="X Y"
171
- ></propskit-joystick>
172
- ```
173
-
174
- ## `propskit-origin`
175
-
176
- Composes a PropsKit label above `fig-origin-grid`. The grid always uses
177
- `aspect-ratio="1 / 1"` and its X/Y fields are always enabled.
178
-
179
- - Observed: `value`, `default`, `label`, `aria-label`, `precision`, `drag`,
180
- `disabled`
181
- - `value` and `default`: serialized `{ "x": number, "y": number }` percentages
182
- - `.value`, `defaultValue`, and event `detail.value`: typed `{ x, y }`
183
- - `input` and `change` use the shared PropsKit envelope
184
-
185
- ## `propskit-easing`
186
-
187
- Composes a PropsKit label above `fig-easing-curve`, constrained to bezier mode.
188
-
189
- - Observed: `value`, `default`, `label`, `aria-label`, `precision`, `edit`,
190
- `disabled`
191
- - `value` and `default`: serialized `{ "x1", "y1", "x2", "y2" }` objects
192
- - `.value`, `defaultValue`, and event `detail.value`: typed
193
- `{ x1, y1, x2, y2 }`
194
- - X coordinates are clamped to `0–1`; Y coordinates may overshoot
195
-
196
- ## `propskit-spring`
197
-
198
- Composes a PropsKit label above `fig-easing-curve`, constrained to spring mode.
199
-
200
- - Observed: `value`, `default`, `label`, `aria-label`, `precision`, `edit`,
201
- `disabled`
202
- - `value` and `default`: serialized `{ "stiffness", "damping", "mass" }`
203
- objects
204
- - `.value`, `defaultValue`, and event `detail.value`: typed
205
- `{ stiffness, damping, mass }`
206
- - Spring values must be positive
207
-
208
- All three controls force a square primitive, support `variant="minimal"`,
209
- participate in PropsKit group reset, and delegate focus to their first
210
- interactive descendant.
211
-
212
21
  ## Point JSON shapes
213
22
 
214
23
  ```json
@@ -218,10 +27,6 @@ interactive descendant.
218
27
  {"x":10,"y":10,"x2":90,"y2":90}
219
28
  ```
220
29
 
221
- Color-point combines a color payload with `x`/`y`.
222
-
223
- Collapsible point groups: `collapsible` and `open` default true (string booleans).
224
-
225
30
  ## `fig-canvas-control`
226
31
 
227
32
  Observed: `type`, `value`, `color`, `name`, `tooltips`, `disabled`, `drag-surface`, `snapping`.
@@ -242,7 +47,7 @@ Observed: `axis`, `handle`, `disabled`.
242
47
 
243
48
  Event `reorder`: `{ oldIndex, newIndex, item }`.
244
49
 
245
- Nested drag is ignored for sliders, handles, canvas controls, and most propskit spatial controls so inner gestures still work. If a row is still stolen, set `handle` to a drag-affordance selector.
50
+ Nested drag is ignored for sliders, handles, and canvas controls so inner gestures still work. If a row is still stolen, set `handle` to a drag-affordance selector.
246
51
 
247
52
  ## AI shells
248
53
 
@@ -5,7 +5,6 @@ description: >-
5
5
  including React JSX usage. Use when adding, using, or debugging fig-* elements from
6
6
  the core bundle—buttons, fields, overlays, menus, sliders, color/fill inputs, media,
7
7
  dialogs, popups, toasts. Not for fig-select or fig-fill-picker (fig-editor),
8
- propskit-* / AI / canvas / angle / wheel / reorder (fig-lab), or fig-layer.
9
8
  user-invocable: false
10
9
  ---
11
10
 
@@ -15,7 +14,6 @@ Zero-dependency web components for Figma UI3 plugin and widget UIs.
15
14
 
16
15
  Public API: `README.md`. React: [react.md](react.md). Per-tag JSX: [components.md](components.md). Attrs: [reference.md](reference.md).
17
16
 
18
- Related skills: `fig-editor` (`fig-select`, `fig-fill-picker`), `fig-lab` (`propskit-*`, AI, canvas), `propkit` (property-row composition).
19
17
 
20
18
  ## Bundles
21
19
 
@@ -30,7 +28,6 @@ import "@rogieking/figui3/fig.js";
30
28
  |---|---|---|
31
29
  | **Core** (this skill) | `fig.css` + `fig.js` | All `fig-*` in [components.md](components.md) |
32
30
  | **Editor** | `fig-editor.css` + `fig-editor.js` | `fig-select*`, `fig-fill-picker`, `fig-interpolation-swatch` |
33
- | **Lab** (unstable) | `fig-lab.css` + `fig-lab.js` | `propskit-*`, `fig-ai-*`, `fig-canvas-control`, `fig-input-angle`, `fig-input-wheel`, `fig-reorder` |
34
31
  | **Layer** | `fig-layer.css` + `fig-layer.js` | `fig-layer` |
35
32
 
36
33
  `fig-editor.js` also imports `fig.js` and `fig-lab.js`. Lab CSS is still separate. `fig-layer` is **not** registered by `fig-editor.js`. Toast is core; layer is `fig-layer.js`.
@@ -71,7 +68,6 @@ import "@rogieking/figui3/fig.js";
71
68
  </fig-field>
72
69
  ```
73
70
 
74
- Labeled property wrappers (`propskit-*`) are lab. See the `propkit` and `fig-lab` skills.
75
71
 
76
72
  ## Select vs dropdown
77
73
 
@@ -79,7 +75,6 @@ Labeled property wrappers (`propskit-*`) are lab. See the `propkit` and `fig-lab
79
75
  |---|---|---|
80
76
  | `fig-dropdown` | core | Native `<select>` wrapper. `type="select\|dropdown"`, `variant="ghost"` |
81
77
  | `fig-select` | editor | Custom listbox: groups, overflow chevrons, sticky separators, rich options |
82
- | `propskit-select` | lab | Full-surface labeled field around `fig-select` |
83
78
 
84
79
  Prefer `fig-select` for Figma-style menus. Use `fig-dropdown` only for a native select.
85
80
 
@@ -112,28 +112,6 @@ type FigTag =
112
112
  | "fig-tooltip"
113
113
  | "fig-truncate"
114
114
  | "fig-video"
115
- | "propskit-color"
116
- | "propskit-color-point"
117
- | "propskit-fill"
118
- | "propskit-gradient"
119
- | "propskit-group"
120
- | "propskit-easing"
121
- | "propskit-image"
122
- | "propskit-number"
123
- | "propskit-oscillator"
124
- | "propskit-point-point"
125
- | "propskit-point-radius"
126
- | "propskit-point-radius-angle"
127
- | "propskit-position"
128
- | "propskit-joystick"
129
- | "propskit-origin"
130
- | "propskit-editable-select"
131
- | "propskit-select"
132
- | "propskit-slider"
133
- | "propskit-spring"
134
- | "propskit-switch"
135
- | "propskit-text"
136
- | "propskit-wheel";
137
115
 
138
116
  declare module "react" {
139
117
  namespace JSX {
@@ -150,7 +128,6 @@ declare module "react" {
150
128
 
151
129
  ## Host JSX
152
130
 
153
- Render the custom elements as tags. Children are React nodes (`key` on lists). `className` works on `fig-*`, `propskit-*`, and `<dialog is="fig-…">`.
154
131
 
155
132
  ```tsx
156
133
  <fig-field direction="horizontal">
@@ -208,7 +185,7 @@ function readValue(event: Event) {
208
185
 
209
186
  Native `addEventListener` only when React does not map the event: dialog `close` / `cancel`, delegated host clicks, imperative APIs.
210
187
 
211
- Common events: `input`, `change`, `loaded`, `optionhover`, `reorder`, `remove`, `modeready`, `webcamstream`, `close`.
188
+ Common events: `input`, `change`, `loaded`, `optionhover`, `optionschange`, `reorder`, `remove`, `modeready`, `webcamstream`, `close`.
212
189
 
213
190
  ## Customized built-ins
214
191
 
@@ -4,7 +4,6 @@ Public API: `README.md`. React recipes: [components.md](components.md).
4
4
 
5
5
  ## Option string formats
6
6
 
7
- Shared by `fig-dropdown`/`fig-options`/`fig-select`/`propskit-select` `options`:
8
7
 
9
8
  - Comma-separated: `Left,Center,Right`
10
9
  - Newline-delimited
@@ -2,100 +2,27 @@
2
2
  name: propkit
3
3
  description: >-
4
4
  Guides Figma-style property panel composition using fig-field rows and FigUI3
5
- controls, including React JSX. Use when building labeled property panels or
6
- choosing between raw fig-* rows and propskit-* wrappers (fig-lab).
5
+ controls, including React JSX.
7
6
  user-invocable: false
8
7
  ---
9
8
 
10
9
  # PropKit
11
10
 
12
- Patterns for Figma property panels. Two layers:
11
+ Compose property panels from horizontal `fig-field` rows and core `fig-*` controls.
13
12
 
14
- | Surface | What to use |
15
- |---|---|
16
- | **Core rows** | Horizontal `fig-field` + core `fig-*` |
17
- | **Lab wrappers** | `propskit-*` (see `fig-lab` skill) |
18
-
19
- Core tags: `figui3` skill + [../figui3/components.md](../figui3/components.md). React: [../figui3/react.md](../figui3/react.md). Select/fill picker: `fig-editor`. Labeled wrappers: `fig-lab`.
13
+ Core tags: `figui3` skill + [../figui3/components.md](../figui3/components.md). React: [../figui3/react.md](../figui3/react.md). Select/fill picker: `fig-editor`.
20
14
 
21
15
  ## Principles
22
16
 
23
17
  1. Default to horizontal `fig-field` rows.
24
- 2. One concise label per control.
25
- 3. For new labeled property controls in lab, prefer `propskit-*` over duplicating field chrome.
26
- 4. Compose from `fig-*` unless the row needs lab wrappers.
27
- 5. Panel width ~240px. Keep density tight.
28
-
29
- ## Field composition
18
+ 2. Use one concise label per control.
19
+ 3. Put control attributes on the control, not the field.
20
+ 4. Use `full` when the control should stretch.
21
+ 5. Wire `input` for live updates and `change` for commits.
30
22
 
31
23
  ```tsx
32
24
  <fig-field direction="horizontal">
33
25
  <label>Opacity</label>
34
- <fig-slider
35
- value={String(opacity)}
36
- min="0"
37
- max="100"
38
- text="true"
39
- units="%"
40
- full
41
- onInput={onInput}
42
- onChange={onChange}
43
- />
26
+ <fig-slider value="100" min="0" max="100" units="%" text="true" full />
44
27
  </fig-field>
45
28
  ```
46
-
47
- - Put control attrs on the control, not a wrapper.
48
- - Use `full` when the control should stretch.
49
- - Do not mix unrelated controls in one row unless grouped on purpose.
50
- - Add `fig-editor` when using `fig-select` / fill picker. Add `fig-lab` when using `propskit-*`.
51
-
52
- ## Control heuristics
53
-
54
- | Intent | Core | Lab wrapper |
55
- |---|---|---|
56
- | Boolean | `fig-switch` | `propskit-switch` |
57
- | Continuous number | `fig-slider` | `propskit-slider` |
58
- | Exact number | `fig-input-number` | `propskit-number` |
59
- | Text | `fig-input-text` | `propskit-text` |
60
- | Small discrete set (2–5) | `fig-segmented-control` | — |
61
- | Larger / rich list | `fig-select` (editor) | `propskit-select` |
62
- | Addable / renameable / removable list | `fig-select` + action buttons | `propskit-editable-select` |
63
- | Native select only | `fig-dropdown` | — |
64
- | Color | `fig-input-color` `text="true"` | `propskit-color` (fill-picker swatch) |
65
- | Fill | `fig-input-fill` | `propskit-fill` (fill-picker swatch) |
66
- | Gradient | `fig-input-gradient` | `propskit-gradient` |
67
- | Image | `fig-image` `upload` | `propskit-image` |
68
- | Easing | `fig-easing-curve` | — |
69
- | Angle | `fig-input-angle` (**lab**) | — |
70
- | X/Y | `fig-joystick` or two numbers | `propskit-position` |
71
-
72
- Do not use dropdown/slider for pure on/off. Do not use `fig-dropdown` for Figma-style property selects when `fig-select` is available.
73
-
74
- Secondary `fig-button` controls nested in PropsKit use the same borderless
75
- `--propskit-bg-subfield` treatment as ghost subfield selects. This treatment
76
- persists on hover and while disabled.
77
-
78
- ## Slider rules
79
-
80
- - Default `type="range"`. Always set `min`, `max`, `step`.
81
- - `opacity`: set `color`, usually `units="%"`
82
- - `hue`: hue workflows only
83
- - `stepper`: include a datalist of stops
84
- - `delta`: include `default`, often symmetric min/max
85
- - Text field on by default; `text="false"` for compact rows
86
- - `transform` when internal scale ≠ display scale
87
- - `variant="classic"` only when the old look is required
88
-
89
- Prompt style: imperative, include direction, tag, and behavior-critical attrs.
90
-
91
- ```txt
92
- Use a horizontal fig-field, with a fig-slider, min=0 max=100 text=true units=%. With a label of Opacity.
93
- ```
94
-
95
- ## Workflow
96
-
97
- 1. Identify intent (boolean, discrete, continuous, color/fill, media, motion).
98
- 2. Pick core vs lab wrapper.
99
- 3. Compose the row; set defaults explicitly.
100
- 4. Wire `onInput` (live) and `onChange` (commit).
101
- 5. Verify keyboard.