@kbach/react-native 1.0.0-beta.51 → 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
@@ -9,6 +9,23 @@ cross-package overview, `kbach.config.js` reference, the color palette,
9
9
  and how the underlying engine is built, see the repo root's
10
10
  [AGENTS.md](https://github.com/semsakadanupol/kbach/blob/main/AGENTS.md).
11
11
 
12
+ > **Before writing a single class here, know these three things —
13
+ > Tailwind familiarity actively misleads on all three:**
14
+ >
15
+ > 1. Color shades are `1`–`12` (lightest→darkest), not Tailwind's
16
+ > `50`–`950` — `bg-blue-500` resolves to nothing; the real class is
17
+ > `bg-blue-6`. Full palette: root AGENTS.md §7.
18
+ > 2. `group-*`, `peer-*`, `has-[…]`, container queries, grid, and pseudo-
19
+ > elements (`before:`/`after:`) are real Tailwind syntax that PARSES
20
+ > here but applies **zero style, with no warning** — native has no
21
+ > cascade/DOM to support them. See §4's "Not supported" list. A typo
22
+ > DOES warn; an unsupported-but-valid utility does not — don't assume
23
+ > silence means it worked.
24
+ > 3. The babel plugin (§1 below) is required on **every** target,
25
+ > including Expo Go — without it `className` does literally nothing,
26
+ > silently, no error. This is the single most common real setup bug
27
+ > reported against this package.
28
+
12
29
  ---
13
30
 
14
31
  ## 1. Install + setup
@@ -220,6 +237,23 @@ Outside React: `getGlobalDarkMode()` / `toggleGlobalDarkMode()` /
220
237
  engine (a space splits the class token). Use underscores if you want them
221
238
  for readability: `w-[calc(100%_-_3rem)]`.
222
239
 
240
+ ### 7.1 Arbitrary values elsewhere — same px/rem-only rule
241
+
242
+ Not just `calc()`: any arbitrary value RN needs as a plain number (font
243
+ size, spacing, radii, ...) follows the identical rule. `text-[20px]` and
244
+ `text-[1.5rem]` work (`rem` × 16, same as everywhere else); `text-[2em]`,
245
+ `text-[50%]`, `text-[10vh]`/`text-[10vw]` don't — `em` needs the parent's
246
+ own cascaded font-size and `%`/viewport units need real layout, neither
247
+ of which exists at native resolve time — dropped with the same dev-only
248
+ `console.warn`, never a crash. Identical on Expo Go's JS-fallback engine
249
+ (`jsEngine/resolveStyle.ts` mirrors `resolve_style.rs`'s `rn_style_value`
250
+ exactly). Web (including Expo Web) has none of this restriction — real
251
+ CSS resolves every unit natively.
252
+
253
+ **`text-[…]` specifically needs `< 1.0.0-beta.52` excluded** — every
254
+ arbitrary `text-[…]` value, including a plain `text-[10px]`, silently
255
+ resolved nothing at all on native/Expo Go before that version (see §13).
256
+
223
257
  ## 8. Dynamic tokens (native counterpart to CSS custom properties)
224
258
 
225
259
  ```tsx
@@ -275,7 +309,7 @@ colors.get('brand'); // a custom color, typed as plain `string`
275
309
 
276
310
  `colors.blue[6]` returns the same value in both light and dark mode
277
311
  unless `blue-6` itself is defined in the theme as a `{ light, dark }` pair
278
- (§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
279
313
  `kbach.config.js` if you want it to differ by mode.
280
314
 
281
315
  `colors.brand` (a custom flat color) is typed `string | ColorScale`
@@ -312,10 +346,11 @@ and `react` at `projectRoot/node_modules/...`. A plain non-monorepo
312
346
  `setDynamicToken`, `getDynamicToken`, `deleteDynamicToken`,
313
347
  `subscribeDynamicTokens`, `useDynamicToken`, `clsx`, `getGlobalDarkMode`,
314
348
  `getGlobalThemeMode`, `setGlobalThemeMode`, `toggleGlobalDarkMode`,
315
- `subscribeGlobalDarkMode`. Types: `ThemeConfig`, `ColorEntry`,
316
- `ContainerConfig`, `StyleObject`, `KbachConfig`, `ThemeState`,
317
- `ThemeProviderProps`, `ThemeStorageAdapter`, `ThemeMode`, `ColorsAPI`,
318
- `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`.
319
354
 
320
355
  Subpath exports: `@kbach/react-native/babel-plugin`,
321
356
  `@kbach/react-native/jsx-runtime`, `@kbach/react-native/jsx-dev-runtime`.
@@ -345,6 +380,19 @@ Subpath exports: `@kbach/react-native/babel-plugin`,
345
380
  missing. It's required on every target, not just Android/dev-client
346
381
  builds; without it nothing routes `className` through this package's
347
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.
348
396
  - **`ERROR [Error: Unable to find node on an unmounted component.]` on
349
397
  Expo Fast Refresh, especially right after editing `kbach.config.js`** —
350
398
  stale `@kbach/react-native` (`< 1.0.0-beta.51`). Root cause: the babel
@@ -359,3 +407,53 @@ Subpath exports: `@kbach/react-native/babel-plugin`,
359
407
  React Native Fast Refresh race. `setTheme` is idempotent by content
360
408
  since beta.51 (compares against the theme's own JSON serialization
361
409
  before replacing it); update.
410
+ - **`text-[10px]` (or any other arbitrary `text-[…]` value) does nothing
411
+ on native or Expo Go** — stale `@kbach/react-native` (`< 1.0.0-beta.52`).
412
+ The native dispatcher's `resolve_text_native` (`resolvers/mod.rs`) never
413
+ got the arbitrary-value length check `color::resolve_text` (web) already
414
+ had — an arbitrary value skipped the font-size/align lookup entirely and
415
+ fell straight through to color resolution, which correctly rejected
416
+ "10px" as not a real color and silently dropped the whole declaration.
417
+ Fixed identically in both the Rust native dispatcher and its Expo Go JS-
418
+ fallback mirror (`jsEngine/resolveUtilityNative.ts`) in beta.52; update.
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-IJAXJVB4.mjs";
3
+ } from "./chunk-P75PP2QR.mjs";
4
4
 
5
5
  // src/darkModeStore.ts
6
6
  import { Appearance } from "react-native";