rift-ds 1.1.0 → 1.3.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.
Files changed (59) hide show
  1. package/README.md +2 -2
  2. package/components/Chart/BarChart.js +1 -1
  3. package/components/Chart/ComboChart.js +1 -1
  4. package/components/Chart/Treemap.js +83 -6
  5. package/components/ColorPicker/ColorPicker.js +1 -1
  6. package/components/Composer/Composer.css +45 -3
  7. package/components/Composer/Composer.d.ts +14 -6
  8. package/components/Composer/Composer.js +25 -5
  9. package/components/DatePicker/DatePicker.css +1 -1
  10. package/components/EventCalendar/EventCalendar.css +2 -2
  11. package/components/FileInput/FileInput.css +1 -1
  12. package/components/Globe/Globe.d.ts +5 -3
  13. package/components/Globe/Globe.js +18 -2
  14. package/components/Inspector/Inspector.css +616 -0
  15. package/components/Inspector/InspectorColorPicker.d.ts +43 -0
  16. package/components/Inspector/InspectorColorPicker.js +51 -0
  17. package/components/Inspector/InspectorDropdown.d.ts +39 -0
  18. package/components/Inspector/InspectorDropdown.js +68 -0
  19. package/components/Inspector/InspectorInput.d.ts +32 -0
  20. package/components/Inspector/InspectorInput.js +52 -0
  21. package/components/Inspector/InspectorSection.d.ts +32 -0
  22. package/components/Inspector/InspectorSection.js +70 -0
  23. package/components/Inspector/InspectorSegmentedControl.d.ts +46 -0
  24. package/components/Inspector/InspectorSegmentedControl.js +62 -0
  25. package/components/Inspector/InspectorSlider.d.ts +41 -0
  26. package/components/Inspector/InspectorSlider.js +81 -0
  27. package/components/Inspector/InspectorToggleSwitch.d.ts +29 -0
  28. package/components/Inspector/InspectorToggleSwitch.js +51 -0
  29. package/components/Instructions/Instructions.css +4 -4
  30. package/components/Prose/Prose.css +27 -0
  31. package/components/SegmentedControl/SegmentedControl.css +7 -5
  32. package/components/Sparkline/Sparkline.css +2 -2
  33. package/components/Spinner/Spinner.css +1 -1
  34. package/components/Timeline/Timeline.css +1 -1
  35. package/components/WorldMap/land.d.ts +1 -1
  36. package/components/registry.json +69 -1
  37. package/components/registry.json.d.ts +69 -1
  38. package/components/registry.json.js +2 -2
  39. package/index.d.ts +7 -0
  40. package/index.js +14 -0
  41. package/package.json +1 -1
  42. package/tokens/motion.d.ts +2 -0
  43. package/tokens/motion.js +2 -0
  44. package/tokens/presets/contrast.css +2 -4
  45. package/tokens/presets/coral.css +2 -4
  46. package/tokens/presets/forest.css +2 -4
  47. package/tokens/presets/gold.css +4 -4
  48. package/tokens/presets/mono.css +0 -2
  49. package/tokens/presets/pink.css +4 -4
  50. package/tokens/presets/terminal.css +5 -4
  51. package/tokens/presets/violet.css +2 -4
  52. package/tokens/presets/warm.css +3 -4
  53. package/tokens/presets/zest.css +2 -4
  54. package/tokens/registry.json +1 -0
  55. package/tokens/registry.json.d.ts +1 -0
  56. package/tokens/registry.json.js +1 -1
  57. package/tokens/tokens-dark.css +8 -5
  58. package/tokens/tokens-light.css +4 -2
  59. package/tokens/tokens-motion.css +2 -0
