@rogieking/figui3 11.3.3 → 11.4.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.
@@ -133,6 +133,17 @@ Handlers below assume `onInput` / `onChange` / `onClick` from [react.md](react.m
133
133
 
134
134
  - Children stay in light DOM.
135
135
 
136
+ ### `fig-audio`
137
+
138
+ ```tsx
139
+ <fig-audio src="track.mp3" controls loop />
140
+ ```
141
+
142
+ - Attrs: `src`, `autoplay`, `controls`, `muted`, `loop`
143
+ - Composes a synchronized `fig-audio-waveform` and `fig-media-controls`.
144
+ - Authored direct waveform and controls children are preserved.
145
+ - Methods: `play()`, `pause()`, `toggle()`; `audioEl` exposes the native audio element.
146
+
136
147
  ### `fig-audio-waveform`
137
148
 
138
149
  ```tsx
@@ -72,6 +72,7 @@ type FigTag =
72
72
  | "fig-handle"
73
73
  | "fig-header"
74
74
  | "fig-icon"
75
+ | "fig-audio"
75
76
  | "fig-image"
76
77
  | "fig-input-color"
77
78
  | "fig-input-combo"
@@ -118,6 +118,7 @@ Without `fig-fill-picker`, fill/color render a preview. With the picker register
118
118
  ## Media
119
119
 
120
120
  - Surface lives in `fig-preview`
121
+ - `fig-audio`: `src`, `autoplay`, `controls`, `muted`, `loop`; composes waveform and shared controls
121
122
  - `fig-image` / `fig-video`: `upload`, `fit`, `aspect-ratio`, `checkerboard`, `loading-indicator`
122
123
  - Video controls render **below** the preview, not as an overlay
123
124
  - Slotted image overlays stay in light DOM
package/CHANGELOG.md CHANGED
@@ -2,6 +2,20 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## [11.4.0]
6
+
7
+ ### Added
8
+
9
+ - Added `fig-audio`, composing synchronized waveform and playback controls with autoplay, muted, and loop support.
10
+ - Added 16px and 24px video icons.
11
+ - Added `preview="large"` image and video upload previews and multi-file summaries to `fig-input-file`.
12
+
13
+ ### Changed
14
+
15
+ - Refined compact file previews with image swatches, audio waveforms, video detection, and explicit preview modes.
16
+ - Updated `fig-icon` to support authored SVG or character content without an implicit default icon.
17
+ - Expanded playground controls and examples for audio, file previews, and icon size, color, and character content.
18
+
5
19
  ## [11.3.3]
6
20
 
7
21
  ### Changed
package/README.md CHANGED
@@ -103,6 +103,7 @@ 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
+ | [Audio](#audio) | `<fig-audio>` | Waveform audio player with shared media controls |
106
107
  | [Audio Waveform](#audio-waveform) | `<fig-audio-waveform>` | Responsive waveform generated from an audio URL |
107
108
  | [Input Wheel](#input-wheel) | `<fig-input-wheel>` | Standalone SVG tick-and-handle numeric scrubber |
108
109
  | [Text Input](#text-input) | `<fig-input-text>` | Styled text/textarea input |
@@ -378,6 +379,29 @@ For `type="range"`, omitting `value` follows native range behavior and starts at
378
379
 
379
380
  ---
380
381
 
382
+ #### Audio
383
+
384
+ `<fig-audio>`
385
+
386
+ An audio player that composes `fig-audio-waveform` with the shared `fig-media-controls`. The waveform progress and playback controls stay synchronized with an internal native audio element.
387
+
388
+ | Attribute | Type | Default | Description |
389
+ |---|---|---|---|
390
+ | `src` | string | — | Audio URL used for playback and waveform generation |
391
+ | `autoplay` | boolean | `false` | Start playback automatically when allowed by the browser |
392
+ | `controls` | boolean | `false` | Show generated playback controls |
393
+ | `muted` | boolean | `false` | Mute audio playback |
394
+ | `loop` | boolean | `false` | Restart playback automatically when it ends |
395
+
396
+ Authored direct `fig-audio-waveform` and `fig-media-controls` children are preserved and synchronized. The `audioEl` property exposes the native audio element; `play()`, `pause()`, and `toggle()` control playback.
397
+
398
+ ```html
399
+ <fig-audio src="track.mp3" controls></fig-audio>
400
+ <fig-audio src="ambience.wav" autoplay muted loop></fig-audio>
401
+ ```
402
+
403
+ ---
404
+
381
405
  #### Audio Waveform
382
406
 
383
407
  `<fig-audio-waveform>`
@@ -493,17 +517,18 @@ The `value`, `min`, `max`, and `step` properties mirror their attributes. `aria-
493
517
  | Attribute | Type | Default | Description |
494
518
  |---|---|---|---|
495
519
  | `accepts` | string | — | Native file chooser filter |
496
- | `preview` | boolean | `false` | Preview supported images or enable button playback for supported audio files |
520
+ | `preview` | `"true"` \| `"false"` \| `"large"` | `false` | Show compact media previews, or use `large` for an upload-enabled `fig-image`/`fig-video` preview |
497
521
  | `label` | string | generated | Empty-state button label; defaults to `Upload audio`, `Upload image`, or `Upload file` from the known file type |
498
522
  | `multiple` | boolean | `false` | Allow multiple files |
499
523
  | `disabled` | boolean | `false` | Disabled state |
500
524
  | `variant` | string | `"property"` | Internal button variant |
501
525
 
502
- Known image and audio files use the image or sound icon; unmatched files retain the upload icon. With `preview`, image files render in a full-width 4:3 `fig-image`, while an audio file becomes a play/pause button with a polarized waveform, synchronized playback progress, and its filename in a tooltip. Image preview supports `.png`, `.jpg`, `.jpeg`, `.gif`, `.webp`, `.svg`, and `.avif`; audio playback supports `.mp3`, `.wav`, `.aac`, `.m4a`, `.ogg`, and `.flac`.
526
+ Known image and audio files use media-specific icons; unmatched files retain the upload icon. A present or `"true"` `preview` uses the compact image swatch, audio waveform playback, or video icon. `preview="large"` renders known images and videos as upload-enabled `fig-image` or `fig-video` previews; audio and other formats retain their compact preview behavior. `preview="false"` disables previews. Image preview supports `.png`, `.jpg`, `.jpeg`, `.gif`, `.webp`, `.svg`, and `.avif`; audio playback supports `.mp3`, `.wav`, `.aac`, `.m4a`, `.ogg`, and `.flac`; video detection supports common formats including `.mp4`, `.webm`, `.mov`, `.m4v`, `.avi`, `.mkv`, `.ogv`, `.mpeg`, `.mpg`, and `.3gp`.
503
527
 
504
528
  ```html
505
529
  <fig-input-file accepts="image/*"></fig-input-file>
506
530
  <fig-input-file accepts="image/*" preview></fig-input-file>
531
+ <fig-input-file accepts="video/*" preview="large"></fig-input-file>
507
532
  <fig-input-file accepts="audio/*"></fig-input-file>
508
533
  <fig-input-file accepts=".mp3,.opus" label="Choose audio"></fig-input-file>
509
534
  ```
package/components.css CHANGED
@@ -431,6 +431,8 @@
431
431
  --icon-24-sound-off: url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12.1465 11.9746C12.4615 11.6597 13 11.8827 13 12.3281V17.999C13 18.4034 12.7564 18.768 12.3828 18.9229C12.0092 19.0776 11.579 18.992 11.293 18.7061L8.58887 16.002C8.58705 16.0001 8.5846 15.9991 8.58203 15.999C8.41225 15.999 8.32734 15.794 8.44727 15.6738L8.78516 15.335C8.93708 15.1829 9.18394 15.183 9.33594 15.335L11.9834 17.9824C11.9897 17.988 12 17.9833 12 17.9746V12.3281C12 12.1955 12.0527 12.0684 12.1465 11.9746ZM15.1465 6.14648C15.3417 5.95122 15.6583 5.95122 15.8535 6.14648C16.0487 6.34176 16.0487 6.65829 15.8535 6.85352L4.85352 17.8535C4.65828 18.0486 4.34172 18.0486 4.14648 17.8535C3.95126 17.6583 3.95133 17.3418 4.14648 17.1465L15.1465 6.14648ZM11.293 5.29199C11.579 5.00601 12.0091 4.92042 12.3828 5.0752C12.7564 5.23001 13 5.59463 13 5.99902V6.67188C13 6.80445 12.9473 6.93165 12.8535 7.02539C12.5386 7.34027 12.0001 7.11723 12 6.67188V6.02344C12 6.01475 11.9897 6.01001 11.9834 6.01562L9.00293 8.99609C9.00111 8.9979 8.99865 8.99896 8.99609 8.99902H6.5C6.22387 8.99902 6.00002 9.22289 6 9.49902V13.6719C5.99993 13.8045 5.9473 13.9317 5.85352 14.0254L5.28125 14.5967C5.17556 14.7019 5.00003 14.6483 5 14.499V9.49902C5.00002 8.67061 5.67158 7.99902 6.5 7.99902H8.58203C8.58459 7.99896 8.58705 7.9979 8.58887 7.99609L11.293 5.29199Z' fill='black' fill-opacity='0.9'/%3E%3C/svg%3E");
432
432
  --icon-16-sound-off: url("data:image/svg+xml,%3Csvg width='16' height='16' viewBox='0 0 16 16' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12.1465 3.14648C12.3417 2.95139 12.6583 2.95139 12.8535 3.14648C13.0487 3.3417 13.0487 3.65824 12.8535 3.85352L3.85352 12.8535C3.65825 13.0488 3.34175 13.0488 3.14648 12.8535C2.95135 12.6582 2.95126 12.3417 3.14648 12.1465L12.1465 3.14648ZM10 12C9.99999 12.4044 9.7564 12.769 9.38281 12.9238C9.00916 13.0786 8.57895 12.993 8.29297 12.707L6.85352 11.2676L7.56055 10.5605L9 12V9.12109L10 8.12109V12ZM8.29297 3.29297C8.57896 3.00699 9.00915 2.92142 9.38281 3.07617C9.72107 3.21634 9.95041 3.52875 9.99121 3.88672L9 4.87891V4L7 6H5.5C5.22389 6.00002 5.00002 6.22388 5 6.5V8.87891L4.03906 9.83887C4.01389 9.72993 4 9.61658 4 9.5V6.5C4.00002 5.6716 4.6716 5.00002 5.5 5H6.58594L8.29297 3.29297Z' fill='black' fill-opacity='0.9'/%3E%3C/svg%3E");
433
433
  --icon-24-image: url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M7.5 6C6.67157 6 6 6.67157 6 7.5V16.5C6 17.3284 6.67157 18 7.5 18H16.5C17.3284 18 18 17.3284 18 16.5V7.5C18 6.67157 17.3284 6 16.5 6H7.5ZM7 7.5C7 7.22386 7.22386 7 7.5 7H16.5C16.7761 7 17 7.22386 17 7.5V14.793L14.3536 12.1464C14.1583 11.9512 13.8417 11.9512 13.6464 12.1464L12 13.7929L9.85355 11.6464C9.65829 11.4512 9.34171 11.4512 9.14645 11.6464L7 13.7929V7.5ZM7 15.2071V16.5C7 16.7761 7.22386 17 7.5 17H16.5C16.7761 17 17 16.7761 17 16.5V16.2071L14 13.2071L12.3536 14.8536C12.1583 15.0488 11.8417 15.0488 11.6464 14.8536L9.5 12.7071L7 15.2071ZM13.5 8C14.3284 8 15 8.67157 15 9.5C15 10.3284 14.3284 11 13.5 11C12.6716 11 12 10.3284 12 9.5C12 8.67157 12.6716 8 13.5 8ZM13.5 9C13.2239 9 13 9.22386 13 9.5C13 9.77614 13.2239 10 13.5 10C13.7761 10 14 9.77614 14 9.5C14 9.22386 13.7761 9 13.5 9Z' fill='black' fill-opacity='0.9'/%3E%3C/svg%3E");
434
+ --icon-24-video: url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M16 6C17.1046 6 18 6.89543 18 8V16C18 17.1046 17.1046 18 16 18H8C6.89543 18 6 17.1046 6 16V8C6 6.89543 6.89543 6 8 6H16ZM8 7C7.44772 7 7 7.44772 7 8V16C7 16.5523 7.44772 17 8 17H16C16.5523 17 17 16.5523 17 16V8C17 7.44772 16.5523 7 16 7H8ZM9.99805 9.13477C10.3063 8.95591 10.6866 8.955 10.9961 9.13184L14.4961 11.1318C14.8077 11.3099 15 11.6411 15 12C15 12.3589 14.8077 12.6901 14.4961 12.8682L10.9961 14.8682C10.6866 15.045 10.3063 15.0441 9.99805 14.8652C9.68973 14.6863 9.5 14.3565 9.5 14V10C9.5 9.64353 9.68973 9.31369 9.99805 9.13477ZM10.5 14L14 12L10.5 10V14Z' fill='black' fill-opacity='0.9'/%3E%3C/svg%3E");
435
+ --icon-16-video: url("data:image/svg+xml,%3Csvg width='16' height='16' viewBox='0 0 16 16' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M11.5 3C12.3284 3 13 3.67157 13 4.5V11.5C13 12.3284 12.3284 13 11.5 13H4.5L4.34668 12.9922C3.59028 12.9154 3 12.2767 3 11.5V4.5C3 3.67157 3.67157 3 4.5 3H11.5ZM4.5 4C4.22386 4 4 4.22386 4 4.5V11.5C4 11.7761 4.22386 12 4.5 12H11.5C11.7761 12 12 11.7761 12 11.5V4.5C12 4.22386 11.7761 4 11.5 4H4.5ZM6.50684 5.62988C6.82034 5.45238 7.20572 5.45722 7.51465 5.64258L10.0146 7.14258C10.3158 7.32332 10.5 7.64879 10.5 8C10.5 8.35121 10.3158 8.67668 10.0146 8.85742L7.51465 10.3574C7.20572 10.5428 6.82034 10.5476 6.50684 10.3701C6.19356 10.1926 6 9.86012 6 9.5V6.5C6 6.13988 6.19356 5.80744 6.50684 5.62988ZM7 9.5L9.5 8L7 6.5V9.5Z' fill='black' fill-opacity='0.9'/%3E%3C/svg%3E");
434
436
  --tip-pointer: path("M8 6L2 0H14L8 6Z");
435
437
 
436
438
 
@@ -1673,14 +1675,7 @@ input[type="color"] {
1673
1675
  }
1674
1676
  }
