@xsolla/xui-input-color 0.184.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.
@@ -0,0 +1,899 @@
1
+ // src/InputColor.tsx
2
+ import { forwardRef as forwardRef2, useEffect, useMemo, useRef, useState } from "react";
3
+
4
+ // ../../foundation/primitives-native/src/Box.tsx
5
+ import {
6
+ View,
7
+ Pressable,
8
+ Image
9
+ } from "react-native";
10
+ import { jsx } from "react/jsx-runtime";
11
+ var Box = ({
12
+ children,
13
+ onPress,
14
+ onLayout,
15
+ onMoveShouldSetResponder,
16
+ onResponderGrant,
17
+ onResponderMove,
18
+ onResponderRelease,
19
+ onResponderTerminate,
20
+ backgroundColor,
21
+ borderColor,
22
+ borderWidth,
23
+ borderBottomWidth,
24
+ borderBottomColor,
25
+ borderTopWidth,
26
+ borderTopColor,
27
+ borderLeftWidth,
28
+ borderLeftColor,
29
+ borderRightWidth,
30
+ borderRightColor,
31
+ borderRadius,
32
+ borderStyle,
33
+ height,
34
+ padding,
35
+ paddingHorizontal,
36
+ paddingVertical,
37
+ margin,
38
+ marginTop,
39
+ marginBottom,
40
+ marginLeft,
41
+ marginRight,
42
+ flexDirection,
43
+ alignItems,
44
+ justifyContent,
45
+ position,
46
+ top,
47
+ bottom,
48
+ left,
49
+ right,
50
+ width,
51
+ minWidth,
52
+ minHeight,
53
+ maxWidth,
54
+ maxHeight,
55
+ flex,
56
+ overflow,
57
+ zIndex,
58
+ hoverStyle,
59
+ pressStyle,
60
+ style,
61
+ "data-testid": dataTestId,
62
+ testID,
63
+ as,
64
+ src,
65
+ alt,
66
+ ...rest
67
+ }) => {
68
+ const getContainerStyle = (pressed) => ({
69
+ backgroundColor: pressed && pressStyle?.backgroundColor ? pressStyle.backgroundColor : backgroundColor,
70
+ borderColor,
71
+ borderWidth,
72
+ borderBottomWidth,
73
+ borderBottomColor,
74
+ borderTopWidth,
75
+ borderTopColor,
76
+ borderLeftWidth,
77
+ borderLeftColor,
78
+ borderRightWidth,
79
+ borderRightColor,
80
+ borderRadius,
81
+ borderStyle,
82
+ overflow,
83
+ zIndex,
84
+ height,
85
+ width,
86
+ minWidth,
87
+ minHeight,
88
+ maxWidth,
89
+ maxHeight,
90
+ padding,
91
+ paddingHorizontal,
92
+ paddingVertical,
93
+ margin,
94
+ marginTop,
95
+ marginBottom,
96
+ marginLeft,
97
+ marginRight,
98
+ flexDirection,
99
+ alignItems,
100
+ justifyContent,
101
+ position,
102
+ top,
103
+ bottom,
104
+ left,
105
+ right,
106
+ flex,
107
+ ...style
108
+ });
109
+ const finalTestID = dataTestId || testID;
110
+ const {
111
+ role,
112
+ tabIndex,
113
+ onKeyDown,
114
+ onKeyUp,
115
+ "aria-label": _ariaLabel,
116
+ "aria-labelledby": _ariaLabelledBy,
117
+ "aria-current": _ariaCurrent,
118
+ "aria-disabled": _ariaDisabled,
119
+ "aria-live": _ariaLive,
120
+ className,
121
+ "data-testid": _dataTestId,
122
+ ...nativeRest
123
+ } = rest;
124
+ if (as === "img" && src) {
125
+ const imageStyle = {
126
+ width,
127
+ height,
128
+ borderRadius,
129
+ position,
130
+ top,
131
+ bottom,
132
+ left,
133
+ right,
134
+ ...style
135
+ };
136
+ return /* @__PURE__ */ jsx(
137
+ Image,
138
+ {
139
+ source: { uri: src },
140
+ style: imageStyle,
141
+ testID: finalTestID,
142
+ resizeMode: "cover",
143
+ ...nativeRest
144
+ }
145
+ );
146
+ }
147
+ if (onPress) {
148
+ return /* @__PURE__ */ jsx(
149
+ Pressable,
150
+ {
151
+ onPress,
152
+ onLayout,
153
+ onMoveShouldSetResponder,
154
+ onResponderGrant,
155
+ onResponderMove,
156
+ onResponderRelease,
157
+ onResponderTerminate,
158
+ style: ({ pressed }) => getContainerStyle(pressed),
159
+ testID: finalTestID,
160
+ ...nativeRest,
161
+ children
162
+ }
163
+ );
164
+ }
165
+ return /* @__PURE__ */ jsx(
166
+ View,
167
+ {
168
+ style: getContainerStyle(),
169
+ testID: finalTestID,
170
+ onLayout,
171
+ onMoveShouldSetResponder,
172
+ onResponderGrant,
173
+ onResponderMove,
174
+ onResponderRelease,
175
+ onResponderTerminate,
176
+ ...nativeRest,
177
+ children
178
+ }
179
+ );
180
+ };
181
+
182
+ // ../../foundation/primitives-native/src/Text.tsx
183
+ import {
184
+ Text as RNText,
185
+ StyleSheet
186
+ } from "react-native";
187
+ import { jsx as jsx2 } from "react/jsx-runtime";
188
+ var roleMap = {
189
+ alert: "alert",
190
+ heading: "header",
191
+ button: "button",
192
+ link: "link",
193
+ text: "text"
194
+ };
195
+ var parseNumericValue = (value) => {
196
+ if (value === void 0) return void 0;
197
+ if (typeof value === "number") return value;
198
+ const parsed = parseFloat(value);
199
+ return isNaN(parsed) ? void 0 : parsed;
200
+ };
201
+ var Text = ({
202
+ children,
203
+ color,
204
+ fontSize,
205
+ fontWeight,
206
+ fontFamily,
207
+ textAlign,
208
+ lineHeight,
209
+ numberOfLines,
210
+ id,
211
+ role,
212
+ testID,
213
+ "data-testid": dataTestId,
214
+ style: styleProp,
215
+ ...props
216
+ }) => {
217
+ let resolvedFontFamily = fontFamily ? fontFamily.split(",")[0].replace(/['"]/g, "").trim() : void 0;
218
+ if (resolvedFontFamily === "Pilat Wide" || resolvedFontFamily === "Pilat Wide Bold" || resolvedFontFamily === "Aktiv Grotesk") {
219
+ resolvedFontFamily = void 0;
220
+ }
221
+ const incomingStyle = StyleSheet.flatten(styleProp);
222
+ const baseStyle = {
223
+ color: color ?? incomingStyle?.color,
224
+ fontSize: typeof fontSize === "number" ? fontSize : void 0,
225
+ fontWeight,
226
+ fontFamily: resolvedFontFamily,
227
+ textDecorationLine: props.textDecoration,
228
+ textAlign: textAlign ?? incomingStyle?.textAlign,
229
+ lineHeight: parseNumericValue(lineHeight ?? incomingStyle?.lineHeight),
230
+ marginTop: parseNumericValue(
231
+ incomingStyle?.marginTop
232
+ ),
233
+ marginBottom: parseNumericValue(
234
+ incomingStyle?.marginBottom
235
+ )
236
+ };
237
+ const accessibilityRole = role ? roleMap[role] : void 0;
238
+ return /* @__PURE__ */ jsx2(
239
+ RNText,
240
+ {
241
+ style: baseStyle,
242
+ numberOfLines,
243
+ testID: dataTestId || testID || id,
244
+ accessibilityRole,
245
+ children
246
+ }
247
+ );
248
+ };
249
+
250
+ // ../../foundation/primitives-native/src/Input.tsx
251
+ import { forwardRef } from "react";
252
+ import { TextInput as RNTextInput } from "react-native";
253
+ import { jsx as jsx3 } from "react/jsx-runtime";
254
+ var keyboardTypeMap = {
255
+ text: "default",
256
+ number: "numeric",
257
+ email: "email-address",
258
+ tel: "phone-pad",
259
+ url: "url",
260
+ decimal: "decimal-pad"
261
+ };
262
+ var inputModeToKeyboardType = {
263
+ none: "default",
264
+ text: "default",
265
+ decimal: "decimal-pad",
266
+ numeric: "number-pad",
267
+ tel: "phone-pad",
268
+ search: "default",
269
+ email: "email-address",
270
+ url: "url"
271
+ };
272
+ var autoCompleteToTextContentType = {
273
+ "one-time-code": "oneTimeCode",
274
+ email: "emailAddress",
275
+ username: "username",
276
+ password: "password",
277
+ "new-password": "newPassword",
278
+ tel: "telephoneNumber",
279
+ "postal-code": "postalCode",
280
+ name: "name"
281
+ };
282
+ var InputPrimitive = forwardRef(
283
+ ({
284
+ value,
285
+ placeholder,
286
+ onChange,
287
+ onChangeText,
288
+ onFocus,
289
+ onBlur,
290
+ onKeyDown,
291
+ disabled,
292
+ secureTextEntry,
293
+ style,
294
+ color,
295
+ fontSize,
296
+ fontFamily,
297
+ placeholderTextColor,
298
+ maxLength,
299
+ type,
300
+ inputMode,
301
+ autoComplete,
302
+ id,
303
+ "aria-describedby": ariaDescribedBy,
304
+ "aria-label": ariaLabel,
305
+ "aria-disabled": ariaDisabled,
306
+ "data-testid": dataTestId,
307
+ testID
308
+ }, ref) => {
309
+ const handleChangeText = (text) => {
310
+ onChangeText?.(text);
311
+ if (onChange) {
312
+ const syntheticEvent = {
313
+ target: { value: text },
314
+ currentTarget: { value: text },
315
+ type: "change",
316
+ nativeEvent: { text },
317
+ preventDefault: () => {
318
+ },
319
+ stopPropagation: () => {
320
+ },
321
+ isTrusted: false
322
+ };
323
+ onChange(syntheticEvent);
324
+ }
325
+ };
326
+ const keyboardType = inputMode ? inputModeToKeyboardType[inputMode] || "default" : type ? keyboardTypeMap[type] || "default" : "default";
327
+ const textContentType = autoComplete ? autoCompleteToTextContentType[autoComplete] : void 0;
328
+ let resolvedFontFamily = fontFamily ? fontFamily.split(",")[0].replace(/['"]/g, "").trim() : void 0;
329
+ if (resolvedFontFamily === "Pilat Wide" || resolvedFontFamily === "Pilat Wide Bold" || resolvedFontFamily === "Aktiv Grotesk") {
330
+ resolvedFontFamily = void 0;
331
+ }
332
+ return /* @__PURE__ */ jsx3(
333
+ RNTextInput,
334
+ {
335
+ ref,
336
+ value,
337
+ placeholder,
338
+ onChangeText: handleChangeText,
339
+ onFocus,
340
+ onBlur,
341
+ onKeyPress: (e) => {
342
+ if (onKeyDown) {
343
+ onKeyDown({
344
+ key: e.nativeEvent.key,
345
+ preventDefault: () => {
346
+ }
347
+ });
348
+ }
349
+ },
350
+ editable: !disabled,
351
+ secureTextEntry: secureTextEntry || type === "password",
352
+ keyboardType,
353
+ textContentType,
354
+ style: [
355
+ {
356
+ color,
357
+ fontSize: typeof fontSize === "number" ? fontSize : void 0,
358
+ fontFamily: resolvedFontFamily,
359
+ flex: 1,
360
+ padding: 0,
361
+ textAlign: style?.textAlign || "left"
362
+ },
363
+ style
364
+ ],
365
+ placeholderTextColor,
366
+ maxLength,
367
+ testID: dataTestId || testID || id,
368
+ accessibilityLabel: ariaLabel,
369
+ accessibilityHint: ariaDescribedBy,
370
+ accessibilityState: {
371
+ disabled: disabled || ariaDisabled
372
+ },
373
+ accessible: true
374
+ }
375
+ );
376
+ }
377
+ );
378
+ InputPrimitive.displayName = "InputPrimitive";
379
+
380
+ // ../../foundation/primitives-native/src/index.tsx
381
+ var isWeb = false;
382
+
383
+ // src/InputColor.tsx
384
+ import {
385
+ useResolvedTheme,
386
+ useId
387
+ } from "@xsolla/xui-core";
388
+ import { Fragment, jsx as jsx4, jsxs } from "react/jsx-runtime";
389
+ var clamp = (n, min, max) => Math.min(Math.max(n, min), max);
390
+ var HEX_CHARS = /[^0-9a-fA-F]/g;
391
+ function hexToRgba(hex) {
392
+ let h = (hex || "").replace(/^#/, "");
393
+ if (h.length === 3 || h.length === 4) {
394
+ h = h.split("").map((c) => c + c).join("");
395
+ }
396
+ const r = parseInt(h.slice(0, 2), 16);
397
+ const g = parseInt(h.slice(2, 4), 16);
398
+ const b = parseInt(h.slice(4, 6), 16);
399
+ const a = h.length >= 8 ? parseInt(h.slice(6, 8), 16) / 255 : 1;
400
+ return {
401
+ r: Number.isNaN(r) ? 0 : r,
402
+ g: Number.isNaN(g) ? 0 : g,
403
+ b: Number.isNaN(b) ? 0 : b,
404
+ a: Number.isNaN(a) ? 1 : parseFloat(a.toFixed(2))
405
+ };
406
+ }
407
+ function rgbaToHex({ r, g, b, a }, includeAlpha) {
408
+ const toHex = (n) => Math.round(clamp(n, 0, 255)).toString(16).padStart(2, "0");
409
+ const alpha = includeAlpha ? toHex(clamp(a, 0, 1) * 255) : "";
410
+ return `#${toHex(r)}${toHex(g)}${toHex(b)}${alpha}`.toUpperCase();
411
+ }
412
+ var SWATCH_SIZE = {
413
+ xl: 36,
414
+ lg: 32,
415
+ md: 26,
416
+ sm: 20,
417
+ xs: 14
418
+ };
419
+ var ALPHA_WIDTH = {
420
+ xl: 96,
421
+ lg: 86,
422
+ md: 77,
423
+ sm: 67,
424
+ xs: 58
425
+ };
426
+ var FRAME_GAP = {
427
+ xl: 10,
428
+ lg: 10,
429
+ md: 8,
430
+ sm: 6,
431
+ xs: 4
432
+ };
433
+ var CHECKERBOARD = "conic-gradient(rgba(0,0,0,0.45) 25%, transparent 0 50%, rgba(0,0,0,0.45) 0 75%, transparent 0)";
434
+ function cornerRadii(corner, radius) {
435
+ const map = {
436
+ all: [radius, radius, radius, radius],
437
+ left: [radius, 0, 0, radius],
438
+ right: [0, radius, radius, 0],
439
+ middle: [0, 0, 0, 0]
440
+ };
441
+ const [tl, tr, br, bl] = map[corner];
442
+ return {
443
+ borderTopLeftRadius: tl,
444
+ borderTopRightRadius: tr,
445
+ borderBottomRightRadius: br,
446
+ borderBottomLeftRadius: bl
447
+ };
448
+ }
449
+ function ColorSwatch({
450
+ size,
451
+ rgba,
452
+ transparency,
453
+ borderColor
454
+ }) {
455
+ const solid = `rgb(${rgba.r}, ${rgba.g}, ${rgba.b})`;
456
+ const withAlpha = `rgba(${rgba.r}, ${rgba.g}, ${rgba.b}, ${rgba.a})`;
457
+ return /* @__PURE__ */ jsxs(
458
+ Box,
459
+ {
460
+ width: size,
461
+ height: size,
462
+ position: "relative",
463
+ borderColor,
464
+ borderWidth: 1,
465
+ style: { borderRadius: 4, overflow: "hidden" },
466
+ "data-testid": "input-color__swatch-preview",
467
+ children: [
468
+ transparency && /* @__PURE__ */ jsx4(
469
+ Box,
470
+ {
471
+ "aria-hidden": true,
472
+ style: {
473
+ position: "absolute",
474
+ inset: 0,
475
+ backgroundImage: CHECKERBOARD,
476
+ backgroundSize: "8px 8px",
477
+ opacity: 0.2
478
+ }
479
+ }
480
+ ),
481
+ transparency ? /* @__PURE__ */ jsxs(Fragment, { children: [
482
+ /* @__PURE__ */ jsx4(
483
+ Box,
484
+ {
485
+ style: {
486
+ position: "absolute",
487
+ top: 0,
488
+ bottom: 0,
489
+ left: 0,
490
+ right: "50%",
491
+ backgroundColor: solid
492
+ }
493
+ }
494
+ ),
495
+ /* @__PURE__ */ jsx4(
496
+ Box,
497
+ {
498
+ style: {
499
+ position: "absolute",
500
+ top: 0,
501
+ bottom: 0,
502
+ left: "50%",
503
+ right: 0,
504
+ backgroundColor: withAlpha
505
+ }
506
+ }
507
+ )
508
+ ] }) : /* @__PURE__ */ jsx4(
509
+ Box,
510
+ {
511
+ style: { position: "absolute", inset: 0, backgroundColor: solid }
512
+ }
513
+ )
514
+ ]
515
+ }
516
+ );
517
+ }
518
+ function TextField({
519
+ value,
520
+ onCommit,
521
+ sanitize,
522
+ maxLength,
523
+ textAlign = "left",
524
+ color,
525
+ fontSize,
526
+ fontFamily,
527
+ ariaLabel,
528
+ inputMode = "text",
529
+ step,
530
+ testID,
531
+ onFocus,
532
+ onBlur
533
+ }) {
534
+ const [text, setText] = useState(value);
535
+ const isFocusedRef = useRef(false);
536
+ useEffect(() => {
537
+ if (!isFocusedRef.current) setText(value);
538
+ }, [value]);
539
+ const handleChange = (e) => {
540
+ const next = sanitize(e.target.value);
541
+ setText(next);
542
+ onCommit(next);
543
+ };
544
+ const handleFocus = () => {
545
+ isFocusedRef.current = true;
546
+ onFocus();
547
+ };
548
+ const handleBlur = () => {
549
+ isFocusedRef.current = false;
550
+ setText(value);
551
+ onBlur();
552
+ };
553
+ const handleKeyDown = (e) => {
554
+ if (e.key === "Enter") {
555
+ e.currentTarget.blur();
556
+ return;
557
+ }
558
+ if (step && (e.key === "ArrowUp" || e.key === "ArrowDown")) {
559
+ e.preventDefault();
560
+ const current = Number.parseInt(text, 10);
561
+ const base = Number.isNaN(current) ? 0 : current;
562
+ const next = String(
563
+ clamp(base + (e.key === "ArrowUp" ? 1 : -1), step.min, step.max)
564
+ );
565
+ setText(next);
566
+ onCommit(next);
567
+ }
568
+ };
569
+ return /* @__PURE__ */ jsx4(Box, { flex: 1, height: "100%", justifyContent: "center", children: /* @__PURE__ */ jsx4(
570
+ InputPrimitive,
571
+ {
572
+ value: text,
573
+ onChange: handleChange,
574
+ onFocus: handleFocus,
575
+ onBlur: handleBlur,
576
+ onKeyDown: handleKeyDown,
577
+ type: "text",
578
+ inputMode,
579
+ maxLength,
580
+ color,
581
+ fontSize,
582
+ fontFamily,
583
+ "aria-label": ariaLabel,
584
+ "data-testid": testID,
585
+ style: textAlign === "center" ? { textAlign: "center" } : void 0
586
+ }
587
+ ) });
588
+ }
589
+ var CHANNEL_LABEL = {
590
+ red: "Red channel",
591
+ green: "Green channel",
592
+ blue: "Blue channel",
593
+ alpha: "Opacity percentage"
594
+ };
595
+ var InputColor = forwardRef2(
596
+ ({
597
+ value,
598
+ defaultValue,
599
+ onChange,
600
+ onSwatchClick,
601
+ type = "color-hex",
602
+ transparency = false,
603
+ size = "md",
604
+ label,
605
+ id: providedId,
606
+ "aria-label": ariaLabel,
607
+ testID,
608
+ themeMode,
609
+ themeProductContext
610
+ }, ref) => {
611
+ const { theme } = useResolvedTheme({ themeMode, themeProductContext });
612
+ const [internalValue, setInternalValue] = useState(
613
+ value ?? defaultValue ?? "#000000"
614
+ );
615
+ useEffect(() => {
616
+ if (value !== void 0) setInternalValue(value);
617
+ }, [value]);
618
+ const currentValue = internalValue;
619
+ const [focusedKey, setFocusedKey] = useState(null);
620
+ const [liveMessage, setLiveMessage] = useState("");
621
+ const rawId = useId();
622
+ const safeId = rawId.replace(/:/g, "");
623
+ const inputId = providedId || `input-color-${safeId}`;
624
+ const labelId = `${inputId}-label`;
625
+ const rgba = useMemo(() => hexToRgba(currentValue), [currentValue]);
626
+ const sizeStyles = theme.sizing.input(size);
627
+ const inputColors = theme.colors.control.input;
628
+ const borderRadius = theme.shape.input[size].borderRadius;
629
+ const swatchSize = SWATCH_SIZE[size];
630
+ const showSwatch = type === "color" || type === "color-hex" || type === "color-rgb";
631
+ const isHex = type === "hex" || type === "color-hex";
632
+ const isRgb = type === "rgb" || type === "color-rgb";
633
+ const isSwatchOnly = type === "color";
634
+ const textColor = inputColors.text;
635
+ const placeholderColor = inputColors.placeholder;
636
+ const fontFamily = theme.fonts.body;
637
+ const emit = (next) => {
638
+ setInternalValue(next);
639
+ setLiveMessage(`Color updated to ${next}`);
640
+ onChange?.(next);
641
+ };
642
+ const emitFromRgba = (next) => emit(rgbaToHex(next, transparency));
643
+ const segmentVisuals = (focused) => {
644
+ let backgroundColor = inputColors.bg;
645
+ let borderColor = inputColors.border;
646
+ let outlineColor;
647
+ if (focused) {
648
+ backgroundColor = theme.colors.control.focus.bg;
649
+ outlineColor = theme.colors.border.brand;
650
+ }
651
+ return { backgroundColor, borderColor, outlineColor };
652
+ };
653
+ const renderSegment = (key, corner, content, opts = {}) => {
654
+ const focused = focusedKey === key;
655
+ const { backgroundColor, borderColor, outlineColor } = segmentVisuals(focused);
656
+ const width = opts.square ? sizeStyles.height : opts.width;
657
+ return /* @__PURE__ */ jsx4(
658
+ Box,
659
+ {
660
+ backgroundColor,
661
+ borderColor,
662
+ borderWidth: 1,
663
+ height: sizeStyles.height,
664
+ width,
665
+ flex: opts.flex,
666
+ flexDirection: "row",
667
+ alignItems: "center",
668
+ justifyContent: opts.square ? "center" : "flex-start",
669
+ gap: FRAME_GAP[size],
670
+ paddingHorizontal: opts.square ? 0 : sizeStyles.paddingHorizontal,
671
+ position: "relative",
672
+ style: {
673
+ ...cornerRadii(corner, borderRadius),
674
+ minWidth: opts.square ? void 0 : 40,
675
+ ...outlineColor && isWeb ? { outline: `1px solid ${outlineColor}`, outlineOffset: "-1px" } : outlineColor && !isWeb ? { borderColor: outlineColor } : {}
676
+ },
677
+ hoverStyle: !focused ? {
678
+ backgroundColor: inputColors.bgHover,
679
+ borderColor: inputColors.borderHover
680
+ } : void 0,
681
+ children: content
682
+ },
683
+ key
684
+ );
685
+ };
686
+ const swatchVisual = /* @__PURE__ */ jsx4(
687
+ ColorSwatch,
688
+ {
689
+ size: swatchSize,
690
+ rgba,
691
+ transparency,
692
+ borderColor: theme.colors.border.secondary
693
+ }
694
+ );
695
+ const swatchNode = isSwatchOnly ? /* @__PURE__ */ jsx4(
696
+ Box,
697
+ {
698
+ as: "button",
699
+ type: "button",
700
+ onPress: () => onSwatchClick?.(),
701
+ cursor: "pointer",
702
+ backgroundColor: "transparent",
703
+ borderWidth: 0,
704
+ padding: 0,
705
+ alignItems: "center",
706
+ justifyContent: "center",
707
+ "aria-label": "Open color picker",
708
+ "data-testid": "input-color__swatch",
709
+ onFocus: () => setFocusedKey("swatch"),
710
+ onBlur: () => setFocusedKey(null),
711
+ children: swatchVisual
712
+ }
713
+ ) : /* @__PURE__ */ jsx4(
714
+ Box,
715
+ {
716
+ "aria-hidden": true,
717
+ alignItems: "center",
718
+ justifyContent: "center",
719
+ "data-testid": "input-color__swatch-decorative",
720
+ children: swatchVisual
721
+ }
722
+ );
723
+ const hexContent = /* @__PURE__ */ jsxs(Fragment, { children: [
724
+ /* @__PURE__ */ jsx4(
725
+ Text,
726
+ {
727
+ color: placeholderColor,
728
+ fontSize: sizeStyles.fontSize,
729
+ style: { lineHeight: `${sizeStyles.lineHeight}px` },
730
+ children: "#"
731
+ }
732
+ ),
733
+ /* @__PURE__ */ jsx4(
734
+ TextField,
735
+ {
736
+ value: rgbaToHex(rgba, false).replace(/^#/, ""),
737
+ sanitize: (t) => t.replace(HEX_CHARS, "").toUpperCase(),
738
+ maxLength: 6,
739
+ onCommit: (digits) => {
740
+ if (digits.length === 3 || digits.length === 6) {
741
+ const next = hexToRgba(`#${digits}`);
742
+ emitFromRgba({ ...next, a: rgba.a });
743
+ }
744
+ },
745
+ color: textColor,
746
+ fontSize: sizeStyles.fontSize,
747
+ fontFamily,
748
+ ariaLabel: "Hex color value",
749
+ testID: "input-color__hex",
750
+ onFocus: () => setFocusedKey("hex"),
751
+ onBlur: () => setFocusedKey(null)
752
+ }
753
+ )
754
+ ] });
755
+ const channelContent = (channel) => {
756
+ const isAlpha = channel === "alpha";
757
+ const display = isAlpha ? Math.round(rgba.a * 100) : rgba[channel[0]];
758
+ const field = /* @__PURE__ */ jsx4(
759
+ TextField,
760
+ {
761
+ value: String(display),
762
+ inputMode: "numeric",
763
+ sanitize: (t) => t.replace(/[^0-9]/g, ""),
764
+ maxLength: 3,
765
+ step: isAlpha ? { min: 0, max: 100 } : { min: 0, max: 255 },
766
+ onCommit: (t) => {
767
+ if (t === "") return;
768
+ const num = parseInt(t, 10);
769
+ if (Number.isNaN(num)) return;
770
+ if (isAlpha) {
771
+ emitFromRgba({ ...rgba, a: clamp(num, 0, 100) / 100 });
772
+ } else {
773
+ const k = channel[0];
774
+ emitFromRgba({ ...rgba, [k]: clamp(num, 0, 255) });
775
+ }
776
+ },
777
+ color: textColor,
778
+ fontSize: sizeStyles.fontSize,
779
+ fontFamily,
780
+ ariaLabel: CHANNEL_LABEL[channel],
781
+ testID: `input-color__channel-${channel}`,
782
+ onFocus: () => setFocusedKey(`channel-${channel}`),
783
+ onBlur: () => setFocusedKey(null)
784
+ }
785
+ );
786
+ if (!isAlpha) return field;
787
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
788
+ field,
789
+ /* @__PURE__ */ jsx4(
790
+ Text,
791
+ {
792
+ color: placeholderColor,
793
+ fontSize: sizeStyles.fontSize,
794
+ style: { lineHeight: `${sizeStyles.lineHeight}px` },
795
+ children: "%"
796
+ }
797
+ )
798
+ ] });
799
+ };
800
+ const cells = [];
801
+ if (isSwatchOnly) {
802
+ cells.push({ key: "swatch", content: swatchNode, square: true });
803
+ } else if (isHex) {
804
+ cells.push({
805
+ key: "field",
806
+ flex: 1,
807
+ content: /* @__PURE__ */ jsxs(Fragment, { children: [
808
+ showSwatch && swatchNode,
809
+ /* @__PURE__ */ jsx4(Box, { flex: 1, flexDirection: "row", alignItems: "center", gap: 4, children: hexContent })
810
+ ] })
811
+ });
812
+ } else if (isRgb) {
813
+ if (showSwatch) {
814
+ cells.push({ key: "swatch", content: swatchNode, square: true });
815
+ }
816
+ ["red", "green", "blue"].forEach(
817
+ (channel) => cells.push({
818
+ key: `channel-${channel}`,
819
+ content: channelContent(channel),
820
+ flex: 1
821
+ })
822
+ );
823
+ }
824
+ if (transparency) {
825
+ cells.push({
826
+ key: "channel-alpha",
827
+ content: channelContent("alpha"),
828
+ width: ALPHA_WIDTH[size]
829
+ });
830
+ }
831
+ const control = cells.map((cell, i) => {
832
+ const corner = cells.length === 1 ? "all" : i === 0 ? "left" : i === cells.length - 1 ? "right" : "middle";
833
+ return renderSegment(cell.key, corner, cell.content, {
834
+ flex: cell.flex,
835
+ width: cell.width,
836
+ square: cell.square
837
+ });
838
+ });
839
+ return /* @__PURE__ */ jsxs(
840
+ Box,
841
+ {
842
+ ref,
843
+ flexDirection: "column",
844
+ gap: sizeStyles.fieldGap,
845
+ width: isSwatchOnly ? void 0 : "100%",
846
+ testID,
847
+ children: [
848
+ label && /* @__PURE__ */ jsx4(Box, { as: "label", id: labelId, children: /* @__PURE__ */ jsx4(
849
+ Text,
850
+ {
851
+ color: theme.colors.content.secondary,
852
+ fontSize: sizeStyles.fontSize - 2,
853
+ fontWeight: "500",
854
+ children: label
855
+ }
856
+ ) }),
857
+ /* @__PURE__ */ jsx4(
858
+ Box,
859
+ {
860
+ flexDirection: "row",
861
+ alignItems: "center",
862
+ gap: 2,
863
+ width: isSwatchOnly ? void 0 : "100%",
864
+ role: "group",
865
+ "aria-labelledby": label ? labelId : void 0,
866
+ "aria-label": !label ? ariaLabel : void 0,
867
+ children: control
868
+ }
869
+ ),
870
+ isWeb && /* @__PURE__ */ jsx4(
871
+ Box,
872
+ {
873
+ role: "status",
874
+ "aria-live": "polite",
875
+ "data-testid": "input-color__live",
876
+ style: {
877
+ position: "absolute",
878
+ width: 1,
879
+ height: 1,
880
+ padding: 0,
881
+ margin: -1,
882
+ overflow: "hidden",
883
+ clip: "rect(0 0 0 0)",
884
+ whiteSpace: "nowrap",
885
+ border: 0
886
+ },
887
+ children: liveMessage
888
+ }
889
+ )
890
+ ]
891
+ }
892
+ );
893
+ }
894
+ );
895
+ InputColor.displayName = "InputColor";
896
+ export {
897
+ InputColor
898
+ };
899
+ //# sourceMappingURL=index.mjs.map