@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 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-native-web", "@scripso-homepad/ui"],
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: 14,
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: 12,
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 hasIcon = showIcon || icon != null;
369
- const iconNode = icon ?? /* @__PURE__ */ jsxRuntime.jsx(ArrowUpRightIcon, { size: metrics.iconSize, color: preset.iconColor });
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 getInputFieldStyles(state) {
470
- const outlineBase = {
523
+ function createOutlineStyle(ringColor) {
524
+ return {
471
525
  borderRadius: radii.lg + INPUT_OUTLINE_WIDTH,
472
- padding: INPUT_OUTLINE_WIDTH,
473
- backgroundColor: colors.transparent
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: outlineBase,
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: outlineBase,
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(reactNative.View, { style: [inputFieldMetrics.container, fieldStyles.container], children: [
654
- leftIcon ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles3.iconSlot, children: renderInputIcon(leftIcon, iconColor) }) : null,
655
- /* @__PURE__ */ jsxRuntime.jsx(
656
- reactNative.TextInput,
657
- {
658
- ref: inputRef,
659
- style: [
660
- inputFieldMetrics.input,
661
- fieldStyles.text,
662
- style
663
- ],
664
- placeholderTextColor: fieldStyles.placeholder,
665
- editable,
666
- onFocus: handleFocus,
667
- onBlur: handleBlur,
668
- accessibilityState: { disabled: isDisabled },
669
- ...props
670
- }
671
- ),
672
- rightIcon ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles3.iconSlot, children: renderInputIcon(rightIcon, iconColor) }) : null
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: 12,
799
+ lineHeight: 16,
692
800
  color: colors.inputError
693
801
  },
694
802
  hint: {
695
803
  fontSize: 12,
696
- lineHeight: 12,
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: 12,
1301
+ lineHeight: 16,
1194
1302
  color: colors.inputError
1195
1303
  },
1196
1304
  hint: {
1197
1305
  fontSize: 12,
1198
- lineHeight: 12,
1306
+ lineHeight: 16,
1199
1307
  color: colors.stormGray300
1200
1308
  }
1201
1309
  });