@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.
Files changed (41) hide show
  1. package/README.md +84 -132
  2. package/android/src/main/jniLibs/arm64-v8a/libkbach_core_engine.so +0 -0
  3. package/android/src/main/jniLibs/x86_64/libkbach_core_engine.so +0 -0
  4. package/dist/chunk-3AY4XSVY.mjs +40 -0
  5. package/dist/chunk-A3PV4XGK.mjs +564 -0
  6. package/dist/chunk-YYCSHELO.mjs +112 -0
  7. package/dist/clsx-BLLSnqAa.d.ts +277 -0
  8. package/dist/darkModeStore.d.ts +73 -0
  9. package/dist/darkModeStore.js +118 -0
  10. package/dist/dynamicTokens.d.ts +36 -0
  11. package/dist/dynamicTokens.js +75 -0
  12. package/dist/index.d.ts +11 -156
  13. package/dist/index.js +2072 -393
  14. package/dist/index.web.d.ts +15 -4
  15. package/dist/index.web.js +438 -401
  16. package/dist/index.web.mjs +268 -14
  17. package/dist/jsx-dev-runtime.js +2177 -332
  18. package/dist/jsx-dev-runtime.web.js +206 -361
  19. package/dist/jsx-dev-runtime.web.mjs +19 -7
  20. package/dist/jsx-runtime.js +2177 -332
  21. package/dist/jsx-runtime.web.js +191 -353
  22. package/dist/jsx-runtime.web.mjs +3 -6
  23. package/dist/theme.d.ts +54 -0
  24. package/dist/{chunk-AEVOM2NB.mjs → theme.js} +86 -61
  25. package/package.json +43 -14
  26. package/src/babel-plugin.js +144 -2
  27. package/dist/chunk-4KCCEMEN.mjs +0 -66
  28. package/dist/chunk-DLIXI5OW.mjs +0 -53
  29. package/dist/chunk-FG5E4NLJ.mjs +0 -18
  30. package/dist/chunk-KSDFO34H.mjs +0 -32
  31. package/dist/chunk-OJQAJLYT.mjs +0 -14
  32. package/dist/chunk-ZUE6SCTE.mjs +0 -14
  33. package/dist/index.d.mts +0 -161
  34. package/dist/index.mjs +0 -32
  35. package/dist/index.web.d.mts +0 -7
  36. package/dist/jsx-dev-runtime.d.mts +0 -10
  37. package/dist/jsx-dev-runtime.mjs +0 -17
  38. package/dist/jsx-dev-runtime.web.d.mts +0 -10
  39. package/dist/jsx-runtime.d.mts +0 -7
  40. package/dist/jsx-runtime.mjs +0 -14
  41. 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
- Kbach's utility-class styling engine for React Native — the same class
4
- names as [`@kbach/react`](https://www.npmjs.com/package/@kbach/react),
5
- resolved to a real `StyleSheet`-ready style object instead of injected CSS.
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 (Android-only, no iOS bridge yet) resolves through a
8
- > Kotlin/JNI TurboModule; Expo Web / react-native-web resolves through the
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
- ## Setup
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
- One package, nothing else to install — the Kotlin TurboModule and its
21
- prebuilt native `.so` ship inside this same package's own `android/`
22
- folder. Android's autolinking discovers it automatically the moment it's
23
- in `node_modules`; no manual `MainApplication.kt` edit needed. Works the
24
- same way whether your app was created with the React Native CLI or with
25
- Expo — **except Expo Go**, which can never load this (or any) custom
26
- native module; see below.
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
- ### React Native CLI
25
+ The babel plugin, added to your existing `babel.config.js`:
29
26
 
30
- Add the Babel plugin so your app's JSX routes through Kbach's JSX runtime
31
- instead of `react/jsx-runtime`:
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
- // babel.config.js
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 rebuild the Android app (`npm run android`, or a clean Gradle build if
42
- you're re-running one that's already built) so Gradle picks up the new
43
- native module. See `apps/native-sandbox` in the
44
- [repo](https://github.com/semsakadanupol/kbach) for a full working
45
- reference project, including the Metro config a monorepo setup like this
46
- one needs (a plain single-app install doesn't need any of that — it's
47
- only relevant if you're linking packages locally instead of installing
48
- from npm).
49
-
50
- ### Expo (native — Android)
51
-
52
- **Expo Go can never work with this package, and that isn't specific to
53
- Kbach.** Expo Go is a single fixed binary Expo pre-builds and ships
54
- through the app stores, containing only the native code Expo bundled into
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
- // babel.config.js
62
+ // kbach.config.js
65
63
  module.exports = {
66
- presets: ['babel-preset-expo'], // not '@react-native/babel-preset'
67
- plugins: ['@kbach/react-native/babel-plugin'],
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
- ```sh
72
- npx expo prebuild # generates android/ (and ios/, which this package doesn't support yet)
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
- Also requires the New Architecture enabled (Expo's default in current SDK
77
- versions) — the native module is a TurboModule, which doesn't exist under
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
- Works standalone, with zero provider — same architecture as `@kbach/react`:
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 { useGlobalDarkMode, toggleGlobalDarkMode } from '@kbach/react-native';
86
+ import { useTheme } from '@kbach/react-native';
139
87
 
140
- function ThemeToggle() {
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
- Or the optional `<ThemeProvider>` / `useTheme()` pair, reading and writing
147
- the exact same global store:
91
+ Works anywhere, no provider. `<ThemeProvider>` is optional — for seeding a
92
+ startup default and opt-in persistence (`<ThemeProvider persist={AsyncStorage}>`).
148
93
 
149
- ```tsx
150
- import { ThemeProvider, useTheme } from '@kbach/react-native';
94
+ ## Colors as values
151
95
 
152
- function Toggle() {
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
- <ThemeProvider defaultMode="system">
158
- <Toggle />
159
- </ThemeProvider>;
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
- By default the mode follows the OS `Appearance` setting live until you
163
- explicitly override it — and **isn't persisted across app launches**.
164
- There's no React-Native-builtin equivalent of `localStorage`, and adding
165
- one would mean forcing a real native dependency (e.g.
166
- `@react-native-async-storage/async-storage`) on every consumer, even ones
167
- that don't want it. If you want persistence, read your own storage at
168
- startup and call `setGlobalThemeMode()` with the result before your first
169
- render — the same "seed once" shape `<ThemeProvider defaultMode>` itself
170
- uses internally.
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
 
@@ -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
+ };