@xsolla/xui-tag 0.222.0 → 0.223.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/README.md +60 -50
- package/native/index.d.mts +47 -2
- package/native/index.d.ts +47 -2
- package/native/index.js +368 -8
- package/native/index.js.map +1 -1
- package/native/index.mjs +373 -6
- package/native/index.mjs.map +1 -1
- package/package.json +8 -5
- package/web/index.d.mts +47 -2
- package/web/index.d.ts +47 -2
- package/web/index.js +366 -8
- package/web/index.js.map +1 -1
- package/web/index.mjs +371 -6
- package/web/index.mjs.map +1 -1
package/web/index.mjs
CHANGED
|
@@ -363,10 +363,141 @@ var Icon = ({
|
|
|
363
363
|
return /* @__PURE__ */ jsx3(StyledIcon, { "data-testid": dataTestId || testID, ...props, children });
|
|
364
364
|
};
|
|
365
365
|
|
|
366
|
+
// ../../foundation/primitives-web/src/Input.tsx
|
|
367
|
+
import { forwardRef } from "react";
|
|
368
|
+
import styled4 from "styled-components";
|
|
369
|
+
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
370
|
+
var FilteredInput = createFilteredElement("input");
|
|
371
|
+
var StyledInput = styled4(FilteredInput)`
|
|
372
|
+
background: transparent;
|
|
373
|
+
border: none;
|
|
374
|
+
outline: none;
|
|
375
|
+
width: 100%;
|
|
376
|
+
height: 100%;
|
|
377
|
+
padding: 0;
|
|
378
|
+
margin: 0;
|
|
379
|
+
color: ${(props) => props.color || "inherit"};
|
|
380
|
+
font-size: ${(props) => typeof props.fontSize === "number" ? `${props.fontSize}px` : props.fontSize || "inherit"};
|
|
381
|
+
font-family: ${(props) => props.fontFamily || '"Aktiv Grotesk", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif'};
|
|
382
|
+
text-align: inherit;
|
|
383
|
+
|
|
384
|
+
&::placeholder {
|
|
385
|
+
color: ${(props) => props.placeholderTextColor || "rgba(255, 255, 255, 0.5)"};
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
&:disabled {
|
|
389
|
+
cursor: not-allowed;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
/*
|
|
393
|
+
* Hide the native number spin buttons. type="number" is rendered with the
|
|
394
|
+
* toolkit's own chevron stepper (see Input "Type number" in Figma), so the
|
|
395
|
+
* OS chrome must not show alongside it. Keyboard ArrowUp / ArrowDown are
|
|
396
|
+
* unaffected — this only removes the painted control.
|
|
397
|
+
*/
|
|
398
|
+
&[type="number"] {
|
|
399
|
+
-moz-appearance: textfield;
|
|
400
|
+
appearance: textfield;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
&[type="number"]::-webkit-outer-spin-button,
|
|
404
|
+
&[type="number"]::-webkit-inner-spin-button {
|
|
405
|
+
-webkit-appearance: none;
|
|
406
|
+
appearance: none;
|
|
407
|
+
margin: 0;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
/* Override browser autofill background */
|
|
411
|
+
&:-webkit-autofill,
|
|
412
|
+
&:-webkit-autofill:hover,
|
|
413
|
+
&:-webkit-autofill:focus,
|
|
414
|
+
&:-webkit-autofill:active {
|
|
415
|
+
-webkit-box-shadow: 0 0 0 1000px transparent inset !important;
|
|
416
|
+
-webkit-background-clip: text !important;
|
|
417
|
+
-webkit-text-fill-color: ${(props) => props.color || "inherit"} !important;
|
|
418
|
+
}
|
|
419
|
+
`;
|
|
420
|
+
var InputPrimitive = forwardRef(
|
|
421
|
+
({
|
|
422
|
+
value,
|
|
423
|
+
placeholder,
|
|
424
|
+
onChange,
|
|
425
|
+
onChangeText,
|
|
426
|
+
onFocus,
|
|
427
|
+
onBlur,
|
|
428
|
+
onKeyDown,
|
|
429
|
+
disabled,
|
|
430
|
+
secureTextEntry,
|
|
431
|
+
style,
|
|
432
|
+
color,
|
|
433
|
+
fontSize,
|
|
434
|
+
fontFamily,
|
|
435
|
+
placeholderTextColor,
|
|
436
|
+
maxLength,
|
|
437
|
+
name,
|
|
438
|
+
type,
|
|
439
|
+
inputMode,
|
|
440
|
+
autoComplete,
|
|
441
|
+
id,
|
|
442
|
+
"aria-invalid": ariaInvalid,
|
|
443
|
+
"aria-describedby": ariaDescribedBy,
|
|
444
|
+
"aria-labelledby": ariaLabelledBy,
|
|
445
|
+
"aria-label": ariaLabel,
|
|
446
|
+
"aria-disabled": ariaDisabled,
|
|
447
|
+
"data-testid": dataTestId,
|
|
448
|
+
testID,
|
|
449
|
+
...rest
|
|
450
|
+
}, ref) => {
|
|
451
|
+
const handleChange = (e) => {
|
|
452
|
+
if (onChange) {
|
|
453
|
+
onChange(e);
|
|
454
|
+
}
|
|
455
|
+
if (onChangeText) {
|
|
456
|
+
onChangeText(e.target.value);
|
|
457
|
+
}
|
|
458
|
+
};
|
|
459
|
+
return /* @__PURE__ */ jsx4(
|
|
460
|
+
StyledInput,
|
|
461
|
+
{
|
|
462
|
+
ref,
|
|
463
|
+
id,
|
|
464
|
+
value,
|
|
465
|
+
name,
|
|
466
|
+
placeholder,
|
|
467
|
+
onChange: handleChange,
|
|
468
|
+
onFocus,
|
|
469
|
+
onBlur,
|
|
470
|
+
onKeyDown,
|
|
471
|
+
disabled,
|
|
472
|
+
type: secureTextEntry ? "password" : type || "text",
|
|
473
|
+
inputMode,
|
|
474
|
+
autoComplete,
|
|
475
|
+
style,
|
|
476
|
+
color,
|
|
477
|
+
fontSize,
|
|
478
|
+
fontFamily,
|
|
479
|
+
placeholderTextColor,
|
|
480
|
+
maxLength,
|
|
481
|
+
"aria-invalid": ariaInvalid,
|
|
482
|
+
"aria-describedby": ariaDescribedBy,
|
|
483
|
+
"aria-labelledby": ariaLabelledBy,
|
|
484
|
+
"aria-label": ariaLabel,
|
|
485
|
+
"aria-disabled": ariaDisabled,
|
|
486
|
+
"data-testid": dataTestId || testID,
|
|
487
|
+
...rest
|
|
488
|
+
}
|
|
489
|
+
);
|
|
490
|
+
}
|
|
491
|
+
);
|
|
492
|
+
InputPrimitive.displayName = "InputPrimitive";
|
|
493
|
+
|
|
494
|
+
// ../../foundation/primitives-web/src/index.tsx
|
|
495
|
+
var isWeb = true;
|
|
496
|
+
|
|
366
497
|
// src/Tag.tsx
|
|
367
498
|
import { useResolvedTheme } from "@xsolla/xui-core";
|
|
368
499
|
import { X } from "@xsolla/xui-icons";
|
|
369
|
-
import { jsx as
|
|
500
|
+
import { jsx as jsx5, jsxs } from "react/jsx-runtime";
|
|
370
501
|
var Tag = ({
|
|
371
502
|
size = "md",
|
|
372
503
|
tone = "primary",
|
|
@@ -375,6 +506,7 @@ var Tag = ({
|
|
|
375
506
|
iconLeft,
|
|
376
507
|
iconRight,
|
|
377
508
|
onRemove,
|
|
509
|
+
removeLabel,
|
|
378
510
|
testID,
|
|
379
511
|
themeMode,
|
|
380
512
|
themeProductContext,
|
|
@@ -437,6 +569,7 @@ var Tag = ({
|
|
|
437
569
|
};
|
|
438
570
|
const { bg, text, border } = resolveColors();
|
|
439
571
|
const isIconOnly = !children && (!!iconLeft || !!iconRight);
|
|
572
|
+
const resolvedRemoveLabel = removeLabel ?? (typeof children === "string" || typeof children === "number" ? `Remove ${children}` : "Remove");
|
|
440
573
|
return /* @__PURE__ */ jsxs(
|
|
441
574
|
Box,
|
|
442
575
|
{
|
|
@@ -460,8 +593,8 @@ var Tag = ({
|
|
|
460
593
|
...style
|
|
461
594
|
},
|
|
462
595
|
children: [
|
|
463
|
-
iconLeft && /* @__PURE__ */
|
|
464
|
-
children && /* @__PURE__ */
|
|
596
|
+
iconLeft && /* @__PURE__ */ jsx5(Icon, { size: sizeStyles.iconSize, color: text, children: iconLeft }),
|
|
597
|
+
children && /* @__PURE__ */ jsx5(
|
|
465
598
|
Text,
|
|
466
599
|
{
|
|
467
600
|
color: text,
|
|
@@ -476,13 +609,245 @@ var Tag = ({
|
|
|
476
609
|
children
|
|
477
610
|
}
|
|
478
611
|
),
|
|
479
|
-
iconRight && /* @__PURE__ */
|
|
480
|
-
onRemove &&
|
|
612
|
+
iconRight && /* @__PURE__ */ jsx5(Icon, { size: sizeStyles.iconSize, color: text, children: iconRight }),
|
|
613
|
+
onRemove && // A real <button>: focusable, activates on Enter / Space, and
|
|
614
|
+
// announced with its accessible name by screen readers.
|
|
615
|
+
/* @__PURE__ */ jsx5(
|
|
616
|
+
Box,
|
|
617
|
+
{
|
|
618
|
+
as: "button",
|
|
619
|
+
type: "button",
|
|
620
|
+
onPress: onRemove,
|
|
621
|
+
"aria-label": resolvedRemoveLabel,
|
|
622
|
+
alignItems: "center",
|
|
623
|
+
justifyContent: "center",
|
|
624
|
+
paddingHorizontal: 0,
|
|
625
|
+
paddingVertical: 0,
|
|
626
|
+
backgroundColor: "transparent",
|
|
627
|
+
borderWidth: 0,
|
|
628
|
+
cursor: "pointer",
|
|
629
|
+
"data-testid": "tag__remove-button",
|
|
630
|
+
children: /* @__PURE__ */ jsx5(X, { size: sizeStyles.iconSize, color: text })
|
|
631
|
+
}
|
|
632
|
+
)
|
|
481
633
|
]
|
|
482
634
|
}
|
|
483
635
|
);
|
|
484
636
|
};
|
|
637
|
+
|
|
638
|
+
// src/TagInput.tsx
|
|
639
|
+
import {
|
|
640
|
+
useState,
|
|
641
|
+
useRef,
|
|
642
|
+
forwardRef as forwardRef2,
|
|
643
|
+
useImperativeHandle
|
|
644
|
+
} from "react";
|
|
645
|
+
import {
|
|
646
|
+
useResolvedTheme as useResolvedTheme2,
|
|
647
|
+
useId
|
|
648
|
+
} from "@xsolla/xui-core";
|
|
649
|
+
import { jsx as jsx6, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
650
|
+
var chipSizeConfig = {
|
|
651
|
+
xl: "lg",
|
|
652
|
+
lg: "md",
|
|
653
|
+
md: "sm",
|
|
654
|
+
sm: "xs",
|
|
655
|
+
xs: "xs"
|
|
656
|
+
};
|
|
657
|
+
var TagInput = forwardRef2(
|
|
658
|
+
({
|
|
659
|
+
value,
|
|
660
|
+
onChange,
|
|
661
|
+
placeholder,
|
|
662
|
+
size = "md",
|
|
663
|
+
disabled = false,
|
|
664
|
+
error,
|
|
665
|
+
errorMessage,
|
|
666
|
+
label,
|
|
667
|
+
"aria-label": ariaLabel,
|
|
668
|
+
id: providedId,
|
|
669
|
+
name,
|
|
670
|
+
onFocus,
|
|
671
|
+
onBlur,
|
|
672
|
+
testID,
|
|
673
|
+
themeMode,
|
|
674
|
+
themeProductContext
|
|
675
|
+
}, ref) => {
|
|
676
|
+
const { theme } = useResolvedTheme2({ themeMode, themeProductContext });
|
|
677
|
+
const [draft, setDraft] = useState("");
|
|
678
|
+
const [isFocus, setIsFocus] = useState(false);
|
|
679
|
+
const inputRef = useRef(null);
|
|
680
|
+
const rawId = useId();
|
|
681
|
+
const safeId = rawId.replace(/:/g, "");
|
|
682
|
+
const inputId = providedId || `tag-input-${safeId}`;
|
|
683
|
+
const labelId = `${inputId}-label`;
|
|
684
|
+
const errorId = `${inputId}-error`;
|
|
685
|
+
useImperativeHandle(ref, () => inputRef.current, []);
|
|
686
|
+
const isError = !!(errorMessage || error);
|
|
687
|
+
const sizeStyles = theme.sizing.input(size);
|
|
688
|
+
const inputColors = theme.colors.control.input;
|
|
689
|
+
const borderRadius = theme.shape.input[size].borderRadius;
|
|
690
|
+
const chipSize = chipSizeConfig[size];
|
|
691
|
+
const chipHeight = theme.sizing.tag(chipSize).height;
|
|
692
|
+
const paddingVertical = Math.max(
|
|
693
|
+
(sizeStyles.height - chipHeight) / 2 - 1,
|
|
694
|
+
0
|
|
695
|
+
);
|
|
696
|
+
const commitDraft = () => {
|
|
697
|
+
if (draft.length === 0) return;
|
|
698
|
+
onChange([...value, draft]);
|
|
699
|
+
setDraft("");
|
|
700
|
+
};
|
|
701
|
+
const removeAt = (index2) => {
|
|
702
|
+
if (disabled) return;
|
|
703
|
+
onChange(value.filter((_, i) => i !== index2));
|
|
704
|
+
inputRef.current?.focus();
|
|
705
|
+
};
|
|
706
|
+
const handleKeyDown = (e) => {
|
|
707
|
+
const nativeEvent = e.nativeEvent;
|
|
708
|
+
const isComposing = nativeEvent?.isComposing === true || nativeEvent?.keyCode === 229;
|
|
709
|
+
if (e.key === "Enter") {
|
|
710
|
+
e.preventDefault();
|
|
711
|
+
if (!isComposing) commitDraft();
|
|
712
|
+
return;
|
|
713
|
+
}
|
|
714
|
+
if (e.key === "Backspace" && draft.length === 0 && value.length > 0) {
|
|
715
|
+
e.preventDefault();
|
|
716
|
+
onChange(value.slice(0, -1));
|
|
717
|
+
}
|
|
718
|
+
};
|
|
719
|
+
const handleChange = (e) => {
|
|
720
|
+
setDraft(e.target.value);
|
|
721
|
+
};
|
|
722
|
+
const handleFocus = () => {
|
|
723
|
+
if (!disabled) setIsFocus(true);
|
|
724
|
+
onFocus?.();
|
|
725
|
+
};
|
|
726
|
+
const handleBlur = () => {
|
|
727
|
+
setIsFocus(false);
|
|
728
|
+
commitDraft();
|
|
729
|
+
onBlur?.();
|
|
730
|
+
};
|
|
731
|
+
let backgroundColor = inputColors.bg;
|
|
732
|
+
let borderColor = inputColors.border;
|
|
733
|
+
let outlineColor;
|
|
734
|
+
if (disabled) {
|
|
735
|
+
backgroundColor = inputColors.bgDisable;
|
|
736
|
+
borderColor = inputColors.borderDisable;
|
|
737
|
+
} else if (isError) {
|
|
738
|
+
outlineColor = theme.colors.border.alert;
|
|
739
|
+
if (isFocus) backgroundColor = theme.colors.control.focus.bg;
|
|
740
|
+
} else if (isFocus) {
|
|
741
|
+
backgroundColor = theme.colors.control.focus.bg;
|
|
742
|
+
outlineColor = theme.colors.border.brand;
|
|
743
|
+
}
|
|
744
|
+
const textColor = disabled ? inputColors.textDisable : inputColors.text;
|
|
745
|
+
return /* @__PURE__ */ jsxs2(
|
|
746
|
+
Box,
|
|
747
|
+
{
|
|
748
|
+
flexDirection: "column",
|
|
749
|
+
gap: sizeStyles.fieldGap,
|
|
750
|
+
width: "100%",
|
|
751
|
+
testID,
|
|
752
|
+
children: [
|
|
753
|
+
label && /* @__PURE__ */ jsx6(Box, { as: "label", id: labelId, htmlFor: inputId, children: /* @__PURE__ */ jsx6(
|
|
754
|
+
Text,
|
|
755
|
+
{
|
|
756
|
+
color: theme.colors.content.secondary,
|
|
757
|
+
fontSize: sizeStyles.fontSize - 2,
|
|
758
|
+
fontWeight: "500",
|
|
759
|
+
children: label
|
|
760
|
+
}
|
|
761
|
+
) }),
|
|
762
|
+
/* @__PURE__ */ jsxs2(
|
|
763
|
+
Box,
|
|
764
|
+
{
|
|
765
|
+
backgroundColor,
|
|
766
|
+
borderColor,
|
|
767
|
+
borderWidth: 1,
|
|
768
|
+
minHeight: sizeStyles.height,
|
|
769
|
+
paddingVertical,
|
|
770
|
+
paddingHorizontal: sizeStyles.paddingHorizontal,
|
|
771
|
+
flexDirection: "row",
|
|
772
|
+
flexWrap: "wrap",
|
|
773
|
+
alignItems: "center",
|
|
774
|
+
gap: 4,
|
|
775
|
+
cursor: disabled ? "not-allowed" : "text",
|
|
776
|
+
onPress: () => {
|
|
777
|
+
if (!disabled) inputRef.current?.focus();
|
|
778
|
+
},
|
|
779
|
+
"data-testid": "tag-input__container",
|
|
780
|
+
style: {
|
|
781
|
+
borderRadius,
|
|
782
|
+
...outlineColor && isWeb ? { outline: `1px solid ${outlineColor}`, outlineOffset: "-1px" } : outlineColor && !isWeb ? { borderColor: outlineColor } : {}
|
|
783
|
+
},
|
|
784
|
+
hoverStyle: !disabled && !isFocus && !isError ? {
|
|
785
|
+
backgroundColor: inputColors.bgHover,
|
|
786
|
+
borderColor: inputColors.borderHover
|
|
787
|
+
} : void 0,
|
|
788
|
+
children: [
|
|
789
|
+
value.map((item, index2) => /* @__PURE__ */ jsx6(
|
|
790
|
+
Tag,
|
|
791
|
+
{
|
|
792
|
+
size: chipSize,
|
|
793
|
+
type: "outlined",
|
|
794
|
+
onRemove: disabled ? void 0 : () => removeAt(index2),
|
|
795
|
+
removeLabel: `Remove ${item}`,
|
|
796
|
+
testID: "tag-input__chip",
|
|
797
|
+
themeMode,
|
|
798
|
+
themeProductContext,
|
|
799
|
+
children: item
|
|
800
|
+
},
|
|
801
|
+
`${index2}-${item}`
|
|
802
|
+
)),
|
|
803
|
+
/* @__PURE__ */ jsx6(Box, { flex: 1, minWidth: 80, height: chipHeight, justifyContent: "center", children: /* @__PURE__ */ jsx6(
|
|
804
|
+
InputPrimitive,
|
|
805
|
+
{
|
|
806
|
+
ref: inputRef,
|
|
807
|
+
id: inputId,
|
|
808
|
+
name,
|
|
809
|
+
value: draft,
|
|
810
|
+
placeholder: value.length === 0 ? placeholder : void 0,
|
|
811
|
+
onChange: handleChange,
|
|
812
|
+
onKeyDown: handleKeyDown,
|
|
813
|
+
onFocus: handleFocus,
|
|
814
|
+
onBlur: handleBlur,
|
|
815
|
+
disabled,
|
|
816
|
+
type: "text",
|
|
817
|
+
color: textColor,
|
|
818
|
+
fontSize: sizeStyles.fontSize,
|
|
819
|
+
fontFamily: theme.fonts.body,
|
|
820
|
+
placeholderTextColor: inputColors.placeholder,
|
|
821
|
+
"aria-invalid": isError || void 0,
|
|
822
|
+
"aria-describedby": errorMessage ? errorId : void 0,
|
|
823
|
+
"aria-labelledby": label ? labelId : void 0,
|
|
824
|
+
"aria-label": !label ? ariaLabel : void 0,
|
|
825
|
+
"aria-disabled": disabled || void 0,
|
|
826
|
+
"data-testid": "tag-input__field"
|
|
827
|
+
}
|
|
828
|
+
) })
|
|
829
|
+
]
|
|
830
|
+
}
|
|
831
|
+
),
|
|
832
|
+
errorMessage && /* @__PURE__ */ jsx6(
|
|
833
|
+
Text,
|
|
834
|
+
{
|
|
835
|
+
id: errorId,
|
|
836
|
+
role: "alert",
|
|
837
|
+
color: theme.colors.content.alert.primary,
|
|
838
|
+
fontSize: sizeStyles.fontSize - 2,
|
|
839
|
+
style: { lineHeight: sizeStyles.lineHeight + "px" },
|
|
840
|
+
children: errorMessage
|
|
841
|
+
}
|
|
842
|
+
)
|
|
843
|
+
]
|
|
844
|
+
}
|
|
845
|
+
);
|
|
846
|
+
}
|
|
847
|
+
);
|
|
848
|
+
TagInput.displayName = "TagInput";
|
|
485
849
|
export {
|
|
486
|
-
Tag
|
|
850
|
+
Tag,
|
|
851
|
+
TagInput
|
|
487
852
|
};
|
|
488
853
|
//# sourceMappingURL=index.mjs.map
|