@onlynative/components 0.1.0-alpha.0 → 0.1.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -8,7 +8,7 @@ Material Design 3 UI components for React Native, part of [OnlyNative UI](https:
8
8
  pnpm add @onlynative/core @onlynative/components @expo/vector-icons react-native-safe-area-context
9
9
  ```
10
10
 
11
- Wrap your app with `MaterialProvider` from `@onlynative/core` (see [@onlynative/core](https://www.npmjs.com/package/@onlynative/core)).
11
+ Wrap your app with `ThemeProvider` from `@onlynative/core` (see [@onlynative/core](https://www.npmjs.com/package/@onlynative/core)).
12
12
 
13
13
  ## Import
14
14
 
@@ -35,7 +35,7 @@ __export(appbar_exports, {
35
35
  module.exports = __toCommonJS(appbar_exports);
36
36
 
37
37
  // src/appbar/AppBar.tsx
38
- var import_react3 = require("react");
38
+ var import_react2 = require("react");
39
39
  var import_react_native6 = require("react-native");
40
40
  var import_react_native_safe_area_context = require("react-native-safe-area-context");
41
41
  var import_core4 = require("@onlynative/core");
@@ -577,7 +577,6 @@ function IconButton({
577
577
  }
578
578
 
579
579
  // src/typography/Typography.tsx
580
- var import_react2 = require("react");
581
580
  var import_react_native3 = require("react-native");
582
581
  var import_core2 = require("@onlynative/core");
583
582
  var import_jsx_runtime2 = require("react/jsx-runtime");
@@ -600,17 +599,18 @@ function Typography({
600
599
  }) {
601
600
  const theme = (0, import_core2.useTheme)();
602
601
  const typographyStyle = theme.typography[variant];
603
- const colorStyle = (0, import_react2.useMemo)(
604
- () => ({ color: color != null ? color : theme.colors.onSurface }),
605
- [color, theme.colors.onSurface]
606
- );
607
602
  const resolvedRole = accessibilityRole != null ? accessibilityRole : HEADING_VARIANTS.has(variant) ? "header" : void 0;
608
603
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
609
604
  Component,
610
605
  {
611
606
  ...textProps,
612
607
  accessibilityRole: resolvedRole,
613
- style: [typographyStyle, colorStyle, style],
608
+ style: [
609
+ { color: theme.colors.onSurface },
610
+ typographyStyle,
611
+ style,
612
+ color != null ? { color } : void 0
613
+ ],
614
614
  children
615
615
  }
616
616
  );
@@ -771,10 +771,10 @@ function AppBar({
771
771
  var _a;
772
772
  const theme = (0, import_core4.useTheme)();
773
773
  const topAppBar = (_a = theme.topAppBar) != null ? _a : import_core4.defaultTopAppBarTokens;
774
- const styles = (0, import_react3.useMemo)(() => createStyles2(theme), [theme]);
775
- const [leadingWidth, setLeadingWidth] = (0, import_react3.useState)(0);
776
- const [actionsWidth, setActionsWidth] = (0, import_react3.useState)(0);
777
- const titleColorStyle = (0, import_react3.useMemo)(
774
+ const styles = (0, import_react2.useMemo)(() => createStyles2(theme), [theme]);
775
+ const [leadingWidth, setLeadingWidth] = (0, import_react2.useState)(0);
776
+ const [actionsWidth, setActionsWidth] = (0, import_react2.useState)(0);
777
+ const titleColorStyle = (0, import_react2.useMemo)(
778
778
  () => ({ color: contentColor != null ? contentColor : theme.colors.onSurface }),
779
779
  [contentColor, theme.colors.onSurface]
780
780
  );
@@ -785,15 +785,15 @@ function AppBar({
785
785
  const titleStartInset = topAppBar.horizontalPadding + Math.max(topAppBar.titleStartInset, leadingWidth);
786
786
  const compactTitleEndInset = topAppBar.horizontalPadding + actionsWidth;
787
787
  const centeredSideInset = topAppBar.horizontalPadding + Math.max(leadingWidth, actionsWidth);
788
- const expandedTitleInsetStyle = (0, import_react3.useMemo)(
788
+ const expandedTitleInsetStyle = (0, import_react2.useMemo)(
789
789
  () => ({ paddingStart: titleStartInset }),
790
790
  [titleStartInset]
791
791
  );
792
- const overlayTitleInsetStyle = (0, import_react3.useMemo)(
792
+ const overlayTitleInsetStyle = (0, import_react2.useMemo)(
793
793
  () => isCenterAligned ? { start: centeredSideInset, end: centeredSideInset } : { start: titleStartInset, end: compactTitleEndInset },
794
794
  [centeredSideInset, compactTitleEndInset, isCenterAligned, titleStartInset]
795
795
  );
796
- const leadingContent = (0, import_react3.useMemo)(() => {
796
+ const leadingContent = (0, import_react2.useMemo)(() => {
797
797
  if (leading) {
798
798
  return leading;
799
799
  }
@@ -819,7 +819,7 @@ function AppBar({
819
819
  styles.iconFrame,
820
820
  theme.colors.onSurface
821
821
  ]);
822
- const actionsContent = (0, import_react3.useMemo)(() => {
822
+ const actionsContent = (0, import_react2.useMemo)(() => {
823
823
  if (trailing) {
824
824
  return trailing;
825
825
  }
@@ -846,7 +846,7 @@ function AppBar({
846
846
  `${String(action.icon)}-${index}`
847
847
  )) });
848
848
  }, [actions, contentColor, styles.actionsRow, styles.iconFrame, trailing]);
849
- const onLeadingLayout = (0, import_react3.useCallback)((event) => {
849
+ const onLeadingLayout = (0, import_react2.useCallback)((event) => {
850
850
  const nextWidth = measureWidth(event);
851
851
  setLeadingWidth((currentWidth) => {
852
852
  if (currentWidth === nextWidth) {
@@ -855,7 +855,7 @@ function AppBar({
855
855
  return nextWidth;
856
856
  });
857
857
  }, []);
858
- const onActionsLayout = (0, import_react3.useCallback)((event) => {
858
+ const onActionsLayout = (0, import_react2.useCallback)((event) => {
859
859
  const nextWidth = measureWidth(event);
860
860
  setActionsWidth((currentWidth) => {
861
861
  if (currentWidth === nextWidth) {
package/dist/index.js CHANGED
@@ -52,7 +52,6 @@ __export(index_exports, {
52
52
  module.exports = __toCommonJS(index_exports);
53
53
 
54
54
  // src/typography/Typography.tsx
55
- var import_react = require("react");
56
55
  var import_react_native = require("react-native");
57
56
  var import_core = require("@onlynative/core");
58
57
  var import_jsx_runtime = require("react/jsx-runtime");
@@ -75,24 +74,25 @@ function Typography({
75
74
  }) {
76
75
  const theme = (0, import_core.useTheme)();
77
76
  const typographyStyle = theme.typography[variant];
78
- const colorStyle = (0, import_react.useMemo)(
79
- () => ({ color: color != null ? color : theme.colors.onSurface }),
80
- [color, theme.colors.onSurface]
81
- );
82
77
  const resolvedRole = accessibilityRole != null ? accessibilityRole : HEADING_VARIANTS.has(variant) ? "header" : void 0;
83
78
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
84
79
  Component,
85
80
  {
86
81
  ...textProps,
87
82
  accessibilityRole: resolvedRole,
88
- style: [typographyStyle, colorStyle, style],
83
+ style: [
84
+ { color: theme.colors.onSurface },
85
+ typographyStyle,
86
+ style,
87
+ color != null ? { color } : void 0
88
+ ],
89
89
  children
90
90
  }
91
91
  );
92
92
  }
93
93
 
94
94
  // src/layout/Layout.tsx
95
- var import_react2 = require("react");
95
+ var import_react = require("react");
96
96
  var import_react_native2 = require("react-native");
97
97
  var import_react_native_safe_area_context = require("react-native-safe-area-context");
98
98
  var import_core2 = require("@onlynative/core");
@@ -126,15 +126,15 @@ function removeBackgroundColor(style) {
126
126
  }
127
127
  function Layout({ immersive, edges, children, style }) {
128
128
  const theme = (0, import_core2.useTheme)();
129
- const themeBackgroundStyle = (0, import_react2.useMemo)(
129
+ const themeBackgroundStyle = (0, import_react.useMemo)(
130
130
  () => ({ backgroundColor: theme.colors.background }),
131
131
  [theme.colors.background]
132
132
  );
133
- const styleWithoutBackground = (0, import_react2.useMemo)(
133
+ const styleWithoutBackground = (0, import_react.useMemo)(
134
134
  () => removeBackgroundColor(style),
135
135
  [style]
136
136
  );
137
- const safeAreaEdges = (0, import_react2.useMemo)(
137
+ const safeAreaEdges = (0, import_react.useMemo)(
138
138
  () => resolveEdges(immersive, edges),
139
139
  [immersive, edges]
140
140
  );
@@ -149,7 +149,7 @@ function Layout({ immersive, edges, children, style }) {
149
149
  }
150
150
 
151
151
  // src/layout/Box.tsx
152
- var import_react3 = require("react");
152
+ var import_react2 = require("react");
153
153
  var import_react_native3 = require("react-native");
154
154
  var import_core3 = require("@onlynative/core");
155
155
 
@@ -188,7 +188,7 @@ function Box({
188
188
  ...viewProps
189
189
  }) {
190
190
  const { spacing } = (0, import_core3.useTheme)();
191
- const layoutStyle = (0, import_react3.useMemo)(() => {
191
+ const layoutStyle = (0, import_react2.useMemo)(() => {
192
192
  const s = (v) => resolveSpacing(spacing, v);
193
193
  return {
194
194
  ...p !== void 0 && { padding: s(p) },
@@ -253,10 +253,10 @@ function Box({
253
253
  }
254
254
 
255
255
  // src/layout/Column.tsx
256
- var import_react4 = require("react");
256
+ var import_react3 = require("react");
257
257
  var import_jsx_runtime4 = require("react/jsx-runtime");
258
258
  function Column({ inverted = false, style, ...boxProps }) {
259
- const directionStyle = (0, import_react4.useMemo)(
259
+ const directionStyle = (0, import_react3.useMemo)(
260
260
  () => ({
261
261
  flexDirection: inverted ? "column-reverse" : "column"
262
262
  }),
@@ -266,12 +266,12 @@ function Column({ inverted = false, style, ...boxProps }) {
266
266
  }
267
267
 
268
268
  // src/layout/Grid.tsx
269
- var import_react6 = __toESM(require("react"));
269
+ var import_react5 = __toESM(require("react"));
270
270
  var import_react_native4 = require("react-native");
271
271
  var import_core4 = require("@onlynative/core");
272
272
 
273
273
  // src/layout/Row.tsx
274
- var import_react5 = require("react");
274
+ var import_react4 = require("react");
275
275
  var import_jsx_runtime5 = require("react/jsx-runtime");
276
276
  function Row({
277
277
  wrap = false,
@@ -279,7 +279,7 @@ function Row({
279
279
  style,
280
280
  ...boxProps
281
281
  }) {
282
- const directionStyle = (0, import_react5.useMemo)(
282
+ const directionStyle = (0, import_react4.useMemo)(
283
283
  () => ({
284
284
  flexDirection: inverted ? "row-reverse" : "row",
285
285
  ...wrap && { flexWrap: "wrap" }
@@ -304,7 +304,7 @@ function Grid({
304
304
  const resolvedColumnGap = resolveSpacing(spacing, columnGap != null ? columnGap : gap);
305
305
  const resolvedRowGap = resolveSpacing(spacing, rowGap != null ? rowGap : gap);
306
306
  const halfGap = resolvedColumnGap ? resolvedColumnGap / 2 : 0;
307
- const cellStyle = (0, import_react6.useMemo)(
307
+ const cellStyle = (0, import_react5.useMemo)(
308
308
  () => ({
309
309
  flexBasis: `${100 / columns}%`,
310
310
  flexShrink: 1,
@@ -313,14 +313,14 @@ function Grid({
313
313
  }),
314
314
  [columns, halfGap]
315
315
  );
316
- const rowStyle = (0, import_react6.useMemo)(
316
+ const rowStyle = (0, import_react5.useMemo)(
317
317
  () => ({
318
318
  marginLeft: -halfGap,
319
319
  marginRight: -halfGap
320
320
  }),
321
321
  [halfGap]
322
322
  );
323
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Row, { wrap: true, rowGap: resolvedRowGap, ...rowProps, style: [rowStyle, style], children: import_react6.default.Children.map(
323
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Row, { wrap: true, rowGap: resolvedRowGap, ...rowProps, style: [rowStyle, style], children: import_react5.default.Children.map(
324
324
  children,
325
325
  (child) => child != null ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react_native4.View, { style: cellStyle, children: child }) : null
326
326
  ) });
@@ -328,7 +328,7 @@ function Grid({
328
328
 
329
329
  // src/button/Button.tsx
330
330
  var import_MaterialCommunityIcons = __toESM(require("@expo/vector-icons/MaterialCommunityIcons"));
331
- var import_react7 = require("react");
331
+ var import_react6 = require("react");
332
332
  var import_react_native7 = require("react-native");
333
333
  var import_react_native8 = require("react-native");
334
334
  var import_react_native9 = require("react-native");
@@ -674,7 +674,7 @@ function Button({
674
674
  const hasLeading = Boolean(leadingIcon);
675
675
  const hasTrailing = Boolean(trailingIcon);
676
676
  const theme = (0, import_core5.useTheme)();
677
- const styles2 = (0, import_react7.useMemo)(
677
+ const styles2 = (0, import_react6.useMemo)(
678
678
  () => createStyles(
679
679
  theme,
680
680
  variant,
@@ -685,14 +685,14 @@ function Button({
685
685
  ),
686
686
  [theme, variant, hasLeading, hasTrailing, containerColor, contentColor]
687
687
  );
688
- const resolvedIconColor = (0, import_react7.useMemo)(() => {
688
+ const resolvedIconColor = (0, import_react6.useMemo)(() => {
689
689
  const base = import_react_native8.StyleSheet.flatten([
690
690
  styles2.label,
691
691
  isDisabled ? styles2.disabledLabel : void 0
692
692
  ]);
693
693
  return typeof (base == null ? void 0 : base.color) === "string" ? base.color : void 0;
694
694
  }, [styles2.label, styles2.disabledLabel, isDisabled]);
695
- const computedLabelStyle = (0, import_react7.useMemo)(
695
+ const computedLabelStyle = (0, import_react6.useMemo)(
696
696
  () => [
697
697
  styles2.label,
698
698
  isDisabled ? styles2.disabledLabel : void 0,
@@ -743,7 +743,7 @@ function Button({
743
743
 
744
744
  // src/icon-button/IconButton.tsx
745
745
  var import_MaterialCommunityIcons2 = __toESM(require("@expo/vector-icons/MaterialCommunityIcons"));
746
- var import_react8 = require("react");
746
+ var import_react7 = require("react");
747
747
  var import_react_native11 = require("react-native");
748
748
  var import_core6 = require("@onlynative/core");
749
749
 
@@ -1156,7 +1156,7 @@ function IconButton({
1156
1156
  }) {
1157
1157
  var _a;
1158
1158
  const theme = (0, import_core6.useTheme)();
1159
- const styles2 = (0, import_react8.useMemo)(() => createStyles2(theme), [theme]);
1159
+ const styles2 = (0, import_react7.useMemo)(() => createStyles2(theme), [theme]);
1160
1160
  const isDisabled = Boolean(disabled);
1161
1161
  const isToggle = selected !== void 0;
1162
1162
  const isSelected = Boolean(selected);
@@ -1164,7 +1164,7 @@ function IconButton({
1164
1164
  const displayIcon = isToggle && isSelected && selectedIcon ? selectedIcon : icon;
1165
1165
  const iconPixelSize = getIconPixelSize(size);
1166
1166
  const accessibilityState = isToggle ? { disabled: isDisabled, selected: isSelected } : { disabled: isDisabled };
1167
- const containerOverrides = (0, import_react8.useMemo)(() => {
1167
+ const containerOverrides = (0, import_react7.useMemo)(() => {
1168
1168
  if (!containerColor) return null;
1169
1169
  const overlay = resolvedIconColor;
1170
1170
  return {
@@ -1232,7 +1232,7 @@ function IconButton({
1232
1232
  }
1233
1233
 
1234
1234
  // src/appbar/AppBar.tsx
1235
- var import_react9 = require("react");
1235
+ var import_react8 = require("react");
1236
1236
  var import_react_native14 = require("react-native");
1237
1237
  var import_react_native_safe_area_context2 = require("react-native-safe-area-context");
1238
1238
  var import_core8 = require("@onlynative/core");
@@ -1395,10 +1395,10 @@ function AppBar({
1395
1395
  var _a;
1396
1396
  const theme = (0, import_core8.useTheme)();
1397
1397
  const topAppBar = (_a = theme.topAppBar) != null ? _a : import_core8.defaultTopAppBarTokens;
1398
- const styles2 = (0, import_react9.useMemo)(() => createStyles3(theme), [theme]);
1399
- const [leadingWidth, setLeadingWidth] = (0, import_react9.useState)(0);
1400
- const [actionsWidth, setActionsWidth] = (0, import_react9.useState)(0);
1401
- const titleColorStyle = (0, import_react9.useMemo)(
1398
+ const styles2 = (0, import_react8.useMemo)(() => createStyles3(theme), [theme]);
1399
+ const [leadingWidth, setLeadingWidth] = (0, import_react8.useState)(0);
1400
+ const [actionsWidth, setActionsWidth] = (0, import_react8.useState)(0);
1401
+ const titleColorStyle = (0, import_react8.useMemo)(
1402
1402
  () => ({ color: contentColor != null ? contentColor : theme.colors.onSurface }),
1403
1403
  [contentColor, theme.colors.onSurface]
1404
1404
  );
@@ -1409,15 +1409,15 @@ function AppBar({
1409
1409
  const titleStartInset = topAppBar.horizontalPadding + Math.max(topAppBar.titleStartInset, leadingWidth);
1410
1410
  const compactTitleEndInset = topAppBar.horizontalPadding + actionsWidth;
1411
1411
  const centeredSideInset = topAppBar.horizontalPadding + Math.max(leadingWidth, actionsWidth);
1412
- const expandedTitleInsetStyle = (0, import_react9.useMemo)(
1412
+ const expandedTitleInsetStyle = (0, import_react8.useMemo)(
1413
1413
  () => ({ paddingStart: titleStartInset }),
1414
1414
  [titleStartInset]
1415
1415
  );
1416
- const overlayTitleInsetStyle = (0, import_react9.useMemo)(
1416
+ const overlayTitleInsetStyle = (0, import_react8.useMemo)(
1417
1417
  () => isCenterAligned ? { start: centeredSideInset, end: centeredSideInset } : { start: titleStartInset, end: compactTitleEndInset },
1418
1418
  [centeredSideInset, compactTitleEndInset, isCenterAligned, titleStartInset]
1419
1419
  );
1420
- const leadingContent = (0, import_react9.useMemo)(() => {
1420
+ const leadingContent = (0, import_react8.useMemo)(() => {
1421
1421
  if (leading) {
1422
1422
  return leading;
1423
1423
  }
@@ -1443,7 +1443,7 @@ function AppBar({
1443
1443
  styles2.iconFrame,
1444
1444
  theme.colors.onSurface
1445
1445
  ]);
1446
- const actionsContent = (0, import_react9.useMemo)(() => {
1446
+ const actionsContent = (0, import_react8.useMemo)(() => {
1447
1447
  if (trailing) {
1448
1448
  return trailing;
1449
1449
  }
@@ -1470,7 +1470,7 @@ function AppBar({
1470
1470
  `${String(action.icon)}-${index}`
1471
1471
  )) });
1472
1472
  }, [actions, contentColor, styles2.actionsRow, styles2.iconFrame, trailing]);
1473
- const onLeadingLayout = (0, import_react9.useCallback)((event) => {
1473
+ const onLeadingLayout = (0, import_react8.useCallback)((event) => {
1474
1474
  const nextWidth = measureWidth(event);
1475
1475
  setLeadingWidth((currentWidth) => {
1476
1476
  if (currentWidth === nextWidth) {
@@ -1479,7 +1479,7 @@ function AppBar({
1479
1479
  return nextWidth;
1480
1480
  });
1481
1481
  }, []);
1482
- const onActionsLayout = (0, import_react9.useCallback)((event) => {
1482
+ const onActionsLayout = (0, import_react8.useCallback)((event) => {
1483
1483
  const nextWidth = measureWidth(event);
1484
1484
  setActionsWidth((currentWidth) => {
1485
1485
  if (currentWidth === nextWidth) {
@@ -1572,7 +1572,7 @@ function AppBar({
1572
1572
  }
1573
1573
 
1574
1574
  // src/card/Card.tsx
1575
- var import_react10 = require("react");
1575
+ var import_react9 = require("react");
1576
1576
  var import_react_native16 = require("react-native");
1577
1577
  var import_core9 = require("@onlynative/core");
1578
1578
 
@@ -1706,7 +1706,7 @@ function Card({
1706
1706
  const isDisabled = Boolean(disabled);
1707
1707
  const isInteractive = onPress !== void 0;
1708
1708
  const theme = (0, import_core9.useTheme)();
1709
- const styles2 = (0, import_react10.useMemo)(
1709
+ const styles2 = (0, import_react9.useMemo)(
1710
1710
  () => createStyles4(theme, variant, containerColor),
1711
1711
  [theme, variant, containerColor]
1712
1712
  );
@@ -1738,7 +1738,7 @@ function Card({
1738
1738
 
1739
1739
  // src/chip/Chip.tsx
1740
1740
  var import_MaterialCommunityIcons3 = __toESM(require("@expo/vector-icons/MaterialCommunityIcons"));
1741
- var import_react11 = require("react");
1741
+ var import_react10 = require("react");
1742
1742
  var import_react_native18 = require("react-native");
1743
1743
  var import_core10 = require("@onlynative/core");
1744
1744
 
@@ -1969,7 +1969,7 @@ function Chip({
1969
1969
  variant === "input" && avatar || leadingIcon || variant === "filter" && isSelected
1970
1970
  );
1971
1971
  const theme = (0, import_core10.useTheme)();
1972
- const styles2 = (0, import_react11.useMemo)(
1972
+ const styles2 = (0, import_react10.useMemo)(
1973
1973
  () => createStyles5(
1974
1974
  theme,
1975
1975
  variant,
@@ -1991,14 +1991,14 @@ function Chip({
1991
1991
  contentColor
1992
1992
  ]
1993
1993
  );
1994
- const resolvedIconColor = (0, import_react11.useMemo)(() => {
1994
+ const resolvedIconColor = (0, import_react10.useMemo)(() => {
1995
1995
  const base = import_react_native18.StyleSheet.flatten([
1996
1996
  styles2.label,
1997
1997
  isDisabled ? styles2.disabledLabel : void 0
1998
1998
  ]);
1999
1999
  return typeof (base == null ? void 0 : base.color) === "string" ? base.color : void 0;
2000
2000
  }, [styles2.label, styles2.disabledLabel, isDisabled]);
2001
- const computedLabelStyle = (0, import_react11.useMemo)(
2001
+ const computedLabelStyle = (0, import_react10.useMemo)(
2002
2002
  () => [
2003
2003
  styles2.label,
2004
2004
  isDisabled ? styles2.disabledLabel : void 0,
@@ -2081,7 +2081,7 @@ function Chip({
2081
2081
 
2082
2082
  // src/checkbox/Checkbox.tsx
2083
2083
  var import_MaterialCommunityIcons4 = __toESM(require("@expo/vector-icons/MaterialCommunityIcons"));
2084
- var import_react12 = require("react");
2084
+ var import_react11 = require("react");
2085
2085
  var import_react_native20 = require("react-native");
2086
2086
  var import_core11 = require("@onlynative/core");
2087
2087
 
@@ -2237,11 +2237,11 @@ function Checkbox({
2237
2237
  const isDisabled = Boolean(disabled);
2238
2238
  const isChecked = Boolean(value);
2239
2239
  const theme = (0, import_core11.useTheme)();
2240
- const styles2 = (0, import_react12.useMemo)(
2240
+ const styles2 = (0, import_react11.useMemo)(
2241
2241
  () => createStyles6(theme, isChecked, containerColor, contentColor),
2242
2242
  [theme, isChecked, containerColor, contentColor]
2243
2243
  );
2244
- const resolvedIconColor = (0, import_react12.useMemo)(() => {
2244
+ const resolvedIconColor = (0, import_react11.useMemo)(() => {
2245
2245
  const base = import_react_native20.StyleSheet.flatten([
2246
2246
  styles2.iconColor,
2247
2247
  isDisabled ? styles2.disabledIconColor : void 0
@@ -2286,7 +2286,7 @@ function Checkbox({
2286
2286
  }
2287
2287
 
2288
2288
  // src/radio/Radio.tsx
2289
- var import_react13 = require("react");
2289
+ var import_react12 = require("react");
2290
2290
  var import_react_native22 = require("react-native");
2291
2291
  var import_core12 = require("@onlynative/core");
2292
2292
 
@@ -2430,7 +2430,7 @@ function Radio({
2430
2430
  const isDisabled = Boolean(disabled);
2431
2431
  const isSelected = Boolean(value);
2432
2432
  const theme = (0, import_core12.useTheme)();
2433
- const styles2 = (0, import_react13.useMemo)(
2433
+ const styles2 = (0, import_react12.useMemo)(
2434
2434
  () => createStyles7(theme, isSelected, containerColor, contentColor),
2435
2435
  [theme, isSelected, containerColor, contentColor]
2436
2436
  );
@@ -2480,7 +2480,7 @@ function Radio({
2480
2480
 
2481
2481
  // src/switch/Switch.tsx
2482
2482
  var import_MaterialCommunityIcons5 = __toESM(require("@expo/vector-icons/MaterialCommunityIcons"));
2483
- var import_react14 = require("react");
2483
+ var import_react13 = require("react");
2484
2484
  var import_react_native24 = require("react-native");
2485
2485
  var import_core13 = require("@onlynative/core");
2486
2486
 
@@ -2652,11 +2652,11 @@ function Switch({
2652
2652
  const isSelected = Boolean(value);
2653
2653
  const hasIcon = isSelected || Boolean(unselectedIcon);
2654
2654
  const theme = (0, import_core13.useTheme)();
2655
- const styles2 = (0, import_react14.useMemo)(
2655
+ const styles2 = (0, import_react13.useMemo)(
2656
2656
  () => createStyles8(theme, isSelected, hasIcon, containerColor, contentColor),
2657
2657
  [theme, isSelected, hasIcon, containerColor, contentColor]
2658
2658
  );
2659
- const resolvedIconColor = (0, import_react14.useMemo)(() => {
2659
+ const resolvedIconColor = (0, import_react13.useMemo)(() => {
2660
2660
  const base = import_react_native24.StyleSheet.flatten([
2661
2661
  styles2.iconColor,
2662
2662
  isDisabled ? styles2.disabledIconColor : void 0
@@ -2710,7 +2710,7 @@ function Switch({
2710
2710
 
2711
2711
  // src/text-field/TextField.tsx
2712
2712
  var import_MaterialCommunityIcons6 = __toESM(require("@expo/vector-icons/MaterialCommunityIcons"));
2713
- var import_react15 = require("react");
2713
+ var import_react14 = require("react");
2714
2714
  var import_react_native26 = require("react-native");
2715
2715
  var import_core14 = require("@onlynative/core");
2716
2716
 
@@ -2938,28 +2938,28 @@ function TextField({
2938
2938
  const isError = Boolean(error) || Boolean(errorText);
2939
2939
  const isFilled = variant === "filled";
2940
2940
  const hasLeadingIcon = Boolean(leadingIcon);
2941
- const { colors, styles: styles2 } = (0, import_react15.useMemo)(
2941
+ const { colors, styles: styles2 } = (0, import_react14.useMemo)(
2942
2942
  () => createStyles9(theme, variant),
2943
2943
  [theme, variant]
2944
2944
  );
2945
- const [isFocused, setIsFocused] = (0, import_react15.useState)(false);
2946
- const [internalHasText, setInternalHasText] = (0, import_react15.useState)(
2945
+ const [isFocused, setIsFocused] = (0, import_react14.useState)(false);
2946
+ const [internalHasText, setInternalHasText] = (0, import_react14.useState)(
2947
2947
  () => value !== void 0 && value !== ""
2948
2948
  );
2949
- const inputRef = (0, import_react15.useRef)(null);
2949
+ const inputRef = (0, import_react14.useRef)(null);
2950
2950
  const isControlled = value !== void 0;
2951
2951
  const hasValue = isControlled ? value !== "" : internalHasText;
2952
2952
  const isLabelFloated = isFocused || hasValue;
2953
- const labelAnimRef = (0, import_react15.useRef)(new import_react_native26.Animated.Value(isLabelFloated ? 1 : 0));
2953
+ const labelAnimRef = (0, import_react14.useRef)(new import_react_native26.Animated.Value(isLabelFloated ? 1 : 0));
2954
2954
  const labelAnim = labelAnimRef.current;
2955
- (0, import_react15.useEffect)(() => {
2955
+ (0, import_react14.useEffect)(() => {
2956
2956
  import_react_native26.Animated.timing(labelAnim, {
2957
2957
  toValue: isLabelFloated ? 1 : 0,
2958
2958
  duration: 150,
2959
2959
  useNativeDriver: import_react_native26.Platform.OS !== "web"
2960
2960
  }).start();
2961
2961
  }, [isLabelFloated, labelAnim]);
2962
- const labelScale = (0, import_react15.useMemo)(() => {
2962
+ const labelScale = (0, import_react14.useMemo)(() => {
2963
2963
  const restingScale = theme.typography.bodyLarge.fontSize / theme.typography.bodySmall.fontSize;
2964
2964
  return labelAnim.interpolate({
2965
2965
  inputRange: [0, 1],
@@ -2970,7 +2970,7 @@ function TextField({
2970
2970
  theme.typography.bodyLarge.fontSize,
2971
2971
  theme.typography.bodySmall.fontSize
2972
2972
  ]);
2973
- const labelTranslateY = (0, import_react15.useMemo)(() => {
2973
+ const labelTranslateY = (0, import_react14.useMemo)(() => {
2974
2974
  const restingTop = isFilled ? labelPositions.filledRestingTop : labelPositions.outlinedRestingTop;
2975
2975
  const floatedTop = isFilled ? labelPositions.filledFloatedTop : labelPositions.outlinedFloatedTop;
2976
2976
  const restingOffset = restingTop - floatedTop;
@@ -2981,7 +2981,7 @@ function TextField({
2981
2981
  }, [isFilled, labelAnim]);
2982
2982
  const labelStart = theme.spacing.md + (hasLeadingIcon ? ICON_WITH_GAP - theme.spacing.md : 0);
2983
2983
  const labelStaticTop = isFilled ? labelPositions.filledFloatedTop : labelPositions.outlinedFloatedTop;
2984
- const handleChangeText = (0, import_react15.useCallback)(
2984
+ const handleChangeText = (0, import_react14.useCallback)(
2985
2985
  (text) => {
2986
2986
  if (!isControlled) {
2987
2987
  setInternalHasText(text !== "");
@@ -2990,7 +2990,7 @@ function TextField({
2990
2990
  },
2991
2991
  [isControlled, onChangeText]
2992
2992
  );
2993
- const handleFocus = (0, import_react15.useCallback)(
2993
+ const handleFocus = (0, import_react14.useCallback)(
2994
2994
  (event) => {
2995
2995
  if (isDisabled) return;
2996
2996
  setIsFocused(true);
@@ -2998,14 +2998,14 @@ function TextField({
2998
2998
  },
2999
2999
  [isDisabled, onFocus]
3000
3000
  );
3001
- const handleBlur = (0, import_react15.useCallback)(
3001
+ const handleBlur = (0, import_react14.useCallback)(
3002
3002
  (event) => {
3003
3003
  setIsFocused(false);
3004
3004
  onBlur == null ? void 0 : onBlur(event);
3005
3005
  },
3006
3006
  [onBlur]
3007
3007
  );
3008
- const handleContainerPress = (0, import_react15.useCallback)(() => {
3008
+ const handleContainerPress = (0, import_react14.useCallback)(() => {
3009
3009
  var _a;
3010
3010
  if (!isDisabled) {
3011
3011
  (_a = inputRef.current) == null ? void 0 : _a.focus();
@@ -3014,7 +3014,7 @@ function TextField({
3014
3014
  const labelColor = isDisabled ? colors.disabledLabelColor : isError ? colors.errorLabelColor : isFocused ? colors.focusedLabelColor : colors.labelColor;
3015
3015
  const labelBackgroundColor = variant === "outlined" && isLabelFloated ? theme.colors.surface : "transparent";
3016
3016
  const iconColor = isDisabled ? colors.disabledIconColor : isError ? colors.errorIconColor : contentColor != null ? contentColor : colors.iconColor;
3017
- const containerStyle = (0, import_react15.useMemo)(
3017
+ const containerStyle = (0, import_react14.useMemo)(
3018
3018
  () => [
3019
3019
  styles2.container,
3020
3020
  containerColor && !isDisabled ? { backgroundColor: containerColor } : void 0,
@@ -3024,7 +3024,7 @@ function TextField({
3024
3024
  ],
3025
3025
  [styles2, isFocused, isError, isDisabled, containerColor]
3026
3026
  );
3027
- const indicatorStyle = (0, import_react15.useMemo)(
3027
+ const indicatorStyle = (0, import_react14.useMemo)(
3028
3028
  () => [
3029
3029
  styles2.indicator,
3030
3030
  isFocused && styles2.indicatorFocused,
@@ -3132,7 +3132,7 @@ function TextField({
3132
3132
  }
3133
3133
 
3134
3134
  // src/list/List.tsx
3135
- var import_react16 = require("react");
3135
+ var import_react15 = require("react");
3136
3136
  var import_react_native28 = require("react-native");
3137
3137
  var import_core15 = require("@onlynative/core");
3138
3138
 
@@ -3251,12 +3251,12 @@ function createDividerStyles(theme, inset) {
3251
3251
  var import_jsx_runtime16 = require("react/jsx-runtime");
3252
3252
  function List({ children, style, ...props }) {
3253
3253
  const theme = (0, import_core15.useTheme)();
3254
- const styles2 = (0, import_react16.useMemo)(() => createListStyles(theme), [theme]);
3254
+ const styles2 = (0, import_react15.useMemo)(() => createListStyles(theme), [theme]);
3255
3255
  return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_react_native28.View, { ...props, style: [styles2.container, style], children });
3256
3256
  }
3257
3257
 
3258
3258
  // src/list/ListItem.tsx
3259
- var import_react17 = require("react");
3259
+ var import_react16 = require("react");
3260
3260
  var import_react_native29 = require("react-native");
3261
3261
  var import_core16 = require("@onlynative/core");
3262
3262
  var import_jsx_runtime17 = require("react/jsx-runtime");
@@ -3285,7 +3285,7 @@ function ListItem({
3285
3285
  const isInteractive = onPress !== void 0;
3286
3286
  const theme = (0, import_core16.useTheme)();
3287
3287
  const lines = getLines(supportingText, overlineText, supportingTextNumberOfLines);
3288
- const styles2 = (0, import_react17.useMemo)(
3288
+ const styles2 = (0, import_react16.useMemo)(
3289
3289
  () => createListItemStyles(theme, lines, containerColor),
3290
3290
  [theme, lines, containerColor]
3291
3291
  );
@@ -3335,7 +3335,7 @@ function ListItem({
3335
3335
  }
3336
3336
 
3337
3337
  // src/list/ListDivider.tsx
3338
- var import_react18 = require("react");
3338
+ var import_react17 = require("react");
3339
3339
  var import_react_native30 = require("react-native");
3340
3340
  var import_core17 = require("@onlynative/core");
3341
3341
  var import_jsx_runtime18 = require("react/jsx-runtime");
@@ -3345,7 +3345,7 @@ function ListDivider({
3345
3345
  ...props
3346
3346
  }) {
3347
3347
  const theme = (0, import_core17.useTheme)();
3348
- const styles2 = (0, import_react18.useMemo)(
3348
+ const styles2 = (0, import_react17.useMemo)(
3349
3349
  () => createDividerStyles(theme, inset),
3350
3350
  [theme, inset]
3351
3351
  );
@@ -2,7 +2,7 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { PropsWithChildren } from 'react';
3
3
  import { StyleProp, ViewStyle, ViewProps, FlexAlignType } from 'react-native';
4
4
  import { Edge } from 'react-native-safe-area-context';
5
- import { Theme } from '@onlynative/core';
5
+ import { MaterialTheme } from '@onlynative/core';
6
6
 
7
7
  interface LayoutProps extends PropsWithChildren {
8
8
  /**
@@ -18,7 +18,7 @@ interface LayoutProps extends PropsWithChildren {
18
18
  declare function Layout({ immersive, edges, children, style }: LayoutProps): react_jsx_runtime.JSX.Element;
19
19
 
20
20
  /** A theme spacing token name or a raw numeric value in dp. */
21
- type SpacingValue = keyof Theme['spacing'] | number;
21
+ type SpacingValue = keyof MaterialTheme['spacing'] | number;
22
22
  interface BoxProps extends ViewProps {
23
23
  /** Padding on all sides */
24
24
  p?: SpacingValue;
@@ -13,9 +13,9 @@ interface TypographyProps extends Omit<TextProps, 'children' | 'style'> {
13
13
  * @default 'bodyMedium'
14
14
  */
15
15
  variant?: TypographyVariant;
16
- /** Override the text color. Defaults to the theme's `onSurface` color. */
16
+ /** Override the text color. Takes priority over `style.color`. Defaults to the theme's `onSurface` color. */
17
17
  color?: string;
18
- /** Additional text styles merged after the theme typography styles. */
18
+ /** Additional text styles. Can override the default theme color via `style.color` when no `color` prop is set. */
19
19
  style?: StyleProp<TextStyle>;
20
20
  /**
21
21
  * Override the underlying text component (e.g. Animated.Text).
@@ -25,7 +25,6 @@ __export(typography_exports, {
25
25
  module.exports = __toCommonJS(typography_exports);
26
26
 
27
27
  // src/typography/Typography.tsx
28
- var import_react = require("react");
29
28
  var import_react_native = require("react-native");
30
29
  var import_core = require("@onlynative/core");
31
30
  var import_jsx_runtime = require("react/jsx-runtime");
@@ -48,17 +47,18 @@ function Typography({
48
47
  }) {
49
48
  const theme = (0, import_core.useTheme)();
50
49
  const typographyStyle = theme.typography[variant];
51
- const colorStyle = (0, import_react.useMemo)(
52
- () => ({ color: color != null ? color : theme.colors.onSurface }),
53
- [color, theme.colors.onSurface]
54
- );
55
50
  const resolvedRole = accessibilityRole != null ? accessibilityRole : HEADING_VARIANTS.has(variant) ? "header" : void 0;
56
51
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
57
52
  Component,
58
53
  {
59
54
  ...textProps,
60
55
  accessibilityRole: resolvedRole,
61
- style: [typographyStyle, colorStyle, style],
56
+ style: [
57
+ { color: theme.colors.onSurface },
58
+ typographyStyle,
59
+ style,
60
+ color != null ? { color } : void 0
61
+ ],
62
62
  children
63
63
  }
64
64
  );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onlynative/components",
3
- "version": "0.1.0-alpha.0",
3
+ "version": "0.1.0-alpha.2",
4
4
  "description": "Material Design 3 UI components for React Native — Button, Card, Chip, TextField, and more.",
5
5
  "private": false,
6
6
  "sideEffects": false,
@@ -117,7 +117,8 @@
117
117
  }
118
118
  },
119
119
  "publishConfig": {
120
- "access": "public"
120
+ "access": "public",
121
+ "provenance": true
121
122
  },
122
123
  "files": [
123
124
  "dist",
@@ -145,11 +146,16 @@
145
146
  },
146
147
  "peerDependencies": {
147
148
  "@expo/vector-icons": ">=14.0.0",
148
- "@onlynative/core": ">=0.1.0-alpha.0",
149
+ "@onlynative/core": ">=0.1.0-alpha.2",
149
150
  "react": ">=18.0.0",
150
151
  "react-native": ">=0.72.0",
151
152
  "react-native-safe-area-context": ">=4.0.0"
152
153
  },
154
+ "peerDependenciesMeta": {
155
+ "@expo/vector-icons": {
156
+ "optional": true
157
+ }
158
+ },
153
159
  "devDependencies": {
154
160
  "@react-native/babel-preset": "^0.81.5",
155
161
  "@onlynative/core": "workspace:*",
@@ -1,8 +1,8 @@
1
1
  import { StyleSheet } from 'react-native'
2
2
  import { defaultTopAppBarTokens } from '@onlynative/core'
3
- import type { Theme } from '@onlynative/core'
3
+ import type { MaterialTheme } from '@onlynative/core'
4
4
 
5
- export function createStyles(theme: Theme) {
5
+ export function createStyles(theme: MaterialTheme) {
6
6
  const topAppBar = theme.topAppBar ?? defaultTopAppBarTokens
7
7
 
8
8
  return StyleSheet.create({
@@ -1,5 +1,5 @@
1
1
  import { StyleSheet } from 'react-native'
2
- import type { Theme } from '@onlynative/core'
2
+ import type { MaterialTheme } from '@onlynative/core'
3
3
 
4
4
  import type { ButtonVariant } from './types'
5
5
  import { alphaColor, blendColor } from '../utils/color'
@@ -17,7 +17,7 @@ interface VariantColors {
17
17
  disabledBorderColor: string
18
18
  }
19
19
 
20
- function getVariantColors(theme: Theme, variant: ButtonVariant): VariantColors {
20
+ function getVariantColors(theme: MaterialTheme, variant: ButtonVariant): VariantColors {
21
21
  const disabledContainerColor = alphaColor(theme.colors.onSurface, 0.12)
22
22
  const disabledLabelColor = alphaColor(theme.colors.onSurface, 0.38)
23
23
  const disabledOutlineColor = alphaColor(theme.colors.onSurface, 0.12)
@@ -129,7 +129,7 @@ function getVariantColors(theme: Theme, variant: ButtonVariant): VariantColors {
129
129
  }
130
130
 
131
131
  function getHorizontalPadding(
132
- theme: Theme,
132
+ theme: MaterialTheme,
133
133
  variant: ButtonVariant,
134
134
  hasLeadingIcon: boolean,
135
135
  hasTrailingIcon: boolean,
@@ -154,7 +154,7 @@ function getHorizontalPadding(
154
154
  }
155
155
 
156
156
  function applyColorOverrides(
157
- theme: Theme,
157
+ theme: MaterialTheme,
158
158
  colors: VariantColors,
159
159
  containerColor?: string,
160
160
  contentColor?: string,
@@ -209,7 +209,7 @@ function applyColorOverrides(
209
209
  }
210
210
 
211
211
  export function createStyles(
212
- theme: Theme,
212
+ theme: MaterialTheme,
213
213
  variant: ButtonVariant,
214
214
  hasLeadingIcon: boolean,
215
215
  hasTrailingIcon: boolean,
@@ -1,5 +1,5 @@
1
1
  import { StyleSheet } from 'react-native'
2
- import type { Theme } from '@onlynative/core'
2
+ import type { MaterialTheme } from '@onlynative/core'
3
3
 
4
4
  import type { CardVariant } from './types'
5
5
  import { alphaColor, blendColor } from '../utils/color'
@@ -15,7 +15,7 @@ interface VariantColors {
15
15
  disabledBorderColor: string
16
16
  }
17
17
 
18
- function getVariantColors(theme: Theme, variant: CardVariant): VariantColors {
18
+ function getVariantColors(theme: MaterialTheme, variant: CardVariant): VariantColors {
19
19
  const disabledContainerColor = alphaColor(theme.colors.onSurface, 0.12)
20
20
  const disabledOutlineColor = alphaColor(theme.colors.onSurface, 0.12)
21
21
 
@@ -78,7 +78,7 @@ function getVariantColors(theme: Theme, variant: CardVariant): VariantColors {
78
78
  }
79
79
 
80
80
  function applyColorOverrides(
81
- theme: Theme,
81
+ theme: MaterialTheme,
82
82
  colors: VariantColors,
83
83
  containerColor?: string,
84
84
  ): VariantColors {
@@ -103,7 +103,7 @@ function applyColorOverrides(
103
103
  }
104
104
 
105
105
  export function createStyles(
106
- theme: Theme,
106
+ theme: MaterialTheme,
107
107
  variant: CardVariant,
108
108
  containerColor?: string,
109
109
  ) {
@@ -1,5 +1,5 @@
1
1
  import { StyleSheet } from 'react-native'
2
- import type { Theme } from '@onlynative/core'
2
+ import type { MaterialTheme } from '@onlynative/core'
3
3
 
4
4
  import { alphaColor, blendColor } from '../utils/color'
5
5
 
@@ -16,7 +16,7 @@ interface BoxColors {
16
16
  disabledIconColor: string
17
17
  }
18
18
 
19
- function getColors(theme: Theme, checked: boolean): BoxColors {
19
+ function getColors(theme: MaterialTheme, checked: boolean): BoxColors {
20
20
  const disabledOnSurface38 = alphaColor(theme.colors.onSurface, 0.38)
21
21
 
22
22
  if (checked) {
@@ -63,7 +63,7 @@ function getColors(theme: Theme, checked: boolean): BoxColors {
63
63
  }
64
64
 
65
65
  function applyColorOverrides(
66
- theme: Theme,
66
+ theme: MaterialTheme,
67
67
  colors: BoxColors,
68
68
  containerColor?: string,
69
69
  contentColor?: string,
@@ -96,7 +96,7 @@ function applyColorOverrides(
96
96
  }
97
97
 
98
98
  export function createStyles(
99
- theme: Theme,
99
+ theme: MaterialTheme,
100
100
  checked: boolean,
101
101
  containerColor?: string,
102
102
  contentColor?: string,
@@ -1,5 +1,5 @@
1
1
  import { StyleSheet } from 'react-native'
2
- import type { Theme } from '@onlynative/core'
2
+ import type { MaterialTheme } from '@onlynative/core'
3
3
 
4
4
  import type { ChipVariant } from './types'
5
5
  import { alphaColor, blendColor } from '../utils/color'
@@ -18,7 +18,7 @@ interface VariantColors {
18
18
  }
19
19
 
20
20
  function getVariantColors(
21
- theme: Theme,
21
+ theme: MaterialTheme,
22
22
  variant: ChipVariant,
23
23
  elevated: boolean,
24
24
  selected: boolean,
@@ -106,7 +106,7 @@ function getVariantColors(
106
106
  }
107
107
 
108
108
  function applyColorOverrides(
109
- theme: Theme,
109
+ theme: MaterialTheme,
110
110
  colors: VariantColors,
111
111
  containerColor?: string,
112
112
  contentColor?: string,
@@ -161,7 +161,7 @@ function applyColorOverrides(
161
161
  }
162
162
 
163
163
  export function createStyles(
164
- theme: Theme,
164
+ theme: MaterialTheme,
165
165
  variant: ChipVariant,
166
166
  elevated: boolean,
167
167
  selected: boolean,
@@ -1,8 +1,8 @@
1
1
  import { StyleSheet } from 'react-native'
2
- import type { Theme } from '@onlynative/core'
2
+ import type { MaterialTheme } from '@onlynative/core'
3
3
  import { alphaColor, blendColor } from '../utils/color'
4
4
 
5
- export function createStyles(theme: Theme) {
5
+ export function createStyles(theme: MaterialTheme) {
6
6
  const disabledContainerColor = alphaColor(theme.colors.onSurface, 0.12)
7
7
  const disabledOutlineColor = alphaColor(theme.colors.onSurface, 0.12)
8
8
  const toggleUnselectedContainerColor = theme.colors.surfaceContainerHighest
@@ -1,8 +1,8 @@
1
- import type { Theme } from '@onlynative/core'
1
+ import type { MaterialTheme } from '@onlynative/core'
2
2
  import type { SpacingValue } from './types'
3
3
 
4
4
  export function resolveSpacing(
5
- spacing: Theme['spacing'],
5
+ spacing: MaterialTheme['spacing'],
6
6
  value: SpacingValue | undefined,
7
7
  ): number | undefined {
8
8
  if (value === undefined) return undefined
@@ -1,8 +1,8 @@
1
1
  import type { FlexAlignType, ViewProps } from 'react-native'
2
- import type { Theme } from '@onlynative/core'
2
+ import type { MaterialTheme } from '@onlynative/core'
3
3
 
4
4
  /** A theme spacing token name or a raw numeric value in dp. */
5
- export type SpacingValue = keyof Theme['spacing'] | number
5
+ export type SpacingValue = keyof MaterialTheme['spacing'] | number
6
6
 
7
7
  export interface BoxProps extends ViewProps {
8
8
  /** Padding on all sides */
@@ -1,5 +1,5 @@
1
1
  import { StyleSheet } from 'react-native'
2
- import type { Theme } from '@onlynative/core'
2
+ import type { MaterialTheme } from '@onlynative/core'
3
3
 
4
4
  import type { ListItemLines } from './types'
5
5
  import { alphaColor, blendColor } from '../utils/color'
@@ -13,7 +13,7 @@ const MIN_HEIGHT: Record<ListItemLines, number> = {
13
13
  3: 88,
14
14
  }
15
15
 
16
- export function createListStyles(theme: Theme) {
16
+ export function createListStyles(theme: MaterialTheme) {
17
17
  return StyleSheet.create({
18
18
  container: {
19
19
  paddingVertical: theme.spacing.sm,
@@ -27,7 +27,7 @@ interface ItemColors {
27
27
  pressedBackgroundColor: string
28
28
  }
29
29
 
30
- function getItemColors(theme: Theme, containerColor?: string): ItemColors {
30
+ function getItemColors(theme: MaterialTheme, containerColor?: string): ItemColors {
31
31
  const base = containerColor ?? 'transparent'
32
32
 
33
33
  if (containerColor) {
@@ -60,7 +60,7 @@ function getItemColors(theme: Theme, containerColor?: string): ItemColors {
60
60
  }
61
61
 
62
62
  export function createListItemStyles(
63
- theme: Theme,
63
+ theme: MaterialTheme,
64
64
  lines: ListItemLines,
65
65
  containerColor?: string,
66
66
  ) {
@@ -121,7 +121,7 @@ export function createListItemStyles(
121
121
  })
122
122
  }
123
123
 
124
- export function createDividerStyles(theme: Theme, inset: boolean) {
124
+ export function createDividerStyles(theme: MaterialTheme, inset: boolean) {
125
125
  return StyleSheet.create({
126
126
  divider: {
127
127
  height: 1,
@@ -1,7 +1,7 @@
1
1
  import { StyleSheet } from 'react-native'
2
- import type { Theme } from '@onlynative/core'
2
+ import type { MaterialTheme } from '@onlynative/core'
3
3
 
4
- import { alphaColor, blendColor } from '../utils/color'
4
+ import { alphaColor } from '../utils/color'
5
5
 
6
6
  interface RadioColors {
7
7
  borderColor: string
@@ -12,7 +12,7 @@ interface RadioColors {
12
12
  disabledDotColor: string
13
13
  }
14
14
 
15
- function getColors(theme: Theme, selected: boolean): RadioColors {
15
+ function getColors(theme: MaterialTheme, selected: boolean): RadioColors {
16
16
  const disabledOnSurface38 = alphaColor(theme.colors.onSurface, 0.38)
17
17
 
18
18
  if (selected) {
@@ -49,7 +49,7 @@ function getColors(theme: Theme, selected: boolean): RadioColors {
49
49
  }
50
50
 
51
51
  function applyColorOverrides(
52
- theme: Theme,
52
+ theme: MaterialTheme,
53
53
  colors: RadioColors,
54
54
  containerColor?: string,
55
55
  contentColor?: string,
@@ -79,7 +79,7 @@ function applyColorOverrides(
79
79
  }
80
80
 
81
81
  export function createStyles(
82
- theme: Theme,
82
+ theme: MaterialTheme,
83
83
  selected: boolean,
84
84
  containerColor?: string,
85
85
  contentColor?: string,
@@ -1,5 +1,5 @@
1
1
  import { StyleSheet } from 'react-native'
2
- import type { Theme } from '@onlynative/core'
2
+ import type { MaterialTheme } from '@onlynative/core'
3
3
 
4
4
  import { alphaColor, blendColor } from '../utils/color'
5
5
 
@@ -17,7 +17,7 @@ interface TrackColors {
17
17
  disabledBorderWidth: number
18
18
  }
19
19
 
20
- function getColors(theme: Theme, selected: boolean): TrackColors {
20
+ function getColors(theme: MaterialTheme, selected: boolean): TrackColors {
21
21
  const disabledOnSurface12 = alphaColor(theme.colors.onSurface, 0.12)
22
22
  const disabledOnSurface38 = alphaColor(theme.colors.onSurface, 0.38)
23
23
 
@@ -69,7 +69,7 @@ function getColors(theme: Theme, selected: boolean): TrackColors {
69
69
  }
70
70
 
71
71
  function applyColorOverrides(
72
- theme: Theme,
72
+ theme: MaterialTheme,
73
73
  colors: TrackColors,
74
74
  containerColor?: string,
75
75
  contentColor?: string,
@@ -106,7 +106,7 @@ function applyColorOverrides(
106
106
  }
107
107
 
108
108
  export function createStyles(
109
- theme: Theme,
109
+ theme: MaterialTheme,
110
110
  selected: boolean,
111
111
  hasIcon: boolean,
112
112
  containerColor?: string,
@@ -1,13 +1,13 @@
1
1
  import { render, type RenderOptions } from '@testing-library/react-native'
2
2
  import type { ReactElement } from 'react'
3
- import { MaterialProvider } from '@onlynative/core'
3
+ import { ThemeProvider } from '@onlynative/core'
4
4
 
5
5
  export function renderWithTheme(
6
6
  ui: ReactElement,
7
7
  options?: Omit<RenderOptions, 'wrapper'>,
8
8
  ) {
9
9
  return render(ui, {
10
- wrapper: ({ children }) => <MaterialProvider>{children}</MaterialProvider>,
10
+ wrapper: ({ children }) => <ThemeProvider>{children}</ThemeProvider>,
11
11
  ...options,
12
12
  })
13
13
  }
@@ -1,5 +1,5 @@
1
1
  import { StyleSheet } from 'react-native'
2
- import type { Theme } from '@onlynative/core'
2
+ import type { MaterialTheme } from '@onlynative/core'
3
3
 
4
4
  import type { TextFieldVariant } from './types'
5
5
  import { alphaColor } from '../utils/color'
@@ -51,7 +51,7 @@ interface VariantColors {
51
51
  }
52
52
 
53
53
  function getVariantColors(
54
- theme: Theme,
54
+ theme: MaterialTheme,
55
55
  variant: TextFieldVariant,
56
56
  ): VariantColors {
57
57
  const disabledOpacity = theme.stateLayer.disabledOpacity
@@ -92,7 +92,7 @@ function getVariantColors(
92
92
  }
93
93
  }
94
94
 
95
- export function createStyles(theme: Theme, variant: TextFieldVariant) {
95
+ export function createStyles(theme: MaterialTheme, variant: TextFieldVariant) {
96
96
  const colors = getVariantColors(theme, variant)
97
97
  const bodyLarge = theme.typography.bodyLarge
98
98
  const bodySmall = theme.typography.bodySmall
@@ -1,9 +1,8 @@
1
- import { useMemo } from 'react'
2
1
  import type { ComponentType, ReactNode } from 'react'
3
2
  import type { StyleProp, TextProps, TextStyle } from 'react-native'
4
3
  import { Text } from 'react-native'
5
4
  import { useTheme } from '@onlynative/core'
6
- import type { Theme } from '@onlynative/core'
5
+ import type { MaterialTheme } from '@onlynative/core'
7
6
 
8
7
  import type { TypographyVariant } from './types'
9
8
 
@@ -24,9 +23,9 @@ export interface TypographyProps extends Omit<TextProps, 'children' | 'style'> {
24
23
  * @default 'bodyMedium'
25
24
  */
26
25
  variant?: TypographyVariant
27
- /** Override the text color. Defaults to the theme's `onSurface` color. */
26
+ /** Override the text color. Takes priority over `style.color`. Defaults to the theme's `onSurface` color. */
28
27
  color?: string
29
- /** Additional text styles merged after the theme typography styles. */
28
+ /** Additional text styles. Can override the default theme color via `style.color` when no `color` prop is set. */
30
29
  style?: StyleProp<TextStyle>
31
30
  /**
32
31
  * Override the underlying text component (e.g. Animated.Text).
@@ -44,12 +43,8 @@ export function Typography({
44
43
  accessibilityRole,
45
44
  ...textProps
46
45
  }: TypographyProps) {
47
- const theme = useTheme() as Theme
46
+ const theme = useTheme() as MaterialTheme
48
47
  const typographyStyle = theme.typography[variant]
49
- const colorStyle = useMemo(
50
- () => ({ color: color ?? theme.colors.onSurface }),
51
- [color, theme.colors.onSurface],
52
- )
53
48
  const resolvedRole =
54
49
  accessibilityRole ?? (HEADING_VARIANTS.has(variant) ? 'header' : undefined)
55
50
 
@@ -57,7 +52,12 @@ export function Typography({
57
52
  <Component
58
53
  {...textProps}
59
54
  accessibilityRole={resolvedRole}
60
- style={[typographyStyle, colorStyle, style]}
55
+ style={[
56
+ { color: theme.colors.onSurface },
57
+ typographyStyle,
58
+ style,
59
+ color != null ? { color } : undefined,
60
+ ]}
61
61
  >
62
62
  {children}
63
63
  </Component>