diff --git a/jest.config.json b/jest.config.json
index f32fc8f..02d4c2a 100644
--- a/jest.config.json
+++ b/jest.config.json
@@ -3,5 +3,5 @@
"transform": {
"^.+\\.tsx?$": "ts-jest"
},
- "testRegex": "__tests__/.*spec\\.ts$"
+ "testRegex": "__tests__/.*spec\\.tsx?$"
}
diff --git a/package-lock.json b/package-lock.json
index 35549f8..fd38c68 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -16,6 +16,7 @@
"@types/jest": "^29.5.11",
"@types/react": "^18.2.45",
"@types/react-native": "^0.72.8",
+ "@types/react-test-renderer": "^17.0.0",
"@types/tailwindcss": "^3.1.0",
"@typescript-eslint/eslint-plugin": "^6.15.0",
"@typescript-eslint/parser": "^6.15.0",
@@ -28,6 +29,7 @@
"prettier": "^3.1.1",
"react": "^17.0.2",
"react-native": "^0.73.1",
+ "react-test-renderer": "^17.0.0",
"ts-jest": "^29.1.1",
"typescript": "^5.3.3"
},
@@ -3102,6 +3104,26 @@
"@types/react": "*"
}
},
+ "node_modules/@types/react-test-renderer": {
+ "version": "17.0.9",
+ "resolved": "https://registry.npmjs.org/@types/react-test-renderer/-/react-test-renderer-17.0.9.tgz",
+ "integrity": "sha512-bOfxcu5oZ+KxvACScbkTwZ4eGCtZFTz4VZCOVAIfGbThxqiXSIGipKVG8ubaYBXquUSQROzNIUzviWdSnnAlzg==",
+ "dev": true,
+ "dependencies": {
+ "@types/react": "^17"
+ }
+ },
+ "node_modules/@types/react-test-renderer/node_modules/@types/react": {
+ "version": "17.0.75",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.75.tgz",
+ "integrity": "sha512-MSA+NzEzXnQKrqpO63CYqNstFjsESgvJAdAyyJ1n6ZQq/GLgf6nOfIKwk+Twuz0L1N6xPe+qz5xRCJrbhMaLsw==",
+ "dev": true,
+ "dependencies": {
+ "@types/prop-types": "*",
+ "@types/scheduler": "*",
+ "csstype": "^3.0.2"
+ }
+ },
"node_modules/@types/scheduler": {
"version": "0.16.2",
"resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz",
@@ -9525,6 +9547,31 @@
"react": "^16.0.0 || ^17.0.0 || ^18.0.0"
}
},
+ "node_modules/react-test-renderer": {
+ "version": "17.0.2",
+ "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-17.0.2.tgz",
+ "integrity": "sha512-yaQ9cB89c17PUb0x6UfWRs7kQCorVdHlutU1boVPEsB8IDZH6n9tHxMacc3y0JoXOJUsZb/t/Mb8FUWMKaM7iQ==",
+ "dev": true,
+ "dependencies": {
+ "object-assign": "^4.1.1",
+ "react-is": "^17.0.2",
+ "react-shallow-renderer": "^16.13.1",
+ "scheduler": "^0.20.2"
+ },
+ "peerDependencies": {
+ "react": "17.0.2"
+ }
+ },
+ "node_modules/react-test-renderer/node_modules/scheduler": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz",
+ "integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==",
+ "dev": true,
+ "dependencies": {
+ "loose-envify": "^1.1.0",
+ "object-assign": "^4.1.1"
+ }
+ },
"node_modules/read-cache": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
@@ -13660,6 +13707,28 @@
"@types/react": "*"
}
},
+ "@types/react-test-renderer": {
+ "version": "17.0.9",
+ "resolved": "https://registry.npmjs.org/@types/react-test-renderer/-/react-test-renderer-17.0.9.tgz",
+ "integrity": "sha512-bOfxcu5oZ+KxvACScbkTwZ4eGCtZFTz4VZCOVAIfGbThxqiXSIGipKVG8ubaYBXquUSQROzNIUzviWdSnnAlzg==",
+ "dev": true,
+ "requires": {
+ "@types/react": "^17"
+ },
+ "dependencies": {
+ "@types/react": {
+ "version": "17.0.75",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.75.tgz",
+ "integrity": "sha512-MSA+NzEzXnQKrqpO63CYqNstFjsESgvJAdAyyJ1n6ZQq/GLgf6nOfIKwk+Twuz0L1N6xPe+qz5xRCJrbhMaLsw==",
+ "dev": true,
+ "requires": {
+ "@types/prop-types": "*",
+ "@types/scheduler": "*",
+ "csstype": "^3.0.2"
+ }
+ }
+ }
+ },
"@types/scheduler": {
"version": "0.16.2",
"resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz",
@@ -18447,6 +18516,30 @@
"react-is": "^16.12.0 || ^17.0.0 || ^18.0.0"
}
},
+ "react-test-renderer": {
+ "version": "17.0.2",
+ "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-17.0.2.tgz",
+ "integrity": "sha512-yaQ9cB89c17PUb0x6UfWRs7kQCorVdHlutU1boVPEsB8IDZH6n9tHxMacc3y0JoXOJUsZb/t/Mb8FUWMKaM7iQ==",
+ "dev": true,
+ "requires": {
+ "object-assign": "^4.1.1",
+ "react-is": "^17.0.2",
+ "react-shallow-renderer": "^16.13.1",
+ "scheduler": "^0.20.2"
+ },
+ "dependencies": {
+ "scheduler": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz",
+ "integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==",
+ "dev": true,
+ "requires": {
+ "loose-envify": "^1.1.0",
+ "object-assign": "^4.1.1"
+ }
+ }
+ }
+ },
"read-cache": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
diff --git a/package.json b/package.json
index 54a174a..064102f 100644
--- a/package.json
+++ b/package.json
@@ -53,6 +53,7 @@
"@types/jest": "^29.5.11",
"@types/react": "^18.2.45",
"@types/react-native": "^0.72.8",
+ "@types/react-test-renderer": "^17.0.0",
"@types/tailwindcss": "^3.1.0",
"@typescript-eslint/eslint-plugin": "^6.15.0",
"@typescript-eslint/parser": "^6.15.0",
@@ -65,6 +66,7 @@
"prettier": "^3.1.1",
"react": "^17.0.2",
"react-native": "^0.73.1",
+ "react-test-renderer": "^17.0.0",
"ts-jest": "^29.1.1",
"typescript": "^5.3.3"
},
diff --git a/src/__tests__/color-scheme.spec.tsx b/src/__tests__/color-scheme.spec.tsx
new file mode 100644
index 0000000..3990939
--- /dev/null
+++ b/src/__tests__/color-scheme.spec.tsx
@@ -0,0 +1,56 @@
+import renderer from 'react-test-renderer';
+import rn from 'react-native';
+import { describe, it, expect } from '@jest/globals';
+import React from 'react';
+import type { RnColorScheme, TailwindFn } from '../';
+import { create, useDeviceContext, useAppColorScheme } from '../';
+
+jest.mock(`react-native`, () => ({
+ Platform: { OS: `ios` },
+ Appearance: { getColorScheme: () => `light` },
+ useColorScheme: () => `light`,
+ useWindowDimensions: () => ({ width: 320, height: 640, fontScale: 1, scale: 2 }),
+}));
+
+const Test: React.FC<{ tw: TailwindFn; initial?: RnColorScheme }> = ({ tw, initial }) => {
+ useDeviceContext(tw, { withDeviceColorScheme: true });
+ const [colorScheme] = useAppColorScheme(tw, initial);
+ return (
+ <>
+ {String(colorScheme)}
+ {tw.prefixMatch(`dark`) ? `match:dark` : `no-match:dark`}
+ >
+ );
+};
+
+describe(`useAppColorScheme()`, () => {
+ it(`should initialize to ambient color scheme, if no initializer`, () => {
+ rn.Appearance.getColorScheme = () => `dark`;
+
+ let component = renderer.create();
+ expect(component.toJSON()).toEqual([`dark`, `match:dark`]);
+
+ rn.Appearance.getColorScheme = () => `light`;
+ component = renderer.create();
+ expect(component.toJSON()).toEqual([`light`, `no-match:dark`]);
+
+ rn.Appearance.getColorScheme = () => null;
+ component = renderer.create();
+ expect(component.toJSON()).toEqual([`null`, `no-match:dark`]);
+
+ rn.Appearance.getColorScheme = () => undefined;
+ component = renderer.create();
+ expect(component.toJSON()).toEqual([`undefined`, `no-match:dark`]);
+ });
+
+ it(`should initialize to explicitly passed color scheme when initializer provided`, () => {
+ rn.Appearance.getColorScheme = () => `dark`;
+
+ let component = renderer.create();
+ expect(component.toJSON()).toEqual([`light`, `no-match:dark`]);
+
+ rn.Appearance.getColorScheme = () => `light`;
+ component = renderer.create();
+ expect(component.toJSON()).toEqual([`dark`, `match:dark`]);
+ });
+});
diff --git a/src/hooks.ts b/src/hooks.ts
index dc4b4fd..44eb30b 100644
--- a/src/hooks.ts
+++ b/src/hooks.ts
@@ -28,9 +28,12 @@ export function useAppColorScheme(
toggleColorScheme: () => void,
setColorScheme: (colorScheme: RnColorScheme) => void,
] {
- const [colorScheme, setColorScheme] = useState(
- initialValue ?? Appearance.getColorScheme(),
- );
+ const [colorScheme, setColorScheme] = useState(() => {
+ const init = initialValue ?? Appearance.getColorScheme();
+ tw.setColorScheme(init);
+ return init;
+ });
+
return [
colorScheme,
() => {
diff --git a/tsconfig.json b/tsconfig.json
index 30fe818..748bb80 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -10,7 +10,8 @@
"lib": ["ES2019"],
"target": "ES2019",
"declaration": true,
- "moduleResolution": "node"
+ "moduleResolution": "node",
+ "jsx": "react"
},
"exclude": ["./dist", "**/*.spec.ts"]
}