@idealyst/components 1.0.23 → 1.0.25
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 +567 -567
- package/package.json +2 -6
- package/plugin/web.js +319 -185
- package/src/Avatar/Avatar.native.tsx +43 -43
- package/src/Avatar/Avatar.styles.tsx +66 -66
- package/src/Avatar/Avatar.web.tsx +50 -50
- package/src/Avatar/index.native.ts +1 -1
- package/src/Avatar/index.ts +1 -1
- package/src/Avatar/index.web.ts +1 -1
- package/src/Avatar/types.ts +42 -42
- package/src/Badge/Badge.native.tsx +42 -42
- package/src/Badge/Badge.styles.tsx +153 -153
- package/src/Badge/Badge.web.tsx +44 -44
- package/src/Badge/index.native.ts +1 -1
- package/src/Badge/index.ts +1 -1
- package/src/Badge/index.web.ts +1 -1
- package/src/Badge/types.ts +33 -33
- package/src/Button/Button.native.tsx +38 -38
- package/src/Button/Button.styles.tsx +214 -214
- package/src/Button/Button.types.ts +11 -11
- package/src/Button/Button.web.tsx +55 -55
- package/src/Button/index.native.ts +2 -2
- package/src/Button/index.ts +4 -4
- package/src/Button/index.web.ts +2 -2
- package/src/Button/types.ts +48 -48
- package/src/Card/Card.native.tsx +51 -51
- package/src/Card/Card.styles.tsx +239 -239
- package/src/Card/Card.web.tsx +61 -61
- package/src/Card/index.native.ts +2 -2
- package/src/Card/index.ts +4 -4
- package/src/Card/index.web.ts +2 -2
- package/src/Card/types.ts +58 -58
- package/src/Checkbox/Checkbox.native.tsx +98 -98
- package/src/Checkbox/Checkbox.styles.tsx +291 -291
- package/src/Checkbox/Checkbox.web.tsx +130 -130
- package/src/Checkbox/index.native.ts +2 -2
- package/src/Checkbox/index.ts +4 -4
- package/src/Checkbox/index.web.ts +2 -2
- package/src/Checkbox/types.ts +78 -78
- package/src/Divider/Divider.native.tsx +144 -144
- package/src/Divider/Divider.styles.tsx +601 -601
- package/src/Divider/Divider.web.tsx +72 -72
- package/src/Divider/index.native.ts +2 -2
- package/src/Divider/index.ts +4 -4
- package/src/Divider/index.web.ts +2 -2
- package/src/Divider/types.ts +53 -53
- package/src/Icon/Icon.native.tsx +38 -38
- package/src/Icon/Icon.styles.tsx +49 -49
- package/src/Icon/Icon.web.tsx +46 -46
- package/src/Icon/icon-types.ts +7452 -7452
- package/src/Icon/index.native.ts +2 -2
- package/src/Icon/index.ts +4 -4
- package/src/Icon/index.web.ts +2 -2
- package/src/Icon/types.ts +35 -35
- package/src/Input/Input.native.tsx +74 -74
- package/src/Input/Input.styles.tsx +176 -176
- package/src/Input/Input.web.tsx +70 -70
- package/src/Input/index.native.ts +2 -2
- package/src/Input/index.ts +4 -4
- package/src/Input/index.web.ts +2 -2
- package/src/Input/types.ts +68 -68
- package/src/Screen/Screen.native.tsx +40 -40
- package/src/Screen/Screen.styles.tsx +59 -59
- package/src/Screen/Screen.web.tsx +32 -32
- package/src/Screen/index.native.ts +1 -1
- package/src/Screen/index.ts +1 -1
- package/src/Screen/index.web.ts +1 -1
- package/src/Screen/types.ts +37 -37
- package/src/Text/Text.native.tsx +35 -35
- package/src/Text/Text.styles.tsx +66 -66
- package/src/Text/Text.web.tsx +40 -40
- package/src/Text/index.native.ts +2 -2
- package/src/Text/index.ts +4 -4
- package/src/Text/index.web.ts +2 -2
- package/src/Text/types.ts +38 -38
- package/src/View/View.native.tsx +55 -55
- package/src/View/View.styles.tsx +102 -102
- package/src/View/View.web.tsx +59 -59
- package/src/View/index.native.ts +2 -2
- package/src/View/index.ts +4 -4
- package/src/View/index.web.ts +2 -2
- package/src/View/types.ts +72 -72
- package/src/examples/AllExamples.tsx +71 -71
- package/src/examples/AvatarExamples.tsx +96 -96
- package/src/examples/BadgeExamples.tsx +199 -199
- package/src/examples/ButtonExamples.tsx +149 -149
- package/src/examples/CardExamples.tsx +175 -175
- package/src/examples/CheckboxExamples.tsx +216 -216
- package/src/examples/DividerExamples.tsx +217 -217
- package/src/examples/IconExamples.tsx +341 -341
- package/src/examples/InputExamples.tsx +133 -133
- package/src/examples/README.md +135 -135
- package/src/examples/ScreenExamples.tsx +153 -153
- package/src/examples/TextExamples.tsx +88 -88
- package/src/examples/ThemeExtensionExamples.tsx +90 -90
- package/src/examples/ValidationExamples.tsx +94 -94
- package/src/examples/ViewExamples.tsx +128 -128
- package/src/examples/extendedTheme.ts +328 -328
- package/src/examples/index.ts +14 -14
- package/src/index.native.ts +48 -48
- package/src/index.ts +47 -47
- package/src/theme/breakpoints.ts +8 -8
- package/src/theme/colorResolver.ts +217 -217
- package/src/theme/colors.ts +314 -314
- package/src/theme/defaultThemes.ts +325 -325
- package/src/theme/index.ts +187 -187
- package/src/theme/themeBuilder.ts +601 -601
- package/src/theme/unistyles.d.ts +5 -5
- package/src/theme/variantHelpers.ts +583 -583
- package/src/theme/variants.ts +55 -55
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@idealyst/components",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.25",
|
|
4
4
|
"description": "Shared component library for React and React Native",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"module": "src/index.ts",
|
|
@@ -35,13 +35,11 @@
|
|
|
35
35
|
}
|
|
36
36
|
},
|
|
37
37
|
"scripts": {
|
|
38
|
-
"build": "rollup -c",
|
|
39
|
-
"dev": "rollup -c -w",
|
|
40
38
|
"prepublishOnly": "echo 'Publishing TypeScript source directly'",
|
|
41
39
|
"publish:npm": "npm publish"
|
|
42
40
|
},
|
|
43
41
|
"peerDependencies": {
|
|
44
|
-
"@idealyst/theme": "^1.0.
|
|
42
|
+
"@idealyst/theme": "^1.0.25",
|
|
45
43
|
"@mdi/js": "^7.4.47",
|
|
46
44
|
"@mdi/react": "^1.6.1",
|
|
47
45
|
"@react-native-vector-icons/common": "^12.0.1",
|
|
@@ -84,8 +82,6 @@
|
|
|
84
82
|
},
|
|
85
83
|
"devDependencies": {
|
|
86
84
|
"@types/react": "^19.1.0",
|
|
87
|
-
"rollup": "^3.20.0",
|
|
88
|
-
"rollup-plugin-typescript2": "^0.34.0",
|
|
89
85
|
"typescript": "^5.0.0"
|
|
90
86
|
},
|
|
91
87
|
"files": [
|
package/plugin/web.js
CHANGED
|
@@ -1,186 +1,320 @@
|
|
|
1
|
-
module.exports = function ({ types: t }) {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
);
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
1
|
+
module.exports = function ({ types: t }, options = {}) {
|
|
2
|
+
const debug = options.debug || false;
|
|
3
|
+
const manifestPath = options.manifestPath || './icons.manifest.json';
|
|
4
|
+
|
|
5
|
+
// Debug logging function that only logs when debug is enabled
|
|
6
|
+
const debugLog = (...args) => {
|
|
7
|
+
if (debug) {
|
|
8
|
+
console.log(...args);
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
debugLog('[mdi-auto-import] Plugin loaded');
|
|
13
|
+
|
|
14
|
+
const importedIcons = new Set();
|
|
15
|
+
const iconImportIdentifiers = new Map();
|
|
16
|
+
let hasIconImport = false;
|
|
17
|
+
let manifestIcons = new Set();
|
|
18
|
+
|
|
19
|
+
// Load icon manifest if it exists
|
|
20
|
+
function loadIconManifest() {
|
|
21
|
+
try {
|
|
22
|
+
const fs = require('fs');
|
|
23
|
+
const path = require('path');
|
|
24
|
+
|
|
25
|
+
// Try to resolve the manifest path relative to the current working directory
|
|
26
|
+
const fullPath = path.resolve(process.cwd(), manifestPath);
|
|
27
|
+
|
|
28
|
+
if (fs.existsSync(fullPath)) {
|
|
29
|
+
const manifestContent = fs.readFileSync(fullPath, 'utf8');
|
|
30
|
+
const manifest = JSON.parse(manifestContent);
|
|
31
|
+
|
|
32
|
+
if (manifest.icons && Array.isArray(manifest.icons)) {
|
|
33
|
+
manifest.icons.forEach(iconName => {
|
|
34
|
+
if (typeof iconName === 'string') {
|
|
35
|
+
manifestIcons.add(iconName);
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
debugLog(`[mdi-auto-import] Loaded ${manifestIcons.size} icons from manifest: ${fullPath}`);
|
|
39
|
+
debugLog('[mdi-auto-import] Manifest icons:', Array.from(manifestIcons));
|
|
40
|
+
} else {
|
|
41
|
+
console.warn(`[mdi-auto-import] Invalid manifest format in ${fullPath}. Expected { "icons": ["icon-name", ...] }`);
|
|
42
|
+
}
|
|
43
|
+
} else {
|
|
44
|
+
debugLog(`[mdi-auto-import] No manifest found at ${fullPath}`);
|
|
45
|
+
}
|
|
46
|
+
} catch (error) {
|
|
47
|
+
console.warn(`[mdi-auto-import] Error loading manifest from ${manifestPath}: ${error.message}`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function formatIconName(name) {
|
|
52
|
+
// Handle empty or invalid names
|
|
53
|
+
if (!name || typeof name !== 'string') {
|
|
54
|
+
throw new Error(`Invalid icon name: ${name}`);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const formatted = name
|
|
58
|
+
// Convert kebab-case and snake_case to PascalCase
|
|
59
|
+
.replace(/[-_]/g, ' ')
|
|
60
|
+
.replace(/([a-z])([A-Z])/g, '$1 $2')
|
|
61
|
+
.split(' ')
|
|
62
|
+
.filter(part => part.length > 0)
|
|
63
|
+
.map(part => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase())
|
|
64
|
+
.join('');
|
|
65
|
+
|
|
66
|
+
debugLog(`[mdi-auto-import] formatIconName: ${name} -> ${formatted}`);
|
|
67
|
+
return formatted;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function getMdiIconName(name) {
|
|
71
|
+
const mdiName = `mdi${formatIconName(name)}`;
|
|
72
|
+
debugLog(`[mdi-auto-import] getMdiIconName: ${name} -> ${mdiName}`);
|
|
73
|
+
return mdiName;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function getIconIdentifier(iconName) {
|
|
77
|
+
if (!iconImportIdentifiers.has(iconName)) {
|
|
78
|
+
iconImportIdentifiers.set(iconName, `_${iconName}`);
|
|
79
|
+
}
|
|
80
|
+
const identifier = iconImportIdentifiers.get(iconName);
|
|
81
|
+
debugLog(`[mdi-auto-import] getIconIdentifier: ${iconName} -> ${identifier}`);
|
|
82
|
+
return identifier;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Recursively extract all possible string literal values from an expression
|
|
86
|
+
function extractIconNames(expression, path) {
|
|
87
|
+
const iconNames = new Set();
|
|
88
|
+
|
|
89
|
+
function traverse(node) {
|
|
90
|
+
if (!node) return;
|
|
91
|
+
|
|
92
|
+
if (t.isStringLiteral(node)) {
|
|
93
|
+
iconNames.add(node.value);
|
|
94
|
+
debugLog(`[mdi-auto-import] Found string literal: ${node.value}`);
|
|
95
|
+
}
|
|
96
|
+
else if (t.isConditionalExpression(node)) {
|
|
97
|
+
// Handle ternary: condition ? 'icon1' : 'icon2'
|
|
98
|
+
debugLog('[mdi-auto-import] Processing conditional expression');
|
|
99
|
+
traverse(node.consequent);
|
|
100
|
+
traverse(node.alternate);
|
|
101
|
+
}
|
|
102
|
+
else if (t.isLogicalExpression(node)) {
|
|
103
|
+
// Handle logical: condition && 'icon1' || 'icon2'
|
|
104
|
+
debugLog('[mdi-auto-import] Processing logical expression');
|
|
105
|
+
traverse(node.left);
|
|
106
|
+
traverse(node.right);
|
|
107
|
+
}
|
|
108
|
+
else if (t.isTemplateLiteral(node)) {
|
|
109
|
+
// Handle template literals with no expressions (static strings)
|
|
110
|
+
if (node.expressions.length === 0 && node.quasis.length === 1) {
|
|
111
|
+
const value = node.quasis[0].value.cooked;
|
|
112
|
+
iconNames.add(value);
|
|
113
|
+
debugLog(`[mdi-auto-import] Found template literal: ${value}`);
|
|
114
|
+
} else {
|
|
115
|
+
debugLog('[mdi-auto-import] Skipping dynamic template literal');
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
else if (t.isMemberExpression(node)) {
|
|
119
|
+
// Handle object.property where object is static
|
|
120
|
+
if (t.isIdentifier(node.object) && t.isIdentifier(node.property)) {
|
|
121
|
+
debugLog(`[mdi-auto-import] Found member expression: ${node.object.name}.${node.property.name}`);
|
|
122
|
+
// We could potentially resolve this if we track object declarations
|
|
123
|
+
// For now, just warn that we found it but can't resolve it
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
else if (t.isCallExpression(node)) {
|
|
127
|
+
debugLog('[mdi-auto-import] Found function call - cannot statically analyze');
|
|
128
|
+
console.warn(`[mdi-auto-import] Function call detected at ${path.node.loc ? `${path.node.loc.start.line}:${path.node.loc.start.column}` : 'unknown location'}. Consider adding icon names to manifest (${manifestPath}) for auto-import support.`);
|
|
129
|
+
// For function calls, we can't statically determine the result
|
|
130
|
+
// But we could potentially add runtime analysis or hints
|
|
131
|
+
}
|
|
132
|
+
else if (t.isIdentifier(node)) {
|
|
133
|
+
debugLog(`[mdi-auto-import] Found identifier: ${node.name}`);
|
|
134
|
+
// We could potentially trace variable declarations
|
|
135
|
+
// For now, just note that we found it
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
debugLog(`[mdi-auto-import] Unhandled expression type: ${node.type}`);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
traverse(expression);
|
|
143
|
+
return Array.from(iconNames);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return {
|
|
147
|
+
name: 'mdi-auto-import',
|
|
148
|
+
visitor: {
|
|
149
|
+
Program: {
|
|
150
|
+
enter(path) {
|
|
151
|
+
// Reset state for each file
|
|
152
|
+
importedIcons.clear();
|
|
153
|
+
iconImportIdentifiers.clear();
|
|
154
|
+
hasIconImport = false;
|
|
155
|
+
manifestIcons.clear();
|
|
156
|
+
|
|
157
|
+
// Load icon manifest
|
|
158
|
+
loadIconManifest();
|
|
159
|
+
|
|
160
|
+
// Add all manifest icons to the import list
|
|
161
|
+
manifestIcons.forEach(iconName => {
|
|
162
|
+
try {
|
|
163
|
+
const mdiIconName = getMdiIconName(iconName);
|
|
164
|
+
importedIcons.add(mdiIconName);
|
|
165
|
+
debugLog(`[mdi-auto-import] Added manifest icon to import list: ${mdiIconName}`);
|
|
166
|
+
} catch (error) {
|
|
167
|
+
console.error(`[mdi-auto-import] Error processing manifest icon "${iconName}": ${error.message}`);
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
// Check if Icon is already imported from @mdi/react
|
|
172
|
+
path.node.body.forEach(node => {
|
|
173
|
+
if (t.isImportDeclaration(node) && node.source.value === '@mdi/react') {
|
|
174
|
+
debugLog('[mdi-auto-import] Found @mdi/react import');
|
|
175
|
+
const hasIconSpecifier = node.specifiers.some(spec =>
|
|
176
|
+
t.isImportDefaultSpecifier(spec) && spec.local.name === 'MdiIcon'
|
|
177
|
+
);
|
|
178
|
+
if (hasIconSpecifier) {
|
|
179
|
+
debugLog('[mdi-auto-import] MdiIcon already imported');
|
|
180
|
+
hasIconImport = true;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
},
|
|
185
|
+
exit(path) {
|
|
186
|
+
if (importedIcons.size === 0) {
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
debugLog(`[mdi-auto-import] importedIcons.size: ${importedIcons.size}`);
|
|
190
|
+
|
|
191
|
+
// Add imports at the top of the file if any icons were used
|
|
192
|
+
if (importedIcons.size > 0) {
|
|
193
|
+
debugLog('[mdi-auto-import] Adding imports for icons:', Array.from(importedIcons));
|
|
194
|
+
|
|
195
|
+
// Import individual icons from @mdi/js
|
|
196
|
+
const iconImportSpecifiers = Array.from(importedIcons).map(iconName => {
|
|
197
|
+
const identifier = getIconIdentifier(iconName);
|
|
198
|
+
return t.importSpecifier(
|
|
199
|
+
t.identifier(identifier),
|
|
200
|
+
t.identifier(iconName)
|
|
201
|
+
);
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
const iconImportDeclaration = t.importDeclaration(
|
|
205
|
+
iconImportSpecifiers,
|
|
206
|
+
t.stringLiteral('@mdi/js')
|
|
207
|
+
);
|
|
208
|
+
|
|
209
|
+
// Import Icon component from @mdi/react if not already imported
|
|
210
|
+
if (!hasIconImport) {
|
|
211
|
+
debugLog('[mdi-auto-import] Adding MdiIcon import from @mdi/react');
|
|
212
|
+
const iconComponentImport = t.importDeclaration(
|
|
213
|
+
[t.importDefaultSpecifier(t.identifier('MdiIcon'))],
|
|
214
|
+
t.stringLiteral('@mdi/react')
|
|
215
|
+
);
|
|
216
|
+
path.unshiftContainer('body', iconComponentImport);
|
|
217
|
+
} else {
|
|
218
|
+
debugLog('[mdi-auto-import] MdiIcon already imported, skipping');
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// Add icon imports
|
|
222
|
+
path.unshiftContainer('body', iconImportDeclaration);
|
|
223
|
+
debugLog('[mdi-auto-import] Imports added successfully');
|
|
224
|
+
} else {
|
|
225
|
+
debugLog('[mdi-auto-import] No icons to import');
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
},
|
|
229
|
+
|
|
230
|
+
JSXElement(path) {
|
|
231
|
+
const { node } = path;
|
|
232
|
+
|
|
233
|
+
// Check if this is an Icon component from @idealyst/components
|
|
234
|
+
if (
|
|
235
|
+
t.isJSXIdentifier(node.openingElement.name) &&
|
|
236
|
+
node.openingElement.name.name === 'Icon'
|
|
237
|
+
) {
|
|
238
|
+
|
|
239
|
+
// Find the name attribute
|
|
240
|
+
const nameAttr = node.openingElement.attributes.find(attr =>
|
|
241
|
+
t.isJSXAttribute(attr) &&
|
|
242
|
+
t.isJSXIdentifier(attr.name) &&
|
|
243
|
+
attr.name.name === 'name'
|
|
244
|
+
);
|
|
245
|
+
|
|
246
|
+
if (!nameAttr) {
|
|
247
|
+
debugLog('[mdi-auto-import] No name attribute found');
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
let iconNames = [];
|
|
252
|
+
|
|
253
|
+
// Handle both string literals and JSX expressions
|
|
254
|
+
if (nameAttr && t.isStringLiteral(nameAttr.value)) {
|
|
255
|
+
iconNames = [nameAttr.value.value];
|
|
256
|
+
debugLog(`[mdi-auto-import] Found direct string literal: ${nameAttr.value.value}`);
|
|
257
|
+
} else if (nameAttr && t.isJSXExpressionContainer(nameAttr.value)) {
|
|
258
|
+
// Handle JSX expressions with enhanced detection
|
|
259
|
+
const expression = nameAttr.value.expression;
|
|
260
|
+
iconNames = extractIconNames(expression, path);
|
|
261
|
+
|
|
262
|
+
if (iconNames.length === 0) {
|
|
263
|
+
// For dynamic expressions we can't resolve, leave a helpful comment
|
|
264
|
+
console.warn(`[mdi-auto-import] Cannot determine icon name for dynamic expression at ${path.node.loc ? `${path.node.loc.start.line}:${path.node.loc.start.column}` : 'unknown location'}. Consider adding icon names to manifest (${manifestPath}) for auto-import support.`);
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
if (iconNames.length > 0) {
|
|
270
|
+
debugLog(`[mdi-auto-import] Processing icons: ${iconNames.join(', ')}`);
|
|
271
|
+
|
|
272
|
+
// Process each icon name found
|
|
273
|
+
const processedIcons = [];
|
|
274
|
+
iconNames.forEach(iconName => {
|
|
275
|
+
try {
|
|
276
|
+
const mdiIconName = getMdiIconName(iconName);
|
|
277
|
+
const iconIdentifier = getIconIdentifier(mdiIconName);
|
|
278
|
+
|
|
279
|
+
// Track that we need to import this icon
|
|
280
|
+
importedIcons.add(mdiIconName);
|
|
281
|
+
processedIcons.push({ iconName, mdiIconName, iconIdentifier });
|
|
282
|
+
debugLog(`[mdi-auto-import] Added icon to import list: ${mdiIconName}`);
|
|
283
|
+
} catch (error) {
|
|
284
|
+
console.error(`[mdi-auto-import] Error processing icon "${iconName}": ${error.message}`);
|
|
285
|
+
}
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
// If we have exactly one icon, we can transform the component
|
|
289
|
+
if (processedIcons.length === 1) {
|
|
290
|
+
const { iconIdentifier } = processedIcons[0];
|
|
291
|
+
|
|
292
|
+
// Replace name="iconName" with path={iconIdentifier}
|
|
293
|
+
const pathAttr = t.jsxAttribute(
|
|
294
|
+
t.jsxIdentifier('path'),
|
|
295
|
+
t.jsxExpressionContainer(t.identifier(iconIdentifier))
|
|
296
|
+
);
|
|
297
|
+
|
|
298
|
+
// Remove the name attribute and add the path attribute
|
|
299
|
+
node.openingElement.attributes = node.openingElement.attributes
|
|
300
|
+
.filter(attr => !(
|
|
301
|
+
t.isJSXAttribute(attr) &&
|
|
302
|
+
t.isJSXIdentifier(attr.name) &&
|
|
303
|
+
attr.name.name === 'name'
|
|
304
|
+
))
|
|
305
|
+
.concat(pathAttr);
|
|
306
|
+
|
|
307
|
+
debugLog(`[mdi-auto-import] Transformed Icon component: name="${processedIcons[0].iconName}" -> path={${iconIdentifier}}`);
|
|
308
|
+
} else if (processedIcons.length > 1) {
|
|
309
|
+
// For multiple possible icons (like conditionals), we add all imports but don't transform
|
|
310
|
+
debugLog(`[mdi-auto-import] Found multiple possible icons (${processedIcons.length}), adding imports but not transforming component`);
|
|
311
|
+
console.warn(`[mdi-auto-import] Found conditional icon usage at ${path.node.loc ? `${path.node.loc.start.line}:${path.node.loc.start.column}` : 'unknown location'}. All possible icons will be imported, but the component will not be auto-transformed. Consider manual transformation if needed.`);
|
|
312
|
+
}
|
|
313
|
+
} else {
|
|
314
|
+
debugLog('[mdi-auto-import] No icon names found');
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
};
|
|
186
320
|
};
|
|
@@ -1,44 +1,44 @@
|
|
|
1
|
-
import React, { useState } from 'react';
|
|
2
|
-
import { View, Text, Image } from 'react-native';
|
|
3
|
-
import { AvatarProps } from './types';
|
|
4
|
-
import { avatarStyles } from './Avatar.styles';
|
|
5
|
-
|
|
6
|
-
const Avatar: React.FC<AvatarProps> = ({
|
|
7
|
-
src,
|
|
8
|
-
alt,
|
|
9
|
-
fallback,
|
|
10
|
-
size = 'medium',
|
|
11
|
-
shape = 'circle',
|
|
12
|
-
style,
|
|
13
|
-
testID,
|
|
14
|
-
}) => {
|
|
15
|
-
const [hasError, setHasError] = useState(false);
|
|
16
|
-
|
|
17
|
-
avatarStyles.useVariants({
|
|
18
|
-
size,
|
|
19
|
-
shape,
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
const handleImageError = () => {
|
|
23
|
-
setHasError(true);
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
return (
|
|
27
|
-
<View style={[avatarStyles.avatar, style]} testID={testID}>
|
|
28
|
-
{src && !hasError ? (
|
|
29
|
-
<Image
|
|
30
|
-
source={typeof src === 'string' ? { uri: src } : src}
|
|
31
|
-
style={avatarStyles.image}
|
|
32
|
-
onError={handleImageError}
|
|
33
|
-
accessibilityLabel={alt}
|
|
34
|
-
/>
|
|
35
|
-
) : (
|
|
36
|
-
<Text style={avatarStyles.fallback}>
|
|
37
|
-
{fallback}
|
|
38
|
-
</Text>
|
|
39
|
-
)}
|
|
40
|
-
</View>
|
|
41
|
-
);
|
|
42
|
-
};
|
|
43
|
-
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import { View, Text, Image } from 'react-native';
|
|
3
|
+
import { AvatarProps } from './types';
|
|
4
|
+
import { avatarStyles } from './Avatar.styles';
|
|
5
|
+
|
|
6
|
+
const Avatar: React.FC<AvatarProps> = ({
|
|
7
|
+
src,
|
|
8
|
+
alt,
|
|
9
|
+
fallback,
|
|
10
|
+
size = 'medium',
|
|
11
|
+
shape = 'circle',
|
|
12
|
+
style,
|
|
13
|
+
testID,
|
|
14
|
+
}) => {
|
|
15
|
+
const [hasError, setHasError] = useState(false);
|
|
16
|
+
|
|
17
|
+
avatarStyles.useVariants({
|
|
18
|
+
size,
|
|
19
|
+
shape,
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
const handleImageError = () => {
|
|
23
|
+
setHasError(true);
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
return (
|
|
27
|
+
<View style={[avatarStyles.avatar, style]} testID={testID}>
|
|
28
|
+
{src && !hasError ? (
|
|
29
|
+
<Image
|
|
30
|
+
source={typeof src === 'string' ? { uri: src } : src}
|
|
31
|
+
style={avatarStyles.image}
|
|
32
|
+
onError={handleImageError}
|
|
33
|
+
accessibilityLabel={alt}
|
|
34
|
+
/>
|
|
35
|
+
) : (
|
|
36
|
+
<Text style={avatarStyles.fallback}>
|
|
37
|
+
{fallback}
|
|
38
|
+
</Text>
|
|
39
|
+
)}
|
|
40
|
+
</View>
|
|
41
|
+
);
|
|
42
|
+
};
|
|
43
|
+
|
|
44
44
|
export default Avatar;
|