react-native-platform-components 1.5.0 → 1.6.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-platform-components",
3
- "version": "1.5.0",
3
+ "version": "1.6.0",
4
4
  "description": "Native UI components for React Native, the real platform widgets on both iOS and Android: TextField, DatePicker, ContextMenu, SelectionMenu, SegmentedControl, TabBar, NavigationRail, Button, ButtonGroup, FloatingActionButton, FloatingToolbar and LiquidGlass. UIKit on iOS, Material 3 Expressive on Android. Fabric, TypeScript, Expo config plugin.",
5
5
  "main": "./lib/commonjs/index.js",
6
6
  "module": "./lib/module/index.js",
@@ -1,8 +1,15 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  exports.MATERIAL3_THEME_PARENT = void 0;
4
7
  exports.resolveMaterial3Parent = resolveMaterial3Parent;
5
8
  exports.applyMaterial3Theme = applyMaterial3Theme;
9
+ exports.resolveDrawables = resolveDrawables;
10
+ exports.copyDrawables = copyDrawables;
11
+ const fs_1 = __importDefault(require("fs"));
12
+ const path_1 = __importDefault(require("path"));
6
13
  const config_plugins_1 = require("@expo/config-plugins");
7
14
  exports.MATERIAL3_THEME_PARENT = 'Theme.Material3.DayNight.NoActionBar';
8
15
  /**
@@ -42,6 +49,57 @@ function applyMaterial3Theme(xml) {
42
49
  xml.resources.style = styles;
43
50
  return xml;
44
51
  }
52
+ const PLUGIN_NAME = 'react-native-platform-components';
53
+ /** Android resource names: lowercase letters, digits and underscores. */
54
+ const DRAWABLE_NAME = /^[a-z][a-z0-9_]*$/;
55
+ /**
56
+ * Expands the `drawables` option into the files to copy, checking each name
57
+ * is a valid Android resource name and appears once.
58
+ */
59
+ function resolveDrawables(projectRoot, entries) {
60
+ const files = [];
61
+ for (const entry of entries) {
62
+ const source = path_1.default.resolve(projectRoot, entry);
63
+ if (!fs_1.default.existsSync(source)) {
64
+ throw new Error(`${PLUGIN_NAME}: drawable not found: ${entry}`);
65
+ }
66
+ let sources = [source];
67
+ if (fs_1.default.statSync(source).isDirectory()) {
68
+ sources = fs_1.default
69
+ .readdirSync(source)
70
+ .filter((file) => file.endsWith('.xml'))
71
+ .sort()
72
+ .map((file) => path_1.default.join(source, file));
73
+ if (sources.length === 0) {
74
+ throw new Error(`${PLUGIN_NAME}: no .xml drawables in ${entry}`);
75
+ }
76
+ }
77
+ for (const file of sources) {
78
+ if (path_1.default.extname(file) !== '.xml') {
79
+ throw new Error(`${PLUGIN_NAME}: ${entry} is not a vector drawable (.xml). ` +
80
+ 'Use an image icon for PNGs.');
81
+ }
82
+ const name = path_1.default.basename(file, '.xml');
83
+ if (!DRAWABLE_NAME.test(name)) {
84
+ throw new Error(`${PLUGIN_NAME}: "${name}" is not a valid drawable name. ` +
85
+ 'Use lowercase letters, digits and underscores, starting with a letter.');
86
+ }
87
+ if (files.some((existing) => existing.name === name)) {
88
+ throw new Error(`${PLUGIN_NAME}: more than one drawable named "${name}"`);
89
+ }
90
+ files.push({ name, source: file });
91
+ }
92
+ }
93
+ return files;
94
+ }
95
+ /** Copies the drawables into `<resDir>/drawable`, replacing earlier copies. */
96
+ function copyDrawables(files, resDir) {
97
+ const drawableDir = path_1.default.join(resDir, 'drawable');
98
+ fs_1.default.mkdirSync(drawableDir, { recursive: true });
99
+ for (const file of files) {
100
+ fs_1.default.copyFileSync(file.source, path_1.default.join(drawableDir, `${file.name}.xml`));
101
+ }
102
+ }
45
103
  /**
46
104
  * Expo config plugin for react-native-platform-components.
47
105
  *
@@ -53,15 +111,30 @@ function applyMaterial3Theme(xml) {
53
111
  * `material: 'system'` modes, but Material 3 widgets look best under a
54
112
  * Material 3 app theme. Pass `{ android: { theme: 'material3' } }` to have
55
113
  * prebuild re-parent `AppTheme` accordingly.
114
+ *
115
+ * It also copies the vector drawables listed in `android.drawables` into the
116
+ * generated project, since hand-added files there don't survive
117
+ * `expo prebuild --clean`.
56
118
  */
