@proyecto-viviana/solid-stately 0.4.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/calendar/createDateFieldState.d.ts +56 -18
- package/dist/calendar/createRangeCalendarState.d.ts +10 -0
- package/dist/calendar/createTimeFieldState.d.ts +38 -67
- package/dist/calendar/intl/index.d.ts +10 -0
- package/dist/collections/ListCollection.d.ts +8 -0
- package/dist/collections/createListState.d.ts +12 -0
- package/dist/collections/getChildNodes.d.ts +8 -0
- package/dist/collections/index.d.ts +2 -2
- package/dist/collections/types.d.ts +9 -0
- package/dist/color/intl/index.d.ts +14 -0
- package/dist/dnd/createDroppableCollectionState.d.ts +17 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +3444 -1304
- package/dist/index.js.map +1 -1
- package/dist/selection/SelectionManager.d.ts +9 -0
- package/package.json +1 -1
- package/src/calendar/createCalendarState.ts +26 -4
- package/src/calendar/createDateFieldState.ts +614 -459
- package/src/calendar/createRangeCalendarState.ts +212 -11
- package/src/calendar/createTimeFieldState.ts +179 -467
- package/src/calendar/intl/index.ts +364 -0
- package/src/collections/ListCollection.ts +31 -0
- package/src/collections/createListState.ts +92 -1
- package/src/collections/getChildNodes.ts +31 -0
- package/src/collections/index.ts +3 -0
- package/src/collections/types.ts +10 -0
- package/src/color/Color.ts +104 -133
- package/src/color/intl/index.ts +1409 -0
- package/src/combobox/createComboBoxState.ts +30 -13
- package/src/dnd/createDroppableCollectionState.ts +125 -6
- package/src/index.ts +3 -0
- package/src/selection/SelectionManager.ts +15 -0
- package/src/steplist/createStepListState.ts +27 -4
package/src/color/Color.ts
CHANGED
|
@@ -16,6 +16,11 @@ import type {
|
|
|
16
16
|
HSLColor,
|
|
17
17
|
HSBColor,
|
|
18
18
|
} from "./types";
|
|
19
|
+
import {
|
|
20
|
+
getColorStringForLocale,
|
|
21
|
+
formatColorMessage,
|
|
22
|
+
type ColorStringKey,
|
|
23
|
+
} from "./intl";
|
|
19
24
|
|
|
20
25
|
// Channel ranges
|
|
21
26
|
const RGB_CHANNEL_RANGE: ColorChannelRange = {
|
|
@@ -46,18 +51,6 @@ const PERCENT_CHANNEL_RANGE: ColorChannelRange = {
|
|
|
46
51
|
pageSize: 10,
|
|
47
52
|
};
|
|
48
53
|
|
|
49
|
-
// Channel names (English only for now)
|
|
50
|
-
const CHANNEL_NAMES: Record<ColorChannel, string> = {
|
|
51
|
-
hue: "Hue",
|
|
52
|
-
saturation: "Saturation",
|
|
53
|
-
brightness: "Brightness",
|
|
54
|
-
lightness: "Lightness",
|
|
55
|
-
red: "Red",
|
|
56
|
-
green: "Green",
|
|
57
|
-
blue: "Blue",
|
|
58
|
-
alpha: "Alpha",
|
|
59
|
-
};
|
|
60
|
-
|
|
61
54
|
// React Stately uses OKLCH for color names so that lightness is perceptually
|
|
62
55
|
// consistent across hues.
|
|
63
56
|
const ORANGE_LIGHTNESS_THRESHOLD = 0.68;
|
|
@@ -122,46 +115,36 @@ function rgbToHsl(r: number, g: number, b: number): { h: number; s: number; l: n
|
|
|
122
115
|
}
|
|
123
116
|
}
|
|
124
117
|
|
|
118
|
+
// 2-decimal precision mirrors upstream RGBColor.toHSL (toFixedNumber(_, 2)); the
|
|
119
|
+
// old integer rounding silently shifted converted hues by up to half a degree,
|
|
120
|
+
// which surfaced as a 1-LSB gradient divergence in ColorArea.
|
|
125
121
|
return {
|
|
126
|
-
h:
|
|
127
|
-
s:
|
|
128
|
-
l:
|
|
122
|
+
h: toFixed(h * 360, 2),
|
|
123
|
+
s: toFixed(s * 100, 2),
|
|
124
|
+
l: toFixed(l * 100, 2),
|
|
129
125
|
};
|
|
130
126
|
}
|
|
131
127
|
|
|
132
128
|
/**
|
|
133
|
-
* Convert HSL to RGB.
|
|
129
|
+
* Convert HSL to RGB. Mirrors upstream @react-stately/color HSLColor.toRGB
|
|
130
|
+
* bit-for-bit — the Wikipedia "HSL to RGB alternative" formula
|
|
131
|
+
* (https://en.wikipedia.org/wiki/HSL_and_HSV#HSL_to_RGB_alternative) — so the
|
|
132
|
+
* float64 LSB rounding matches the oracle exactly. The classic hue2rgb algorithm
|
|
133
|
+
* is equivalent in the reals but rounds a channel differently at .5 boundaries
|
|
134
|
+
* (e.g. hsl(50,100%,50%) green computes to 212.5 → 213 here, 212 upstream).
|
|
135
|
+
* h is in degrees [0,360]; s and l are percentages [0,100].
|
|
134
136
|
*/
|
|
135
137
|
function hslToRgb(h: number, s: number, l: number): { r: number; g: number; b: number } {
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
if (s === 0) {
|
|
143
|
-
r = g = b = l;
|
|
144
|
-
} else {
|
|
145
|
-
const hue2rgb = (p: number, q: number, t: number) => {
|
|
146
|
-
if (t < 0) t += 1;
|
|
147
|
-
if (t > 1) t -= 1;
|
|
148
|
-
if (t < 1 / 6) return p + (q - p) * 6 * t;
|
|
149
|
-
if (t < 1 / 2) return q;
|
|
150
|
-
if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
|
|
151
|
-
return p;
|
|
152
|
-
};
|
|
153
|
-
|
|
154
|
-
const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
|
|
155
|
-
const p = 2 * l - q;
|
|
156
|
-
r = hue2rgb(p, q, h + 1 / 3);
|
|
157
|
-
g = hue2rgb(p, q, h);
|
|
158
|
-
b = hue2rgb(p, q, h - 1 / 3);
|
|
159
|
-
}
|
|
138
|
+
const saturation = s / 100;
|
|
139
|
+
const lightness = l / 100;
|
|
140
|
+
const a = saturation * Math.min(lightness, 1 - lightness);
|
|
141
|
+
const fn = (n: number, k = (n + h / 30) % 12) =>
|
|
142
|
+
lightness - a * Math.max(Math.min(k - 3, 9 - k, 1), -1);
|
|
160
143
|
|
|
161
144
|
return {
|
|
162
|
-
r: Math.round(
|
|
163
|
-
g: Math.round(
|
|
164
|
-
b: Math.round(
|
|
145
|
+
r: Math.round(fn(0) * 255),
|
|
146
|
+
g: Math.round(fn(8) * 255),
|
|
147
|
+
b: Math.round(fn(4) * 255),
|
|
165
148
|
};
|
|
166
149
|
}
|
|
167
150
|
|
|
@@ -194,72 +177,38 @@ function rgbToHsb(r: number, g: number, b: number): { h: number; s: number; b: n
|
|
|
194
177
|
}
|
|
195
178
|
}
|
|
196
179
|
|
|
180
|
+
// 2-decimal precision mirrors upstream RGBColor.toHSB (toFixedNumber(_, 2)).
|
|
197
181
|
return {
|
|
198
|
-
h:
|
|
199
|
-
s:
|
|
200
|
-
b:
|
|
182
|
+
h: toFixed(h * 360, 2),
|
|
183
|
+
s: toFixed(s * 100, 2),
|
|
184
|
+
b: toFixed(v * 100, 2),
|
|
201
185
|
};
|
|
202
186
|
}
|
|
203
187
|
|
|
204
188
|
/**
|
|
205
|
-
* Convert HSB to RGB.
|
|
189
|
+
* Convert HSB (HSV) to RGB. Mirrors upstream @react-stately/color HSBColor.toRGB
|
|
190
|
+
* bit-for-bit — the Wikipedia "HSV to RGB alternative" formula
|
|
191
|
+
* (https://en.wikipedia.org/wiki/HSL_and_HSV#HSV_to_RGB_alternative) — so the
|
|
192
|
+
* float64 LSB rounding matches the oracle exactly. The classic sextant algorithm
|
|
193
|
+
* is equivalent in the reals but can round a channel differently at .5 boundaries.
|
|
194
|
+
* h is in degrees [0,360]; s and b are percentages [0,100].
|
|
206
195
|
*/
|
|
207
196
|
function hsbToRgb(h: number, s: number, b: number): { r: number; g: number; b: number } {
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
let r: number, g: number, bl: number;
|
|
213
|
-
|
|
214
|
-
const i = Math.floor(h * 6);
|
|
215
|
-
const f = h * 6 - i;
|
|
216
|
-
const p = b * (1 - s);
|
|
217
|
-
const q = b * (1 - f * s);
|
|
218
|
-
const t = b * (1 - (1 - f) * s);
|
|
219
|
-
|
|
220
|
-
switch (i % 6) {
|
|
221
|
-
case 0:
|
|
222
|
-
r = b;
|
|
223
|
-
g = t;
|
|
224
|
-
bl = p;
|
|
225
|
-
break;
|
|
226
|
-
case 1:
|
|
227
|
-
r = q;
|
|
228
|
-
g = b;
|
|
229
|
-
bl = p;
|
|
230
|
-
break;
|
|
231
|
-
case 2:
|
|
232
|
-
r = p;
|
|
233
|
-
g = b;
|
|
234
|
-
bl = t;
|
|
235
|
-
break;
|
|
236
|
-
case 3:
|
|
237
|
-
r = p;
|
|
238
|
-
g = q;
|
|
239
|
-
bl = b;
|
|
240
|
-
break;
|
|
241
|
-
case 4:
|
|
242
|
-
r = t;
|
|
243
|
-
g = p;
|
|
244
|
-
bl = b;
|
|
245
|
-
break;
|
|
246
|
-
default:
|
|
247
|
-
r = b;
|
|
248
|
-
g = p;
|
|
249
|
-
bl = q;
|
|
250
|
-
break;
|
|
251
|
-
}
|
|
197
|
+
const saturation = s / 100;
|
|
198
|
+
const brightness = b / 100;
|
|
199
|
+
const fn = (n: number, k = (n + h / 60) % 6) =>
|
|
200
|
+
brightness - saturation * brightness * Math.max(Math.min(k, 4 - k, 1), 0);
|
|
252
201
|
|
|
253
202
|
return {
|
|
254
|
-
r: Math.round(
|
|
255
|
-
g: Math.round(
|
|
256
|
-
b: Math.round(
|
|
203
|
+
r: Math.round(fn(5) * 255),
|
|
204
|
+
g: Math.round(fn(3) * 255),
|
|
205
|
+
b: Math.round(fn(1) * 255),
|
|
257
206
|
};
|
|
258
207
|
}
|
|
259
208
|
|
|
260
|
-
function getOklchHueName(l: number, c: number, h: number): [string, number] {
|
|
209
|
+
function getOklchHueName(l: number, c: number, h: number, locale: string): [string, number] {
|
|
261
210
|
if (c < GRAY_THRESHOLD) {
|
|
262
|
-
return ["gray", l];
|
|
211
|
+
return [getColorStringForLocale("gray", locale), l];
|
|
263
212
|
}
|
|
264
213
|
|
|
265
214
|
for (let i = 0; i < OKLCH_HUES.length; i += 1) {
|
|
@@ -280,27 +229,29 @@ function getOklchHueName(l: number, c: number, h: number): [string, number] {
|
|
|
280
229
|
hueName = "yellow green";
|
|
281
230
|
}
|
|
282
231
|
|
|
283
|
-
|
|
232
|
+
const name = getColorStringForLocale(hueName as ColorStringKey, locale).toLocaleLowerCase(
|
|
233
|
+
locale
|
|
234
|
+
);
|
|
235
|
+
return [name, l];
|
|
284
236
|
}
|
|
285
237
|
}
|
|
286
238
|
|
|
287
|
-
return ["pink", l];
|
|
239
|
+
return [getColorStringForLocale("pink", locale).toLocaleLowerCase(locale), l];
|
|
288
240
|
}
|
|
289
241
|
|
|
290
|
-
function getColorNameFromColor(color: Color): string {
|
|
242
|
+
function getColorNameFromColor(color: Color, locale: string): string {
|
|
291
243
|
let [l, c, h] = toOKLCH(color);
|
|
292
|
-
const alpha = color.getChannelValue("alpha");
|
|
293
244
|
|
|
294
245
|
if (l > 0.999) {
|
|
295
|
-
return
|
|
246
|
+
return getColorStringForLocale("white", locale);
|
|
296
247
|
}
|
|
297
248
|
|
|
298
249
|
if (l < 0.001) {
|
|
299
|
-
return
|
|
250
|
+
return getColorStringForLocale("black", locale);
|
|
300
251
|
}
|
|
301
252
|
|
|
302
253
|
let hue: string;
|
|
303
|
-
[hue, l] = getOklchHueName(l, c, h);
|
|
254
|
+
[hue, l] = getOklchHueName(l, c, h, locale);
|
|
304
255
|
|
|
305
256
|
let chroma = "";
|
|
306
257
|
if (c <= 0.1 && c >= GRAY_THRESHOLD) {
|
|
@@ -322,17 +273,34 @@ function getColorNameFromColor(color: Color): string {
|
|
|
322
273
|
lightness = "very light";
|
|
323
274
|
}
|
|
324
275
|
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
276
|
+
if (chroma) {
|
|
277
|
+
chroma = getColorStringForLocale(chroma as ColorStringKey, locale);
|
|
278
|
+
}
|
|
279
|
+
if (lightness) {
|
|
280
|
+
lightness = getColorStringForLocale(lightness as ColorStringKey, locale);
|
|
328
281
|
}
|
|
329
282
|
|
|
330
|
-
|
|
283
|
+
const alpha = color.getChannelValue("alpha");
|
|
284
|
+
if (alpha < 1) {
|
|
285
|
+
const percentTransparent = new Intl.NumberFormat(locale, { style: "percent" }).format(1 - alpha);
|
|
286
|
+
return formatColorMessage("transparentColorName", locale, {
|
|
287
|
+
lightness,
|
|
288
|
+
chroma,
|
|
289
|
+
hue,
|
|
290
|
+
percentTransparent,
|
|
291
|
+
})
|
|
292
|
+
.replace(/\s+/g, " ")
|
|
293
|
+
.trim();
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
return formatColorMessage("colorName", locale, { lightness, chroma, hue })
|
|
297
|
+
.replace(/\s+/g, " ")
|
|
298
|
+
.trim();
|
|
331
299
|
}
|
|
332
300
|
|
|
333
|
-
function getHueNameFromColor(color: Color): string {
|
|
301
|
+
function getHueNameFromColor(color: Color, locale: string): string {
|
|
334
302
|
const [l, c, h] = toOKLCH(color);
|
|
335
|
-
const [name] = getOklchHueName(l, c, h);
|
|
303
|
+
const [name] = getOklchHueName(l, c, h, locale);
|
|
336
304
|
return name;
|
|
337
305
|
}
|
|
338
306
|
|
|
@@ -543,8 +511,8 @@ class RGBColorImpl implements Color {
|
|
|
543
511
|
}
|
|
544
512
|
}
|
|
545
513
|
|
|
546
|
-
getChannelName(channel: ColorChannel,
|
|
547
|
-
return
|
|
514
|
+
getChannelName(channel: ColorChannel, locale: string): string {
|
|
515
|
+
return getColorStringForLocale(channel as ColorStringKey, locale);
|
|
548
516
|
}
|
|
549
517
|
|
|
550
518
|
getChannelFormatOptions(channel: ColorChannel): Intl.NumberFormatOptions {
|
|
@@ -576,12 +544,12 @@ class RGBColorImpl implements Color {
|
|
|
576
544
|
return ["red", "green", "blue"];
|
|
577
545
|
}
|
|
578
546
|
|
|
579
|
-
getColorName(
|
|
580
|
-
return getColorNameFromColor(this);
|
|
547
|
+
getColorName(locale: string): string {
|
|
548
|
+
return getColorNameFromColor(this, locale);
|
|
581
549
|
}
|
|
582
550
|
|
|
583
|
-
getHueName(
|
|
584
|
-
return getHueNameFromColor(this);
|
|
551
|
+
getHueName(locale: string): string {
|
|
552
|
+
return getHueNameFromColor(this, locale);
|
|
585
553
|
}
|
|
586
554
|
}
|
|
587
555
|
|
|
@@ -595,9 +563,11 @@ class HSLColorImpl implements Color {
|
|
|
595
563
|
private alpha: number;
|
|
596
564
|
|
|
597
565
|
constructor(hue: number, saturation: number, lightness: number, alpha: number = 1) {
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
this.
|
|
566
|
+
// Store raw like upstream HSLColor's constructor — precision comes from the
|
|
567
|
+
// conversion (toFixed(_, 2)); rounding to integers here diverged from S2.
|
|
568
|
+
this.hue = clamp(hue % 360, 0, 360);
|
|
569
|
+
this.saturation = clamp(saturation, 0, 100);
|
|
570
|
+
this.lightness = clamp(lightness, 0, 100);
|
|
601
571
|
this.alpha = clamp(toFixed(alpha, 2), 0, 1);
|
|
602
572
|
}
|
|
603
573
|
|
|
@@ -711,8 +681,8 @@ class HSLColorImpl implements Color {
|
|
|
711
681
|
}
|
|
712
682
|
}
|
|
713
683
|
|
|
714
|
-
getChannelName(channel: ColorChannel,
|
|
715
|
-
return
|
|
684
|
+
getChannelName(channel: ColorChannel, locale: string): string {
|
|
685
|
+
return getColorStringForLocale(channel as ColorStringKey, locale);
|
|
716
686
|
}
|
|
717
687
|
|
|
718
688
|
getChannelFormatOptions(channel: ColorChannel): Intl.NumberFormatOptions {
|
|
@@ -750,12 +720,12 @@ class HSLColorImpl implements Color {
|
|
|
750
720
|
return ["hue", "saturation", "lightness"];
|
|
751
721
|
}
|
|
752
722
|
|
|
753
|
-
getColorName(
|
|
754
|
-
return getColorNameFromColor(this);
|
|
723
|
+
getColorName(locale: string): string {
|
|
724
|
+
return getColorNameFromColor(this, locale);
|
|
755
725
|
}
|
|
756
726
|
|
|
757
|
-
getHueName(
|
|
758
|
-
return getHueNameFromColor(this);
|
|
727
|
+
getHueName(locale: string): string {
|
|
728
|
+
return getHueNameFromColor(this, locale);
|
|
759
729
|
}
|
|
760
730
|
}
|
|
761
731
|
|
|
@@ -769,9 +739,10 @@ class HSBColorImpl implements Color {
|
|
|
769
739
|
private alpha: number;
|
|
770
740
|
|
|
771
741
|
constructor(hue: number, saturation: number, brightness: number, alpha: number = 1) {
|
|
772
|
-
|
|
773
|
-
this.
|
|
774
|
-
this.
|
|
742
|
+
// Store raw like upstream HSBColor's constructor (see HSLColorImpl).
|
|
743
|
+
this.hue = clamp(hue % 360, 0, 360);
|
|
744
|
+
this.saturation = clamp(saturation, 0, 100);
|
|
745
|
+
this.brightness = clamp(brightness, 0, 100);
|
|
775
746
|
this.alpha = clamp(toFixed(alpha, 2), 0, 1);
|
|
776
747
|
}
|
|
777
748
|
|
|
@@ -884,8 +855,8 @@ class HSBColorImpl implements Color {
|
|
|
884
855
|
}
|
|
885
856
|
}
|
|
886
857
|
|
|
887
|
-
getChannelName(channel: ColorChannel,
|
|
888
|
-
return
|
|
858
|
+
getChannelName(channel: ColorChannel, locale: string): string {
|
|
859
|
+
return getColorStringForLocale(channel as ColorStringKey, locale);
|
|
889
860
|
}
|
|
890
861
|
|
|
891
862
|
getChannelFormatOptions(channel: ColorChannel): Intl.NumberFormatOptions {
|
|
@@ -923,12 +894,12 @@ class HSBColorImpl implements Color {
|
|
|
923
894
|
return ["hue", "saturation", "brightness"];
|
|
924
895
|
}
|
|
925
896
|
|
|
926
|
-
getColorName(
|
|
927
|
-
return getColorNameFromColor(this);
|
|
897
|
+
getColorName(locale: string): string {
|
|
898
|
+
return getColorNameFromColor(this, locale);
|
|
928
899
|
}
|
|
929
900
|
|
|
930
|
-
getHueName(
|
|
931
|
-
return getHueNameFromColor(this);
|
|
901
|
+
getHueName(locale: string): string {
|
|
902
|
+
return getHueNameFromColor(this, locale);
|
|
932
903
|
}
|
|
933
904
|
}
|
|
934
905
|
|