@scripso-homepad/ui 0.4.1 → 0.4.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.
Files changed (86) hide show
  1. package/dist/{chunk-C7GHBVMM.js → chunk-66WR57JJ.js} +53 -10
  2. package/dist/chunk-66WR57JJ.js.map +1 -0
  3. package/dist/index.cjs +2297 -391
  4. package/dist/index.cjs.map +1 -1
  5. package/dist/index.d.cts +144 -2
  6. package/dist/index.d.ts +144 -2
  7. package/dist/index.js +1978 -96
  8. package/dist/index.js.map +1 -1
  9. package/dist/web/index.cjs +30411 -759
  10. package/dist/web/index.cjs.map +1 -1
  11. package/dist/web/index.css +78 -0
  12. package/dist/web/index.css.map +1 -0
  13. package/dist/web/index.d.cts +267 -6
  14. package/dist/web/index.d.ts +267 -6
  15. package/dist/web/index.js +30179 -601
  16. package/dist/web/index.js.map +1 -1
  17. package/package.json +5 -4
  18. package/src/components/Calendar.stories.tsx +337 -0
  19. package/src/components/Calendar.tsx +441 -0
  20. package/src/components/DatePicker.stories.tsx +219 -0
  21. package/src/components/DatePicker.tsx +366 -0
  22. package/src/components/Input.tsx +5 -1
  23. package/src/components/Select.stories.tsx +134 -0
  24. package/src/components/Select.tsx +462 -0
  25. package/src/css.d.ts +1 -0
  26. package/src/icons/CalendarIcon.tsx +28 -0
  27. package/src/icons/CalendarIcon.web.tsx +34 -0
  28. package/src/icons/ChevronDownIcon.tsx +11 -4
  29. package/src/icons/ChevronDownIcon.web.tsx +6 -4
  30. package/src/icons/ChevronNavIcons.tsx +44 -0
  31. package/src/icons/ChevronNavIcons.web.tsx +57 -0
  32. package/src/icons/LockIcon.tsx +30 -0
  33. package/src/icons/LockIcon.web.tsx +35 -0
  34. package/src/icons/calendarIconPaths.ts +2 -0
  35. package/src/icons/chevronDownPath.ts +1 -0
  36. package/src/icons/chevronNavPaths.ts +2 -0
  37. package/src/icons/lockIconPaths.ts +2 -0
  38. package/src/index.ts +43 -0
  39. package/src/theme/calendar.ts +357 -0
  40. package/src/theme/input.ts +16 -6
  41. package/src/theme/select.ts +249 -0
  42. package/src/utils/calendarDays.ts +273 -0
  43. package/src/utils/calendarLocaleContext.tsx +95 -0
  44. package/src/utils/calendarLocalization.ts +187 -0
  45. package/src/utils/countryDropdownScrollStyles.ts +53 -13
  46. package/src/utils/formatMultiSelectDisplay.ts +56 -0
  47. package/src/web/components/Badge.stories.tsx +43 -0
  48. package/src/web/components/Badge.tsx +35 -0
  49. package/src/web/components/Pagination.stories.tsx +78 -0
  50. package/src/web/components/Pagination.tsx +153 -0
  51. package/src/web/components/StatusBadge.tsx +20 -0
  52. package/src/web/components/Table.stories.tsx +415 -0
  53. package/src/web/components/Table.tsx +3 -0
  54. package/src/web/components/TableActionButton.tsx +67 -0
  55. package/src/web/components/TableActionsMenu.tsx +208 -0
  56. package/src/web/components/TableIconText.tsx +23 -0
  57. package/src/web/components/TableRowStatusActions.tsx +33 -0
  58. package/src/web/components/TableStatusActionsCell.tsx +29 -0
  59. package/src/web/components/pagination-utils.ts +39 -0
  60. package/src/web/components/table/DataTable.tsx +123 -0
  61. package/src/web/components/table/TablePrimitives.tsx +214 -0
  62. package/src/web/components/table/TableScrollArea.tsx +51 -0
  63. package/src/web/components/table/constants.ts +59 -0
  64. package/src/web/components/table/data-table-class-names.ts +26 -0
  65. package/src/web/components/table/index.ts +44 -0
  66. package/src/web/components/table/table-row-context.tsx +19 -0
  67. package/src/web/components/table/use-horizontal-scroll-state.ts +72 -0
  68. package/src/web/components/table-scroll.css +81 -0
  69. package/src/web/hooks/useOnClickOutside.ts +20 -5
  70. package/src/web/icons/TableMenuActivateIcon.tsx +27 -0
  71. package/src/web/icons/TableMenuCheckIcon.tsx +27 -0
  72. package/src/web/icons/TableMenuCloseIcon.tsx +27 -0
  73. package/src/web/icons/TableMenuEditIcon.tsx +27 -0
  74. package/src/web/icons/TableMenuInfoIcon.tsx +27 -0
  75. package/src/web/icons/TableMenuRefreshIcon.tsx +27 -0
  76. package/src/web/icons/TableMenuSuspendIcon.tsx +34 -0
  77. package/src/web/icons/TableMenuTrashIcon.tsx +27 -0
  78. package/src/web/icons/TableMoreIcon.tsx +41 -0
  79. package/src/web/icons/TableSortIcon.tsx +37 -0
  80. package/src/web/index.ts +74 -0
  81. package/src/web/layout/AppHeader.stories.tsx +2 -0
  82. package/src/web/layout/AppHeader.tsx +18 -14
  83. package/src/web/layout/DashboardLayout.stories.tsx +1 -0
  84. package/src/web/layout/DashboardLayout.tsx +8 -4
  85. package/src/web/layout/story-helpers.tsx +10 -2
  86. package/dist/chunk-C7GHBVMM.js.map +0 -1
