@idealyst/components 1.1.7 → 1.1.8

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 (105) hide show
  1. package/package.json +3 -3
  2. package/src/Accordion/Accordion.native.tsx +8 -6
  3. package/src/Accordion/Accordion.styles.old.tsx +298 -0
  4. package/src/Accordion/Accordion.styles.tsx +102 -236
  5. package/src/ActivityIndicator/ActivityIndicator.styles.old.tsx +94 -0
  6. package/src/ActivityIndicator/ActivityIndicator.styles.tsx +44 -74
  7. package/src/Alert/Alert.native.tsx +16 -6
  8. package/src/Alert/Alert.styles.old.tsx +209 -0
  9. package/src/Alert/Alert.styles.tsx +67 -149
  10. package/src/Avatar/Avatar.styles.old.tsx +99 -0
  11. package/src/Avatar/Avatar.styles.tsx +35 -80
  12. package/src/Badge/Badge.styles.old.tsx +157 -0
  13. package/src/Badge/Badge.styles.tsx +61 -121
  14. package/src/Breadcrumb/Breadcrumb.styles.old.tsx +231 -0
  15. package/src/Breadcrumb/Breadcrumb.styles.tsx +83 -200
  16. package/src/Breadcrumb/Breadcrumb.web.tsx +28 -23
  17. package/src/Button/Button.styles.tsx +89 -141
  18. package/src/Card/Card.native.tsx +7 -11
  19. package/src/Card/Card.styles.old.tsx +160 -0
  20. package/src/Card/Card.styles.tsx +105 -142
  21. package/src/Card/Card.web.tsx +5 -4
  22. package/src/Checkbox/Checkbox.native.tsx +9 -5
  23. package/src/Checkbox/Checkbox.styles.old.tsx +271 -0
  24. package/src/Checkbox/Checkbox.styles.tsx +104 -216
  25. package/src/Checkbox/Checkbox.web.tsx +6 -6
  26. package/src/Chip/Chip.styles.old.tsx +184 -0
  27. package/src/Chip/Chip.styles.tsx +34 -72
  28. package/src/Dialog/Dialog.native.tsx +7 -4
  29. package/src/Dialog/Dialog.styles.old.tsx +202 -0
  30. package/src/Dialog/Dialog.styles.tsx +69 -133
  31. package/src/Divider/Divider.styles.old.tsx +172 -0
  32. package/src/Divider/Divider.styles.tsx +62 -84
  33. package/src/Icon/Icon.native.tsx +8 -8
  34. package/src/Icon/Icon.styles.old.tsx +81 -0
  35. package/src/Icon/Icon.styles.tsx +52 -66
  36. package/src/Icon/Icon.web.tsx +43 -7
  37. package/src/Icon/IconSvg/IconSvg.web.tsx +2 -0
  38. package/src/Image/Image.styles.old.tsx +69 -0
  39. package/src/Image/Image.styles.tsx +46 -60
  40. package/src/Input/Input.native.tsx +138 -53
  41. package/src/Input/Input.styles.old.tsx +289 -0
  42. package/src/Input/Input.styles.tsx +127 -198
  43. package/src/List/List.native.tsx +5 -2
  44. package/src/List/List.styles.old.tsx +242 -0
  45. package/src/List/List.styles.tsx +179 -215
  46. package/src/List/ListItem.native.tsx +12 -6
  47. package/src/List/ListItem.web.tsx +23 -13
  48. package/src/Menu/Menu.styles.old.tsx +197 -0
  49. package/src/Menu/Menu.styles.tsx +68 -150
  50. package/src/Menu/MenuItem.native.tsx +5 -3
  51. package/src/Menu/MenuItem.styles.old.tsx +114 -0
  52. package/src/Menu/MenuItem.styles.tsx +57 -89
  53. package/src/Menu/MenuItem.web.tsx +8 -3
  54. package/src/Popover/Popover.native.tsx +10 -4
  55. package/src/Popover/Popover.styles.old.tsx +135 -0
  56. package/src/Popover/Popover.styles.tsx +51 -112
  57. package/src/Pressable/Pressable.styles.old.tsx +27 -0
  58. package/src/Pressable/Pressable.styles.tsx +35 -27
  59. package/src/Progress/Progress.styles.old.tsx +200 -0
  60. package/src/Progress/Progress.styles.tsx +75 -164
  61. package/src/RadioButton/RadioButton.native.tsx +4 -3
  62. package/src/RadioButton/RadioButton.styles.old.tsx +175 -0
  63. package/src/RadioButton/RadioButton.styles.tsx +83 -154
  64. package/src/RadioButton/RadioButton.web.tsx +2 -2
  65. package/src/SVGImage/SVGImage.styles.old.tsx +86 -0
  66. package/src/SVGImage/SVGImage.styles.tsx +35 -78
  67. package/src/Screen/Screen.native.tsx +18 -25
  68. package/src/Screen/Screen.styles.old.tsx +87 -0
  69. package/src/Screen/Screen.styles.tsx +105 -67
  70. package/src/Screen/Screen.web.tsx +1 -1
  71. package/src/Select/Select.native.tsx +42 -33
  72. package/src/Select/Select.styles.old.tsx +353 -0
  73. package/src/Select/Select.styles.tsx +223 -292
  74. package/src/Skeleton/Skeleton.styles.old.tsx +67 -0
  75. package/src/Skeleton/Skeleton.styles.tsx +29 -53
  76. package/src/Slider/Slider.styles.old.tsx +259 -0
  77. package/src/Slider/Slider.styles.tsx +153 -234
  78. package/src/Switch/Switch.native.tsx +7 -5
  79. package/src/Switch/Switch.styles.old.tsx +203 -0
  80. package/src/Switch/Switch.styles.tsx +101 -174
  81. package/src/Switch/Switch.web.tsx +5 -5
  82. package/src/TabBar/TabBar.native.tsx +3 -2
  83. package/src/TabBar/TabBar.styles.old.tsx +343 -0
  84. package/src/TabBar/TabBar.styles.tsx +145 -279
  85. package/src/Table/Table.native.tsx +18 -9
  86. package/src/Table/Table.styles.old.tsx +311 -0
  87. package/src/Table/Table.styles.tsx +152 -286
  88. package/src/Text/Text.native.tsx +1 -3
  89. package/src/Text/Text.style.demo.tsx +16 -0
  90. package/src/Text/Text.styles.old.tsx +219 -0
  91. package/src/Text/Text.styles.tsx +94 -84
  92. package/src/Text/Text.web.tsx +2 -2
  93. package/src/Text/index.ts +1 -0
  94. package/src/TextArea/TextArea.styles.old.tsx +213 -0
  95. package/src/TextArea/TextArea.styles.tsx +93 -181
  96. package/src/Tooltip/Tooltip.styles.old.tsx +82 -0
  97. package/src/Tooltip/Tooltip.styles.tsx +32 -56
  98. package/src/Video/Video.styles.old.tsx +51 -0
  99. package/src/Video/Video.styles.tsx +32 -44
  100. package/src/View/View.native.tsx +12 -14
  101. package/src/View/View.styles.old.tsx +125 -0
  102. package/src/View/View.styles.tsx +76 -106
  103. package/src/View/View.web.tsx +1 -0
  104. package/src/examples/CardExamples.tsx +0 -6
  105. package/src/extensions/extendComponent.ts +61 -0