1675
1677
 
1676
- /* Gradient/Image types - inset thumbnail with hidden input */
1677
- &[data-type="gradient"],
1678
- &[data-type="image"] {
1679
- background-color: var(--figma-color-bg-secondary);
1680
- input[type="color"] {
1681
- display: none;
1682
- }
1683
- }
1678
+
1684
1679
  }
1685
1680
 
1686
1681
  /* Fig Image */
@@ -1749,7 +1744,7 @@ fig-audio-waveform {
1749
1744
 
1750
1745
  .fig-audio-waveform-surface {
1751
1746
  display: block;
1752
- width: calc(100% - var(--spacer-3));
1747
+ width: 100%;
1753
1748
  height: 100%;
1754
1749
  }
1755
1750
 
@@ -1771,6 +1766,29 @@ fig-audio-waveform {
1771
1766
  }
1772
1767
  }
1773
1768
 
1769
+ fig-audio {
1770
+ display: inline-flex;
1771
+ flex-direction: column;
1772
+ align-items: stretch;
1773
+ gap: var(--spacer-2);
1774
+ width: 100%;
1775
+ max-width: 100%;
1776
+ min-width: 0;
1777
+
1778
+ > audio {
1779
+ display: none;
1780
+ }
1781
+
1782
+ > fig-audio-waveform,
1783
+ > fig-media-controls {
1784
+ width: 100%;
1785
+ min-width: 0;
1786
+ }
1787
+ > fig-audio-waveform{
1788
+ padding: 0 var(--spacer-2);
1789
+ }
1790
+ }
1791
+
1774
1792
  fig-input-file {
1775
1793
  display: flex;
1776
1794
  align-items: center;
@@ -1849,6 +1867,10 @@ fig-input-file {
1849
1867
  }
1850
1868
  }
