react-native-icon-switcher 0.0.0-stage → 0.1.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.
Files changed (92) hide show
  1. package/IconSwitcher.podspec +20 -0
  2. package/LICENSE +20 -0
  3. package/README.md +252 -2
  4. package/android/build.gradle +51 -0
  5. package/android/src/main/AndroidManifest.xml +2 -0
  6. package/android/src/main/java/com/iconswitcher/IconSwitcher.kt +380 -0
  7. package/android/src/main/java/com/iconswitcher/IconSwitcherExceptions.kt +24 -0
  8. package/android/src/main/java/com/iconswitcher/IconSwitcherModule.kt +67 -0
  9. package/android/src/main/java/com/iconswitcher/IconSwitcherPackage.kt +30 -0
  10. package/android/src/test/AndroidManifest.xml +39 -0
  11. package/android/src/test/java/com/iconswitcher/IconSwitcherTest.kt +392 -0
  12. package/app.plugin.js +1 -0
  13. package/ios/ISIconSwitcher.h +49 -0
  14. package/ios/ISIconSwitcher.m +205 -0
  15. package/ios/IconSwitcher.h +5 -0
  16. package/ios/IconSwitcher.mm +100 -0
  17. package/jest/index.d.ts +31 -0
  18. package/jest/index.js +98 -0
  19. package/lib/module/NativeIconSwitcher.js +5 -0
  20. package/lib/module/NativeIconSwitcher.js.map +1 -0
  21. package/lib/module/config.js +6 -0
  22. package/lib/module/config.js.map +1 -0
  23. package/lib/module/errors.js +28 -0
  24. package/lib/module/errors.js.map +1 -0
  25. package/lib/module/index.js +69 -0
  26. package/lib/module/index.js.map +1 -0
  27. package/lib/module/package.json +1 -0
  28. package/lib/module/register.js +2 -0
  29. package/lib/module/register.js.map +1 -0
  30. package/lib/module/remote/index.js +119 -0
  31. package/lib/module/remote/index.js.map +1 -0
  32. package/lib/module/types.js +2 -0
  33. package/lib/module/types.js.map +1 -0
  34. package/lib/module/typetests/icon-name.typetest.js +8 -0
  35. package/lib/module/typetests/icon-name.typetest.js.map +1 -0
  36. package/lib/module/typetests/types-in-sync.typetest.js +7 -0
  37. package/lib/module/typetests/types-in-sync.typetest.js.map +1 -0
  38. package/lib/typescript/package.json +1 -0
  39. package/lib/typescript/src/NativeIconSwitcher.d.ts +18 -0
  40. package/lib/typescript/src/NativeIconSwitcher.d.ts.map +1 -0
  41. package/lib/typescript/src/config.d.ts +4 -0
  42. package/lib/typescript/src/config.d.ts.map +1 -0
  43. package/lib/typescript/src/errors.d.ts +7 -0
  44. package/lib/typescript/src/errors.d.ts.map +1 -0
  45. package/lib/typescript/src/index.d.ts +20 -0
  46. package/lib/typescript/src/index.d.ts.map +1 -0
  47. package/lib/typescript/src/register.d.ts +7 -0
  48. package/lib/typescript/src/register.d.ts.map +1 -0
  49. package/lib/typescript/src/remote/index.d.ts +17 -0
  50. package/lib/typescript/src/remote/index.d.ts.map +1 -0
  51. package/lib/typescript/src/types.d.ts +59 -0
  52. package/lib/typescript/src/types.d.ts.map +1 -0
  53. package/package.json +251 -4
  54. package/plugin/build/cli.d.ts +3 -0
  55. package/plugin/build/cli.js +89 -0
  56. package/plugin/build/core/assets.d.ts +80 -0
  57. package/plugin/build/core/assets.js +463 -0
  58. package/plugin/build/core/errors.d.ts +4 -0
  59. package/plugin/build/core/errors.js +11 -0
  60. package/plugin/build/core/validate.d.ts +6 -0
  61. package/plugin/build/core/validate.js +229 -0
  62. package/plugin/build/index.d.ts +6 -0
  63. package/plugin/build/index.js +134 -0
  64. package/plugin/build/load-config.d.ts +3 -0
  65. package/plugin/build/load-config.js +50 -0
  66. package/plugin/build/paths.d.ts +15 -0
  67. package/plugin/build/paths.js +153 -0
  68. package/plugin/build/sync.d.ts +12 -0
  69. package/plugin/build/sync.js +162 -0
  70. package/plugin/build/transforms/android.d.ts +5 -0
  71. package/plugin/build/transforms/android.js +212 -0
  72. package/plugin/build/transforms/errors.d.ts +4 -0
  73. package/plugin/build/transforms/errors.js +11 -0
  74. package/plugin/build/transforms/index.d.ts +4 -0
  75. package/plugin/build/transforms/index.js +12 -0
  76. package/plugin/build/transforms/ios.d.ts +4 -0
  77. package/plugin/build/transforms/ios.js +111 -0
  78. package/plugin/build/transforms/sampleConfigs.d.ts +3 -0
  79. package/plugin/build/transforms/sampleConfigs.js +33 -0
  80. package/plugin/build/transforms/types.d.ts +2 -0
  81. package/plugin/build/transforms/types.js +14 -0
  82. package/plugin/build/types.d.ts +61 -0
  83. package/plugin/build/types.js +5 -0
  84. package/src/NativeIconSwitcher.ts +17 -0
  85. package/src/config.ts +15 -0
  86. package/src/errors.ts +38 -0
  87. package/src/index.tsx +78 -0
  88. package/src/register.ts +4 -0
  89. package/src/remote/index.ts +142 -0
  90. package/src/types.ts +59 -0
  91. package/src/typetests/icon-name.typetest.ts +12 -0
  92. package/src/typetests/types-in-sync.typetest.ts +16 -0
