@idealyst/theme 1.2.103 → 1.2.105
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/package.json +2 -2
- package/src/babel/plugin.js +60 -40
- package/src/componentStyles.ts +12 -28
- package/src/styleBuilder.ts +24 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@idealyst/theme",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.105",
|
|
4
4
|
"description": "Theming system for Idealyst Framework",
|
|
5
5
|
"readme": "README.md",
|
|
6
6
|
"main": "src/index.ts",
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
"publish:npm": "npm publish"
|
|
64
64
|
},
|
|
65
65
|
"dependencies": {
|
|
66
|
-
"@idealyst/tooling": "^1.2.
|
|
66
|
+
"@idealyst/tooling": "^1.2.105"
|
|
67
67
|
},
|
|
68
68
|
"peerDependencies": {
|
|
69
69
|
"react-native-unistyles": ">=3.0.0"
|
package/src/babel/plugin.js
CHANGED
|
@@ -126,11 +126,42 @@ function mergeObjectExpressions(t, target, source) {
|
|
|
126
126
|
const idx = resultProps.indexOf(existingProp);
|
|
127
127
|
resultProps[idx] = t.objectProperty(existingProp.key, mergedValue);
|
|
128
128
|
}
|
|
129
|
-
// If
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
129
|
+
// If base is a dynamic function and extension is anything (plain object
|
|
130
|
+
// or arrow function), extract the extension's object and merge it into the
|
|
131
|
+
// base function's return body. Extensions should only provide plain objects,
|
|
132
|
+
// but if a function is given we unwrap its body to get the object.
|
|
133
|
+
else if (t.isArrowFunctionExpression(existingValue)) {
|
|
134
|
+
let extObj = newValue;
|
|
135
|
+
// If extension mistakenly provides a function, unwrap its return body
|
|
136
|
+
if (t.isArrowFunctionExpression(extObj)) {
|
|
137
|
+
extObj = extObj.body;
|
|
138
|
+
if (t.isParenthesizedExpression(extObj)) {
|
|
139
|
+
extObj = extObj.expression;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (t.isObjectExpression(extObj)) {
|
|
144
|
+
let baseBody = existingValue.body;
|
|
145
|
+
if (t.isParenthesizedExpression(baseBody)) {
|
|
146
|
+
baseBody = baseBody.expression;
|
|
147
|
+
}
|
|
148
|
+
if (t.isObjectExpression(baseBody)) {
|
|
149
|
+
const mergedBody = mergeObjectExpressions(t, baseBody, extObj);
|
|
150
|
+
const idx = resultProps.indexOf(existingProp);
|
|
151
|
+
resultProps[idx] = t.objectProperty(
|
|
152
|
+
existingProp.key,
|
|
153
|
+
t.arrowFunctionExpression(existingValue.params, mergedBody)
|
|
154
|
+
);
|
|
155
|
+
} else {
|
|
156
|
+
// Block body or other complex form — fall back to replacement
|
|
157
|
+
const idx = resultProps.indexOf(existingProp);
|
|
158
|
+
resultProps[idx] = prop;
|
|
159
|
+
}
|
|
160
|
+
} else {
|
|
161
|
+
// Extension body isn't an object — fall back to replacement
|
|
162
|
+
const idx = resultProps.indexOf(existingProp);
|
|
163
|
+
resultProps[idx] = prop;
|
|
164
|
+
}
|
|
134
165
|
}
|
|
135
166
|
// Otherwise, source replaces target
|
|
136
167
|
else {
|
|
@@ -188,33 +219,6 @@ function mergeObjectExpressions(t, target, source) {
|
|
|
188
219
|
return t.objectExpression(resultProps);
|
|
189
220
|
}
|
|
190
221
|
|
|
191
|
-
/**
|
|
192
|
-
* Merge two dynamic style functions (arrow functions that return style objects).
|
|
193
|
-
* Creates a new function that merges both return values.
|
|
194
|
-
*/
|
|
195
|
-
function mergeDynamicStyleFunctions(t, baseFn, extFn) {
|
|
196
|
-
// Get the bodies (assuming they return ObjectExpressions)
|
|
197
|
-
let baseBody = baseFn.body;
|
|
198
|
-
let extBody = extFn.body;
|
|
199
|
-
|
|
200
|
-
// Handle parenthesized expressions
|
|
201
|
-
if (t.isParenthesizedExpression(baseBody)) {
|
|
202
|
-
baseBody = baseBody.expression;
|
|
203
|
-
}
|
|
204
|
-
if (t.isParenthesizedExpression(extBody)) {
|
|
205
|
-
extBody = extBody.expression;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
// If both return ObjectExpressions directly, merge them
|
|
209
|
-
if (t.isObjectExpression(baseBody) && t.isObjectExpression(extBody)) {
|
|
210
|
-
const mergedBody = mergeObjectExpressions(t, baseBody, extBody);
|
|
211
|
-
return t.arrowFunctionExpression(baseFn.params, mergedBody);
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
// For block statements, this is more complex - just use extension for now
|
|
215
|
-
return extFn;
|
|
216
|
-
}
|
|
217
|
-
|
|
218
222
|
/**
|
|
219
223
|
* Merge a callback body (the object returned by theme => ({ ... }))
|
|
220
224
|
*/
|
|
@@ -941,16 +945,24 @@ module.exports = function idealystStylesPlugin({ types: t }) {
|
|
|
941
945
|
if (t.isIdentifier(node.callee, { name: 'extendStyle' })) {
|
|
942
946
|
debug(`FOUND extendStyle in: ${filename}`);
|
|
943
947
|
|
|
944
|
-
const [componentNameArg,
|
|
948
|
+
const [componentNameArg, stylesArg] = node.arguments;
|
|
945
949
|
|
|
946
950
|
if (!t.isStringLiteral(componentNameArg)) {
|
|
947
951
|
debug(` SKIP - componentName is not a string literal`);
|
|
948
952
|
return;
|
|
949
953
|
}
|
|
950
954
|
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
955
|
+
// Accept either a function callback or a plain object
|
|
956
|
+
let stylesCallback = stylesArg;
|
|
957
|
+
if (t.isObjectExpression(stylesArg)) {
|
|
958
|
+
// Wrap plain object in an arrow function: (theme) => ({ ... })
|
|
959
|
+
stylesCallback = t.arrowFunctionExpression(
|
|
960
|
+
[t.identifier('theme')],
|
|
961
|
+
t.parenthesizedExpression(stylesArg)
|
|
962
|
+
);
|
|
963
|
+
} else if (!t.isArrowFunctionExpression(stylesArg) &&
|
|
964
|
+
!t.isFunctionExpression(stylesArg)) {
|
|
965
|
+
debug(` SKIP - second argument is not a function or object`);
|
|
954
966
|
return;
|
|
955
967
|
}
|
|
956
968
|
|
|
@@ -987,16 +999,24 @@ module.exports = function idealystStylesPlugin({ types: t }) {
|
|
|
987
999
|
if (t.isIdentifier(node.callee, { name: 'overrideStyle' })) {
|
|
988
1000
|
debug(`FOUND overrideStyle in: ${filename}`);
|
|
989
1001
|
|
|
990
|
-
const [componentNameArg,
|
|
1002
|
+
const [componentNameArg, stylesArg] = node.arguments;
|
|
991
1003
|
|
|
992
1004
|
if (!t.isStringLiteral(componentNameArg)) {
|
|
993
1005
|
debug(` SKIP - componentName is not a string literal`);
|
|
994
1006
|
return;
|
|
995
1007
|
}
|
|
996
1008
|
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1009
|
+
// Accept either a function callback or a plain object
|
|
1010
|
+
let stylesCallback = stylesArg;
|
|
1011
|
+
if (t.isObjectExpression(stylesArg)) {
|
|
1012
|
+
// Wrap plain object in an arrow function: (theme) => ({ ... })
|
|
1013
|
+
stylesCallback = t.arrowFunctionExpression(
|
|
1014
|
+
[t.identifier('theme')],
|
|
1015
|
+
t.parenthesizedExpression(stylesArg)
|
|
1016
|
+
);
|
|
1017
|
+
} else if (!t.isArrowFunctionExpression(stylesArg) &&
|
|
1018
|
+
!t.isFunctionExpression(stylesArg)) {
|
|
1019
|
+
debug(` SKIP - second argument is not a function or object`);
|
|
1000
1020
|
return;
|
|
1001
1021
|
}
|
|
1002
1022
|
|
package/src/componentStyles.ts
CHANGED
|
@@ -22,10 +22,12 @@ import type { TextStyle, ViewStyle } from 'react-native';
|
|
|
22
22
|
/**
|
|
23
23
|
* Registry interface that components augment to register their style types.
|
|
24
24
|
* This enables type-safe extendStyle and overrideStyle calls.
|
|
25
|
+
*
|
|
26
|
+
* Style definitions must use plain style objects, not functions.
|
|
25
27
|
*/
|
|
26
28
|
export interface ComponentStyleRegistry {
|
|
27
29
|
// Components augment this interface to add their style types
|
|
28
|
-
// Example: Text: { text:
|
|
30
|
+
// Example: Text: { text: TextStyle & { variants?: { ... } } }
|
|
29
31
|
}
|
|
30
32
|
|
|
31
33
|
/**
|
|
@@ -37,38 +39,25 @@ export type ComponentStyleDef<K extends string> = K extends keyof ComponentStyle
|
|
|
37
39
|
: Record<string, any>;
|
|
38
40
|
|
|
39
41
|
/**
|
|
40
|
-
* Deep partial type
|
|
41
|
-
*
|
|
42
|
+
* Deep partial type for style objects.
|
|
43
|
+
* Recursively makes all properties optional.
|
|
44
|
+
* Extensions must be plain style objects — functions are not supported.
|
|
42
45
|
*/
|
|
43
|
-
export type DeepPartialStyle<T> = T extends
|
|
44
|
-
?
|
|
45
|
-
: T
|
|
46
|
-
? { [K in keyof T]?: DeepPartialStyle<T[K]> }
|
|
47
|
-
: T;
|
|
46
|
+
export type DeepPartialStyle<T> = T extends object
|
|
47
|
+
? { [K in keyof T]?: DeepPartialStyle<T[K]> }
|
|
48
|
+
: T;
|
|
48
49
|
|
|
49
50
|
/**
|
|
50
|
-
* Style definition for extendStyle -
|
|
51
|
-
*
|
|
51
|
+
* Style definition for extendStyle - plain style objects only.
|
|
52
|
+
* Functions are not supported; the babel plugin merges plain objects into base styles.
|
|
52
53
|
*/
|
|
53
54
|
export type ExtendStyleDef<K extends string> = DeepPartialStyle<ComponentStyleDef<K>>;
|
|
54
55
|
|
|
55
56
|
/**
|
|
56
|
-
* Style definition for overrideStyle - requires full implementation
|
|
57
|
+
* Style definition for overrideStyle - requires full style implementation.
|
|
57
58
|
*/
|
|
58
59
|
export type OverrideStyleDef<K extends string> = ComponentStyleDef<K>;
|
|
59
60
|
|
|
60
|
-
/**
|
|
61
|
-
* Helper to extract the params type from a dynamic style function.
|
|
62
|
-
* Use this to type your extension functions.
|
|
63
|
-
*
|
|
64
|
-
* @example
|
|
65
|
-
* ```typescript
|
|
66
|
-
* type TextParams = StyleParams<TextStyleDef['text']>;
|
|
67
|
-
* // TextParams = { color?: TextColorVariant }
|
|
68
|
-
* ```
|
|
69
|
-
*/
|
|
70
|
-
export type StyleParams<T> = T extends (params: infer P) => any ? P : never;
|
|
71
|
-
|
|
72
61
|
// =============================================================================
|
|
73
62
|
// Common Style Types
|
|
74
63
|
// =============================================================================
|
|
@@ -86,8 +75,3 @@ export interface StyleWithVariants<TVariants extends Record<string, any> = Recor
|
|
|
86
75
|
[K in keyof TVariants]?: TVariants[K];
|
|
87
76
|
} & { styles: ViewStyle | TextStyle }>;
|
|
88
77
|
}
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* Dynamic style function type.
|
|
92
|
-
*/
|
|
93
|
-
export type DynamicStyleFn<TParams, TStyle> = (params: TParams) => TStyle;
|
package/src/styleBuilder.ts
CHANGED
|
@@ -102,18 +102,27 @@ export function defineStyle<TTheme, TStyles extends Record<string, unknown>>(
|
|
|
102
102
|
/**
|
|
103
103
|
* Extend existing component styles (merged at build time).
|
|
104
104
|
* Import BEFORE components for extensions to apply.
|
|
105
|
+
*
|
|
106
|
+
* Accepts either a plain style object or a theme callback:
|
|
107
|
+
* ```typescript
|
|
108
|
+
* // Plain object (no theme access needed)
|
|
109
|
+
* extendStyle('Text', { text: { fontFamily: 'MyFont' } });
|
|
110
|
+
*
|
|
111
|
+
* // Theme callback (when you need theme tokens)
|
|
112
|
+
* extendStyle('Text', (theme) => ({ text: { color: theme.colors.text.primary } }));
|
|
113
|
+
* ```
|
|
105
114
|
*/
|
|
106
115
|
export function extendStyle<K extends keyof ComponentStyleRegistry>(
|
|
107
116
|
componentName: K,
|
|
108
|
-
styles: (theme: any) => ExtendStyleDef<K>
|
|
117
|
+
styles: ExtendStyleDef<K> | ((theme: any) => ExtendStyleDef<K>)
|
|
109
118
|
): void;
|
|
110
119
|
export function extendStyle<K extends string>(
|
|
111
120
|
componentName: K,
|
|
112
|
-
styles: (theme: any) => Record<string, any>
|
|
121
|
+
styles: Record<string, any> | ((theme: any) => Record<string, any>)
|
|
113
122
|
): void;
|
|
114
123
|
export function extendStyle(
|
|
115
124
|
_componentName: string,
|
|
116
|
-
_styles:
|
|
125
|
+
_styles: any
|
|
117
126
|
): void {
|
|
118
127
|
// Babel removes this call and merges into defineStyle
|
|
119
128
|
}
|
|
@@ -121,18 +130,27 @@ export function extendStyle(
|
|
|
121
130
|
/**
|
|
122
131
|
* Override component styles completely (replaces base at build time).
|
|
123
132
|
* Import BEFORE components for overrides to apply.
|
|
133
|
+
*
|
|
134
|
+
* Accepts either a plain style object or a theme callback:
|
|
135
|
+
* ```typescript
|
|
136
|
+
* // Plain object
|
|
137
|
+
* overrideStyle('Text', { text: { fontFamily: 'MyFont' } });
|
|
138
|
+
*
|
|
139
|
+
* // Theme callback
|
|
140
|
+
* overrideStyle('Text', (theme) => ({ text: { color: theme.colors.text.primary } }));
|
|
141
|
+
* ```
|
|
124
142
|
*/
|
|
125
143
|
export function overrideStyle<K extends keyof ComponentStyleRegistry>(
|
|
126
144
|
componentName: K,
|
|
127
|
-
styles: (theme: any) => OverrideStyleDef<K>
|
|
145
|
+
styles: OverrideStyleDef<K> | ((theme: any) => OverrideStyleDef<K>)
|
|
128
146
|
): void;
|
|
129
147
|
export function overrideStyle<K extends string>(
|
|
130
148
|
componentName: K,
|
|
131
|
-
styles: (theme: any) => Record<string, any>
|
|
149
|
+
styles: Record<string, any> | ((theme: any) => Record<string, any>)
|
|
132
150
|
): void;
|
|
133
151
|
export function overrideStyle(
|
|
134
152
|
_componentName: string,
|
|
135
|
-
_styles:
|
|
153
|
+
_styles: any
|
|
136
154
|
): void {
|
|
137
155
|
// Babel removes this call and replaces defineStyle
|
|
138
156
|
}
|