@@ -26,6 +26,7 @@ const View = forwardRef<RNView | RNScrollView, ViewProps>(({
26
26
  testID,
27
27
  id,
28
28
  }, ref) => {
29
+ // Set active variants for this render
29
30
  viewStyles.useVariants({
30
31
  background,
31
32
  radius,
@@ -39,25 +40,22 @@ const View = forwardRef<RNView | RNScrollView, ViewProps>(({
39
40
  marginHorizontal,
40
41
  });
41
42
 
42
- const getStyles = (): ViewStyle => {
43
- const baseStyles: ViewStyle = {};
44
-
45
- if (backgroundColor) baseStyles.backgroundColor = backgroundColor;
46
- if (borderRadius !== undefined) baseStyles.borderRadius = borderRadius;
47
- if (borderWidth !== undefined) baseStyles.borderWidth = borderWidth;
48
- if (borderColor) baseStyles.borderColor = borderColor;
49
-
50
- return baseStyles;
51
- };
52
-
43
+ // Call style as function to get theme-reactive styles
53
44
  const viewStyle = (viewStyles.view as any)({});
54
45
 
46
+ // Override styles for direct prop values
47
+ const overrideStyles: ViewStyle = {};
48
+ if (backgroundColor) overrideStyles.backgroundColor = backgroundColor;
49
+ if (borderRadius !== undefined) overrideStyles.borderRadius = borderRadius;
50
+ if (borderWidth !== undefined) overrideStyles.borderWidth = borderWidth;
51
+ if (borderColor) overrideStyles.borderColor = borderColor;
52
+
55
53
  if (scrollable) {
56
54
  return (
57
55
  <RNScrollView
58
56
  ref={ref as any}
59
- style={[{ flex: 1 }, style]}
60
- contentContainerStyle={[viewStyle, getStyles()]}
57
+ style={[viewStyle, { flex: 1 }, overrideStyles, style]}
58
+ contentContainerStyle={[viewStyle, overrideStyles]}
61
59
  testID={testID}
62
60
  nativeID={id}
63
61
  >
@@ -67,7 +65,7 @@ const View = forwardRef<RNView | RNScrollView, ViewProps>(({
67
65
  }
68
66
 
69
67
  return (
70
- <RNView ref={ref as any} style={[viewStyle, getStyles(), style]} testID={testID} nativeID={id}>
68
+ <RNView ref={ref as any} style={[viewStyle, overrideStyles, style]} testID={testID} nativeID={id}>
71
69
  {children}
72
70
  </RNView>
73
71
  );
@@ -0,0 +1,125 @@
1
+ import { StyleSheet } from 'react-native-unistyles';
2
+ import { Theme, StylesheetStyles, Surface } from '@idealyst/theme';
3
+ import {
4
+ buildGapVariants,
5
+ buildPaddingVariants,
6
+ buildPaddingVerticalVariants,
7
+ buildPaddingHorizontalVariants,
8
+ buildMarginVariants,
9
+ buildMarginVerticalVariants,
10
+ buildMarginHorizontalVariants,
11
+ } from '../utils/buildViewStyleVariants';
12
+ import { ViewBackgroundVariant, ViewBorderVariant, ViewRadiusVariant } from './types';
13
+ import { ViewStyleSize } from '../utils/viewStyleProps';
14
+ import { applyExtensions } from '../extensions/applyExtension';
15
+
16
+ type ViewVariants = {
17
+ background: ViewBackgroundVariant;
18
+ radius: ViewRadiusVariant;
19
+ border: ViewBorderVariant;
20
+ gap: ViewStyleSize;
21
+ padding: ViewStyleSize;
22
+ paddingVertical: ViewStyleSize;
23
+ paddingHorizontal: ViewStyleSize;
24
+ margin: ViewStyleSize;
25
+ marginVertical: ViewStyleSize;
26
+ marginHorizontal: ViewStyleSize;
27
+ };
28
+
29
+ export type ExpandedViewStyles = StylesheetStyles<keyof ViewVariants>;
30
+
31
+ export type ViewStylesheet = {
32
+ view: ExpandedViewStyles;
33
+ };
34
+
35
+ /**
36
+ * Create background variants for view
37
+ */
38
+ function createBackgroundVariants(theme: Theme) {
39
+ const variants: any = {
40
+ transparent: {
41
+ backgroundColor: 'transparent',
42
+ },
43
+ };
44
+
45
+ // Add all surface colors programmatically
46
+ for (const surface in theme.colors.surface) {
47
+ variants[surface] = {
48
+ backgroundColor: theme.colors.surface[surface as Surface],
49
+ };
50
+ }
51
+
52
+ return variants;
53
+ }
54
+
55
+ /**
56
+ * Create radius variants for view
57
+ */
58
+ function createRadiusVariants() {
59
+ return {
60
+ none: { borderRadius: 0 },
61
+ xs: { borderRadius: 2 },
62
+ sm: { borderRadius: 4 },
63
+ md: { borderRadius: 8 },
64
+ lg: { borderRadius: 12 },
65
+ xl: { borderRadius: 16 },
66
+ } as const;
67
+ }
68
+
69
+ /**
70
+ * Create border variants for view
71
+ */
72
+ function createBorderVariants(theme: Theme) {
73
+ return {
74
+ none: {
75
+ borderWidth: 0,
76
+ },
77
+ thin: {
78
+ borderWidth: 1,
79
+ borderStyle: 'solid',
80
+ borderColor: theme.colors['gray.300'],
81
+ },
82
+ thick: {
83
+ borderWidth: 2,
84
+ borderStyle: 'solid',
85
+ borderColor: theme.colors['gray.300'],
86
+ },
87
+ } as const;
88
+ }
89
+
90
+ /**
91
+ * Create dynamic view styles.
92
+ * Returns a function to ensure Unistyles can track theme changes.
93
+ * All styles must be dynamic functions (not static objects) to work with
94
+ * Unistyles' Babel transform and theme reactivity on native.
95
+ */
96
+ function createViewStyles(theme: Theme) {
97
+ return (_props?: {}) => ({
98
+ display: 'flex' as const,
99
+ variants: {
100
+ background: createBackgroundVariants(theme),
101
+ radius: createRadiusVariants(),
102
+ border: createBorderVariants(theme),
103
+ gap: buildGapVariants(theme),
104
+ padding: buildPaddingVariants(theme),
105
+ paddingVertical: buildPaddingVerticalVariants(theme),
106
+ paddingHorizontal: buildPaddingHorizontalVariants(theme),
107
+ margin: buildMarginVariants(theme),
108
+ marginVertical: buildMarginVerticalVariants(theme),
109
+ marginHorizontal: buildMarginHorizontalVariants(theme),
110
+ },
111
+ _web: {
112
+ display: 'flex',
113
+ flexDirection: 'column',
114
+ boxSizing: 'border-box',
115
+ },
116
+ });
117
+ }
118
+
119
+ // Styles use applyExtensions to enable theme extensions and ensure proper
120
+ // reactivity with Unistyles' native Shadow Tree updates.
121
+ export const viewStyles = StyleSheet.create((theme: Theme) => {
122
+ return applyExtensions('View', theme, {
123
+ view: createViewStyles(theme),
124
+ });
125
+ });
@@ -1,125 +1,95 @@
1
+ /**
2
+ * View styles using defineStyle with $iterator expansion.
3
+ */
1
4
  import { StyleSheet } from 'react-native-unistyles';
2
- import { Theme, StylesheetStyles, Surface } from '@idealyst/theme';
3
- import {
4
- buildGapVariants,
5
- buildPaddingVariants,
6
- buildPaddingVerticalVariants,
7
- buildPaddingHorizontalVariants,
8
- buildMarginVariants,
9
- buildMarginVerticalVariants,
10
- buildMarginHorizontalVariants,
11
- } from '../utils/buildViewStyleVariants';
5
+ import { defineStyle, ThemeStyleWrapper } from '@idealyst/theme';
6
+ import type { Theme as BaseTheme } from '@idealyst/theme';
12
7
  import { ViewBackgroundVariant, ViewBorderVariant, ViewRadiusVariant } from './types';
13
8
  import { ViewStyleSize } from '../utils/viewStyleProps';
14
- import { applyExtensions } from '../extensions/applyExtension';
15
9
 
16
- type ViewVariants = {
17
- background: ViewBackgroundVariant;
18
- radius: ViewRadiusVariant;
19
- border: ViewBorderVariant;
20
- gap: ViewStyleSize;
21
- padding: ViewStyleSize;
22
- paddingVertical: ViewStyleSize;
23
- paddingHorizontal: ViewStyleSize;
24
- margin: ViewStyleSize;
25
- marginVertical: ViewStyleSize;
26
- marginHorizontal: ViewStyleSize;
27
- };
10
+ // Required: Unistyles must see StyleSheet usage in original source to process this file
11
+ void StyleSheet;
28
12
 
29
- export type ExpandedViewStyles = StylesheetStyles<keyof ViewVariants>;
13
+ // Wrap theme for $iterator support
14
+ type Theme = ThemeStyleWrapper<BaseTheme>;
30
15
 
31
- export type ViewStylesheet = {
32
- view: ExpandedViewStyles;
16
+ export type ViewVariants = {
17
+ background: ViewBackgroundVariant;
18
+ radius: ViewRadiusVariant;
19
+ border: ViewBorderVariant;
20
+ gap: ViewStyleSize;
21
+ padding: ViewStyleSize;
22
+ paddingVertical: ViewStyleSize;
23
+ paddingHorizontal: ViewStyleSize;
24
+ margin: ViewStyleSize;
25
+ marginVertical: ViewStyleSize;
26
+ marginHorizontal: ViewStyleSize;
33
27
  };
34
28
 
35
- /**
36
- * Create background variants for view
37
- */
38
- function createBackgroundVariants(theme: Theme) {
39
- const variants: any = {
40
- transparent: {
41
- backgroundColor: 'transparent',
42
- },
43
- };
44
-
45
- // Add all surface colors programmatically
46
- for (const surface in theme.colors.surface) {
47
- variants[surface] = {
48
- backgroundColor: theme.colors.surface[surface as Surface],
49
- };
50
- }
51
-
52
- return variants;
53
- }
29
+ export type ViewDynamicProps = Partial<ViewVariants>;
54
30
 
55
31
  /**
56
- * Create radius variants for view
32
+ * View styles with $iterator expansion for spacing variants.
33
+ *
34
+ * NOTE: At least one top-level theme access is required for Unistyles to trace
35
+ * theme dependencies. We use a transparent borderColor as a marker.
57
36
  */
58
- function createRadiusVariants() {
59
- return {
60
- none: { borderRadius: 0 },
61
- xs: { borderRadius: 2 },
62
- sm: { borderRadius: 4 },
63
- md: { borderRadius: 8 },
64
- lg: { borderRadius: 12 },
65
- xl: { borderRadius: 16 },
66
- } as const;
67
- }
68
-
69
- /**
70
- * Create border variants for view
71
- */
72
- function createBorderVariants(theme: Theme) {
73
- return {
74
- none: {
75
- borderWidth: 0,
76
- },
77
- thin: {
78
- borderWidth: 1,
79
- borderStyle: 'solid',
80
- borderColor: theme.colors['gray.300'],
81
- },
82
- thick: {
83
- borderWidth: 2,
84
- borderStyle: 'solid',
85
- borderColor: theme.colors['gray.300'],
86
- },
87
- } as const;
88
- }
89
-
90
- // Style creators for extension support
91
- function createViewStyles(theme: Theme) {
92
- return () => ({
37
+ export const viewStyles = defineStyle('View', (theme: Theme) => ({
38
+ view: (_props: ViewDynamicProps) => ({
93
39
  display: 'flex' as const,
40
+ // Theme marker for Unistyles reactivity (invisible, overridden by variants)
41
+ borderColor: theme.colors.border.primary,
42
+ borderWidth: 0,
94
43
  variants: {
95
- background: createBackgroundVariants(theme),
96
- radius: createRadiusVariants(),
97
- border: createBorderVariants(theme),
98
- gap: buildGapVariants(theme),
99
- padding: buildPaddingVariants(theme),
100
- paddingVertical: buildPaddingVerticalVariants(theme),
101
- paddingHorizontal: buildPaddingHorizontalVariants(theme),
102
- margin: buildMarginVariants(theme),
103
- marginVertical: buildMarginVerticalVariants(theme),
104
- marginHorizontal: buildMarginHorizontalVariants(theme),
44
+ background: {
45
+ transparent: { backgroundColor: 'transparent' },
46
+ primary: { backgroundColor: theme.colors.surface.primary },
47
+ secondary: { backgroundColor: theme.colors.surface.secondary },
48
+ tertiary: { backgroundColor: theme.colors.surface.tertiary },
49
+ inverse: { backgroundColor: theme.colors.surface.inverse },
50
+ 'inverse-secondary': { backgroundColor: theme.colors.surface['inverse-secondary'] },
51
+ 'inverse-tertiary': { backgroundColor: theme.colors.surface['inverse-tertiary'] },
52
+ },
53
+ radius: {
54
+ none: { borderRadius: 0 },
55
+ xs: { borderRadius: 2 },
56
+ sm: { borderRadius: 4 },
57
+ md: { borderRadius: 8 },
58
+ lg: { borderRadius: 12 },
59
+ xl: { borderRadius: 16 },
60
+ },
61
+ border: {
62
+ none: { borderWidth: 0 },
63
+ thin: { borderWidth: 1, borderStyle: 'solid' as const, borderColor: theme.colors['gray.300'] },
64
+ thick: { borderWidth: 2, borderStyle: 'solid' as const, borderColor: theme.colors['gray.300'] },
65
+ },
66
+ // $iterator expands for each view size
67
+ gap: {
68
+ gap: theme.sizes.$view.spacing,
69
+ },
70
+ padding: {
71
+ padding: theme.sizes.$view.padding,
72
+ },
73
+ paddingVertical: {
74
+ paddingVertical: theme.sizes.$view.padding,
75
+ },
76
+ paddingHorizontal: {
77
+ paddingHorizontal: theme.sizes.$view.padding,
78
+ },
79
+ margin: {
80
+ margin: theme.sizes.$view.padding,
81
+ },
82
+ marginVertical: {
83
+ marginVertical: theme.sizes.$view.padding,
84
+ },
85
+ marginHorizontal: {
86
+ marginHorizontal: theme.sizes.$view.padding,
87
+ },
105
88
  },
106
89
  _web: {
107
90
  display: 'flex',
108
91
  flexDirection: 'column',
109
92
  boxSizing: 'border-box',
110
93
  },
111
- });
112
- }
113
-
114
- // Styles are inlined here instead of in @idealyst/theme because Unistyles' Babel
115
- // transform on native cannot resolve function calls to extract variant structures.
116
- export const viewStyles = StyleSheet.create((theme: Theme) => {
117
- // Apply extensions to main visual elements
118
- const extended = applyExtensions('View', theme, {
119
- view: createViewStyles(theme),
120
- });
121
-
122
- return {
123
- ...extended,
124
- };
125
- });
94
+ }),
95
+ }));
@@ -58,6 +58,7 @@ const View = forwardRef<HTMLDivElement, ViewProps>(({
58
58
  return style;
59
59
  }, [style]);
60
60
 
61
+ // Call style as function to get theme-reactive styles
61
62
  /** @ts-ignore */
62
63
  const webProps = getWebProps([(viewStyles.view as any)({}), dynamicStyles]);
63
64
 
@@ -17,12 +17,6 @@ export const CardExamples = () => {
17
17
  <View gap="md">
18
18
  <Text typography="subtitle1">Variants</Text>
19
19
  <View gap="sm" style={{ gap: 10 }}>
20
- <Card type="default" padding="md">
21
- <Text>Default Card</Text>
22
- <Text typography="caption" color="secondary">
23
- This is a default card with standard styling
24
- </Text>
25
- </Card>
26
20
 
27
21
  <Card type="outlined" padding="md">
28
22
  <Text>Outlined Card</Text>
@@ -1,4 +1,5 @@
1
1
  import { Theme } from '@idealyst/theme';
2
+ import { UnistylesRuntime } from 'react-native-unistyles';
2
3
  import {
3
4
  ComponentStyleElements,
4
5
  ComponentName,
@@ -18,6 +19,57 @@ const extensionRegistry = new Map<ComponentName, StyleExtension<any>[]>();
18
19
  */
19
20
  const replacementRegistry = new Map<ComponentName, StyleExtension<any>>();
20
21
 
22
+ /**
23
+ * Compute all extensions for a given theme.
24
+ * Returns an object with component names as keys and merged element extensions as values.
25
+ */
26
+ function computeExtensionsForTheme(theme: Theme): Record<string, Record<string, any>> {
27
+ const result: Record<string, Record<string, any>> = {};
28
+
29
+ for (const [component, extensions] of extensionRegistry) {
30
+ if (!extensions || extensions.length === 0) continue;
31
+
32
+ // Resolve all extensions (call functions with theme)
33
+ const resolved = extensions.map(ext =>
34
+ typeof ext === 'function' ? ext(theme) : ext
35
+ );
36
+
37
+ // Merge all extensions in order (later ones win)
38
+ result[component] = deepMergeAll(...resolved);
39
+ }
40
+
41
+ return result;
42
+ }
43
+
44
+ /**
45
+ * Update theme's __extensions to trigger Unistyles reactivity.
46
+ * This is called whenever extensions change.
47
+ */
48
+ function syncExtensionsToThemes(): void {
49
+ try {
50
+ // Update both light and dark themes with computed extensions
51
+ UnistylesRuntime.updateTheme('light', (currentTheme) => {
52
+ const extensions = computeExtensionsForTheme(currentTheme);
53
+ return {
54
+ ...currentTheme,
55
+ __extensions: extensions,
56
+ };
57
+ });
58
+
59
+ UnistylesRuntime.updateTheme('dark', (currentTheme) => {
60
+ const extensions = computeExtensionsForTheme(currentTheme);
61
+ return {
62
+ ...currentTheme,
63
+ __extensions: extensions,
64
+ };
65
+ });
66
+ } catch (error) {
67
+ // UnistylesRuntime may not be available in all contexts (e.g., SSR)
68
+ // Silently ignore errors - extensions will still work via getExtension
69
+ console.warn('Unable to sync extensions to theme:', error);
70
+ }
71
+ }
72
+
21
73
  /**
22
74
  * Completely replace the styles of a component.
23
75
  *
@@ -249,6 +301,9 @@ export function extendComponent<K extends ComponentName>(
249
301
  const existing = extensionRegistry.get(component) ?? [];
250
302
  existing.push(extension);
251
303
  extensionRegistry.set(component, existing);
304
+
305
+ // Sync extensions to theme for Unistyles reactivity
306
+ syncExtensionsToThemes();
252
307
  }
253
308
 
254
309
  /**
@@ -298,6 +353,9 @@ export function getExtension<K extends ComponentName>(
298
353
  */
299
354
  export function clearExtension<K extends ComponentName>(component: K): void {
300
355
  extensionRegistry.delete(component);
356
+
357
+ // Sync extensions to theme for Unistyles reactivity
358
+ syncExtensionsToThemes();
301
359
  }
302
360
 
303
361
  /**
@@ -313,6 +371,9 @@ export function clearExtension<K extends ComponentName>(component: K): void {
313
371
  */
314
372
  export function clearAllExtensions(): void {
315
373
  extensionRegistry.clear();
374
+
375
+ // Sync extensions to theme for Unistyles reactivity
376
+ syncExtensionsToThemes();
316
377
  }
317
378
 
318
379
  /**