@@ -0,0 +1,30 @@
1
+ import Svg, { Path } from "react-native-svg";
2
+
3
+ import { LOCK_ICON_PATH } from "./lockIconPaths";
4
+
5
+ export { LOCK_ICON_PATH } from "./lockIconPaths";
6
+
7
+ interface LockIconProps {
8
+ size?: number;
9
+ color?: string;
10
+ strokeWidth?: number;
11
+ }
12
+
13
+ /** Native — react-native-svg (peer dependency). */
14
+ export function LockIcon({
15
+ size = 20,
16
+ color = "#c7cdd1",
17
+ strokeWidth = 2,
18
+ }: LockIconProps) {
19
+ return (
20
+ <Svg width={size} height={size} viewBox="0 0 20 20" fill="none">
21
+ <Path
22
+ d={LOCK_ICON_PATH}
23
+ stroke={color}
24
+ strokeWidth={strokeWidth}
25
+ strokeLinecap="round"
26
+ strokeLinejoin="round"
27
+ />
28
+ </Svg>
29
+ );
30
+ }
@@ -0,0 +1,35 @@
1
+ import { LOCK_ICON_PATH } from "./lockIconPaths";
2
+
3
+ interface LockIconProps {
4
+ size?: number;
5
+ color?: string;
6
+ strokeWidth?: number;
7
+ }
8
+
9
+ /** Web / Storybook — plain SVG (no react-native-svg). */
10
+ export function LockIcon({
11
+ size = 20,
12
+ color = "#c7cdd1",
13
+ strokeWidth = 2,
14
+ }: LockIconProps) {
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={LOCK_ICON_PATH}
26
+ stroke={color}
27
+ strokeWidth={strokeWidth}
28
+ strokeLinecap="round"
29
+ strokeLinejoin="round"
30
+ />
31
+ </svg>
32
+ );
33
+ }
34
+
35
+ export { LOCK_ICON_PATH } from "./lockIconPaths";
@@ -0,0 +1,2 @@
1
+ export const CALENDAR_ICON_BODY_PATH =
2
+ "M6.66667 1.6665V4.99984M13.3333 1.6665V4.99984M2.5 8.33317H17.5M4.16667 3.33317H15.8333C16.7538 3.33317 17.5 4.07936 17.5 4.99984V16.6665C17.5 17.587 16.7538 18.3332 15.8333 18.3332H4.16667C3.24619 18.3332 2.5 17.587 2.5 16.6665V4.99984C2.5 4.07936 3.24619 3.33317 4.16667 3.33317Z";
@@ -1 +1,2 @@
1
1
  export const CHEVRON_DOWN_PATH = "M4 6L8 10L12 6";
