@kbach/react-native 1.0.0-beta.4 → 1.0.0-beta.41
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 +84 -132
- package/android/src/main/jniLibs/arm64-v8a/libkbach_core_engine.so +0 -0
- package/android/src/main/jniLibs/x86_64/libkbach_core_engine.so +0 -0
- package/dist/chunk-3AY4XSVY.mjs +40 -0
- package/dist/chunk-A3PV4XGK.mjs +564 -0
- package/dist/chunk-YYCSHELO.mjs +112 -0
- package/dist/clsx-BLLSnqAa.d.ts +277 -0
- package/dist/darkModeStore.d.ts +73 -0
- package/dist/darkModeStore.js +118 -0
- package/dist/dynamicTokens.d.ts +36 -0
- package/dist/dynamicTokens.js +75 -0
- package/dist/index.d.ts +11 -156
- package/dist/index.js +2072 -393
- package/dist/index.web.d.ts +15 -4
- package/dist/index.web.js +438 -401
- package/dist/index.web.mjs +268 -14
- package/dist/jsx-dev-runtime.js +2177 -332
- package/dist/jsx-dev-runtime.web.js +206 -361
- package/dist/jsx-dev-runtime.web.mjs +19 -7
- package/dist/jsx-runtime.js +2177 -332
- package/dist/jsx-runtime.web.js +191 -353
- package/dist/jsx-runtime.web.mjs +3 -6
- package/dist/theme.d.ts +54 -0
- package/dist/{chunk-AEVOM2NB.mjs → theme.js} +86 -61
- package/package.json +43 -14
- package/src/babel-plugin.js +144 -2
- package/dist/chunk-4KCCEMEN.mjs +0 -66
- package/dist/chunk-DLIXI5OW.mjs +0 -53
- package/dist/chunk-FG5E4NLJ.mjs +0 -18
- package/dist/chunk-KSDFO34H.mjs +0 -32
- package/dist/chunk-OJQAJLYT.mjs +0 -14
- package/dist/chunk-ZUE6SCTE.mjs +0 -14
- package/dist/index.d.mts +0 -161
- package/dist/index.mjs +0 -32
- package/dist/index.web.d.mts +0 -7
- package/dist/jsx-dev-runtime.d.mts +0 -10
- package/dist/jsx-dev-runtime.mjs +0 -17
- package/dist/jsx-dev-runtime.web.d.mts +0 -10
- package/dist/jsx-runtime.d.mts +0 -7
- package/dist/jsx-runtime.mjs +0 -14
- package/dist/jsx-runtime.web.d.mts +0 -7
package/README.md
CHANGED
|
@@ -1,173 +1,125 @@
|
|
|
1
1
|
# @kbach/react-native
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
Utility-class styling for React Native — the same class names as
|
|
4
|
+
[`@kbach/react`](https://www.npmjs.com/package/@kbach/react), resolved to a
|
|
5
|
+
`StyleSheet`-ready style object instead of CSS.
|
|
6
6
|
|
|
7
|
-
> **Beta.** Native
|
|
8
|
-
>
|
|
9
|
-
> same Rust engine compiled to WASM instead — both call the identical
|
|
10
|
-
> resolution logic, so class semantics stay identical everywhere. The
|
|
11
|
-
> native module ships prebuilt (see Setup below) — no Rust toolchain or
|
|
12
|
-
> manual native wiring required on any platform.
|
|
7
|
+
> **Beta.** Native is Android-only (no iOS bridge yet). Ships a prebuilt
|
|
8
|
+
> native module — no Rust toolchain or manual linking.
|
|
13
9
|
|
|
14
|
-
##
|
|
10
|
+
## Install
|
|
15
11
|
|
|
16
12
|
```sh
|
|
17
|
-
npm install @kbach/react-native
|
|
13
|
+
npm install @kbach/react-native@beta
|
|
18
14
|
```
|
|
19
15
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
Expo
|
|
26
|
-
|
|
16
|
+
## Setup
|
|
17
|
+
|
|
18
|
+
| Target | What to do |
|
|
19
|
+
| :-- | :-- |
|
|
20
|
+
| **Expo Go** | Nothing. A pure-JS fallback engine loads automatically. |
|
|
21
|
+
| **Expo Web** / `react-native-web` | Nothing. Resolves through the same CSS engine `@kbach/react` uses. |
|
|
22
|
+
| **Expo dev client / prebuild / EAS** | Add the babel plugin (below), then `npx expo prebuild && npx expo run:android`. |
|
|
23
|
+
| **React Native CLI** | Add the babel plugin (below), then rebuild the app. |
|
|
27
24
|
|
|
28
|
-
|
|
25
|
+
The babel plugin, added to your existing `babel.config.js`:
|
|
29
26
|
|
|
30
|
-
|
|
31
|
-
|
|
27
|
+
```js
|
|
28
|
+
// Expo — keep the function form your project already has:
|
|
29
|
+
module.exports = function (api) {
|
|
30
|
+
api.cache(true);
|
|
31
|
+
return {
|
|
32
|
+
presets: ['babel-preset-expo'],
|
|
33
|
+
plugins: ['@kbach/react-native/babel-plugin'],
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
```
|
|
32
37
|
|
|
33
38
|
```js
|
|
34
|
-
//
|
|
39
|
+
// React Native CLI:
|
|
35
40
|
module.exports = {
|
|
36
41
|
presets: ['module:@react-native/babel-preset'],
|
|
37
42
|
plugins: ['@kbach/react-native/babel-plugin'],
|
|
38
43
|
};
|
|
39
44
|
```
|
|
40
45
|
|
|
41
|
-
Then
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
it at their own build time — there is no mechanism for *any* third-party
|
|
56
|
-
package to add native code to it at runtime, whether that's a raw
|
|
57
|
-
TurboModule (what this package uses) or even Expo's own Modules API. This
|
|
58
|
-
is exactly why the **dev client** concept exists: a custom build of your
|
|
59
|
-
app — built once via `expo prebuild`/`expo run:android`, functionally the
|
|
60
|
-
same "real native project" as the CLI path above — that *does* include
|
|
61
|
-
this module:
|
|
46
|
+
Then write classes:
|
|
47
|
+
|
|
48
|
+
```tsx
|
|
49
|
+
import { View, Text } from 'react-native';
|
|
50
|
+
|
|
51
|
+
<View className="flex-1 items-center justify-center bg-white dark:bg-black">
|
|
52
|
+
<Text className="text-lg font-bold">Hello Kbach</Text>
|
|
53
|
+
</View>;
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Theme
|
|
57
|
+
|
|
58
|
+
Optional. Create `kbach.config.js` at your project root — the babel plugin
|
|
59
|
+
picks it up automatically, no import or `applyKbachConfig()` call needed:
|
|
62
60
|
|
|
63
61
|
```js
|
|
64
|
-
//
|
|
62
|
+
// kbach.config.js
|
|
65
63
|
module.exports = {
|
|
66
|
-
|
|
67
|
-
|
|
64
|
+
extend: {
|
|
65
|
+
colors: {
|
|
66
|
+
brand: '#ff6b35',
|
|
67
|
+
surface: 'gray-2',
|
|
68
|
+
dark: { surface: 'gray-11' }, // makes `bg-surface` mode-aware
|
|
69
|
+
},
|
|
70
|
+
},
|
|
68
71
|
};
|
|
69
72
|
```
|
|
70
73
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
npx expo run:android # builds and installs a dev client with the native module included
|
|
74
|
-
```
|
|
74
|
+
It's plain JavaScript — **quote any key containing a hyphen**
|
|
75
|
+
(`'surface-dim': '#121318'`).
|
|
75
76
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
the legacy bridge at all. If you're on an older SDK/config with the New
|
|
79
|
-
Architecture off, turn it on in `app.json`
|
|
80
|
-
(`"newArchEnabled": true` under `expo`) before prebuilding.
|
|
81
|
-
|
|
82
|
-
EAS Build works the same way — it runs the same `prebuild` step, so no
|
|
83
|
-
extra configuration beyond the two steps above.
|
|
84
|
-
|
|
85
|
-
### Expo Web
|
|
86
|
-
|
|
87
|
-
**Works — no extra setup, no separate package, no init call.** `expo start
|
|
88
|
-
--web` (and EAS's web builds) render through `react-native-web` —
|
|
89
|
-
`View`/`Text`/etc. become real DOM elements with real CSS, not a
|
|
90
|
-
Kotlin/JNI bridge, so on web this package resolves classes through the
|
|
91
|
-
same Rust engine [`@kbach/react`](https://www.npmjs.com/package/@kbach/react)
|
|
92
|
-
uses — WASM instead of JNI — automatically. Metro picks the right
|
|
93
|
-
implementation per platform on its own via this package's `"browser"`
|
|
94
|
-
export condition; your app code and JSX never change. The WASM module
|
|
95
|
-
initializes itself eagerly (synchronously, at import time — no `await`
|
|
96
|
-
needed before your first render, unlike a from-scratch WASM setup).
|
|
97
|
-
|
|
98
|
-
The only thing this doesn't cover on web is an iOS-parity feature gap —
|
|
99
|
-
everything web-side resolves through the exact same
|
|
100
|
-
[`resolve_style.rs`](https://github.com/semsakadanupol/kbach/blob/main/packages/core-engine/src/resolve_style.rs)
|
|
101
|
-
logic real native uses, so see this README's "What this is" section above
|
|
102
|
-
for what's covered.
|
|
103
|
-
|
|
104
|
-
## What this is
|
|
105
|
-
|
|
106
|
-
- A JSX runtime (`@kbach/react-native/jsx-runtime`) that intercepts
|
|
107
|
-
`className`/`kb` props on every element and calls into the native bridge
|
|
108
|
-
to resolve them to a style object, synchronously, on every render.
|
|
109
|
-
- A Babel plugin (`@kbach/react-native/babel-plugin`) that routes your
|
|
110
|
-
app's own files (never `node_modules`) through that JSX runtime via a
|
|
111
|
-
per-file `@jsxImportSource` pragma.
|
|
112
|
-
- `setTheme()`/`getTheme()` for customizing the color palette and spacing
|
|
113
|
-
scale — the same `ThemeConfig` shape `@kbach/react` uses, kept as an
|
|
114
|
-
independent type here so a native-only project isn't forced to depend on
|
|
115
|
-
a web-oriented package.
|
|
116
|
-
- `shadow-*` resolves to real native shadows — RN's discrete
|
|
117
|
-
`shadowColor`/`shadowOffset`/`shadowOpacity`/`shadowRadius` props plus
|
|
118
|
-
Android's `elevation` (both emitted together; `elevation` is what
|
|
119
|
-
actually renders a shadow on Android — the `shadow*` props are iOS-only
|
|
120
|
-
in RN itself, ready for whenever this package gets an iOS bridge),
|
|
121
|
-
derived from the same named tiers (`sm`/`DEFAULT`/`md`/`lg`/`xl`/`2xl`)
|
|
122
|
-
`@kbach/react`'s CSS `box-shadow` scale uses. `shadow-inner` and
|
|
123
|
-
arbitrary `shadow-[...]` values aren't supported — RN's native shadow
|
|
124
|
-
props can't express an inset shadow, and an arbitrary value is a raw CSS
|
|
125
|
-
string with no mechanical translation into discrete native props.
|
|
126
|
-
- Responsive breakpoints (`sm:`/`md:`/`lg:`/`xl:`/`2xl:`) — gated live
|
|
127
|
-
against the current window width (`Dimensions.get('window').width`),
|
|
128
|
-
same mobile-first "min-width and up" semantics as web, and freely
|
|
129
|
-
combinable with `dark:`/`active:` (e.g. `dark:md:bg-blue-8`). Call RN's
|
|
130
|
-
own `useWindowDimensions()` somewhere in your tree to re-render on
|
|
131
|
-
rotation/resize — same role `useColorScheme()` plays for `dark:` below.
|
|
77
|
+
Full config reference (colors, spacing, breakpoints, fonts, dark mode) is
|
|
78
|
+
in [AGENTS.md](https://github.com/semsakadanupol/kbach/blob/main/AGENTS.md).
|
|
132
79
|
|
|
133
80
|
## Dark mode
|
|
134
81
|
|
|
135
|
-
|
|
82
|
+
Zero setup on every target. `dark:` classes react to the OS setting;
|
|
83
|
+
`useTheme()` gives you a manual toggle:
|
|
136
84
|
|
|
137
85
|
```tsx
|
|
138
|
-
import {
|
|
86
|
+
import { useTheme } from '@kbach/react-native';
|
|
139
87
|
|
|
140
|
-
|
|
141
|
-
const isDark = useGlobalDarkMode();
|
|
142
|
-
return <Pressable onPress={toggleGlobalDarkMode}><Text>{isDark ? 'Dark' : 'Light'}</Text></Pressable>;
|
|
143
|
-
}
|
|
88
|
+
const { mode, isDark, setMode, toggle } = useTheme();
|
|
144
89
|
```
|
|
145
90
|
|
|
146
|
-
|
|
147
|
-
|
|
91
|
+
Works anywhere, no provider. `<ThemeProvider>` is optional — for seeding a
|
|
92
|
+
startup default and opt-in persistence (`<ThemeProvider persist={AsyncStorage}>`).
|
|
148
93
|
|
|
149
|
-
|
|
150
|
-
import { ThemeProvider, useTheme } from '@kbach/react-native';
|
|
94
|
+
## Colors as values
|
|
151
95
|
|
|
152
|
-
|
|
153
|
-
const { mode, isDark, setMode, toggle } = useTheme();
|
|
154
|
-
return <Pressable onPress={toggle}><Text>{mode}</Text></Pressable>;
|
|
155
|
-
}
|
|
96
|
+
For a real color string rather than a class — a chart prop, a shadow color:
|
|
156
97
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
98
|
+
```tsx
|
|
99
|
+
import { useColors } from '@kbach/react-native';
|
|
100
|
+
|
|
101
|
+
const colors = useColors();
|
|
102
|
+
colors.blue[6]; // '#2563eb'
|
|
103
|
+
colors.blue['6/50']; // same at 50% opacity
|
|
104
|
+
colors.get('brand'); // a custom color, typed as plain `string`
|
|
160
105
|
```
|
|
161
106
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
107
|
+
## What differs on native
|
|
108
|
+
|
|
109
|
+
React Native has no CSS cascade, so a fixed subset of modifiers is
|
|
110
|
+
supported — `dark:`, `sm:`–`2xl:`, `active:`, `hover:`, `focus:`,
|
|
111
|
+
`disabled:`, and `data-[…]:`/`aria-[…]:`. `group-*`/`peer-*`/`has-[…]` and
|
|
112
|
+
container queries parse without error but do not apply. When two classes
|
|
113
|
+
set the same property the more-specific one wins regardless of source
|
|
114
|
+
order (`dark:bg-black bg-white` → black in dark mode).
|
|
115
|
+
|
|
116
|
+
Expo Go covers a documented subset of utilities (no grid, filters,
|
|
117
|
+
gradients, or DOM-only typography). Expo Web and a real dev-client build
|
|
118
|
+
cover the full set.
|
|
119
|
+
|
|
120
|
+
See [AGENTS.md](https://github.com/semsakadanupol/kbach/blob/main/AGENTS.md)
|
|
121
|
+
for the complete reference — modifier list, `calc()`/`min()`/`max()`
|
|
122
|
+
support, dynamic tokens, monorepo setup, and how the engine works.
|
|
171
123
|
|
|
172
124
|
## License
|
|
173
125
|
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import {
|
|
2
|
+
resolveClassName
|
|
3
|
+
} from "./chunk-A3PV4XGK.mjs";
|
|
4
|
+
|
|
5
|
+
// src/jsxRuntimeCoreWeb.ts
|
|
6
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
7
|
+
import { Fragment } from "react";
|
|
8
|
+
function makeElement(isStaticChildren, type, props, key) {
|
|
9
|
+
return (isStaticChildren ? _jsxs : _jsx)(type, props, key);
|
|
10
|
+
}
|
|
11
|
+
function processElement(resolveClassName2, type, rawProps, key, isStaticChildren) {
|
|
12
|
+
if (type === null || typeof type === "symbol" || !rawProps) {
|
|
13
|
+
return makeElement(isStaticChildren, type, rawProps ?? {}, key);
|
|
14
|
+
}
|
|
15
|
+
const { className: classStrRaw, dataSet: userDataSet, ...rest } = rawProps;
|
|
16
|
+
if (typeof classStrRaw !== "string") {
|
|
17
|
+
return makeElement(isStaticChildren, type, rawProps, key);
|
|
18
|
+
}
|
|
19
|
+
const resolved = resolveClassName2(classStrRaw);
|
|
20
|
+
const dataSet = { ...userDataSet, kb: resolved };
|
|
21
|
+
return makeElement(isStaticChildren, type, { ...rest, className: classStrRaw, dataSet }, key);
|
|
22
|
+
}
|
|
23
|
+
function createJsxFunctionsWeb(resolveClassName2) {
|
|
24
|
+
function jsx2(type, props, key) {
|
|
25
|
+
return processElement(resolveClassName2, type, props, key, false);
|
|
26
|
+
}
|
|
27
|
+
function jsxs2(type, props, key) {
|
|
28
|
+
return processElement(resolveClassName2, type, props, key, true);
|
|
29
|
+
}
|
|
30
|
+
return { jsx: jsx2, jsxs: jsxs2 };
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// src/jsx-runtime.web.tsx
|
|
34
|
+
var { jsx, jsxs } = createJsxFunctionsWeb(resolveClassName);
|
|
35
|
+
|
|
36
|
+
export {
|
|
37
|
+
Fragment,
|
|
38
|
+
jsx,
|
|
39
|
+
jsxs
|
|
40
|
+
};
|