@mrmeg/expo-ui 0.22.0 → 0.23.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/CHANGELOG.md CHANGED
@@ -3,6 +3,37 @@
3
3
  All notable changes to `@mrmeg/expo-ui` are documented here. This project
4
4
  adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
5
5
 
6
+ ## [0.23.0]
7
+
8
+ ### Added
9
+
10
+ - **Density tokens.** `spacing` gains `smd` (12) and `mdl` (20) scale steps plus
11
+ semantic layout tokens: `screenPadding`, `sectionSpacing` (now 24),
12
+ `cardPadding`, `dialogPadding`, `rowPaddingY`/`rowPaddingX`, `rowGap`,
13
+ `rowMinHeight`, and `formRowMinHeight`. Components read these so a single
14
+ retune shifts the whole library's density.
15
+
16
+ ### Changed
17
+
18
+ - **Compact surfaces and rows.** `Card` header/content/footer padding drops
19
+ from 24 to 16 with a 16px title. `Item` rows use 10/16 padding and a 12px
20
+ gap, with a 40px visual min height on web while native keeps the 44pt touch
21
+ target. `Checkbox` and `RadioGroup` rows are 32px on web (native unchanged).
22
+ `Dialog`/`AlertDialog` padding is 20, `StatCard` padding is 16,
23
+ `EmptyState` vertical padding is 32, and `Accordion` triggers use 12px
24
+ vertical padding.
25
+ - **Dialog spacing is symmetric.** `DialogContent` and `AlertDialogContent`
26
+ space their children with a 16px gap instead of fixed header/footer
27
+ margins, so a header-only dialog no longer reads bottom-heavy.
28
+
29
+ ### Fixed
30
+
31
+ - **Dialog could not be dismissed on web.** The web overlay primitive wrapped
32
+ the backdrop in a react-native-web `Pressable` whose click handler stopped
33
+ propagation, so outside presses (mouse and touch) and Escape never reached
34
+ Radix. `DialogContent` now renders the overlay `asChild` on web; native is
35
+ unchanged.
36
+
6
37
  ## [0.22.0]
7
38
 
8
39
  ### Added
package/LLM_USAGE.md CHANGED
@@ -157,11 +157,18 @@ semantic colors without destructuring `withAlpha` outside the factory:
157
157
  const { styles } = useStyles(({ theme, spacing, withAlpha }) => ({
158
158
  card: {
159
159
  backgroundColor: withAlpha(theme.colors.primary, 0.08),
160
- padding: spacing.md,
160
+ padding: spacing.cardPadding,
161
161
  },
162
162
  }));
163
163
  ```
164
164
 
165
+ Layout spacing uses semantic density tokens rather than raw scale steps:
166
+ `spacing.screenPadding` (16) for screen and block gutters, `spacing.cardPadding`
167
+ (16) for bordered panels, `spacing.sectionSpacing` (24) between grouped lists,
168
+ `spacing.dialogPadding` (20) for dialogs, and `spacing.rowPaddingY`/`rowPaddingX`
169
+ (10/16) with `spacing.rowGap` (12) for list rows. `Item` already applies the row
170
+ tokens and keeps a 44px hit area on native while rendering 40px on web.
171
+
165
172
  When the saved theme preference is `system`, the package theme store owns the
166
173
  OS color-scheme subscription, including web `prefers-color-scheme`. Do not add
167
174
  app-local Appearance or `matchMedia` listeners for package components; import
package/README.md CHANGED
@@ -124,6 +124,24 @@ const { styles } = useStyles(({ theme, spacing, withAlpha }) => ({
124
124
  }));
125
125
  ```
126
126
 