57
119
  const withPlatformComponents = (config, options) => {
58
120
  const theme = options?.android?.theme ?? 'appcompat';
59
- if (theme !== 'material3') {
60
- return config;
121
+ const drawables = options?.android?.drawables ?? [];
122
+ if (theme === 'material3') {
123
+ config = (0, config_plugins_1.withAndroidStyles)(config, (styleConfig) => {
124
+ styleConfig.modResults = applyMaterial3Theme(styleConfig.modResults);
125
+ return styleConfig;
126
+ });
127
+ }
128
+ if (drawables.length > 0) {
129
+ config = (0, config_plugins_1.withDangerousMod)(config, [
130
+ 'android',
131
+ (modConfig) => {
132
+ const { projectRoot, platformProjectRoot } = modConfig.modRequest;
133
+ copyDrawables(resolveDrawables(projectRoot, drawables), path_1.default.join(platformProjectRoot, 'app', 'src', 'main', 'res'));
134
+ return modConfig;
135
+ },
136
+ ]);
61
137
  }
62
- return (0, config_plugins_1.withAndroidStyles)(config, (styleConfig) => {
63
- styleConfig.modResults = applyMaterial3Theme(styleConfig.modResults);
64
- return styleConfig;
65
- });
138
+ return config;
66
139
  };
67
140
  exports.default = withPlatformComponents;
@@ -13,6 +13,13 @@ export type AndroidTheme = 'material3' | 'appcompat';
13
13
  export type PlatformComponentsPluginOptions = {
14
14
  android?: {
15
15
  theme?: AndroidTheme;
16
+ /**
17
+ * Vector drawables to copy into `res/drawable` at prebuild, so drawable
18
+ * icon names (`android: 'home'`) resolve in an Expo app. Each entry is a
19
+ * `.xml` file or a directory of them, relative to the project root. The
20
+ * drawable name is the file name without `.xml`.
21
+ */
22
+ drawables?: string[];
16
23
  };
17
24
  };
18
25
  export declare const MATERIAL3_THEME_PARENT = "Theme.Material3.DayNight.NoActionBar";
@@ -23,6 +30,19 @@ export declare function resolveMaterial3Parent(currentParent: string | undefined
23
30
  * Idempotent: running prebuild again leaves the result unchanged.
24
31
  */
25
32
  export declare function applyMaterial3Theme(xml: ResourceXML): ResourceXML;
33
+ export type DrawableFile = {
34
+ /** Resource name: the file name without `.xml`. */
35
+ name: string;
36
+ /** Absolute path of the source file. */
37
+ source: string;
38
+ };
39
+ /**
40
+ * Expands the `drawables` option into the files to copy, checking each name
41
+ * is a valid Android resource name and appears once.
42
+ */
43
+ export declare function resolveDrawables(projectRoot: string, entries: string[]): DrawableFile[];
44
+ /** Copies the drawables into `<resDir>/drawable`, replacing earlier copies. */
45
+ export declare function copyDrawables(files: DrawableFile[], resDir: string): void;
26
46
  /**
27
47
  * Expo config plugin for react-native-platform-components.
28
48
  *
@@ -34,6 +54,10 @@ export declare function applyMaterial3Theme(xml: ResourceXML): ResourceXML;
34
54
  * `material: 'system'` modes, but Material 3 widgets look best under a
35
55
  * Material 3 app theme. Pass `{ android: { theme: 'material3' } }` to have
36
56
  * prebuild re-parent `AppTheme` accordingly.
57
+ *
58
+ * It also copies the vector drawables listed in `android.drawables` into the
59
+ * generated project, since hand-added files there don't survive
60
+ * `expo prebuild --clean`.
37
61
  */
38
62
  declare const withPlatformComponents: ConfigPlugin<PlatformComponentsPluginOptions | void>;
39
63
  export default withPlatformComponents;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,aAAa,EAClB,KAAK,YAAY,EAClB,MAAM,sBAAsB,CAAC;AAE9B,KAAK,WAAW,GAAG,aAAa,CAAC,SAAS,CAAC,WAAW,CAAC;AAEvD;;;;;;;;GAQG;AACH,MAAM,MAAM,YAAY,GAAG,WAAW,GAAG,WAAW,CAAC;AAErD,MAAM,MAAM,+BAA+B,GAAG;IAC5C,OAAO,CAAC,EAAE;QACR,KAAK,CAAC,EAAE,YAAY,CAAC;KACtB,CAAC;CACH,CAAC;AAEF,eAAO,MAAM,sBAAsB,yCAAyC,CAAC;AAW7E,wBAAgB,sBAAsB,CACpC,aAAa,EAAE,MAAM,GAAG,SAAS,GAChC,MAAM,CASR;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,WAAW,GAAG,WAAW,CAejE;AAED;;;;;;;;;;;GAWG;AACH,QAAA,MAAM,sBAAsB,EAAE,YAAY,CACxC,+BAA+B,GAAG,IAAI,CAWvC,CAAC;AAEF,eAAe,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAGL,KAAK,aAAa,EAClB,KAAK,YAAY,EAClB,MAAM,sBAAsB,CAAC;AAE9B,KAAK,WAAW,GAAG,aAAa,CAAC,SAAS,CAAC,WAAW,CAAC;AAEvD;;;;;;;;GAQG;AACH,MAAM,MAAM,YAAY,GAAG,WAAW,GAAG,WAAW,CAAC;AAErD,MAAM,MAAM,+BAA+B,GAAG;IAC5C,OAAO,CAAC,EAAE;QACR,KAAK,CAAC,EAAE,YAAY,CAAC;QACrB;;;;;WAKG;QACH,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;KACtB,CAAC;CACH,CAAC;AAEF,eAAO,MAAM,sBAAsB,yCAAyC,CAAC;AAW7E,wBAAgB,sBAAsB,CACpC,aAAa,EAAE,MAAM,GAAG,SAAS,GAChC,MAAM,CASR;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,WAAW,GAAG,WAAW,CAejE;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,mDAAmD;IACnD,IAAI,EAAE,MAAM,CAAC;IACb,wCAAwC;IACxC,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAOF;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,EAAE,GAChB,YAAY,EAAE,CAyChB;AAED,+EAA+E;AAC/E,wBAAgB,aAAa,CAAC,KAAK,EAAE,YAAY,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAMzE;AAED;;;;;;;;;;;;;;;GAeG;AACH,QAAA,MAAM,sBAAsB,EAAE,YAAY,CACxC,+BAA+B,GAAG,IAAI,CA2BvC,CAAC;AAEF,eAAe,sBAAsB,CAAC"}
@@ -9,7 +9,8 @@
9
9
  "declaration": true,
10
10
  "declarationMap": true,
11
11
  "outDir": "build",
12
- "rootDir": "src"
12
+ "rootDir": "src",
13
+ "types": ["node"]
13
14
  },
14
15
  "include": [
15
16
  "src/**/*"