2
+ export const CHEVRON_DOWN_PATH_20 = "M5 7.5L10 12.5L15 7.5";
@@ -0,0 +1,2 @@
1
+ export const CHEVRON_LEFT_PATH = "M12.5 15L7.5 10L12.5 5";
2
+ export const CHEVRON_RIGHT_PATH = "M7.5 15L12.5 10L7.5 5";
@@ -0,0 +1,2 @@
1
+ export const LOCK_ICON_PATH =
2
+ "M5.83333 8.33317V5.83317C5.83333 4.7281 6.27232 3.66829 7.05372 2.88689C7.83512 2.10549 8.89493 1.6665 10 1.6665C11.1051 1.6665 12.1649 2.10549 12.9463 2.88689C13.7277 3.66829 14.1667 4.7281 14.1667 5.83317V8.33317M10.8333 13.3332C10.8333 13.7934 10.4602 14.1665 10 14.1665C9.53976 14.1665 9.16667 13.7934 9.16667 13.3332C9.16667 12.8729 9.53976 12.4998 10 12.4998C10.4602 12.4998 10.8333 12.8729 10.8333 13.3332ZM4.16667 8.33317H15.8333C16.7538 8.33317 17.5 9.07936 17.5 9.99984V16.6665C17.5 17.587 16.7538 18.3332 15.8333 18.3332H4.16667C3.24619 18.3332 2.5 17.587 2.5 16.6665V9.99984C2.5 9.07936 3.24619 8.33317 4.16667 8.33317Z";
package/src/index.ts CHANGED
@@ -8,12 +8,53 @@ export type {
8
8
  export { Input } from "./components/Input";
9
9
  export type { InputProps } from "./components/Input";
10
10
 
11
+ export { Select } from "./components/Select";
12
+ export type {
13
+ MultipleSelectProps,
14
+ SelectOption,
15
+ SelectProps,
16
+ SingleSelectProps,
17
+ } from "./components/Select";
18
+
11
19
  export { PhoneInput } from "./components/PhoneInput";
12
20
  export type { PhoneInputProps } from "./components/PhoneInput";
13
21
 
14
22
  export { CountryCodeSelector } from "./components/CountryCodeSelector";
15
23
  export type { CountryCodeSelectorProps } from "./components/CountryCodeSelector";
16
24
 
25
+ export { Calendar } from "./components/Calendar";
26
+ export type {
27
+ CalendarLabels,
28
+ CalendarProps,
29
+ CalendarRangeProps,
30
+ CalendarSingleProps,
31
+ DateRange,
32
+ } from "./components/Calendar";
33
+ export { CalendarLocaleProvider, useCalendarLocale } from "./utils/calendarLocaleContext";
34
+ export {
35
+ calendarTranslations,
36
+ formatLocalizedCalendarMonthYear,
37
+ getCalendarMonthLabels,
38
+ getCalendarTranslations,
39
+ resolveCalendarLocale,
40
+ resolveWeekdayLabels,
41
+ } from "./utils/calendarLocalization";
42
+ export type { CalendarLocaleProviderProps } from "./utils/calendarLocaleContext";
43
+ export type {
44
+ CalendarLocale,
45
+ CalendarTranslations,
46
+ CalendarTranslationKey,
47
+ } from "./utils/calendarLocalization";
48
+
49
+ export { DatePicker } from "./components/DatePicker";
50
+ export type {
51
+ DatePickerProps,
52
+ DatePickerRangeProps,
53
+ DatePickerSingleProps,
54
+ } from "./components/DatePicker";
55
+
56
+ export { CalendarIcon } from "./icons/CalendarIcon";
57
+
17
58
  export {
18
59
  countries,
19
60
  defaultCountry,
@@ -24,6 +65,8 @@ export type { Country } from "./data/countries";
24
65
  export { Label } from "./components/Label";
25
66
  export type { LabelProps } from "./components/Label";
26
67
 
68
+ export { LockIcon } from "./icons/LockIcon";
69
+
27
70
  export {
28
71
  colors,
29
72
  brand,
@@ -0,0 +1,357 @@
1
+ import { Dimensions, Platform, StyleSheet, type TextStyle, type ViewStyle } from "react-native";
2
+ import { colors, fonts, fontSize, fontWeight, radii, spacing } from "./tokens";
3
+
4
+ export const CALENDAR_DROPDOWN_GAP = spacing.sm;
5
+ export const CALENDAR_PANEL_WIDTH = 296;
6
+ export const CALENDAR_PANEL_PADDING = spacing.md;
7
+ export const CALENDAR_PANEL_GAP = spacing.md;
8
+ export const CALENDAR_CONTENT_WIDTH =
9
+ CALENDAR_PANEL_WIDTH - CALENDAR_PANEL_PADDING * 2;
10
+ export const CALENDAR_HEADER_HEIGHT = 20;
11
+ export const CALENDAR_WEEKDAY_CELL_SIZE = 32;
12
+ export const CALENDAR_WEEKDAY_GAP = spacing.sm;
13
+ export const CALENDAR_WEEKDAY_RADIUS = 6;
14
+ export const CALENDAR_DAY_SIZE = CALENDAR_WEEKDAY_CELL_SIZE;
15
+ export const CALENDAR_DAY_GRID_WIDTH = CALENDAR_CONTENT_WIDTH;
16
+ export const CALENDAR_DAY_GAP_X = spacing.sm;
17
+ export const CALENDAR_DAY_GAP_Y = spacing.lg;
18
+ export const CALENDAR_DAY_ROWS = 6;
19
+ export const CALENDAR_DAY_GRID_HEIGHT =
20
+ CALENDAR_DAY_SIZE * CALENDAR_DAY_ROWS + CALENDAR_DAY_GAP_Y * (CALENDAR_DAY_ROWS - 1);
21
+ export const CALENDAR_PICKER_COLUMNS = 3;
22
+ export const CALENDAR_PICKER_ROWS = 4;
23
+ export const CALENDAR_YEARS_PER_PAGE = 12;
24
+ export const CALENDAR_PICKER_CELL_WIDTH =
25
+ (CALENDAR_DAY_GRID_WIDTH - CALENDAR_DAY_GAP_X * (CALENDAR_PICKER_COLUMNS - 1)) /
26
+ CALENDAR_PICKER_COLUMNS;
27
+ export const CALENDAR_PICKER_CELL_HEIGHT = 36;
28
+ export const CALENDAR_PICKER_BODY_HEIGHT =
29
+ CALENDAR_WEEKDAY_CELL_SIZE + CALENDAR_WEEKDAY_GAP + CALENDAR_DAY_GRID_HEIGHT;
30
+ export const CALENDAR_DAY_DOT_SIZE = 3;
31
+ export const CALENDAR_TODAY_TEXT_COLOR = "#082640";
32
+ export const CALENDAR_TODAY_DOT_COLOR = "#0033A0";
33
+ export const CALENDAR_NAV_ICON_SIZE = 20;
34
+ export const CALENDAR_NAV_ICON_COLOR = colors.stormGray850;
35
+ export const CALENDAR_FIELD_ICON_SIZE = 20;
36
+ export const CALENDAR_FIELD_WIDTH = CALENDAR_PANEL_WIDTH;
37
+ export const CALENDAR_FIELD_HEIGHT = 52;
38
+ export const CALENDAR_FIELD_PADDING = spacing.lg;
39
+ export const CALENDAR_FIELD_GAP = spacing.sm;
40
+ export const CALENDAR_FIELD_PLACEHOLDER_COLOR = colors.stormGray200;
41
+
42
+ /** @deprecated Use `CALENDAR_PANEL_WIDTH` */
43
+ export const CALENDAR_PANEL_MIN_WIDTH = CALENDAR_PANEL_WIDTH;
44
+
45
+ export const CALENDAR_PANEL_TOTAL_HEIGHT =
46
+ CALENDAR_PANEL_PADDING * 2 +
47
+ CALENDAR_HEADER_HEIGHT +
48
+ CALENDAR_PANEL_GAP * 2 +
49
+ CALENDAR_WEEKDAY_CELL_SIZE +
50
+ CALENDAR_DAY_GRID_HEIGHT;
51
+ export const CALENDAR_PANEL_HEIGHT = CALENDAR_PANEL_TOTAL_HEIGHT;
52
+
53
+ export const calendarLabelTypography = {
54
+ fontFamily: fonts.sans,
55
+ fontSize: fontSize.sm,
56
+ fontWeight: fontWeight.medium,
57
+ lineHeight: fontSize.sm,
58
+ letterSpacing: 0,
59
+ color: colors.slateBlue,
60
+ } as const;
61
+
62
+ export const calendarFieldTypography = {
63
+ fontFamily: fonts.sans,
64
+ fontSize: fontSize.md,
65
+ fontWeight: fontWeight.regular,
66
+ lineHeight: fontSize.md,
67
+ letterSpacing: 0,
68
+ textAlign: "left",
69
+ } as const;
70
+
71
+ export const calendarFieldPlaceholderTypography = {
72
+ ...calendarFieldTypography,
73
+ color: CALENDAR_FIELD_PLACEHOLDER_COLOR,
74
+ } as const;
75
+
76
+ export const calendarDropdownMetrics = StyleSheet.create({
77
+ panel: {
78
+ width: CALENDAR_PANEL_WIDTH,
79
+ height: CALENDAR_PANEL_HEIGHT,
80
+ borderRadius: radii.lg,
81
+ borderWidth: 1,
82
+ borderColor: colors.stormGray50,
83
+ backgroundColor: colors.white,
84
+ padding: CALENDAR_PANEL_PADDING,
85
+ gap: CALENDAR_PANEL_GAP,
86
+ overflow: "hidden",
87
+ flexDirection: "column",
88
+ opacity: 1,
89
+ ...(Platform.OS === "web"
90
+ ? ({
91
+ boxSizing: "border-box",
92
+ } as ViewStyle)
93
+ : null),
94
+ },
95
+ header: {
96
+ flexDirection: "row",
97
+ alignItems: "center",
98
+ justifyContent: "space-between",
99
+ height: CALENDAR_HEADER_HEIGHT,
100
+ minHeight: CALENDAR_HEADER_HEIGHT,
101
+ maxHeight: CALENDAR_HEADER_HEIGHT,
102
+ },
103
+ headerTitle: {
104
+ textAlign: "center",
105
+ fontFamily: fonts.sans,
106
+ fontSize: fontSize.md,
107
+ fontWeight: fontWeight.bold,
108
+ lineHeight: 18,
109
+ letterSpacing: 0,
110
+ color: colors.stormGray850,
111
+ },
112
+ headerTitlePressable: {
113
+ flex: 1,
114
+ alignItems: "center",
115
+ justifyContent: "center",
116
+ minHeight: CALENDAR_HEADER_HEIGHT,
117
+ },
118
+ navButton: {
119
+ width: CALENDAR_NAV_ICON_SIZE,
120
+ height: CALENDAR_NAV_ICON_SIZE,
121
+ alignItems: "center",
122
+ justifyContent: "center",
123
+ },
124
+ weekdayRow: {
125
+ flexDirection: "row",
126
+ gap: CALENDAR_WEEKDAY_GAP,
127
+ height: CALENDAR_WEEKDAY_CELL_SIZE,
128
+ minHeight: CALENDAR_WEEKDAY_CELL_SIZE,
129
+ maxHeight: CALENDAR_WEEKDAY_CELL_SIZE,
130
+ opacity: 1,
131
+ },
132
+ weekdayCell: {
133
+ width: CALENDAR_WEEKDAY_CELL_SIZE,
134
+ height: CALENDAR_WEEKDAY_CELL_SIZE,
135
+ borderRadius: CALENDAR_WEEKDAY_RADIUS,
136
+ padding: spacing.xs,
137
+ backgroundColor: colors.stormGray0,
138
+ alignItems: "center",
139
+ justifyContent: "center",
140
+ opacity: 1,
141
+ ...(Platform.OS === "web"
142
+ ? ({
143
+ boxSizing: "border-box",
144
+ } as ViewStyle)
145
+ : null),
146
+ },
147
+ weekdayLabel: {
148
+ fontFamily: fonts.sans,
149
+ fontSize: fontSize.sm,
150
+ fontWeight: fontWeight.regular,
151
+ lineHeight: fontSize.sm,
152
+ letterSpacing: 0,
153
+ textAlign: "center",
154
+ color: colors.stormGray300,
155
+ textTransform: "uppercase",
156
+ },
157
+ dayGrid: {
158
+ width: CALENDAR_DAY_GRID_WIDTH,
159
+ height: CALENDAR_DAY_GRID_HEIGHT,
160
+ flexDirection: "row",
161
+ flexWrap: "wrap",
162
+ columnGap: CALENDAR_DAY_GAP_X,
163
+ rowGap: CALENDAR_DAY_GAP_Y,
164
+ alignContent: "flex-start",
165
+ opacity: 1,
166
+ },
167
+ dayCell: {
168
+ width: CALENDAR_DAY_SIZE,
169
+ height: CALENDAR_DAY_SIZE,
170
+ minHeight: CALENDAR_DAY_SIZE,
171
+ maxHeight: CALENDAR_DAY_SIZE,
172
+ alignItems: "center",
173
+ justifyContent: "center",
174
+ borderRadius: CALENDAR_WEEKDAY_RADIUS,
175
+ padding: spacing.xs,
176
+ backgroundColor: colors.white,
177
+ opacity: 1,
178
+ position: "relative",
179
+ ...(Platform.OS === "web"
180
+ ? ({
181
+ boxSizing: "border-box",
182
+ } as ViewStyle)
183
+ : null),
184
+ },
185
+ dayCellPast: {
186
+ backgroundColor: colors.stormGray50,
187
+ },
188
+ dayCellSelected: {
189
+ backgroundColor: colors.navy,
190
+ },
191
+ dayLabel: {
192
+ fontFamily: fonts.sans,
193
+ fontSize: fontSize.md,
194
+ fontWeight: fontWeight.regular,
195
+ lineHeight: 18,
196
+ letterSpacing: 0,
197
+ textAlign: "center",
198
+ color: colors.navy,
199
+ includeFontPadding: false,
200
+ textAlignVertical: "center",
201
+ },
202
+ dayLabelToday: {
203
+ color: CALENDAR_TODAY_TEXT_COLOR,
204
+ },
205
+ dayLabelSelected: {
206
+ fontWeight: fontWeight.semibold,
207
+ color: colors.white,
208
+ },
209
+ dayLabelFuture: {
210
+ color: colors.navy,
211
+ },
212
+ dayLabelMuted: {
213
+ color: colors.stormGray300,
214
+ },
215
+ dayLabelOutsideMonth: {
216
+ color: colors.stormGray300,
217
+ },
218
+ dayLabelDisabled: {
219
+ color: colors.stormGray300,
220
+ opacity: 0.5,
221
+ },
222
+ todayDot: {
223
+ position: "absolute",
224
+ bottom: 5,
225
+ left: "50%",
226
+ width: CALENDAR_DAY_DOT_SIZE,
227
+ height: CALENDAR_DAY_DOT_SIZE,
228
+ borderRadius: 15,
229
+ backgroundColor: CALENDAR_TODAY_DOT_COLOR,
230
+ marginLeft: -(CALENDAR_DAY_DOT_SIZE / 2),
231
+ zIndex: 1,
232
+ },
233
+ pickerBody: {
234
+ width: CALENDAR_DAY_GRID_WIDTH,
235
+ height: CALENDAR_PICKER_BODY_HEIGHT,
236
+ justifyContent: "center",
237
+ },
238
+ pickerGrid: {
239
+ width: CALENDAR_DAY_GRID_WIDTH,
240
+ flexDirection: "row",
241
+ flexWrap: "wrap",
242
+ columnGap: CALENDAR_DAY_GAP_X,
243
+ rowGap: CALENDAR_DAY_GAP_Y,
244
+ alignContent: "flex-start",
245
+ },
246
+ pickerCell: {
247
+ width: CALENDAR_PICKER_CELL_WIDTH,
248
+ minHeight: CALENDAR_PICKER_CELL_HEIGHT,
249
+ alignItems: "center",
250
+ justifyContent: "center",
251
+ borderRadius: CALENDAR_WEEKDAY_RADIUS,
252
+ paddingHorizontal: spacing.xs,
253
+ paddingVertical: spacing.xs,
254
+ backgroundColor: colors.white,
255
+ ...(Platform.OS === "web"
256
+ ? ({
257
+ boxSizing: "border-box",
258
+ } as ViewStyle)
259
+ : null),
260
+ },
261
+ pickerCellSelected: {
262
+ backgroundColor: colors.navy,
263
+ },
264
+ pickerLabel: {
265
+ fontFamily: fonts.sans,
266
+ fontSize: fontSize.md,
267
+ fontWeight: fontWeight.regular,
268
+ lineHeight: 18,
269
+ letterSpacing: 0,
270
+ textAlign: "center",
271
+ color: colors.navy,
272
+ includeFontPadding: false,
273
+ ...(Platform.OS === "android" ? { textAlignVertical: "center" as const } : null),
274
+ },
275
+ pickerLabelSelected: {
276
+ fontWeight: fontWeight.semibold,
277
+ color: colors.white,
278
+ },
279
+ pickerLabelDisabled: {
280
+ color: colors.stormGray300,
281
+ opacity: 0.5,
282
+ },
283
+ pickerLabelCurrent: {
284
+ color: CALENDAR_TODAY_TEXT_COLOR,
285
+ },
286
+ });
287
+
288
+ export function resolveCalendarDropdownTop(
289
+ anchor: { y: number; height: number },
290
+ panelHeight: number = CALENDAR_PANEL_HEIGHT,
291
+ ): number {
292
+ const windowHeight = Dimensions.get("window").height;
293
+ const spaceBelow = windowHeight - (anchor.y + anchor.height + CALENDAR_DROPDOWN_GAP);
294
+ const spaceAbove = anchor.y - CALENDAR_DROPDOWN_GAP;
295
+ const topBelow = anchor.y + anchor.height + CALENDAR_DROPDOWN_GAP;
296
+ const topAbove = anchor.y - CALENDAR_DROPDOWN_GAP - panelHeight;
297
+
298
+ if (spaceBelow >= panelHeight) {
299
+ return topBelow;
300
+ }
301
+
302
+ if (spaceAbove >= panelHeight) {
303
+ return topAbove;
304
+ }
305
+
306
+ if (spaceAbove > spaceBelow) {
307
+ return Math.max(0, topAbove);
308
+ }
309
+
310
+ return Math.max(0, Math.min(topBelow, windowHeight - panelHeight));
311
+ }
312
+
313
+ export function resolveCalendarDropdownLeft(
314
+ anchor: { x: number },
315
+ panelWidth: number = CALENDAR_PANEL_WIDTH,
316
+ ): number {
317
+ const windowWidth = Dimensions.get("window").width;
318
+ const maxLeft = Math.max(0, windowWidth - panelWidth);
319
+
320
+ return Math.max(0, Math.min(anchor.x, maxLeft));
321
+ }
322
+
323
+ export const calendarFieldMetrics = StyleSheet.create({
324
+ container: {
325
+ flexDirection: "row",
326
+ alignItems: "center",
327
+ width: CALENDAR_FIELD_WIDTH,
328
+ minWidth: CALENDAR_FIELD_WIDTH,
329
+ maxWidth: CALENDAR_FIELD_WIDTH,
330
+ height: CALENDAR_FIELD_HEIGHT,
331
+ minHeight: CALENDAR_FIELD_HEIGHT,
332
+ maxHeight: CALENDAR_FIELD_HEIGHT,
333
+ borderRadius: radii.lg,
334
+ padding: CALENDAR_FIELD_PADDING,
335
+ gap: CALENDAR_FIELD_GAP,
336
+ opacity: 1,
337
+ ...(Platform.OS === "web"
338
+ ? ({
339
+ boxSizing: "border-box",
340
+ } as ViewStyle)
341
+ : null),
342
+ },
343
+ value: {
344
+ flex: 1,
345
+ minWidth: 0,
346
+ ...calendarFieldTypography,
347
+ paddingVertical: 0,
348
+ paddingHorizontal: 0,
349
+ margin: 0,
350
+ ...(Platform.OS === "android" ? { includeFontPadding: false } : null),
351
+ ...(Platform.OS === "web"
352
+ ? ({
353
+ outlineStyle: "none",
354
+ } as TextStyle)
355
+ : null),
356
+ },
357
+ });
@@ -5,6 +5,10 @@ export const INPUT_HEIGHT = 52;
5
5
  export const INPUT_ICON_SIZE = 20;
6
6
  export const INPUT_ICON_GAP = 10;
7
7
  export const INPUT_OUTLINE_WIDTH = 2;
8
+ /** Native line box; web uses a taller metric for Noto Sans Armenian descenders. */
9
+ export const INPUT_INNER_LINE_HEIGHT = 20;
10
+ export const INPUT_WEB_INNER_LINE_HEIGHT = 22;
11
+ export const INPUT_WEB_VERTICAL_PADDING = 14;
8
12
 
9
13
  export type InputVisualState =
10
14
  | "default"
@@ -125,16 +129,20 @@ export const inputFieldMetrics = StyleSheet.create({
125
129
  padding: 16,
126
130
  gap: INPUT_ICON_GAP,
127
131
  ...(Platform.OS === "web"
128
- ? ({ boxSizing: "border-box" } as ViewStyle)
132
+ ? ({
133
+ boxSizing: "border-box",
134
+ paddingVertical: INPUT_WEB_VERTICAL_PADDING,
135
+ paddingHorizontal: 16,
136
+ } as ViewStyle)
129
137
  : null),
130
138
  },
131
139
  input: {
132
140
  flex: 1,
133
- alignSelf: "stretch",
141
+ minWidth: 0,
134
142
  fontFamily: fonts.sans,
135
143
  fontSize: fontSize.md,
136
144
  fontWeight: fontWeight.medium,
137
- lineHeight: Platform.OS === "web" ? fontSize.md : 20,
145
+ lineHeight: INPUT_INNER_LINE_HEIGHT,
138
146
  paddingVertical: 0,
139
147
  paddingHorizontal: 0,
140
148
  margin: 0,
@@ -145,10 +153,12 @@ export const inputFieldMetrics = StyleSheet.create({
145
153
  : null),
146
154
  ...(Platform.OS === "web"
147
155
  ? ({
148
- height: "100%",
149
- minHeight: 0,
156
+ alignSelf: "center",
157
+ lineHeight: INPUT_WEB_INNER_LINE_HEIGHT,
150
158
  outlineStyle: "none",
151
159
  } as TextStyle)
152
- : null),
160
+ : {
161
+ alignSelf: "stretch",
162
+ }),
153
163
  },
154
164
  });