127
+ ### Spacing and density
128
+
129
+ `spacing` exposes an 8px base scale (`xxs` 2, `xs` 4, `sm` 8, `smd` 12, `md` 16, `mdl` 20, `lg` 24, `xl` 32, `xxl` 48, `xxxl` 64) plus semantic density tokens that package components read from. Reach for the semantic names in app code so a future density tune lands everywhere at once:
130
+
131
+ | Token | Value | Use |
132
+ |-------|-------|-----|
133
+ | `screenPadding` | 16 | Horizontal gutter for screens, scroll content, and landing blocks |
134
+ | `sectionSpacing` | 24 | Gap between grouped lists, cards, or settings groups |
135
+ | `cardPadding` | 16 | `Card`, `StatCard`, and any bordered panel |
136
+ | `dialogPadding` | 20 | `Dialog` and `AlertDialog` content |
137
+ | `rowPaddingY` / `rowPaddingX` | 10 / 16 | `Item` rows and hand-rolled list rows |
138
+ | `rowGap` | 12 | Gap between row media, content, and actions |
139
+ | `rowMinHeight` | 40 | Visual row height on web; native rows keep `touchTarget` |
140
+ | `formRowMinHeight` | 32 | Checkbox and radio rows on web; native keeps `touchTarget` |
141
+ | `touchTarget` | 44 | Minimum native hit area; pair a smaller visual height with `hitSlop` |
142
+
143
+ Controls (`Button`, `TextInput`, `Select`, `Tabs`, `Toggle`) size themselves from their own `size` prop (28/32/36/40) and do not read these tokens.
144
+
127
145
  ### Color overrides
128
146
 
129
147
  The package ships a neutral default palette. `useTheme()` resolves colors in