@@ -0,0 +1,463 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.planAssets = planAssets;
7
+ exports.writeAssets = writeAssets;
8
+ exports._readCornerRgb = _readCornerRgb;
9
+ const node_crypto_1 = __importDefault(require("node:crypto"));
10
+ const promises_1 = __importDefault(require("node:fs/promises"));
11
+ const node_path_1 = __importDefault(require("node:path"));
12
+ const sharp_1 = __importDefault(require("sharp"));
13
+ const LEGACY_DENSITIES = [
14
+ { folder: 'mipmap-mdpi', size: 48 },
15
+ { folder: 'mipmap-hdpi', size: 72 },
16
+ { folder: 'mipmap-xhdpi', size: 96 },
17
+ { folder: 'mipmap-xxhdpi', size: 144 },
18
+ { folder: 'mipmap-xxxhdpi', size: 192 },
19
+ ];
20
+ const ADAPTIVE_DENSITIES = [
21
+ { folder: 'mipmap-mdpi', size: 108 },
22
+ { folder: 'mipmap-hdpi', size: 162 },
23
+ { folder: 'mipmap-xhdpi', size: 216 },
24
+ { folder: 'mipmap-xxhdpi', size: 324 },
25
+ { folder: 'mipmap-xxxhdpi', size: 432 },
26
+ ];
27
+ const PNG_OPTIONS = { compressionLevel: 9, adaptiveFiltering: false };
28
+ function _iosSetFolder(icon) {
29
+ return icon.isDefault
30
+ ? 'AppIcon.appiconset'
31
+ : `AppIcon-${icon.name}.appiconset`;
32
+ }
33
+ function _androidBaseName(icon) {
34
+ return icon.isDefault ? 'ic_launcher' : `ic_launcher_${icon.name}`;
35
+ }
36
+ function _colorResourceName(icon) {
37
+ return icon.isDefault
38
+ ? 'icon_switcher_default_background'
39
+ : `icon_switcher_${icon.name}_background`;
40
+ }
41
+ function _iosVariants(icon) {
42
+ if (!icon.ios) {
43
+ return [];
44
+ }
45
+ const out = [
46
+ { variant: 'light', source: icon.ios.light },
47
+ ];
48
+ if (icon.ios.dark) {
49
+ out.push({ variant: 'dark', source: icon.ios.dark });
50
+ }
51
+ if (icon.ios.tinted) {
52
+ out.push({ variant: 'tinted', source: icon.ios.tinted });
53
+ }
54
+ return out;
55
+ }
56
+ function _legacySource(icon) {
57
+ const android = icon.android;
58
+ if (!android) {
59
+ return null;
60
+ }
61
+ if ('legacy' in android) {
62
+ return android.legacy;
63
+ }
64
+ return null;
65
+ }
66
+ function _hasAdaptive(icon) {
67
+ const android = icon.android;
68
+ return android !== null && !('legacy' in android);
69
+ }
70
+ function planAssets(cfg, projectRoot) {
71
+ const assets = [];
72
+ const colorEntries = [];
73
+ for (const icon of cfg.icons) {
74
+ const setFolder = _iosSetFolder(icon);
75
+ const iosVariants = _iosVariants(icon);
76
+ if (iosVariants.length > 0) {
77
+ for (const { variant, source } of iosVariants) {
78
+ const filename = variant === 'light'
79
+ ? 'AppIcon-1024.png'
80
+ : `AppIcon-1024-${variant}.png`;
81
+ assets.push({
82
+ relativePath: node_path_1.default.join(setFolder, filename),
83
+ job: {
84
+ kind: 'ios-png',
85
+ iconName: icon.name,
86
+ isDefault: icon.isDefault,
87
+ variant,
88
+ sourcePath: source,
89
+ flattenOn: cfg.ios.flattenOn,
90
+ width: 1024,
91
+ height: 1024,
92
+ },
93
+ });
94
+ }
95
+ assets.push({
96
+ relativePath: node_path_1.default.join(setFolder, 'Contents.json'),
97
+ job: {
98
+ kind: 'ios-contents',
99
+ iconName: icon.name,
100
+ isDefault: icon.isDefault,
101
+ variants: iosVariants.map((v) => v.variant),
102
+ },
103
+ });
104
+ }
105
+ const legacySource = _legacySource(icon);
106
+ if (legacySource) {
107
+ const base = _androidBaseName(icon);
108
+ for (const { folder, size } of LEGACY_DENSITIES) {
109
+ for (const round of [false, true]) {
110
+ assets.push({
111
+ relativePath: node_path_1.default.join(folder, `${base}${round ? '_round' : ''}.png`),
112
+ job: {
113
+ kind: 'android-legacy',
114
+ iconName: icon.name,
115
+ isDefault: icon.isDefault,
116
+ round,
117
+ sourcePath: legacySource,
118
+ density: folder,
119
+ size,
120
+ },
121
+ });
122
+ }
123
+ }
124
+ }
125
+ if (_hasAdaptive(icon)) {
126
+ const android = icon.android;
127
+ const base = _androidBaseName(icon);
128
+ const backgroundIsColor = typeof android.background === 'string' &&
129
+ android.background.startsWith('#');
130
+ const backgroundImagePath = typeof android.background === 'string' &&
131
+ !android.background.startsWith('#')
132
+ ? android.background
133
+ : undefined;
134
+ for (const { folder, size } of LEGACY_DENSITIES) {
135
+ for (const round of [false, true]) {
136
+ assets.push({
137
+ relativePath: node_path_1.default.join(folder, `${base}${round ? '_round' : ''}.png`),
138
+ job: {
139
+ kind: 'android-legacy',
140
+ iconName: icon.name,
141
+ isDefault: icon.isDefault,
142
+ round,
143
+ sourcePath: android.foreground,
144
+ density: folder,
145
+ size,
146
+ backgroundColor: backgroundIsColor
147
+ ? android.background
148
+ : undefined,
149
+ backgroundImagePath,
150
+ },
151
+ });
152
+ }
153
+ }
154
+ for (const { folder, size } of ADAPTIVE_DENSITIES) {
155
+ assets.push({
156
+ relativePath: node_path_1.default.join(folder, `${base}_foreground.png`),
157
+ job: {
158
+ kind: 'android-adaptive-foreground',
159
+ iconName: icon.name,
160
+ isDefault: icon.isDefault,
161
+ sourcePath: android.foreground,
162
+ density: folder,
163
+ size,
164
+ },
165
+ });
166
+ if (typeof android.background === 'string' &&
167
+ !android.background.startsWith('#')) {
168
+ assets.push({
169
+ relativePath: node_path_1.default.join(folder, `${base}_background.png`),
170
+ job: {
171
+ kind: 'android-adaptive-background-image',
172
+ iconName: icon.name,
173
+ isDefault: icon.isDefault,
174
+ sourcePath: android.background,
175
+ density: folder,
176
+ size,
177
+ },
178
+ });
179
+ }
180
+ if (android.monochrome) {
181
+ assets.push({
182
+ relativePath: node_path_1.default.join(folder, `${base}_monochrome.png`),
183
+ job: {
184
+ kind: 'android-adaptive-foreground',
185
+ iconName: icon.name,
186
+ isDefault: icon.isDefault,
187
+ sourcePath: android.monochrome,
188
+ density: folder,
189
+ size,
190
+ },
191
+ });
192
+ }
193
+ }
194
+ if (backgroundIsColor) {
195
+ colorEntries.push({
196
+ resourceName: _colorResourceName(icon),
197
+ color: android.background,
198
+ });
199
+ }
200
+ for (const round of [false, true]) {
201
+ assets.push({
202
+ relativePath: node_path_1.default.join('mipmap-anydpi-v26', `${base}${round ? '_round' : ''}.xml`),
203
+ job: {
204
+ kind: 'android-adaptive-xml',
205
+ iconName: icon.name,
206
+ isDefault: icon.isDefault,
207
+ round,
208
+ backgroundIsColor,
209
+ hasMonochrome: Boolean(android.monochrome),
210
+ },
211
+ });
212
+ }
213
+ }
214
+ }
215
+ if (colorEntries.length > 0) {
216
+ const unique = new Map();
217
+ for (const e of colorEntries) {
218
+ unique.set(e.resourceName, e.color);
219
+ }
220
+ assets.push({
221
+ relativePath: node_path_1.default.join('values', 'icon_switcher_colors.xml'),
222
+ job: {
223
+ kind: 'android-colors-xml',
224
+ entries: [...unique.entries()].map(([resourceName, color]) => ({
225
+ resourceName,
226
+ color,
227
+ })),
228
+ },
229
+ });
230
+ }
231
+ return {
232
+ projectRoot,
233
+ flattenOn: cfg.ios.flattenOn,
234
+ assets,
235
+ };
236
+ }
237
+ function _hexToRgb(hex) {
238
+ let normalized = hex.slice(1);
239
+ if (normalized.length === 3) {
240
+ normalized = normalized
241
+ .split('')
242
+ .map((c) => c + c)
243
+ .join('');
244
+ }
245
+ const num = Number.parseInt(normalized, 16);
246
+ return {
247
+ r: (num >> 16) & 0xff,
248
+ g: (num >> 8) & 0xff,
249
+ b: num & 0xff,
250
+ };
251
+ }
252
+ async function _flattenPng(sourceAbs, flattenOn, width, height) {
253
+ const { r, g, b } = _hexToRgb(flattenOn);
254
+ const background = await (0, sharp_1.default)({
255
+ create: {
256
+ width,
257
+ height,
258
+ channels: 3,
259
+ background: { r, g, b },
260
+ },
261
+ })
262
+ .png(PNG_OPTIONS)
263
+ .toBuffer();
264
+ const resized = await (0, sharp_1.default)(sourceAbs)
265
+ .resize(width, height, {
266
+ fit: 'contain',
267
+ background: { r, g, b, alpha: 0 },
268
+ })
269
+ .png()
270
+ .toBuffer();
271
+ return (0, sharp_1.default)(background)
272
+ .composite([{ input: resized, blend: 'over' }])
273
+ .removeAlpha()
274
+ .png(PNG_OPTIONS)
275
+ .toBuffer();
276
+ }
277
+ async function _applyRoundMask(image, size) {
278
+ const mask = Buffer.from(`<svg width="${size}" height="${size}"><circle cx="${size / 2}" cy="${size / 2}" r="${size / 2}" fill="white"/></svg>`);
279
+ return (0, sharp_1.default)(image)
280
+ .composite([{ input: mask, blend: 'dest-in' }])
281
+ .png(PNG_OPTIONS)
282
+ .toBuffer();
283
+ }
284
+ async function _legacyPng(sourceAbs, size, round) {
285
+ const resized = await (0, sharp_1.default)(sourceAbs)
286
+ .resize(size, size, { fit: 'cover' })
287
+ .png()
288
+ .toBuffer();
289
+ if (!round) {
290
+ return (0, sharp_1.default)(resized).png(PNG_OPTIONS).toBuffer();
291
+ }
292
+ return _applyRoundMask(resized, size);
293
+ }
294
+ async function _legacyCompositePng(foregroundAbs, size, round, background) {
295
+ let base;
296
+ if ('color' in background) {
297
+ const { r, g, b } = _hexToRgb(background.color);
298
+ base = await (0, sharp_1.default)({
299
+ create: {
300
+ width: size,
301
+ height: size,
302
+ channels: 4,
303
+ background: { r, g, b, alpha: 255 },
304
+ },
305
+ })
306
+ .png()
307
+ .toBuffer();
308
+ }
309
+ else {
310
+ base = await (0, sharp_1.default)(background.imageAbs)
311
+ .resize(size, size, { fit: 'cover' })
312
+ .png()
313
+ .toBuffer();
314
+ }
315
+ const foreground = await (0, sharp_1.default)(foregroundAbs)
316
+ .resize(size, size, {
317
+ fit: 'contain',
318
+ background: { r: 0, g: 0, b: 0, alpha: 0 },
319
+ })
320
+ .png()
321
+ .toBuffer();
322
+ const flat = await (0, sharp_1.default)(base)
323
+ .composite([{ input: foreground, blend: 'over' }])
324
+ .png(PNG_OPTIONS)
325
+ .toBuffer();
326
+ if (!round) {
327
+ return flat;
328
+ }
329
+ return _applyRoundMask(flat, size);
330
+ }
331
+ async function _resizePng(sourceAbs, size) {
332
+ return (0, sharp_1.default)(sourceAbs)
333
+ .resize(size, size, {
334
+ fit: 'contain',
335
+ background: { r: 0, g: 0, b: 0, alpha: 0 },
336
+ })
337
+ .png(PNG_OPTIONS)
338
+ .toBuffer();
339
+ }
340
+ function _iosContentsJson(variants) {
341
+ const images = variants.map((variant) => {
342
+ const base = {
343
+ idiom: 'universal',
344
+ platform: 'ios',
345
+ size: '1024x1024',
346
+ };
347
+ const filename = variant === 'light' ? 'AppIcon-1024.png' : `AppIcon-1024-${variant}.png`;
348
+ if (variant === 'light') {
349
+ return { ...base, filename };
350
+ }
351
+ const appearanceValue = variant === 'dark' ? 'dark' : 'tinted';
352
+ return {
353
+ ...base,
354
+ filename,
355
+ appearances: [{ appearance: 'luminosity', value: appearanceValue }],
356
+ };
357
+ });
358
+ return `${JSON.stringify({
359
+ images,
360
+ info: { version: 1, author: 'xcode' },
361
+ }, null, 2)}\n`;
362
+ }
363
+ function _adaptiveXml(base, backgroundIsColor, colorResource, hasMonochrome) {
364
+ const backgroundRef = backgroundIsColor
365
+ ? `@color/${colorResource}`
366
+ : `@mipmap/${base}_background`;
367
+ const lines = [
368
+ '<?xml version="1.0" encoding="utf-8"?>',
369
+ '<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">',
370
+ ` <background android:drawable="${backgroundRef}" />`,
371
+ ` <foreground android:drawable="@mipmap/${base}_foreground" />`,
372
+ ];
373
+ if (hasMonochrome) {
374
+ lines.push(` <monochrome android:drawable="@mipmap/${base}_monochrome" />`);
375
+ }
376
+ lines.push('</adaptive-icon>', '');
377
+ return lines.join('\n');
378
+ }
379
+ function _colorsXml(entries) {
380
+ const lines = ['<?xml version="1.0" encoding="utf-8"?>', '<resources>'];
381
+ for (const { resourceName, color } of entries) {
382
+ lines.push(` <color name="${resourceName}">${color}</color>`);
383
+ }
384
+ lines.push('</resources>', '');
385
+ return lines.join('\n');
386
+ }
387
+ async function _writeBuffer(abs, data) {
388
+ await promises_1.default.mkdir(node_path_1.default.dirname(abs), { recursive: true });
389
+ await promises_1.default.writeFile(abs, data);
390
+ return node_crypto_1.default.createHash('sha256').update(data).digest('hex');
391
+ }
392
+ async function _writeText(abs, text) {
393
+ const data = Buffer.from(text, 'utf8');
394
+ return _writeBuffer(abs, data);
395
+ }
396
+ async function _renderJob(plan, job) {
397
+ const root = plan.projectRoot;
398
+ switch (job.kind) {
399
+ case 'ios-png':
400
+ return _flattenPng(node_path_1.default.join(root, job.sourcePath), job.flattenOn, job.width, job.height);
401
+ case 'ios-contents':
402
+ return _iosContentsJson(job.variants);
403
+ case 'android-legacy': {
404
+ const foregroundAbs = node_path_1.default.join(root, job.sourcePath);
405
+ if (job.backgroundColor !== undefined) {
406
+ return _legacyCompositePng(foregroundAbs, job.size, job.round, {
407
+ color: job.backgroundColor,
408
+ });
409
+ }
410
+ if (job.backgroundImagePath !== undefined) {
411
+ return _legacyCompositePng(foregroundAbs, job.size, job.round, {
412
+ imageAbs: node_path_1.default.join(root, job.backgroundImagePath),
413
+ });
414
+ }
415
+ return _legacyPng(foregroundAbs, job.size, job.round);
416
+ }
417
+ case 'android-adaptive-foreground':
418
+ case 'android-adaptive-background-image':
419
+ return _resizePng(node_path_1.default.join(root, job.sourcePath), job.size);
420
+ case 'android-adaptive-xml': {
421
+ const base = job.isDefault
422
+ ? 'ic_launcher'
423
+ : `ic_launcher_${job.iconName}`;
424
+ const colorResource = job.isDefault
425
+ ? 'icon_switcher_default_background'
426
+ : `icon_switcher_${job.iconName}_background`;
427
+ return _adaptiveXml(base, job.backgroundIsColor, colorResource, job.hasMonochrome);
428
+ }
429
+ case 'android-colors-xml':
430
+ return _colorsXml(job.entries);
431
+ default: {
432
+ const _exhaustive = job;
433
+ return _exhaustive;
434
+ }
435
+ }
436
+ }
437
+ async function writeAssets(plan, opts) {
438
+ const written = [];
439
+ for (const asset of plan.assets) {
440
+ const isIos = asset.relativePath.includes('.appiconset');
441
+ const baseDir = isIos ? opts.iosAssetCatalog : opts.androidResDir;
442
+ const absolutePath = node_path_1.default.join(baseDir, asset.relativePath);
443
+ const payload = await _renderJob(plan, asset.job);
444
+ const sha256 = typeof payload === 'string'
445
+ ? await _writeText(absolutePath, payload)
446
+ : await _writeBuffer(absolutePath, payload);
447
+ written.push({
448
+ relativePath: asset.relativePath,
449
+ absolutePath,
450
+ sha256,
451
+ });
452
+ }
453
+ return written;
454
+ }
455
+ /** Test helper: corner pixel RGB after iOS flatten (alpha removed). */
456
+ async function _readCornerRgb(pngPath) {
457
+ var _a, _b, _c;
458
+ const { data } = await (0, sharp_1.default)(pngPath)
459
+ .extract({ left: 0, top: 0, width: 1, height: 1 })
460
+ .raw()
461
+ .toBuffer({ resolveWithObject: true });
462
+ return { r: (_a = data[0]) !== null && _a !== void 0 ? _a : 0, g: (_b = data[1]) !== null && _b !== void 0 ? _b : 0, b: (_c = data[2]) !== null && _c !== void 0 ? _c : 0 };
463
+ }
@@ -0,0 +1,4 @@
1
+ export declare class ConfigError extends Error {
2
+ readonly name = "ConfigError";
3
+ constructor(message: string);
4
+ }
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ConfigError = void 0;
4
+ class ConfigError extends Error {
5
+ constructor(message) {
6
+ super(message);
7
+ this.name = 'ConfigError';
8
+ Object.setPrototypeOf(this, new.target.prototype);
9
+ }
10
+ }
11
+ exports.ConfigError = ConfigError;
@@ -0,0 +1,6 @@
1
+ import type { IconSwitcherConfig, IconSource, ResolvedConfig } from '../types';
2
+ export interface ResolveConfigContext {
3
+ projectRoot: string;
4
+ expoDefault?: IconSource;
5
+ }
6
+ export declare function resolveConfig(cfg: IconSwitcherConfig, ctx: ResolveConfigContext): ResolvedConfig;