@fusion.dev/helix-headless 0.154.0 → 0.156.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/custom-elements.json +3213 -179
- package/dist/accordion/item/accordion-item.d.ts +15 -0
- package/dist/accordion/item/accordion-item.js +12 -1
- package/dist/accordion/root/accordion-root.d.ts +2 -1
- package/dist/accordion/root/accordion-root.js +1 -0
- package/dist/breadcrumbs/breadcrumb/breadcrumb.d.ts +36 -3
- package/dist/breadcrumbs/breadcrumb/breadcrumb.js +42 -2
- package/dist/breadcrumbs/root/breadcrumbs-root.d.ts +15 -5
- package/dist/breadcrumbs/root/breadcrumbs-root.js +29 -4
- package/dist/button-group/root/button-group-root.d.ts +2 -0
- package/dist/button-group/root/button-group-root.js +1 -0
- package/dist/canvas/node/canvas-node.js +1 -1
- package/dist/canvas/root/canvas-root.d.ts +17 -2
- package/dist/canvas/root/canvas-root.js +23 -6
- package/dist/chat/composer/chat-composer.js +1 -1
- package/dist/chat/root/chat-root.d.ts +14 -1
- package/dist/chat/root/chat-root.js +14 -4
- package/dist/color-input/root/color-input-root.d.ts +9 -3
- package/dist/color-input/root/color-input-root.js +3 -1
- package/dist/color-picker/channels.d.ts +5 -3
- package/dist/color-picker/channels.js +79 -21
- package/dist/color-picker/root/color-picker-root.d.ts +58 -5
- package/dist/color-picker/root/color-picker-root.js +75 -13
- package/dist/combobox/root/combobox-root.d.ts +10 -0
- package/dist/combobox/root/combobox-root.js +18 -3
- package/dist/command/root/command-root.d.ts +116 -1
- package/dist/command/root/command-root.js +124 -15
- package/dist/data-table/root/data-table-root.d.ts +25 -0
- package/dist/data-table/root/data-table-root.js +13 -3
- package/dist/date-input/root/date-input-root.d.ts +33 -1
- package/dist/date-input/root/date-input-root.js +9 -2
- package/dist/date-picker/root/date-picker-root.d.ts +43 -13
- package/dist/date-picker/root/date-picker-root.js +54 -31
- package/dist/element-events.generated.js +3 -1
- package/dist/graph/root/graph-root.d.ts +13 -0
- package/dist/graph/root/graph-root.js +16 -0
- package/dist/list/root/list-root.d.ts +74 -1
- package/dist/list/root/list-root.js +92 -4
- package/dist/list/selection.js +3 -3
- package/dist/map/root/map-root.d.ts +6 -0
- package/dist/map/root/map-root.js +8 -1
- package/dist/navigation/root/navigation-root.d.ts +26 -0
- package/dist/navigation/root/navigation-root.js +58 -1
- package/dist/number-input/root/number-input-root.d.ts +63 -6
- package/dist/number-input/root/number-input-root.js +96 -11
- package/dist/object-inspector/root/object-inspector-root.d.ts +36 -1
- package/dist/object-inspector/root/object-inspector-root.js +26 -2
- package/dist/option/root/option-root.d.ts +32 -0
- package/dist/option/root/option-root.js +44 -5
- package/dist/outline/root/outline-root.d.ts +6 -2
- package/dist/outline/root/outline-root.js +7 -3
- package/dist/select/root/select-root.d.ts +29 -3
- package/dist/select/root/select-root.js +34 -9
- package/dist/slider/root/slider-root.d.ts +71 -9
- package/dist/slider/root/slider-root.js +129 -42
- package/dist/speed-dial/item/speed-dial-item.d.ts +29 -1
- package/dist/speed-dial/item/speed-dial-item.js +48 -7
- package/dist/speed-dial/root/speed-dial-root.d.ts +32 -6
- package/dist/speed-dial/root/speed-dial-root.js +50 -5
- package/dist/splitter/root/splitter-root.d.ts +22 -0
- package/dist/splitter/root/splitter-root.js +36 -7
- package/dist/steps/reach.d.ts +5 -1
- package/dist/steps/reach.js +2 -2
- package/dist/steps/root/steps-root.d.ts +37 -2
- package/dist/steps/root/steps-root.js +49 -7
- package/dist/steps/step/step.d.ts +6 -0
- package/dist/steps/step/step.js +4 -0
- package/dist/table/root/table-root.d.ts +20 -0
- package/dist/table/root/table-root.js +13 -3
- package/dist/tabs/root/tabs-root.d.ts +37 -0
- package/dist/tabs/root/tabs-root.js +92 -2
- package/dist/tabs/tab/tab.d.ts +38 -2
- package/dist/tabs/tab/tab.js +45 -4
- package/dist/tag/group/tag-group.d.ts +29 -3
- package/dist/tag/group/tag-group.js +42 -11
- package/dist/time-input/root/time-input-root.d.ts +32 -1
- package/dist/time-input/root/time-input-root.js +9 -2
- package/dist/time-picker/root/time-picker-root.d.ts +63 -1
- package/dist/time-picker/root/time-picker-root.js +58 -7
- package/dist/timeline/item/timeline-item.d.ts +25 -0
- package/dist/timeline/item/timeline-item.js +27 -2
- package/dist/toggle/root/toggle-root.d.ts +2 -0
- package/dist/toggle/root/toggle-root.js +1 -1
- package/dist/tree/item/tree-item.d.ts +10 -0
- package/dist/tree/item/tree-item.js +12 -0
- package/dist/tree/root/tree-root.d.ts +40 -1
- package/dist/tree/root/tree-root.js +120 -4
- package/dist/tree/selection.d.ts +6 -0
- package/dist/tree/selection.js +11 -0
- package/dist/video/root/keys.d.ts +6 -2
- package/dist/video/root/keys.js +18 -1
- package/dist/video/root/video-root.d.ts +60 -1
- package/dist/video/root/video-root.js +70 -2
- package/dist/video-playlist/item/video-playlist-item.d.ts +15 -1
- package/dist/video-playlist/item/video-playlist-item.js +7 -0
- package/dist/video-playlist/root/video-playlist-root.d.ts +43 -4
- package/dist/video-playlist/root/video-playlist-root.js +69 -2
- package/dist/virtual-list/root/virtual-list-root.d.ts +8 -0
- package/dist/virtual-list/root/virtual-list-root.js +3 -0
- package/lint.json +1 -1
- package/package.json +5 -5
- package/types/jsx.d.ts +3885 -383
- package/types/vue.d.ts +1045 -107
- package/types/words.d.ts +146 -1
|
@@ -11,7 +11,7 @@ import { property, state } from 'lit/decorators.js';
|
|
|
11
11
|
import { keyed } from 'lit/directives/keyed.js';
|
|
12
12
|
import { repeat } from 'lit/directives/repeat.js';
|
|
13
13
|
import { html } from 'lit/static-html.js';
|
|
14
|
-
import { TURN_WORDS } from '../naming.js';
|
|
14
|
+
import { authorWords, TURN_WORDS } from '../naming.js';
|
|
15
15
|
const REGIONS = ['header', 'actions', 'resume', 'status', 'composer'];
|
|
16
16
|
const SECOND_NAMES = {
|
|
17
17
|
author: {
|
|
@@ -40,6 +40,7 @@ const drawnInFull = ({ element }) => element.firstElementChild?.hasUpdated !== f
|
|
|
40
40
|
let HelixHeadlessChat = class HelixHeadlessChat extends MixinCollection(HelixElement) {
|
|
41
41
|
constructor() {
|
|
42
42
|
super(...arguments);
|
|
43
|
+
this.arrivalLabel = '{author}: {text}';
|
|
43
44
|
this.authorStyles = {};
|
|
44
45
|
this.defaultPinned = true;
|
|
45
46
|
this.failedLabel = 'Not sent';
|
|
@@ -180,6 +181,7 @@ let HelixHeadlessChat = class HelixHeadlessChat extends MixinCollection(HelixEle
|
|
|
180
181
|
if (this.fed) {
|
|
181
182
|
return this.turns.map((turn) => ({
|
|
182
183
|
author: turn.author,
|
|
184
|
+
by: authorWords(turn.author, turn.authorLabel ?? '', this.words),
|
|
183
185
|
failed: this.failedLabel,
|
|
184
186
|
id: this.identity(turn),
|
|
185
187
|
state: turn.state,
|
|
@@ -188,6 +190,7 @@ let HelixHeadlessChat = class HelixHeadlessChat extends MixinCollection(HelixEle
|
|
|
188
190
|
}
|
|
189
191
|
return this.messages.map((message) => ({
|
|
190
192
|
author: message.author,
|
|
193
|
+
by: authorWords(message.author, message.authorLabel, this.words),
|
|
191
194
|
failed: message.failedLabel,
|
|
192
195
|
id: message,
|
|
193
196
|
state: message.state,
|
|
@@ -349,9 +352,12 @@ let HelixHeadlessChat = class HelixHeadlessChat extends MixinCollection(HelixEle
|
|
|
349
352
|
return at < 0 ? [] : turns.slice(at + 1);
|
|
350
353
|
}
|
|
351
354
|
phrase(turn) {
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
+
if (turn.state === 'failed') {
|
|
356
|
+
return formatWords(this, 'failedTurnLabel', { failed: turn.failed, text: turn.text });
|
|
357
|
+
}
|
|
358
|
+
return turn.by === ''
|
|
359
|
+
? turn.text
|
|
360
|
+
: formatWords(this, 'arrivalLabel', { author: turn.by, text: turn.text });
|
|
355
361
|
}
|
|
356
362
|
watchSizes() {
|
|
357
363
|
if (typeof ResizeObserver === 'undefined') {
|
|
@@ -509,6 +515,10 @@ let HelixHeadlessChat = class HelixHeadlessChat extends MixinCollection(HelixEle
|
|
|
509
515
|
</div>`;
|
|
510
516
|
}
|
|
511
517
|
};
|
|
518
|
+
__decorate([
|
|
519
|
+
words,
|
|
520
|
+
property({ attribute: 'arrival-label' })
|
|
521
|
+
], HelixHeadlessChat.prototype, "arrivalLabel", void 0);
|
|
512
522
|
__decorate([
|
|
513
523
|
property({ attribute: 'author-styles', converter: wordsConverter })
|
|
514
524
|
], HelixHeadlessChat.prototype, "authorStyles", void 0);
|
|
@@ -17,8 +17,9 @@ declare const HelixHeadlessColorInput_base: (new (...args: any[]) => import("@fu
|
|
|
17
17
|
* style the panel to match your interface.
|
|
18
18
|
*
|
|
19
19
|
* The field reads every color syntax, including `#f00`, `#ff0000`,
|
|
20
|
-
* `rgb(255 0 0)`, `rgba(255,0,0,.5)`, `rgb(255 0 0 / 50%)`,
|
|
21
|
-
* `hsl(0 100% 50%)
|
|
20
|
+
* `rgb(255 0 0)`, `rgba(255,0,0,.5)`, `rgb(255 0 0 / 50%)`,
|
|
21
|
+
* `hsl(0 100% 50%)`, `oklch(62.8% 0.258 29.2)`, and `hsb(0, 100%, 100%)`. It
|
|
22
|
+
* writes colors in the syntax that `format` names. The
|
|
22
23
|
* field shows the value without reformatting it, because half-typed input does
|
|
23
24
|
* not survive a round trip through a formatter. Date Input does the same with
|
|
24
25
|
* dates.
|
|
@@ -75,6 +76,8 @@ declare const HelixHeadlessColorInput_base: (new (...args: any[]) => import("@fu
|
|
|
75
76
|
* @csspart picker-channel-marker-label - The value a mark stands at, when `marker-labels` is set.
|
|
76
77
|
* @csspart picker-channel-markers - The row of marks along the track.
|
|
77
78
|
* @csspart picker-channel-output - The current value, shown beside the track.
|
|
79
|
+
* @csspart picker-channel-thumb - A ramp's thumb box, which holds no content in a picker.
|
|
80
|
+
* @csspart picker-channel-thumbs - The layer over a ramp's track that holds its thumb box.
|
|
78
81
|
* @csspart picker-channel-tooltip - A ramp's value in a bubble, where a ramp shows one.
|
|
79
82
|
* @csspart picker-channel-tooltips - The layer over a ramp's track that holds its bubble.
|
|
80
83
|
* @csspart picker-channels - The channel sliders beside the sample.
|
|
@@ -99,7 +102,9 @@ declare const HelixHeadlessColorInput_base: (new (...args: any[]) => import("@fu
|
|
|
99
102
|
* @csspart picker-grid-brightness - The range input for the square's vertical axis.
|
|
100
103
|
* @csspart picker-grid-handle - The mark showing where in the square the color sits.
|
|
101
104
|
* @csspart picker-grid-saturation - The range input for the square's horizontal axis.
|
|
105
|
+
* @csspart picker-hint - The picker's own help, which the field's `hint` stands in for here, so it stays hidden.
|
|
102
106
|
* @csspart picker-icon - An icon drawn by the picker.
|
|
107
|
+
* @csspart picker-label - The picker's own name, which the field's `label` stands in for here, so it stays hidden.
|
|
103
108
|
* @csspart picker-sample - A chip of the current color. Pressing it copies the value.
|
|
104
109
|
* @csspart picker-swatch - One preset.
|
|
105
110
|
* @csspart picker-swatches - The row of presets.
|
|
@@ -150,7 +155,8 @@ export declare class HelixHeadlessColorInput extends HelixHeadlessColorInput_bas
|
|
|
150
155
|
*/
|
|
151
156
|
colorWords: Partial<ColorWords>;
|
|
152
157
|
/**
|
|
153
|
-
* The syntax the value is written in: `hex`, `rgb`,
|
|
158
|
+
* The syntax the value is written in: `hex`, `rgb`, `hsl`, `oklch`, or
|
|
159
|
+
* `hsb`, as Color Picker's `format`.
|
|
154
160
|
*
|
|
155
161
|
* **Undefaulted, because it reflects.** The two together stamp an attribute
|
|
156
162
|
* onto every host anybody renders, including the ones nobody configured: the
|
|
@@ -126,6 +126,7 @@ let HelixHeadlessColorInput = class HelixHeadlessColorInput extends MixinPickerF
|
|
|
126
126
|
channel-hint: picker-channel-hint, channel-label: picker-channel-label,
|
|
127
127
|
channel-marker: picker-channel-marker, channel-marker-label: picker-channel-marker-label,
|
|
128
128
|
channel-markers: picker-channel-markers, channel-output: picker-channel-output,
|
|
129
|
+
channel-thumb: picker-channel-thumb, channel-thumbs: picker-channel-thumbs,
|
|
129
130
|
channel-tooltip: picker-channel-tooltip, channel-tooltips: picker-channel-tooltips,
|
|
130
131
|
channels: picker-channels, controls: picker-controls, eyedropper: picker-eyedropper,
|
|
131
132
|
eyedropper-button: picker-eyedropper-button, eyedropper-live: picker-eyedropper-live, eyedropper-spinner: picker-eyedropper-spinner, eyedropper-text: picker-eyedropper-text,
|
|
@@ -133,7 +134,8 @@ let HelixHeadlessColorInput = class HelixHeadlessColorInput extends MixinPickerF
|
|
|
133
134
|
fields: picker-fields, footer: picker-footer, format: picker-format,
|
|
134
135
|
format-button: picker-format-button, format-live: picker-format-live, format-spinner: picker-format-spinner, format-text: picker-format-text, grid: picker-grid,
|
|
135
136
|
grid-brightness: picker-grid-brightness, grid-handle: picker-grid-handle,
|
|
136
|
-
grid-saturation: picker-grid-saturation,
|
|
137
|
+
grid-saturation: picker-grid-saturation, hint: picker-hint, icon: picker-icon,
|
|
138
|
+
label: picker-label, sample: picker-sample,
|
|
137
139
|
swatch: picker-swatch, swatches: picker-swatches, value: picker-value,
|
|
138
140
|
wheel: picker-wheel, wheel-hue: picker-wheel-hue"
|
|
139
141
|
?invalid=${this.resolvedFeedback !== ''}
|
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
import { type Color, type ColorFormat } from '@fusion.dev/helix-core';
|
|
2
2
|
/** One number a color is written with, in the syntax the picker writes. */
|
|
3
|
-
export type ChannelName = 'alpha' | 'blue' | 'green' | 'hue' | 'lightness' | 'red' | 'saturation';
|
|
4
|
-
/** A channel as a field shows it: its number
|
|
3
|
+
export type ChannelName = 'alpha' | 'blue' | 'brightness' | 'chroma' | 'green' | 'hue' | 'lightness' | 'red' | 'saturation';
|
|
4
|
+
/** A channel as a field shows it: its number, the range it may take, and its step. */
|
|
5
5
|
export interface ChannelField {
|
|
6
6
|
channel: ChannelName;
|
|
7
7
|
max: number;
|
|
8
8
|
min: number;
|
|
9
|
+
step: number;
|
|
9
10
|
value: number;
|
|
10
11
|
}
|
|
11
12
|
/**
|
|
12
13
|
* The numbers a color is written with in `format`, for a field each, as React
|
|
13
14
|
* Aria's ColorField takes a `channel`: red, green and blue for hex and rgb,
|
|
14
|
-
* hue, saturation and lightness for hsl,
|
|
15
|
+
* hue, saturation and lightness for hsl, hue, saturation and brightness for
|
|
16
|
+
* hsb, lightness, chroma and hue for oklch, and the opacity where the picker
|
|
15
17
|
* carries one.
|
|
16
18
|
*
|
|
17
19
|
* Hex is written as bytes, so its fields are the bytes: a field of two hex
|
|
@@ -1,4 +1,16 @@
|
|
|
1
|
-
import { clamp, toHsl, toRgb } from '@fusion.dev/helix-core';
|
|
1
|
+
import { clamp, toHsl, toOklch, toRgb } from '@fusion.dev/helix-core';
|
|
2
|
+
const onStep = (value, step) => {
|
|
3
|
+
const decimals = String(step).split('.')[1]?.length ?? 0;
|
|
4
|
+
return Number((Math.round(value / step) * step).toFixed(decimals));
|
|
5
|
+
};
|
|
6
|
+
const FAMILY = {
|
|
7
|
+
hex: /^rgba?$/,
|
|
8
|
+
hsb: /^hsba?$/,
|
|
9
|
+
hsl: /^hsla?$/,
|
|
10
|
+
oklch: /^oklch$/,
|
|
11
|
+
rgb: /^rgba?$/,
|
|
12
|
+
};
|
|
13
|
+
const OKLCH_STEPS = [0.1, 0.001, 0.1];
|
|
2
14
|
const percent = (token) => {
|
|
3
15
|
if (token === undefined) {
|
|
4
16
|
return 100;
|
|
@@ -8,7 +20,8 @@ const percent = (token) => {
|
|
|
8
20
|
};
|
|
9
21
|
const readWritten = (value, format) => {
|
|
10
22
|
const text = value.trim().toLowerCase();
|
|
11
|
-
if (format
|
|
23
|
+
if ((format === 'hex' || format === 'rgb') &&
|
|
24
|
+
/^#([\da-f]{3,4}|[\da-f]{6}|[\da-f]{8})$/.test(text)) {
|
|
12
25
|
const digits = text.slice(1);
|
|
13
26
|
const width = digits.length <= 4 ? 1 : 2;
|
|
14
27
|
const byte = (index) => {
|
|
@@ -18,23 +31,46 @@ const readWritten = (value, format) => {
|
|
|
18
31
|
const count = digits.length / width;
|
|
19
32
|
return [byte(0), byte(1), byte(2), count === 4 ? Math.round((byte(3) / 255) * 100) : 100];
|
|
20
33
|
}
|
|
21
|
-
const call = /^(rgba?|hsla
|
|
22
|
-
if (!call?.[1] || call[2] === undefined) {
|
|
23
|
-
return null;
|
|
24
|
-
}
|
|
25
|
-
if (call[1].startsWith('hsl') !== (format === 'hsl')) {
|
|
34
|
+
const call = /^(rgba?|hsla?|hsba?|oklch)\(([^)]*)\)$/.exec(text);
|
|
35
|
+
if (!call?.[1] || call[2] === undefined || !FAMILY[format].test(call[1])) {
|
|
26
36
|
return null;
|
|
27
37
|
}
|
|
28
38
|
const [first, second, third, fourth] = call[2].replace(/[,/]/g, ' ').split(/\s+/).filter(Boolean);
|
|
29
|
-
const numbers = [first, second, third].map((one) => Number.parseFloat(one ?? ''));
|
|
39
|
+
const numbers = [first, second, third].map((one) => one === 'none' ? 0 : Number.parseFloat(one ?? ''));
|
|
30
40
|
if (numbers.some(Number.isNaN)) {
|
|
31
41
|
return null;
|
|
32
42
|
}
|
|
43
|
+
if (format === 'oklch') {
|
|
44
|
+
const [lightness = 0, chroma = 0, hue = 0] = numbers;
|
|
45
|
+
return [
|
|
46
|
+
onStep(first?.endsWith('%') ? lightness : lightness * 100, OKLCH_STEPS[0]),
|
|
47
|
+
onStep(second?.endsWith('%') ? (chroma / 100) * 0.4 : chroma, OKLCH_STEPS[1]),
|
|
48
|
+
onStep(hue, OKLCH_STEPS[2]),
|
|
49
|
+
Math.round(percent(fourth)),
|
|
50
|
+
];
|
|
51
|
+
}
|
|
33
52
|
return [...numbers, percent(fourth)].map((one) => Math.round(one));
|
|
34
53
|
};
|
|
35
54
|
export const channelFields = (value, color, format, alpha) => {
|
|
36
55
|
const written = readWritten(value, format);
|
|
37
56
|
const fromModel = () => {
|
|
57
|
+
if (format === 'hsb') {
|
|
58
|
+
return [
|
|
59
|
+
Math.round(color.hue),
|
|
60
|
+
Math.round(color.saturation),
|
|
61
|
+
Math.round(color.brightness),
|
|
62
|
+
Math.round(color.alpha),
|
|
63
|
+
];
|
|
64
|
+
}
|
|
65
|
+
if (format === 'oklch') {
|
|
66
|
+
const { chroma, hue, lightness } = toOklch(color);
|
|
67
|
+
return [
|
|
68
|
+
onStep(lightness * 100, OKLCH_STEPS[0]),
|
|
69
|
+
onStep(chroma, OKLCH_STEPS[1]),
|
|
70
|
+
onStep(hue, OKLCH_STEPS[2]),
|
|
71
|
+
Math.round(color.alpha),
|
|
72
|
+
];
|
|
73
|
+
}
|
|
38
74
|
if (format === 'hsl') {
|
|
39
75
|
const { hue, lightness, saturation } = toHsl(color);
|
|
40
76
|
return [Math.round(hue), saturation, lightness, Math.round(color.alpha)];
|
|
@@ -43,18 +79,32 @@ export const channelFields = (value, color, format, alpha) => {
|
|
|
43
79
|
return [red, green, blue, Math.round(color.alpha)];
|
|
44
80
|
};
|
|
45
81
|
const [one = 0, two = 0, three = 0, four = 100] = written ?? fromModel();
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
{ channel: '
|
|
50
|
-
{ channel: '
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
{ channel: '
|
|
55
|
-
{ channel: '
|
|
56
|
-
|
|
57
|
-
|
|
82
|
+
const byFormat = {
|
|
83
|
+
hex: [],
|
|
84
|
+
hsb: [
|
|
85
|
+
{ channel: 'hue', max: 360, min: 0, step: 1, value: one },
|
|
86
|
+
{ channel: 'saturation', max: 100, min: 0, step: 1, value: two },
|
|
87
|
+
{ channel: 'brightness', max: 100, min: 0, step: 1, value: three },
|
|
88
|
+
],
|
|
89
|
+
hsl: [
|
|
90
|
+
{ channel: 'hue', max: 360, min: 0, step: 1, value: one },
|
|
91
|
+
{ channel: 'saturation', max: 100, min: 0, step: 1, value: two },
|
|
92
|
+
{ channel: 'lightness', max: 100, min: 0, step: 1, value: three },
|
|
93
|
+
],
|
|
94
|
+
oklch: [
|
|
95
|
+
{ channel: 'lightness', max: 100, min: 0, step: OKLCH_STEPS[0], value: one },
|
|
96
|
+
{ channel: 'chroma', max: 0.4, min: 0, step: OKLCH_STEPS[1], value: two },
|
|
97
|
+
{ channel: 'hue', max: 360, min: 0, step: OKLCH_STEPS[2], value: three },
|
|
98
|
+
],
|
|
99
|
+
rgb: [],
|
|
100
|
+
};
|
|
101
|
+
const bytes = [
|
|
102
|
+
{ channel: 'red', max: 255, min: 0, step: 1, value: one },
|
|
103
|
+
{ channel: 'green', max: 255, min: 0, step: 1, value: two },
|
|
104
|
+
{ channel: 'blue', max: 255, min: 0, step: 1, value: three },
|
|
105
|
+
];
|
|
106
|
+
const fields = byFormat[format].length > 0 ? byFormat[format] : bytes;
|
|
107
|
+
return alpha ? [...fields, { channel: 'alpha', max: 100, min: 0, step: 1, value: four }] : fields;
|
|
58
108
|
};
|
|
59
109
|
export const writeChannel = (fields, format, alpha, channel, value) => {
|
|
60
110
|
if (Number.isNaN(value)) {
|
|
@@ -65,7 +115,7 @@ export const writeChannel = (fields, format, alpha, channel, value) => {
|
|
|
65
115
|
if (field === undefined) {
|
|
66
116
|
return null;
|
|
67
117
|
}
|
|
68
|
-
numbers.set(channel, clamp(
|
|
118
|
+
numbers.set(channel, clamp(onStep(value, field.step), field.min, field.max));
|
|
69
119
|
const get = (name, fallback = 0) => numbers.get(name) ?? fallback;
|
|
70
120
|
const opacity = get('alpha', 100);
|
|
71
121
|
const fraction = Number((opacity / 100).toFixed(2));
|
|
@@ -73,6 +123,14 @@ export const writeChannel = (fields, format, alpha, channel, value) => {
|
|
|
73
123
|
const body = `${get('hue')}, ${get('saturation')}%, ${get('lightness')}%`;
|
|
74
124
|
return alpha ? `hsla(${body}, ${fraction})` : `hsl(${body})`;
|
|
75
125
|
}
|
|
126
|
+
if (format === 'hsb') {
|
|
127
|
+
const body = `${get('hue')}, ${get('saturation')}%, ${get('brightness')}%`;
|
|
128
|
+
return alpha ? `hsba(${body}, ${fraction})` : `hsb(${body})`;
|
|
129
|
+
}
|
|
130
|
+
if (format === 'oklch') {
|
|
131
|
+
const body = `${get('lightness')}% ${get('chroma')} ${get('hue')}`;
|
|
132
|
+
return alpha ? `oklch(${body} / ${fraction})` : `oklch(${body})`;
|
|
133
|
+
}
|
|
76
134
|
if (format === 'rgb') {
|
|
77
135
|
const body = `${get('red')}, ${get('green')}, ${get('blue')}`;
|
|
78
136
|
return alpha ? `rgba(${body}, ${fraction})` : `rgb(${body})`;
|
|
@@ -32,6 +32,11 @@ declare const HelixHeadlessColorPicker_base: (new (...args: any[]) => import("@f
|
|
|
32
32
|
* is named by its color. The opacity ramp is heard as a percentage. Set
|
|
33
33
|
* `color-words` to speak the names in another language.
|
|
34
34
|
*
|
|
35
|
+
* `label` names the picker, which is then a group with that name, and the
|
|
36
|
+
* square's ramps say it before their own, as "Brand, Saturation". `hint`
|
|
37
|
+
* writes help under the picker, which the square, the ramps and the value
|
|
38
|
+
* field are described by. Inside Color Input the field carries both.
|
|
39
|
+
*
|
|
35
40
|
* The presets are a listbox with the current color selected, and one tab
|
|
36
41
|
* stop. The arrow keys move between them, Home and End go to the ends, and
|
|
37
42
|
* Enter, Space or a press chooses one.
|
|
@@ -43,6 +48,8 @@ declare const HelixHeadlessColorPicker_base: (new (...args: any[]) => import("@f
|
|
|
43
48
|
* @documentation https://fusion.dev/helix/components/color-picker
|
|
44
49
|
*
|
|
45
50
|
* @slot eyedropper-icon - The icon on the eyedropper button, usually a dropper.
|
|
51
|
+
* @slot hint - Help under the picker, for content richer than the `hint` text.
|
|
52
|
+
* @slot label - The name above the picker, for content richer than the `label` text.
|
|
46
53
|
*
|
|
47
54
|
* @event {Event} change - Fired after the value changes.
|
|
48
55
|
* @event {HelixBeforeChangeEvent} helix-before-change - Fired before the color changes. Cancelable: call `preventDefault()` to keep the current color.
|
|
@@ -62,6 +69,8 @@ declare const HelixHeadlessColorPicker_base: (new (...args: any[]) => import("@f
|
|
|
62
69
|
* @csspart channel-marker-label - The value a mark stands at, when `marker-labels` is set.
|
|
63
70
|
* @csspart channel-markers - The row of marks along the track.
|
|
64
71
|
* @csspart channel-output - The current value, shown beside the track.
|
|
72
|
+
* @csspart channel-thumb - A ramp's thumb box, which holds no content in a picker.
|
|
73
|
+
* @csspart channel-thumbs - The layer over a ramp's track that holds its thumb box.
|
|
65
74
|
* @csspart channel-tooltip - A ramp's value in a bubble, where a ramp shows one.
|
|
66
75
|
* @csspart channel-tooltips - The layer over a ramp's track that holds its bubble.
|
|
67
76
|
* @csspart channels - The ramps beside the sample.
|
|
@@ -88,6 +97,8 @@ declare const HelixHeadlessColorPicker_base: (new (...args: any[]) => import("@f
|
|
|
88
97
|
* `--color-picker-brightness`, and this tier ships no CSS.
|
|
89
98
|
* @csspart grid-brightness - The range input for the square's vertical axis.
|
|
90
99
|
* @csspart grid-saturation - The range input for the square's horizontal axis.
|
|
100
|
+
* @csspart hint - The help under the picker, while `hint` is set or the `hint` slot has content.
|
|
101
|
+
* @csspart label - The name above the picker, while `label` is set or the `label` slot has content.
|
|
91
102
|
* @csspart sample - A chip of the current color. Pressing it copies the value.
|
|
92
103
|
* @csspart swatch - One preset, an option in the `swatches` listbox.
|
|
93
104
|
* @csspart swatches - The row of presets, a listbox.
|
|
@@ -100,7 +111,10 @@ declare const HelixHeadlessColorPicker_base: (new (...args: any[]) => import("@f
|
|
|
100
111
|
* @cssproperty --color-picker-saturation - The chosen saturation, 0 to 100, as a percentage.
|
|
101
112
|
* @cssproperty --color-picker-swatch - The color a chip shows: the current color on the sample, and the preset's color on each preset.
|
|
102
113
|
*
|
|
114
|
+
* @cssstate copied - The moment after the sample copies the value, while it says `copied-label`.
|
|
115
|
+
* @cssstate dragging - While a pointer drags the square's handle.
|
|
103
116
|
* @cssstate invalid - While `invalid` is set or `feedback` says what is wrong.
|
|
117
|
+
* @cssstate sampling - While the eyedropper is open over the screen.
|
|
104
118
|
*/
|
|
105
119
|
export declare class HelixHeadlessColorPicker extends HelixHeadlessColorPicker_base {
|
|
106
120
|
/**
|
|
@@ -142,14 +156,20 @@ export declare class HelixHeadlessColorPicker extends HelixHeadlessColorPicker_b
|
|
|
142
156
|
/**
|
|
143
157
|
* Whether the picker shows a number field for each channel of the color, as
|
|
144
158
|
* React Aria's ColorField does with `channel`: red, green and blue for hex
|
|
145
|
-
* and rgb, hue, saturation and lightness for hsl,
|
|
146
|
-
*
|
|
159
|
+
* and rgb, hue, saturation and lightness for hsl, hue, saturation and
|
|
160
|
+
* brightness for hsb, lightness, chroma and hue for oklch, and the opacity
|
|
161
|
+
* with `alpha`.
|
|
147
162
|
*
|
|
148
163
|
* For a reader who has the numbers from a brand guide, and for a keyboard,
|
|
149
164
|
* where typing 128 is quicker than holding an arrow key. The fields follow
|
|
150
165
|
* the syntax the format toggle sets.
|
|
151
166
|
*/
|
|
152
167
|
channelFields: boolean;
|
|
168
|
+
/**
|
|
169
|
+
* What the chroma channel's field is called, in `channel-fields` with
|
|
170
|
+
* oklch.
|
|
171
|
+
*/
|
|
172
|
+
chromaLabel: string;
|
|
153
173
|
/**
|
|
154
174
|
* The words a color's name is spoken in, as JSON keyed by their English,
|
|
155
175
|
* such as `{"red": "rot", "vibrant": "kräftiges"}`.
|
|
@@ -179,10 +199,16 @@ export declare class HelixHeadlessColorPicker extends HelixHeadlessColorPicker_b
|
|
|
179
199
|
*/
|
|
180
200
|
eyedropperLabel: string;
|
|
181
201
|
/**
|
|
182
|
-
* The syntax the value is written in: `hex`, `rgb`,
|
|
202
|
+
* The syntax the value is written in: `hex`, `rgb`, `hsl`, `oklch`, or
|
|
203
|
+
* `hsb`.
|
|
183
204
|
*
|
|
184
205
|
* Only what is written. Everything is read whatever this says, so a picker on
|
|
185
|
-
* `hex` still takes an `rgb()` handed to it and stores the
|
|
206
|
+
* `hex` still takes an `rgb()` or an `oklch()` handed to it and stores the
|
|
207
|
+
* hex for it. `oklch` writes the sRGB color the picker holds, such as
|
|
208
|
+
* `oklch(62.8% 0.258 29.2)`; a color outside sRGB that is handed in is
|
|
209
|
+
* clipped to it. `hsb` writes the picker's own model, `hsb(0, 100%, 100%)`,
|
|
210
|
+
* as React Aria's and Zag's color strings do. It is not CSS, so the toggle
|
|
211
|
+
* walks the other four.
|
|
186
212
|
*/
|
|
187
213
|
format?: ColorFormat;
|
|
188
214
|
/**
|
|
@@ -193,13 +219,23 @@ export declare class HelixHeadlessColorPicker extends HelixHeadlessColorPicker_b
|
|
|
193
219
|
* What the green channel's field is called, in `channel-fields`.
|
|
194
220
|
*/
|
|
195
221
|
greenLabel: string;
|
|
222
|
+
/**
|
|
223
|
+
* Help under the picker, such as what the color is used for. The `hint`
|
|
224
|
+
* slot takes richer content.
|
|
225
|
+
*/
|
|
226
|
+
hint: string;
|
|
196
227
|
/**
|
|
197
228
|
* What the hue channel is called.
|
|
198
229
|
*/
|
|
199
230
|
hueLabel: string;
|
|
231
|
+
/**
|
|
232
|
+
* The name above the picker, such as "Brand color". The picker is then a
|
|
233
|
+
* group with this name. The `label` slot takes richer content.
|
|
234
|
+
*/
|
|
235
|
+
label: string;
|
|
200
236
|
/**
|
|
201
237
|
* What the lightness channel's field is called, in `channel-fields` with
|
|
202
|
-
* hsl.
|
|
238
|
+
* hsl and oklch.
|
|
203
239
|
*/
|
|
204
240
|
lightnessLabel: string;
|
|
205
241
|
/**
|
|
@@ -353,6 +389,23 @@ export declare class HelixHeadlessColorPicker extends HelixHeadlessColorPicker_b
|
|
|
353
389
|
private sampling;
|
|
354
390
|
/** The preset the reader was last on, which holds the row's one tab stop. */
|
|
355
391
|
private swatchAt;
|
|
392
|
+
/**
|
|
393
|
+
* The children in a slot, read off the children rather than heard from
|
|
394
|
+
* `slotchange`: a declarative shadow root fires that before anything
|
|
395
|
+
* listens, so a served picker kept its label hidden.
|
|
396
|
+
*/
|
|
397
|
+
private slottedIn;
|
|
398
|
+
private readonly handleNamingSlot;
|
|
399
|
+
/** The picker's own name, from `label` or the `label` slot's words. */
|
|
400
|
+
private get named();
|
|
401
|
+
/** Whether help is shown under the picker. */
|
|
402
|
+
private get hinted();
|
|
403
|
+
/** The ids a control in the picker is described by: the help, then the message. */
|
|
404
|
+
private get describedBy();
|
|
405
|
+
/** Whether a pointer is dragging the square's handle, said as `:state(dragging)`. */
|
|
406
|
+
private dragging;
|
|
407
|
+
/** Whether the eyedropper is open, said as `:state(sampling)`. */
|
|
408
|
+
private picking;
|
|
356
409
|
/**
|
|
357
410
|
* Whether the value on this element was produced here.
|
|
358
411
|
*
|