@@ -132,7 +132,7 @@ function AccordionTrigger({ children, style: styleOverride, disabled, ...props }
132
132
  justifyContent: "space-between",
133
133
  gap: spacing.md,
134
134
  borderRadius: spacing.radiusMd,
135
- paddingVertical: spacing.md,
135
+ paddingVertical: spacing.smd,
136
136
  ...(Platform.OS === "web" && {
137
137
  cursor: "pointer",
138
138
  userSelect: "none",
@@ -98,24 +98,24 @@ const createCardStyles = (theme) => StyleSheet.create({
98
98
  backgroundColor: "transparent",
99
99
  },
100
100
  header: {
101
- padding: spacing.lg,
101
+ padding: spacing.cardPadding,
102
102
  paddingBottom: spacing.xs,
103
103
  gap: spacing.xs,
104
104
  },
105
105
  content: {
106
- paddingHorizontal: spacing.lg,
107
- paddingBottom: spacing.lg,
106
+ paddingHorizontal: spacing.cardPadding,
107
+ paddingBottom: spacing.cardPadding,
108
108
  },
109
109
  footer: {
110
110
  flexDirection: "row",
111
111
  alignItems: "center",
112
- paddingHorizontal: spacing.lg,
113
- paddingBottom: spacing.lg,
112
+ paddingHorizontal: spacing.cardPadding,
113
+ paddingBottom: spacing.cardPadding,
114
114
  paddingTop: 0,
115
115
  },
116
116
  title: {
117
- fontSize: 18,
118
- lineHeight: 24,
117
+ fontSize: 16,
118
+ lineHeight: 22,
119
119
  letterSpacing: 0,
120
120
  },
121
121
  description: {
@@ -117,7 +117,7 @@ const styles = StyleSheet.create({
117
117
  flexDirection: "row",
118
118
  alignItems: "center",
119
119
  gap: spacing.sm,
120
- minHeight: spacing.touchTarget,
120
+ minHeight: Platform.select({ web: spacing.formRowMinHeight, default: spacing.touchTarget }),
121
121
  },
122
122
  labelContainer: {
123
123
  flex: 1,
@@ -22,7 +22,25 @@ function DialogRoot({ children, ...props }) {
22
22
  function DialogContent({ portalHost, style, children, ...props }) {
23
23
  const { theme, getShadowStyle, getContrastingColor } = useTheme();
24
24
  const textColor = getContrastingColor(theme.colors.popover, palette.white, palette.black);
25
- return (_jsx(DialogPrimitive.Portal, { hostName: portalHost, children: _jsx(FullWindowOverlay, { children: _jsx(DialogPrimitive.Overlay, { style: StyleSheet.flatten([
25
+ return (_jsx(DialogPrimitive.Portal, { hostName: portalHost, children: _jsx(FullWindowOverlay, { children: _jsx(DialogPrimitive.Overlay
26
+ // On web the primitive wraps the overlay in a react-native-web
27
+ // Pressable whose click handler stops propagation unconditionally.
28
+ // With that Pressable between the overlay and the Radix content,
29
+ // outside presses (mouse and touch) and Escape never dismissed the
30
+ // dialog, so a dialog without a Close button was stuck. `asChild`
31
+ // makes the primitive clone our fade wrapper instead, removing the
32
+ // Pressable; Radix dismissal then works. Native keeps the Pressable,
33
+ // which is what implements closeOnPress there.
34
+ , {
35
+ // On web the primitive wraps the overlay in a react-native-web
36
+ // Pressable whose click handler stops propagation unconditionally.
37
+ // With that Pressable between the overlay and the Radix content,
38
+ // outside presses (mouse and touch) and Escape never dismissed the
39
+ // dialog, so a dialog without a Close button was stuck. `asChild`
40
+ // makes the primitive clone our fade wrapper instead, removing the
41
+ // Pressable; Radix dismissal then works. Native keeps the Pressable,
42
+ // which is what implements closeOnPress there.
43
+ asChild: Platform.OS === "web", style: StyleSheet.flatten([
26
44
  StyleSheet.absoluteFill,
27
45
  { backgroundColor: theme.colors.overlay },
28
46
  Platform.OS === "web" && { zIndex: 50 },
@@ -32,7 +50,8 @@ function DialogContent({ portalHost, style, children, ...props }) {
32
50
  borderColor: theme.colors.border,
33
51
  borderWidth: 1,
34
52
  borderRadius: spacing.radiusLg,
35
- padding: spacing.lg,
53
+ padding: spacing.dialogPadding,
54
+ gap: spacing.md,
36
55
  width: "100%",
37
56
  ...getShadowStyle("soft"),
38
57
  },
@@ -40,7 +59,7 @@ function DialogContent({ portalHost, style, children, ...props }) {
40
59
  ]), ...props, children: children }) }) }) }) }) }) }) }) }));
41
60
  }
42
61
  function DialogHeader({ children, style, ...props }) {
43
- return (_jsx(View, { style: StyleSheet.flatten([{ gap: spacing.xs, marginBottom: spacing.md }, style]), ...props, children: children }));
62
+ return (_jsx(View, { style: StyleSheet.flatten([{ gap: spacing.xs }, style]), ...props, children: children }));
44
63
  }
45
64
  function DialogFooter({ children, style, ...props }) {
46
65
  return (_jsx(View, { style: StyleSheet.flatten([
@@ -48,7 +67,6 @@ function DialogFooter({ children, style, ...props }) {
48
67
  flexDirection: "row",
49
68
  justifyContent: "flex-end",
50
69
  gap: spacing.sm,
51
- marginTop: spacing.lg,
52
70
  },
53
71
  style,
54
72
  ]), ...props, children: children }));
@@ -107,7 +125,8 @@ function AlertDialogContent({ portalHost, style, children, ...props }) {
107
125
  borderColor: theme.colors.border,
108
126
  borderWidth: 1,
109
127
  borderRadius: spacing.radiusLg,
110
- padding: spacing.lg,
128
+ padding: spacing.dialogPadding,
129
+ gap: spacing.md,
111
130
  width: "100%",
112
131
  ...getShadowStyle("soft"),
113
132
  },
@@ -33,7 +33,7 @@ const createStyles = (theme) => StyleSheet.create({
33
33
  container: {
34
34
  alignItems: "center",
35
35
  justifyContent: "center",
36
- paddingVertical: spacing.xxl,
36
+ paddingVertical: spacing.xl,
37
37
  paddingHorizontal: spacing.lg,
38
38
  },
39
39
  bordered: {
@@ -41,7 +41,7 @@ const createStyles = (theme) => StyleSheet.create({
41
41
  borderStyle: "dashed",
42
42
  borderColor: theme.colors.border,
43
43
  borderRadius: spacing.radiusLg,
44
- padding: spacing.xl,
44
+ padding: spacing.lg,
45
45
  },
46
46
  iconWrapper: {
47
47
  width: MEDIA_SIZE,
@@ -16,8 +16,9 @@ export interface ItemProps {
16
16
  /**
17
17
  * Item
18
18
  *
19
- * Grouped-list row container: `spacing.md` padding and gap, a comfortable
20
- * 44pt min height, and an optional pressable scale interaction. Compose
19
+ * Grouped-list row container: compact row padding (`spacing.rowPaddingY` /
20
+ * `spacing.rowPaddingX`) and gap, a 44pt min height on native (40 on web),
21
+ * and an optional pressable scale interaction. Compose
21
22
  * with `ItemMedia`, `ItemContent` (+ `ItemTitle`/`ItemDescription`), and
22
23
  * `ItemActions`.
23
24
  *
@@ -8,12 +8,13 @@ import { spacing } from "../constants/spacing.js";
8
8
  // Default ItemMedia footprint (see ItemMedia's `size` prop) — used to inset
9
9
  // the optional separator past the media slot without needing a context.
10
10
  const DEFAULT_MEDIA_SIZE = 40;
11
- const SEPARATOR_INSET = spacing.md + DEFAULT_MEDIA_SIZE + spacing.md;
11
+ const SEPARATOR_INSET = spacing.rowPaddingX + DEFAULT_MEDIA_SIZE + spacing.rowGap;
12
12
  /**
13
13
  * Item
14
14
  *
15
- * Grouped-list row container: `spacing.md` padding and gap, a comfortable
16
- * 44pt min height, and an optional pressable scale interaction. Compose
15
+ * Grouped-list row container: compact row padding (`spacing.rowPaddingY` /
16
+ * `spacing.rowPaddingX`) and gap, a 44pt min height on native (40 on web),
17
+ * and an optional pressable scale interaction. Compose
17
18
  * with `ItemMedia`, `ItemContent` (+ `ItemTitle`/`ItemDescription`), and
18
19
  * `ItemActions`.
19
20
  *
@@ -104,9 +105,10 @@ const styles = StyleSheet.create({
104
105
  row: {
105
106
  flexDirection: "row",
106
107
  alignItems: "center",
107
- minHeight: spacing.touchTarget,
108
- padding: spacing.md,
109
- gap: spacing.md,
108
+ minHeight: Platform.select({ web: spacing.rowMinHeight, default: spacing.touchTarget }),
109
+ paddingVertical: spacing.rowPaddingY,
110
+ paddingHorizontal: spacing.rowPaddingX,
111
+ gap: spacing.rowGap,
110
112
  },
111
113
  content: {
112
114
  flex: 1,
@@ -151,7 +151,7 @@ const styles = StyleSheet.create({
151
151
  flexDirection: "row",
152
152
  alignItems: "center",
153
153
  gap: spacing.sm,
154
- minHeight: spacing.touchTarget,
154
+ minHeight: Platform.select({ web: spacing.formRowMinHeight, default: spacing.touchTarget }),
155
155
  },
156
156
  labelContainer: {
157
157
  flex: 1,
@@ -37,5 +37,5 @@ export function StatCard({ label, value, unit, change, icon, onPress, style }) {
37
37
  : change.direction === "down"
38
38
  ? theme.colors.destructive
39
39
  : theme.colors.textDim;
40
- return (_jsx(Card, { onPress: onPress, style: style, children: _jsxs(View, { style: { padding: spacing.lg, gap: spacing.xs }, children: [_jsxs(View, { style: { flexDirection: "row", alignItems: "center", justifyContent: "space-between" }, children: [_jsx(CaptionText, { selectable: false, style: { color: theme.colors.textDim, textTransform: "uppercase", letterSpacing: 0.96 }, children: label }), !!icon && _jsx(Icon, { name: icon, size: spacing.iconSm, color: theme.colors.mutedForeground, decorative: true })] }), _jsxs(View, { style: { flexDirection: "row", alignItems: "flex-end" }, children: [_jsx(StyledText, { selectable: false, size: "xxl", fontWeight: "bold", style: { color: theme.colors.foreground, fontVariant: ["tabular-nums"] }, children: value }), !!unit && (_jsx(StyledText, { selectable: false, size: "base", style: { color: theme.colors.textDim, marginLeft: spacing.xxs, marginBottom: 2 }, children: unit }))] }), !!change && (_jsxs(View, { style: { flexDirection: "row", alignItems: "center", gap: spacing.xxs }, children: [change.direction !== "neutral" && (_jsx(Icon, { name: DIRECTION_ICON[change.direction], size: spacing.iconXs, color: changeColor, decorative: true })), _jsx(StyledText, { selectable: false, size: "sm", style: { color: changeColor }, children: change.value })] }))] }) }));
40
+ return (_jsx(Card, { onPress: onPress, style: style, children: _jsxs(View, { style: { padding: spacing.cardPadding, gap: spacing.xs }, children: [_jsxs(View, { style: { flexDirection: "row", alignItems: "center", justifyContent: "space-between" }, children: [_jsx(CaptionText, { selectable: false, style: { color: theme.colors.textDim, textTransform: "uppercase", letterSpacing: 0.96 }, children: label }), !!icon && _jsx(Icon, { name: icon, size: spacing.iconSm, color: theme.colors.mutedForeground, decorative: true })] }), _jsxs(View, { style: { flexDirection: "row", alignItems: "flex-end" }, children: [_jsx(StyledText, { selectable: false, size: "xxl", fontWeight: "bold", style: { color: theme.colors.foreground, fontVariant: ["tabular-nums"] }, children: value }), !!unit && (_jsx(StyledText, { selectable: false, size: "base", style: { color: theme.colors.textDim, marginLeft: spacing.xxs, marginBottom: 2 }, children: unit }))] }), !!change && (_jsxs(View, { style: { flexDirection: "row", alignItems: "center", gap: spacing.xxs }, children: [change.direction !== "neutral" && (_jsx(Icon, { name: DIRECTION_ICON[change.direction], size: spacing.iconXs, color: changeColor, decorative: true })), _jsx(StyledText, { selectable: false, size: "sm", style: { color: changeColor }, children: change.value })] }))] }) }));
41
41
  }
@@ -1,15 +1,19 @@
1
1
  /**
2
2
  * Spacing Constants
3
3
  *
4
- * A consistent spacing scale based on an 8px base unit.
5
- * Use these constants throughout the app for consistent spacing.
4
+ * A consistent spacing scale based on an 8px base unit, plus a small set of
5
+ * density tokens that components reach for when composing rows, surfaces, and
6
+ * screens. Tune the density tokens to shift the whole library's feel without
7
+ * touching the base scale.
6
8
  */
7
9
  export declare const spacing: {
8
10
  readonly base: 8;
9
11
  readonly xxs: 2;
10
12
  readonly xs: 4;
11
13
  readonly sm: 8;
14
+ readonly smd: 12;
12
15
  readonly md: 16;
16
+ readonly mdl: 20;
13
17
  readonly lg: 24;
14
18
  readonly xl: 32;
15
19
  readonly xxl: 48;
@@ -17,12 +21,18 @@ export declare const spacing: {
17
21
  readonly gutter: 16;
18
22
  readonly gutterVertical: 24;
19
23
  readonly screenPadding: 16;
24
+ readonly sectionSpacing: 24;
25
+ readonly rowPaddingY: 10;
26
+ readonly rowPaddingX: 16;
27
+ readonly rowGap: 12;
28
+ readonly rowMinHeight: 40;
29
+ readonly formRowMinHeight: 32;
30
+ readonly cardPadding: 16;
31
+ readonly dialogPadding: 20;
32
+ readonly touchTarget: 44;
20
33
  readonly buttonPadding: 10;
21
34
  readonly inputPadding: 10;
22
- readonly cardPadding: 16;
23
- readonly sectionSpacing: 32;
24
35
  readonly listItemSpacing: 8;
25
- readonly touchTarget: 44;
26
36
  readonly radiusNone: 0;
27
37
  readonly radiusXs: 4;
28
38
  readonly radiusSm: 8;
@@ -37,5 +47,5 @@ export declare const spacing: {
37
47
  readonly iconLg: 32;
38
48
  readonly iconXl: 48;
39
49
  };
40
- export declare const base: 8, xxs: 2, xs: 4, sm: 8, md: 16, lg: 24, xl: 32, xxl: 48, xxxl: 64, gutter: 16, gutterVertical: 24, screenPadding: 16, buttonPadding: 10, inputPadding: 10, cardPadding: 16, sectionSpacing: 32, listItemSpacing: 8, touchTarget: 44, radiusNone: 0, radiusXs: 4, radiusSm: 8, radiusMd: 12, radiusLg: 14, radiusXl: 18, radius2xl: 24, radiusFull: 9999, iconXs: 12, iconSm: 16, iconMd: 24, iconLg: 32, iconXl: 48;
50
+ export declare const base: 8, xxs: 2, xs: 4, sm: 8, smd: 12, md: 16, mdl: 20, lg: 24, xl: 32, xxl: 48, xxxl: 64, gutter: 16, gutterVertical: 24, screenPadding: 16, sectionSpacing: 24, rowPaddingY: 10, rowPaddingX: 16, rowGap: 12, rowMinHeight: 40, formRowMinHeight: 32, cardPadding: 16, dialogPadding: 20, touchTarget: 44, buttonPadding: 10, inputPadding: 10, listItemSpacing: 8, radiusNone: 0, radiusXs: 4, radiusSm: 8, radiusMd: 12, radiusLg: 14, radiusXl: 18, radius2xl: 24, radiusFull: 9999, iconXs: 12, iconSm: 16, iconMd: 24, iconLg: 32, iconXl: 48;
41
51
  export declare const space: (multiplier: number) => number;
@@ -1,8 +1,10 @@
1
1
  /**
2
2
  * Spacing Constants
3
3
  *
4
- * A consistent spacing scale based on an 8px base unit.
5
- * Use these constants throughout the app for consistent spacing.
4
+ * A consistent spacing scale based on an 8px base unit, plus a small set of
5
+ * density tokens that components reach for when composing rows, surfaces, and
6
+ * screens. Tune the density tokens to shift the whole library's feel without
7
+ * touching the base scale.
6
8
  */
7
9
  export const spacing = {
8
10
  // Base unit: 8px
@@ -11,7 +13,9 @@ export const spacing = {
11
13
  xxs: 2, // 2px - Minimal spacing
12
14
  xs: 4, // 4px - Extra small
13
15
  sm: 8, // 8px - Small (1 unit)
16
+ smd: 12, // 12px - Between small and medium (1.5 units); compact gaps and row padding
14
17
  md: 16, // 16px - Medium (2 units)
18
+ mdl: 20, // 20px - Between medium and large (2.5 units); dialog and sheet padding
15
19
  lg: 24, // 24px - Large (3 units)
16
20
  xl: 32, // 32px - Extra large (4 units)
17
21
  xxl: 48, // 48px - 2x extra large (6 units)
@@ -20,13 +24,20 @@ export const spacing = {
20
24
  gutter: 16, // Standard horizontal gutter
21
25
  gutterVertical: 24, // Standard vertical spacing
22
26
  screenPadding: 16, // Default screen edge padding
27
+ sectionSpacing: 24, // Space between major sections / grouped lists
28
+ // Density tokens — rows, surfaces, overlays
29
+ rowPaddingY: 10, // Vertical padding for list / settings rows
30
+ rowPaddingX: 16, // Horizontal padding for list / settings rows
31
+ rowGap: 12, // Gap between media, content, and actions in a row
32
+ rowMinHeight: 40, // Visual min height for rows on pointer surfaces (web)
33
+ formRowMinHeight: 32, // Visual min height for checkbox / radio rows on web
34
+ cardPadding: 16, // Default card / stat card padding
35
+ dialogPadding: 20, // Default dialog / alert dialog padding
36
+ touchTarget: 44, // Minimum comfortable native touch target
23
37
  // Component-specific
24
38
  buttonPadding: 10, // Default button padding
25
39
  inputPadding: 10, // Default input padding
26
- cardPadding: 16, // Default card padding
27
- sectionSpacing: 32, // Space between major sections
28
40
  listItemSpacing: 8, // Space between list items
29
- touchTarget: 44, // Minimum comfortable native touch target
30
41
  // Border radius — shadcn-inspired scale (radiusMd = 12px default)
31
42
  radiusNone: 0,
32
43
  radiusXs: 4,
@@ -44,6 +55,6 @@ export const spacing = {
44
55
  iconXl: 48,
45
56
  };
46
57
  // Export individual constants for convenience
47
- export const { base, xxs, xs, sm, md, lg, xl, xxl, xxxl, gutter, gutterVertical, screenPadding, buttonPadding, inputPadding, cardPadding, sectionSpacing, listItemSpacing, touchTarget, radiusNone, radiusXs, radiusSm, radiusMd, radiusLg, radiusXl, radius2xl, radiusFull, iconXs, iconSm, iconMd, iconLg, iconXl, } = spacing;
58
+ export const { base, xxs, xs, sm, smd, md, mdl, lg, xl, xxl, xxxl, gutter, gutterVertical, screenPadding, sectionSpacing, rowPaddingY, rowPaddingX, rowGap, rowMinHeight, formRowMinHeight, cardPadding, dialogPadding, touchTarget, buttonPadding, inputPadding, listItemSpacing, radiusNone, radiusXs, radiusSm, radiusMd, radiusLg, radiusXl, radius2xl, radiusFull, iconXs, iconSm, iconMd, iconLg, iconXl, } = spacing;
48
59
  // Helper function to multiply base spacing
49
60
  export const space = (multiplier) => spacing.base * multiplier;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mrmeg/expo-ui",
3
- "version": "0.22.0",
3
+ "version": "0.23.0",
4
4
  "private": false,
5
5
  "description": "Reusable Expo and React Native UI primitives for MrMeg projects.",
6
6
  "keywords": [
@@ -83,7 +83,7 @@
83
83
  "scripts": {
84
84
  "typecheck": "tsc --noEmit -p tsconfig.json",
85
85
  "test": "jest --config ../../jest.config.js packages/ui/src --runInBand --watchman=false && bun run check:forbidden-imports",
86
- "build": "rm -rf dist && tsc -p tsconfig.build.json && node ../../scripts/fix-ui-package-esm.mjs && bun run check:forbidden-imports",
86
+ "build": "rm -rf dist && tsc -p tsconfig.build.json && node ../../scripts/fix-package-esm.mjs ui && bun run check:forbidden-imports",
87
87
  "check:forbidden-imports": "node ../../scripts/check-ui-forbidden-imports.mjs",
88
88
  "publish:dry-run": "bun pm pack --dry-run"
89
89
  },
@@ -98,7 +98,7 @@
98
98
  "@rn-primitives/dropdown-menu": "~1.5.2",
99
99
  "@rn-primitives/label": "~1.5.2",
100
100
  "@rn-primitives/popover": "~1.5.2",
101
- "@rn-primitives/portal": "~1.5.2",
101
+ "@rn-primitives/portal": "~1.5.3",
102
102
  "@rn-primitives/radio-group": "~1.5.2",
103
103
  "@rn-primitives/select": "~1.5.2",
104
104
  "@rn-primitives/separator": "~1.5.2",