@ecohouse/ui 0.1.1 → 0.1.3
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 +2 -1
- package/dist/index.cjs +1266 -109
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +188 -12
- package/dist/index.d.ts +188 -12
- package/dist/index.js +1260 -112
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
- package/src/components/Button/Button.tsx +106 -88
- package/src/components/Checkbox/Checkbox.stories.tsx +112 -0
- package/src/components/Checkbox/Checkbox.tsx +150 -0
- package/src/components/Checkbox/index.ts +2 -0
- package/src/components/Input/Input.stories.tsx +11 -40
- package/src/components/Input/Input.tsx +58 -54
- package/src/components/Input/index.ts +1 -1
- package/src/components/Select/Select.stories.tsx +196 -0
- package/src/components/Select/Select.tsx +851 -0
- package/src/components/Select/index.ts +2 -0
- package/src/components/Textarea/Textarea.stories.tsx +71 -0
- package/src/components/Textarea/Textarea.tsx +241 -0
- package/src/components/Textarea/index.ts +2 -0
- package/src/components/Toggle/Toggle.stories.tsx +100 -0
- package/src/components/Toggle/Toggle.tsx +176 -0
- package/src/components/Toggle/index.ts +2 -0
- package/src/components/index.ts +13 -1
- package/src/icons/Check/CheckIcon.tsx +26 -0
- package/src/icons/Check/CheckIcon.web.tsx +32 -0
- package/src/icons/Check/checkPath.ts +2 -0
- package/src/icons/Check/index.ts +1 -0
- package/src/icons/ChevronDown/ChevronDownIcon.tsx +30 -0
- package/src/icons/ChevronDown/ChevronDownIcon.web.tsx +36 -0
- package/src/icons/ChevronDown/chevronDownPath.ts +2 -0
- package/src/icons/ChevronDown/index.ts +1 -0
- package/src/icons/Search/SearchIcon.tsx +37 -0
- package/src/icons/Search/SearchIcon.web.tsx +43 -0
- package/src/icons/Search/index.ts +1 -0
- package/src/icons/Search/searchPath.ts +5 -0
- package/src/icons/index.ts +3 -0
- package/src/icons/registry.ts +8 -2
- package/src/index.ts +21 -3
- package/src/theme/index.ts +7 -1
- package/src/theme/typography.ts +52 -2
- package/src/utils/mergeRefs.ts +20 -0
- package/src/web/styles/fonts.css +1 -0
- package/src/web/styles/typography.css +6 -2
package/dist/index.cjs
CHANGED
|
@@ -83,9 +83,32 @@ var inputTypography = {
|
|
|
83
83
|
fontFamily: fonts.sans,
|
|
84
84
|
fontSize: 12,
|
|
85
85
|
fontWeight: "500",
|
|
86
|
-
lineHeight:
|
|
86
|
+
lineHeight: 12,
|
|
87
|
+
letterSpacing: 0.36
|
|
88
|
+
},
|
|
89
|
+
field: {
|
|
90
|
+
fontFamily: fonts.sans,
|
|
91
|
+
fontSize: 14,
|
|
92
|
+
fontWeight: "400",
|
|
93
|
+
lineHeight: 19,
|
|
87
94
|
letterSpacing: 0
|
|
88
95
|
},
|
|
96
|
+
hint: {
|
|
97
|
+
fontFamily: fonts.sans,
|
|
98
|
+
fontSize: 12,
|
|
99
|
+
fontWeight: "400",
|
|
100
|
+
lineHeight: 12,
|
|
101
|
+
letterSpacing: 0.36
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
var selectTypography = {
|
|
105
|
+
label: {
|
|
106
|
+
fontFamily: fonts.sans,
|
|
107
|
+
fontSize: 12,
|
|
108
|
+
fontWeight: "500",
|
|
109
|
+
lineHeight: 12,
|
|
110
|
+
letterSpacing: 0.36
|
|
111
|
+
},
|
|
89
112
|
field: {
|
|
90
113
|
fontFamily: fonts.sans,
|
|
91
114
|
fontSize: 14,
|
|
@@ -97,8 +120,31 @@ var inputTypography = {
|
|
|
97
120
|
fontFamily: fonts.sans,
|
|
98
121
|
fontSize: 12,
|
|
99
122
|
fontWeight: "400",
|
|
100
|
-
lineHeight:
|
|
123
|
+
lineHeight: 12,
|
|
124
|
+
letterSpacing: 0.36
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
var textareaTypography = {
|
|
128
|
+
label: {
|
|
129
|
+
fontFamily: fonts.sans,
|
|
130
|
+
fontSize: 12,
|
|
131
|
+
fontWeight: "500",
|
|
132
|
+
lineHeight: 12,
|
|
133
|
+
letterSpacing: 0.36
|
|
134
|
+
},
|
|
135
|
+
field: {
|
|
136
|
+
fontFamily: fonts.sans,
|
|
137
|
+
fontSize: 14,
|
|
138
|
+
fontWeight: "400",
|
|
139
|
+
lineHeight: 19,
|
|
101
140
|
letterSpacing: 0
|
|
141
|
+
},
|
|
142
|
+
hint: {
|
|
143
|
+
fontFamily: fonts.sans,
|
|
144
|
+
fontSize: 12,
|
|
145
|
+
fontWeight: "400",
|
|
146
|
+
lineHeight: 12,
|
|
147
|
+
letterSpacing: 0.36
|
|
102
148
|
}
|
|
103
149
|
};
|
|
104
150
|
function ArrowRightIcon({
|
|
@@ -178,6 +224,21 @@ function CameraIcon({ size = 24, color = colors.primary, strokeWidth = 2 }) {
|
|
|
178
224
|
) });
|
|
179
225
|
}
|
|
180
226
|
|
|
227
|
+
// src/icons/Check/checkPath.ts
|
|
228
|
+
var CHECK_PATH = "M4.16669 10.8333L7.50002 14.1667L15.8334 5.83334";
|
|
229
|
+
function CheckIcon({ size = 20, color = colors.primary, strokeWidth = 2 }) {
|
|
230
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Svg__default.default, { width: size, height: size, viewBox: "0 0 20 20", fill: "none", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
231
|
+
Svg.Path,
|
|
232
|
+
{
|
|
233
|
+
d: CHECK_PATH,
|
|
234
|
+
stroke: color,
|
|
235
|
+
strokeWidth,
|
|
236
|
+
strokeLinecap: "round",
|
|
237
|
+
strokeLinejoin: "round"
|
|
238
|
+
}
|
|
239
|
+
) });
|
|
240
|
+
}
|
|
241
|
+
|
|
181
242
|
// src/icons/CheckBadge/checkBadgePath.ts
|
|
182
243
|
var CHECK_BADGE_PATH = "M12.5 8.33317L9.16663 11.6665L7.49996 9.99984M11.0384 2.88233L12.0558 3.74941C12.3122 3.96786 12.6305 4.09992 12.9662 4.12671L14.2987 4.23291C15.0822 4.29543 15.7045 4.91733 15.767 5.70077L15.8729 7.03353C15.8997 7.36925 16.0322 7.68799 16.2507 7.94433L17.1174 8.96152C17.6272 9.5597 17.6272 10.4396 17.1175 11.0378L16.2508 12.0551C16.0323 12.3115 15.9 12.6303 15.8732 12.9661L15.7666 14.2986C15.704 15.082 15.0827 15.7043 14.2993 15.7668L12.9663 15.8732C12.6305 15.9 12.312 16.0317 12.0556 16.2502L11.0384 17.1173C10.4402 17.627 9.55973 17.6271 8.96155 17.1174L7.9443 16.2502C7.68796 16.0318 7.36938 15.8998 7.03365 15.8731L5.70064 15.7668C4.9172 15.7043 4.29588 15.0822 4.23336 14.2987L4.12675 12.9661C4.09996 12.6304 3.96759 12.3118 3.74915 12.0555L2.88245 11.0378C2.37268 10.4397 2.37244 9.56002 2.88221 8.96184L3.74969 7.94418C3.96814 7.68784 4.09923 7.36926 4.12602 7.03353L4.23263 5.70093C4.29515 4.91749 4.91826 4.29535 5.70171 4.23283L7.03324 4.12663C7.36897 4.09984 7.68771 3.96788 7.94404 3.74943L8.96164 2.88233C9.55982 2.37256 10.4402 2.37256 11.0384 2.88233Z";
|
|
183
244
|
function CheckBadgeIcon({ size = 20, color = colors.primary, strokeWidth = 2 }) {
|
|
@@ -193,6 +254,25 @@ function CheckBadgeIcon({ size = 20, color = colors.primary, strokeWidth = 2 })
|
|
|
193
254
|
) });
|
|
194
255
|
}
|
|
195
256
|
|
|
257
|
+
// src/icons/ChevronDown/chevronDownPath.ts
|
|
258
|
+
var CHEVRON_DOWN_PATH = "M5 7.5L10 12.5L15 7.5";
|
|
259
|
+
function ChevronDownIcon({
|
|
260
|
+
size = 20,
|
|
261
|
+
color = colors.primary,
|
|
262
|
+
strokeWidth = 2
|
|
263
|
+
}) {
|
|
264
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Svg__default.default, { width: size, height: size, viewBox: "0 0 20 20", fill: "none", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
265
|
+
Svg.Path,
|
|
266
|
+
{
|
|
267
|
+
d: CHEVRON_DOWN_PATH,
|
|
268
|
+
stroke: color,
|
|
269
|
+
strokeWidth,
|
|
270
|
+
strokeLinecap: "round",
|
|
271
|
+
strokeLinejoin: "round"
|
|
272
|
+
}
|
|
273
|
+
) });
|
|
274
|
+
}
|
|
275
|
+
|
|
196
276
|
// src/icons/Clock/clockPath.ts
|
|
197
277
|
var CLOCK_PATH = "M12 7V12H17M12 21C7.02944 21 3 16.9706 3 12C3 7.02944 7.02944 3 12 3C16.9706 3 21 7.02944 21 12C21 16.9706 16.9706 21 12 21Z";
|
|
198
278
|
function ClockIcon({ size = 24, color = colors.primary, strokeWidth = 2 }) {
|
|
@@ -301,6 +381,38 @@ function PhoneIcon({ size = 20, color = colors.primary, strokeWidth = 2 }) {
|
|
|
301
381
|
) });
|
|
302
382
|
}
|
|
303
383
|
|
|
384
|
+
// src/icons/Search/searchPath.ts
|
|
385
|
+
var SEARCH_CIRCLE_PATH = "M9.16667 15.8333C12.8486 15.8333 15.8333 12.8486 15.8333 9.16667C15.8333 5.48477 12.8486 2.5 9.16667 2.5C5.48477 2.5 2.5 5.48477 2.5 9.16667C2.5 12.8486 5.48477 15.8333 9.16667 15.8333Z";
|
|
386
|
+
var SEARCH_HANDLE_PATH = "M17.5 17.5L13.875 13.875";
|
|
387
|
+
function SearchIcon({
|
|
388
|
+
size = 20,
|
|
389
|
+
color = colors.primary,
|
|
390
|
+
strokeWidth = 2
|
|
391
|
+
}) {
|
|
392
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Svg__default.default, { width: size, height: size, viewBox: "0 0 20 20", fill: "none", children: [
|
|
393
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
394
|
+
Svg.Path,
|
|
395
|
+
{
|
|
396
|
+
d: SEARCH_CIRCLE_PATH,
|
|
397
|
+
stroke: color,
|
|
398
|
+
strokeWidth,
|
|
399
|
+
strokeLinecap: "round",
|
|
400
|
+
strokeLinejoin: "round"
|
|
401
|
+
}
|
|
402
|
+
),
|
|
403
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
404
|
+
Svg.Path,
|
|
405
|
+
{
|
|
406
|
+
d: SEARCH_HANDLE_PATH,
|
|
407
|
+
stroke: color,
|
|
408
|
+
strokeWidth,
|
|
409
|
+
strokeLinecap: "round",
|
|
410
|
+
strokeLinejoin: "round"
|
|
411
|
+
}
|
|
412
|
+
)
|
|
413
|
+
] });
|
|
414
|
+
}
|
|
415
|
+
|
|
304
416
|
// src/icons/Show/showPath.ts
|
|
305
417
|
var SHOW_PATH = "M1.66669 10C1.66669 10 4.16669 4.16667 10 4.16667C15.8334 4.16667 18.3334 10 18.3334 10C18.3334 10 15.8334 15.8333 10 15.8333C4.16669 15.8333 1.66669 10 1.66669 10Z";
|
|
306
418
|
var SHOW_PUPIL_PATH = "M10 12.5C11.3807 12.5 12.5 11.3807 12.5 10C12.5 8.61929 11.3807 7.5 10 7.5C8.61929 7.5 7.5 8.61929 7.5 10C7.5 11.3807 8.61929 12.5 10 12.5Z";
|
|
@@ -351,7 +463,9 @@ var icons = {
|
|
|
351
463
|
bell: BellIcon,
|
|
352
464
|
building: BuildingIcon,
|
|
353
465
|
camera: CameraIcon,
|
|
466
|
+
check: CheckIcon,
|
|
354
467
|
checkBadge: CheckBadgeIcon,
|
|
468
|
+
chevronDown: ChevronDownIcon,
|
|
355
469
|
clock: ClockIcon,
|
|
356
470
|
facebook: FacebookIcon,
|
|
357
471
|
home: HomeIcon,
|
|
@@ -361,13 +475,14 @@ var icons = {
|
|
|
361
475
|
mail: MailIcon,
|
|
362
476
|
navigate: NavigateIcon,
|
|
363
477
|
phone: PhoneIcon,
|
|
478
|
+
search: SearchIcon,
|
|
364
479
|
show: ShowIcon,
|
|
365
480
|
user: UserIcon
|
|
366
481
|
};
|
|
367
482
|
var iconNames = Object.keys(icons);
|
|
368
483
|
var iconGroups = {
|
|
369
|
-
navigation: ["arrowRight", "home", "navigate"],
|
|
370
|
-
actions: ["show", "bell", "camera", "key", "checkBadge"],
|
|
484
|
+
navigation: ["arrowRight", "chevronDown", "home", "navigate"],
|
|
485
|
+
actions: ["show", "bell", "camera", "key", "check", "checkBadge", "search"],
|
|
371
486
|
objects: ["bag", "building", "clock", "user"],
|
|
372
487
|
communication: ["mail", "phone"],
|
|
373
488
|
social: ["facebook", "instagram", "linkedin"]
|
|
@@ -380,6 +495,18 @@ function Icon({ name, ...props }) {
|
|
|
380
495
|
const Component = icons[name];
|
|
381
496
|
return /* @__PURE__ */ jsxRuntime.jsx(Component, { ...props });
|
|
382
497
|
}
|
|
498
|
+
|
|
499
|
+
// src/utils/mergeRefs.ts
|
|
500
|
+
function mergeRefs(internalRef, forwardedRef) {
|
|
501
|
+
return (node) => {
|
|
502
|
+
internalRef.current = node;
|
|
503
|
+
if (typeof forwardedRef === "function") {
|
|
504
|
+
forwardedRef(node);
|
|
505
|
+
} else if (forwardedRef) {
|
|
506
|
+
forwardedRef.current = node;
|
|
507
|
+
}
|
|
508
|
+
};
|
|
509
|
+
}
|
|
383
510
|
function hasClassList(node) {
|
|
384
511
|
return typeof node === "object" && node !== null && "classList" in node && typeof node.classList?.add === "function";
|
|
385
512
|
}
|
|
@@ -460,107 +587,214 @@ var sizeConfig = {
|
|
|
460
587
|
iconSize: 12
|
|
461
588
|
}
|
|
462
589
|
};
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
590
|
+
var Button = react.forwardRef(
|
|
591
|
+
function Button2({
|
|
592
|
+
title,
|
|
593
|
+
children,
|
|
594
|
+
onPress,
|
|
595
|
+
disabled = false,
|
|
596
|
+
variant = "primary",
|
|
597
|
+
size = "lg",
|
|
598
|
+
showIcon = false,
|
|
599
|
+
icon,
|
|
600
|
+
style,
|
|
601
|
+
textStyle,
|
|
602
|
+
className,
|
|
603
|
+
textClassName,
|
|
604
|
+
accessibilityLabel,
|
|
605
|
+
...rest
|
|
606
|
+
}, forwardedRef) {
|
|
607
|
+
const containerRef = react.useRef(null);
|
|
608
|
+
const textRef = react.useRef(null);
|
|
609
|
+
const preset = variantConfig[variant];
|
|
610
|
+
const metrics = sizeConfig[size];
|
|
611
|
+
const label = typeof children !== "undefined" ? children : title;
|
|
612
|
+
const hasCustomChildren = typeof children !== "undefined";
|
|
613
|
+
const customIcon = icon != null && typeof icon !== "boolean" ? icon : void 0;
|
|
614
|
+
const hasIcon = showIcon || icon === true || customIcon != null;
|
|
615
|
+
const resolvedContainerClassName = className?.trim() || void 0;
|
|
616
|
+
const resolvedAccessibilityLabel = accessibilityLabel ?? (typeof label === "string" ? label : void 0);
|
|
617
|
+
const setContainerRef = react.useMemo(() => mergeRefs(containerRef, forwardedRef), [forwardedRef]);
|
|
618
|
+
useApplyWebClassName(containerRef, resolvedContainerClassName);
|
|
619
|
+
useApplyWebClassName(textRef, textClassName);
|
|
620
|
+
const iconNode = customIcon ?? /* @__PURE__ */ jsxRuntime.jsx(ArrowRightIcon, { size: metrics.iconSize, color: preset.iconColor });
|
|
621
|
+
const containerStyle = [
|
|
622
|
+
styles.base,
|
|
623
|
+
{
|
|
624
|
+
minHeight: metrics.minHeight,
|
|
625
|
+
borderRadius: metrics.borderRadius,
|
|
626
|
+
backgroundColor: preset.backgroundColor,
|
|
627
|
+
paddingTop: metrics.paddingVertical,
|
|
628
|
+
paddingBottom: metrics.paddingVertical,
|
|
629
|
+
paddingLeft: metrics.paddingLeft,
|
|
630
|
+
paddingRight: hasIcon ? metrics.paddingRightWithIcon : metrics.paddingRight,
|
|
631
|
+
gap: hasIcon ? metrics.gap : 0
|
|
632
|
+
},
|
|
633
|
+
disabled && styles.disabled,
|
|
634
|
+
style
|
|
635
|
+
];
|
|
636
|
+
const labelStyle = [
|
|
637
|
+
styles.label,
|
|
638
|
+
metrics.text,
|
|
639
|
+
{ color: preset.textColor },
|
|
640
|
+
reactNative.Platform.OS === "android" ? styles.labelAndroid : null,
|
|
641
|
+
!hasIcon && styles.labelCentered,
|
|
642
|
+
textStyle
|
|
643
|
+
];
|
|
644
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
645
|
+
reactNative.TouchableOpacity,
|
|
646
|
+
{
|
|
647
|
+
...rest,
|
|
648
|
+
ref: setContainerRef,
|
|
649
|
+
style: containerStyle,
|
|
650
|
+
onPress,
|
|
651
|
+
disabled,
|
|
652
|
+
activeOpacity: 0.7,
|
|
653
|
+
accessibilityRole: "button",
|
|
654
|
+
accessibilityLabel: resolvedAccessibilityLabel,
|
|
655
|
+
accessibilityState: { disabled },
|
|
656
|
+
children: [
|
|
657
|
+
hasCustomChildren ? children : /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { ref: textRef, style: labelStyle, children: label }),
|
|
658
|
+
hasIcon ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
659
|
+
reactNative.View,
|
|
660
|
+
{
|
|
661
|
+
style: [
|
|
662
|
+
styles.iconContainer,
|
|
663
|
+
{
|
|
664
|
+
width: metrics.iconContainerSize,
|
|
665
|
+
height: metrics.iconContainerSize,
|
|
666
|
+
borderRadius: metrics.iconContainerSize / 2,
|
|
667
|
+
backgroundColor: preset.iconBadgeBackgroundColor
|
|
668
|
+
}
|
|
669
|
+
],
|
|
670
|
+
children: iconNode
|
|
671
|
+
}
|
|
672
|
+
) : null
|
|
673
|
+
]
|
|
674
|
+
}
|
|
675
|
+
);
|
|
676
|
+
}
|
|
677
|
+
);
|
|
678
|
+
var styles = reactNative.StyleSheet.create({
|
|
679
|
+
base: {
|
|
680
|
+
flexDirection: "row",
|
|
681
|
+
alignItems: "center",
|
|
682
|
+
alignSelf: "flex-start",
|
|
683
|
+
borderWidth: 0
|
|
684
|
+
},
|
|
685
|
+
disabled: {
|
|
686
|
+
opacity: 0.6
|
|
687
|
+
},
|
|
688
|
+
label: {},
|
|
689
|
+
labelAndroid: {
|
|
690
|
+
includeFontPadding: false
|
|
691
|
+
},
|
|
692
|
+
labelCentered: {
|
|
693
|
+
textAlign: "center"
|
|
694
|
+
},
|
|
695
|
+
iconContainer: {
|
|
696
|
+
alignItems: "center",
|
|
697
|
+
justifyContent: "center",
|
|
698
|
+
flexShrink: 0
|
|
699
|
+
}
|
|
700
|
+
});
|
|
701
|
+
var BOX_SIZE = 20;
|
|
702
|
+
var BOX_RADIUS = 6;
|
|
703
|
+
var CHECK_SIZE = 12;
|
|
704
|
+
var CHECK_STROKE = 2.5;
|
|
705
|
+
var variantChrome = {
|
|
706
|
+
default: {
|
|
707
|
+
backgroundColor: colors.dark,
|
|
708
|
+
borderColor: colors.grey700
|
|
709
|
+
},
|
|
710
|
+
light: {
|
|
711
|
+
backgroundColor: colors.grey700,
|
|
712
|
+
borderColor: colors.grey500
|
|
713
|
+
}
|
|
714
|
+
};
|
|
715
|
+
var Checkbox = react.forwardRef(function Checkbox2({
|
|
716
|
+
value,
|
|
717
|
+
defaultValue = false,
|
|
718
|
+
onValueChange,
|
|
467
719
|
disabled = false,
|
|
468
|
-
variant = "
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
icon,
|
|
720
|
+
variant = "default",
|
|
721
|
+
label,
|
|
722
|
+
children,
|
|
472
723
|
style,
|
|
473
|
-
|
|
724
|
+
labelStyle,
|
|
474
725
|
className,
|
|
475
|
-
|
|
476
|
-
|
|
726
|
+
hitSlop = 8,
|
|
727
|
+
accessibilityLabel,
|
|
728
|
+
...rest
|
|
729
|
+
}, forwardedRef) {
|
|
477
730
|
const containerRef = react.useRef(null);
|
|
478
|
-
const
|
|
479
|
-
const
|
|
480
|
-
const
|
|
481
|
-
const
|
|
482
|
-
const
|
|
483
|
-
const
|
|
484
|
-
const
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
minHeight: metrics.minHeight,
|
|
493
|
-
borderRadius: metrics.borderRadius,
|
|
494
|
-
backgroundColor: preset.backgroundColor,
|
|
495
|
-
paddingTop: metrics.paddingVertical,
|
|
496
|
-
paddingBottom: metrics.paddingVertical,
|
|
497
|
-
paddingLeft: metrics.paddingLeft,
|
|
498
|
-
paddingRight: hasIcon ? metrics.paddingRightWithIcon : metrics.paddingRight,
|
|
499
|
-
gap: hasIcon ? metrics.gap : 0
|
|
500
|
-
},
|
|
501
|
-
disabled && styles.disabled,
|
|
502
|
-
style
|
|
503
|
-
];
|
|
504
|
-
const labelStyle = [
|
|
505
|
-
styles.label,
|
|
506
|
-
metrics.text,
|
|
507
|
-
{ color: preset.textColor },
|
|
508
|
-
reactNative.Platform.OS === "android" ? styles.labelAndroid : null,
|
|
509
|
-
!hasIcon && styles.labelCentered,
|
|
510
|
-
textStyle
|
|
511
|
-
];
|
|
731
|
+
const isControlled = typeof value === "boolean";
|
|
732
|
+
const [uncontrolledValue, setUncontrolledValue] = react.useState(defaultValue);
|
|
733
|
+
const isActive = isControlled ? value : uncontrolledValue;
|
|
734
|
+
const chrome = variantChrome[variant];
|
|
735
|
+
const labelContent = children ?? label;
|
|
736
|
+
const resolvedAccessibilityLabel = accessibilityLabel ?? (typeof labelContent === "string" ? labelContent : void 0);
|
|
737
|
+
const setContainerRef = react.useMemo(() => mergeRefs(containerRef, forwardedRef), [forwardedRef]);
|
|
738
|
+
useApplyWebClassName(containerRef, className);
|
|
739
|
+
const handlePress = () => {
|
|
740
|
+
if (disabled) return;
|
|
741
|
+
const next = !isActive;
|
|
742
|
+
if (!isControlled) setUncontrolledValue(next);
|
|
743
|
+
onValueChange?.(next);
|
|
744
|
+
};
|
|
512
745
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
513
|
-
reactNative.
|
|
746
|
+
reactNative.Pressable,
|
|
514
747
|
{
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
onPress,
|
|
748
|
+
...rest,
|
|
749
|
+
ref: setContainerRef,
|
|
750
|
+
onPress: handlePress,
|
|
518
751
|
disabled,
|
|
519
|
-
|
|
520
|
-
accessibilityRole: "
|
|
521
|
-
|
|
752
|
+
hitSlop,
|
|
753
|
+
accessibilityRole: "checkbox",
|
|
754
|
+
accessibilityLabel: resolvedAccessibilityLabel,
|
|
755
|
+
accessibilityState: { checked: isActive, disabled },
|
|
756
|
+
style: [styles2.root, disabled && styles2.disabled, style],
|
|
522
757
|
children: [
|
|
523
|
-
|
|
524
|
-
hasIcon ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
758
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
525
759
|
reactNative.View,
|
|
526
760
|
{
|
|
527
761
|
style: [
|
|
528
|
-
|
|
762
|
+
styles2.box,
|
|
529
763
|
{
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
borderRadius: metrics.iconContainerSize / 2,
|
|
533
|
-
backgroundColor: preset.iconBadgeBackgroundColor
|
|
764
|
+
backgroundColor: chrome.backgroundColor,
|
|
765
|
+
borderColor: chrome.borderColor
|
|
534
766
|
}
|
|
535
767
|
],
|
|
536
|
-
children:
|
|
768
|
+
children: isActive ? /* @__PURE__ */ jsxRuntime.jsx(CheckIcon, { size: CHECK_SIZE, color: colors.primary, strokeWidth: CHECK_STROKE }) : null
|
|
537
769
|
}
|
|
538
|
-
)
|
|
770
|
+
),
|
|
771
|
+
labelContent != null && labelContent !== false ? typeof labelContent === "string" || typeof labelContent === "number" ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles2.label, labelStyle], children: labelContent }) : labelContent : null
|
|
539
772
|
]
|
|
540
773
|
}
|
|
541
774
|
);
|
|
542
|
-
}
|
|
543
|
-
var
|
|
544
|
-
|
|
775
|
+
});
|
|
776
|
+
var styles2 = reactNative.StyleSheet.create({
|
|
777
|
+
root: {
|
|
545
778
|
flexDirection: "row",
|
|
546
779
|
alignItems: "center",
|
|
547
780
|
alignSelf: "flex-start",
|
|
548
|
-
|
|
781
|
+
gap: 10
|
|
549
782
|
},
|
|
550
783
|
disabled: {
|
|
551
|
-
opacity: 0.
|
|
784
|
+
opacity: 0.5
|
|
552
785
|
},
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
textAlign: "center"
|
|
559
|
-
},
|
|
560
|
-
iconContainer: {
|
|
786
|
+
box: {
|
|
787
|
+
width: BOX_SIZE,
|
|
788
|
+
height: BOX_SIZE,
|
|
789
|
+
borderRadius: BOX_RADIUS,
|
|
790
|
+
borderWidth: 1,
|
|
561
791
|
alignItems: "center",
|
|
562
792
|
justifyContent: "center",
|
|
563
793
|
flexShrink: 0
|
|
794
|
+
},
|
|
795
|
+
label: {
|
|
796
|
+
...inputTypography.field,
|
|
797
|
+
color: colors.white
|
|
564
798
|
}
|
|
565
799
|
});
|
|
566
800
|
var DEFAULT_WIDTH = 308;
|
|
@@ -584,14 +818,12 @@ var sizeConfig2 = {
|
|
|
584
818
|
text: inputTypography.hint
|
|
585
819
|
}
|
|
586
820
|
};
|
|
587
|
-
function
|
|
588
|
-
state,
|
|
821
|
+
function resolveVisualState({
|
|
589
822
|
disabled,
|
|
590
823
|
error,
|
|
591
824
|
focused,
|
|
592
825
|
hasValue
|
|
593
826
|
}) {
|
|
594
|
-
if (state) return state;
|
|
595
827
|
if (disabled) return "disabled";
|
|
596
828
|
if (error) return "error";
|
|
597
829
|
if (focused) return "active";
|
|
@@ -643,13 +875,12 @@ function chromeFor(state) {
|
|
|
643
875
|
return base;
|
|
644
876
|
}
|
|
645
877
|
}
|
|
646
|
-
|
|
878
|
+
var Input = react.forwardRef(function Input2({
|
|
647
879
|
label = "Label",
|
|
648
880
|
showLabel = true,
|
|
649
881
|
hint = "Hint",
|
|
650
882
|
showHint = true,
|
|
651
883
|
placeholder = "placeholder",
|
|
652
|
-
state: stateProp,
|
|
653
884
|
size = "lg",
|
|
654
885
|
disabled = false,
|
|
655
886
|
error = false,
|
|
@@ -663,43 +894,40 @@ function Input({
|
|
|
663
894
|
rightIcon,
|
|
664
895
|
showRightIcon = false,
|
|
665
896
|
onRightIconPress,
|
|
897
|
+
rightIconAccessibilityLabel,
|
|
666
898
|
style,
|
|
667
899
|
fieldStyle,
|
|
668
900
|
inputStyle,
|
|
669
901
|
className,
|
|
670
902
|
inputClassName,
|
|
903
|
+
accessibilityLabel,
|
|
671
904
|
...textInputProps
|
|
672
|
-
}) {
|
|
905
|
+
}, forwardedRef) {
|
|
673
906
|
const rootRef = react.useRef(null);
|
|
674
907
|
const inputRef = react.useRef(null);
|
|
908
|
+
const setInputRef = react.useMemo(() => mergeRefs(inputRef, forwardedRef), [forwardedRef]);
|
|
675
909
|
const [focused, setFocused] = react.useState(false);
|
|
676
910
|
const [uncontrolledValue, setUncontrolledValue] = react.useState(defaultValue ?? "");
|
|
677
911
|
const metrics = sizeConfig2[size];
|
|
678
912
|
const isControlled = typeof value === "string";
|
|
679
913
|
const currentValue = isControlled ? value : uncontrolledValue;
|
|
680
914
|
const hasValue = currentValue.length > 0;
|
|
681
|
-
const
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
error,
|
|
685
|
-
focused,
|
|
686
|
-
hasValue
|
|
687
|
-
});
|
|
688
|
-
const chrome = chromeFor(resolvedState);
|
|
689
|
-
const isDisabled = resolvedState === "disabled" || disabled;
|
|
915
|
+
const visualState = resolveVisualState({ disabled, error, focused, hasValue });
|
|
916
|
+
const chrome = chromeFor(visualState);
|
|
917
|
+
const resolvedAccessibilityLabel = accessibilityLabel ?? (showLabel ? void 0 : label);
|
|
690
918
|
const hasLeftIcon = showLeftIcon || leftIcon != null;
|
|
691
919
|
const hasRightIcon = showRightIcon || rightIcon != null;
|
|
692
920
|
const leftIconNode = leftIcon ?? /* @__PURE__ */ jsxRuntime.jsx(UserIcon, { size: metrics.iconSize, color: chrome.leftIconColor });
|
|
693
921
|
const rightIconNode = rightIcon ?? /* @__PURE__ */ jsxRuntime.jsx(ShowIcon, { size: metrics.iconSize, color: chrome.rightIconColor });
|
|
694
922
|
useApplyWebClassName(rootRef, className);
|
|
695
923
|
useApplyWebClassName(inputRef, inputClassName);
|
|
696
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { ref: rootRef, style: [
|
|
697
|
-
showLabel && label ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [
|
|
924
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { ref: rootRef, style: [styles3.root, disabled && styles3.disabled, style], children: [
|
|
925
|
+
showLabel && label ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles3.label, { color: chrome.labelColor }], children: label }) : null,
|
|
698
926
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
699
927
|
reactNative.View,
|
|
700
928
|
{
|
|
701
929
|
style: [
|
|
702
|
-
|
|
930
|
+
styles3.field,
|
|
703
931
|
{
|
|
704
932
|
height: metrics.height,
|
|
705
933
|
borderRadius: metrics.borderRadius,
|
|
@@ -714,15 +942,15 @@ function Input({
|
|
|
714
942
|
fieldStyle
|
|
715
943
|
],
|
|
716
944
|
children: [
|
|
717
|
-
hasLeftIcon ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [
|
|
945
|
+
hasLeftIcon ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [styles3.iconSlot, { width: metrics.iconSize, height: metrics.iconSize }], children: leftIconNode }) : null,
|
|
718
946
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
719
947
|
reactNative.TextInput,
|
|
720
948
|
{
|
|
721
|
-
ref:
|
|
949
|
+
ref: setInputRef,
|
|
722
950
|
...textInputProps,
|
|
723
951
|
value: isControlled ? value : void 0,
|
|
724
952
|
defaultValue: isControlled ? void 0 : defaultValue,
|
|
725
|
-
editable: !
|
|
953
|
+
editable: !disabled,
|
|
726
954
|
placeholder,
|
|
727
955
|
placeholderTextColor: chrome.placeholderColor,
|
|
728
956
|
onChangeText: (text) => {
|
|
@@ -738,34 +966,36 @@ function Input({
|
|
|
738
966
|
onBlur?.(event);
|
|
739
967
|
},
|
|
740
968
|
style: [
|
|
741
|
-
|
|
969
|
+
styles3.input,
|
|
742
970
|
metrics.text,
|
|
743
971
|
{ color: chrome.textColor },
|
|
744
|
-
reactNative.Platform.OS === "web" ?
|
|
745
|
-
reactNative.Platform.OS === "android" ?
|
|
972
|
+
reactNative.Platform.OS === "web" ? styles3.inputWeb : null,
|
|
973
|
+
reactNative.Platform.OS === "android" ? styles3.inputAndroid : null,
|
|
746
974
|
inputStyle
|
|
747
975
|
],
|
|
748
|
-
|
|
976
|
+
accessibilityLabel: resolvedAccessibilityLabel,
|
|
977
|
+
accessibilityState: { disabled }
|
|
749
978
|
}
|
|
750
979
|
),
|
|
751
980
|
hasRightIcon ? onRightIconPress ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
752
981
|
reactNative.TouchableOpacity,
|
|
753
982
|
{
|
|
754
983
|
onPress: onRightIconPress,
|
|
755
|
-
disabled
|
|
756
|
-
style: [
|
|
984
|
+
disabled,
|
|
985
|
+
style: [styles3.iconSlot, { width: metrics.iconSize, height: metrics.iconSize }],
|
|
757
986
|
accessibilityRole: "button",
|
|
987
|
+
accessibilityLabel: rightIconAccessibilityLabel,
|
|
758
988
|
hitSlop: 8,
|
|
759
989
|
children: rightIconNode
|
|
760
990
|
}
|
|
761
|
-
) : /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [
|
|
991
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [styles3.iconSlot, { width: metrics.iconSize, height: metrics.iconSize }], children: rightIconNode }) : null
|
|
762
992
|
]
|
|
763
993
|
}
|
|
764
994
|
),
|
|
765
|
-
showHint && hint ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [
|
|
995
|
+
showHint && hint ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles3.hint, { color: chrome.hintColor }], children: hint }) : null
|
|
766
996
|
] });
|
|
767
|
-
}
|
|
768
|
-
var
|
|
997
|
+
});
|
|
998
|
+
var styles3 = reactNative.StyleSheet.create({
|
|
769
999
|
root: {
|
|
770
1000
|
width: DEFAULT_WIDTH,
|
|
771
1001
|
gap: 8,
|
|
@@ -802,6 +1032,924 @@ var styles2 = reactNative.StyleSheet.create({
|
|
|
802
1032
|
...inputTypography.hint
|
|
803
1033
|
}
|
|
804
1034
|
});
|
|
1035
|
+
var DEFAULT_WIDTH2 = 308;
|
|
1036
|
+
var TRIGGER_HEIGHT = 44;
|
|
1037
|
+
var TRIGGER_RADIUS = 60;
|
|
1038
|
+
var MENU_RADIUS = 24;
|
|
1039
|
+
var MENU_MAX_LIST_HEIGHT = 248;
|
|
1040
|
+
var ITEM_RADIUS = 12;
|
|
1041
|
+
var ICON_SIZE = 20;
|
|
1042
|
+
var CHIP_GAP = 6;
|
|
1043
|
+
var FALLBACK_ELLIPSIS_WIDTH = 20;
|
|
1044
|
+
function itemBackground(state) {
|
|
1045
|
+
switch (state) {
|
|
1046
|
+
case "hover":
|
|
1047
|
+
return colors.grey600;
|
|
1048
|
+
case "selected":
|
|
1049
|
+
return colors.primaryMuted;
|
|
1050
|
+
default:
|
|
1051
|
+
return "transparent";
|
|
1052
|
+
}
|
|
1053
|
+
}
|
|
1054
|
+
function toArray(value) {
|
|
1055
|
+
if (value == null || value === "") return [];
|
|
1056
|
+
return Array.isArray(value) ? value : [value];
|
|
1057
|
+
}
|
|
1058
|
+
function resolveVisibleOptions(options, containerWidth, chipWidths, ellipsisWidth) {
|
|
1059
|
+
if (options.length === 0) return { visible: [], hasOverflow: false };
|
|
1060
|
+
if (containerWidth <= 0) return { visible: options.slice(0, 1), hasOverflow: options.length > 1 };
|
|
1061
|
+
const visible = [];
|
|
1062
|
+
let used = 0;
|
|
1063
|
+
for (let index = 0; index < options.length; index += 1) {
|
|
1064
|
+
const option = options[index];
|
|
1065
|
+
const chipWidth = chipWidths[option.value];
|
|
1066
|
+
if (chipWidth == null) {
|
|
1067
|
+
if (visible.length === 0) visible.push(option);
|
|
1068
|
+
break;
|
|
1069
|
+
}
|
|
1070
|
+
const remainingAfter = options.length - index - 1;
|
|
1071
|
+
const gap = visible.length > 0 ? CHIP_GAP : 0;
|
|
1072
|
+
const reserve = remainingAfter > 0 ? CHIP_GAP + ellipsisWidth : 0;
|
|
1073
|
+
const nextUsed = used + gap + chipWidth;
|
|
1074
|
+
if (visible.length > 0 && nextUsed + reserve > containerWidth) {
|
|
1075
|
+
return { visible, hasOverflow: true };
|
|
1076
|
+
}
|
|
1077
|
+
visible.push(option);
|
|
1078
|
+
used = nextUsed;
|
|
1079
|
+
}
|
|
1080
|
+
return { visible, hasOverflow: visible.length < options.length };
|
|
1081
|
+
}
|
|
1082
|
+
function MultiValueChips({ options, disabled, onRemove }) {
|
|
1083
|
+
const [containerWidth, setContainerWidth] = react.useState(0);
|
|
1084
|
+
const [chipWidths, setChipWidths] = react.useState({});
|
|
1085
|
+
const [ellipsisWidth, setEllipsisWidth] = react.useState(FALLBACK_ELLIPSIS_WIDTH);
|
|
1086
|
+
react.useEffect(() => {
|
|
1087
|
+
setChipWidths((current) => {
|
|
1088
|
+
const validValues = new Set(options.map((option) => option.value));
|
|
1089
|
+
const keys = Object.keys(current);
|
|
1090
|
+
if (keys.every((key) => validValues.has(key))) return current;
|
|
1091
|
+
const next = {};
|
|
1092
|
+
for (const key of keys) {
|
|
1093
|
+
if (validValues.has(key)) next[key] = current[key];
|
|
1094
|
+
}
|
|
1095
|
+
return next;
|
|
1096
|
+
});
|
|
1097
|
+
}, [options]);
|
|
1098
|
+
const { visible, hasOverflow } = react.useMemo(
|
|
1099
|
+
() => resolveVisibleOptions(options, containerWidth, chipWidths, ellipsisWidth),
|
|
1100
|
+
[chipWidths, containerWidth, ellipsisWidth, options]
|
|
1101
|
+
);
|
|
1102
|
+
const handleContainerLayout = (event) => {
|
|
1103
|
+
const next = Math.floor(event.nativeEvent.layout.width);
|
|
1104
|
+
setContainerWidth((current) => current === next ? current : next);
|
|
1105
|
+
};
|
|
1106
|
+
const handleChipLayout = (value, event) => {
|
|
1107
|
+
const next = Math.ceil(event.nativeEvent.layout.width);
|
|
1108
|
+
setChipWidths((current) => current[value] === next ? current : { ...current, [value]: next });
|
|
1109
|
+
};
|
|
1110
|
+
const handleEllipsisLayout = (event) => {
|
|
1111
|
+
const next = Math.ceil(event.nativeEvent.layout.width);
|
|
1112
|
+
setEllipsisWidth((current) => current === next ? current : next);
|
|
1113
|
+
};
|
|
1114
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles4.multiValueRoot, children: [
|
|
1115
|
+
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { pointerEvents: "none", style: styles4.measureRow, children: [
|
|
1116
|
+
options.map((option) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1117
|
+
reactNative.View,
|
|
1118
|
+
{
|
|
1119
|
+
style: styles4.chip,
|
|
1120
|
+
onLayout: (event) => handleChipLayout(option.value, event),
|
|
1121
|
+
children: [
|
|
1122
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles4.chipLabel, numberOfLines: 1, children: option.label }),
|
|
1123
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles4.chipRemove, children: "\xD7" })
|
|
1124
|
+
]
|
|
1125
|
+
},
|
|
1126
|
+
`measure-${option.value}`
|
|
1127
|
+
)),
|
|
1128
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles4.ellipsis, onLayout: handleEllipsisLayout, children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles4.ellipsisText, children: "..." }) })
|
|
1129
|
+
] }),
|
|
1130
|
+
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles4.chipsRow, onLayout: handleContainerLayout, children: [
|
|
1131
|
+
visible.map((option) => /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles4.chip, children: [
|
|
1132
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles4.chipLabel, numberOfLines: 1, children: option.label }),
|
|
1133
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1134
|
+
reactNative.Pressable,
|
|
1135
|
+
{
|
|
1136
|
+
onPress: (event) => {
|
|
1137
|
+
event?.stopPropagation?.();
|
|
1138
|
+
onRemove(option.value);
|
|
1139
|
+
},
|
|
1140
|
+
disabled,
|
|
1141
|
+
hitSlop: 6,
|
|
1142
|
+
accessibilityRole: "button",
|
|
1143
|
+
accessibilityLabel: `Remove ${option.label}`,
|
|
1144
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles4.chipRemove, children: "\xD7" })
|
|
1145
|
+
}
|
|
1146
|
+
)
|
|
1147
|
+
] }, option.value)),
|
|
1148
|
+
hasOverflow ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles4.ellipsis, children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles4.ellipsisText, children: "..." }) }) : null
|
|
1149
|
+
] })
|
|
1150
|
+
] });
|
|
1151
|
+
}
|
|
1152
|
+
var Select = react.forwardRef(
|
|
1153
|
+
function Select2(props, forwardedRef) {
|
|
1154
|
+
const {
|
|
1155
|
+
label = "Label",
|
|
1156
|
+
showLabel = true,
|
|
1157
|
+
hint,
|
|
1158
|
+
showHint = false,
|
|
1159
|
+
placeholder = "placeholder",
|
|
1160
|
+
options,
|
|
1161
|
+
open: openProp,
|
|
1162
|
+
defaultOpen = false,
|
|
1163
|
+
onOpenChange,
|
|
1164
|
+
disabled = false,
|
|
1165
|
+
error = false,
|
|
1166
|
+
leftIcon,
|
|
1167
|
+
showLeftIcon = true,
|
|
1168
|
+
showSearch = true,
|
|
1169
|
+
searchPlaceholder = "Search...",
|
|
1170
|
+
onSearchChange,
|
|
1171
|
+
loading = false,
|
|
1172
|
+
emptyText = "No results",
|
|
1173
|
+
style,
|
|
1174
|
+
className,
|
|
1175
|
+
accessibilityLabel,
|
|
1176
|
+
// Pulled out only to keep them off `rest` (which is spread onto the root View);
|
|
1177
|
+
// the real values are read from `props` directly below to preserve discriminated typing.
|
|
1178
|
+
multiple: _multiple,
|
|
1179
|
+
value: _value,
|
|
1180
|
+
defaultValue: _defaultValue,
|
|
1181
|
+
onValueChange: _onValueChange,
|
|
1182
|
+
...rest
|
|
1183
|
+
} = props;
|
|
1184
|
+
const multiple = props.multiple === true;
|
|
1185
|
+
const valueProp = props.value;
|
|
1186
|
+
const rootRef = react.useRef(null);
|
|
1187
|
+
const triggerRef = react.useRef(null);
|
|
1188
|
+
const searchInputRef = react.useRef(null);
|
|
1189
|
+
const setRootRef = react.useMemo(() => mergeRefs(rootRef, forwardedRef), [forwardedRef]);
|
|
1190
|
+
const isOpenControlled = typeof openProp === "boolean";
|
|
1191
|
+
const isValueControlled = valueProp !== void 0;
|
|
1192
|
+
const [uncontrolledSingle, setUncontrolledSingle] = react.useState(
|
|
1193
|
+
!multiple ? props.defaultValue ?? "" : ""
|
|
1194
|
+
);
|
|
1195
|
+
const [uncontrolledMultiple, setUncontrolledMultiple] = react.useState(
|
|
1196
|
+
multiple ? props.defaultValue ?? [] : []
|
|
1197
|
+
);
|
|
1198
|
+
const [uncontrolledOpen, setUncontrolledOpen] = react.useState(defaultOpen);
|
|
1199
|
+
const [searchQuery, setSearchQuery] = react.useState("");
|
|
1200
|
+
const [hoveredValue, setHoveredValue] = react.useState(null);
|
|
1201
|
+
const selectedValues = react.useMemo(() => {
|
|
1202
|
+
const current = isValueControlled ? valueProp : multiple ? uncontrolledMultiple : uncontrolledSingle;
|
|
1203
|
+
return toArray(current);
|
|
1204
|
+
}, [isValueControlled, multiple, valueProp, uncontrolledMultiple, uncontrolledSingle]);
|
|
1205
|
+
const isOpen = isOpenControlled ? openProp : uncontrolledOpen;
|
|
1206
|
+
const selectedOptions = react.useMemo(
|
|
1207
|
+
() => selectedValues.map((value) => options.find((option) => option.value === value)).filter((option) => option != null),
|
|
1208
|
+
[options, selectedValues]
|
|
1209
|
+
);
|
|
1210
|
+
const hasValue = selectedOptions.length > 0;
|
|
1211
|
+
const isExternalSearch = onSearchChange != null;
|
|
1212
|
+
const filteredOptions = react.useMemo(() => {
|
|
1213
|
+
if (isExternalSearch) return options;
|
|
1214
|
+
const query = searchQuery.trim().toLowerCase();
|
|
1215
|
+
if (!query) return options;
|
|
1216
|
+
return options.filter((option) => option.label.toLowerCase().includes(query));
|
|
1217
|
+
}, [isExternalSearch, options, searchQuery]);
|
|
1218
|
+
useApplyWebClassName(rootRef, className);
|
|
1219
|
+
const setOpen = react.useCallback(
|
|
1220
|
+
(next) => {
|
|
1221
|
+
if (!isOpenControlled) setUncontrolledOpen(next);
|
|
1222
|
+
onOpenChange?.(next);
|
|
1223
|
+
if (next) {
|
|
1224
|
+
setHoveredValue(selectedValues[0] ?? null);
|
|
1225
|
+
} else {
|
|
1226
|
+
setSearchQuery("");
|
|
1227
|
+
setHoveredValue(null);
|
|
1228
|
+
onSearchChange?.("");
|
|
1229
|
+
}
|
|
1230
|
+
},
|
|
1231
|
+
[isOpenControlled, onOpenChange, onSearchChange, selectedValues]
|
|
1232
|
+
);
|
|
1233
|
+
const handleSearchChange = (text) => {
|
|
1234
|
+
setSearchQuery(text);
|
|
1235
|
+
onSearchChange?.(text);
|
|
1236
|
+
};
|
|
1237
|
+
react.useEffect(() => {
|
|
1238
|
+
if (reactNative.Platform.OS !== "web" || !isOpen) return;
|
|
1239
|
+
const handlePointerDown = (event) => {
|
|
1240
|
+
const root = rootRef.current;
|
|
1241
|
+
const target = event.target;
|
|
1242
|
+
if (root?.contains && target instanceof Node && !root.contains(target)) {
|
|
1243
|
+
setOpen(false);
|
|
1244
|
+
}
|
|
1245
|
+
};
|
|
1246
|
+
document.addEventListener("mousedown", handlePointerDown);
|
|
1247
|
+
document.addEventListener("touchstart", handlePointerDown);
|
|
1248
|
+
return () => {
|
|
1249
|
+
document.removeEventListener("mousedown", handlePointerDown);
|
|
1250
|
+
document.removeEventListener("touchstart", handlePointerDown);
|
|
1251
|
+
};
|
|
1252
|
+
}, [isOpen, setOpen]);
|
|
1253
|
+
const commitValues = react.useCallback(
|
|
1254
|
+
(nextValues) => {
|
|
1255
|
+
if (multiple) {
|
|
1256
|
+
if (!isValueControlled) setUncontrolledMultiple(nextValues);
|
|
1257
|
+
props.onValueChange?.(nextValues);
|
|
1258
|
+
return;
|
|
1259
|
+
}
|
|
1260
|
+
const nextValue = nextValues[0] ?? "";
|
|
1261
|
+
if (!isValueControlled) setUncontrolledSingle(nextValue);
|
|
1262
|
+
props.onValueChange?.(nextValue);
|
|
1263
|
+
},
|
|
1264
|
+
[isValueControlled, multiple, props]
|
|
1265
|
+
);
|
|
1266
|
+
const handleTriggerPress = () => {
|
|
1267
|
+
if (disabled) return;
|
|
1268
|
+
setOpen(!isOpen);
|
|
1269
|
+
};
|
|
1270
|
+
const handleSelect = react.useCallback(
|
|
1271
|
+
(optionValue) => {
|
|
1272
|
+
if (disabled) return;
|
|
1273
|
+
if (multiple) {
|
|
1274
|
+
const exists = selectedValues.includes(optionValue);
|
|
1275
|
+
const nextValues = exists ? selectedValues.filter((value) => value !== optionValue) : [...selectedValues, optionValue];
|
|
1276
|
+
commitValues(nextValues);
|
|
1277
|
+
return;
|
|
1278
|
+
}
|
|
1279
|
+
commitValues([optionValue]);
|
|
1280
|
+
setOpen(false);
|
|
1281
|
+
},
|
|
1282
|
+
[commitValues, disabled, multiple, selectedValues, setOpen]
|
|
1283
|
+
);
|
|
1284
|
+
const handleRemoveChip = (optionValue) => {
|
|
1285
|
+
if (disabled || !multiple) return;
|
|
1286
|
+
commitValues(selectedValues.filter((value) => value !== optionValue));
|
|
1287
|
+
};
|
|
1288
|
+
const focusTrigger = react.useCallback(() => {
|
|
1289
|
+
const node = triggerRef.current;
|
|
1290
|
+
node?.focus?.();
|
|
1291
|
+
}, []);
|
|
1292
|
+
const closeAndFocusTrigger = react.useCallback(() => {
|
|
1293
|
+
setOpen(false);
|
|
1294
|
+
focusTrigger();
|
|
1295
|
+
}, [focusTrigger, setOpen]);
|
|
1296
|
+
react.useEffect(() => {
|
|
1297
|
+
if (reactNative.Platform.OS !== "web") return;
|
|
1298
|
+
const isTriggerFocused = () => document.activeElement === triggerRef.current;
|
|
1299
|
+
const isSearchFocused = () => document.activeElement === searchInputRef.current;
|
|
1300
|
+
const handleKeyDown = (event) => {
|
|
1301
|
+
if (!isOpen) {
|
|
1302
|
+
if (!isTriggerFocused() || disabled) return;
|
|
1303
|
+
if (event.key === "ArrowDown" || event.key === "ArrowUp" || event.key === "Enter") {
|
|
1304
|
+
event.preventDefault();
|
|
1305
|
+
setOpen(true);
|
|
1306
|
+
}
|
|
1307
|
+
return;
|
|
1308
|
+
}
|
|
1309
|
+
if (event.key === "Escape") {
|
|
1310
|
+
event.preventDefault();
|
|
1311
|
+
closeAndFocusTrigger();
|
|
1312
|
+
return;
|
|
1313
|
+
}
|
|
1314
|
+
if (event.key === "ArrowDown" || event.key === "ArrowUp") {
|
|
1315
|
+
event.preventDefault();
|
|
1316
|
+
setHoveredValue((current) => {
|
|
1317
|
+
if (filteredOptions.length === 0) return current;
|
|
1318
|
+
const currentIndex = filteredOptions.findIndex((option) => option.value === current);
|
|
1319
|
+
const delta = event.key === "ArrowDown" ? 1 : -1;
|
|
1320
|
+
const nextIndex = currentIndex === -1 ? delta === 1 ? 0 : filteredOptions.length - 1 : Math.min(Math.max(currentIndex + delta, 0), filteredOptions.length - 1);
|
|
1321
|
+
return filteredOptions[nextIndex]?.value ?? current;
|
|
1322
|
+
});
|
|
1323
|
+
return;
|
|
1324
|
+
}
|
|
1325
|
+
if (isSearchFocused() && (event.key === "Home" || event.key === "End" || event.key === " ")) {
|
|
1326
|
+
return;
|
|
1327
|
+
}
|
|
1328
|
+
if (event.key === "Home" || event.key === "End") {
|
|
1329
|
+
if (filteredOptions.length === 0) return;
|
|
1330
|
+
event.preventDefault();
|
|
1331
|
+
setHoveredValue(
|
|
1332
|
+
event.key === "Home" ? filteredOptions[0].value : filteredOptions[filteredOptions.length - 1].value
|
|
1333
|
+
);
|
|
1334
|
+
return;
|
|
1335
|
+
}
|
|
1336
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
1337
|
+
if (hoveredValue == null) return;
|
|
1338
|
+
event.preventDefault();
|
|
1339
|
+
handleSelect(hoveredValue);
|
|
1340
|
+
if (!multiple) focusTrigger();
|
|
1341
|
+
}
|
|
1342
|
+
};
|
|
1343
|
+
document.addEventListener("keydown", handleKeyDown);
|
|
1344
|
+
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
1345
|
+
}, [
|
|
1346
|
+
isOpen,
|
|
1347
|
+
disabled,
|
|
1348
|
+
filteredOptions,
|
|
1349
|
+
hoveredValue,
|
|
1350
|
+
multiple,
|
|
1351
|
+
closeAndFocusTrigger,
|
|
1352
|
+
focusTrigger,
|
|
1353
|
+
handleSelect,
|
|
1354
|
+
setOpen
|
|
1355
|
+
]);
|
|
1356
|
+
const leftIconNode = leftIcon ?? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1357
|
+
UserIcon,
|
|
1358
|
+
{
|
|
1359
|
+
size: ICON_SIZE,
|
|
1360
|
+
color: error ? colors.red : isOpen ? colors.primary : colors.grey100
|
|
1361
|
+
}
|
|
1362
|
+
);
|
|
1363
|
+
const hasLeftIcon = showLeftIcon || leftIcon != null;
|
|
1364
|
+
const triggerBorderColor = error ? colors.redMuted : isOpen ? colors.primaryMuted : colors.grey700;
|
|
1365
|
+
const triggerTextColor = hasValue ? error ? colors.red : colors.white : error ? colors.red : colors.grey100;
|
|
1366
|
+
const labelColor = error ? colors.red : colors.white;
|
|
1367
|
+
const hintColor = error ? colors.red : colors.grey100;
|
|
1368
|
+
const singleLabel = selectedOptions[0]?.label ?? placeholder;
|
|
1369
|
+
const resolvedAccessibilityLabel = accessibilityLabel ?? (typeof label === "string" ? label : void 0);
|
|
1370
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1371
|
+
reactNative.View,
|
|
1372
|
+
{
|
|
1373
|
+
...rest,
|
|
1374
|
+
ref: setRootRef,
|
|
1375
|
+
style: [styles4.root, isOpen && styles4.rootOpen, disabled && styles4.disabled, style],
|
|
1376
|
+
accessibilityState: { disabled, expanded: isOpen },
|
|
1377
|
+
children: [
|
|
1378
|
+
showLabel && label ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles4.label, { color: labelColor }], children: label }) : null,
|
|
1379
|
+
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [styles4.triggerWrap, isOpen && styles4.triggerWrapOpen], children: [
|
|
1380
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1381
|
+
reactNative.Pressable,
|
|
1382
|
+
{
|
|
1383
|
+
ref: triggerRef,
|
|
1384
|
+
onPress: handleTriggerPress,
|
|
1385
|
+
disabled,
|
|
1386
|
+
accessibilityRole: "combobox",
|
|
1387
|
+
accessibilityLabel: resolvedAccessibilityLabel,
|
|
1388
|
+
accessibilityState: { disabled, expanded: isOpen },
|
|
1389
|
+
style: [
|
|
1390
|
+
styles4.trigger,
|
|
1391
|
+
{
|
|
1392
|
+
borderColor: triggerBorderColor,
|
|
1393
|
+
backgroundColor: colors.grey700
|
|
1394
|
+
}
|
|
1395
|
+
],
|
|
1396
|
+
children: [
|
|
1397
|
+
hasLeftIcon ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles4.iconSlot, children: leftIconNode }) : null,
|
|
1398
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles4.triggerContent, children: multiple && hasValue ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1399
|
+
MultiValueChips,
|
|
1400
|
+
{
|
|
1401
|
+
options: selectedOptions,
|
|
1402
|
+
disabled,
|
|
1403
|
+
onRemove: handleRemoveChip
|
|
1404
|
+
}
|
|
1405
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles4.triggerText, { color: triggerTextColor }], numberOfLines: 1, children: multiple ? placeholder : singleLabel }) }),
|
|
1406
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [styles4.iconSlot, isOpen && styles4.chevronOpen], children: /* @__PURE__ */ jsxRuntime.jsx(ChevronDownIcon, { size: ICON_SIZE, color: colors.grey100 }) })
|
|
1407
|
+
]
|
|
1408
|
+
}
|
|
1409
|
+
),
|
|
1410
|
+
isOpen ? /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles4.menu, children: [
|
|
1411
|
+
showSearch ? /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles4.searchField, children: [
|
|
1412
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles4.iconSlot, children: /* @__PURE__ */ jsxRuntime.jsx(SearchIcon, { size: ICON_SIZE, color: colors.grey100 }) }),
|
|
1413
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1414
|
+
reactNative.TextInput,
|
|
1415
|
+
{
|
|
1416
|
+
ref: searchInputRef,
|
|
1417
|
+
value: searchQuery,
|
|
1418
|
+
onChangeText: handleSearchChange,
|
|
1419
|
+
editable: !disabled,
|
|
1420
|
+
placeholder: searchPlaceholder,
|
|
1421
|
+
placeholderTextColor: colors.grey100,
|
|
1422
|
+
style: [
|
|
1423
|
+
styles4.searchInput,
|
|
1424
|
+
reactNative.Platform.OS === "web" ? styles4.searchInputWeb : null,
|
|
1425
|
+
reactNative.Platform.OS === "android" ? styles4.searchInputAndroid : null
|
|
1426
|
+
],
|
|
1427
|
+
accessibilityLabel: searchPlaceholder
|
|
1428
|
+
}
|
|
1429
|
+
)
|
|
1430
|
+
] }) : null,
|
|
1431
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1432
|
+
reactNative.ScrollView,
|
|
1433
|
+
{
|
|
1434
|
+
style: styles4.optionList,
|
|
1435
|
+
contentContainerStyle: styles4.optionListContent,
|
|
1436
|
+
keyboardShouldPersistTaps: "handled",
|
|
1437
|
+
showsVerticalScrollIndicator: false,
|
|
1438
|
+
children: [
|
|
1439
|
+
loading ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles4.statusRow, children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles4.statusText, children: "Loading..." }) }) : filteredOptions.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles4.statusRow, children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles4.statusText, children: emptyText }) }) : null,
|
|
1440
|
+
!loading && filteredOptions.map((option) => {
|
|
1441
|
+
const isSelected = selectedValues.includes(option.value);
|
|
1442
|
+
const isHovered = hoveredValue === option.value;
|
|
1443
|
+
const visualState = isSelected ? "selected" : isHovered ? "hover" : "default";
|
|
1444
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1445
|
+
reactNative.Pressable,
|
|
1446
|
+
{
|
|
1447
|
+
onPress: () => handleSelect(option.value),
|
|
1448
|
+
disabled,
|
|
1449
|
+
onHoverIn: () => setHoveredValue(option.value),
|
|
1450
|
+
onHoverOut: () => setHoveredValue((current) => current === option.value ? null : current),
|
|
1451
|
+
onPressIn: () => setHoveredValue(option.value),
|
|
1452
|
+
onPressOut: () => setHoveredValue((current) => current === option.value ? null : current),
|
|
1453
|
+
accessibilityRole: multiple ? "checkbox" : "button",
|
|
1454
|
+
accessibilityState: { selected: isSelected, checked: isSelected, disabled },
|
|
1455
|
+
style: [
|
|
1456
|
+
styles4.item,
|
|
1457
|
+
{
|
|
1458
|
+
backgroundColor: itemBackground(visualState)
|
|
1459
|
+
}
|
|
1460
|
+
],
|
|
1461
|
+
children: [
|
|
1462
|
+
multiple ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { pointerEvents: "none", style: styles4.itemCheckbox, children: /* @__PURE__ */ jsxRuntime.jsx(Checkbox, { value: isSelected, variant: "light" }) }) : null,
|
|
1463
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles4.itemLabel, numberOfLines: 1, children: option.label })
|
|
1464
|
+
]
|
|
1465
|
+
},
|
|
1466
|
+
option.value
|
|
1467
|
+
);
|
|
1468
|
+
})
|
|
1469
|
+
]
|
|
1470
|
+
}
|
|
1471
|
+
)
|
|
1472
|
+
] }) : null
|
|
1473
|
+
] }),
|
|
1474
|
+
showHint && hint ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles4.hint, { color: hintColor }], children: hint }) : null
|
|
1475
|
+
]
|
|
1476
|
+
}
|
|
1477
|
+
);
|
|
1478
|
+
}
|
|
1479
|
+
);
|
|
1480
|
+
var styles4 = reactNative.StyleSheet.create({
|
|
1481
|
+
root: {
|
|
1482
|
+
width: DEFAULT_WIDTH2,
|
|
1483
|
+
gap: 8,
|
|
1484
|
+
alignSelf: "flex-start"
|
|
1485
|
+
},
|
|
1486
|
+
rootOpen: {
|
|
1487
|
+
zIndex: 30
|
|
1488
|
+
},
|
|
1489
|
+
disabled: {
|
|
1490
|
+
opacity: 0.6
|
|
1491
|
+
},
|
|
1492
|
+
label: {
|
|
1493
|
+
...selectTypography.label
|
|
1494
|
+
},
|
|
1495
|
+
triggerWrap: {
|
|
1496
|
+
position: "relative",
|
|
1497
|
+
zIndex: 1
|
|
1498
|
+
},
|
|
1499
|
+
triggerWrapOpen: {
|
|
1500
|
+
zIndex: 20
|
|
1501
|
+
},
|
|
1502
|
+
trigger: {
|
|
1503
|
+
height: TRIGGER_HEIGHT,
|
|
1504
|
+
borderRadius: TRIGGER_RADIUS,
|
|
1505
|
+
borderWidth: 1,
|
|
1506
|
+
paddingVertical: 12,
|
|
1507
|
+
paddingHorizontal: 16,
|
|
1508
|
+
flexDirection: "row",
|
|
1509
|
+
alignItems: "center",
|
|
1510
|
+
gap: 10,
|
|
1511
|
+
overflow: "hidden"
|
|
1512
|
+
},
|
|
1513
|
+
triggerContent: {
|
|
1514
|
+
flex: 1,
|
|
1515
|
+
justifyContent: "center",
|
|
1516
|
+
minWidth: 0,
|
|
1517
|
+
overflow: "hidden"
|
|
1518
|
+
},
|
|
1519
|
+
triggerText: {
|
|
1520
|
+
...selectTypography.field
|
|
1521
|
+
},
|
|
1522
|
+
multiValueRoot: {
|
|
1523
|
+
width: "100%",
|
|
1524
|
+
position: "relative"
|
|
1525
|
+
},
|
|
1526
|
+
measureRow: {
|
|
1527
|
+
position: "absolute",
|
|
1528
|
+
left: 0,
|
|
1529
|
+
top: 0,
|
|
1530
|
+
flexDirection: "row",
|
|
1531
|
+
opacity: 0,
|
|
1532
|
+
zIndex: -1
|
|
1533
|
+
},
|
|
1534
|
+
chipsRow: {
|
|
1535
|
+
flexDirection: "row",
|
|
1536
|
+
alignItems: "center",
|
|
1537
|
+
gap: CHIP_GAP,
|
|
1538
|
+
overflow: "hidden"
|
|
1539
|
+
},
|
|
1540
|
+
chip: {
|
|
1541
|
+
flexDirection: "row",
|
|
1542
|
+
alignItems: "center",
|
|
1543
|
+
gap: 4,
|
|
1544
|
+
paddingVertical: 2,
|
|
1545
|
+
paddingHorizontal: 8,
|
|
1546
|
+
borderRadius: 999,
|
|
1547
|
+
backgroundColor: colors.grey600,
|
|
1548
|
+
flexShrink: 0
|
|
1549
|
+
},
|
|
1550
|
+
chipLabel: {
|
|
1551
|
+
...selectTypography.hint,
|
|
1552
|
+
color: colors.white,
|
|
1553
|
+
maxWidth: 120
|
|
1554
|
+
},
|
|
1555
|
+
chipRemove: {
|
|
1556
|
+
color: colors.grey100,
|
|
1557
|
+
fontSize: 14,
|
|
1558
|
+
lineHeight: 14
|
|
1559
|
+
},
|
|
1560
|
+
ellipsis: {
|
|
1561
|
+
flexShrink: 0,
|
|
1562
|
+
paddingHorizontal: 2
|
|
1563
|
+
},
|
|
1564
|
+
ellipsisText: {
|
|
1565
|
+
...selectTypography.field,
|
|
1566
|
+
color: colors.white,
|
|
1567
|
+
lineHeight: 16
|
|
1568
|
+
},
|
|
1569
|
+
iconSlot: {
|
|
1570
|
+
width: ICON_SIZE,
|
|
1571
|
+
height: ICON_SIZE,
|
|
1572
|
+
alignItems: "center",
|
|
1573
|
+
justifyContent: "center",
|
|
1574
|
+
flexShrink: 0
|
|
1575
|
+
},
|
|
1576
|
+
chevronOpen: {
|
|
1577
|
+
transform: [{ rotate: "180deg" }]
|
|
1578
|
+
},
|
|
1579
|
+
menu: {
|
|
1580
|
+
position: "absolute",
|
|
1581
|
+
top: "100%",
|
|
1582
|
+
left: 0,
|
|
1583
|
+
right: 0,
|
|
1584
|
+
marginTop: 8,
|
|
1585
|
+
zIndex: 10,
|
|
1586
|
+
borderRadius: MENU_RADIUS,
|
|
1587
|
+
padding: 12,
|
|
1588
|
+
gap: 8,
|
|
1589
|
+
backgroundColor: colors.grey700,
|
|
1590
|
+
...reactNative.Platform.select({
|
|
1591
|
+
web: {
|
|
1592
|
+
boxShadow: `0 8px 24px ${colors.black}73`
|
|
1593
|
+
},
|
|
1594
|
+
default: {
|
|
1595
|
+
elevation: 8
|
|
1596
|
+
}
|
|
1597
|
+
})
|
|
1598
|
+
},
|
|
1599
|
+
optionList: {
|
|
1600
|
+
maxHeight: MENU_MAX_LIST_HEIGHT
|
|
1601
|
+
},
|
|
1602
|
+
optionListContent: {
|
|
1603
|
+
gap: 8
|
|
1604
|
+
},
|
|
1605
|
+
statusRow: {
|
|
1606
|
+
minHeight: 43,
|
|
1607
|
+
padding: 12,
|
|
1608
|
+
justifyContent: "center"
|
|
1609
|
+
},
|
|
1610
|
+
statusText: {
|
|
1611
|
+
...selectTypography.field,
|
|
1612
|
+
color: colors.grey100
|
|
1613
|
+
},
|
|
1614
|
+
searchField: {
|
|
1615
|
+
height: 40,
|
|
1616
|
+
borderRadius: ITEM_RADIUS,
|
|
1617
|
+
paddingHorizontal: 12,
|
|
1618
|
+
flexDirection: "row",
|
|
1619
|
+
alignItems: "center",
|
|
1620
|
+
gap: 8,
|
|
1621
|
+
backgroundColor: colors.grey800
|
|
1622
|
+
},
|
|
1623
|
+
searchInput: {
|
|
1624
|
+
...selectTypography.field,
|
|
1625
|
+
flex: 1,
|
|
1626
|
+
color: colors.white,
|
|
1627
|
+
paddingVertical: 0,
|
|
1628
|
+
margin: 0
|
|
1629
|
+
},
|
|
1630
|
+
searchInputWeb: {
|
|
1631
|
+
outlineStyle: "none"
|
|
1632
|
+
},
|
|
1633
|
+
searchInputAndroid: {
|
|
1634
|
+
includeFontPadding: false
|
|
1635
|
+
},
|
|
1636
|
+
item: {
|
|
1637
|
+
minHeight: 43,
|
|
1638
|
+
borderRadius: ITEM_RADIUS,
|
|
1639
|
+
padding: 12,
|
|
1640
|
+
flexDirection: "row",
|
|
1641
|
+
alignItems: "center",
|
|
1642
|
+
gap: 8
|
|
1643
|
+
},
|
|
1644
|
+
itemCheckbox: {
|
|
1645
|
+
flexShrink: 0
|
|
1646
|
+
},
|
|
1647
|
+
itemLabel: {
|
|
1648
|
+
...selectTypography.field,
|
|
1649
|
+
color: colors.white,
|
|
1650
|
+
flex: 1
|
|
1651
|
+
},
|
|
1652
|
+
hint: {
|
|
1653
|
+
...selectTypography.hint
|
|
1654
|
+
}
|
|
1655
|
+
});
|
|
1656
|
+
var DEFAULT_WIDTH3 = 308;
|
|
1657
|
+
var FIELD_HEIGHT = 100;
|
|
1658
|
+
var FIELD_RADIUS = 16;
|
|
1659
|
+
var FIELD_PADDING_VERTICAL = 12;
|
|
1660
|
+
var FIELD_PADDING_HORIZONTAL = 16;
|
|
1661
|
+
function resolveVisualState2({
|
|
1662
|
+
disabled,
|
|
1663
|
+
error,
|
|
1664
|
+
focused,
|
|
1665
|
+
hasValue
|
|
1666
|
+
}) {
|
|
1667
|
+
if (disabled) return "disabled";
|
|
1668
|
+
if (error) return "error";
|
|
1669
|
+
if (focused) return "active";
|
|
1670
|
+
if (hasValue) return "filled";
|
|
1671
|
+
return "default";
|
|
1672
|
+
}
|
|
1673
|
+
function chromeFor2(state) {
|
|
1674
|
+
const base = {
|
|
1675
|
+
borderColor: colors.grey700,
|
|
1676
|
+
backgroundColor: colors.grey700,
|
|
1677
|
+
textColor: colors.white,
|
|
1678
|
+
placeholderColor: colors.grey100,
|
|
1679
|
+
labelColor: colors.white,
|
|
1680
|
+
hintColor: colors.grey100
|
|
1681
|
+
};
|
|
1682
|
+
switch (state) {
|
|
1683
|
+
case "active":
|
|
1684
|
+
return {
|
|
1685
|
+
...base,
|
|
1686
|
+
borderColor: colors.primaryMuted
|
|
1687
|
+
};
|
|
1688
|
+
case "error":
|
|
1689
|
+
return {
|
|
1690
|
+
...base,
|
|
1691
|
+
borderColor: colors.redMuted,
|
|
1692
|
+
textColor: colors.red,
|
|
1693
|
+
placeholderColor: colors.red,
|
|
1694
|
+
labelColor: colors.red,
|
|
1695
|
+
hintColor: colors.red
|
|
1696
|
+
};
|
|
1697
|
+
case "filled":
|
|
1698
|
+
return base;
|
|
1699
|
+
case "disabled":
|
|
1700
|
+
return {
|
|
1701
|
+
...base,
|
|
1702
|
+
textColor: colors.grey0
|
|
1703
|
+
};
|
|
1704
|
+
default:
|
|
1705
|
+
return base;
|
|
1706
|
+
}
|
|
1707
|
+
}
|
|
1708
|
+
var Textarea = react.forwardRef(function Textarea2({
|
|
1709
|
+
label = "Label",
|
|
1710
|
+
showLabel = true,
|
|
1711
|
+
hint = "Hint",
|
|
1712
|
+
showHint = true,
|
|
1713
|
+
placeholder = "placeholder",
|
|
1714
|
+
disabled = false,
|
|
1715
|
+
error = false,
|
|
1716
|
+
value,
|
|
1717
|
+
defaultValue,
|
|
1718
|
+
onChangeText,
|
|
1719
|
+
onFocus,
|
|
1720
|
+
onBlur,
|
|
1721
|
+
style,
|
|
1722
|
+
fieldStyle,
|
|
1723
|
+
inputStyle,
|
|
1724
|
+
className,
|
|
1725
|
+
inputClassName,
|
|
1726
|
+
accessibilityLabel,
|
|
1727
|
+
...textInputProps
|
|
1728
|
+
}, forwardedRef) {
|
|
1729
|
+
const rootRef = react.useRef(null);
|
|
1730
|
+
const inputRef = react.useRef(null);
|
|
1731
|
+
const setInputRef = react.useMemo(() => mergeRefs(inputRef, forwardedRef), [forwardedRef]);
|
|
1732
|
+
const [focused, setFocused] = react.useState(false);
|
|
1733
|
+
const [uncontrolledValue, setUncontrolledValue] = react.useState(defaultValue ?? "");
|
|
1734
|
+
const isControlled = typeof value === "string";
|
|
1735
|
+
const currentValue = isControlled ? value : uncontrolledValue;
|
|
1736
|
+
const hasValue = currentValue.length > 0;
|
|
1737
|
+
const visualState = resolveVisualState2({ disabled, error, focused, hasValue });
|
|
1738
|
+
const chrome = chromeFor2(visualState);
|
|
1739
|
+
const resolvedAccessibilityLabel = accessibilityLabel ?? (showLabel ? void 0 : label);
|
|
1740
|
+
useApplyWebClassName(rootRef, className);
|
|
1741
|
+
useApplyWebClassName(inputRef, inputClassName);
|
|
1742
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { ref: rootRef, style: [styles5.root, disabled && styles5.disabled, style], children: [
|
|
1743
|
+
showLabel && label ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles5.label, { color: chrome.labelColor }], children: label }) : null,
|
|
1744
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1745
|
+
reactNative.View,
|
|
1746
|
+
{
|
|
1747
|
+
style: [
|
|
1748
|
+
styles5.field,
|
|
1749
|
+
{
|
|
1750
|
+
borderColor: chrome.borderColor,
|
|
1751
|
+
backgroundColor: chrome.backgroundColor
|
|
1752
|
+
},
|
|
1753
|
+
fieldStyle
|
|
1754
|
+
],
|
|
1755
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1756
|
+
reactNative.TextInput,
|
|
1757
|
+
{
|
|
1758
|
+
ref: setInputRef,
|
|
1759
|
+
...textInputProps,
|
|
1760
|
+
multiline: true,
|
|
1761
|
+
textAlignVertical: "top",
|
|
1762
|
+
value: isControlled ? value : void 0,
|
|
1763
|
+
defaultValue: isControlled ? void 0 : defaultValue,
|
|
1764
|
+
editable: !disabled,
|
|
1765
|
+
placeholder,
|
|
1766
|
+
placeholderTextColor: chrome.placeholderColor,
|
|
1767
|
+
onChangeText: (text) => {
|
|
1768
|
+
if (!isControlled) setUncontrolledValue(text);
|
|
1769
|
+
onChangeText?.(text);
|
|
1770
|
+
},
|
|
1771
|
+
onFocus: (event) => {
|
|
1772
|
+
setFocused(true);
|
|
1773
|
+
onFocus?.(event);
|
|
1774
|
+
},
|
|
1775
|
+
onBlur: (event) => {
|
|
1776
|
+
setFocused(false);
|
|
1777
|
+
onBlur?.(event);
|
|
1778
|
+
},
|
|
1779
|
+
style: [
|
|
1780
|
+
styles5.input,
|
|
1781
|
+
textareaTypography.field,
|
|
1782
|
+
{ color: chrome.textColor },
|
|
1783
|
+
reactNative.Platform.OS === "web" ? styles5.inputWeb : null,
|
|
1784
|
+
reactNative.Platform.OS === "android" ? styles5.inputAndroid : null,
|
|
1785
|
+
inputStyle
|
|
1786
|
+
],
|
|
1787
|
+
accessibilityLabel: resolvedAccessibilityLabel,
|
|
1788
|
+
accessibilityState: { disabled }
|
|
1789
|
+
}
|
|
1790
|
+
)
|
|
1791
|
+
}
|
|
1792
|
+
),
|
|
1793
|
+
showHint && hint ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles5.hint, { color: chrome.hintColor }], children: hint }) : null
|
|
1794
|
+
] });
|
|
1795
|
+
});
|
|
1796
|
+
var styles5 = reactNative.StyleSheet.create({
|
|
1797
|
+
root: {
|
|
1798
|
+
width: DEFAULT_WIDTH3,
|
|
1799
|
+
gap: 8,
|
|
1800
|
+
alignSelf: "flex-start"
|
|
1801
|
+
},
|
|
1802
|
+
disabled: {
|
|
1803
|
+
opacity: 0.6
|
|
1804
|
+
},
|
|
1805
|
+
label: {
|
|
1806
|
+
...textareaTypography.label
|
|
1807
|
+
},
|
|
1808
|
+
field: {
|
|
1809
|
+
height: FIELD_HEIGHT,
|
|
1810
|
+
borderRadius: FIELD_RADIUS,
|
|
1811
|
+
borderWidth: 1,
|
|
1812
|
+
paddingTop: FIELD_PADDING_VERTICAL,
|
|
1813
|
+
paddingBottom: FIELD_PADDING_VERTICAL,
|
|
1814
|
+
paddingLeft: FIELD_PADDING_HORIZONTAL,
|
|
1815
|
+
paddingRight: FIELD_PADDING_HORIZONTAL
|
|
1816
|
+
},
|
|
1817
|
+
input: {
|
|
1818
|
+
flex: 1,
|
|
1819
|
+
paddingVertical: 0,
|
|
1820
|
+
margin: 0
|
|
1821
|
+
},
|
|
1822
|
+
inputWeb: {
|
|
1823
|
+
outlineStyle: "none",
|
|
1824
|
+
resize: "none"
|
|
1825
|
+
},
|
|
1826
|
+
inputAndroid: {
|
|
1827
|
+
includeFontPadding: false
|
|
1828
|
+
},
|
|
1829
|
+
hint: {
|
|
1830
|
+
...textareaTypography.hint
|
|
1831
|
+
}
|
|
1832
|
+
});
|
|
1833
|
+
var TRACK_WIDTH = 44;
|
|
1834
|
+
var TRACK_HEIGHT = 24;
|
|
1835
|
+
var TRACK_RADIUS = 43;
|
|
1836
|
+
var TRACK_PADDING = 4;
|
|
1837
|
+
var THUMB_SIZE = TRACK_HEIGHT - TRACK_PADDING * 2;
|
|
1838
|
+
var THUMB_TRAVEL = TRACK_WIDTH - TRACK_PADDING * 2 - THUMB_SIZE;
|
|
1839
|
+
var ANIMATION_DURATION = 300;
|
|
1840
|
+
var Toggle = react.forwardRef(function Toggle2({
|
|
1841
|
+
value,
|
|
1842
|
+
defaultValue = false,
|
|
1843
|
+
onValueChange,
|
|
1844
|
+
disabled = false,
|
|
1845
|
+
label,
|
|
1846
|
+
children,
|
|
1847
|
+
accessibilityLabel,
|
|
1848
|
+
style,
|
|
1849
|
+
labelStyle,
|
|
1850
|
+
className,
|
|
1851
|
+
hitSlop = 10,
|
|
1852
|
+
...rest
|
|
1853
|
+
}, forwardedRef) {
|
|
1854
|
+
const containerRef = react.useRef(null);
|
|
1855
|
+
const isControlled = typeof value === "boolean";
|
|
1856
|
+
const [uncontrolledValue, setUncontrolledValue] = react.useState(defaultValue);
|
|
1857
|
+
const isActive = isControlled ? value : uncontrolledValue;
|
|
1858
|
+
const labelContent = children ?? label;
|
|
1859
|
+
const resolvedAccessibilityLabel = accessibilityLabel ?? (typeof labelContent === "string" ? labelContent : void 0);
|
|
1860
|
+
const setContainerRef = react.useMemo(() => mergeRefs(containerRef, forwardedRef), [forwardedRef]);
|
|
1861
|
+
const progress = react.useRef(new reactNative.Animated.Value(isActive ? 1 : 0)).current;
|
|
1862
|
+
useApplyWebClassName(containerRef, className);
|
|
1863
|
+
react.useEffect(() => {
|
|
1864
|
+
reactNative.Animated.timing(progress, {
|
|
1865
|
+
toValue: isActive ? 1 : 0,
|
|
1866
|
+
duration: ANIMATION_DURATION,
|
|
1867
|
+
easing: reactNative.Easing.out(reactNative.Easing.ease),
|
|
1868
|
+
useNativeDriver: false
|
|
1869
|
+
}).start();
|
|
1870
|
+
}, [isActive, progress]);
|
|
1871
|
+
const handlePress = () => {
|
|
1872
|
+
if (disabled) return;
|
|
1873
|
+
const next = !isActive;
|
|
1874
|
+
if (!isControlled) setUncontrolledValue(next);
|
|
1875
|
+
onValueChange?.(next);
|
|
1876
|
+
};
|
|
1877
|
+
const trackBackgroundColor = progress.interpolate({
|
|
1878
|
+
inputRange: [0, 1],
|
|
1879
|
+
outputRange: [colors.grey700, colors.primary]
|
|
1880
|
+
});
|
|
1881
|
+
const thumbTranslateX = progress.interpolate({
|
|
1882
|
+
inputRange: [0, 1],
|
|
1883
|
+
outputRange: [0, THUMB_TRAVEL]
|
|
1884
|
+
});
|
|
1885
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1886
|
+
reactNative.Pressable,
|
|
1887
|
+
{
|
|
1888
|
+
...rest,
|
|
1889
|
+
ref: setContainerRef,
|
|
1890
|
+
onPress: handlePress,
|
|
1891
|
+
disabled,
|
|
1892
|
+
hitSlop,
|
|
1893
|
+
accessibilityRole: "switch",
|
|
1894
|
+
accessibilityLabel: resolvedAccessibilityLabel,
|
|
1895
|
+
accessibilityState: { checked: isActive, disabled },
|
|
1896
|
+
style: [styles6.pressable, disabled && styles6.disabled, style],
|
|
1897
|
+
children: [
|
|
1898
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1899
|
+
reactNative.Animated.View,
|
|
1900
|
+
{
|
|
1901
|
+
style: [
|
|
1902
|
+
styles6.track,
|
|
1903
|
+
{
|
|
1904
|
+
backgroundColor: trackBackgroundColor
|
|
1905
|
+
}
|
|
1906
|
+
],
|
|
1907
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1908
|
+
reactNative.Animated.View,
|
|
1909
|
+
{
|
|
1910
|
+
style: [
|
|
1911
|
+
styles6.thumb,
|
|
1912
|
+
{
|
|
1913
|
+
transform: [{ translateX: thumbTranslateX }]
|
|
1914
|
+
}
|
|
1915
|
+
]
|
|
1916
|
+
}
|
|
1917
|
+
)
|
|
1918
|
+
}
|
|
1919
|
+
),
|
|
1920
|
+
labelContent != null && labelContent !== false ? typeof labelContent === "string" || typeof labelContent === "number" ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles6.label, labelStyle], children: labelContent }) : labelContent : null
|
|
1921
|
+
]
|
|
1922
|
+
}
|
|
1923
|
+
);
|
|
1924
|
+
});
|
|
1925
|
+
var styles6 = reactNative.StyleSheet.create({
|
|
1926
|
+
pressable: {
|
|
1927
|
+
flexDirection: "row",
|
|
1928
|
+
alignItems: "center",
|
|
1929
|
+
alignSelf: "flex-start",
|
|
1930
|
+
gap: 10
|
|
1931
|
+
},
|
|
1932
|
+
disabled: {
|
|
1933
|
+
opacity: 0.6
|
|
1934
|
+
},
|
|
1935
|
+
track: {
|
|
1936
|
+
width: TRACK_WIDTH,
|
|
1937
|
+
height: TRACK_HEIGHT,
|
|
1938
|
+
borderRadius: TRACK_RADIUS,
|
|
1939
|
+
padding: TRACK_PADDING,
|
|
1940
|
+
justifyContent: "center"
|
|
1941
|
+
},
|
|
1942
|
+
thumb: {
|
|
1943
|
+
width: THUMB_SIZE,
|
|
1944
|
+
height: THUMB_SIZE,
|
|
1945
|
+
borderRadius: THUMB_SIZE / 2,
|
|
1946
|
+
backgroundColor: colors.white
|
|
1947
|
+
},
|
|
1948
|
+
label: {
|
|
1949
|
+
...inputTypography.field,
|
|
1950
|
+
color: colors.white
|
|
1951
|
+
}
|
|
1952
|
+
});
|
|
805
1953
|
|
|
806
1954
|
exports.ArrowRightIcon = ArrowRightIcon;
|
|
807
1955
|
exports.BagIcon = BagIcon;
|
|
@@ -810,6 +1958,9 @@ exports.BuildingIcon = BuildingIcon;
|
|
|
810
1958
|
exports.Button = Button;
|
|
811
1959
|
exports.CameraIcon = CameraIcon;
|
|
812
1960
|
exports.CheckBadgeIcon = CheckBadgeIcon;
|
|
1961
|
+
exports.CheckIcon = CheckIcon;
|
|
1962
|
+
exports.Checkbox = Checkbox;
|
|
1963
|
+
exports.ChevronDownIcon = ChevronDownIcon;
|
|
813
1964
|
exports.ClockIcon = ClockIcon;
|
|
814
1965
|
exports.FacebookIcon = FacebookIcon;
|
|
815
1966
|
exports.HomeIcon = HomeIcon;
|
|
@@ -821,7 +1972,11 @@ exports.LinkedInIcon = LinkedInIcon;
|
|
|
821
1972
|
exports.MailIcon = MailIcon;
|
|
822
1973
|
exports.NavigateIcon = NavigateIcon;
|
|
823
1974
|
exports.PhoneIcon = PhoneIcon;
|
|
1975
|
+
exports.SearchIcon = SearchIcon;
|
|
1976
|
+
exports.Select = Select;
|
|
824
1977
|
exports.ShowIcon = ShowIcon;
|
|
1978
|
+
exports.Textarea = Textarea;
|
|
1979
|
+
exports.Toggle = Toggle;
|
|
825
1980
|
exports.UserIcon = UserIcon;
|
|
826
1981
|
exports.buttonTypography = buttonTypography;
|
|
827
1982
|
exports.colors = colors;
|
|
@@ -833,5 +1988,7 @@ exports.iconGroups = iconGroups;
|
|
|
833
1988
|
exports.iconNames = iconNames;
|
|
834
1989
|
exports.icons = icons;
|
|
835
1990
|
exports.inputTypography = inputTypography;
|
|
1991
|
+
exports.selectTypography = selectTypography;
|
|
1992
|
+
exports.textareaTypography = textareaTypography;
|
|
836
1993
|
//# sourceMappingURL=index.cjs.map
|
|
837
1994
|
//# sourceMappingURL=index.cjs.map
|