@kbach/react-native 1.0.0-beta.52 → 1.0.0-beta.53

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/AGENTS.md CHANGED
@@ -14,7 +14,7 @@ and how the underlying engine is built, see the repo root's
14
14
  >
15
15
  > 1. Color shades are `1`–`12` (lightest→darkest), not Tailwind's
16
16
  > `50`–`950` — `bg-blue-500` resolves to nothing; the real class is
17
- > `bg-blue-6`. Full palette: root AGENTS.md §6.
17
+ > `bg-blue-6`. Full palette: root AGENTS.md §7.
18
18
  > 2. `group-*`, `peer-*`, `has-[…]`, container queries, grid, and pseudo-
19
19
  > elements (`before:`/`after:`) are real Tailwind syntax that PARSES
20
20
  > here but applies **zero style, with no warning** — native has no
@@ -309,7 +309,7 @@ colors.get('brand'); // a custom color, typed as plain `string`
309
309
 
310
310
  `colors.blue[6]` returns the same value in both light and dark mode
311
311
  unless `blue-6` itself is defined in the theme as a `{ light, dark }` pair
312
- (§5.1 of the root AGENTS.md) — define a color as mode-aware in
312
+ (§6.1 of the root AGENTS.md) — define a color as mode-aware in
313
313
  `kbach.config.js` if you want it to differ by mode.
314
314
 
315
315
  `colors.brand` (a custom flat color) is typed `string | ColorScale`
@@ -346,10 +346,11 @@ and `react` at `projectRoot/node_modules/...`. A plain non-monorepo
346
346
  `setDynamicToken`, `getDynamicToken`, `deleteDynamicToken`,
347
347
  `subscribeDynamicTokens`, `useDynamicToken`, `clsx`, `getGlobalDarkMode`,
348
348
  `getGlobalThemeMode`, `setGlobalThemeMode`, `toggleGlobalDarkMode`,
349
- `subscribeGlobalDarkMode`. Types: `ThemeConfig`, `ColorEntry`,
350
- `ContainerConfig`, `StyleObject`, `KbachConfig`, `ThemeState`,
351
- `ThemeProviderProps`, `ThemeStorageAdapter`, `ThemeMode`, `ColorsAPI`,
352
- `ColorScale`, `ClassValue`.
349
+ `subscribeGlobalDarkMode`, `Button`, `Paragraph`, `H1`, `H2`, `H3`, `H4`,
350
+ `H5`, `H6` (§14). Types: `ThemeConfig`, `ColorEntry`, `ContainerConfig`,
351
+ `StyleObject`, `KbachConfig`, `ThemeState`, `ThemeProviderProps`,
352
+ `ThemeStorageAdapter`, `ThemeMode`, `ColorsAPI`, `ColorScale`,
353
+ `ClassValue`, `ButtonProps`, `ParagraphProps`, `HeadingProps`.
353
354
 
354
355
  Subpath exports: `@kbach/react-native/babel-plugin`,
355
356
  `@kbach/react-native/jsx-runtime`, `@kbach/react-native/jsx-dev-runtime`.
@@ -379,6 +380,19 @@ Subpath exports: `@kbach/react-native/babel-plugin`,
379
380
  missing. It's required on every target, not just Android/dev-client
380
381
  builds; without it nothing routes `className` through this package's
381
382
  jsx-runtime at all, so RN just silently ignores the unrecognized prop.
383
+ - **`useColors().get('yourCustomColor')` returns the literal name, not
384
+ the color, on Expo Web — icons/fills using it render invisible** —
385
+ stale `@kbach/react-native` (`< 1.0.0-beta.53`). Root cause: on web,
386
+ this package loads as two separate module instances in the same
387
+ bundle — a bare `import` resolves through package.json's `import`
388
+ condition, but the babel plugin's injected
389
+ `require('@kbach/react-native').applyKbachConfig(...)` always resolves
390
+ through `require` — so `kbach.config.js`'s custom colors landed in one
391
+ instance's theme state while every component's own `useColors()` read
392
+ the other, untouched one. Fixed by routing `theme.ts`'s active-theme
393
+ state through a `globalThis`-backed slot instead of a plain
394
+ module-scope variable, so both instances share it regardless of which
395
+ one set it. Update.
382
396
  - **`ERROR [Error: Unable to find node on an unmounted component.]` on
