@scripso-homepad/ui 0.3.7 → 0.3.8

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.
@@ -161,12 +161,12 @@ const styles = StyleSheet.create({
161
161
  },
162
162
  error: {
163
163
  fontSize: 12,
164
- lineHeight: 12,
164
+ lineHeight: 16,
165
165
  color: colors.inputError,
166
166
  },
167
167
  hint: {
168
168
  fontSize: 12,
169
- lineHeight: 12,
169
+ lineHeight: 16,
170
170
  color: colors.stormGray300,
171
171
  },
172
172
  });
@@ -1,48 +1,36 @@
1
- import { StyleSheet, View } from "react-native";
1
+ import Svg, { Path } from "react-native-svg";
2
+ import { EYE_OPEN_OUTLINE_PATH, EYE_OPEN_PUPIL_PATH } from "./eyeIconPaths";
3
+
4
+ export { EYE_OPEN_OUTLINE_PATH, EYE_OPEN_PUPIL_PATH } from "./eyeIconPaths";
2
5
 
3
6
  interface EyeIconProps {
4
7
  size?: number;
5
8
  color?: string;
9
+ strokeWidth?: number;
6
10
  }
7
11
 
8
- /** Minimal eye icon for input fields (no SVG dependency). */
9
- export function EyeIcon({ size = 20, color = "#c7cdd1" }: EyeIconProps) {
10
- const stroke = Math.max(1.5, size * 0.1);
11
- const eyeWidth = size * 0.78;
12
- const eyeHeight = size * 0.44;
13
-
12
+ /** Native open eye (password hidden). */
13
+ export function EyeIcon({
14
+ size = 20,
15
+ color = "#c7cdd1",
16
+ strokeWidth = 2,
17
+ }: EyeIconProps) {
14
18
  return (
15
- <View style={[styles.root, { width: size, height: size }]}>
16
- <View
17
- style={{
18
- position: "absolute",
19
- left: (size - eyeWidth) / 2,
20
- top: (size - eyeHeight) / 2,
21
- width: eyeWidth,
22
- height: eyeHeight,
23
- borderRadius: eyeHeight / 2,
24
- borderWidth: stroke,
25
- borderColor: color,
26
- }}
19
+ <Svg width={size} height={size} viewBox="0 0 20 20" fill="none">
20
+ <Path
21
+ d={EYE_OPEN_OUTLINE_PATH}
22
+ stroke={color}
23
+ strokeWidth={strokeWidth}
24
+ strokeLinecap="round"
25
+ strokeLinejoin="round"
27
26
  />
28
- <View
29
- style={{
30
- position: "absolute",
31
- left: size / 2 - size * 0.14,
32
- top: size / 2 - size * 0.14,
33
- width: size * 0.28,
34
- height: size * 0.28,
35
- borderRadius: size * 0.14,
36
- borderWidth: stroke,
37
- borderColor: color,
38
- }}
27
+ <Path
28
+ d={EYE_OPEN_PUPIL_PATH}
29
+ stroke={color}
30
+ strokeWidth={strokeWidth}
31
+ strokeLinecap="round"
32
+ strokeLinejoin="round"
39
33
  />
40
- </View>
34
+ </Svg>
41
35
  );
42
36
  }
43
-
44
- const styles = StyleSheet.create({
45
- root: {
46
- position: "relative",
47
- },
48
- });
@@ -0,0 +1,42 @@
1
+ import { EYE_OPEN_OUTLINE_PATH, EYE_OPEN_PUPIL_PATH } from "./eyeIconPaths";
2
+
3
+ interface EyeIconProps {
4
+ size?: number;
5
+ color?: string;
6
+ strokeWidth?: number;
7
+ }
8
+
9
+ /** Web — open eye (password hidden). */
10
+ export function EyeIcon({
11
+ size = 20,
12
+ color = "#c7cdd1",
13
+ strokeWidth = 2,
14
+ }: EyeIconProps) {
15
+ return (
16
+ <svg
17
+ width={size}
18
+ height={size}
19
+ viewBox="0 0 20 20"
20
+ fill="none"
21
+ xmlns="http://www.w3.org/2000/svg"
22
+ aria-hidden
23
+ >
24
+ <path
25
+ d={EYE_OPEN_OUTLINE_PATH}
26
+ stroke={color}
27
+ strokeWidth={strokeWidth}
28
+ strokeLinecap="round"
29
+ strokeLinejoin="round"
30
+ />
31
+ <path
32
+ d={EYE_OPEN_PUPIL_PATH}
33
+ stroke={color}
34
+ strokeWidth={strokeWidth}
35
+ strokeLinecap="round"
36
+ strokeLinejoin="round"
37
+ />
38
+ </svg>
39
+ );
40
+ }
41
+
42
+ export { EYE_OPEN_OUTLINE_PATH, EYE_OPEN_PUPIL_PATH } from "./eyeIconPaths";
@@ -0,0 +1,29 @@
1
+ import Svg, { Path } from "react-native-svg";
2
+ import { EYE_OFF_PATH } from "./eyeIconPaths";
3
+
4
+ export { EYE_OFF_PATH } from "./eyeIconPaths";
5
+
6
+ interface EyeOffIconProps {
7
+ size?: number;
8
+ color?: string;
9
+ strokeWidth?: number;
10
+ }
11
+
12
+ /** Native — slashed eye (password visible). */
13
+ export function EyeOffIcon({
14
+ size = 20,
15
+ color = "#c7cdd1",
16
+ strokeWidth = 2,
17
+ }: EyeOffIconProps) {
18
+ return (
19
+ <Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
20
+ <Path
21
+ d={EYE_OFF_PATH}
22
+ stroke={color}
23
+ strokeWidth={strokeWidth}
24
+ strokeLinecap="round"
25
+ strokeLinejoin="round"
26
+ />
27
+ </Svg>
28
+ );
29
+ }
@@ -0,0 +1,35 @@
1
+ import { EYE_OFF_PATH } from "./eyeIconPaths";
2
+
3
+ interface EyeOffIconProps {
4
+ size?: number;
5
+ color?: string;
6
+ strokeWidth?: number;
7
+ }
8
+
9
+ /** Web — slashed eye (password visible). */
10
+ export function EyeOffIcon({
11
+ size = 20,
12
+ color = "#c7cdd1",
13
+ strokeWidth = 2,
14
+ }: EyeOffIconProps) {
15
+ return (
16
+ <svg
17
+ width={size}
18
+ height={size}
19
+ viewBox="0 0 24 24"
20
+ fill="none"
21
+ xmlns="http://www.w3.org/2000/svg"
22
+ aria-hidden
23
+ >
24
+ <path
25
+ d={EYE_OFF_PATH}
26
+ stroke={color}
27
+ strokeWidth={strokeWidth}
28
+ strokeLinecap="round"
29
+ strokeLinejoin="round"
30
+ />
31
+ </svg>
32
+ );
33
+ }
34
+
35
+ export { EYE_OFF_PATH } from "./eyeIconPaths";
@@ -0,0 +1,8 @@
1
+ export const EYE_OPEN_OUTLINE_PATH =
2
+ "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";
3
+
4
+ export const EYE_OPEN_PUPIL_PATH =
5
+ "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";
6
+
7
+ export const EYE_OFF_PATH =
8
+ "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";
@@ -37,18 +37,33 @@ interface FieldStyleSet {
37
37
  icon: string;
38
38
  }
39
39
 
40
- export function getInputFieldStyles(state: InputVisualState): FieldStyleSet {
41
- const outlineBase: ViewStyle = {
40
+ function createOutlineStyle(ringColor: string): ViewStyle {
41
+ return {
42
42
  borderRadius: radii.lg + INPUT_OUTLINE_WIDTH,
43
- padding: INPUT_OUTLINE_WIDTH,
43
+ borderWidth: INPUT_OUTLINE_WIDTH,
44
+ borderColor: ringColor,
45
+ padding: 0,
44
46
  backgroundColor: colors.transparent,
47
+ width: "100%",
48
+ alignSelf: "stretch",
49
+ ...(Platform.OS !== "web" ? { overflow: "hidden" as const } : null),
50
+ };
51
+ }
52
+
53
+ const defaultOutline = createOutlineStyle(colors.transparent);
54
+
55
+ export function getInputFieldStyles(state: InputVisualState): FieldStyleSet {
56
+ const containerBase: ViewStyle = {
57
+ borderRadius: radii.lg,
58
+ ...(Platform.OS !== "web" ? { overflow: "hidden" as const } : null),
45
59
  };
46
60
 
47
61
  switch (state) {
48
62
  case "disabled":
49
63
  return {
50
- outline: outlineBase,
64
+ outline: defaultOutline,
51
65
  container: {
66
+ ...containerBase,
52
67
  borderWidth: 1,
53
68
  borderColor: colors.stormGray50,
54
69
  backgroundColor: colors.stormGray50,
@@ -59,11 +74,9 @@ export function getInputFieldStyles(state: InputVisualState): FieldStyleSet {
59
74
  };
60
75
  case "error":
61
76
  return {
62
- outline: {
63
- ...outlineBase,
64
- backgroundColor: colors.inputOutlineError,
65
- },
77
+ outline: createOutlineStyle(colors.inputOutlineError),
66
78
  container: {
79
+ ...containerBase,
67
80
  borderWidth: 1,
68
81
  borderColor: colors.inputError,
69
82
  backgroundColor: colors.white,
@@ -74,11 +87,9 @@ export function getInputFieldStyles(state: InputVisualState): FieldStyleSet {
74
87
  };
75
88
  case "focused":
76
89
  return {
77
- outline: {
78
- ...outlineBase,
79
- backgroundColor: colors.inputOutlineFocus,
80
- },
90
+ outline: createOutlineStyle(colors.inputOutlineFocus),
81
91
  container: {
92
+ ...containerBase,
82
93
  borderWidth: 1,
83
94
  borderColor: colors.navy,
84
95
  backgroundColor: colors.white,
@@ -89,8 +100,9 @@ export function getInputFieldStyles(state: InputVisualState): FieldStyleSet {
89
100
  };
90
101
  default:
91
102
  return {
92
- outline: outlineBase,
103
+ outline: defaultOutline,
93
104
  container: {
105
+ ...containerBase,
94
106
  borderWidth: 1,
95
107
  borderColor: colors.stormGray50,
96
108
  backgroundColor: colors.white,
@@ -122,12 +134,15 @@ export const inputFieldMetrics = StyleSheet.create({
122
134
  fontFamily: fonts.sans,
123
135
  fontSize: fontSize.md,
124
136
  fontWeight: fontWeight.medium,
125
- lineHeight: fontSize.md,
137
+ lineHeight: Platform.OS === "web" ? fontSize.md : 20,
126
138
  paddingVertical: 0,
127
139
  paddingHorizontal: 0,
128
140
  margin: 0,
129
141
  borderWidth: 0,
130
142
  backgroundColor: colors.transparent,
143
+ ...(Platform.OS === "android"
144
+ ? { includeFontPadding: false }
145
+ : null),
131
146
  ...(Platform.OS === "web"
132
147
  ? ({
133
148
  height: "100%",
@@ -236,20 +236,20 @@ export const labelTypography = {
236
236
  letterSpacing: 0,
237
237
  } as const;
238
238
 
239
- /** Button label typography — matches Figma (SemiBold, 100% line-height). */
239
+ /** Button label typography — SemiBold; line-height slightly above 100% for RN clipping. */
240
240
  export const buttonTypography = {
241
241
  lg: {
242
242
  fontFamily: fonts.sans,
243
243
  fontSize: 14,
244
244
  fontWeight: fontWeight.semibold,
245
- lineHeight: 14,
245
+ lineHeight: 18,
246
246
  letterSpacing: 0,
247
247
  },
248
248
  sm: {
249
249
  fontFamily: fonts.sans,
250
250
  fontSize: 12,
251
251
  fontWeight: fontWeight.semibold,
252
- lineHeight: 12,
252
+ lineHeight: 16,
253
253
  letterSpacing: 0,
254
254
  },
255
255
  } as const;