@idealyst/components 1.1.6 → 1.1.7

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 (104) hide show
  1. package/package.json +8 -3
  2. package/src/Accordion/Accordion.native.tsx +15 -9
  3. package/src/Accordion/Accordion.styles.tsx +193 -168
  4. package/src/Accordion/Accordion.web.tsx +12 -7
  5. package/src/ActivityIndicator/ActivityIndicator.native.tsx +3 -2
  6. package/src/ActivityIndicator/ActivityIndicator.styles.tsx +22 -11
  7. package/src/ActivityIndicator/ActivityIndicator.web.tsx +2 -2
  8. package/src/Alert/Alert.native.tsx +11 -10
  9. package/src/Alert/Alert.styles.tsx +162 -253
  10. package/src/Alert/Alert.web.tsx +6 -10
  11. package/src/Avatar/Avatar.native.tsx +5 -2
  12. package/src/Avatar/Avatar.styles.tsx +48 -18
  13. package/src/Avatar/Avatar.web.tsx +2 -2
  14. package/src/Badge/Badge.native.tsx +2 -2
  15. package/src/Badge/Badge.styles.tsx +37 -16
  16. package/src/Badge/Badge.web.tsx +6 -6
  17. package/src/Breadcrumb/Breadcrumb.native.tsx +12 -5
  18. package/src/Breadcrumb/Breadcrumb.styles.tsx +59 -58
  19. package/src/Breadcrumb/Breadcrumb.web.tsx +13 -6
  20. package/src/Button/Button.native.tsx +39 -14
  21. package/src/Button/Button.styles.tsx +106 -208
  22. package/src/Button/Button.web.tsx +10 -8
  23. package/src/Card/Card.native.tsx +14 -6
  24. package/src/Card/Card.styles.tsx +64 -62
  25. package/src/Card/Card.web.tsx +5 -4
  26. package/src/Checkbox/Checkbox.native.tsx +7 -3
  27. package/src/Checkbox/Checkbox.styles.tsx +49 -25
  28. package/src/Checkbox/Checkbox.web.tsx +3 -3
  29. package/src/Chip/Chip.native.tsx +5 -5
  30. package/src/Chip/Chip.styles.tsx +71 -21
  31. package/src/Chip/Chip.web.tsx +5 -5
  32. package/src/Dialog/Dialog.native.tsx +10 -4
  33. package/src/Dialog/Dialog.styles.tsx +130 -90
  34. package/src/Dialog/Dialog.web.tsx +4 -4
  35. package/src/Divider/Divider.native.tsx +29 -42
  36. package/src/Divider/Divider.styles.tsx +138 -242
  37. package/src/Divider/Divider.web.tsx +17 -14
  38. package/src/Icon/Icon.native.tsx +11 -3
  39. package/src/Icon/Icon.styles.tsx +10 -4
  40. package/src/Image/Image.styles.tsx +53 -37
  41. package/src/Input/Input.native.tsx +6 -7
  42. package/src/Input/Input.styles.tsx +194 -174
  43. package/src/Input/Input.web.tsx +5 -8
  44. package/src/Link/Link.native.tsx +4 -1
  45. package/src/List/List.styles.tsx +79 -105
  46. package/src/List/ListItem.native.tsx +5 -3
  47. package/src/List/ListItem.web.tsx +4 -3
  48. package/src/Menu/Menu.native.tsx +1 -1
  49. package/src/Menu/Menu.styles.tsx +53 -37
  50. package/src/Menu/Menu.web.tsx +2 -2
  51. package/src/Menu/MenuItem.native.tsx +5 -3
  52. package/src/Menu/MenuItem.styles.tsx +68 -69
  53. package/src/Menu/MenuItem.web.tsx +16 -3
  54. package/src/Popover/Popover.native.tsx +1 -1
  55. package/src/Popover/Popover.styles.tsx +40 -29
  56. package/src/Popover/Popover.web.tsx +1 -1
  57. package/src/Pressable/Pressable.native.tsx +3 -1
  58. package/src/Pressable/Pressable.styles.tsx +20 -13
  59. package/src/Pressable/Pressable.web.tsx +1 -1
  60. package/src/Progress/Progress.native.tsx +15 -6
  61. package/src/Progress/Progress.styles.tsx +125 -85
  62. package/src/Progress/Progress.web.tsx +10 -9
  63. package/src/RadioButton/RadioButton.native.tsx +8 -3
  64. package/src/RadioButton/RadioButton.styles.tsx +44 -37
  65. package/src/RadioButton/RadioButton.web.tsx +3 -3
  66. package/src/SVGImage/SVGImage.styles.tsx +28 -16
  67. package/src/Screen/Screen.native.tsx +23 -13
  68. package/src/Screen/Screen.styles.tsx +57 -46
  69. package/src/Screen/Screen.web.tsx +1 -1
  70. package/src/Select/Select.native.tsx +11 -5
  71. package/src/Select/Select.styles.tsx +72 -52
  72. package/src/Select/Select.web.tsx +5 -5
  73. package/src/Skeleton/Skeleton.styles.tsx +26 -14
  74. package/src/Slider/Slider.native.tsx +9 -5
  75. package/src/Slider/Slider.styles.tsx +59 -48
  76. package/src/Slider/Slider.web.tsx +5 -5
  77. package/src/Switch/Switch.native.tsx +6 -2
  78. package/src/Switch/Switch.styles.tsx +46 -19
  79. package/src/Switch/Switch.web.tsx +4 -4
  80. package/src/TabBar/TabBar.native.tsx +23 -31
  81. package/src/TabBar/TabBar.styles.tsx +215 -371
  82. package/src/TabBar/TabBar.web.tsx +21 -33
  83. package/src/Table/Table.native.tsx +1 -1
  84. package/src/Table/Table.styles.tsx +11 -4
  85. package/src/Table/Table.web.tsx +1 -1
  86. package/src/Text/Text.native.tsx +3 -4
  87. package/src/Text/Text.styles.tsx +7 -1
  88. package/src/Text/Text.web.tsx +1 -1
  89. package/src/TextArea/TextArea.styles.tsx +90 -58
  90. package/src/Tooltip/Tooltip.native.tsx +2 -2
  91. package/src/Tooltip/Tooltip.styles.tsx +21 -12
  92. package/src/Tooltip/Tooltip.web.tsx +2 -2
  93. package/src/Video/Video.styles.tsx +39 -23
  94. package/src/View/View.native.tsx +4 -2
  95. package/src/View/View.styles.tsx +33 -22
  96. package/src/View/View.web.tsx +13 -2
  97. package/src/extensions/applyExtension.ts +210 -0
  98. package/src/extensions/extendComponent.ts +377 -0
  99. package/src/extensions/index.ts +102 -0
  100. package/src/extensions/types.ts +497 -0
  101. package/src/globals.ts +16 -0
  102. package/src/index.native.ts +4 -0
  103. package/src/index.ts +28 -0
  104. package/src/utils/deepMerge.ts +54 -2