383
397
  Expo Fast Refresh, especially right after editing `kbach.config.js`** —
384
398
  stale `@kbach/react-native` (`< 1.0.0-beta.51`). Root cause: the babel
@@ -403,3 +417,43 @@ Subpath exports: `@kbach/react-native/babel-plugin`,
403
417
  Fixed identically in both the Rust native dispatcher and its Expo Go JS-
404
418
  fallback mirror (`jsEngine/resolveUtilityNative.ts`) in beta.52; update.
405
419
  Web (including Expo Web) was never affected.
420
+
421
+ ## 14. Semantic HTML on Expo Web
422
+
423
+ On Expo Web, `react-native-web` renders a bare `<View>`/`<Text>` as a
424
+ plain `<div>`/`<span>` by default — confirmed directly in its own source.
425
+ That's **not** a Kbach limitation: this package's jsx-runtime never reads
426
+ or substitutes the JSX element type at all, so whatever tag shows up is
427
+ exactly whatever component the app wrote.
428
+
429
+ `react-native-web` already has a real fix for this that this package
430
+ never gets in the way of: an `accessibilityRole`/`role` prop on ANY host
431
+ component makes it render the matching real HTML element instead —
432
+ `accessibilityRole="button"` → `<button>`, `accessibilityRole="header"` +
433
+ `aria-level` (web-only; real native has no heading-LEVEL concept, only
434
+ `header` itself) → `<h1>`-`<h6>`, `role="paragraph"` → `<p>`, and so on
435
+ (`react-native-web`'s own `propsToAccessibilityComponent`). `role` covers
436
+ every value in React Native's own typed `Role` union (`button`,
437
+ `heading`, `list`, `listitem`, `navigation`, `main`, `form`, `article`,
438
+ `banner`, `contentinfo`, `complementary`, `region`, ...); `"paragraph"`
439
+ is the one react-native-web additionally supports that isn't in that
440
+ union at all.
441
+
442
+ This package exports a handful of convenience components that are just
443
+ that prop, pre-set on the right underlying component — nothing beyond
444
+ that, and writing `<Pressable accessibilityRole="button">` directly
445
+ instead of `<Button>` behaves identically:
446
+
447
+ ```tsx
448
+ import { Button, Paragraph, H1, H2, H3, H4, H5, H6 } from '@kbach/react-native';
449
+
450
+ <Button className="px-4 py-2 rounded bg-blue-6" onPress={...}>Save</Button>
451
+ <H1 className="text-2xl font-bold">Page title</H1>
452
+ <Paragraph className="text-sm text-gray-7">Body copy.</Paragraph>
453
+ ```
454
+
455
+ `className` keeps working on every one of these exactly like it does on
456
+ a bare `Pressable`/`Text`. No `Div` or `Input` here on purpose: a plain
457
+ `<View>` already is the right generic container, and `<TextInput>`
458
+ already renders a real `<input>` (or `<textarea>` when `multiline`) by
459
+ default, with no role needed at all.
package/README.md CHANGED
@@ -145,6 +145,22 @@ colors.blue['6/50']; // same at 50% opacity
145
145
  colors.get('brand'); // a custom color, typed as plain `string`
