@scripso-homepad/ui 0.3.7 → 0.3.9
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 +7 -2
- package/dist/index.cjs +152 -44
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +10 -4
- package/dist/index.d.ts +10 -4
- package/dist/index.js +153 -45
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/Button.tsx +11 -2
- package/src/components/Input.stories.tsx +9 -0
- package/src/components/Input.tsx +60 -5
- package/src/components/PhoneInput.tsx +2 -2
- package/src/icons/EyeIcon.tsx +25 -37
- package/src/icons/EyeIcon.web.tsx +42 -0
- package/src/icons/EyeOffIcon.tsx +29 -0
- package/src/icons/EyeOffIcon.web.tsx +35 -0
- package/src/icons/eyeIconPaths.ts +8 -0
- package/src/theme/input.ts +29 -14
- package/src/theme/tokens.ts +3 -3
package/README.md
CHANGED
|
@@ -55,8 +55,13 @@ export default defineConfig({
|
|
|
55
55
|
}),
|
|
56
56
|
],
|
|
57
57
|
resolve: {
|
|
58
|
+
dedupe: ["react", "react-dom", "react-native", "react-native-web"],
|
|
58
59
|
alias: {
|
|
59
60
|
"react-native": "react-native-web",
|
|
61
|
+
react: path.resolve(__dirname, "node_modules/react"),
|
|
62
|
+
"react-dom": path.resolve(__dirname, "node_modules/react-dom"),
|
|
63
|
+
"react/jsx-runtime": path.resolve(__dirname, "node_modules/react/jsx-runtime"),
|
|
64
|
+
"react/jsx-dev-runtime": path.resolve(__dirname, "node_modules/react/jsx-dev-runtime"),
|
|
60
65
|
"@scripso-homepad/ui": resolveUiPackageEntry(),
|
|
61
66
|
},
|
|
62
67
|
extensions: [
|
|
@@ -71,8 +76,8 @@ export default defineConfig({
|
|
|
71
76
|
],
|
|
72
77
|
},
|
|
73
78
|
optimizeDeps: {
|
|
74
|
-
include: ["react-
|
|
75
|
-
exclude: ["react-native-svg"],
|
|
79
|
+
include: ["react", "react-dom", "react/jsx-runtime", "react-native-web"],
|
|
80
|
+
exclude: ["react-native-svg", "@scripso-homepad/ui"],
|
|
76
81
|
esbuildOptions: {
|
|
77
82
|
resolveExtensions: [
|
|
78
83
|
".web.js",
|
package/dist/index.cjs
CHANGED
|
@@ -233,14 +233,14 @@ var buttonTypography = {
|
|
|
233
233
|
fontFamily: fonts.sans,
|
|
234
234
|
fontSize: 14,
|
|
235
235
|
fontWeight: fontWeight.semibold,
|
|
236
|
-
lineHeight:
|
|
236
|
+
lineHeight: 18,
|
|
237
237
|
letterSpacing: 0
|
|
238
238
|
},
|
|
239
239
|
sm: {
|
|
240
240
|
fontFamily: fonts.sans,
|
|
241
241
|
fontSize: 12,
|
|
242
242
|
fontWeight: fontWeight.semibold,
|
|
243
|
-
lineHeight:
|
|
243
|
+
lineHeight: 16,
|
|
244
244
|
letterSpacing: 0
|
|
245
245
|
}
|
|
246
246
|
};
|
|
@@ -365,8 +365,9 @@ function Button({
|
|
|
365
365
|
useApplyWebClassName(textRef, textClassName);
|
|
366
366
|
const label = typeof children !== "undefined" ? children : title;
|
|
367
367
|
const hasCustomChildren = typeof children !== "undefined";
|
|
368
|
-
const
|
|
369
|
-
const
|
|
368
|
+
const customIcon = icon != null && typeof icon !== "boolean" ? icon : void 0;
|
|
369
|
+
const hasIcon = showIcon || icon === true || customIcon != null;
|
|
370
|
+
const iconNode = customIcon ?? /* @__PURE__ */ jsxRuntime.jsx(ArrowUpRightIcon, { size: metrics.iconSize, color: preset.iconColor });
|
|
370
371
|
const containerStyle = [
|
|
371
372
|
styles.base,
|
|
372
373
|
{
|
|
@@ -386,6 +387,7 @@ function Button({
|
|
|
386
387
|
styles.label,
|
|
387
388
|
metrics.text,
|
|
388
389
|
{ color: preset.textColor },
|
|
390
|
+
reactNative.Platform.OS === "android" ? styles.labelAndroid : null,
|
|
389
391
|
!hasIcon && styles.labelCentered,
|
|
390
392
|
hasIcon && styles.labelWithIcon,
|
|
391
393
|
textStyle
|
|
@@ -438,6 +440,9 @@ var styles = reactNative.StyleSheet.create({
|
|
|
438
440
|
opacity: 0.6
|
|
439
441
|
},
|
|
440
442
|
label: {},
|
|
443
|
+
labelAndroid: {
|
|
444
|
+
includeFontPadding: false
|
|
445
|
+
},
|
|
441
446
|
labelCentered: {
|
|
442
447
|
textAlign: "center"
|
|
443
448
|
},
|
|
@@ -452,6 +457,55 @@ var styles = reactNative.StyleSheet.create({
|
|
|
452
457
|
flexShrink: 0
|
|
453
458
|
}
|
|
454
459
|
});
|
|
460
|
+
|
|
461
|
+
// src/icons/eyeIconPaths.ts
|
|
462
|
+
var EYE_OPEN_OUTLINE_PATH = "M1.71835 10.2898C1.6489 10.1027 1.6489 9.89691 1.71835 9.70981C2.39476 8.06969 3.54294 6.66735 5.01732 5.68056C6.4917 4.69378 8.22588 4.16699 10 4.16699C11.7741 4.16699 13.5083 4.69378 14.9827 5.68056C16.4571 6.66735 17.6053 8.06969 18.2817 9.70981C18.3511 9.89691 18.3511 10.1027 18.2817 10.2898C17.6053 11.9299 16.4571 13.3323 14.9827 14.3191C13.5083 15.3058 11.7741 15.8326 10 15.8326C8.22588 15.8326 6.4917 15.3058 5.01732 14.3191C3.54294 13.3323 2.39476 11.9299 1.71835 10.2898Z";
|
|
463
|
+
var EYE_OPEN_PUPIL_PATH = "M10 12.4998C11.3807 12.4998 12.5 11.3805 12.5 9.99981C12.5 8.6191 11.3807 7.49981 10 7.49981C8.6193 7.49981 7.50001 8.6191 7.50001 9.99981C7.50001 11.3805 8.6193 12.4998 10 12.4998Z";
|
|
464
|
+
var EYE_OFF_PATH = "M10.733 5.076C13.0624 4.7984 15.4186 5.29082 17.4419 6.47805C19.4651 7.66528 21.0442 9.48208 21.938 11.651C22.0213 11.8755 22.0213 12.1225 21.938 12.347C21.5705 13.238 21.0848 14.0755 20.494 14.837M14.084 14.158C13.5182 14.7045 12.7604 15.0069 11.9738 15C11.1872 14.9932 10.4348 14.6777 9.87854 14.1215C9.32232 13.5652 9.00681 12.8128 8.99998 12.0262C8.99314 11.2396 9.29553 10.4818 9.842 9.916M17.479 17.499C16.1525 18.2848 14.6725 18.776 13.1394 18.9394C11.6063 19.1028 10.056 18.9345 8.59363 18.4459C7.13131 17.9573 5.79119 17.1599 4.66421 16.1077C3.53723 15.0556 2.64975 13.7734 2.062 12.348C1.97866 12.1235 1.97866 11.8765 2.062 11.652C2.94863 9.50186 4.50867 7.69725 6.508 6.509M2 2L22 22";
|
|
465
|
+
function EyeIcon({
|
|
466
|
+
size = 20,
|
|
467
|
+
color = "#c7cdd1",
|
|
468
|
+
strokeWidth = 2
|
|
469
|
+
}) {
|
|
470
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Svg__default.default, { width: size, height: size, viewBox: "0 0 20 20", fill: "none", children: [
|
|
471
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
472
|
+
Svg.Path,
|
|
473
|
+
{
|
|
474
|
+
d: EYE_OPEN_OUTLINE_PATH,
|
|
475
|
+
stroke: color,
|
|
476
|
+
strokeWidth,
|
|
477
|
+
strokeLinecap: "round",
|
|
478
|
+
strokeLinejoin: "round"
|
|
479
|
+
}
|
|
480
|
+
),
|
|
481
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
482
|
+
Svg.Path,
|
|
483
|
+
{
|
|
484
|
+
d: EYE_OPEN_PUPIL_PATH,
|
|
485
|
+
stroke: color,
|
|
486
|
+
strokeWidth,
|
|
487
|
+
strokeLinecap: "round",
|
|
488
|
+
strokeLinejoin: "round"
|
|
489
|
+
}
|
|
490
|
+
)
|
|
491
|
+
] });
|
|
492
|
+
}
|
|
493
|
+
function EyeOffIcon({
|
|
494
|
+
size = 20,
|
|
495
|
+
color = "#c7cdd1",
|
|
496
|
+
strokeWidth = 2
|
|
497
|
+
}) {
|
|
498
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Svg__default.default, { width: size, height: size, viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
499
|
+
Svg.Path,
|
|
500
|
+
{
|
|
501
|
+
d: EYE_OFF_PATH,
|
|
502
|
+
stroke: color,
|
|
503
|
+
strokeWidth,
|
|
504
|
+
strokeLinecap: "round",
|
|
505
|
+
strokeLinejoin: "round"
|
|
506
|
+
}
|
|
507
|
+
) });
|
|
508
|
+
}
|
|
455
509
|
var INPUT_HEIGHT = 52;
|
|
456
510
|
var INPUT_ICON_SIZE = 20;
|
|
457
511
|
var INPUT_ICON_GAP = 10;
|
|
@@ -466,17 +520,30 @@ function resolveInputVisualState({
|
|
|
466
520
|
if (focused) return "focused";
|
|
467
521
|
return "default";
|
|
468
522
|
}
|
|
469
|
-
function
|
|
470
|
-
|
|
523
|
+
function createOutlineStyle(ringColor) {
|
|
524
|
+
return {
|
|
471
525
|
borderRadius: radii.lg + INPUT_OUTLINE_WIDTH,
|
|
472
|
-
|
|
473
|
-
|
|
526
|
+
borderWidth: INPUT_OUTLINE_WIDTH,
|
|
527
|
+
borderColor: ringColor,
|
|
528
|
+
padding: 0,
|
|
529
|
+
backgroundColor: colors.transparent,
|
|
530
|
+
width: "100%",
|
|
531
|
+
alignSelf: "stretch",
|
|
532
|
+
...reactNative.Platform.OS !== "web" ? { overflow: "hidden" } : null
|
|
533
|
+
};
|
|
534
|
+
}
|
|
535
|
+
var defaultOutline = createOutlineStyle(colors.transparent);
|
|
536
|
+
function getInputFieldStyles(state) {
|
|
537
|
+
const containerBase = {
|
|
538
|
+
borderRadius: radii.lg,
|
|
539
|
+
...reactNative.Platform.OS !== "web" ? { overflow: "hidden" } : null
|
|
474
540
|
};
|
|
475
541
|
switch (state) {
|
|
476
542
|
case "disabled":
|
|
477
543
|
return {
|
|
478
|
-
outline:
|
|
544
|
+
outline: defaultOutline,
|
|
479
545
|
container: {
|
|
546
|
+
...containerBase,
|
|
480
547
|
borderWidth: 1,
|
|
481
548
|
borderColor: colors.stormGray50,
|
|
482
549
|
backgroundColor: colors.stormGray50
|
|
@@ -487,11 +554,9 @@ function getInputFieldStyles(state) {
|
|
|
487
554
|
};
|
|
488
555
|
case "error":
|
|
489
556
|
return {
|
|
490
|
-
outline:
|
|
491
|
-
...outlineBase,
|
|
492
|
-
backgroundColor: colors.inputOutlineError
|
|
493
|
-
},
|
|
557
|
+
outline: createOutlineStyle(colors.inputOutlineError),
|
|
494
558
|
container: {
|
|
559
|
+
...containerBase,
|
|
495
560
|
borderWidth: 1,
|
|
496
561
|
borderColor: colors.inputError,
|
|
497
562
|
backgroundColor: colors.white
|
|
@@ -502,11 +567,9 @@ function getInputFieldStyles(state) {
|
|
|
502
567
|
};
|
|
503
568
|
case "focused":
|
|
504
569
|
return {
|
|
505
|
-
outline:
|
|
506
|
-
...outlineBase,
|
|
507
|
-
backgroundColor: colors.inputOutlineFocus
|
|
508
|
-
},
|
|
570
|
+
outline: createOutlineStyle(colors.inputOutlineFocus),
|
|
509
571
|
container: {
|
|
572
|
+
...containerBase,
|
|
510
573
|
borderWidth: 1,
|
|
511
574
|
borderColor: colors.navy,
|
|
512
575
|
backgroundColor: colors.white
|
|
@@ -517,8 +580,9 @@ function getInputFieldStyles(state) {
|
|
|
517
580
|
};
|
|
518
581
|
default:
|
|
519
582
|
return {
|
|
520
|
-
outline:
|
|
583
|
+
outline: defaultOutline,
|
|
521
584
|
container: {
|
|
585
|
+
...containerBase,
|
|
522
586
|
borderWidth: 1,
|
|
523
587
|
borderColor: colors.stormGray50,
|
|
524
588
|
backgroundColor: colors.white
|
|
@@ -547,12 +611,13 @@ var inputFieldMetrics = reactNative.StyleSheet.create({
|
|
|
547
611
|
fontFamily: fonts.sans,
|
|
548
612
|
fontSize: fontSize.md,
|
|
549
613
|
fontWeight: fontWeight.medium,
|
|
550
|
-
lineHeight: fontSize.md,
|
|
614
|
+
lineHeight: reactNative.Platform.OS === "web" ? fontSize.md : 20,
|
|
551
615
|
paddingVertical: 0,
|
|
552
616
|
paddingHorizontal: 0,
|
|
553
617
|
margin: 0,
|
|
554
618
|
borderWidth: 0,
|
|
555
619
|
backgroundColor: colors.transparent,
|
|
620
|
+
...reactNative.Platform.OS === "android" ? { includeFontPadding: false } : null,
|
|
556
621
|
...reactNative.Platform.OS === "web" ? {
|
|
557
622
|
height: "100%",
|
|
558
623
|
minHeight: 0,
|
|
@@ -615,23 +680,32 @@ function Input({
|
|
|
615
680
|
containerStyle,
|
|
616
681
|
style,
|
|
617
682
|
className,
|
|
683
|
+
fieldClassName,
|
|
684
|
+
fieldStyle,
|
|
618
685
|
labelClassName,
|
|
619
686
|
inputClassName,
|
|
620
687
|
errorClassName,
|
|
621
688
|
hintClassName,
|
|
622
689
|
editable = true,
|
|
690
|
+
secureTextEntry,
|
|
691
|
+
showPasswordToggle,
|
|
623
692
|
onFocus,
|
|
624
693
|
onBlur,
|
|
625
694
|
...props
|
|
626
695
|
}) {
|
|
627
696
|
const wrapperRef = react.useRef(null);
|
|
697
|
+
const fieldRef = react.useRef(null);
|
|
628
698
|
const inputRef = react.useRef(null);
|
|
629
699
|
const helperRef = react.useRef(null);
|
|
630
700
|
const [focused, setFocused] = react.useState(false);
|
|
701
|
+
const [passwordVisible, setPasswordVisible] = react.useState(false);
|
|
631
702
|
useApplyWebClassName(wrapperRef, className);
|
|
703
|
+
useApplyWebClassName(fieldRef, fieldClassName);
|
|
632
704
|
useApplyWebClassName(inputRef, inputClassName);
|
|
633
705
|
useApplyWebClassName(helperRef, error ? errorClassName : hintClassName);
|
|
634
706
|
const isDisabled = editable === false;
|
|
707
|
+
const passwordToggleEnabled = secureTextEntry === true && showPasswordToggle !== false && rightIcon == null;
|
|
708
|
+
const effectiveSecureTextEntry = passwordToggleEnabled ? !passwordVisible : secureTextEntry;
|
|
635
709
|
const visualState = resolveInputVisualState({
|
|
636
710
|
focused,
|
|
637
711
|
error: Boolean(error),
|
|
@@ -648,29 +722,57 @@ function Input({
|
|
|
648
722
|
onBlur?.(event);
|
|
649
723
|
}
|
|
650
724
|
const helperMessage = error ?? hint;
|
|
725
|
+
function togglePasswordVisibility() {
|
|
726
|
+
if (!isDisabled) {
|
|
727
|
+
setPasswordVisible((visible) => !visible);
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
const trailingIcon = passwordToggleEnabled ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
731
|
+
reactNative.Pressable,
|
|
732
|
+
{
|
|
733
|
+
onPress: togglePasswordVisibility,
|
|
734
|
+
disabled: isDisabled,
|
|
735
|
+
accessibilityRole: "button",
|
|
736
|
+
accessibilityLabel: passwordVisible ? "Hide password" : "Show password",
|
|
737
|
+
hitSlop: 8,
|
|
738
|
+
style: styles3.iconPressable,
|
|
739
|
+
children: renderInputIcon(
|
|
740
|
+
passwordVisible ? /* @__PURE__ */ jsxRuntime.jsx(EyeOffIcon, {}) : /* @__PURE__ */ jsxRuntime.jsx(EyeIcon, {}),
|
|
741
|
+
iconColor
|
|
742
|
+
)
|
|
743
|
+
}
|
|
744
|
+
) : rightIcon ? renderInputIcon(rightIcon, iconColor) : null;
|
|
651
745
|
return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { ref: wrapperRef, style: [styles3.wrapper, containerStyle], children: [
|
|
652
746
|
label ? /* @__PURE__ */ jsxRuntime.jsx(Label, { disabled: isDisabled, className: labelClassName, children: label }) : null,
|
|
653
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: fieldStyles.outline, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
style:
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
747
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: fieldStyles.outline, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
748
|
+
reactNative.View,
|
|
749
|
+
{
|
|
750
|
+
ref: fieldRef,
|
|
751
|
+
style: [inputFieldMetrics.container, fieldStyles.container, fieldStyle],
|
|
752
|
+
children: [
|
|
753
|
+
leftIcon ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles3.iconSlot, children: renderInputIcon(leftIcon, iconColor) }) : null,
|
|
754
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
755
|
+
reactNative.TextInput,
|
|
756
|
+
{
|
|
757
|
+
ref: inputRef,
|
|
758
|
+
style: [
|
|
759
|
+
inputFieldMetrics.input,
|
|
760
|
+
fieldStyles.text,
|
|
761
|
+
style
|
|
762
|
+
],
|
|
763
|
+
placeholderTextColor: fieldStyles.placeholder,
|
|
764
|
+
editable,
|
|
765
|
+
secureTextEntry: effectiveSecureTextEntry,
|
|
766
|
+
onFocus: handleFocus,
|
|
767
|
+
onBlur: handleBlur,
|
|
768
|
+
accessibilityState: { disabled: isDisabled },
|
|
769
|
+
...props
|
|
770
|
+
}
|
|
771
|
+
),
|
|
772
|
+
trailingIcon ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles3.iconSlot, children: trailingIcon }) : null
|
|
773
|
+
]
|
|
774
|
+
}
|
|
775
|
+
) }),
|
|
674
776
|
helperMessage ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { ref: helperRef, style: error ? styles3.error : styles3.hint, children: helperMessage }) : null
|
|
675
777
|
] });
|
|
676
778
|
}
|
|
@@ -686,14 +788,20 @@ var styles3 = reactNative.StyleSheet.create({
|
|
|
686
788
|
justifyContent: "center",
|
|
687
789
|
flexShrink: 0
|
|
688
790
|
},
|
|
791
|
+
iconPressable: {
|
|
792
|
+
width: INPUT_ICON_SIZE,
|
|
793
|
+
height: INPUT_ICON_SIZE,
|
|
794
|
+
alignItems: "center",
|
|
795
|
+
justifyContent: "center"
|
|
796
|
+
},
|
|
689
797
|
error: {
|
|
690
798
|
fontSize: 12,
|
|
691
|
-
lineHeight:
|
|
799
|
+
lineHeight: 16,
|
|
692
800
|
color: colors.inputError
|
|
693
801
|
},
|
|
694
802
|
hint: {
|
|
695
803
|
fontSize: 12,
|
|
696
|
-
lineHeight:
|
|
804
|
+
lineHeight: 16,
|
|
697
805
|
color: colors.stormGray300
|
|
698
806
|
}
|
|
699
807
|
});
|
|
@@ -1190,12 +1298,12 @@ var styles5 = reactNative.StyleSheet.create({
|
|
|
1190
1298
|
},
|
|
1191
1299
|
error: {
|
|
1192
1300
|
fontSize: 12,
|
|
1193
|
-
lineHeight:
|
|
1301
|
+
lineHeight: 16,
|
|
1194
1302
|
color: colors.inputError
|
|
1195
1303
|
},
|
|
1196
1304
|
hint: {
|
|
1197
1305
|
fontSize: 12,
|
|
1198
|
-
lineHeight:
|
|
1306
|
+
lineHeight: 16,
|
|
1199
1307
|
color: colors.stormGray300
|
|
1200
1308
|
}
|
|
1201
1309
|
});
|