@@ -99,6 +99,10 @@ const Checkbox = forwardRef<View, CheckboxProps>(({
99
99
  const labelContent = children || label;
100
100
  const displayHelperText = error || helperText;
101
101
 
102
+ const containerStyle = (checkboxStyles.container as any)({});
103
+ const checkboxStyle = (checkboxStyles.checkbox as any)({ intent });
104
+ const checkmarkStyle = (checkboxStyles.checkmark as any)({});
105
+
102
106
  return (
103
107
  <View ref={ref} nativeID={id} style={[checkboxStyles.wrapper, style]}>
104
108
  <Pressable
@@ -106,15 +110,15 @@ const Checkbox = forwardRef<View, CheckboxProps>(({
106
110
  disabled={disabled}
107
111
  testID={testID}
108
112
  {...nativeA11yProps}
109
- style={checkboxStyles.container}
113
+ style={containerStyle}
110
114
  >
111
- <View style={checkboxStyles.checkbox({ intent })}>
115
+ <View style={checkboxStyle}>
112
116
  {(internalChecked || indeterminate) && (
113
117
  <MaterialCommunityIcons
114
118
  name={indeterminate ? 'minus' : 'check'}
115
119
  size={14}
116
120
  color="#ffffff"
117
- style={checkboxStyles.checkmark}
121
+ style={checkmarkStyle}
118
122
  />
119
123
  )}
120
124
  </View>
@@ -1,10 +1,11 @@
1
1
  import { StyleSheet } from 'react-native-unistyles';
2
- import { Theme, StylesheetStyles, Intent, Size} from '@idealyst/theme';
2
+ import { Theme, StylesheetStyles, Intent, Size } from '@idealyst/theme';
3
3
  import {
4
4
  buildMarginVariants,
5
5
  buildMarginVerticalVariants,
6
6
  buildMarginHorizontalVariants,
7
7
  } from '../utils/buildViewStyleVariants';
8
+ import { applyExtensions } from '../extensions/applyExtension';
8
9
 
9
10
  type CheckboxSize = Size;
10
11
  type CheckboxIntent = Intent | 'info';
@@ -169,11 +170,11 @@ function createCheckboxStyles(theme: Theme) {
169
170
  }
170
171
 
171
172
  function createCheckmarkStyles(_theme: Theme) {
172
- return {
173
- position: 'absolute',
174
- display: 'flex',
175
- alignItems: 'center',
176
- justifyContent: 'center',
173
+ return () => ({
174
+ position: 'absolute' as const,
175
+ display: 'flex' as const,
176
+ alignItems: 'center' as const,
177
+ justifyContent: 'center' as const,
177
178
  color: '#ffffff',
178
179
  variants: {
179
180
  size: createCheckmarkSizeVariants(),
@@ -182,15 +183,13 @@ function createCheckmarkStyles(_theme: Theme) {
182
183
  false: { opacity: 0 },
183
184
  },
184
185
  },
185
- } as const;
186
+ });
186
187
  }
187
188
 
188
- // Styles are inlined here instead of in @idealyst/theme because Unistyles' Babel
189
- // transform on native cannot resolve function calls to extract variant structures.
190
- export const checkboxStyles = StyleSheet.create((theme: Theme) => {
191
- return {
192
- wrapper: {
193
- flexDirection: 'column',
189
+ // Helper functions to create static styles wrapped in dynamic functions
190
+ function createWrapperStyles(theme: Theme) {
191
+ return () => ({
192
+ flexDirection: 'column' as const,
194
193
  gap: 4,
195
194
  variants: {
196
195
  // Spacing variants from FormInputStyleProps
@@ -204,10 +203,13 @@ export const checkboxStyles = StyleSheet.create((theme: Theme) => {
204
203
  alignItems: 'flex-start',
205
204
  width: 'auto',
206
205
  },
207
- },
208
- container: {
209
- flexDirection: 'row',
210
- alignItems: 'center',
206
+ });
207
+ }
208
+
209
+ function createContainerStyles() {
210
+ return () => ({
211
+ flexDirection: 'row' as const,
212
+ alignItems: 'center' as const,
211
213
  gap: 8,
212
214
  _web: {
213
215
  display: 'flex',
@@ -217,9 +219,11 @@ export const checkboxStyles = StyleSheet.create((theme: Theme) => {
217
219
  width: 'fit-content',
218
220
  cursor: 'pointer',
219
221
  },
220
- },
221
- checkbox: createCheckboxStyles(theme),
222
- label: {
222
+ });
223
+ }
224
+
225
+ function createLabelStyles(theme: Theme) {
226
+ return () => ({
223
227
  color: theme.colors.text.primary,
224
228
  variants: {
225
229
  size: createLabelSizeVariants(),
@@ -234,9 +238,11 @@ export const checkboxStyles = StyleSheet.create((theme: Theme) => {
234
238
  margin: 0,
235
239
  padding: 0,
236
240
  },
237
- },
238
- checkmark: createCheckmarkStyles(theme),
239
- helperText: {
241
+ });
242
+ }
243
+
244
+ function createHelperTextStyles(theme: Theme) {
245
+ return () => ({
240
246
  fontSize: 14,
241
247
  color: theme.colors.text.secondary,
242
248
  marginTop: 2,
@@ -246,6 +252,24 @@ export const checkboxStyles = StyleSheet.create((theme: Theme) => {
246
252
  false: { color: theme.colors.text.secondary },
247
253
  },
248
254
  },
249
- },
250
- };
255
+ });
256
+ }
257
+
258
+ // Styles are inlined here instead of in @idealyst/theme because Unistyles' Babel
259
+ // transform on native cannot resolve function calls to extract variant structures.
260
+ export const checkboxStyles = StyleSheet.create((theme: Theme) => {
261
+ // Apply extensions to main visual elements
262
+ const extended = applyExtensions('Checkbox', theme, {
263
+ container: createContainerStyles(),
264
+ checkbox: createCheckboxStyles(theme),
265
+ checkmark: createCheckmarkStyles(theme),
266
+ });
267
+
268
+ return {
269
+ ...extended,
270
+ // Minor utility styles (not extended)
271
+ wrapper: createWrapperStyles(theme)(),
272
+ label: createLabelStyles(theme)(),
273
+ helperText: createHelperTextStyles(theme)(),
274
+ };
251
275
  });
@@ -126,11 +126,11 @@ const Checkbox = forwardRef<HTMLDivElement, CheckboxProps>(({
126
126
 
127
127
  // Create style arrays
128
128
  const wrapperStyleArray = [checkboxStyles.wrapper, style as any];
129
- const containerStyleArray = [checkboxStyles.container];
130
- const checkboxStyleArray = [checkboxStyles.checkbox({ intent })];
129
+ const containerStyleArray = [(checkboxStyles.container as any)({})];
130
+ const checkboxStyleArray = [(checkboxStyles.checkbox as any)({ intent })];
131
131
  const labelStyleArray = [checkboxStyles.label];
132
132
  const helperTextStyleArray = [checkboxStyles.helperText];
133
- const checkmarkStyleArray = [checkboxStyles.checkmark];
133
+ const checkmarkStyleArray = [(checkboxStyles.checkmark as any)({})];
134
134
 
135
135
  // Generate web props
136
136
  const wrapperProps = getWebProps(wrapperStyleArray);
@@ -42,11 +42,11 @@ const Chip = forwardRef<ComponentRef<typeof Pressable>, ChipProps>(({
42
42
  const isSelected = selectable ? selected : false;
43
43
 
44
44
  // Compute dynamic styles
45
- const containerStyle = chipStyles.container(size, intent, type, isSelected, disabled);
46
- const labelStyle = chipStyles.label(size, intent, type, isSelected);
47
- const iconStyle = chipStyles.icon(size, intent, type, isSelected);
48
- const deleteButtonStyle = chipStyles.deleteButton(size);
49
- const deleteIconStyle = chipStyles.deleteIcon(size, intent, type, isSelected);
45
+ const containerStyle = (chipStyles.container as any)({ size, intent, type, selected: isSelected, disabled });
46
+ const labelStyle = (chipStyles.label as any)({ size, intent, type, selected: isSelected });
47
+ const iconStyle = (chipStyles.icon as any)({ size, intent, type, selected: isSelected });
48
+ const deleteButtonStyle = (chipStyles.deleteButton as any)({ size });
49
+ const deleteIconStyle = (chipStyles.deleteIcon as any)({ size, intent, type, selected: isSelected });
50
50
 
51
51
  // Map chip size to icon size
52
52
  const iconSize = size === 'sm' ? 12 : size === 'md' ? 14 : 16;
@@ -1,15 +1,28 @@
1
1
  import { StyleSheet } from 'react-native-unistyles';
2
- import { Theme, Intent} from '@idealyst/theme';
2
+ import { Theme, Intent } from '@idealyst/theme';
3
+ import { applyExtensions } from '../extensions/applyExtension';
3
4
 
4
5
  type ChipSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl';
5
6
  type ChipType = 'filled' | 'outlined' | 'soft';
6
7
  type ChipIntent = Intent;
7
8
 
8
- // Styles are inlined here instead of in @idealyst/theme because Unistyles' Babel
9
- // transform on native cannot resolve function calls to extract variant structures.
10
- export const chipStyles = StyleSheet.create((theme: Theme) => {
11
- return {
12
- container: (size: ChipSize, intent: ChipIntent, type: ChipType, selected: boolean, disabled: boolean) => {
9
+ type ChipDynamicProps = {
10
+ size: ChipSize;
11
+ intent: ChipIntent;
12
+ type: ChipType;
13
+ selected: boolean;
14
+ disabled?: boolean;
15
+ };
16
+
17
+ type ChipDeleteButtonProps = {
18
+ size: ChipSize;
19
+ };
20
+
21
+ /**
22
+ * Create container styles
23
+ */
24
+ function createContainerStyles(theme: Theme) {
25
+ return ({ size, intent, type, selected, disabled = false }: ChipDynamicProps) => {
13
26
  const intentValue = theme.intents[intent];
14
27
  const sizeValue = theme.sizes.chip[size];
15
28
 
@@ -48,9 +61,14 @@ export const chipStyles = StyleSheet.create((theme: Theme) => {
48
61
  borderStyle: borderWidth > 0 ? ('solid' as const) : undefined,
49
62
  opacity: disabled ? 0.5 : 1,
50
63
  } as const;
51
- },
52
-
53
- label: (size: ChipSize, intent: ChipIntent, type: ChipType, selected: boolean) => {
64
+ };
65
+ }
66
+
67
+ /**
68
+ * Create label styles
69
+ */
70
+ function createLabelStyles(theme: Theme) {
71
+ return ({ size, intent, type, selected }: ChipDynamicProps) => {
54
72
  const intentValue = theme.intents[intent];
55
73
  const sizeValue = theme.sizes.chip[size];
56
74
 
@@ -72,9 +90,14 @@ export const chipStyles = StyleSheet.create((theme: Theme) => {
72
90
  lineHeight: sizeValue.lineHeight as number,
73
91
  color,
74
92
  } as const;
75
- },
76
-
77
- icon: (size: ChipSize, intent: ChipIntent, type: ChipType, selected: boolean) => {
93
+ };
94
+ }
95
+
96
+ /**
97
+ * Create icon styles
98
+ */
99
+ function createIconStyles(theme: Theme) {
100
+ return ({ size, intent, type, selected }: ChipDynamicProps) => {
78
101
  const intentValue = theme.intents[intent];
79
102
  const sizeValue = theme.sizes.chip[size];
80
103
 
@@ -97,9 +120,14 @@ export const chipStyles = StyleSheet.create((theme: Theme) => {
97
120
  height: sizeValue.iconSize as number,
98
121
  color,
99
122
  } as const;
100
- },
101
-
102
- deleteButton: (size: ChipSize) => {
123
+ };
124
+ }
125
+
126
+ /**
127
+ * Create delete button styles
128
+ */
129
+ function createDeleteButtonStyles(theme: Theme) {
130
+ return ({ size }: ChipDeleteButtonProps) => {
103
131
  const sizeValue = theme.sizes.chip[size];
104
132
 
105
133
  return {
@@ -112,9 +140,14 @@ export const chipStyles = StyleSheet.create((theme: Theme) => {
112
140
  width: sizeValue.iconSize as number,
113
141
  height: sizeValue.iconSize as number,
114
142
  } as const;
115
- },
116
-
117
- deleteIcon: (size: ChipSize, intent: ChipIntent, type: ChipType, selected: boolean) => {
143
+ };
144
+ }
145
+
146
+ /**
147
+ * Create delete icon styles
148
+ */
149
+ function createDeleteIconStyles(theme: Theme) {
150
+ return ({ size, intent, type, selected }: ChipDynamicProps) => {
118
151
  const intentValue = theme.intents[intent];
119
152
  const sizeValue = theme.sizes.chip[size];
120
153
 
@@ -133,6 +166,23 @@ export const chipStyles = StyleSheet.create((theme: Theme) => {
133
166
  fontSize: sizeValue.iconSize as number,
134
167
  color,
135
168
  } as const;
136
- },
137
- } as const;
138
- });
169
+ };
170
+ }
171
+
172
+ // Styles are inlined here instead of in @idealyst/theme because Unistyles' Babel
173
+ // transform on native cannot resolve function calls to extract variant structures.
174
+ export const chipStyles = StyleSheet.create((theme: Theme) => {
175
+ // Apply extensions to main visual elements
176
+ const extended = applyExtensions('Chip', theme, {
177
+ container: createContainerStyles(theme),
178
+ label: createLabelStyles(theme),
179
+ icon: createIconStyles(theme),
180
+ });
181
+
182
+ return {
183
+ ...extended,
184
+ // Minor utility styles (not extended)
185
+ deleteButton: createDeleteButtonStyles(theme),
186
+ deleteIcon: createDeleteIconStyles(theme),
187
+ };
188
+ });
@@ -30,11 +30,11 @@ const Chip = forwardRef<HTMLDivElement, ChipProps>(({
30
30
  const isSelected = selectable ? selected : false;
31
31
 
32
32
  // Compute dynamic styles
33
- const containerProps = getWebProps([chipStyles.container(size, intent, type, isSelected, disabled), style as any]);
34
- const labelProps = getWebProps([chipStyles.label(size, intent, type, isSelected)]);
35
- const iconProps = getWebProps([chipStyles.icon(size, intent, type, isSelected)]);
36
- const deleteButtonProps = getWebProps([chipStyles.deleteButton(size)]);
37
- const deleteIconProps = getWebProps([chipStyles.deleteIcon(size, intent, type, isSelected)]);
33
+ const containerProps = getWebProps([(chipStyles.container as any)({ size, intent, type, selected: isSelected, disabled }), style as any]);
34
+ const labelProps = getWebProps([(chipStyles.label as any)({ size, intent, type, selected: isSelected })]);
35
+ const iconProps = getWebProps([(chipStyles.icon as any)({ size, intent, type, selected: isSelected })]);
36
+ const deleteButtonProps = getWebProps([(chipStyles.deleteButton as any)({ size })]);
37
+ const deleteIconProps = getWebProps([(chipStyles.deleteIcon as any)({ size, intent, type, selected: isSelected })]);
38
38
 
39
39
  const handleClick = () => {
40
40
  if (disabled) return;
@@ -115,6 +115,12 @@ const Dialog = forwardRef<View, DialogProps>(({
115
115
  };
116
116
  });
117
117
 
118
+ // Get dynamic styles
119
+ const backdropStyle = (dialogStyles.backdrop as any)({});
120
+ const containerStyle = (dialogStyles.container as any)({});
121
+ const headerStyle = (dialogStyles.header as any)({});
122
+ const contentStyle = (dialogStyles.content as any)({});
123
+
118
124
  return (
119
125
  <Modal
120
126
  visible={open}
@@ -125,11 +131,11 @@ const Dialog = forwardRef<View, DialogProps>(({
125
131
  testID={testID}
126
132
  >
127
133
  <TouchableWithoutFeedback onPress={handleBackdropPress}>
128
- <Animated.View style={[dialogStyles.backdrop, backdropAnimatedStyle]}>
134
+ <Animated.View style={[backdropStyle, backdropAnimatedStyle]}>
129
135
  <TouchableWithoutFeedback onPress={(e) => e.stopPropagation()}>
130
- <Animated.View ref={ref as any} style={[dialogStyles.container, style, containerAnimatedStyle]} nativeID={id} {...nativeA11yProps}>
136
+ <Animated.View ref={ref as any} style={[containerStyle, style, containerAnimatedStyle]} nativeID={id} {...nativeA11yProps}>
131
137
  {(title || showCloseButton) && (
132
- <View style={dialogStyles.header}>
138
+ <View style={headerStyle}>
133
139
  {title && (
134
140
  <Text style={dialogStyles.title}>
135
141
  {title}
@@ -147,7 +153,7 @@ const Dialog = forwardRef<View, DialogProps>(({
147
153
  )}
148
154
  </View>
149
155
  )}
150
- <View style={dialogStyles.content}>
156
+ <View style={contentStyle}>
151
157
  {children}
152
158
  </View>
153
159
  </Animated.View>
@@ -1,5 +1,6 @@
1
1
  import { StyleSheet } from 'react-native-unistyles';
2
- import { Theme, StylesheetStyles} from '@idealyst/theme';
2
+ import { Theme, StylesheetStyles } from '@idealyst/theme';
3
+ import { applyExtensions } from '../extensions/applyExtension';
3
4
  type DialogSize = 'sm' | 'md' | 'lg' | 'fullscreen';
4
5
  type DialogType = 'default' | 'alert' | 'confirmation';
5
6
 
@@ -64,103 +65,142 @@ function createContainerTypeVariants(theme: Theme) {
64
65
  } as const;
65
66
  }
66
67
 
67
- // Styles are inlined here instead of in @idealyst/theme because Unistyles' Babel transform on native cannot resolve function calls to extract variant structures.
68
- export const dialogStyles = StyleSheet.create((theme: Theme) => {
69
- return {
70
- backdrop: {
71
- position: 'absolute',
72
- top: 0,
73
- left: 0,
74
- right: 0,
75
- bottom: 0,
76
- backgroundColor: 'rgba(0, 0, 0, 0.5)',
77
- display: 'flex',
78
- alignItems: 'center',
79
- justifyContent: 'center',
80
- zIndex: 1000,
81
- _web: {
82
- position: 'fixed',
83
- transition: 'opacity 150ms ease-out',
84
- },
68
+ // Helper functions to create static styles wrapped in dynamic functions
69
+ function createBackdropStyles() {
70
+ return () => ({
71
+ position: 'absolute' as const,
72
+ top: 0,
73
+ left: 0,
74
+ right: 0,
75
+ bottom: 0,
76
+ backgroundColor: 'rgba(0, 0, 0, 0.5)',
77
+ display: 'flex' as const,
78
+ alignItems: 'center' as const,
79
+ justifyContent: 'center' as const,
80
+ zIndex: 1000,
81
+ _web: {
82
+ position: 'fixed',
83
+ transition: 'opacity 150ms ease-out',
85
84
  },
86
- container: {
87
- backgroundColor: theme.colors.surface.primary,
88
- borderRadius: 12,
89
- shadowColor: '#000',
90
- shadowOffset: { width: 0, height: 10 },
91
- shadowOpacity: 0.25,
92
- shadowRadius: 20,
93
- elevation: 10,
94
- maxHeight: '90%',
95
- variants: {
96
- size: createContainerSizeVariants(),
97
- type: createContainerTypeVariants(theme),
98
- },
99
- _web: {
100
- position: 'relative',
101
- display: 'flex',
102
- flexDirection: 'column',
103
- overflow: 'auto',
104
- boxShadow: '0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)',
105
- transition: 'opacity 150ms ease-out, transform 150ms ease-out',
106
- transformOrigin: 'center center',
107
- },
85
+ });
86
+ }
87
+
88
+ function createDialogContainerStyles(theme: Theme) {
89
+ return () => ({
90
+ backgroundColor: theme.colors.surface.primary,
91
+ borderRadius: 12,
92
+ shadowColor: '#000',
93
+ shadowOffset: { width: 0, height: 10 },
94
+ shadowOpacity: 0.25,
95
+ shadowRadius: 20,
96
+ elevation: 10,
97
+ maxHeight: '90%',
98
+ variants: {
99
+ size: createContainerSizeVariants(),
100
+ type: createContainerTypeVariants(theme),
108
101
  },
109
- header: {
110
- borderBottomWidth: 1,
111
- borderBottomColor: theme.colors.border.primary,
102
+ _web: {
103
+ position: 'relative',
112
104
  display: 'flex',
113
- flexDirection: 'row',
114
- alignItems: 'center',
115
- justifyContent: 'space-between',
116
- _web: {
117
- borderBottomStyle: 'solid',
118
- },
119
- },
120
- title: {
121
- marginLeft: 24,
122
- fontSize: 18,
123
- paddingVertical: 16,
124
- fontWeight: '600',
125
- color: theme.colors.text.primary,
126
- flex: 1,
127
- _web: {
128
- paddingVertical: 4,
129
- },
105
+ flexDirection: 'column',
106
+ overflow: 'auto',
107
+ boxShadow: '0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)',
108
+ transition: 'opacity 150ms ease-out, transform 150ms ease-out',
109
+ transformOrigin: 'center center',
130
110
  },
131
- closeButton: {
132
- width: 32,
133
- height: 32,
134
- marginRight: 16,
135
- borderRadius: 16,
136
- backgroundColor: 'transparent',
137
- display: 'flex',
138
- alignItems: 'center',
139
- justifyContent: 'center',
140
- _web: {
141
- border: 'none',
142
- cursor: 'pointer',
143
- _hover: {
144
- backgroundColor: theme.colors.surface.secondary,
145
- },
146
- },
111
+ });
112
+ }
113
+
114
+ function createHeaderStyles(theme: Theme) {
115
+ return () => ({
116
+ borderBottomWidth: 1,
117
+ borderBottomColor: theme.colors.border.primary,
118
+ display: 'flex' as const,
119
+ flexDirection: 'row' as const,
120
+ alignItems: 'center' as const,
121
+ justifyContent: 'space-between' as const,
122
+ _web: {
123
+ borderBottomStyle: 'solid',
147
124
  },
148
- closeButtonText: {
149
- fontSize: 18,
150
- color: theme.colors.text.secondary,
151
- fontWeight: '500',
125
+ });
126
+ }
127
+
128
+ function createTitleStyles(theme: Theme) {
129
+ return () => ({
130
+ marginLeft: 24,
131
+ fontSize: 18,
132
+ paddingVertical: 16,
133
+ fontWeight: '600' as const,
134
+ color: theme.colors.text.primary,
135
+ flex: 1,
136
+ _web: {
137
+ paddingVertical: 4,
152
138
  },
153
- content: {
154
- padding: 24,
155
- _web: {
156
- overflow: 'visible',
157
- maxHeight: 'none',
139
+ });
140
+ }
141
+
142
+ function createCloseButtonStyles(theme: Theme) {
143
+ return () => ({
144
+ width: 32,
145
+ height: 32,
146
+ marginRight: 16,
147
+ borderRadius: 16,
148
+ backgroundColor: 'transparent' as const,
149
+ display: 'flex' as const,
150
+ alignItems: 'center' as const,
151
+ justifyContent: 'center' as const,
152
+ _web: {
153
+ border: 'none',
154
+ cursor: 'pointer',
155
+ _hover: {
156
+ backgroundColor: theme.colors.surface.secondary,
158
157
  },
159
158
  },
160
- modal: {
161
- margin: 0,
162
- justifyContent: 'center',
163
- alignItems: 'center',
159
+ });
160
+ }
161
+
162
+ function createCloseButtonTextStyles(theme: Theme) {
163
+ return () => ({
164
+ fontSize: 18,
165
+ color: theme.colors.text.secondary,
166
+ fontWeight: '500' as const,
167
+ });
168
+ }
169
+
170
+ function createContentStyles() {
171
+ return () => ({
172
+ padding: 24,
173
+ _web: {
174
+ overflow: 'visible',
175
+ maxHeight: 'none',
164
176
  },
177
+ });
178
+ }
179
+
180
+ function createModalStyles() {
181
+ return () => ({
182
+ margin: 0,
183
+ justifyContent: 'center' as const,
184
+ alignItems: 'center' as const,
185
+ });
186
+ }
187
+
188
+ // Styles are inlined here instead of in @idealyst/theme because Unistyles' Babel transform on native cannot resolve function calls to extract variant structures.
189
+ export const dialogStyles = StyleSheet.create((theme: Theme) => {
190
+ // Apply extensions to main visual elements
191
+ const extended = applyExtensions('Dialog', theme, {
192
+ backdrop: createBackdropStyles(),
193
+ container: createDialogContainerStyles(theme),
194
+ header: createHeaderStyles(theme),
195
+ content: createContentStyles(),
196
+ });
197
+
198
+ return {
199
+ ...extended,
200
+ // Minor utility styles (not extended)
201
+ title: createTitleStyles(theme)(),
202
+ closeButton: createCloseButtonStyles(theme)(),
203
+ closeButtonText: createCloseButtonTextStyles(theme)(),
204
+ modal: createModalStyles()(),
165
205
  };
166
206
  });
@@ -133,20 +133,20 @@ const Dialog = forwardRef<HTMLDivElement, DialogProps>(({
133
133
  });
134
134
 
135
135
  const backdropProps = getWebProps([
136
- dialogStyles.backdrop,
136
+ (dialogStyles.backdrop as any)({}),
137
137
  { opacity: isVisible ? 1 : 0 }
138
138
  ]);
139
139
  const containerProps = getWebProps([
140
- dialogStyles.container,
140
+ (dialogStyles.container as any)({}),
141
141
  style as any,
142
142
  isVisible
143
143
  ? { opacity: 1, transform: 'scale(1) translateY(0px)' }
144
144
  : { opacity: 0, transform: 'scale(0.96) translateY(-4px)' }
145
145
  ]);
146
- const headerProps = getWebProps([dialogStyles.header]);
146
+ const headerProps = getWebProps([(dialogStyles.header as any)({})]);
147
147
  const titleProps = getWebProps([dialogStyles.title]);
148
148
  const closeButtonProps = getWebProps([dialogStyles.closeButton]);
149
- const contentProps = getWebProps([dialogStyles.content]);
149
+ const contentProps = getWebProps([(dialogStyles.content as any)({})]);
150
150
 
151
151
  const mergedBackdropRef = useMergeRefs(ref, backdropProps.ref);
152
152