@ecohouse/ui 0.1.0

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 ADDED
@@ -0,0 +1,58 @@
1
+ # eco-cottage-ui (`@ecohouse/ui`)
2
+
3
+ Presentation-only universal UI package for EcoHouse customer web and mobile.
4
+
5
+ ## Purpose
6
+
7
+ Reusable design tokens and cross-platform components built with **React Native primitives** + **React Native Web**, documented in Storybook.
8
+
9
+ ## Package rules (MUST)
10
+
11
+ This package is **presentation-only**:
12
+
13
+ - No backend API clients
14
+ - No application secrets
15
+ - No provider SDKs
16
+ - No EcoHouse booking / domain business logic
17
+
18
+ Application routes, API calls, and booking logic stay in `eco-cottage-web` and `eco-cottage-mobile`. Consumers install published npm versions only (exact pin in `package-lock.json`).
19
+
20
+ ## Stack (Architecture v1.4 §§4.4, 5)
21
+
22
+ | Area | Technology |
23
+ | ------------- | ----------------------------------------- |
24
+ | Package | TypeScript, tsup |
25
+ | UI | React Native primitives, React Native Web |
26
+ | Docs | Storybook |
27
+ | Lint / format | ESLint, Prettier |
28
+ | Tests | Vitest |
29
+ | Commits | Conventional Commits (commitlint + husky) |
30
+
31
+ ## Current exports
32
+
33
+ | Export | Description |
34
+ | ------------------ | --------------------------------------------------------- |
35
+ | `Button` | Primary actions with variants, sizes, optional icon badge |
36
+ | Design tokens | `colors`, typography, spacing, radii, shadows |
37
+ | `ArrowUpRightIcon` | Default button badge icon |
38
+
39
+ ## Scripts
40
+
41
+ ```bash
42
+ npm ci
43
+ npm run lint
44
+ npm run format:check
45
+ npm run typecheck
46
+ npm test
47
+ npm run build
48
+ npm run storybook
49
+ npm run build-storybook
50
+ ```
51
+
52
+ ## Branch model
53
+
54
+ `feature/*` (or ticket branches such as `E0-1-ui/bootstrap-repo`) → `development` → `staging` → `main`
55
+
56
+ ## Out of scope for E0-1
57
+
58
+ npm publishing / semantic-release / consumer update PRs (E0-3-ui), full component set, consumer app integration.
package/dist/index.cjs ADDED
@@ -0,0 +1,502 @@
1
+ 'use strict';
2
+
3
+ var react = require('react');
4
+ var reactNative = require('react-native');
5
+ var Svg = require('react-native-svg');
6
+ var jsxRuntime = require('react/jsx-runtime');
7
+
8
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
9
+
10
+ var Svg__default = /*#__PURE__*/_interopDefault(Svg);
11
+
12
+ // src/components/Button.tsx
13
+
14
+ // src/icons/arrowUpRightPath.ts
15
+ var ARROW_UP_RIGHT_PATH = "M14.1667 14.1668V5.8335H5.83333M14.1667 5.8335L5.83333 14.1668";
16
+ function ArrowUpRightIcon({
17
+ size = 20,
18
+ color = "#082640",
19
+ strokeWidth = 2
20
+ }) {
21
+ return /* @__PURE__ */ jsxRuntime.jsx(Svg__default.default, { width: size, height: size, viewBox: "0 0 20 20", fill: "none", children: /* @__PURE__ */ jsxRuntime.jsx(
22
+ Svg.Path,
23
+ {
24
+ d: ARROW_UP_RIGHT_PATH,
25
+ stroke: color,
26
+ strokeWidth,
27
+ strokeLinecap: "round",
28
+ strokeLinejoin: "round"
29
+ }
30
+ ) });
31
+ }
32
+
33
+ // src/theme/tokens.ts
34
+ var stormGray = {
35
+ "0": "#fbfcfc",
36
+ "0.5": "#eceef0",
37
+ "1": "#dadde0",
38
+ "1.5": "#c7cdd1",
39
+ "2": "#b5bcc1",
40
+ "3": "#8f9aa3",
41
+ "4": "#6a7984",
42
+ "5": "#455765",
43
+ "6": "#374651",
44
+ "7": "#29343d",
45
+ "8": "#1c2328",
46
+ "8.5": "#151a1e"
47
+ };
48
+ var navy = {
49
+ "0": "#f6fafe",
50
+ "0.5": "#dee5eb",
51
+ "1": "#c6d0d8",
52
+ "1.5": "#afbac5",
53
+ "2": "#97a5b2",
54
+ "3": "#677b8c",
55
+ "4": "#385066",
56
+ "5": "#082640",
57
+ "6": "#061e33",
58
+ "7": "#051726",
59
+ "8": "#030f1a",
60
+ "8.5": "#020b13"
61
+ };
62
+ var rubyRed = {
63
+ "0": "#fff5f6",
64
+ "0.5": "#f7dddf",
65
+ "1": "#efc4c8",
66
+ "1.5": "#e7acb1",
67
+ "2": "#df939a",
68
+ "3": "#ce626d",
69
+ "4": "#be313f",
70
+ "5": "#ae0011",
71
+ "6": "#8b000e",
72
+ "7": "#68000a",
73
+ "8": "#460007",
74
+ "8.5": "#340005"
75
+ };
76
+ var emeraldGreen = {
77
+ "0": "#f0fbf5",
78
+ "0.5": "#dcf2e5",
79
+ "1": "#c8e8d5",
80
+ "1.5": "#b4dfc5",
81
+ "2": "#a0d5b5",
82
+ "3": "#77c394",
83
+ "4": "#4fb074",
84
+ "5": "#279d54",
85
+ "6": "#1f7e43",
86
+ "7": "#175e32",
87
+ "8": "#103f22",
88
+ "8.5": "#0c2f19"
89
+ };
90
+ var brand = {
91
+ slateBlue: "#182e3c",
92
+ stormGray: stormGray["5"],
93
+ navy: navy["5"],
94
+ rubyRed: rubyRed["5"],
95
+ emeraldGreen: emeraldGreen["5"]
96
+ };
97
+ var colors = {
98
+ // Brand colors
99
+ slateBlue: brand.slateBlue,
100
+ // Emerald Green — Figma scale + brand swatch
101
+ emeraldGreen0: emeraldGreen["0"],
102
+ emeraldGreen50: emeraldGreen["0.5"],
103
+ emeraldGreen100: emeraldGreen["1"],
104
+ emeraldGreen150: emeraldGreen["1.5"],
105
+ emeraldGreen200: emeraldGreen["2"],
106
+ emeraldGreen300: emeraldGreen["3"],
107
+ emeraldGreen400: emeraldGreen["4"],
108
+ emeraldGreen500: emeraldGreen["5"],
109
+ emeraldGreen600: emeraldGreen["6"],
110
+ emeraldGreen700: emeraldGreen["7"],
111
+ emeraldGreen800: emeraldGreen["8"],
112
+ emeraldGreen850: emeraldGreen["8.5"],
113
+ /** Primary brand emerald green — Figma Emerald Green 5 */
114
+ emeraldGreen: brand.emeraldGreen,
115
+ // Ruby Red — Figma scale + brand swatch
116
+ rubyRed0: rubyRed["0"],
117
+ rubyRed50: rubyRed["0.5"],
118
+ rubyRed100: rubyRed["1"],
119
+ rubyRed150: rubyRed["1.5"],
120
+ rubyRed200: rubyRed["2"],
121
+ rubyRed300: rubyRed["3"],
122
+ rubyRed400: rubyRed["4"],
123
+ rubyRed500: rubyRed["5"],
124
+ rubyRed600: rubyRed["6"],
125
+ rubyRed700: rubyRed["7"],
126
+ rubyRed800: rubyRed["8"],
127
+ rubyRed850: rubyRed["8.5"],
128
+ /** Primary brand ruby red — Figma Ruby Red 5 */
129
+ rubyRed: brand.rubyRed,
130
+ // Navy — Figma scale + brand swatch
131
+ navy0: navy["0"],
132
+ navy50: navy["0.5"],
133
+ navy100: navy["1"],
134
+ navy150: navy["1.5"],
135
+ navy200: navy["2"],
136
+ navy300: navy["3"],
137
+ navy400: navy["4"],
138
+ navy500: navy["5"],
139
+ navy600: navy["6"],
140
+ navy700: navy["7"],
141
+ navy800: navy["8"],
142
+ navy850: navy["8.5"],
143
+ /** Primary brand navy — Figma Navy 5 */
144
+ navy: brand.navy,
145
+ // Storm Gray — Figma scale + brand swatch
146
+ stormGray0: stormGray["0"],
147
+ stormGray50: stormGray["0.5"],
148
+ stormGray100: stormGray["1"],
149
+ stormGray150: stormGray["1.5"],
150
+ stormGray200: stormGray["2"],
151
+ stormGray300: stormGray["3"],
152
+ stormGray400: stormGray["4"],
153
+ stormGray500: stormGray["5"],
154
+ /** Figma brand swatch "Storm Gray" — same as `stormGray500` */
155
+ stormGrayBrand: brand.stormGray,
156
+ stormGray600: stormGray["6"],
157
+ stormGray700: stormGray["7"],
158
+ stormGray800: stormGray["8"],
159
+ stormGray850: stormGray["8.5"],
160
+ /** @deprecated Use `stormGray0` */
161
+ storm0: stormGray["0"],
162
+ /** @deprecated Use `stormGray50` */
163
+ storm50: stormGray["0.5"],
164
+ /** @deprecated Use `stormGray200` */
165
+ storm200: stormGray["2"],
166
+ /** @deprecated Use `stormGray300` */
167
+ storm300: stormGray["3"],
168
+ /** @deprecated Use `stormGray500` */
169
+ storm500: stormGray["5"],
170
+ /** @deprecated Use `stormGray700` */
171
+ storm700: stormGray["7"],
172
+ /** @deprecated Use `stormGray850` */
173
+ storm900: stormGray["8.5"],
174
+ countrySelectorSelectedBg: `${stormGray["0.5"]}99`,
175
+ white: "#ffffff",
176
+ error: "#dc2626",
177
+ errorDark: "#b3261e",
178
+ errorLight: "#fee2e2",
179
+ /** @deprecated Use `rubyRed` */
180
+ inputError: brand.rubyRed,
181
+ inputOutlineFocus: navy["0.5"],
182
+ inputOutlineError: rubyRed["0.5"],
183
+ warning: "#92400e",
184
+ warningBg: "#fef3c7",
185
+ success: "#28a745",
186
+ successMuted: "#9fd4a8",
187
+ /** @deprecated Use `emeraldGreen` */
188
+ green: brand.emeraldGreen,
189
+ transparent: "transparent"
190
+ };
191
+ var radii = {
192
+ sm: 8,
193
+ md: 12,
194
+ lg: 16,
195
+ xl: 20,
196
+ full: 9999
197
+ };
198
+ var spacing = {
199
+ xs: 4,
200
+ sm: 8,
201
+ md: 12,
202
+ lg: 16,
203
+ xl: 24,
204
+ xxl: 32
205
+ };
206
+ var fontSize = {
207
+ xs: 11,
208
+ sm: 12,
209
+ md: 14,
210
+ base: 16,
211
+ lg: 18,
212
+ xl: 24,
213
+ xxl: 32
214
+ };
215
+ var typographyScale = {
216
+ 12: { fontSize: 12, lineHeight: 16 },
217
+ 14: { fontSize: 14, lineHeight: 19 },
218
+ 18: { fontSize: 18, lineHeight: 24 },
219
+ 20: { fontSize: 20, lineHeight: 27 },
220
+ 24: { fontSize: 24, lineHeight: 25 },
221
+ 32: { fontSize: 32, lineHeight: 34 }
222
+ };
223
+ var fontWeight = {
224
+ regular: "400",
225
+ medium: "500",
226
+ semibold: "600",
227
+ bold: "700"
228
+ };
229
+ var fonts = {
230
+ sans: "Noto Sans Armenian"
231
+ };
232
+ var labelTypography = {
233
+ fontFamily: fonts.sans,
234
+ fontSize: typographyScale[12].fontSize,
235
+ fontWeight: fontWeight.medium,
236
+ lineHeight: typographyScale[12].lineHeight,
237
+ letterSpacing: 0
238
+ };
239
+ var buttonTypography = {
240
+ lg: {
241
+ fontFamily: fonts.sans,
242
+ fontSize: typographyScale[14].fontSize,
243
+ fontWeight: fontWeight.semibold,
244
+ lineHeight: typographyScale[14].lineHeight,
245
+ letterSpacing: 0
246
+ },
247
+ sm: {
248
+ fontFamily: fonts.sans,
249
+ fontSize: typographyScale[12].fontSize,
250
+ fontWeight: fontWeight.semibold,
251
+ lineHeight: typographyScale[12].lineHeight,
252
+ letterSpacing: 0
253
+ }
254
+ };
255
+ var shadows = {
256
+ card: {
257
+ shadowColor: colors.navy,
258
+ shadowOffset: { width: 0, height: 4 },
259
+ shadowOpacity: 0.05,
260
+ shadowRadius: 20,
261
+ elevation: 2
262
+ },
263
+ cardLg: {
264
+ shadowColor: colors.navy,
265
+ shadowOffset: { width: 0, height: 4 },
266
+ shadowOpacity: 0.1,
267
+ shadowRadius: 20,
268
+ elevation: 4
269
+ }
270
+ };
271
+ function hasClassList(node) {
272
+ return typeof node === "object" && node !== null && "classList" in node && typeof node.classList?.add === "function";
273
+ }
274
+ function resolveWebElement(ref) {
275
+ const node = ref.current;
276
+ if (!node) return null;
277
+ if (hasClassList(node)) return node;
278
+ const host = node;
279
+ if (hasClassList(host._touchableNode)) return host._touchableNode;
280
+ if (typeof host.getScrollableNode === "function") {
281
+ const scrollNode = host.getScrollableNode();
282
+ if (hasClassList(scrollNode)) return scrollNode;
283
+ }
284
+ return null;
285
+ }
286
+ function useApplyWebClassName(ref, className, enabled = true) {
287
+ react.useLayoutEffect(() => {
288
+ if (!enabled || reactNative.Platform.OS !== "web" || !className?.trim()) return;
289
+ let cancelled = false;
290
+ let rafId = 0;
291
+ let appliedElement = null;
292
+ const classes = className.trim().split(/\s+/);
293
+ const apply = () => {
294
+ if (cancelled) return;
295
+ const element = resolveWebElement(ref);
296
+ if (!element) {
297
+ rafId = requestAnimationFrame(apply);
298
+ return;
299
+ }
300
+ appliedElement = element;
301
+ element.classList.add(...classes);
302
+ };
303
+ apply();
304
+ return () => {
305
+ cancelled = true;
306
+ if (rafId) cancelAnimationFrame(rafId);
307
+ appliedElement?.classList.remove(...classes);
308
+ };
309
+ }, [ref, className, enabled]);
310
+ }
311
+ var variantConfig = {
312
+ white: {
313
+ backgroundColor: colors.white,
314
+ textColor: colors.slateBlue,
315
+ iconBadgeBackgroundColor: colors.stormGray150,
316
+ iconColor: colors.navy
317
+ },
318
+ primary: {
319
+ backgroundColor: colors.navy,
320
+ textColor: colors.stormGray0,
321
+ iconBadgeBackgroundColor: colors.white,
322
+ iconColor: colors.navy
323
+ },
324
+ green: {
325
+ backgroundColor: colors.green,
326
+ textColor: colors.stormGray0,
327
+ iconBadgeBackgroundColor: colors.white,
328
+ iconColor: colors.green
329
+ },
330
+ gray: {
331
+ backgroundColor: colors.stormGray50,
332
+ textColor: colors.slateBlue,
333
+ iconBadgeBackgroundColor: colors.stormGray150,
334
+ iconColor: colors.navy
335
+ }
336
+ };
337
+ var sizeConfig = {
338
+ lg: {
339
+ /** Matches Tailwind `h-13` so size stays stable before web classNames attach. */
340
+ minHeight: 52,
341
+ borderRadius: 16,
342
+ paddingTop: 8,
343
+ paddingRight: 8,
344
+ paddingBottom: 8,
345
+ paddingLeft: 24,
346
+ paddingHorizontalCentered: 24,
347
+ text: buttonTypography.lg,
348
+ iconContainerSize: 36,
349
+ iconContainerRadius: 12,
350
+ iconContainerPadding: 8,
351
+ iconSize: 20
352
+ },
353
+ sm: {
354
+ minHeight: 40,
355
+ borderRadius: 12,
356
+ paddingTop: 8,
357
+ paddingRight: 8,
358
+ paddingBottom: 8,
359
+ paddingLeft: 16,
360
+ paddingHorizontalCentered: 16,
361
+ text: buttonTypography.sm,
362
+ iconContainerSize: 32,
363
+ iconContainerRadius: 8,
364
+ iconContainerPadding: 8,
365
+ iconSize: 16
366
+ }
367
+ };
368
+ function Button({
369
+ title,
370
+ children,
371
+ onPress,
372
+ disabled = false,
373
+ variant = "primary",
374
+ size = "lg",
375
+ showIcon = false,
376
+ icon,
377
+ style,
378
+ textStyle,
379
+ className,
380
+ textClassName
381
+ }) {
382
+ const containerRef = react.useRef(null);
383
+ const textRef = react.useRef(null);
384
+ const preset = variantConfig[variant];
385
+ const metrics = sizeConfig[size];
386
+ const label = typeof children !== "undefined" ? children : title;
387
+ const hasCustomChildren = typeof children !== "undefined";
388
+ const customIcon = icon != null && typeof icon !== "boolean" ? icon : void 0;
389
+ const hasIcon = showIcon || icon === true || customIcon != null;
390
+ const resolvedContainerClassName = [reactNative.Platform.OS === "web" ? "max-md:px-4!" : "", className].filter(Boolean).join(" ");
391
+ useApplyWebClassName(containerRef, resolvedContainerClassName || void 0);
392
+ useApplyWebClassName(textRef, textClassName);
393
+ const iconNode = customIcon ?? /* @__PURE__ */ jsxRuntime.jsx(ArrowUpRightIcon, { size: metrics.iconSize, color: preset.iconColor });
394
+ const containerStyle = [
395
+ styles.base,
396
+ {
397
+ minHeight: metrics.minHeight,
398
+ borderRadius: metrics.borderRadius,
399
+ backgroundColor: preset.backgroundColor,
400
+ paddingTop: metrics.paddingTop,
401
+ paddingBottom: metrics.paddingBottom,
402
+ paddingLeft: hasIcon ? metrics.paddingLeft : metrics.paddingHorizontalCentered,
403
+ paddingRight: hasIcon ? metrics.paddingRight : metrics.paddingHorizontalCentered
404
+ },
405
+ hasIcon ? styles.withIcon : styles.centered,
406
+ disabled && styles.disabled,
407
+ style
408
+ ];
409
+ const labelStyle = [
410
+ styles.label,
411
+ metrics.text,
412
+ { color: preset.textColor },
413
+ reactNative.Platform.OS === "android" ? styles.labelAndroid : null,
414
+ !hasIcon && styles.labelCentered,
415
+ hasIcon && styles.labelWithIcon,
416
+ textStyle
417
+ ];
418
+ return /* @__PURE__ */ jsxRuntime.jsxs(
419
+ reactNative.TouchableOpacity,
420
+ {
421
+ ref: containerRef,
422
+ style: containerStyle,
423
+ onPress,
424
+ disabled,
425
+ activeOpacity: 0.7,
426
+ accessibilityRole: "button",
427
+ accessibilityState: { disabled },
428
+ children: [
429
+ hasCustomChildren ? children : /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { ref: textRef, style: labelStyle, children: label }),
430
+ hasIcon ? /* @__PURE__ */ jsxRuntime.jsx(
431
+ reactNative.View,
432
+ {
433
+ style: [
434
+ styles.iconContainer,
435
+ {
436
+ width: metrics.iconContainerSize,
437
+ height: metrics.iconContainerSize,
438
+ borderRadius: metrics.iconContainerRadius,
439
+ padding: metrics.iconContainerPadding,
440
+ backgroundColor: preset.iconBadgeBackgroundColor
441
+ }
442
+ ],
443
+ children: iconNode
444
+ }
445
+ ) : null
446
+ ]
447
+ }
448
+ );
449
+ }
450
+ var styles = reactNative.StyleSheet.create({
451
+ base: {
452
+ flexDirection: "row",
453
+ alignItems: "center",
454
+ borderWidth: 0
455
+ },
456
+ centered: {
457
+ justifyContent: "center"
458
+ },
459
+ withIcon: {
460
+ justifyContent: "space-between"
461
+ },
462
+ disabled: {
463
+ opacity: 0.6
464
+ },
465
+ label: {},
466
+ labelAndroid: {
467
+ includeFontPadding: false
468
+ },
469
+ labelCentered: {
470
+ textAlign: "center"
471
+ },
472
+ labelWithIcon: {
473
+ flex: 1,
474
+ flexShrink: 1,
475
+ marginRight: 8
476
+ },
477
+ iconContainer: {
478
+ alignItems: "center",
479
+ justifyContent: "center",
480
+ flexShrink: 0
481
+ }
482
+ });
483
+
484
+ exports.ArrowUpRightIcon = ArrowUpRightIcon;
485
+ exports.Button = Button;
486
+ exports.brand = brand;
487
+ exports.buttonTypography = buttonTypography;
488
+ exports.colors = colors;
489
+ exports.emeraldGreen = emeraldGreen;
490
+ exports.fontSize = fontSize;
491
+ exports.fontWeight = fontWeight;
492
+ exports.fonts = fonts;
493
+ exports.labelTypography = labelTypography;
494
+ exports.navy = navy;
495
+ exports.radii = radii;
496
+ exports.rubyRed = rubyRed;
497
+ exports.shadows = shadows;
498
+ exports.spacing = spacing;
499
+ exports.stormGray = stormGray;
500
+ exports.typographyScale = typographyScale;
501
+ //# sourceMappingURL=index.cjs.map
502
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/icons/arrowUpRightPath.ts","../src/icons/ArrowUpRightIcon.tsx","../src/theme/tokens.ts","../src/utils/useApplyWebClassName.ts","../src/components/Button.tsx"],"names":["jsx","Svg","Path","useLayoutEffect","Platform","useRef","jsxs","TouchableOpacity","Text","View","StyleSheet"],"mappings":"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","file":"index.cjs","sourcesContent":["export const ARROW_UP_RIGHT_PATH = \"M14.1667 14.1668V5.8335H5.83333M14.1667 5.8335L5.83333 14.1668\";\n","import Svg, { Path } from \"react-native-svg\";\nimport { ARROW_UP_RIGHT_PATH } from \"./arrowUpRightPath\";\n\nexport { ARROW_UP_RIGHT_PATH } from \"./arrowUpRightPath\";\n\ninterface ArrowUpRightIconProps {\n size?: number;\n color?: string;\n strokeWidth?: number;\n}\n\n/** Native — react-native-svg (peer dependency). */\nexport function ArrowUpRightIcon({\n size = 20,\n color = \"#082640\",\n strokeWidth = 2,\n}: ArrowUpRightIconProps) {\n return (\n <Svg width={size} height={size} viewBox=\"0 0 20 20\" fill=\"none\">\n <Path\n d={ARROW_UP_RIGHT_PATH}\n stroke={color}\n strokeWidth={strokeWidth}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </Svg>\n );\n}\n","/**\n * EcoHouse design tokens — aligned with the shared design system\n * (navy / storm gray / slate-blue palette).\n */\n\n/** Storm Gray scale — Figma steps 0 → 8.5 */\nexport const stormGray = {\n \"0\": \"#fbfcfc\",\n \"0.5\": \"#eceef0\",\n \"1\": \"#dadde0\",\n \"1.5\": \"#c7cdd1\",\n \"2\": \"#b5bcc1\",\n \"3\": \"#8f9aa3\",\n \"4\": \"#6a7984\",\n \"5\": \"#455765\",\n \"6\": \"#374651\",\n \"7\": \"#29343d\",\n \"8\": \"#1c2328\",\n \"8.5\": \"#151a1e\",\n} as const;\n\nexport type StormGrayStep = keyof typeof stormGray;\n\n/** Navy scale — Figma steps 0 → 8.5 */\nexport const navy = {\n \"0\": \"#f6fafe\",\n \"0.5\": \"#dee5eb\",\n \"1\": \"#c6d0d8\",\n \"1.5\": \"#afbac5\",\n \"2\": \"#97a5b2\",\n \"3\": \"#677b8c\",\n \"4\": \"#385066\",\n \"5\": \"#082640\",\n \"6\": \"#061e33\",\n \"7\": \"#051726\",\n \"8\": \"#030f1a\",\n \"8.5\": \"#020b13\",\n} as const;\n\nexport type NavyStep = keyof typeof navy;\n\n/** Ruby Red scale — Figma steps 0 → 8.5 */\nexport const rubyRed = {\n \"0\": \"#fff5f6\",\n \"0.5\": \"#f7dddf\",\n \"1\": \"#efc4c8\",\n \"1.5\": \"#e7acb1\",\n \"2\": \"#df939a\",\n \"3\": \"#ce626d\",\n \"4\": \"#be313f\",\n \"5\": \"#ae0011\",\n \"6\": \"#8b000e\",\n \"7\": \"#68000a\",\n \"8\": \"#460007\",\n \"8.5\": \"#340005\",\n} as const;\n\nexport type RubyRedStep = keyof typeof rubyRed;\n\n/** Emerald Green scale — Figma steps 0 → 8.5 */\nexport const emeraldGreen = {\n \"0\": \"#f0fbf5\",\n \"0.5\": \"#dcf2e5\",\n \"1\": \"#c8e8d5\",\n \"1.5\": \"#b4dfc5\",\n \"2\": \"#a0d5b5\",\n \"3\": \"#77c394\",\n \"4\": \"#4fb074\",\n \"5\": \"#279d54\",\n \"6\": \"#1f7e43\",\n \"7\": \"#175e32\",\n \"8\": \"#103f22\",\n \"8.5\": \"#0c2f19\",\n} as const;\n\nexport type EmeraldGreenStep = keyof typeof emeraldGreen;\n\n/** Figma brand palette — primary swatch per color family */\nexport const brand = {\n slateBlue: \"#182e3c\",\n stormGray: stormGray[\"5\"],\n navy: navy[\"5\"],\n rubyRed: rubyRed[\"5\"],\n emeraldGreen: emeraldGreen[\"5\"],\n} as const;\n\nexport const colors = {\n // Brand colors\n slateBlue: brand.slateBlue,\n\n // Emerald Green — Figma scale + brand swatch\n emeraldGreen0: emeraldGreen[\"0\"],\n emeraldGreen50: emeraldGreen[\"0.5\"],\n emeraldGreen100: emeraldGreen[\"1\"],\n emeraldGreen150: emeraldGreen[\"1.5\"],\n emeraldGreen200: emeraldGreen[\"2\"],\n emeraldGreen300: emeraldGreen[\"3\"],\n emeraldGreen400: emeraldGreen[\"4\"],\n emeraldGreen500: emeraldGreen[\"5\"],\n emeraldGreen600: emeraldGreen[\"6\"],\n emeraldGreen700: emeraldGreen[\"7\"],\n emeraldGreen800: emeraldGreen[\"8\"],\n emeraldGreen850: emeraldGreen[\"8.5\"],\n\n /** Primary brand emerald green — Figma Emerald Green 5 */\n emeraldGreen: brand.emeraldGreen,\n\n // Ruby Red — Figma scale + brand swatch\n rubyRed0: rubyRed[\"0\"],\n rubyRed50: rubyRed[\"0.5\"],\n rubyRed100: rubyRed[\"1\"],\n rubyRed150: rubyRed[\"1.5\"],\n rubyRed200: rubyRed[\"2\"],\n rubyRed300: rubyRed[\"3\"],\n rubyRed400: rubyRed[\"4\"],\n rubyRed500: rubyRed[\"5\"],\n rubyRed600: rubyRed[\"6\"],\n rubyRed700: rubyRed[\"7\"],\n rubyRed800: rubyRed[\"8\"],\n rubyRed850: rubyRed[\"8.5\"],\n\n /** Primary brand ruby red — Figma Ruby Red 5 */\n rubyRed: brand.rubyRed,\n\n // Navy — Figma scale + brand swatch\n navy0: navy[\"0\"],\n navy50: navy[\"0.5\"],\n navy100: navy[\"1\"],\n navy150: navy[\"1.5\"],\n navy200: navy[\"2\"],\n navy300: navy[\"3\"],\n navy400: navy[\"4\"],\n navy500: navy[\"5\"],\n navy600: navy[\"6\"],\n navy700: navy[\"7\"],\n navy800: navy[\"8\"],\n navy850: navy[\"8.5\"],\n\n /** Primary brand navy — Figma Navy 5 */\n navy: brand.navy,\n\n // Storm Gray — Figma scale + brand swatch\n stormGray0: stormGray[\"0\"],\n stormGray50: stormGray[\"0.5\"],\n stormGray100: stormGray[\"1\"],\n stormGray150: stormGray[\"1.5\"],\n stormGray200: stormGray[\"2\"],\n stormGray300: stormGray[\"3\"],\n stormGray400: stormGray[\"4\"],\n stormGray500: stormGray[\"5\"],\n /** Figma brand swatch \"Storm Gray\" — same as `stormGray500` */\n stormGrayBrand: brand.stormGray,\n stormGray600: stormGray[\"6\"],\n stormGray700: stormGray[\"7\"],\n stormGray800: stormGray[\"8\"],\n stormGray850: stormGray[\"8.5\"],\n\n /** @deprecated Use `stormGray0` */\n storm0: stormGray[\"0\"],\n /** @deprecated Use `stormGray50` */\n storm50: stormGray[\"0.5\"],\n /** @deprecated Use `stormGray200` */\n storm200: stormGray[\"2\"],\n /** @deprecated Use `stormGray300` */\n storm300: stormGray[\"3\"],\n /** @deprecated Use `stormGray500` */\n storm500: stormGray[\"5\"],\n /** @deprecated Use `stormGray700` */\n storm700: stormGray[\"7\"],\n /** @deprecated Use `stormGray850` */\n storm900: stormGray[\"8.5\"],\n\n countrySelectorSelectedBg: `${stormGray[\"0.5\"]}99`,\n\n white: \"#ffffff\",\n error: \"#dc2626\",\n errorDark: \"#b3261e\",\n errorLight: \"#fee2e2\",\n /** @deprecated Use `rubyRed` */\n inputError: brand.rubyRed,\n inputOutlineFocus: navy[\"0.5\"],\n inputOutlineError: rubyRed[\"0.5\"],\n warning: \"#92400e\",\n warningBg: \"#fef3c7\",\n success: \"#28a745\",\n successMuted: \"#9fd4a8\",\n /** @deprecated Use `emeraldGreen` */\n green: brand.emeraldGreen,\n transparent: \"transparent\",\n} as const;\n\nexport const radii = {\n sm: 8,\n md: 12,\n lg: 16,\n xl: 20,\n full: 9999,\n} as const;\n\nexport const spacing = {\n xs: 4,\n sm: 8,\n md: 12,\n lg: 16,\n xl: 24,\n xxl: 32,\n} as const;\n\nexport const fontSize = {\n xs: 11,\n sm: 12,\n md: 14,\n base: 16,\n lg: 18,\n xl: 24,\n xxl: 32,\n} as const;\n\n/**\n * Canonical Homepad type scale (matches `.typography-*` in `src/web/styles/typography.css`).\n * font-size / line-height pairs:\n * 12/16 · 14/19 · 18/24 · 20/27 · 24/25 · 32/34\n */\nexport const typographyScale = {\n 12: { fontSize: 12, lineHeight: 16 },\n 14: { fontSize: 14, lineHeight: 19 },\n 18: { fontSize: 18, lineHeight: 24 },\n 20: { fontSize: 20, lineHeight: 27 },\n 24: { fontSize: 24, lineHeight: 25 },\n 32: { fontSize: 32, lineHeight: 34 },\n} as const;\n\nexport const fontWeight = {\n regular: \"400\" as const,\n medium: \"500\" as const,\n semibold: \"600\" as const,\n bold: \"700\" as const,\n};\n\nexport const fonts = {\n sans: \"Noto Sans Armenian\",\n} as const;\n\n/** Input label typography — Medium, typography-12 scale. */\nexport const labelTypography = {\n fontFamily: fonts.sans,\n fontSize: typographyScale[12].fontSize,\n fontWeight: fontWeight.medium,\n lineHeight: typographyScale[12].lineHeight,\n letterSpacing: 0,\n} as const;\n\n/** Button label typography — SemiBold. */\nexport const buttonTypography = {\n lg: {\n fontFamily: fonts.sans,\n fontSize: typographyScale[14].fontSize,\n fontWeight: fontWeight.semibold,\n lineHeight: typographyScale[14].lineHeight,\n letterSpacing: 0,\n },\n sm: {\n fontFamily: fonts.sans,\n fontSize: typographyScale[12].fontSize,\n fontWeight: fontWeight.semibold,\n lineHeight: typographyScale[12].lineHeight,\n letterSpacing: 0,\n },\n} as const;\n\nexport const shadows = {\n card: {\n shadowColor: colors.navy,\n shadowOffset: { width: 0, height: 4 },\n shadowOpacity: 0.05,\n shadowRadius: 20,\n elevation: 2,\n },\n cardLg: {\n shadowColor: colors.navy,\n shadowOffset: { width: 0, height: 4 },\n shadowOpacity: 0.1,\n shadowRadius: 20,\n elevation: 4,\n },\n} as const;\n","import { useLayoutEffect } from \"react\";\nimport { Platform } from \"react-native\";\n\ninterface ClassListElement {\n classList: {\n add: (...classes: string[]) => void;\n remove: (...classes: string[]) => void;\n };\n}\n\nfunction hasClassList(node: unknown): node is ClassListElement {\n return (\n typeof node === \"object\" &&\n node !== null &&\n \"classList\" in node &&\n typeof (node as ClassListElement).classList?.add === \"function\"\n );\n}\n\nfunction resolveWebElement(ref: React.RefObject<unknown>): ClassListElement | null {\n const node = ref.current;\n if (!node) return null;\n\n if (hasClassList(node)) return node;\n\n const host = node as {\n _touchableNode?: unknown;\n getScrollableNode?: () => unknown;\n };\n\n if (hasClassList(host._touchableNode)) return host._touchableNode;\n\n if (typeof host.getScrollableNode === \"function\") {\n const scrollNode = host.getScrollableNode();\n if (hasClassList(scrollNode)) return scrollNode;\n }\n\n return null;\n}\n\n/**\n * Applies CSS class names to the underlying DOM node on web.\n * Keeps TouchableOpacity/Text as the render path so default RN styles stay intact.\n *\n * Retries via rAF when the host node is not ready yet — otherwise classes like\n * `h-13` / `w-full` would only land after a later re-render (e.g. typing in a form),\n * which visibly changes button size.\n */\nexport function useApplyWebClassName(\n ref: React.RefObject<unknown>,\n className?: string,\n enabled = true,\n): void {\n useLayoutEffect(() => {\n if (!enabled || Platform.OS !== \"web\" || !className?.trim()) return;\n\n let cancelled = false;\n let rafId = 0;\n let appliedElement: ClassListElement | null = null;\n const classes = className.trim().split(/\\s+/);\n\n const apply = () => {\n if (cancelled) return;\n\n const element = resolveWebElement(ref);\n if (!element) {\n rafId = requestAnimationFrame(apply);\n return;\n }\n\n appliedElement = element;\n element.classList.add(...classes);\n };\n\n apply();\n\n return () => {\n cancelled = true;\n if (rafId) cancelAnimationFrame(rafId);\n appliedElement?.classList.remove(...classes);\n };\n }, [ref, className, enabled]);\n}\n","import { useRef, type ComponentRef, type ReactNode } from \"react\";\nimport {\n Platform,\n StyleSheet,\n Text,\n TouchableOpacity,\n View,\n type GestureResponderEvent,\n type StyleProp,\n type TextStyle,\n type ViewStyle,\n} from \"react-native\";\nimport { ArrowUpRightIcon } from \"../icons/ArrowUpRightIcon\";\nimport { colors, buttonTypography } from \"../theme/tokens\";\nimport { useApplyWebClassName } from \"../utils/useApplyWebClassName\";\n\nexport type ButtonVariant = \"white\" | \"primary\" | \"green\" | \"gray\";\nexport type ButtonSize = \"lg\" | \"sm\";\n\nexport interface ButtonProps {\n title?: string;\n children?: ReactNode;\n onPress: (event: GestureResponderEvent) => void;\n disabled?: boolean;\n variant?: ButtonVariant;\n size?: ButtonSize;\n showIcon?: boolean;\n /** Custom icon inside the badge. Defaults to `ArrowUpRightIcon` when `showIcon` is true. */\n icon?: ReactNode;\n style?: StyleProp<ViewStyle>;\n textStyle?: StyleProp<TextStyle>;\n className?: string;\n textClassName?: string;\n}\n\ntype VariantStyleSet = {\n backgroundColor: string;\n textColor: string;\n iconBadgeBackgroundColor: string;\n iconColor: string;\n};\n\nconst variantConfig: Record<ButtonVariant, VariantStyleSet> = {\n white: {\n backgroundColor: colors.white,\n textColor: colors.slateBlue,\n iconBadgeBackgroundColor: colors.stormGray150,\n iconColor: colors.navy,\n },\n primary: {\n backgroundColor: colors.navy,\n textColor: colors.stormGray0,\n iconBadgeBackgroundColor: colors.white,\n iconColor: colors.navy,\n },\n green: {\n backgroundColor: colors.green,\n textColor: colors.stormGray0,\n iconBadgeBackgroundColor: colors.white,\n iconColor: colors.green,\n },\n gray: {\n backgroundColor: colors.stormGray50,\n textColor: colors.slateBlue,\n iconBadgeBackgroundColor: colors.stormGray150,\n iconColor: colors.navy,\n },\n};\n\nconst sizeConfig = {\n lg: {\n /** Matches Tailwind `h-13` so size stays stable before web classNames attach. */\n minHeight: 52,\n borderRadius: 16,\n paddingTop: 8,\n paddingRight: 8,\n paddingBottom: 8,\n paddingLeft: 24,\n paddingHorizontalCentered: 24,\n text: buttonTypography.lg,\n iconContainerSize: 36,\n iconContainerRadius: 12,\n iconContainerPadding: 8,\n iconSize: 20,\n },\n sm: {\n minHeight: 40,\n borderRadius: 12,\n paddingTop: 8,\n paddingRight: 8,\n paddingBottom: 8,\n paddingLeft: 16,\n paddingHorizontalCentered: 16,\n text: buttonTypography.sm,\n iconContainerSize: 32,\n iconContainerRadius: 8,\n iconContainerPadding: 8,\n iconSize: 16,\n },\n} as const;\n\nexport function Button({\n title,\n children,\n onPress,\n disabled = false,\n variant = \"primary\",\n size = \"lg\",\n showIcon = false,\n icon,\n style,\n textStyle,\n className,\n textClassName,\n}: ButtonProps) {\n const containerRef = useRef<ComponentRef<typeof TouchableOpacity>>(null);\n const textRef = useRef<ComponentRef<typeof Text>>(null);\n const preset = variantConfig[variant];\n const metrics = sizeConfig[size];\n\n const label = typeof children !== \"undefined\" ? children : title;\n const hasCustomChildren = typeof children !== \"undefined\";\n const customIcon = icon != null && typeof icon !== \"boolean\" ? icon : undefined;\n const hasIcon = showIcon || icon === true || customIcon != null;\n const resolvedContainerClassName = [Platform.OS === \"web\" ? \"max-md:px-4!\" : \"\", className]\n .filter(Boolean)\n .join(\" \");\n\n useApplyWebClassName(containerRef, resolvedContainerClassName || undefined);\n useApplyWebClassName(textRef, textClassName);\n\n const iconNode = customIcon ?? (\n <ArrowUpRightIcon size={metrics.iconSize} color={preset.iconColor} />\n );\n\n const containerStyle = [\n styles.base,\n {\n minHeight: metrics.minHeight,\n borderRadius: metrics.borderRadius,\n backgroundColor: preset.backgroundColor,\n paddingTop: metrics.paddingTop,\n paddingBottom: metrics.paddingBottom,\n paddingLeft: hasIcon ? metrics.paddingLeft : metrics.paddingHorizontalCentered,\n paddingRight: hasIcon ? metrics.paddingRight : metrics.paddingHorizontalCentered,\n },\n hasIcon ? styles.withIcon : styles.centered,\n disabled && styles.disabled,\n style,\n ];\n\n const labelStyle = [\n styles.label,\n metrics.text,\n { color: preset.textColor },\n Platform.OS === \"android\" ? styles.labelAndroid : null,\n !hasIcon && styles.labelCentered,\n hasIcon && styles.labelWithIcon,\n textStyle,\n ];\n\n return (\n <TouchableOpacity\n ref={containerRef}\n style={containerStyle}\n onPress={onPress}\n disabled={disabled}\n activeOpacity={0.7}\n accessibilityRole=\"button\"\n accessibilityState={{ disabled }}\n >\n {hasCustomChildren ? (\n children\n ) : (\n <Text ref={textRef} style={labelStyle}>\n {label}\n </Text>\n )}\n\n {hasIcon ? (\n <View\n style={[\n styles.iconContainer,\n {\n width: metrics.iconContainerSize,\n height: metrics.iconContainerSize,\n borderRadius: metrics.iconContainerRadius,\n padding: metrics.iconContainerPadding,\n backgroundColor: preset.iconBadgeBackgroundColor,\n },\n ]}\n >\n {iconNode}\n </View>\n ) : null}\n </TouchableOpacity>\n );\n}\n\nconst styles = StyleSheet.create({\n base: {\n flexDirection: \"row\",\n alignItems: \"center\",\n borderWidth: 0,\n },\n centered: {\n justifyContent: \"center\",\n },\n withIcon: {\n justifyContent: \"space-between\",\n },\n disabled: {\n opacity: 0.6,\n },\n label: {},\n labelAndroid: {\n includeFontPadding: false,\n },\n labelCentered: {\n textAlign: \"center\",\n },\n labelWithIcon: {\n flex: 1,\n flexShrink: 1,\n marginRight: 8,\n },\n iconContainer: {\n alignItems: \"center\",\n justifyContent: \"center\",\n flexShrink: 0,\n },\n});\n"]}