@sincpro/mobile-ui 0.7.2 → 1.0.1

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 (270) hide show
  1. package/README.md +7 -5
  2. package/dist/Actions/Actions.Button.d.ts +91 -91
  3. package/dist/Actions/Actions.Button.js +36 -43
  4. package/dist/Actions/Actions.FAB.js +5 -5
  5. package/dist/Actions/Actions.FilterButton.js +3 -3
  6. package/dist/Actions/Actions.IconButton.d.ts +31 -31
  7. package/dist/Actions/Actions.IconButton.js +4 -4
  8. package/dist/Actions/index.d.ts +11 -11
  9. package/dist/Actions/index.js +5 -5
  10. package/dist/Dialog/BottomSheet/BottomSheet.Root.js +1 -1
  11. package/dist/Dialog/BottomSheet/index.d.ts +1 -1
  12. package/dist/Dialog/BottomSheet/index.js +1 -1
  13. package/dist/Dialog/Confirmation.context.js +3 -3
  14. package/dist/Dialog/Dialog.ActionSheet.js +6 -6
  15. package/dist/Dialog/Dialog.Confirmation.js +4 -4
  16. package/dist/Dialog/Dialog.EditValue.js +4 -4
  17. package/dist/Dialog/Dialog.Sheet.js +6 -4
  18. package/dist/Dialog/index.d.ts +5 -5
  19. package/dist/Dialog/index.js +5 -5
  20. package/dist/Display/Display.Accordion.js +5 -5
  21. package/dist/Display/Display.Avatar.d.ts +30 -30
  22. package/dist/Display/Display.Avatar.js +2 -2
  23. package/dist/Display/Display.AvatarGroup.js +3 -3
  24. package/dist/Display/Display.Badge.d.ts +3 -3
  25. package/dist/Display/Display.Badge.js +1 -1
  26. package/dist/Display/Display.Card.d.ts +15 -15
  27. package/dist/Display/Display.Card.js +4 -4
  28. package/dist/Display/Display.Carousel.js +2 -2
  29. package/dist/Display/Display.Chip.d.ts +3 -3
  30. package/dist/Display/Display.Chip.js +12 -12
  31. package/dist/Display/Display.CircleButton.d.ts +1 -1
  32. package/dist/Display/Display.CircleButton.js +3 -3
  33. package/dist/Display/Display.CopyableText.js +2 -2
  34. package/dist/Display/Display.CountRecords.js +2 -2
  35. package/dist/Display/Display.DataTable.js +2 -2
  36. package/dist/Display/Display.Date.d.ts +1 -1
  37. package/dist/Display/Display.Date.js +5 -5
  38. package/dist/Display/Display.Divider.d.ts +24 -24
  39. package/dist/Display/Display.Divider.js +1 -1
  40. package/dist/Display/Display.GradientSurface.d.ts +58 -39
  41. package/dist/Display/Display.GradientSurface.js +31 -15
  42. package/dist/Display/Display.Icon.d.ts +1 -1
  43. package/dist/Display/Display.Icon.js +1 -1
  44. package/dist/Display/Display.IconBadge.js +3 -3
  45. package/dist/Display/Display.Image.js +4 -4
  46. package/dist/Display/Display.KeyValue.js +2 -2
  47. package/dist/Display/Display.ListItem.js +5 -5
  48. package/dist/Display/Display.Logo.d.ts +3 -3
  49. package/dist/Display/Display.Logo.js +2 -2
  50. package/dist/Display/Display.MediaCard.js +4 -4
  51. package/dist/Display/Display.MediaEmbed.js +7 -7
  52. package/dist/Display/Display.MenuButton.d.ts +4 -4
  53. package/dist/Display/Display.MenuButton.js +6 -6
  54. package/dist/Display/Display.MenuCard.d.ts +1 -1
  55. package/dist/Display/Display.MenuCard.js +3 -3
  56. package/dist/Display/Display.MenuGrid.d.ts +1 -1
  57. package/dist/Display/Display.MenuGrid.js +1 -1
  58. package/dist/Display/Display.Monetary.d.ts +1 -1
  59. package/dist/Display/Display.Monetary.js +2 -2
  60. package/dist/Display/Display.Pattern.d.ts +33 -12
  61. package/dist/Display/Display.Pattern.js +60 -14
  62. package/dist/Display/Display.PriceTag.js +2 -2
  63. package/dist/Display/Display.ProductCard.js +7 -7
  64. package/dist/Display/Display.Rating.js +3 -3
  65. package/dist/Display/Display.SearchHistory.js +6 -6
  66. package/dist/Display/Display.SectionHeader.js +4 -4
  67. package/dist/Display/Display.Stat.js +2 -2
  68. package/dist/Display/Display.StatCard.js +4 -4
  69. package/dist/Display/Display.StatusDot.js +3 -3
  70. package/dist/Display/Display.Story.js +3 -3
  71. package/dist/Display/Display.StoryTray.js +5 -5
  72. package/dist/Display/Display.StoryViewer.js +4 -4
  73. package/dist/Display/Display.SwipeableRow.js +4 -4
  74. package/dist/Display/Display.Tag.js +2 -2
  75. package/dist/Display/Display.Timeline.js +4 -4
  76. package/dist/Display/Display.Tooltip.js +3 -3
  77. package/dist/Display/index.d.ts +45 -45
  78. package/dist/Display/index.js +42 -42
  79. package/dist/Feedback/ErrorBoundary.d.ts +1 -1
  80. package/dist/Feedback/ErrorBoundary.js +1 -1
  81. package/dist/Feedback/Feedback.Banner.d.ts +3 -3
  82. package/dist/Feedback/Feedback.Banner.js +5 -5
  83. package/dist/Feedback/Feedback.DomainSplashScreen.js +5 -4
  84. package/dist/Feedback/Feedback.Empty.js +3 -3
  85. package/dist/Feedback/Feedback.EmptyState.js +5 -5
  86. package/dist/Feedback/Feedback.Error.js +4 -4
  87. package/dist/Feedback/Feedback.Loading.d.ts +1 -1
  88. package/dist/Feedback/Feedback.Loading.js +2 -2
  89. package/dist/Feedback/Feedback.PermissionCard.js +5 -5
  90. package/dist/Feedback/Feedback.Progress.js +2 -2
  91. package/dist/Feedback/Feedback.ProgressCircle.js +1 -1
  92. package/dist/Feedback/Feedback.Skeleton.js +2 -2
  93. package/dist/Feedback/Feedback.Spinner.js +3 -3
  94. package/dist/Feedback/Feedback.Splash.d.ts +1 -1
  95. package/dist/Feedback/Feedback.Splash.js +7 -6
  96. package/dist/Feedback/Toast.context.js +7 -7
  97. package/dist/Feedback/index.d.ts +13 -13
  98. package/dist/Feedback/index.js +13 -13
  99. package/dist/Form/Form.Button.d.ts +2 -2
  100. package/dist/Form/Form.Button.js +1 -1
  101. package/dist/Form/Form.Checkbox.js +4 -4
  102. package/dist/Form/Form.ControlledCheckbox.js +1 -1
  103. package/dist/Form/Form.ControlledInput.js +1 -1
  104. package/dist/Form/Form.ControlledMonetaryInput.js +1 -1
  105. package/dist/Form/Form.ControlledRadioButton.js +1 -1
  106. package/dist/Form/Form.DatePicker.js +5 -5
  107. package/dist/Form/Form.Dropdown.js +7 -7
  108. package/dist/Form/Form.FAB.d.ts +2 -2
  109. package/dist/Form/Form.FAB.js +1 -1
  110. package/dist/Form/Form.FilterButton.d.ts +2 -2
  111. package/dist/Form/Form.FilterButton.js +1 -1
  112. package/dist/Form/Form.FractionalQuantityInput.js +4 -4
  113. package/dist/Form/Form.IconButton.d.ts +2 -2
  114. package/dist/Form/Form.IconButton.js +1 -1
  115. package/dist/Form/Form.Input.js +4 -4
  116. package/dist/Form/Form.InputField.d.ts +1 -1
  117. package/dist/Form/Form.InputField.js +3 -3
  118. package/dist/Form/Form.MonetaryInput.js +5 -4
  119. package/dist/Form/Form.PasswordInput.d.ts +1 -1
  120. package/dist/Form/Form.PasswordInput.js +3 -3
  121. package/dist/Form/Form.PinInput.js +5 -5
  122. package/dist/Form/Form.QuantitySelector.js +3 -3
  123. package/dist/Form/Form.RadioButton.js +4 -4
  124. package/dist/Form/Form.SearchBar.js +4 -4
  125. package/dist/Form/Form.Select.js +6 -6
  126. package/dist/Form/Form.Slider.js +3 -3
  127. package/dist/Form/Form.Switch.js +4 -4
  128. package/dist/Form/Form.TextInput.js +3 -3
  129. package/dist/Form/index.d.ts +27 -27
  130. package/dist/Form/index.js +25 -25
  131. package/dist/Navigation/Navigation.AppBar.d.ts +5 -4
  132. package/dist/Navigation/Navigation.AppBar.js +10 -10
  133. package/dist/Navigation/Navigation.BottomNav.d.ts +1 -1
  134. package/dist/Navigation/Navigation.BottomNav.js +25 -16
  135. package/dist/Navigation/Navigation.CollapsingHeader.d.ts +1 -1
  136. package/dist/Navigation/Navigation.CollapsingHeader.js +3 -3
  137. package/dist/Navigation/Navigation.FloatingBar.js +2 -2
  138. package/dist/Navigation/Navigation.Header.js +6 -6
  139. package/dist/Navigation/Navigation.HeaderToolbar.js +5 -5
  140. package/dist/Navigation/Navigation.Menu.js +6 -6
  141. package/dist/Navigation/Navigation.MenuSection.js +2 -2
  142. package/dist/Navigation/Navigation.RowItem.d.ts +1 -1
  143. package/dist/Navigation/Navigation.RowItem.js +2 -2
  144. package/dist/Navigation/Navigation.SearchBar.js +6 -6
  145. package/dist/Navigation/Navigation.SegmentedControl.js +4 -4
  146. package/dist/Navigation/Navigation.Steps.js +5 -5
  147. package/dist/Navigation/Navigation.TabIcon.js +2 -2
  148. package/dist/Navigation/Navigation.TabItem.js +2 -2
  149. package/dist/Navigation/Navigation.Tabs.js +5 -5
  150. package/dist/Navigation/index.d.ts +19 -19
  151. package/dist/Navigation/index.js +15 -15
  152. package/dist/Typography/Typography.Heading.d.ts +1 -1
  153. package/dist/Typography/Typography.Heading.js +1 -1
  154. package/dist/Typography/Typography.Text.d.ts +2 -2
  155. package/dist/Typography/Typography.Text.js +8 -6
  156. package/dist/Typography/index.d.ts +2 -2
  157. package/dist/Typography/index.js +2 -2
  158. package/dist/branding.d.ts +22 -0
  159. package/dist/branding.js +20 -3
  160. package/dist/icons/AddItemIcon.d.ts +1 -1
  161. package/dist/icons/ArrangeCircle.d.ts +1 -1
  162. package/dist/icons/ArrowDownIcon.d.ts +1 -1
  163. package/dist/icons/ArrowUpIcon.d.ts +1 -1
  164. package/dist/icons/BoxIcon.d.ts +1 -1
  165. package/dist/icons/BoxTimeIcon.d.ts +1 -1
  166. package/dist/icons/CalendarIcon.d.ts +1 -1
  167. package/dist/icons/CardIcon.d.ts +1 -1
  168. package/dist/icons/CashierIcon.d.ts +1 -1
  169. package/dist/icons/DuoIcon.d.ts +1 -1
  170. package/dist/icons/HomeIcon.d.ts +1 -1
  171. package/dist/icons/HomeIconOutlined.d.ts +1 -1
  172. package/dist/icons/LogoIcon.d.ts +1 -1
  173. package/dist/icons/MoneyReceiveIcon.d.ts +1 -1
  174. package/dist/icons/PinIcon.d.ts +1 -1
  175. package/dist/icons/PrinterIcon.d.ts +1 -1
  176. package/dist/icons/ProfileIcon.d.ts +1 -1
  177. package/dist/icons/SettingsIcon.d.ts +1 -1
  178. package/dist/icons/SinpeIcon.d.ts +1 -1
  179. package/dist/icons/ToggleOffIcon.d.ts +1 -1
  180. package/dist/icons/WalletMoneyIcon.d.ts +1 -1
  181. package/dist/index.d.ts +24 -23
  182. package/dist/index.js +26 -24
  183. package/dist/layouts/AuthContainer.d.ts +5 -2
  184. package/dist/layouts/AuthContainer.js +6 -6
  185. package/dist/layouts/Container.js +1 -1
  186. package/dist/layouts/GradientContainer.js +1 -1
  187. package/dist/layouts/ScrollContainer.js +1 -1
  188. package/dist/layouts/TabNavigatorLayout.js +4 -4
  189. package/dist/primitives/AspectRatio.js +1 -1
  190. package/dist/primitives/BaseButton.d.ts +85 -85
  191. package/dist/primitives/BaseButton.js +34 -50
  192. package/dist/primitives/Box.js +1 -1
  193. package/dist/primitives/Pressable.js +1 -1
  194. package/dist/primitives/Row.js +1 -1
  195. package/dist/primitives/Stack.js +1 -1
  196. package/dist/primitives/index.d.ts +6 -6
  197. package/dist/primitives/index.js +6 -6
  198. package/dist/theme/active.d.ts +1 -1
  199. package/dist/theme/active.js +14 -1
  200. package/dist/theme/build.d.ts +33 -0
  201. package/dist/theme/build.js +118 -0
  202. package/dist/theme/color.d.ts +26 -0
  203. package/dist/theme/color.js +109 -0
  204. package/dist/theme/components/index.d.ts +1 -1
  205. package/dist/theme/components/index.js +1 -1
  206. package/dist/theme/contrast.d.ts +29 -0
  207. package/dist/theme/contrast.js +57 -0
  208. package/dist/theme/css-vars.d.ts +3 -1
  209. package/dist/theme/css-vars.js +29 -3
  210. package/dist/theme/dark.d.ts +3 -4
  211. package/dist/theme/dark.js +91 -48
  212. package/dist/theme/default.d.ts +5 -1
  213. package/dist/theme/default.js +89 -41
  214. package/dist/theme/define.d.ts +4 -1
  215. package/dist/theme/define.js +4 -1
  216. package/dist/theme/globals.css +61 -46
  217. package/dist/theme/index.d.ts +14 -10
  218. package/dist/theme/index.js +13 -9
  219. package/dist/theme/theme.d.ts +1 -1
  220. package/dist/theme/theme.js +2 -2
  221. package/dist/theme/types.d.ts +77 -16
  222. package/dist/theme/types.js +13 -3
  223. package/dist/theme/typography.d.ts +4 -4
  224. package/dist/theme/typography.js +26 -28
  225. package/dist/theme/useTheme.d.ts +1 -1
  226. package/dist/theme/useTheme.js +1 -1
  227. package/dist/theme/validate.d.ts +16 -0
  228. package/dist/theme/validate.js +200 -0
  229. package/dist/tokens/index.d.ts +2 -2
  230. package/dist/tokens/index.js +2 -2
  231. package/dist/views/AppSplashView.d.ts +2 -2
  232. package/dist/views/AppSplashView.js +3 -3
  233. package/dist/views/AuthFormView.d.ts +1 -1
  234. package/dist/views/AuthFormView.js +3 -3
  235. package/dist/views/FormViewV2.d.ts +2 -2
  236. package/dist/views/FormViewV2.js +9 -9
  237. package/dist/views/ListViewV2.d.ts +3 -3
  238. package/dist/views/ListViewV2.js +16 -16
  239. package/dist/views/Wizard/Wizard.context.js +1 -1
  240. package/dist/views/Wizard/Wizard.d.ts +1 -1
  241. package/dist/views/Wizard/Wizard.js +1 -1
  242. package/dist/views/Wizard/index.d.ts +4 -4
  243. package/dist/views/Wizard/index.js +2 -2
  244. package/dist/views/types/IFormView.d.ts +1 -1
  245. package/dist/views/types/IListView.d.ts +1 -1
  246. package/dist/widgets/CircleButton.d.ts +2 -2
  247. package/dist/widgets/CircleButton.js +1 -1
  248. package/dist/widgets/GeoPermissionCard.js +3 -3
  249. package/dist/widgets/HomeHeader.js +3 -3
  250. package/dist/widgets/JSONViewer.js +2 -2
  251. package/dist/widgets/MenuCard.d.ts +2 -2
  252. package/dist/widgets/MenuCard.js +1 -1
  253. package/dist/widgets/MenuGrid.d.ts +3 -3
  254. package/dist/widgets/MenuGrid.js +1 -1
  255. package/dist/widgets/MenuSection.d.ts +2 -2
  256. package/dist/widgets/MenuSection.js +1 -1
  257. package/dist/widgets/PromoBanner.js +3 -3
  258. package/dist/widgets/PromoModal.js +3 -3
  259. package/dist/widgets/QuickActions.js +3 -3
  260. package/dist/widgets/ScreenHeader.js +2 -2
  261. package/dist/widgets/TimeZoneSelector.d.ts +1 -1
  262. package/dist/widgets/TimeZoneSelector.js +4 -4
  263. package/dist/widgets/TimeZoneSelectorModal.d.ts +1 -1
  264. package/dist/widgets/TimeZoneSelectorModal.js +5 -5
  265. package/dist/widgets/index.d.ts +16 -16
  266. package/dist/widgets/index.js +10 -10
  267. package/package.json +56 -50
  268. package/tailwind.preset.js +19 -0
  269. package/dist/icons/icon_getters.d.ts +0 -6
  270. package/dist/icons/icon_getters.js +0 -23
