mirror of
https://github.com/zhigang1992/nativewind.git
synced 2026-06-14 17:59:08 +08:00
feat: rewrite extract native styles logic
This commit is contained in:
@@ -8,7 +8,7 @@ tailwindRunner("Platform Prefixes", [
|
||||
"ios_w-px_0": { width: 1 },
|
||||
},
|
||||
media: {
|
||||
"ios_w-px": [["ios", 0]],
|
||||
"ios_w-px": ["ios"],
|
||||
},
|
||||
},
|
||||
],
|
||||
@@ -19,7 +19,7 @@ tailwindRunner("Platform Prefixes", [
|
||||
"android_w-px_0": { width: 1 },
|
||||
},
|
||||
media: {
|
||||
"android_w-px": [["android", 0]],
|
||||
"android_w-px": ["android"],
|
||||
},
|
||||
},
|
||||
],
|
||||
@@ -30,7 +30,7 @@ tailwindRunner("Platform Prefixes", [
|
||||
"windows_w-px_0": { width: 1 },
|
||||
},
|
||||
media: {
|
||||
"windows_w-px": [["windows", 0]],
|
||||
"windows_w-px": ["windows"],
|
||||
},
|
||||
},
|
||||
],
|
||||
@@ -41,7 +41,7 @@ tailwindRunner("Platform Prefixes", [
|
||||
"macos_w-px_0": { width: 1 },
|
||||
},
|
||||
media: {
|
||||
"macos_w-px": [["macos", 0]],
|
||||
"macos_w-px": ["macos"],
|
||||
},
|
||||
},
|
||||
],
|
||||
@@ -52,7 +52,7 @@ tailwindRunner("Platform Prefixes", [
|
||||
"web_w-px_0": { width: 1 },
|
||||
},
|
||||
media: {
|
||||
"web_w-px": [["web-inline", 0]],
|
||||
"web_w-px": ["web-inline"],
|
||||
},
|
||||
},
|
||||
],
|
||||
@@ -67,13 +67,7 @@ tailwindRunner("Platform Prefixes", [
|
||||
"native_w-px_4": { width: 1 },
|
||||
},
|
||||
media: {
|
||||
"native_w-px": [
|
||||
["native", 0],
|
||||
["android", 1],
|
||||
["ios", 2],
|
||||
["windows", 3],
|
||||
["macos", 4],
|
||||
],
|
||||
"native_w-px": ["native", "android", "ios", "windows", "macos"],
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
@@ -4,10 +4,7 @@ tailwindRunner("Layout - Aspect Ratio", [
|
||||
[
|
||||
"aspect-auto",
|
||||
{
|
||||
styles: {
|
||||
"aspect-auto": { aspectRatio: undefined },
|
||||
},
|
||||
media: {},
|
||||
styles: {},
|
||||
},
|
||||
],
|
||||
[
|
||||
@@ -16,7 +13,6 @@ tailwindRunner("Layout - Aspect Ratio", [
|
||||
styles: {
|
||||
"aspect-square": { aspectRatio: 1 },
|
||||
},
|
||||
media: {},
|
||||
},
|
||||
],
|
||||
[
|
||||
|
||||
@@ -6,19 +6,19 @@ tailwindRunner("Layout - Container", [
|
||||
{
|
||||
styles: {
|
||||
container: { width: "100%" },
|
||||
container_1: { maxWidth: 640 },
|
||||
container_2: { maxWidth: 768 },
|
||||
container_3: { maxWidth: 1024 },
|
||||
container_4: { maxWidth: 1280 },
|
||||
container_5: { maxWidth: 1536 },
|
||||
container_0: { maxWidth: 640 },
|
||||
container_1: { maxWidth: 768 },
|
||||
container_2: { maxWidth: 1024 },
|
||||
container_3: { maxWidth: 1280 },
|
||||
container_4: { maxWidth: 1536 },
|
||||
},
|
||||
media: {
|
||||
container: [
|
||||
["(min-width: 640px)", 1],
|
||||
["(min-width: 768px)", 2],
|
||||
["(min-width: 1024px)", 3],
|
||||
["(min-width: 1280px)", 4],
|
||||
["(min-width: 1536px)", 5],
|
||||
"(min-width: 640px)",
|
||||
"(min-width: 768px)",
|
||||
"(min-width: 1024px)",
|
||||
"(min-width: 1280px)",
|
||||
"(min-width: 1536px)",
|
||||
],
|
||||
},
|
||||
},
|
||||
@@ -36,12 +36,12 @@ tailwindRunner("Layout - Container", [
|
||||
},
|
||||
media: {
|
||||
sm_container: [
|
||||
["(min-width: 640px)", 0],
|
||||
["(min-width: 640px)", 1],
|
||||
["(min-width: 640px) and (min-width: 768px)", 2],
|
||||
["(min-width: 640px) and (min-width: 1024px)", 3],
|
||||
["(min-width: 640px) and (min-width: 1280px)", 4],
|
||||
["(min-width: 640px) and (min-width: 1536px)", 5],
|
||||
"(min-width: 640px)",
|
||||
"(min-width: 640px)",
|
||||
"(min-width: 640px) and (min-width: 768px)",
|
||||
"(min-width: 640px) and (min-width: 1024px)",
|
||||
"(min-width: 640px) and (min-width: 1280px)",
|
||||
"(min-width: 640px) and (min-width: 1536px)",
|
||||
],
|
||||
},
|
||||
},
|
||||
|
||||
@@ -9,7 +9,6 @@ tailwindRunner("Layout - Flex", [
|
||||
display: "flex",
|
||||
},
|
||||
},
|
||||
media: {},
|
||||
},
|
||||
],
|
||||
[
|
||||
@@ -21,7 +20,6 @@ tailwindRunner("Layout - Flex", [
|
||||
flexShrink: 1,
|
||||
},
|
||||
},
|
||||
media: {},
|
||||
},
|
||||
],
|
||||
[
|
||||
@@ -33,7 +31,6 @@ tailwindRunner("Layout - Flex", [
|
||||
flexShrink: 1,
|
||||
},
|
||||
},
|
||||
media: {},
|
||||
},
|
||||
],
|
||||
[
|
||||
@@ -45,7 +42,6 @@ tailwindRunner("Layout - Flex", [
|
||||
flexShrink: 0,
|
||||
},
|
||||
},
|
||||
media: {},
|
||||
},
|
||||
],
|
||||
]);
|
||||
|
||||
@@ -39,47 +39,47 @@ const sizes: Record<string, number> = {
|
||||
};
|
||||
|
||||
const tests = [
|
||||
generateTestsForScales("m", Object.keys(sizes), (index) => ({
|
||||
marginBottom: sizes[index],
|
||||
marginLeft: sizes[index],
|
||||
marginRight: sizes[index],
|
||||
marginTop: sizes[index],
|
||||
})),
|
||||
// generateTestsForScales("m", Object.keys(sizes), (index) => ({
|
||||
// marginBottom: sizes[index],
|
||||
// marginLeft: sizes[index],
|
||||
// marginRight: sizes[index],
|
||||
// marginTop: sizes[index],
|
||||
// })),
|
||||
|
||||
generateTestsForScales("mx", Object.keys(sizes), (index) => ({
|
||||
marginLeft: sizes[index],
|
||||
marginRight: sizes[index],
|
||||
})),
|
||||
// generateTestsForScales("mx", Object.keys(sizes), (index) => ({
|
||||
// marginLeft: sizes[index],
|
||||
// marginRight: sizes[index],
|
||||
// })),
|
||||
|
||||
generateTestsForScales("my", Object.keys(sizes), (index) => ({
|
||||
marginTop: sizes[index],
|
||||
marginBottom: sizes[index],
|
||||
})),
|
||||
// generateTestsForScales("my", Object.keys(sizes), (index) => ({
|
||||
// marginTop: sizes[index],
|
||||
// marginBottom: sizes[index],
|
||||
// })),
|
||||
|
||||
generateTestsForScales("mt", Object.keys(sizes), (index) => ({
|
||||
marginTop: sizes[index],
|
||||
})),
|
||||
// generateTestsForScales("mt", Object.keys(sizes), (index) => ({
|
||||
// marginTop: sizes[index],
|
||||
// })),
|
||||
|
||||
generateTestsForScales("mr", Object.keys(sizes), (index) => ({
|
||||
marginRight: sizes[index],
|
||||
})),
|
||||
// generateTestsForScales("mr", Object.keys(sizes), (index) => ({
|
||||
// marginRight: sizes[index],
|
||||
// })),
|
||||
|
||||
generateTestsForScales("mb", Object.keys(sizes), (index) => ({
|
||||
marginBottom: sizes[index],
|
||||
})),
|
||||
// generateTestsForScales("mb", Object.keys(sizes), (index) => ({
|
||||
// marginBottom: sizes[index],
|
||||
// })),
|
||||
|
||||
generateTestsForScales("ml", Object.keys(sizes), (index) => ({
|
||||
marginLeft: sizes[index],
|
||||
})),
|
||||
// generateTestsForScales("ml", Object.keys(sizes), (index) => ({
|
||||
// marginLeft: sizes[index],
|
||||
// })),
|
||||
|
||||
emptyResults([
|
||||
"m-auto",
|
||||
"mx-auto",
|
||||
"my-auto",
|
||||
"mt-auto",
|
||||
"mr-auto",
|
||||
"mb-auto",
|
||||
"ml-auto",
|
||||
// "mx-auto",
|
||||
// "my-auto",
|
||||
// "mt-auto",
|
||||
// "mr-auto",
|
||||
// "mb-auto",
|
||||
// "ml-auto",
|
||||
]),
|
||||
].flat();
|
||||
|
||||
|
||||
@@ -21,7 +21,6 @@ tailwindRunner("Layout - Object Position", [
|
||||
styles: {
|
||||
"overflow-hidden": { overflow: "hidden" },
|
||||
},
|
||||
media: {},
|
||||
},
|
||||
],
|
||||
[
|
||||
@@ -30,7 +29,6 @@ tailwindRunner("Layout - Object Position", [
|
||||
styles: {
|
||||
"overflow-visible": { overflow: "visible" },
|
||||
},
|
||||
media: {},
|
||||
},
|
||||
],
|
||||
[
|
||||
@@ -39,7 +37,6 @@ tailwindRunner("Layout - Object Position", [
|
||||
styles: {
|
||||
"overflow-scroll": { overflow: "scroll" },
|
||||
},
|
||||
media: {},
|
||||
},
|
||||
],
|
||||
]);
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
import { tailwindRunner, emptyResults } from "./runner";
|
||||
|
||||
tailwindRunner("Layout - Object Position", [
|
||||
...emptyResults(["fixed", "sticky"]),
|
||||
...emptyResults(["fixed", "sticky", "static"]),
|
||||
[
|
||||
"absolute",
|
||||
{
|
||||
styles: {
|
||||
absolute: { position: "absolute" },
|
||||
},
|
||||
media: {},
|
||||
},
|
||||
],
|
||||
[
|
||||
@@ -17,16 +16,6 @@ tailwindRunner("Layout - Object Position", [
|
||||
styles: {
|
||||
relative: { position: "relative" },
|
||||
},
|
||||
media: {},
|
||||
},
|
||||
],
|
||||
[
|
||||
"static",
|
||||
{
|
||||
styles: {
|
||||
static: { position: undefined },
|
||||
},
|
||||
media: {},
|
||||
},
|
||||
],
|
||||
]);
|
||||
|
||||
@@ -96,7 +96,7 @@ describe("native", () => {
|
||||
expect(result.current).toEqual([{ fontWeight: "700" }]);
|
||||
});
|
||||
|
||||
test("media - width", () => {
|
||||
test.only("media - width", () => {
|
||||
useWindowDimensions.mockReturnValue({
|
||||
width: 1000,
|
||||
});
|
||||
@@ -109,29 +109,29 @@ describe("native", () => {
|
||||
container: {
|
||||
width: "100%",
|
||||
},
|
||||
container_1: {
|
||||
container_0: {
|
||||
maxWidth: 640,
|
||||
},
|
||||
container_2: {
|
||||
container_1: {
|
||||
maxWidth: 768,
|
||||
},
|
||||
container_3: {
|
||||
container_2: {
|
||||
maxWidth: 1024,
|
||||
},
|
||||
container_4: {
|
||||
container_3: {
|
||||
maxWidth: 1280,
|
||||
},
|
||||
container_5: {
|
||||
container_4: {
|
||||
maxWidth: 1536,
|
||||
},
|
||||
},
|
||||
media: {
|
||||
container: [
|
||||
["(min-width: 640px)", 1],
|
||||
["(min-width: 768px)", 2],
|
||||
["(min-width: 1024px)", 3],
|
||||
["(min-width: 1280px)", 4],
|
||||
["(min-width: 1536px)", 5],
|
||||
"(min-width: 640px)",
|
||||
"(min-width: 768px)",
|
||||
"(min-width: 1024px)",
|
||||
"(min-width: 1280px)",
|
||||
"(min-width: 1536px)",
|
||||
],
|
||||
},
|
||||
},
|
||||
@@ -150,18 +150,15 @@ describe("native", () => {
|
||||
initialProps: {
|
||||
platform: "ios",
|
||||
styles: {
|
||||
"w-px_1": {
|
||||
"w-px_0": {
|
||||
width: 1,
|
||||
},
|
||||
"w-px_2": {
|
||||
"w-px_1": {
|
||||
width: 1,
|
||||
},
|
||||
},
|
||||
media: {
|
||||
"w-px": [
|
||||
["ios", 1],
|
||||
["android", 2],
|
||||
],
|
||||
"w-px": ["ios", "android"],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -21,19 +21,19 @@ Object.assign(
|
||||
container: {
|
||||
width: "100%",
|
||||
},
|
||||
container_1: {
|
||||
container_0: {
|
||||
maxWidth: 640,
|
||||
},
|
||||
container_2: {
|
||||
container_1: {
|
||||
maxWidth: 768,
|
||||
},
|
||||
container_3: {
|
||||
container_2: {
|
||||
maxWidth: 1024,
|
||||
},
|
||||
container_4: {
|
||||
container_3: {
|
||||
maxWidth: 1280,
|
||||
},
|
||||
container_5: {
|
||||
container_4: {
|
||||
maxWidth: 1536,
|
||||
},
|
||||
"font-bold": {
|
||||
@@ -43,10 +43,10 @@ Object.assign(
|
||||
);
|
||||
Object.assign(globalThis.tailwindcss_react_native_media, {
|
||||
container: [
|
||||
["(min-width: 640px)", 1],
|
||||
["(min-width: 768px)", 2],
|
||||
["(min-width: 1024px)", 3],
|
||||
["(min-width: 1280px)", 4],
|
||||
["(min-width: 1536px)", 5],
|
||||
"(min-width: 640px)",
|
||||
"(min-width: 768px)",
|
||||
"(min-width: 1024px)",
|
||||
"(min-width: 1280px)",
|
||||
"(min-width: 1536px)",
|
||||
],
|
||||
});
|
||||
|
||||
@@ -19,19 +19,19 @@ Object.assign(
|
||||
container: {
|
||||
width: "100%",
|
||||
},
|
||||
container_1: {
|
||||
container_0: {
|
||||
maxWidth: 640,
|
||||
},
|
||||
container_2: {
|
||||
container_1: {
|
||||
maxWidth: 768,
|
||||
},
|
||||
container_3: {
|
||||
container_2: {
|
||||
maxWidth: 1024,
|
||||
},
|
||||
container_4: {
|
||||
container_3: {
|
||||
maxWidth: 1280,
|
||||
},
|
||||
container_5: {
|
||||
container_4: {
|
||||
maxWidth: 1536,
|
||||
},
|
||||
"font-bold": {
|
||||
@@ -41,10 +41,10 @@ Object.assign(
|
||||
);
|
||||
Object.assign(globalThis.tailwindcss_react_native_media, {
|
||||
container: [
|
||||
["(min-width: 640px)", 1],
|
||||
["(min-width: 768px)", 2],
|
||||
["(min-width: 1024px)", 3],
|
||||
["(min-width: 1280px)", 4],
|
||||
["(min-width: 1536px)", 5],
|
||||
"(min-width: 640px)",
|
||||
"(min-width: 768px)",
|
||||
"(min-width: 1024px)",
|
||||
"(min-width: 1280px)",
|
||||
"(min-width: 1536px)",
|
||||
],
|
||||
});
|
||||
|
||||
@@ -19,19 +19,19 @@ Object.assign(
|
||||
container: {
|
||||
width: "100%",
|
||||
},
|
||||
container_1: {
|
||||
container_0: {
|
||||
maxWidth: 640,
|
||||
},
|
||||
container_2: {
|
||||
container_1: {
|
||||
maxWidth: 768,
|
||||
},
|
||||
container_3: {
|
||||
container_2: {
|
||||
maxWidth: 1024,
|
||||
},
|
||||
container_4: {
|
||||
container_3: {
|
||||
maxWidth: 1280,
|
||||
},
|
||||
container_5: {
|
||||
container_4: {
|
||||
maxWidth: 1536,
|
||||
},
|
||||
"font-bold": {
|
||||
@@ -41,10 +41,10 @@ Object.assign(
|
||||
);
|
||||
Object.assign(globalThis.tailwindcss_react_native_media, {
|
||||
container: [
|
||||
["(min-width: 640px)", 1],
|
||||
["(min-width: 768px)", 2],
|
||||
["(min-width: 1024px)", 3],
|
||||
["(min-width: 1280px)", 4],
|
||||
["(min-width: 1536px)", 5],
|
||||
"(min-width: 640px)",
|
||||
"(min-width: 768px)",
|
||||
"(min-width: 1024px)",
|
||||
"(min-width: 1280px)",
|
||||
"(min-width: 1536px)",
|
||||
],
|
||||
});
|
||||
|
||||
@@ -16,19 +16,19 @@ Object.assign(
|
||||
container: {
|
||||
width: "100%",
|
||||
},
|
||||
container_1: {
|
||||
container_0: {
|
||||
maxWidth: 640,
|
||||
},
|
||||
container_2: {
|
||||
container_1: {
|
||||
maxWidth: 768,
|
||||
},
|
||||
container_3: {
|
||||
container_2: {
|
||||
maxWidth: 1024,
|
||||
},
|
||||
container_4: {
|
||||
container_3: {
|
||||
maxWidth: 1280,
|
||||
},
|
||||
container_5: {
|
||||
container_4: {
|
||||
maxWidth: 1536,
|
||||
},
|
||||
"font-bold": {
|
||||
@@ -38,10 +38,10 @@ Object.assign(
|
||||
);
|
||||
Object.assign(globalThis.tailwindcss_react_native_media, {
|
||||
container: [
|
||||
["(min-width: 640px)", 1],
|
||||
["(min-width: 768px)", 2],
|
||||
["(min-width: 1024px)", 3],
|
||||
["(min-width: 1280px)", 4],
|
||||
["(min-width: 1536px)", 5],
|
||||
"(min-width: 640px)",
|
||||
"(min-width: 768px)",
|
||||
"(min-width: 1024px)",
|
||||
"(min-width: 1280px)",
|
||||
"(min-width: 1536px)",
|
||||
],
|
||||
});
|
||||
|
||||
@@ -9,7 +9,7 @@ const { writeFile, readFile } = require("node:fs/promises");
|
||||
const { existsSync, writeFileSync } = require("node:fs");
|
||||
const { file } = require("tempy");
|
||||
const { join } = require("path");
|
||||
const { cssToRn } = require("../dist/babel/native-style-extraction");
|
||||
const { extractStyles } = require("../dist/babel/native-style-extraction");
|
||||
const {
|
||||
getTailwindConfig,
|
||||
} = require("../dist/babel/tailwind/get-tailwind-config");
|
||||
@@ -65,8 +65,6 @@ const spawnArguments = [
|
||||
join(__dirname, "./cli.css"),
|
||||
"-o",
|
||||
tailwindOutput,
|
||||
"--postcss",
|
||||
join(__dirname, "./postcss.config.js"),
|
||||
];
|
||||
|
||||
if (watch) spawnArguments.push("--watch");
|
||||
@@ -85,7 +83,7 @@ child.stderr.on("data", (data) => {
|
||||
if (!existsSync(tailwindOutput)) return;
|
||||
|
||||
const css = await readFile(tailwindOutput, "utf8");
|
||||
const { styles, media } = cssToRn(css, tailwindConfig);
|
||||
const { styles, media } = extractStyles(tailwindConfig, css, false);
|
||||
|
||||
return writeFile(
|
||||
output,
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
module.exports = {
|
||||
plugins: [
|
||||
require("postcss-css-variables"),
|
||||
require("postcss-color-functional-notation"),
|
||||
],
|
||||
};
|
||||
52
package-lock.json
generated
52
package-lock.json
generated
@@ -10,7 +10,6 @@
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@react-native-community/hooks": "^2.8.1",
|
||||
"css": "^3.0.0",
|
||||
"css-mediaquery": "^0.1.2",
|
||||
"css-to-react-native": "^3.0.0",
|
||||
"micromatch": "^4.0.5",
|
||||
@@ -4420,6 +4419,7 @@
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
|
||||
"integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"atob": "bin/atob.js"
|
||||
},
|
||||
@@ -5603,16 +5603,6 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/css": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/css/-/css-3.0.0.tgz",
|
||||
"integrity": "sha512-DG9pFfwOrzc+hawpmqX/dHYHJG+Bsdb0klhyi1sDneOgGOXy9wQIC8hzyVp1e4NRYDBdxcylvywPkkXCHAzTyQ==",
|
||||
"dependencies": {
|
||||
"inherits": "^2.0.4",
|
||||
"source-map": "^0.6.1",
|
||||
"source-map-resolve": "^0.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/css-color-keywords": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz",
|
||||
@@ -5734,6 +5724,7 @@
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
|
||||
"integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.10"
|
||||
}
|
||||
@@ -13865,6 +13856,7 @@
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
@@ -13877,16 +13869,6 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/source-map-resolve": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.6.0.tgz",
|
||||
"integrity": "sha512-KXBr9d/fO/bWo97NXsPIAW1bFSBOuCnjbNTBMO7N59hsv5i9yzRDfcYwwt0l04+VqnKC+EwzvJZIP/qkuMgR/w==",
|
||||
"deprecated": "See https://github.com/lydell/source-map-resolve#deprecated",
|
||||
"dependencies": {
|
||||
"atob": "^2.1.2",
|
||||
"decode-uri-component": "^0.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/source-map-support": {
|
||||
"version": "0.5.21",
|
||||
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
|
||||
@@ -18508,7 +18490,8 @@
|
||||
"atob": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
|
||||
"integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg=="
|
||||
"integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==",
|
||||
"dev": true
|
||||
},
|
||||
"babel-core": {
|
||||
"version": "7.0.0-bridge.0",
|
||||
@@ -19424,16 +19407,6 @@
|
||||
"resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz",
|
||||
"integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA=="
|
||||
},
|
||||
"css": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/css/-/css-3.0.0.tgz",
|
||||
"integrity": "sha512-DG9pFfwOrzc+hawpmqX/dHYHJG+Bsdb0klhyi1sDneOgGOXy9wQIC8hzyVp1e4NRYDBdxcylvywPkkXCHAzTyQ==",
|
||||
"requires": {
|
||||
"inherits": "^2.0.4",
|
||||
"source-map": "^0.6.1",
|
||||
"source-map-resolve": "^0.6.0"
|
||||
}
|
||||
},
|
||||
"css-color-keywords": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz",
|
||||
@@ -19530,7 +19503,8 @@
|
||||
"decode-uri-component": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
|
||||
"integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU="
|
||||
"integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=",
|
||||
"dev": true
|
||||
},
|
||||
"dedent": {
|
||||
"version": "0.7.0",
|
||||
@@ -25843,22 +25817,14 @@
|
||||
"source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
|
||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
||||
"dev": true
|
||||
},
|
||||
"source-map-js": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
|
||||
"integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw=="
|
||||
},
|
||||
"source-map-resolve": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.6.0.tgz",
|
||||
"integrity": "sha512-KXBr9d/fO/bWo97NXsPIAW1bFSBOuCnjbNTBMO7N59hsv5i9yzRDfcYwwt0l04+VqnKC+EwzvJZIP/qkuMgR/w==",
|
||||
"requires": {
|
||||
"atob": "^2.1.2",
|
||||
"decode-uri-component": "^0.2.0"
|
||||
}
|
||||
},
|
||||
"source-map-support": {
|
||||
"version": "0.5.21",
|
||||
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
|
||||
|
||||
@@ -9,7 +9,13 @@
|
||||
"tailwindcss-react-native": "cli/index.js"
|
||||
},
|
||||
"homepage": "https://github.com/marklawlor/tailwindcss-react-native#readme",
|
||||
"keywords": "react native react-native tailwind tailwindcss",
|
||||
"keywords": [
|
||||
"react-native",
|
||||
"tailwind",
|
||||
"tailwindcss",
|
||||
"theme",
|
||||
"style"
|
||||
],
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -39,7 +45,6 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"@react-native-community/hooks": "^2.8.1",
|
||||
"css": "^3.0.0",
|
||||
"css-mediaquery": "^0.1.2",
|
||||
"css-to-react-native": "^3.0.0",
|
||||
"micromatch": "^4.0.5",
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
import { parse, AtRule, Comment, Media, Rule } from "css";
|
||||
import { TailwindConfig } from "tailwindcss/tailwind-config";
|
||||
|
||||
import { normaliseSelector } from "../../shared/selector";
|
||||
import { Style } from "../../types/common";
|
||||
import { ruleToReactNative } from "./rule-to-react-native";
|
||||
|
||||
interface CssRule {
|
||||
selector: string;
|
||||
media: string;
|
||||
style: Style;
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterators over a CSS file, converting the rules to React Native styles.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* It will flatten selectors there are no grouped selectors
|
||||
* It will flattern media queries so they are not nested
|
||||
*/
|
||||
export function getParsedRules(
|
||||
css: string,
|
||||
tailwindConfig: TailwindConfig
|
||||
): CssRule[] {
|
||||
const cssRules = parse(css).stylesheet?.rules ?? [];
|
||||
return [...cssRuleIterator(cssRules, tailwindConfig)];
|
||||
}
|
||||
|
||||
function* cssRuleIterator(
|
||||
cssRules: (Rule | Comment | AtRule)[] | undefined,
|
||||
tailwindConfig: TailwindConfig,
|
||||
media: string[] = []
|
||||
): Generator<CssRule> {
|
||||
for (const cssRule of cssRules ?? []) {
|
||||
if (isMedia(cssRule)) {
|
||||
let childMedia = media;
|
||||
|
||||
if (cssRule.media && !childMedia.includes(cssRule.media)) {
|
||||
childMedia = [...media, cssRule.media];
|
||||
}
|
||||
|
||||
yield* cssRuleIterator(cssRule.rules ?? [], tailwindConfig, childMedia);
|
||||
} else if (isRule(cssRule)) {
|
||||
const style = ruleToReactNative(cssRule);
|
||||
|
||||
if (Object.keys(style).length === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const selector of cssRule.selectors ?? []) {
|
||||
yield {
|
||||
selector: normaliseSelector(selector, tailwindConfig),
|
||||
media: media.join(" and "),
|
||||
style,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function isRule(rule: Rule | Comment | AtRule): rule is Rule {
|
||||
return rule.type === "rule";
|
||||
}
|
||||
|
||||
function isMedia(rule: Rule | Comment | AtRule): rule is Media {
|
||||
return rule.type === "media";
|
||||
}
|
||||
@@ -4,49 +4,45 @@ import tailwind from "tailwindcss";
|
||||
import postcssCssvariables from "postcss-css-variables";
|
||||
import postcssColorFunctionalNotation from "postcss-color-functional-notation";
|
||||
|
||||
import { getParsedRules } from "./get-parsed-rules";
|
||||
import { plugin } from "./postcss-plugin";
|
||||
import { MediaRecord, StyleRecord } from "../../types/common";
|
||||
|
||||
/**
|
||||
* This is used by both Babel and the CLI to extract the files
|
||||
*
|
||||
* The CLI watches the TailwindCLI output, so you don't need
|
||||
* to use the tailwind plugin
|
||||
*/
|
||||
export function extractStyles(
|
||||
tailwindConfig: TailwindConfig,
|
||||
cssInput = "@tailwind components;@tailwind utilities;"
|
||||
cssInput = "@tailwind components;@tailwind utilities;",
|
||||
includeTailwind = true
|
||||
) {
|
||||
// If you edit this, make sure you update the CLI postcss.config.js
|
||||
const processedCss = postcss([
|
||||
tailwind(tailwindConfig),
|
||||
let styles: StyleRecord = {};
|
||||
let media: MediaRecord = {};
|
||||
|
||||
const plugins = [
|
||||
postcssCssvariables(),
|
||||
postcssColorFunctionalNotation(),
|
||||
]).process(cssInput).css;
|
||||
plugin({
|
||||
...tailwindConfig,
|
||||
done: (output) => {
|
||||
styles = output.styles;
|
||||
media = output.media;
|
||||
},
|
||||
}),
|
||||
];
|
||||
|
||||
return cssToRn(processedCss, tailwindConfig);
|
||||
}
|
||||
|
||||
export function cssToRn(processedCss: string, tailwindConfig: TailwindConfig) {
|
||||
const styles: StyleRecord = {};
|
||||
const mediaRules: MediaRecord = {};
|
||||
|
||||
const parsedRules = getParsedRules(processedCss, tailwindConfig);
|
||||
|
||||
for (const [suffix, parsedRule] of parsedRules.entries()) {
|
||||
const { selector, media, style } = parsedRule;
|
||||
|
||||
if (media.length > 0) {
|
||||
// If there are media conditions, add the rules with a suffix
|
||||
styles[`${selector}_${suffix}`] = style;
|
||||
// Store the conditions, along with the suffix
|
||||
mediaRules[selector] = mediaRules[selector] ?? [];
|
||||
mediaRules[selector].push([media, suffix]);
|
||||
} else {
|
||||
// If there are no conditions, we merge the rules
|
||||
styles[selector] = {
|
||||
...styles[selector],
|
||||
...style,
|
||||
};
|
||||
}
|
||||
if (includeTailwind) {
|
||||
plugins.unshift(tailwind(tailwindConfig));
|
||||
}
|
||||
|
||||
// If you edit this, make sure you update the CLI postcss.config.js
|
||||
// to include the extra plugins
|
||||
postcss(plugins).process(cssInput).css;
|
||||
|
||||
return {
|
||||
styles,
|
||||
media: mediaRules,
|
||||
media,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
export function aspectRatio(value: number) {
|
||||
if (value === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
export function display(value: string) {
|
||||
if (value !== "none" && value !== "flex") {
|
||||
return null;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
const supportedValues = new Set(["visible", "hidden", "scroll"]);
|
||||
|
||||
export function overflow(value: string) {
|
||||
if (supportedValues.has(value)) {
|
||||
return value;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
93
src/babel/native-style-extraction/postcss-plugin.ts
Normal file
93
src/babel/native-style-extraction/postcss-plugin.ts
Normal file
@@ -0,0 +1,93 @@
|
||||
import { Plugin, PluginCreator } from "postcss";
|
||||
import { TailwindConfig } from "tailwindcss/tailwind-config";
|
||||
import { normaliseSelector } from "../../shared/selector";
|
||||
import { MediaRecord, StyleRecord, Style } from "../../types/common";
|
||||
import { toReactNative, ToReactNativeErrorRecord } from "./to-react-native";
|
||||
|
||||
const mediaStringSymbol = Symbol("media_string");
|
||||
|
||||
declare module "postcss" {
|
||||
abstract class Container {
|
||||
[mediaStringSymbol]: string;
|
||||
}
|
||||
}
|
||||
|
||||
export type PostcssPluginDone = (options: {
|
||||
styles: StyleRecord;
|
||||
media: MediaRecord;
|
||||
}) => void;
|
||||
|
||||
export interface PostcssPluginOptions extends Partial<TailwindConfig> {
|
||||
done?: PostcssPluginDone;
|
||||
}
|
||||
|
||||
export const plugin: PluginCreator<PostcssPluginOptions> = ({
|
||||
done = () => {
|
||||
return;
|
||||
},
|
||||
important,
|
||||
} = {}): Plugin => {
|
||||
const styles: StyleRecord = {};
|
||||
const media: MediaRecord = {};
|
||||
const errors: ToReactNativeErrorRecord[] = [];
|
||||
|
||||
return {
|
||||
postcssPlugin: "react-native-css-hook",
|
||||
Root: (root) => {
|
||||
root.walk((node) => {
|
||||
if (node.type === "atrule" && node.name === "media") {
|
||||
// For each media AtRule, calculate the full media query based upon its parent
|
||||
// This is because media queries can be nested
|
||||
if (node.parent?.[mediaStringSymbol]) {
|
||||
// postcssCssvariables can cause duplicate media queries so we just remove them
|
||||
node[mediaStringSymbol] =
|
||||
node.parent[mediaStringSymbol] === node.params
|
||||
? node.params
|
||||
: `${node.parent[mediaStringSymbol]} and ${node.params}`;
|
||||
} else {
|
||||
node[mediaStringSymbol] = node.params;
|
||||
}
|
||||
} else if (node.type === "rule") {
|
||||
let declarations: Style = {};
|
||||
|
||||
// Get all the declarations
|
||||
node.walkDecls((decl) => {
|
||||
declarations = {
|
||||
...declarations,
|
||||
...toReactNative(decl, {
|
||||
onError: (error) => errors.push(error),
|
||||
}),
|
||||
};
|
||||
});
|
||||
|
||||
if (Object.keys(declarations).length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (node.parent?.[mediaStringSymbol]) {
|
||||
// The parent has a media query, so this needs to be added a media style
|
||||
for (const s of node.selectors) {
|
||||
const selector = normaliseSelector(s, { important });
|
||||
|
||||
media[selector] ??= [];
|
||||
styles[`${selector}_${media[selector].length}`] = declarations;
|
||||
media[selector].push(node.parent[mediaStringSymbol]);
|
||||
}
|
||||
} else {
|
||||
// The parent is the root, so we are not in a media query
|
||||
for (const s of node.selectors) {
|
||||
const selector = normaliseSelector(s);
|
||||
styles[selector] = { ...styles[selector], ...declarations };
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
done({ styles, media });
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
plugin.postcss = true;
|
||||
|
||||
export default plugin;
|
||||
@@ -1,92 +0,0 @@
|
||||
import { AtRule, Comment, Page, Rule } from "css";
|
||||
import {
|
||||
getPropertyName,
|
||||
getStylesForProperty,
|
||||
Style,
|
||||
} from "css-to-react-native";
|
||||
|
||||
import { isInvalidStyle } from "./is-valid-style";
|
||||
import { postProcessingCss, preProcessingCss } from "./patches";
|
||||
|
||||
/**
|
||||
* Convert a css rule to react-native.
|
||||
*
|
||||
* The heavy lifting is performed by 'css-to-react-native', but this comes with some quirks
|
||||
*
|
||||
* CTRN only accepts __valid__ css that can be mapped 1-1 to RN. Invalid CSS will
|
||||
* produce warnings in the console.
|
||||
*
|
||||
* This library is more friendly and fixes what it can / produces better warnings.
|
||||
*
|
||||
* Hence why we have pre/post processing.
|
||||
*
|
||||
* - Pre fixes so CTRN can process it (or it skips processing altogether)
|
||||
* - Post fixes the result of CTRN (or it skips the value)
|
||||
*/
|
||||
export function ruleToReactNative({ declarations = [] }: Rule | Page): Style {
|
||||
const style: Style = {};
|
||||
|
||||
for (const declaration of declarations) {
|
||||
if (isComment(declaration)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const { property: cssAttribute, value: cssValue } = declaration;
|
||||
|
||||
if (cssAttribute === undefined || cssValue === undefined) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const name = getPropertyName(cssAttribute);
|
||||
|
||||
const value = preProcessingCss[name]
|
||||
? preProcessingCss[name](cssValue)
|
||||
: cssValue;
|
||||
|
||||
if (value === null) {
|
||||
warnInvalidStyle(cssAttribute, name, value);
|
||||
continue;
|
||||
}
|
||||
|
||||
const nativeStyles: Style =
|
||||
typeof value === "object" ? value : getStylesForProperty(name, value);
|
||||
|
||||
for (const [nativeAttribute, nativeValue] of Object.entries(nativeStyles)) {
|
||||
if (isInvalidStyle(nativeAttribute)) {
|
||||
warnInvalidStyle(cssAttribute, nativeAttribute, nativeValue);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (postProcessingCss[nativeAttribute]) {
|
||||
const postprocessedValue =
|
||||
postProcessingCss[nativeAttribute](nativeValue);
|
||||
|
||||
if (postprocessedValue === null) {
|
||||
warnInvalidStyle(cssAttribute, nativeAttribute, nativeValue);
|
||||
} else {
|
||||
style[nativeAttribute] = postprocessedValue;
|
||||
}
|
||||
} else {
|
||||
style[nativeAttribute] = nativeValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return style;
|
||||
}
|
||||
|
||||
function warnInvalidStyle(selector: string, attribute: string, value: unknown) {
|
||||
if (process.env.NODE_ENV === "production") {
|
||||
throw new Error(
|
||||
`Class name '${selector}' maps to invalid style {${attribute}: ${value}}`
|
||||
);
|
||||
} else if (process.env.NODE_ENV !== "test") {
|
||||
console.warn(`Class name '${selector}' is being ignored as it produces an invalid React Native style { ${attribute}: '${value}' }
|
||||
Either remove this selector, add a platform modifier (e.g. 'web:${selector}') or change to file to be platform specific.
|
||||
`);
|
||||
}
|
||||
}
|
||||
|
||||
function isComment(rule: Rule | Comment | AtRule): rule is Comment {
|
||||
return rule.type === "comment";
|
||||
}
|
||||
57
src/babel/native-style-extraction/to-react-native/index.ts
Normal file
57
src/babel/native-style-extraction/to-react-native/index.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
import { Declaration } from "postcss";
|
||||
import {
|
||||
getPropertyName,
|
||||
getStylesForProperty,
|
||||
Style,
|
||||
} from "css-to-react-native";
|
||||
|
||||
import { properties } from "./properties";
|
||||
import { isInvalidProperty, StyleProperty } from "./is-invalid-property";
|
||||
|
||||
export interface ToReactNativeErrorRecord {
|
||||
declaration: Declaration;
|
||||
error: Error;
|
||||
result?: Style;
|
||||
}
|
||||
|
||||
export type ToReactNativeErrorCallback = (
|
||||
options: ToReactNativeErrorRecord
|
||||
) => void;
|
||||
|
||||
export interface ToReactNativeOptions {
|
||||
onError: ToReactNativeErrorCallback;
|
||||
}
|
||||
|
||||
export function toReactNative(
|
||||
declaration: Declaration,
|
||||
{ onError }: ToReactNativeOptions
|
||||
) {
|
||||
const { prop, value } = declaration;
|
||||
|
||||
const name = getPropertyName(prop) as StyleProperty;
|
||||
|
||||
let styles: Style | undefined;
|
||||
|
||||
if (isInvalidProperty(name)) {
|
||||
onError({
|
||||
declaration,
|
||||
error: new Error("invalid property"),
|
||||
result: styles,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const transform = properties[name];
|
||||
styles = transform
|
||||
? transform(value, name)
|
||||
: getStylesForProperty(name, value);
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
} catch (error: any) {
|
||||
onError({ declaration, error, result: styles });
|
||||
return;
|
||||
}
|
||||
|
||||
return styles;
|
||||
}
|
||||
@@ -1,8 +1,15 @@
|
||||
export function isInvalidStyle(property: string) {
|
||||
return !validProps.has(property);
|
||||
import { ImageStyle, TextStyle, ViewStyle } from "react-native";
|
||||
|
||||
export type StyleProperty =
|
||||
| keyof TextStyle
|
||||
| keyof ViewStyle
|
||||
| keyof ImageStyle;
|
||||
|
||||
export function isInvalidProperty(property: string) {
|
||||
return !validProps.has(property as StyleProperty);
|
||||
}
|
||||
|
||||
const validProps = new Set([
|
||||
const validProps = new Set<StyleProperty>([
|
||||
"alignContent",
|
||||
"alignItems",
|
||||
"alignSelf",
|
||||
@@ -35,7 +42,6 @@ const validProps = new Set([
|
||||
"borderWidth",
|
||||
"bottom",
|
||||
"color",
|
||||
"decomposedMatrix",
|
||||
"direction",
|
||||
"display",
|
||||
"elevation",
|
||||
@@ -0,0 +1,15 @@
|
||||
import { getStylesForProperty, Style } from "css-to-react-native";
|
||||
|
||||
export function aspectRatio(value: string): Style {
|
||||
if (value === "0") {
|
||||
return {};
|
||||
} else if (typeof value === "string" && value.includes("/")) {
|
||||
const [left, right] = value.split("/").map((n) => {
|
||||
return Number.parseInt(n, 10);
|
||||
});
|
||||
|
||||
return { aspectRatio: left / right };
|
||||
}
|
||||
|
||||
return getStylesForProperty("aspectRatio", value);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import { Style } from "css-to-react-native";
|
||||
|
||||
export function display(value: string): Style {
|
||||
if (value !== "none" && value !== "flex") {
|
||||
throw new Error("display");
|
||||
}
|
||||
|
||||
return { display: value };
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
import { getStylesForProperty, Style } from "css-to-react-native";
|
||||
|
||||
export function flex(value: string, name: string): Style {
|
||||
const { flexGrow, flexShrink } = getStylesForProperty(name, value);
|
||||
return { flexGrow, flexShrink };
|
||||
}
|
||||
@@ -1,34 +1,36 @@
|
||||
import { getStylesForProperty, Style } from "css-to-react-native";
|
||||
import { StyleProperty } from "../is-invalid-property";
|
||||
import { aspectRatio } from "./aspect-ratio";
|
||||
import { display } from "./display";
|
||||
import { flex } from "./flex";
|
||||
import { overflow } from "./overflow";
|
||||
import { position } from "./position";
|
||||
|
||||
function noAuto(value: number | string) {
|
||||
function noAuto(value: string, name: string): Style {
|
||||
if (value === "auto") {
|
||||
return null;
|
||||
throw new Error("no auto");
|
||||
}
|
||||
|
||||
return value;
|
||||
return getStylesForProperty(name, value);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export const postProcessingCss: Record<string, (value: any) => any> = {
|
||||
export const properties: Partial<
|
||||
Record<StyleProperty, (value: string, name: string) => Style>
|
||||
> = {
|
||||
aspectRatio,
|
||||
display,
|
||||
flex,
|
||||
overflow,
|
||||
position,
|
||||
top: noAuto,
|
||||
flexBasis: noAuto,
|
||||
top: noAuto,
|
||||
bottom: noAuto,
|
||||
left: noAuto,
|
||||
right: noAuto,
|
||||
margin: noAuto,
|
||||
marginTop: noAuto,
|
||||
marginRight: noAuto,
|
||||
marginBottom: noAuto,
|
||||
marginLeft: noAuto,
|
||||
};
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export const preProcessingCss: Record<string, (value: any) => any> = {
|
||||
zIndex: noAuto,
|
||||
};
|
||||
@@ -0,0 +1,11 @@
|
||||
import { getStylesForProperty, Style } from "css-to-react-native";
|
||||
|
||||
const supportedValues = new Set(["visible", "hidden", "scroll"]);
|
||||
|
||||
export function overflow(value: string): Style {
|
||||
if (!supportedValues.has(value)) {
|
||||
throw new Error("overflow");
|
||||
}
|
||||
|
||||
return getStylesForProperty("overflow", value);
|
||||
}
|
||||
@@ -1,17 +1,18 @@
|
||||
import { Style } from "css-to-react-native";
|
||||
|
||||
const supportedValues = new Set(["absolute", "relative"]);
|
||||
|
||||
export function position(value: string) {
|
||||
export function position(value: string): Style {
|
||||
if (supportedValues.has(value)) {
|
||||
return value;
|
||||
return { position: value };
|
||||
}
|
||||
|
||||
// This is a special edge case
|
||||
// The tailwindcss keeps picking up `static` as its a javascript keyword
|
||||
// We cannot return `null` (and show the warning) as the user isn't
|
||||
// actualy using the className
|
||||
// So instead of throwing an error we just ignore it
|
||||
if (value === "static") {
|
||||
return;
|
||||
return {};
|
||||
}
|
||||
|
||||
return null;
|
||||
throw new Error("position");
|
||||
}
|
||||
@@ -7,148 +7,12 @@ export interface NativePluginOptions {
|
||||
|
||||
export const nativePlugin = plugin.withOptions<NativePluginOptions | undefined>(
|
||||
function () {
|
||||
return ({ matchUtilities, theme }) => {
|
||||
matchUtilities(
|
||||
{
|
||||
aspect: (value: string) => {
|
||||
let aspectRatio = value;
|
||||
|
||||
if (value.includes("/")) {
|
||||
const [left, right] = value.split("/").map((n) => {
|
||||
return Number.parseInt(n, 10);
|
||||
});
|
||||
|
||||
aspectRatio = `${left / right}`;
|
||||
}
|
||||
|
||||
return {
|
||||
aspectRatio,
|
||||
};
|
||||
},
|
||||
},
|
||||
{ values: theme("aspectRatio") }
|
||||
);
|
||||
return () => {
|
||||
/*Nothing here yet */
|
||||
};
|
||||
},
|
||||
function ({ rem = 16 } = {}) {
|
||||
const config: Partial<TailwindConfig> = {
|
||||
corePlugins: {
|
||||
accentColor: false,
|
||||
accessibility: false,
|
||||
animation: false,
|
||||
appearance: false,
|
||||
aspectRatio: false,
|
||||
backdropBlur: false,
|
||||
backdropBrightness: false,
|
||||
backdropContrast: false,
|
||||
backdropFilter: false,
|
||||
backdropGrayscale: false,
|
||||
backdropHueRotate: false,
|
||||
backdropInvert: false,
|
||||
backdropOpacity: false,
|
||||
backdropSaturate: false,
|
||||
backdropSepia: false,
|
||||
backgroundAttachment: false,
|
||||
backgroundBlendMode: false,
|
||||
backgroundClip: false,
|
||||
backgroundImage: false,
|
||||
backgroundOrigin: false,
|
||||
backgroundPosition: false,
|
||||
backgroundRepeat: false,
|
||||
backgroundSize: false,
|
||||
blur: false,
|
||||
borderCollapse: false,
|
||||
boxDecorationBreak: false,
|
||||
boxShadow: false,
|
||||
boxSizing: false,
|
||||
breakAfter: false,
|
||||
breakBefore: false,
|
||||
breakInside: false,
|
||||
brightness: false,
|
||||
caretColor: false,
|
||||
clear: false,
|
||||
columns: false,
|
||||
content: false,
|
||||
contrast: false,
|
||||
cursor: false,
|
||||
divideColor: false,
|
||||
divideOpacity: false,
|
||||
divideStyle: false,
|
||||
divideWidth: false,
|
||||
dropShadow: false,
|
||||
fill: false,
|
||||
filter: false,
|
||||
float: false,
|
||||
fontSmoothing: false,
|
||||
gap: false,
|
||||
gradientColorStops: false,
|
||||
grayscale: false,
|
||||
gridAutoColumns: false,
|
||||
gridAutoFlow: false,
|
||||
gridAutoRows: false,
|
||||
gridColumn: false,
|
||||
gridColumnEnd: false,
|
||||
gridColumnStart: false,
|
||||
gridRow: false,
|
||||
gridRowEnd: false,
|
||||
gridRowStart: false,
|
||||
gridTemplateColumns: false,
|
||||
gridTemplateRows: false,
|
||||
hueRotate: false,
|
||||
invert: false,
|
||||
isolation: false,
|
||||
justifyItems: false,
|
||||
justifySelf: false,
|
||||
listStylePosition: false,
|
||||
listStyleType: false,
|
||||
mixBlendMode: false,
|
||||
objectFit: false,
|
||||
objectPosition: false,
|
||||
order: false,
|
||||
overscrollBehavior: false,
|
||||
placeItems: false,
|
||||
placeSelf: false,
|
||||
placeholderColor: false,
|
||||
placeholderOpacity: false,
|
||||
preflight: false,
|
||||
resize: false,
|
||||
ringColor: false,
|
||||
ringOffsetColor: false,
|
||||
ringOffsetWidth: false,
|
||||
ringOpacity: false,
|
||||
ringWidth: false,
|
||||
rotate: false,
|
||||
saturate: false,
|
||||
scale: false,
|
||||
scrollBehavior: false,
|
||||
scrollMargin: false,
|
||||
scrollPadding: false,
|
||||
scrollSnapAlign: false,
|
||||
scrollSnapStop: false,
|
||||
scrollSnapType: false,
|
||||
sepia: false,
|
||||
skew: false,
|
||||
space: false,
|
||||
stroke: false,
|
||||
strokeWidth: false,
|
||||
tableLayout: false,
|
||||
textIndent: false,
|
||||
textOverflow: false,
|
||||
touchAction: false,
|
||||
transform: false,
|
||||
transformOrigin: false,
|
||||
transitionDelay: false,
|
||||
transitionDuration: false,
|
||||
transitionProperty: false,
|
||||
transitionTimingFunction: false,
|
||||
translate: false,
|
||||
userSelect: false,
|
||||
verticalAlign: false,
|
||||
visibility: false,
|
||||
whitespace: false,
|
||||
willChange: false,
|
||||
wordBreak: false,
|
||||
},
|
||||
theme: {
|
||||
aspectRatio: {
|
||||
auto: "0",
|
||||
|
||||
12
src/types/common.d.ts
vendored
12
src/types/common.d.ts
vendored
@@ -1,10 +1,6 @@
|
||||
import type {
|
||||
ImageStyle,
|
||||
TextStyle,
|
||||
ViewStyle,
|
||||
} from "react-native";
|
||||
import type { ImageStyle, TextStyle, ViewStyle } from "react-native";
|
||||
|
||||
export type Style = ViewStyle | TextStyle | ImageStyle;
|
||||
export type StyleRecord = Record<string, Style>;
|
||||
export type Media = [string, number];
|
||||
export type MediaRecord = Record<string, Media[]>;
|
||||
export type StyleRecord = Record<string, Record<string, any>>;
|
||||
export type MediaRecord = Record<string, string[]>;
|
||||
export type StyleErrorRecord = Record<string, string>;
|
||||
|
||||
@@ -49,8 +49,14 @@ export function useTailwind<
|
||||
tailwindStyleIds.push(styles[selector] as P);
|
||||
}
|
||||
|
||||
for (const [media, suffix] of mediaRules[selector] ?? []) {
|
||||
const isMatch = match(media, {
|
||||
const rules = mediaRules[selector];
|
||||
|
||||
if (!rules) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (let index = 0, length = rules.length; index < length; index++) {
|
||||
const isMatch = match(rules[index], {
|
||||
type: platform,
|
||||
width,
|
||||
height,
|
||||
@@ -62,7 +68,7 @@ export function useTailwind<
|
||||
} as any);
|
||||
|
||||
if (isMatch) {
|
||||
tailwindStyleIds.push(styles[`${selector}_${suffix}`] as P);
|
||||
tailwindStyleIds.push(styles[`${selector}_${index}`] as P);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user