@@ -0,0 +1,616 @@
1
+ /* ============================================
2
+ INSPECTOR FAMILY
3
+ One-row controls for tool panels and settings
4
+ rails: each control is one bar with its name
5
+ inside on the left and its state on the right.
6
+ The form controls (Slider, Input, ToggleSwitch,
7
+ SegmentedControl, Dropdown, ColorPicker) keep
8
+ their label
9
+ above; these are their counterparts for a
10
+ dense panel.
11
+
12
+ Shaped and sized like Button, not like Input:
13
+ the bar reads --radius-pill, and its height,
14
+ side inset and type are computed from the
15
+ Button's own tokens for the same size, so a
16
+ bar and a Button of one size sit level.
17
+
18
+ Colour climbs the neutral Button's ladder one
19
+ step per state, which holds in both themes:
20
+ bar passive-hover (neutral fill at
21
+ 80%: a step off
22
+ a glass panel)
23
+ fill neutral-bg-hover (a slider's value,
24
+ a hovered bar, a
25
+ selected segment)
26
+ press neutral-bg-active
27
+ Nothing in the family takes the action colour
28
+ except the focus ring: a selected segment and
29
+ an on switch are neutral, the same call
30
+ SegmentedControl's `neutral` variant makes.
31
+ ============================================ */
32
+
33
+ /* ---------- size ----------
34
+ default 8px + 24px line + 8px = 40px, 20px sides, paragraph-emphasis
35
+ compact 6px + 20px line + 6px = 32px, 12px sides, paragraph-sm-emphasis */
36
+ .ds-inspector-bar,
37
+ .ds-inspector-dropdown,
38
+ .ds-inspector-color-picker {
39
+ --ds-inspector-height: calc(2 * var(--padding-200) + var(--font-paragraph-emphasis-line-height));
40
+ --ds-inspector-inset: var(--padding-500);
41
+ --ds-inspector-font-family: var(--font-paragraph-emphasis-family);
42
+ --ds-inspector-font-size: var(--font-paragraph-emphasis-size);
43
+ --ds-inspector-line-height: var(--font-paragraph-emphasis-line-height);
44
+ --ds-inspector-letter-spacing: var(--font-paragraph-emphasis-letter-spacing);
45
+ --ds-inspector-label-weight: var(--font-paragraph-emphasis-weight);
46
+ --ds-inspector-value-weight: var(--font-paragraph-weight);
47
+ }
48
+
49
+ .ds-inspector-bar--compact,
50
+ .ds-inspector-dropdown--compact,
51
+ .ds-inspector-color-picker--compact {
52
+ --ds-inspector-height: calc(2 * var(--padding-150) + var(--font-paragraph-sm-emphasis-line-height));
53
+ --ds-inspector-inset: var(--padding-300);
54
+ --ds-inspector-font-family: var(--font-paragraph-sm-emphasis-family);
55
+ --ds-inspector-font-size: var(--font-paragraph-sm-emphasis-size);
56
+ --ds-inspector-line-height: var(--font-paragraph-sm-emphasis-line-height);
57
+ --ds-inspector-letter-spacing: var(--font-paragraph-sm-emphasis-letter-spacing);
58
+ --ds-inspector-label-weight: var(--font-paragraph-sm-emphasis-weight);
59
+ --ds-inspector-value-weight: var(--font-paragraph-sm-weight);
60
+ }
61
+
62
+ /* ============================================
63
+ THE BAR (shared by every control but the dropdown,
64
+ which dresses the library Dropdown's trigger instead)
65
+ ============================================ */
66
+
67
+ .ds-inspector-bar {
68
+ position: relative;
69
+ display: flex;
70
+ align-items: center;
71
+ justify-content: space-between;
72
+ gap: var(--gap-300);
73
+ min-width: 0;
74
+ box-sizing: border-box;
75
+ height: var(--ds-inspector-height);
76
+ padding: 0 var(--ds-inspector-inset);
77
+ overflow: hidden;
78
+ border-radius: var(--radius-pill);
79
+ background: var(--color-action-passive-bg-hover);
80
+ font-family: var(--ds-inspector-font-family);
81
+ font-size: var(--ds-inspector-font-size);
82
+ line-height: var(--ds-inspector-line-height);
83
+ letter-spacing: var(--ds-inspector-letter-spacing);
84
+ font-weight: var(--ds-inspector-value-weight);
85
+ color: var(--color-text-secondary);
86
+ transition: background-color var(--motion-duration-fast) var(--motion-ease-standard);
87
+ }
88
+
89
+ .ds-inspector-bar:has(:focus-visible) {
90
+ outline: 2px solid var(--color-action-primary-bg);
91
+ outline-offset: 2px;
92
+ }
93
+
94
+ .ds-inspector-bar__label {
95
+ position: relative;
96
+ flex-shrink: 0;
97
+ white-space: nowrap;
98
+ font-weight: var(--ds-inspector-label-weight);
99
+ color: var(--color-text-primary);
100
+ pointer-events: none;
101
+ }
102
+
103
+ .ds-inspector-bar__value {
104
+ position: relative;
105
+ min-width: 0;
106
+ overflow: hidden;
107
+ text-overflow: ellipsis;
108
+ white-space: nowrap;
109
+ font-variant-numeric: tabular-nums;
110
+ pointer-events: none;
111
+ }
112
+
113
+ /* An invisible native control laid over the whole bar: the platform's
114
+ pointer, keyboard and screen-reader behaviour, none of its paint. */
115
+ .ds-inspector-bar__native {
116
+ position: absolute;
117
+ inset: 0;
118
+ width: 100%;
119
+ height: 100%;
120
+ margin: 0;
121
+ opacity: 0;
122
+ cursor: pointer;
123
+ appearance: none;
124
+ background: transparent;
125
+ }
126
+
127
+ /* Disabled: the system's 0.4 and not-allowed, on the whole bar. */
128
+ .ds-inspector-bar--disabled {
129
+ opacity: 0.4;
130
+ cursor: not-allowed;
131
+ }
132
+
133
+ .ds-inspector-bar--disabled * {
134
+ cursor: not-allowed;
135
+ }
136
+
137
+ /* ============================================
138
+ SLIDER — the fill is the value
139
+ ============================================ */
140
+
141
+ .ds-inspector-slider__fill {
142
+ position: absolute;
143
+ inset: 0 auto 0 0;
144
+ width: var(--ds-inspector-pct, 0%);
145
+ background: var(--color-action-neutral-bg-hover);
146
+ transition: background-color var(--motion-duration-fast) var(--motion-ease-standard);
147
+ pointer-events: none;
148
+ }
149
+
150
+ .ds-inspector-slider:not(.ds-inspector-bar--disabled):hover .ds-inspector-slider__fill,
151
+ .ds-inspector-slider:has(:active) .ds-inspector-slider__fill {
152
+ background: var(--color-action-neutral-bg-active);
153
+ }
154
+
155
+ /* A short grip line just inside the fill's edge, held off both ends of the
156
+ bar so it never sits on the rounded corners. */
157
+ .ds-inspector-slider__grip {
158
+ position: absolute;
159
+ top: 30%;
160
+ bottom: 30%;
161
+ left: clamp(
162
+ var(--padding-200),
163
+ calc(var(--ds-inspector-pct, 0%) - var(--padding-200)),
164
+ calc(100% - var(--padding-200))
165
+ );
166
+ width: calc(var(--border-050) * 1.5);
167
+ border-radius: var(--radius-pill);
168
+ background: var(--color-text-secondary);
169
+ pointer-events: none;
170
+ /* Never `left`: the grip tracks the drag, and easing it would lag. */
171
+ transition:
172
+ top var(--motion-duration-fast) var(--motion-ease-standard),
173
+ bottom var(--motion-duration-fast) var(--motion-ease-standard),
174
+ background-color var(--motion-duration-fast) var(--motion-ease-standard);
175
+ }
176
+
177
+ .ds-inspector-slider:not(.ds-inspector-bar--disabled):hover .ds-inspector-slider__grip {
178
+ background: var(--color-text-primary);
179
+ }
180
+
181
+ /* Held: the grip stands up taller, so the bar reads as gripped. */
182
+ .ds-inspector-slider:has(:active) .ds-inspector-slider__grip {
183
+ top: 22%;
184
+ bottom: 22%;
185
+ background: var(--color-text-primary);
186
+ }
187
+
188
+ .ds-inspector-slider .ds-inspector-bar__native {
189
+ cursor: ew-resize;
190
+ }
191
+
192
+ .ds-inspector-slider:has(:active) .ds-inspector-bar__native {
193
+ cursor: grabbing;
194
+ }
195
+
196
+ /* The range's thumb is drawn one hairline-pair wide, so the input's
197
+ value-to-position mapping stays within a pixel of the painted fill. */
198
+ .ds-inspector-slider .ds-inspector-bar__native::-webkit-slider-thumb {
199
+ appearance: none;
200
+ width: var(--border-050);
201
+ height: 100%;
202
+ }
203
+
204
+ .ds-inspector-slider .ds-inspector-bar__native::-moz-range-thumb {
205
+ width: var(--border-050);
206
+ height: 100%;
207
+ border: none;
208
+ }
209
+
210
+ /* ============================================
211
+ INPUT — name left, the field in the rest
212
+ ============================================ */
213
+
214
+ .ds-inspector-input {
215
+ cursor: text;
216
+ }
217
+
218
+ .ds-inspector-input:not(.ds-inspector-bar--disabled):hover,
219
+ .ds-inspector-input:focus-within {
220
+ background: var(--color-action-neutral-bg-hover);
221
+ }
222
+
223
+ /* The name is a real <label>, so a click on it focuses the field. */
224
+ .ds-inspector-input .ds-inspector-bar__label {
225
+ pointer-events: auto;
226
+ cursor: text;
227
+ }
228
+
229
+ .ds-inspector-input__field {
230
+ flex: 1;
231
+ /* width 0 + flex 1: the field takes the bar's spare room and never asks
232
+ for its intrinsic 20-character width, which would push its container. */
233
+ width: 0;
234
+ min-width: 0;
235
+ padding: 0;
236
+ border: none;
237
+ outline: none;
238
+ background: transparent;
239
+ font: inherit;
240
+ text-align: right;
241
+ color: var(--color-text-primary);
242
+ }
243
+
244
+ .ds-inspector-input__field::placeholder {
245
+ color: var(--color-text-tertiary);
246
+ }
247
+
248
+ /* ============================================
249
+ TOGGLE SWITCH — the whole bar is the switch
250
+ ============================================ */
251
+
252
+ .ds-inspector-toggle-switch:not(.ds-inspector-bar--disabled):hover {
253
+ background: var(--color-action-neutral-bg-hover);
254
+ }
255
+
256
+ .ds-inspector-toggle-switch:has(:active) {
257
+ background: var(--color-action-neutral-bg-active);
258
+ }
259
+
260
+ .ds-inspector-toggle-switch__track {
261
+ position: relative;
262
+ flex-shrink: 0;
263
+ width: calc(var(--padding-400) * 1.75);
264
+ height: var(--padding-400);
265
+ border-radius: var(--radius-pill);
266
+ background: var(--color-action-neutral-bg-active);
267
+ transition: background-color var(--motion-duration-fast) var(--motion-ease-standard);
268
+ pointer-events: none;
269
+ }
270
+
271
+ .ds-inspector-toggle-switch__knob {
272
+ position: absolute;
273
+ top: var(--border-050);
274
+ left: var(--border-050);
275
+ width: calc(var(--padding-400) - 2 * var(--border-050));
276
+ height: calc(var(--padding-400) - 2 * var(--border-050));
277
+ border-radius: var(--radius-pill);
278
+ background: var(--color-bg-container-primary);
279
+ transition: transform var(--motion-duration-base) var(--motion-ease-entrance);
280
+ }
281
+
282
+ /* On reads from the native checkbox itself, so the paint is right whether
283
+ the switch is controlled or not. Monochrome on purpose: on is the primary
284
+ text colour, not the action colour. */
285
+ .ds-inspector-toggle-switch:has(.ds-inspector-bar__native:checked) .ds-inspector-toggle-switch__track {
286
+ background: var(--color-text-primary);
287
+ }
288
+
289
+ .ds-inspector-toggle-switch:has(.ds-inspector-bar__native:checked) .ds-inspector-toggle-switch__knob {
290
+ transform: translateX(calc(var(--padding-400) * 0.75));
291
+ }
292
+
293
+ /* ============================================
294
+ SEGMENTED CONTROL — name left, choices right
295
+ ============================================ */
296
+
297
+ /* The bar's own inset shrinks on the right, so the selected segment sits
298
+ as an inset chip in the bar's end rather than touching its edge. */
299
+ .ds-inspector-segmented-control {
300
+ padding-right: var(--padding-100);
301
+ }
302
+
303
+ /* Focus rings the segment, not the whole bar. */
304
+ .ds-inspector-segmented-control:has(:focus-visible) {
305
+ outline: none;
306
+ }
307
+
308
+ .ds-inspector-segmented-control__segments {
309
+ position: relative;
310
+ display: flex;
311
+ gap: var(--gap-050);
312
+ min-width: 0;
313
+ }
314
+
315
+ .ds-inspector-segmented-control__segment {
316
+ position: relative;
317
+ padding: var(--padding-050) var(--padding-200);
318
+ /* The chip nests in the bar's end, so it shares the bar's shape. */
319
+ border-radius: var(--radius-pill);
320
+ white-space: nowrap;
321
+ cursor: pointer;
322
+ transition:
323
+ background-color var(--motion-duration-fast) var(--motion-ease-standard),
324
+ color var(--motion-duration-fast) var(--motion-ease-standard);
325
+ }
326
+
327
+ .ds-inspector-segmented-control__segment:not(:has(:disabled)):hover {
328
+ color: var(--color-text-primary);
329
+ background: var(--color-action-passive-bg-active);
330
+ }
331
+
332
+ .ds-inspector-segmented-control__segment:has(:checked) {
333
+ color: var(--color-text-primary);
334
+ font-weight: var(--ds-inspector-label-weight);
335
+ background: var(--color-action-neutral-bg-hover);
336
+ }
337
+
338
+ .ds-inspector-segmented-control__segment:not(:has(:disabled)):active {
339
+ background: var(--color-action-neutral-bg-active);
340
+ }
341
+
342
+ .ds-inspector-segmented-control__segment:has(:focus-visible) {
343
+ outline: 2px solid var(--color-action-primary-bg);
344
+ outline-offset: 0;
345
+ }
346
+
347
+ .ds-inspector-segmented-control__segment:has(:disabled) {
348
+ opacity: 0.4;
349
+ cursor: not-allowed;
350
+ }
351
+
352
+ /* The radio itself is invisible; its segment is the target. */
353
+ .ds-inspector-segmented-control__radio {
354
+ position: absolute;
355
+ inset: 0;
356
+ margin: 0;
357
+ opacity: 0;
358
+ cursor: inherit;
359
+ }
360
+
361
+ /* ============================================
362
+ DROPDOWN — the library Dropdown, dressed as a bar
363
+ ============================================ */
364
+
365
+ .ds-inspector-dropdown {
366
+ position: relative;
367
+ min-width: 0;
368
+ }
369
+
370
+ .ds-inspector-dropdown__label {
371
+ position: absolute;
372
+ top: 50%;
373
+ left: var(--ds-inspector-inset);
374
+ z-index: 1;
375
+ transform: translateY(-50%);
376
+ white-space: nowrap;
377
+ font-family: var(--ds-inspector-font-family);
378
+ font-size: var(--ds-inspector-font-size);
379
+ font-weight: var(--ds-inspector-label-weight);
380
+ line-height: var(--ds-inspector-line-height);
381
+ letter-spacing: var(--ds-inspector-letter-spacing);
382
+ color: var(--color-text-primary);
383
+ pointer-events: none;
384
+ }
385
+
386
+ .ds-inspector-dropdown .ds-dropdown__trigger {
387
+ box-sizing: border-box;
388
+ height: var(--ds-inspector-height);
389
+ padding: 0 calc(var(--ds-inspector-inset) - var(--padding-100)) 0
390
+ calc(var(--ds-inspector-inset) + var(--ds-inspector-label-width, 0px) + var(--gap-300));
391
+ border-color: transparent;
392
+ border-radius: var(--radius-pill);
393
+ background: var(--color-action-passive-bg-hover);
394
+ transition: background-color var(--motion-duration-fast) var(--motion-ease-standard);
395
+ }
396
+
397
+ .ds-inspector-dropdown .ds-dropdown__trigger:hover:not(:focus-visible),
398
+ .ds-inspector-dropdown .ds-dropdown--open .ds-dropdown__trigger {
399
+ border-color: transparent;
400
+ background: var(--color-action-neutral-bg-hover);
401
+ }
402
+
403
+ .ds-inspector-dropdown .ds-dropdown__trigger:active {
404
+ background: var(--color-action-neutral-bg-active);
405
+ }
406
+
407
+ /* The trigger's selected-border focus becomes the family's ring, so every
408
+ inspector control shows focus the same way. */
409
+ .ds-inspector-dropdown .ds-dropdown__trigger:focus-visible {
410
+ border-color: transparent;
411
+ outline: 2px solid var(--color-action-primary-bg);
412
+ outline-offset: 2px;
413
+ }
414
+
415
+ .ds-inspector-dropdown .ds-dropdown__value {
416
+ text-align: right;
417
+ font-family: var(--ds-dropdown-font, var(--ds-inspector-font-family));
418
+ font-size: var(--ds-inspector-font-size);
419
+ font-weight: var(--ds-inspector-value-weight);
420
+ line-height: var(--ds-inspector-line-height);
421
+ letter-spacing: var(--ds-inspector-letter-spacing);
422
+ color: var(--color-text-secondary);
423
+ }
424
+
425
+ .ds-inspector-dropdown .ds-dropdown__chevron {
426
+ --icon-size: var(--icon-size-500);
427
+ color: var(--color-icon-secondary);
428
+ }
429
+
430
+ /* ============================================
431
+ COLOR PICKER — the library ColorPicker, dressed as a bar
432
+ ============================================ */
433
+
434
+ .ds-inspector-color-picker {
435
+ position: relative;
436
+ min-width: 0;
437
+ }
438
+
439
+ /* The name rides over the trigger and lets clicks through, so the whole
440
+ bar opens the panel. The reading sits at the far end, so no room needs
441
+ reserving for the name the way the dropdown's left-aligned value does. */
442
+ .ds-inspector-color-picker__label {
443
+ position: absolute;
444
+ top: calc(var(--ds-inspector-height) / 2);
445
+ left: var(--ds-inspector-inset);
446
+ z-index: 1;
447
+ transform: translateY(-50%);
448
+ white-space: nowrap;
449
+ font-family: var(--ds-inspector-font-family);
450
+ font-size: var(--ds-inspector-font-size);
451
+ font-weight: var(--ds-inspector-label-weight);
452
+ line-height: var(--ds-inspector-line-height);
453
+ letter-spacing: var(--ds-inspector-letter-spacing);
454
+ color: var(--color-text-primary);
455
+ pointer-events: none;
456
+ }
457
+
458
+ .ds-inspector-color-picker .ds-colorpicker {
459
+ display: flex;
460
+ align-items: stretch;
461
+ width: 100%;
462
+ }
463
+
464
+ /* The swatch is a circle one line tall, so its end inset is whatever
465
+ centres it in the bar: concentric with the pill's end cap. */
466
+ .ds-inspector-color-picker .ds-colorpicker__trigger {
467
+ justify-content: flex-end;
468
+ gap: var(--gap-300);
469
+ width: 100%;
470
+ box-sizing: border-box;
471
+ height: var(--ds-inspector-height);
472
+ padding: 0 calc((var(--ds-inspector-height) - var(--ds-inspector-line-height)) / 2) 0
473
+ var(--ds-inspector-inset);
474
+ border-color: transparent;
475
+ border-radius: var(--radius-pill);
476
+ background: var(--color-action-passive-bg-hover);
477
+ transition: background-color var(--motion-duration-fast) var(--motion-ease-standard);
478
+ }
479
+
480
+ .ds-inspector-color-picker .ds-colorpicker__trigger:hover:not(:disabled),
481
+ .ds-inspector-color-picker .ds-colorpicker--open .ds-colorpicker__trigger {
482
+ border-color: transparent;
483
+ background: var(--color-action-neutral-bg-hover);
484
+ }
485
+
486
+ .ds-inspector-color-picker .ds-colorpicker__trigger:active:not(:disabled) {
487
+ background: var(--color-action-neutral-bg-active);
488
+ }
489
+
490
+ /* The trigger's selected-border focus becomes the family's ring. */
491
+ .ds-inspector-color-picker .ds-colorpicker__trigger:focus-visible {
492
+ border-color: transparent;
493
+ outline: 2px solid var(--color-action-primary-bg);
494
+ outline-offset: 2px;
495
+ }
496
+
497
+ /* The reading comes before the swatch, so the colour sits at the bar's end
498
+ where the switch's track and the dropdown's chevron sit. */
499
+ .ds-inspector-color-picker .ds-colorpicker__trigger-text {
500
+ order: -1;
501
+ padding-right: 0;
502
+ font-family: var(--ds-inspector-font-family);
503
+ font-size: var(--ds-inspector-font-size);
504
+ font-weight: var(--ds-inspector-value-weight);
505
+ line-height: var(--ds-inspector-line-height);
506
+ letter-spacing: var(--ds-inspector-letter-spacing);
507
+ color: var(--color-text-secondary);
508
+ }
509
+
510
+ .ds-inspector-color-picker .ds-colorpicker__trigger-swatch {
511
+ width: var(--ds-inspector-line-height);
512
+ height: var(--ds-inspector-line-height);
513
+ border-radius: var(--radius-pill);
514
+ }
515
+
516
+ /* The panel opens under the bar and spans it. */
517
+ .ds-inspector-color-picker .ds-colorpicker__panel {
518
+ right: 0;
519
+ width: auto;
520
+ }
521
+
522
+ /* Disabled dims the whole bar, name included, rather than the trigger alone. */
523
+ .ds-inspector-color-picker--disabled {
524
+ opacity: 0.4;
525
+ cursor: not-allowed;
526
+ }
527
+
528
+ .ds-inspector-color-picker--disabled .ds-colorpicker__trigger {
529
+ opacity: 1;
530
+ }
531
+
532
+ /* ============================================
533
+ SECTION — a collapsible, titled run of controls
534
+ ============================================ */
535
+
536
+ .ds-inspector-section {
537
+ display: flex;
538
+ flex-direction: column;
539
+ border-bottom: var(--border-025) solid var(--color-divider);
540
+ }
541
+
542
+ .ds-inspector-section:last-of-type {
543
+ border-bottom: none;
544
+ }
545
+
546
+ .ds-inspector-section__trigger {
547
+ display: flex;
548
+ align-items: center;
549
+ justify-content: space-between;
550
+ gap: var(--gap-200);
551
+ width: 100%;
552
+ padding: var(--padding-300) 0;
553
+ background: none;
554
+ border: none;
555
+ border-radius: var(--radius-200);
556
+ cursor: pointer;
557
+ text-align: left;
558
+ font-family: var(--font-paragraph-emphasis-family);
559
+ font-size: var(--font-paragraph-emphasis-size);
560
+ font-weight: var(--font-paragraph-emphasis-weight);
561
+ line-height: var(--font-paragraph-emphasis-line-height);
562
+ letter-spacing: var(--font-paragraph-emphasis-letter-spacing);
563
+ color: var(--color-text-primary);
564
+ }
565
+
566
+ .ds-inspector-section__trigger:focus-visible {
567
+ outline: 2px solid var(--color-action-primary-bg);
568
+ outline-offset: 2px;
569
+ }
570
+
571
+ .ds-inspector-section__icon {
572
+ flex-shrink: 0;
573
+ --icon-size: var(--icon-size-500);
574
+ color: var(--color-icon-secondary);
575
+ transition: transform var(--motion-duration-slow) var(--motion-ease-emphasized);
576
+ }
577
+
578
+ .ds-inspector-section--open .ds-inspector-section__icon {
579
+ transform: rotate(180deg);
580
+ }
581
+
582
+ .ds-inspector-section__panel {
583
+ display: grid;
584
+ /* minmax(0, 1fr), not auto: an auto column grows to its content's
585
+ intrinsic width, which would let a wide control push the panel. */
586
+ grid-template-columns: minmax(0, 1fr);
587
+ grid-template-rows: 0fr;
588
+ transition: grid-template-rows var(--motion-duration-slow) var(--motion-ease-emphasized);
589
+ }
590
+
591
+ .ds-inspector-section--open .ds-inspector-section__panel {
592
+ grid-template-rows: 1fr;
593
+ }
594
+
595
+ /* Clipped while closed or moving; released once settled open, so a
596
+ Dropdown menu inside can open past the section's edge. */
597
+ .ds-inspector-section__body {
598
+ min-height: 0;
599
+ overflow: hidden;
600
+ display: flex;
601
+ flex-direction: column;
602
+ gap: var(--gap-200);
603
+ }
604
+
605
+ .ds-inspector-section--settled .ds-inspector-section__body {
606
+ overflow: visible;
607
+ }
608
+
609
+ /* The section's foot: an empty flex item sized so the gap above it plus
610
+ its own height equal the trigger's padding, so the content sits as far
611
+ from the divider as the title does. Padding instead would keep a closed
612
+ panel from reaching zero height. */
613
+ .ds-inspector-section__body::after {
614
+ content: "";
615
+ flex: 0 0 calc(var(--padding-300) - var(--gap-200));
616
+ }
@@ -0,0 +1,43 @@
1
+ import { default as React } from 'react';
2
+ /** Props owned by InspectorColorPicker itself — everything else falls through to the wrapper. */
3
+ type InspectorColorPickerOwnProps = {
4
+ /** The setting's name, drawn inside the bar on the left. Also the start of the trigger's accessible name. */
5
+ label: string;
6
+ /** Current colour as a hex string — 3, 6 or 8 digit, with or without `#`. */
7
+ value?: string;
8
+ /** Initial colour for uncontrolled use. */
9
+ defaultValue?: string;
10
+ /**
11
+ * Called with the colour as an uppercase hex string (`#RRGGBB`, or
12
+ * `#RRGGBBAA` when `showAlpha` and alpha is below 100%). Fires live while
13
+ * dragging, as in ColorPicker.
14
+ */
15
+ onValueChange?: (value: string) => void;
16
+ /** Add an alpha (opacity) slider to the panel and emit 8-digit hex when alpha is below 100%. */
17
+ showAlpha?: boolean;
18
+ /** When set, a hidden input carries the current hex under this name, so the picker joins native form submission. */
19
+ name?: string;
20
+ /** Whether the picker is disabled. */
21
+ disabled?: boolean;
22
+ /** Component size, matching Button: `default` is 40px tall, `compact` 32px. */
23
+ size?: 'default' | 'compact';
24
+ /** Additional CSS classes, applied to the wrapper. */
25
+ className?: string;
26
+ };
27
+ export interface InspectorColorPickerProps extends InspectorColorPickerOwnProps, Omit<React.ComponentPropsWithoutRef<'div'>, keyof InspectorColorPickerOwnProps | 'onChange' | 'defaultValue'> {
28
+ }
29
+ /**
30
+ * A one-row colour setting for inspector panels: the name on the left, the
31
+ * hex reading and a round swatch at the bar's end. It is the library
32
+ * ColorPicker with its trigger dressed as an inspector bar, so the panel,
33
+ * its saturation area, hue and alpha sliders and hex field are
34
+ * ColorPicker's own. The form counterpart, with a label above and helper
35
+ * text below, is ColorPicker itself.
36
+ *
37
+ * The whole bar is the trigger: the name is an overlay that lets clicks
38
+ * through, and the trigger is named by the name followed by the hex reading
39
+ * ("Tint colour #163300"). Forwards a ref to the wrapper and spreads
40
+ * unrecognised props onto it.
41
+ */
42
+ export declare const InspectorColorPicker: React.ForwardRefExoticComponent<InspectorColorPickerProps & React.RefAttributes<HTMLDivElement>>;
43
+ export {};
@@ -0,0 +1,51 @@
1
+ "use client";
2
+ import { jsxs, jsx } from "react/jsx-runtime";
3
+ import React from "react";
4
+ import { ColorPicker } from "../ColorPicker/ColorPicker.js";
5
+ import "./Inspector.css";
6
+ const InspectorColorPicker = React.forwardRef(
7
+ ({
8
+ label,
9
+ value,
10
+ defaultValue,
11
+ onValueChange,
12
+ showAlpha = false,
13
+ name,
14
+ disabled = false,
15
+ size = "default",
16
+ className = "",
17
+ ...rest
18
+ }, ref) => {
19
+ const baseId = React.useId();
20
+ const labelId = `${baseId}-label`;
21
+ const triggerId = `${baseId}-trigger`;
22
+ const classes = [
23
+ "ds-inspector-color-picker",
24
+ size === "compact" ? "ds-inspector-color-picker--compact" : "",
25
+ disabled ? "ds-inspector-color-picker--disabled" : "",
26
+ className
27
+ ].filter(Boolean).join(" ");
28
+ return /* @__PURE__ */ jsxs("div", { ...rest, ref, className: classes, children: [
29
+ /* @__PURE__ */ jsx("span", { id: labelId, className: "ds-inspector-color-picker__label", "aria-hidden": "true", children: label }),
30
+ /* @__PURE__ */ jsx(
31
+ ColorPicker,
32
+ {
33
+ id: triggerId,
34
+ "aria-labelledby": `${labelId} ${triggerId}-value`,
35
+ size,
36
+ value,
37
+ defaultValue,
38
+ onValueChange,
39
+ showAlpha,
40
+ showText: true,
41
+ name,
42
+ disabled
43
+ }
44
+ )
45
+ ] });
46
+ }
47
+ );
48
+ InspectorColorPicker.displayName = "InspectorColorPicker";
49
+ export {
50
+ InspectorColorPicker
51
+ };