@@ -0,0 +1,109 @@
1
+ /**
2
+ * Color primitives for theme derivation (HSL). Used by buildThemeFromBrand
3
+ * and container/tonal helpers — keeps brand math in one place.
4
+ */
5
+ export function hexToRgb(hex) {
6
+ const h = hex.trim().replace(/^#/, "");
7
+ const full = h.length === 3
8
+ ? h
9
+ .split("")
10
+ .map((c) => c + c)
11
+ .join("")
12
+ : h;
13
+ return {
14
+ r: Number.parseInt(full.slice(0, 2), 16),
15
+ g: Number.parseInt(full.slice(2, 4), 16),
16
+ b: Number.parseInt(full.slice(4, 6), 16),
17
+ };
18
+ }
19
+ export function rgbToHex(r, g, b) {
20
+ const clamp = (n) => Math.max(0, Math.min(255, Math.round(n)));
21
+ return ("#" +
22
+ [clamp(r), clamp(g), clamp(b)]
23
+ .map((n) => n.toString(16).padStart(2, "0"))
24
+ .join("")
25
+ .toUpperCase());
26
+ }
27
+ export function hexToHsl(hex) {
28
+ const { r, g, b } = hexToRgb(hex);
29
+ const rn = r / 255;
30
+ const gn = g / 255;
31
+ const bn = b / 255;
32
+ const max = Math.max(rn, gn, bn);
33
+ const min = Math.min(rn, gn, bn);
34
+ const l = (max + min) / 2;
35
+ if (max === min)
36
+ return { h: 0, s: 0, l };
37
+ const d = max - min;
38
+ const s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
39
+ let h = 0;
40
+ if (max === rn)
41
+ h = ((gn - bn) / d + (gn < bn ? 6 : 0)) / 6;
42
+ else if (max === gn)
43
+ h = ((bn - rn) / d + 2) / 6;
44
+ else
45
+ h = ((rn - gn) / d + 4) / 6;
46
+ return { h: h * 360, s, l };
47
+ }
48
+ export function hslToHex({ h, s, l }) {
49
+ const hh = ((h % 360) + 360) % 360;
50
+ const c = (1 - Math.abs(2 * l - 1)) * s;
51
+ const x = c * (1 - Math.abs(((hh / 60) % 2) - 1));
52
+ const m = l - c / 2;
53
+ let rn = 0;
54
+ let gn = 0;
55
+ let bn = 0;
56
+ if (hh < 60) {
57
+ rn = c;
58
+ gn = x;
59
+ }
60
+ else if (hh < 120) {
61
+ rn = x;
62
+ gn = c;
63
+ }
64
+ else if (hh < 180) {
65
+ gn = c;
66
+ bn = x;
67
+ }
68
+ else if (hh < 240) {
69
+ gn = x;
70
+ bn = c;
71
+ }
72
+ else if (hh < 300) {
73
+ rn = x;
74
+ bn = c;
75
+ }
76
+ else {
77
+ rn = c;
78
+ bn = x;
79
+ }
80
+ return rgbToHex((rn + m) * 255, (gn + m) * 255, (bn + m) * 255);
81
+ }
82
+ /** Mix two hex colors. `t=0` → a, `t=1` → b. */
83
+ export function mixHex(a, b, t) {
84
+ const A = hexToRgb(a);
85
+ const B = hexToRgb(b);
86
+ const u = Math.max(0, Math.min(1, t));
87
+ return rgbToHex(A.r + (B.r - A.r) * u, A.g + (B.g - A.g) * u, A.b + (B.b - A.b) * u);
88
+ }
89
+ /** Shift lightness in HSL. delta in [-1, 1] absolute L change. */
90
+ export function shiftLightness(hex, delta) {
91
+ const hsl = hexToHsl(hex);
92
+ return hslToHex({
93
+ ...hsl,
94
+ l: Math.max(0, Math.min(1, hsl.l + delta)),
95
+ });
96
+ }
97
+ /** Soft container fill + on-container ink (M3-style tonal pair). */
98
+ export function containerPair(seed, mode) {
99
+ if (mode === "light") {
100
+ return {
101
+ container: mixHex(seed, "#FFFFFF", 0.88),
102
+ onContainer: shiftLightness(seed, -0.22),
103
+ };
104
+ }
105
+ return {
106
+ container: mixHex(seed, "#000000", 0.72),
107
+ onContainer: mixHex(seed, "#FFFFFF", 0.45),
108
+ };
109
+ }
@@ -6,4 +6,4 @@
6
6
  * Components that need access to theme tokens via hook.
7
7
  * Estos son el 1% de casos donde className no es suficiente.
8
8
  */
9
- export { ThemedActivityIndicator } from "../../theme/components/ThemedActivityIndicator";
9
+ export { ThemedActivityIndicator } from "./ThemedActivityIndicator.js";
@@ -6,4 +6,4 @@
6
6
  * Components that need access to theme tokens via hook.
7
7
  * Estos son el 1% de casos donde className no es suficiente.
8
8
  */
9
- export { ThemedActivityIndicator } from "../../theme/components/ThemedActivityIndicator";
9
+ export { ThemedActivityIndicator } from "./ThemedActivityIndicator.js";
@@ -0,0 +1,29 @@
1
+ /**
2
+ * WCAG 2.1 contrast helpers for theme authors.
3
+ * Used by `validateTheme` and by consumers building brand palettes.
4
+ */
5
+ export declare function parseHex(hex: string): {
6
+ r: number;
7
+ g: number;
8
+ b: number;
9
+ };
10
+ export declare function relativeLuminance(hex: string): number;
11
+ /** Contrast ratio between two sRGB hex colors (WCAG 2.1). */
12
+ export declare function contrastRatio(fg: string, bg: string): number;
13
+ export type ResolveOnColorOptions = {
14
+ /** Ink for light fills. Default `#FFFFFF`. */
15
+ light?: string;
16
+ /** Ink for dark/saturated fills. Default `#0A0A0A`. */
17
+ dark?: string;
18
+ /** Minimum contrast (AA body = 4.5). */
19
+ minRatio?: number;
20
+ };
21
+ /**
22
+ * Picks light or dark ink for text/icons on a filled surface so WCAG AA holds
23
+ * for any brand `primary` / `accent` / state color — not a hardcoded ink.
24
+ *
25
+ * @example
26
+ * text: { onPrimary: resolveOnColor("#C9A84C") } // → #0A0A0A
27
+ * text: { onPrimary: resolveOnColor("#0B1F4A") } // → #FFFFFF
28
+ */
29
+ export declare function resolveOnColor(fill: string, options?: ResolveOnColorOptions): string;
@@ -0,0 +1,57 @@
1
+ /**
2
+ * WCAG 2.1 contrast helpers for theme authors.
3
+ * Used by `validateTheme` and by consumers building brand palettes.
4
+ */
5
+ export function parseHex(hex) {
6
+ const h = hex.trim().replace(/^#/, "");
7
+ const full = h.length === 3
8
+ ? h
9
+ .split("")
10
+ .map((c) => c + c)
11
+ .join("")
12
+ : h;
13
+ return {
14
+ r: Number.parseInt(full.slice(0, 2), 16),
15
+ g: Number.parseInt(full.slice(2, 4), 16),
16
+ b: Number.parseInt(full.slice(4, 6), 16),
17
+ };
18
+ }
19
+ export function relativeLuminance(hex) {
20
+ const { r, g, b } = parseHex(hex);
21
+ const norm = (c) => {
22
+ const s = c / 255;
23
+ return s <= 0.03928 ? s / 12.92 : Math.pow((s + 0.055) / 1.055, 2.4);
24
+ };
25
+ return 0.2126 * norm(r) + 0.7152 * norm(g) + 0.0722 * norm(b);
26
+ }
27
+ /** Contrast ratio between two sRGB hex colors (WCAG 2.1). */
28
+ export function contrastRatio(fg, bg) {
29
+ const L1 = relativeLuminance(fg);
30
+ const L2 = relativeLuminance(bg);
31
+ return (Math.max(L1, L2) + 0.05) / (Math.min(L1, L2) + 0.05);
32
+ }
33
+ const DEFAULT_ON_LIGHT = "#FFFFFF";
34
+ const DEFAULT_ON_DARK = "#0A0A0A";
35
+ /**
36
+ * Picks light or dark ink for text/icons on a filled surface so WCAG AA holds
37
+ * for any brand `primary` / `accent` / state color — not a hardcoded ink.
38
+ *
39
+ * @example
40
+ * text: { onPrimary: resolveOnColor("#C9A84C") } // → #0A0A0A
41
+ * text: { onPrimary: resolveOnColor("#0B1F4A") } // → #FFFFFF
42
+ */
43
+ export function resolveOnColor(fill, options = {}) {
44
+ const light = options.light ?? DEFAULT_ON_LIGHT;
45
+ const dark = options.dark ?? DEFAULT_ON_DARK;
46
+ const min = options.minRatio ?? 4.5;
47
+ const withLight = contrastRatio(light, fill);
48
+ const withDark = contrastRatio(dark, fill);
49
+ if (withLight >= min && withDark >= min) {
50
+ return withLight >= withDark ? light : dark;
51
+ }
52
+ if (withLight >= min)
53
+ return light;
54
+ if (withDark >= min)
55
+ return dark;
56
+ return withLight >= withDark ? light : dark;
57
+ }
@@ -1,7 +1,9 @@
1
- import type { ThemeTokens } from "../theme/types";
1
+ import type { ThemeTokens } from "./types.js";
2
2
  /**
3
3
  * Deriva las CSS variables (tripletes RGB para `rgb(var(--x) / <alpha>)`) a
4
4
  * partir del objeto de tokens tipado. Fuente ÚNICA: las clases (className) y el
5
5
  * objeto JS (style) salen del mismo `ThemeTokens`, sin posibilidad de divergir.
6
+ *
7
+ * State / material opacities are emitted as unitless numbers (not RGB).
6
8
  */
7
9
  export declare function themeToVars(t: ThemeTokens): Record<string, string>;
@@ -6,15 +6,17 @@ function toRgbTriplet(color) {
6
6
  .map((c) => c + c)
7
7
  .join("")
8
8
  : hex;
9
- const r = parseInt(full.slice(0, 2), 16);
10
- const g = parseInt(full.slice(2, 4), 16);
11
- const b = parseInt(full.slice(4, 6), 16);
9
+ const r = Number.parseInt(full.slice(0, 2), 16);
10
+ const g = Number.parseInt(full.slice(2, 4), 16);
11
+ const b = Number.parseInt(full.slice(4, 6), 16);
12
12
  return `${r} ${g} ${b}`;
13
13
  }
14
14
  /**
15
15
  * Deriva las CSS variables (tripletes RGB para `rgb(var(--x) / <alpha>)`) a
16
16
  * partir del objeto de tokens tipado. Fuente ÚNICA: las clases (className) y el
17
17
  * objeto JS (style) salen del mismo `ThemeTokens`, sin posibilidad de divergir.
18
+ *
19
+ * State / material opacities are emitted as unitless numbers (not RGB).
18
20
  */
19
21
  export function themeToVars(t) {
20
22
  const rgb = toRgbTriplet;
@@ -29,6 +31,9 @@ export function themeToVars(t) {
29
31
  "--bg-accent": rgb(t.bg.accent),
30
32
  "--bg-hover": rgb(t.bg.hover),
31
33
  "--bg-disabled": rgb(t.bg.disabled),
34
+ "--bg-container-lowest": rgb(t.bg.containerLowest),
35
+ "--bg-container": rgb(t.bg.container),
36
+ "--bg-container-high": rgb(t.bg.containerHigh),
32
37
  "--text-primary": rgb(t.text.primary),
33
38
  "--text-secondary": rgb(t.text.secondary),
34
39
  "--text-tertiary": rgb(t.text.tertiary),
@@ -58,6 +63,27 @@ export function themeToVars(t) {
58
63
  "--warning-light": rgb(t.warningLight),
59
64
  "--danger-light": rgb(t.dangerLight),
60
65
  "--info-light": rgb(t.infoLight),
66
+ "--container-primary": rgb(t.container.primary),
67
+ "--container-on-primary": rgb(t.container.onPrimary),
68
+ "--container-secondary": rgb(t.container.secondary),
69
+ "--container-on-secondary": rgb(t.container.onSecondary),
70
+ "--container-accent": rgb(t.container.accent),
71
+ "--container-on-accent": rgb(t.container.onAccent),
72
+ "--container-success": rgb(t.container.success),
73
+ "--container-on-success": rgb(t.container.onSuccess),
74
+ "--container-warning": rgb(t.container.warning),
75
+ "--container-on-warning": rgb(t.container.onWarning),
76
+ "--container-danger": rgb(t.container.danger),
77
+ "--container-on-danger": rgb(t.container.onDanger),
78
+ "--container-info": rgb(t.container.info),
79
+ "--container-on-info": rgb(t.container.onInfo),
80
+ "--state-hover": String(t.state.hover),
81
+ "--state-press": String(t.state.press),
82
+ "--state-focus": String(t.state.focus),
83
+ "--state-drag": String(t.state.drag),
84
+ "--material-blur": String(t.material.blur),
85
+ "--material-opacity": String(t.material.opacity),
86
+ "--material-border-opacity": String(t.material.borderOpacity),
61
87
  "--ring": rgb(t.ring),
62
88
  "--input": rgb(t.input),
63
89
  };
@@ -1,7 +1,6 @@
1
- import type { ThemeTokens } from "../theme/types";
1
+ import type { ThemeTokens } from "./types.js";
2
2
  /**
3
- * SINCPRO brand-dark theme.
4
- * Identity: black (#0B0B0B) surfaces + neon-green (#00F58C) as primary CTA / accent.
5
- * Border/text tones shift to near-black warm neutrals (not blue-slate).
3
+ * Default dark theme. Companion to `DEFAULT_THEME`.
4
+ * Prefer `buildThemeFromBrand({ mode: "dark", ... })` for brand apps.
6
5
  */
7
6
  export declare const DEFAULT_DARK_THEME: ThemeTokens;
@@ -1,63 +1,102 @@
1
+ import { containerPair } from "./color.js";
2
+ import { resolveOnColor } from "./contrast.js";
3
+ /** Web UI dark palette. The same roles, measured on #181614. */
4
+ const PRIMARY = "#8FA9E8";
5
+ const SECONDARY = "#B0C3F1";
6
+ const ACCENT = "#C89B3C";
7
+ const SUCCESS = "#6FCF8B";
8
+ const WARNING = "#E3B341";
9
+ const DANGER = "#F08D7F";
10
+ const INFO = "#5CC4D8";
11
+ const INK = "#ECE8E1";
12
+ const MUTED = "#A39B90";
13
+ const primaryC = containerPair(PRIMARY, "dark");
14
+ const secondaryC = containerPair(SECONDARY, "dark");
15
+ const accentC = containerPair(ACCENT, "dark");
16
+ const successC = containerPair(SUCCESS, "dark");
17
+ const warningC = containerPair(WARNING, "dark");
18
+ const dangerC = containerPair(DANGER, "dark");
19
+ const infoC = containerPair(INFO, "dark");
1
20
  /**
2
- * SINCPRO brand-dark theme.
3
- * Identity: black (#0B0B0B) surfaces + neon-green (#00F58C) as primary CTA / accent.
4
- * Border/text tones shift to near-black warm neutrals (not blue-slate).
21
+ * Default dark theme. Companion to `DEFAULT_THEME`.
22
+ * Prefer `buildThemeFromBrand({ mode: "dark", ... })` for brand apps.
5
23
  */
6
24
  export const DEFAULT_DARK_THEME = {
7
- name: "dark",
8
- primary: "#00F58C", // verde neón → primary action in dark (border, link, focus indicator)
9
- secondary: "#6B6963",
10
- accent: "#00F58C",
25
+ name: "default-dark",
26
+ primary: PRIMARY,
27
+ secondary: SECONDARY,
28
+ accent: ACCENT,
11
29
  bg: {
12
- page: "#0B0B0B",
13
- card: "#161616",
14
- popover: "#161616",
15
- muted: "#1E1E1E",
16
- accent: "#0D2B1F", // dark-green tint for selected/active rows
17
- hover: "#262626",
18
- disabled: "#161616",
19
- inverse: "#0B0B0B",
30
+ page: "#181614",
31
+ card: "#221F1C",
32
+ popover: "#221F1C",
33
+ muted: "#302C28",
34
+ accent: primaryC.container,
35
+ hover: "#2A2622",
36
+ disabled: "#302C28",
37
+ inverse: "#FAF9F7",
38
+ containerLowest: "#141210",
39
+ container: "#221F1C",
40
+ containerHigh: "#302C28",
20
41
  },
21
42
  text: {
22
- primary: "#FFFFFF",
23
- secondary: "#B0B0B0",
24
- tertiary: "#7D7D7D",
25
- muted: "#9D9D9D",
26
- accent: "#00F58C",
27
- inverse: "#0B0B0B",
28
- disabled: "#4A4A4A",
29
- onPrimary: "#06170E", // texto sobre verde neón: oscuro para contraste
30
- onSecondary: "#0B0B0B",
31
- onAccent: "#06170E",
32
- onDanger: "#FFFFFF",
33
- onSuccess: "#FFFFFF",
43
+ primary: INK,
44
+ secondary: MUTED,
45
+ tertiary: "#8A8178",
46
+ muted: MUTED,
47
+ accent: PRIMARY,
48
+ inverse: "#0A0A0A",
49
+ disabled: "#8A8A8A",
50
+ onPrimary: resolveOnColor(PRIMARY),
51
+ onSecondary: resolveOnColor(SECONDARY),
52
+ onAccent: resolveOnColor(ACCENT),
53
+ onDanger: resolveOnColor(DANGER),
54
+ onSuccess: resolveOnColor(SUCCESS),
34
55
  },
35
56
  icon: {
36
- primary: "#FFFFFF",
37
- secondary: "#9A9A9A",
38
- tertiary: "#7D7D7D",
39
- inverse: "#0B0B0B",
40
- disabled: "#4A4A4A",
57
+ primary: INK,
58
+ secondary: MUTED,
59
+ tertiary: "#8A8178",
60
+ inverse: "#0A0A0A",
61
+ disabled: "#8A8A8A",
41
62
  },
42
63
  border: {
43
- default: "#262626",
44
- light: "#1E1E1E",
45
- strong: "#3A3A3A",
46
- focus: "#00F58C",
64
+ default: "#302C28",
65
+ light: "#221F1C",
66
+ strong: "#443F38",
67
+ focus: PRIMARY,
47
68
  },
48
- success: "#00C357",
49
- warning: "#FFB020",
50
- danger: "#FF4D1F",
51
- info: "#5B8DEF",
52
- successLight: "#0D2B1A",
53
- warningLight: "#2B1E04",
54
- dangerLight: "#2B0A04",
55
- infoLight: "#0A143B",
56
- ring: "#00F58C",
57
- input: "#262626",
69
+ success: SUCCESS,
70
+ warning: WARNING,
71
+ danger: DANGER,
72
+ info: INFO,
73
+ successLight: successC.container,
74
+ warningLight: warningC.container,
75
+ dangerLight: dangerC.container,
76
+ infoLight: infoC.container,
77
+ container: {
78
+ primary: primaryC.container,
79
+ onPrimary: primaryC.onContainer,
80
+ secondary: secondaryC.container,
81
+ onSecondary: secondaryC.onContainer,
82
+ accent: accentC.container,
83
+ onAccent: accentC.onContainer,
84
+ success: successC.container,
85
+ onSuccess: successC.onContainer,
86
+ warning: warningC.container,
87
+ onWarning: warningC.onContainer,
88
+ danger: dangerC.container,
89
+ onDanger: dangerC.onContainer,
90
+ info: infoC.container,
91
+ onInfo: infoC.onContainer,
92
+ },
93
+ state: { hover: 0.1, press: 0.16, focus: 0.14, drag: 0.2 },
94
+ material: { blur: 28, opacity: 0.62, borderOpacity: 0.22 },
95
+ ring: PRIMARY,
96
+ input: "#302C28",
58
97
  gradient: {
59
- primary: ["#22E584", "#00F58C"], // verde gradient → primary btn en dark = CTA verde
60
- accent: ["#22E584", "#00F58C"],
98
+ primary: ["#1C3765", PRIMARY],
99
+ accent: [ACCENT, "#DBB055"],
61
100
  },
62
101
  shadow: {
63
102
  sm: {
@@ -82,4 +121,8 @@ export const DEFAULT_DARK_THEME = {
82
121
  elevation: 7,
83
122
  },
84
123
  },
124
+ pattern: {
125
+ mode: "dark-pattern",
126
+ size: 56,
127
+ },
85
128
  };
@@ -1,2 +1,6 @@
1
- import type { ThemeTokens } from "../theme/types";
1
+ import type { ThemeTokens } from "./types.js";
2
+ /**
3
+ * Default light theme. Sample values — not the framework identity.
4
+ * Prefer `buildThemeFromBrand` or `extendTheme` at app boot.
5
+ */
2
6
  export declare const DEFAULT_THEME: ThemeTokens;
@@ -1,64 +1,108 @@
1
+ import { containerPair } from "./color.js";
2
+ import { resolveOnColor } from "./contrast.js";
3
+ /** Web UI light palette. Gold is a fill, never a border or a label. */
4
+ const PRIMARY = "#2A4A85";
5
+ const SECONDARY = "#1C3765";
6
+ const ACCENT = "#C89B3C";
7
+ const SUCCESS = "#2F6B3C";
8
+ const WARNING = "#7E5E12";
9
+ const DANGER = "#9B3B30";
10
+ const INFO = "#0F5C6E";
11
+ const INK = "#1A1714";
12
+ const MUTED = "#6B6459";
13
+ const primaryC = containerPair(PRIMARY, "light");
14
+ const secondaryC = containerPair(SECONDARY, "light");
15
+ const accentC = containerPair(ACCENT, "light");
16
+ const successC = containerPair(SUCCESS, "light");
17
+ const warningC = containerPair(WARNING, "light");
18
+ const dangerC = containerPair(DANGER, "light");
19
+ const infoC = containerPair(INFO, "light");
20
+ /**
21
+ * Default light theme. Sample values — not the framework identity.
22
+ * Prefer `buildThemeFromBrand` or `extendTheme` at app boot.
23
+ */
1
24
  export const DEFAULT_THEME = {
2
- name: "default",
3
- primary: "#2563EB",
4
- secondary: "#64748B",
5
- accent: "#F59E0B",
25
+ name: "default-light",
26
+ primary: PRIMARY,
27
+ secondary: SECONDARY,
28
+ accent: ACCENT,
6
29
  bg: {
7
- page: "#F0F1F3",
30
+ page: "#FAF9F7",
8
31
  card: "#FFFFFF",
9
32
  popover: "#FFFFFF",
10
- muted: "#F3F4F6",
11
- accent: "#EFF6FF",
12
- hover: "#F3F4F6",
13
- disabled: "#F3F4F6",
14
- inverse: "#0E1714",
33
+ muted: "#F3F0EA",
34
+ accent: primaryC.container,
35
+ hover: "#EBE6DE",
36
+ disabled: "#E4DFD7",
37
+ inverse: "#181614",
38
+ containerLowest: "#FAF9F7",
39
+ container: "#F3F0EA",
40
+ containerHigh: "#E4DFD7",
15
41
  },
16
42
  text: {
17
- primary: "#0F172A",
18
- secondary: "#475569",
19
- tertiary: "#94A3B8",
20
- muted: "#64748B",
21
- accent: "#1E40AF",
43
+ primary: INK,
44
+ secondary: MUTED,
45
+ tertiary: "#A39B90",
46
+ muted: MUTED,
47
+ accent: PRIMARY,
22
48
  inverse: "#FFFFFF",
23
- disabled: "#94A3B8",
49
+ disabled: "#A39B90",
24
50
  onPrimary: "#FFFFFF",
25
51
  onSecondary: "#FFFFFF",
26
- onAccent: "#FFFFFF",
27
- onDanger: "#FFFFFF",
28
- onSuccess: "#FFFFFF",
52
+ onAccent: "#1A1714",
53
+ onDanger: resolveOnColor(DANGER),
54
+ onSuccess: resolveOnColor(SUCCESS),
29
55
  },
30
56
  icon: {
31
- primary: "#0F172A",
32
- secondary: "#64748B",
33
- tertiary: "#94A3B8",
57
+ primary: INK,
58
+ secondary: MUTED,
59
+ tertiary: "#A39B90",
34
60
  inverse: "#FFFFFF",
35
- disabled: "#CBD5E1",
61
+ disabled: "#A39B90",
36
62
  },
37
63
  border: {
38
- default: "#E5E7EB",
39
- light: "#F3F4F6",
40
- strong: "#D1D5DB",
41
- focus: "#2563EB",
64
+ default: "#E4DFD7",
65
+ light: "#F3F0EA",
66
+ strong: "#D5CEC2",
67
+ focus: PRIMARY,
42
68
  },
43
- success: "#16A34A",
44
- warning: "#F59E0B",
45
- danger: "#DC2626",
46
- info: "#2563EB",
47
- successLight: "#DCFCE7",
48
- warningLight: "#FEF3C7",
49
- dangerLight: "#FEE2E2",
50
- infoLight: "#DBEAFE",
51
- ring: "#2563EB",
52
- input: "#E5E7EB",
69
+ success: SUCCESS,
70
+ warning: WARNING,
71
+ danger: DANGER,
72
+ info: INFO,
73
+ successLight: successC.container,
74
+ warningLight: warningC.container,
75
+ dangerLight: dangerC.container,
76
+ infoLight: infoC.container,
77
+ container: {
78
+ primary: primaryC.container,
79
+ onPrimary: primaryC.onContainer,
80
+ secondary: secondaryC.container,
81
+ onSecondary: secondaryC.onContainer,
82
+ accent: accentC.container,
83
+ onAccent: accentC.onContainer,
84
+ success: successC.container,
85
+ onSuccess: successC.onContainer,
86
+ warning: warningC.container,
87
+ onWarning: warningC.onContainer,
88
+ danger: dangerC.container,
89
+ onDanger: dangerC.onContainer,
90
+ info: infoC.container,
91
+ onInfo: infoC.onContainer,
92
+ },
93
+ state: { hover: 0.08, press: 0.12, focus: 0.12, drag: 0.16 },
94
+ material: { blur: 24, opacity: 0.78, borderOpacity: 0.18 },
95
+ ring: PRIMARY,
96
+ input: "#E4DFD7",
53
97
  gradient: {
54
- primary: ["#2563EB", "#1E40AF"],
55
- accent: ["#F59E0B", "#D97706"],
98
+ primary: [SECONDARY, PRIMARY],
99
+ accent: ["#B88A2E", ACCENT],
56
100
  },
57
101
  shadow: {
58
102
  sm: {
59
103
  shadowColor: "#000000",
60
104
  shadowOffset: { width: 0, height: 1 },
61
- shadowOpacity: 0.05,
105
+ shadowOpacity: 0.06,
62
106
  shadowRadius: 2,
63
107
  elevation: 1,
64
108
  },
@@ -72,9 +116,13 @@ export const DEFAULT_THEME = {
72
116
  lg: {
73
117
  shadowColor: "#000000",
74
118
  shadowOffset: { width: 0, height: 10 },
75
- shadowOpacity: 0.1,
119
+ shadowOpacity: 0.14,
76
120
  shadowRadius: 15,
77
121
  elevation: 5,
78
122
  },
79
123
  },
124
+ pattern: {
125
+ mode: "light-pattern",
126
+ size: 56,
127
+ },
80
128
  };
@@ -1,10 +1,13 @@
1
- import type { ThemeTokens } from "../theme/types";
1
+ import type { ThemeTokens } from "./types.js";
2
2
  export type DeepPartial<T> = {
3
3
  [K in keyof T]?: T[K] extends readonly unknown[] ? T[K] : T[K] extends object ? DeepPartial<T[K]> : T[K];
4
4
  };
5
5
  /**
6
6
  * Defines a complete, typed theme (powerful API: the framework parametrizes
7
7
  * every token explicitly).
8
+ *
9
+ * Tip for brand palettes: set on-colors with `resolveOnColor` from
10
+ * `@sincpro/mobile-ui/theme` so light and dark brand fills both stay WCAG AA.
8
11
  */
9
12
  export declare function defineTheme(tokens: ThemeTokens): ThemeTokens;
10
13
  /**
@@ -1,4 +1,4 @@
1
- import { DEFAULT_THEME } from "../theme/default";
1
+ import { DEFAULT_THEME } from "./default.js";
2
2
  function isPlainObject(v) {
3
3
  return typeof v === "object" && v !== null && !Array.isArray(v);
4
4
  }
@@ -15,6 +15,9 @@ function deepMerge(base, override) {
15
15
  /**
16
16
  * Defines a complete, typed theme (powerful API: the framework parametrizes
17
17
  * every token explicitly).
18
+ *
19
+ * Tip for brand palettes: set on-colors with `resolveOnColor` from
20
+ * `@sincpro/mobile-ui/theme` so light and dark brand fills both stay WCAG AA.
18
21
  */
19
22
  export function defineTheme(tokens) {
20
23
  return tokens;