1851
1869
 
1870
+ :is(fig-swatch, fig-chit) {
1871
+ background-color: transparent;
1872
+ }
1873
+
1852
1874
  &[dragover] fig-button {
1853
1875
  outline: 1px dashed var(--figma-color-border-brand);
1854
1876
  outline-offset: -1px;
@@ -6466,7 +6488,7 @@ fig-toolbelt {
6466
6488
  .fig-mask-icon,
6467
6489
  fig-icon {
6468
6490
  --size: var(--spacer-4);
6469
- --icon: var(--icon-24-add);
6491
+ --icon: none;
6470
6492
 
6471
6493
  &[size="small"] {
6472
6494
  --size: var(--spacer-3);
@@ -6475,24 +6497,39 @@ fig-icon {
6475
6497
  display: inline-flex;
6476
6498
  width: var(--size);
6477
6499
  height: var(--size);
6500
+ align-items: center;
6501
+ justify-content: center;
6478
6502
  background: currentColor;
6479
- mask-image: var(--icon);
6480
- mask-size: auto;
6481
- mask-repeat: no-repeat;
6482
- mask-position: center;
6483
6503
  flex-shrink: 0;
6504
+ /* Safari still requires the prefix; other engines use the standard form. */
6484
6505
  -webkit-mask-image: var(--icon);
6485
6506
  -webkit-mask-size: auto;
6486
6507
  -webkit-mask-repeat: no-repeat;
6487
6508
  -webkit-mask-position: center;
6509
+ mask-image: var(--icon);
6510
+ mask-size: auto;
6511
+ mask-repeat: no-repeat;
6512
+ mask-position: center;
6488
6513
 
6489
- /* Slotted SVGs paint themselves, so the mask/background pipeline must be
6514
+ /* Slotted SVGs/character icons paint themselves, so the mask/background pipeline must be
6490
6515
  fully disabled — including the inline background-color set by [color]. */
6491
- &:has(> svg) {
6516
+ &:has(> *),
6517
+ &:not([name]) {
6492
6518
  background: transparent !important;
6493
6519
  color: var(--icon-color, inherit);
6494
- mask-image: none;
6495
6520
  -webkit-mask-image: none;
6521
+ mask-image: none;
6522
+ }
6523
+
6524
+ &:not([name]) {
6525
+ align-items: center;
6526
+ justify-content: center;
6527
+ }
6528
+
6529
+ & > label {
6530
+ color: inherit;
6531
+ font: inherit;
6532
+ line-height: 1;
6496
6533
  }
6497
6534
 
6498
6535
  & > svg {