146
146
  ```
147
147
 
148
+ ## Semantic HTML on web
149
+
150
+ On Expo Web, `<View>`/`<Text>` render as a plain `<div>`/`<span>` by
151
+ default (`react-native-web`'s own choice, not this package's). For a real
152
+ `<button>`/`<h1>`-`<h6>`/`<p>` instead, use these — each is just the
153
+ right underlying component with its semantic role pre-set, so `className`
154
+ keeps working exactly like it does on a bare `Pressable`/`Text`:
155
+
156
+ ```tsx
157
+ import { Button, H1, Paragraph } from '@kbach/react-native';
158
+
159
+ <H1 className="text-2xl font-bold">Page title</H1>
160
+ <Paragraph className="text-sm text-gray-7">Body copy.</Paragraph>
161
+ <Button className="px-4 py-2 rounded bg-blue-6" onPress={...}>Save</Button>
162
+ ```
163
+
148
164
  ## What differs on native
149
165
 
150
166
  React Native has no CSS cascade, so a fixed subset of modifiers is
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  getTheme
3
- } from "./chunk-Z5Q3FGXR.mjs";
3
+ } from "./chunk-P75PP2QR.mjs";
4
4
 
5
5
  // src/darkModeStore.ts
6
6
  import { Appearance } from "react-native";
@@ -346,19 +346,28 @@ var defaultTheme = {
346
346
  // Empty by default, matching real Tailwind's own defaults.
347
347
  container: {}
348
348
  };
349
- var activeTheme = defaultTheme;
350
- var activeThemeJson = JSON.stringify(defaultTheme);
349
+ var GLOBAL_STATE_KEY = "__kbachReactNativeThemeState__";
350
+ function getThemeState() {
351
+ const g = globalThis;
352
+ let state = g[GLOBAL_STATE_KEY];
353
+ if (!state) {
354
+ state = { theme: defaultTheme, json: JSON.stringify(defaultTheme) };
355
+ g[GLOBAL_STATE_KEY] = state;
356
+ }
357
+ return state;
358
+ }
351
359
  function setTheme(theme) {
352
360
  const json = JSON.stringify(theme);
353
- if (json === activeThemeJson) return;
354
- activeTheme = theme;
355
- activeThemeJson = json;
361
+ const state = getThemeState();
362
+ if (json === state.json) return;
363
+ state.theme = theme;
364
+ state.json = json;
356
365
  }
357
366
  function getTheme() {
358
- return activeTheme;
367
+ return getThemeState().theme;
359
368
  }
360
369
  function getThemeJson() {
361
- return activeThemeJson;
370
+ return getThemeState().json;
362
371
  }
363
372
 
364
373
  // src/wasmGlue.generated.ts
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  resolveClassName
3
- } from "./chunk-Z5Q3FGXR.mjs";
3
+ } from "./chunk-P75PP2QR.mjs";
4
4
 
5
5
  // src/jsxRuntimeCoreWeb.ts
6
6
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
package/dist/index.d.ts CHANGED
@@ -1,8 +1,9 @@
1
1
  export { ColorEntry, ContainerConfig, ThemeConfig, defaultTheme, getTheme, setTheme } from './theme';
2
- export { C as ClassArray, a as ClassDictionary, b as ClassValue, c as ColorScale, d as ColorsAPI, K as KbachConfig, T as ThemeProvider, e as ThemeProviderProps, f as ThemeState, g as ThemeStorageAdapter, h as applyKbachConfig, i as clsx, r as resolveKbachConfig, u as useColors, j as useDynamicToken, k as useTheme } from './clsx-BLLSnqAa.js';
2
+ export { B as Button, a as ButtonProps, C as ClassArray, b as ClassDictionary, c as ClassValue, d as ColorScale, e as ColorsAPI, H as H1, f as H2, g as H3, h as H4, i as H5, j as H6, k as HeadingProps, K as KbachConfig, P as Paragraph, l as ParagraphProps, T as ThemeProvider, m as ThemeProviderProps, n as ThemeState, o as ThemeStorageAdapter, p as applyKbachConfig, q as clsx, r as resolveKbachConfig, u as useColors, s as useDynamicToken, t as useTheme } from './semanticElements-Bk3TB-vt.js';
3
3
  export { ThemeMode, getGlobalDarkMode, getGlobalThemeMode, setGlobalThemeMode, subscribeGlobalDarkMode, toggleGlobalDarkMode } from './darkModeStore';
4
4
  export { deleteDynamicToken, getDynamicToken, setDynamicToken, subscribeDynamicTokens } from './dynamicTokens';
5
5
  import 'react';
6
+ import 'react-native';
6
7
 
7
8
  type StyleValue = string | number | {
8
9
  width: number;
package/dist/index.js CHANGED
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
+ var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
5
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
8
  var __export = (target, all) => {
7
9
  for (var name in all)
@@ -15,11 +17,27 @@ var __copyProps = (to, from, except, desc) => {
15
17
  }
16
18
  return to;
17
19
  };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
18
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
29
 
20
30
  // src/index.ts
21
31
  var src_exports = {};
22
32
  __export(src_exports, {
33
+ Button: () => Button,
34
+ H1: () => H1,
35
+ H2: () => H2,
36
+ H3: () => H3,
37
+ H4: () => H4,
38
+ H5: () => H5,
39
+ H6: () => H6,
40
+ Paragraph: () => Paragraph,
23
41
  ThemeProvider: () => ThemeProvider,
24
42
  applyKbachConfig: () => applyKbachConfig,
25
43
  clsx: () => clsx,
@@ -2179,8 +2197,42 @@ function resolveClassValue(value) {
2179
2197
  }
2180
2198
  return "";
2181
2199
  }
2200
+
2201
+ // src/semanticElements.tsx
2202
+ var React = __toESM(require("react"));
2203
+ var import_react_native2 = require("react-native");
2204
+ var import_jsx_runtime2 = require("react/jsx-runtime");
2205
+ var Button = React.forwardRef(function Button2(props, ref) {
2206
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native2.Pressable, { ref, accessibilityRole: "button", ...props });
2207
+ });
2208
+ var PARAGRAPH_ROLE = "paragraph";
2209
+ var Paragraph = React.forwardRef(function Paragraph2(props, ref) {
2210
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native2.Text, { ref, role: PARAGRAPH_ROLE, ...props });
2211
+ });
2212
+ function makeHeading(level) {
2213
+ const extra = { "aria-level": level };
2214
+ const Heading = React.forwardRef(function Heading2(props, ref) {
2215
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native2.Text, { ref, accessibilityRole: "header", ...extra, ...props });
2216
+ });
2217
+ Heading.displayName = `H${level}`;
2218
+ return Heading;
2219
+ }
2220
+ var H1 = makeHeading(1);
2221
+ var H2 = makeHeading(2);
2222
+ var H3 = makeHeading(3);
2223
+ var H4 = makeHeading(4);
2224
+ var H5 = makeHeading(5);
2225
+ var H6 = makeHeading(6);
2182
2226
  // Annotate the CommonJS export names for ESM import in node:
2183
2227
  0 && (module.exports = {
2228
+ Button,
2229
+ H1,
2230
+ H2,
2231
+ H3,
2232
+ H4,
2233
+ H5,
2234
+ H6,
2235
+ Paragraph,
2184
2236
  ThemeProvider,
2185
2237
  applyKbachConfig,
2186
2238
  clsx,
@@ -1,8 +1,9 @@
1
1
  export { ColorEntry, ContainerConfig, ThemeConfig, defaultTheme, getTheme, setTheme } from './theme';
2
- export { C as ClassArray, a as ClassDictionary, b as ClassValue, c as ColorScale, d as ColorsAPI, K as KbachConfig, T as ThemeProvider, e as ThemeProviderProps, f as ThemeState, h as applyKbachConfig, i as clsx, r as resolveKbachConfig, u as useColors, j as useDynamicToken, k as useTheme } from './clsx-BLLSnqAa.js';
2
+ export { B as Button, a as ButtonProps, C as ClassArray, b as ClassDictionary, c as ClassValue, d as ColorScale, e as ColorsAPI, H as H1, f as H2, g as H3, h as H4, i as H5, j as H6, k as HeadingProps, K as KbachConfig, P as Paragraph, l as ParagraphProps, T as ThemeProvider, m as ThemeProviderProps, n as ThemeState, p as applyKbachConfig, q as clsx, r as resolveKbachConfig, u as useColors, s as useDynamicToken, t as useTheme } from './semanticElements-Bk3TB-vt.js';
3
3
  export { ThemeMode, getGlobalDarkMode, getGlobalThemeMode, setGlobalThemeMode, subscribeGlobalDarkMode, toggleGlobalDarkMode } from './darkModeStore';
4
4
  export { deleteDynamicToken, getDynamicToken, setDynamicToken, subscribeDynamicTokens } from './dynamicTokens';
5
5
  import 'react';
6
+ import 'react-native';
6
7
 
7
8
  /**
8
9
  * Resolves `classString` to CSS via the WASM engine, injects every returned
package/dist/index.web.js CHANGED
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
+ var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
5
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
8
  var __export = (target, all) => {
7
9
  for (var name in all)
@@ -15,11 +17,27 @@ var __copyProps = (to, from, except, desc) => {
15
17
  }
16
18
  return to;
17
19
  };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
18
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
29
 
20
30
  // src/index.web.ts
21
31
  var index_web_exports = {};
22
32
  __export(index_web_exports, {
33
+ Button: () => Button,
34
+ H1: () => H1,
35
+ H2: () => H2,
36
+ H3: () => H3,
37
+ H4: () => H4,
38
+ H5: () => H5,
39
+ H6: () => H6,
40
+ Paragraph: () => Paragraph,
23
41
  ThemeProvider: () => ThemeProvider,
24
42
  applyKbachConfig: () => applyKbachConfig,
25
43
  clsx: () => clsx,
@@ -500,8 +518,42 @@ function resolveClassValue(value) {
500
518
  }
501
519
  return "";
502
520
  }
521
+
522
+ // src/semanticElements.tsx
523
+ var React = __toESM(require("react"));
524
+ var import_react_native = require("react-native");
525
+ var import_jsx_runtime2 = require("react/jsx-runtime");
526
+ var Button = React.forwardRef(function Button2(props, ref) {
527
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native.Pressable, { ref, accessibilityRole: "button", ...props });
528
+ });
529
+ var PARAGRAPH_ROLE = "paragraph";
530
+ var Paragraph = React.forwardRef(function Paragraph2(props, ref) {
531
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native.Text, { ref, role: PARAGRAPH_ROLE, ...props });
532
+ });
533
+ function makeHeading(level) {
534
+ const extra = { "aria-level": level };
535
+ const Heading = React.forwardRef(function Heading2(props, ref) {
536
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native.Text, { ref, accessibilityRole: "header", ...extra, ...props });
537
+ });
538
+ Heading.displayName = `H${level}`;
539
+ return Heading;
540
+ }
541
+ var H1 = makeHeading(1);
542
+ var H2 = makeHeading(2);
543
+ var H3 = makeHeading(3);
544
+ var H4 = makeHeading(4);
545
+ var H5 = makeHeading(5);
546
+ var H6 = makeHeading(6);
503
547
  // Annotate the CommonJS export names for ESM import in node:
504
548
  0 && (module.exports = {
549
+ Button,
550
+ H1,
551
+ H2,
552
+ H3,
553
+ H4,
554
+ H5,
555
+ H6,
556
+ Paragraph,
505
557
  ThemeProvider,
506
558
  applyKbachConfig,
507
559
  clsx,
@@ -10,13 +10,13 @@ import {
10
10
  subscribeDynamicTokens,
11
11
  subscribeGlobalDarkMode,
12
12
  toggleGlobalDarkMode
13
- } from "./chunk-23JJORPW.mjs";
13
+ } from "./chunk-3JQAZNJK.mjs";
14
14
  import {
15
15
  defaultTheme,
16
16
  getTheme,
17
17
  resolveClassName,
18
18
  setTheme
19
- } from "./chunk-Z5Q3FGXR.mjs";
19
+ } from "./chunk-P75PP2QR.mjs";
20
20
 
21
21
  // src/config.ts
22
22
  function parseHexRgb(hex) {
@@ -262,7 +262,41 @@ function resolveClassValue(value) {
262
262
  }
263
263
  return "";
264
264
  }
265
+
266
+ // src/semanticElements.tsx
267
+ import * as React from "react";
268
+ import { Pressable, Text } from "react-native";
269
+ import { jsx as jsx2 } from "react/jsx-runtime";
270
+ var Button = React.forwardRef(function Button2(props, ref) {
271
+ return /* @__PURE__ */ jsx2(Pressable, { ref, accessibilityRole: "button", ...props });
272
+ });
273
+ var PARAGRAPH_ROLE = "paragraph";
274
+ var Paragraph = React.forwardRef(function Paragraph2(props, ref) {
275
+ return /* @__PURE__ */ jsx2(Text, { ref, role: PARAGRAPH_ROLE, ...props });
276
+ });
277
+ function makeHeading(level) {
278
+ const extra = { "aria-level": level };
279
+ const Heading = React.forwardRef(function Heading2(props, ref) {
280
+ return /* @__PURE__ */ jsx2(Text, { ref, accessibilityRole: "header", ...extra, ...props });
281
+ });
282
+ Heading.displayName = `H${level}`;
283
+ return Heading;
284
+ }
285
+ var H1 = makeHeading(1);
286
+ var H2 = makeHeading(2);
287
+ var H3 = makeHeading(3);
288
+ var H4 = makeHeading(4);
289
+ var H5 = makeHeading(5);
290
+ var H6 = makeHeading(6);
265
291
  export {
292
+ Button,
293
+ H1,
294
+ H2,
295
+ H3,
296
+ H4,
297
+ H5,
298
+ H6,
299
+ Paragraph,
266
300
  ThemeProvider,
267
301
  applyKbachConfig,
268
302
  clsx,
@@ -1,10 +1,10 @@
1
- import * as react from 'react';
1
+ import * as React from 'react';
2
2
  export { Fragment } from 'react';
3
3
 
4
4
  declare const jsxDEV: (type: unknown, props: Record<string, unknown> | null, key?: string, isStaticChildren?: boolean, source?: {
5
5
  fileName: string;
6
6
  lineNumber: number;
7
7
  columnNumber: number;
8
- }, self?: unknown) => react.ReactElement;
8
+ }, self?: unknown) => React.ReactElement;
9
9
 
10
10
  export { jsxDEV };
@@ -1,10 +1,10 @@
1
- import * as react from 'react';
1
+ import * as React from 'react';
2
2
  export { Fragment } from 'react';
3
3
 
4
4
  declare const jsxDEV: (type: unknown, props: Record<string, unknown> | null, key?: string, isStaticChildren?: boolean, source?: {
5
5
  fileName: string;
6
6
  lineNumber: number;
7
7
  columnNumber: number;
8
- }, self?: unknown) => react.ReactElement;
8
+ }, self?: unknown) => React.ReactElement;
9
9
 
10
10
  export { jsxDEV };
@@ -1,10 +1,10 @@
1
- import "./chunk-23JJORPW.mjs";
1
+ import "./chunk-3JQAZNJK.mjs";
2
2
  import {
3
3
  Fragment,
4
4
  jsx,
5
5
  jsxs
6
- } from "./chunk-HVGMZKV7.mjs";
7
- import "./chunk-Z5Q3FGXR.mjs";
6
+ } from "./chunk-TC6VSV44.mjs";
7
+ import "./chunk-P75PP2QR.mjs";
8
8
 
9
9
  // src/jsxRuntimeCore.ts
10
10
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
@@ -1,7 +1,7 @@
1
- import * as react from 'react';
1
+ import * as React from 'react';
2
2
  export { Fragment, JSX } from 'react';
3
3
 
4
- declare const jsx: (type: unknown, props: Record<string, unknown> | null, key?: string) => react.ReactElement;
5
- declare const jsxs: (type: unknown, props: Record<string, unknown> | null, key?: string) => react.ReactElement;
4
+ declare const jsx: (type: unknown, props: Record<string, unknown> | null, key?: string) => React.ReactElement;
5
+ declare const jsxs: (type: unknown, props: Record<string, unknown> | null, key?: string) => React.ReactElement;
6
6
 
7
7
  export { jsx, jsxs };
@@ -1,7 +1,7 @@
1
- import * as react from 'react';
1
+ import * as React from 'react';
2
2
  export { Fragment, JSX } from 'react';
3
3
 
4
- declare const jsx: (type: unknown, props: Record<string, unknown> | null, key?: string) => react.ReactElement;
5
- declare const jsxs: (type: unknown, props: Record<string, unknown> | null, key?: string) => react.ReactElement;
4
+ declare const jsx: (type: unknown, props: Record<string, unknown> | null, key?: string) => React.ReactElement;
5
+ declare const jsxs: (type: unknown, props: Record<string, unknown> | null, key?: string) => React.ReactElement;
6
6
 
7
7
  export { jsx, jsxs };
@@ -2,8 +2,8 @@ import {
2
2
  Fragment,
3
3
  jsx,
4
4
  jsxs
5
- } from "./chunk-HVGMZKV7.mjs";
6
- import "./chunk-Z5Q3FGXR.mjs";
5
+ } from "./chunk-TC6VSV44.mjs";
6
+ import "./chunk-P75PP2QR.mjs";
7
7
  export {
8
8
  Fragment,
9
9
  jsx,
@@ -1,7 +1,8 @@
1
1
  import { ThemeConfig, ContainerConfig } from './theme';
2
2
  import { ThemeMode } from './darkModeStore';
3
- import * as react from 'react';
3
+ import * as React from 'react';
4
4
  import { ReactNode } from 'react';
5
+ import { PressableProps, TextProps } from 'react-native';
5
6
 
6
7
  /**
7
8
  * A `kbach.config.js`-style theme customization — same shape as
@@ -165,7 +166,7 @@ interface ThemeProviderProps {
165
166
  * state — mounting more than one is very likely a mistake, so this warns
166
167
  * once in dev.
167
168
  */
168
- declare function ThemeProvider({ children, defaultMode, persist }: ThemeProviderProps): react.JSX.Element;
169
+ declare function ThemeProvider({ children, defaultMode, persist }: ThemeProviderProps): React.JSX.Element;
169
170
 
170
171
  interface ColorScale {
171
172
  /** `colors.blue[6]` -> raw value */
@@ -274,4 +275,60 @@ type ClassArray = ClassValue[];
274
275
  */
275
276
  declare function clsx(...inputs: ClassValue[]): string;
276
277
 
277
- export { type ClassArray as C, type KbachConfig as K, ThemeProvider as T, type ClassDictionary as a, type ClassValue as b, type ColorScale as c, type ColorsAPI as d, type ThemeProviderProps as e, type ThemeState as f, type ThemeStorageAdapter as g, applyKbachConfig as h, clsx as i, useDynamicToken as j, useTheme as k, resolveKbachConfig as r, useColors as u };
278
+ /**
279
+ * On Expo Web, `react-native-web` renders a bare `<View>`/`<Text>` as a
280
+ * plain `<div>`/`<span>` by default — confirmed directly in its own
281
+ * source (`exports/View/index.js`, `exports/Text/index.js`). That's
282
+ * NOTHING to do with Kbach: this package's jsx-runtime never reads or
283
+ * substitutes the JSX element type at all (`processElement` in
284
+ * `jsxRuntimeCore(.web).ts` only ever destructures `className`/`style`,
285
+ * passing `type` straight through unchanged) — whatever tag shows up is
286
+ * exactly whatever component the app wrote.
287
+ *
288
+ * `react-native-web` already has a real fix for this that nothing here
289
+ * needs to add: an `accessibilityRole`/`role` prop on ANY host component
290
+ * makes it render the matching real HTML element instead
291
+ * (`propsToAccessibilityComponent`, react-native-web's own
292
+ * AccessibilityUtil) — `button` -> `<button>`, `header` (+ `aria-level`,
293
+ * web-only) -> `<h1>`-`<h6>`, `paragraph` -> `<p>`, and so on. These
294
+ * components are JUST that prop, pre-set on the right underlying
295
+ * component — nothing Kbach-specific, and writing
296
+ * `<Pressable accessibilityRole="button">` directly instead of `<Button>`
297
+ * behaves identically. `className` keeps working on every one of these
298
+ * exactly like it does on a bare `Pressable`/`Text`.
299
+ *
300
+ * Deliberately NOT a `Div` or an `Input`: a plain `<View>` already IS the
301
+ * right generic container (there's no more-semantic alternative to ask
302
+ * for), and `<TextInput>` already renders a real `<input>` (or
303
+ * `<textarea>` when `multiline`) by default — react-native-web's own
304
+ * TextInput component picks that unconditionally, with no role needed at
305
+ * all. Only the cases that actually need a role to stop defaulting to
306
+ * `<div>`/`<span>` are here.
307
+ */
308
+ type ButtonProps = PressableProps;
309
+ /**
310
+ * A real `<button>` on Expo Web, a real accessible button on native —
311
+ * `<Pressable accessibilityRole="button">`, nothing else changed. Not the
312
+ * same thing as React Native's OWN built-in `Button` (a fixed-chrome,
313
+ * barely-styleable native control) — this is a styleable `Pressable`,
314
+ * matching how every other interactive element in a Kbach app is built.
315
+ */
316
+ declare const Button: React.ForwardRefExoticComponent<PressableProps & React.RefAttributes<any>>;
317
+ type ParagraphProps = TextProps;
318
+ /** A real `<p>` on Expo Web — `<Text role="paragraph">`, nothing else changed. */
319
+ declare const Paragraph: React.ForwardRefExoticComponent<TextProps & React.RefAttributes<any>>;
320
+ type HeadingProps = TextProps;
321
+ /** A real `<h1>` on Expo Web — `<Text accessibilityRole="header">` + the web-only level hint, nothing else changed. */
322
+ declare const H1: React.ForwardRefExoticComponent<TextProps & React.RefAttributes<any>>;
323
+ /** A real `<h2>` on Expo Web — see `H1`'s own doc comment. */
324
+ declare const H2: React.ForwardRefExoticComponent<TextProps & React.RefAttributes<any>>;
325
+ /** A real `<h3>` on Expo Web — see `H1`'s own doc comment. */
326
+ declare const H3: React.ForwardRefExoticComponent<TextProps & React.RefAttributes<any>>;
327
+ /** A real `<h4>` on Expo Web — see `H1`'s own doc comment. */
328
+ declare const H4: React.ForwardRefExoticComponent<TextProps & React.RefAttributes<any>>;
329
+ /** A real `<h5>` on Expo Web — see `H1`'s own doc comment. */
330
+ declare const H5: React.ForwardRefExoticComponent<TextProps & React.RefAttributes<any>>;
331
+ /** A real `<h6>` on Expo Web — see `H1`'s own doc comment. */
332
+ declare const H6: React.ForwardRefExoticComponent<TextProps & React.RefAttributes<any>>;
333
+
334
+ export { Button as B, type ClassArray as C, H1 as H, type KbachConfig as K, Paragraph as P, ThemeProvider as T, type ButtonProps as a, type ClassDictionary as b, type ClassValue as c, type ColorScale as d, type ColorsAPI as e, H2 as f, H3 as g, H4 as h, H5 as i, H6 as j, type HeadingProps as k, type ParagraphProps as l, type ThemeProviderProps as m, type ThemeState as n, type ThemeStorageAdapter as o, applyKbachConfig as p, clsx as q, resolveKbachConfig as r, useDynamicToken as s, useTheme as t, useColors as u };
package/dist/theme.js CHANGED
@@ -375,19 +375,28 @@ var defaultTheme = {
375
375
  // Empty by default, matching real Tailwind's own defaults.
376
376
  container: {}
377
377
  };
378
- var activeTheme = defaultTheme;
379
- var activeThemeJson = JSON.stringify(defaultTheme);
378
+ var GLOBAL_STATE_KEY = "__kbachReactNativeThemeState__";
379
+ function getThemeState() {
380
+ const g = globalThis;
381
+ let state = g[GLOBAL_STATE_KEY];
382
+ if (!state) {
383
+ state = { theme: defaultTheme, json: JSON.stringify(defaultTheme) };
384
+ g[GLOBAL_STATE_KEY] = state;
385
+ }
386
+ return state;
387
+ }
380
388
  function setTheme(theme) {
381
389
  const json = JSON.stringify(theme);
382
- if (json === activeThemeJson) return;
383
- activeTheme = theme;
384
- activeThemeJson = json;
390
+ const state = getThemeState();
391
+ if (json === state.json) return;
392
+ state.theme = theme;
393
+ state.json = json;
385
394
  }
386
395
  function getTheme() {
387
- return activeTheme;
396
+ return getThemeState().theme;
388
397
  }
389
398
  function getThemeJson() {
390
- return activeThemeJson;
399
+ return getThemeState().json;
391
400
  }
392
401
  // Annotate the CommonJS export names for ESM import in node:
393
402
  0 && (module.exports = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kbach/react-native",
3
- "version": "1.0.0-beta.52",
3
+ "version": "1.0.0-beta.53",
4
4
  "description": "Kbach's utility-class styling engine for React Native — the same class names as @kbach/react, resolved to a StyleSheet-ready style object via a Kotlin/JNI TurboModule (native), the same WASM engine @kbach/react uses (Expo Web / react-native-web), or a pure-JS fallback engine (Expo Go). Ships its own native Android module — one npm install, no separate native package. Beta. Native is Android-only (no iOS bridge yet); works with the React Native CLI, an Expo dev client, AND Expo Go (a reduced-coverage pure-JS fallback, since Expo Go can't load any custom native module).",
5
5
  "keywords": [
6
6
  "css",