@kbach/react 0.6.9 → 0.6.11
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 +31 -12
- package/dist/{chunk-XJFOY7HN.mjs → chunk-OWJUMH2V.mjs} +18 -10
- package/dist/{chunk-35CBHSAG.mjs → chunk-Z5SUFJ53.mjs} +1 -1
- package/dist/index.d.mts +19 -1
- package/dist/index.d.ts +19 -1
- package/dist/index.js +80 -62
- package/dist/index.mjs +27 -13
- package/dist/jsx-dev-runtime.js +56 -50
- package/dist/jsx-dev-runtime.mjs +2 -2
- package/dist/jsx-runtime.js +56 -50
- package/dist/jsx-runtime.mjs +2 -2
- package/dist/vite-plugin.js +2 -1
- package/dist/vite-plugin.mjs +2 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -20,7 +20,7 @@ npm install @kbach/react
|
|
|
20
20
|
|
|
21
21
|
## Setup
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
Step 1 is always required. After that, pick **one** of the two setups below — Quick if you just want styles working, Static CSS if you're shipping to production and/or using SSR.
|
|
24
24
|
|
|
25
25
|
### 1. Configure the JSX runtime
|
|
26
26
|
|
|
@@ -39,25 +39,30 @@ Don't also pass `jsxImportSource` to `@vitejs/plugin-react` (or any other bundle
|
|
|
39
39
|
|
|
40
40
|
Alternatives if you can't use tsconfig: a per-file `/** @jsxImportSource @kbach/react */` pragma comment, or `['@babel/preset-react', { runtime: 'automatic', importSource: '@kbach/react' }]` in `babel.config.js` for non-Vite/non-SWC toolchains.
|
|
41
41
|
|
|
42
|
-
###
|
|
42
|
+
### 2a. Quick setup (runtime CSS injection)
|
|
43
|
+
|
|
44
|
+
No build plugin, works with any bundler (Vite, webpack, Turbopack, Metro-for-web, …). Styles are generated and injected into a `<style>` tag by client-side JS the moment `ThemeProvider` mounts.
|
|
43
45
|
|
|
44
46
|
```jsx
|
|
45
|
-
import { ThemeProvider } from '@kbach/react';
|
|
47
|
+
import { ThemeProvider, KbachReset } from '@kbach/react';
|
|
46
48
|
|
|
47
49
|
export default function Root() {
|
|
48
50
|
return (
|
|
49
51
|
<ThemeProvider defaultMode="system">
|
|
52
|
+
<KbachReset />
|
|
50
53
|
<App />
|
|
51
54
|
</ThemeProvider>
|
|
52
55
|
);
|
|
53
56
|
}
|
|
54
57
|
```
|
|
55
58
|
|
|
56
|
-
|
|
59
|
+
`<KbachReset />` renders Kbach's base browser-default reset (borderless buttons/inputs, visible checkboxes/radios, no arrow-less `<select>`, etc. — see [CSS resets](#css-resets) below) as a plain `<style>` tag instead of waiting for the client-side injector. On a plain client-rendered app (Vite CSR, Create React App, …) it's a nice-to-have, since the injector already runs before first paint there. **On SSR** (Next.js, React Router framework mode, Remix, …) it's the difference between correct styling from the first byte and a flash of raw browser defaults (default button border, unstyled `<select>`, serif-ish fonts, …) that only clears up once hydration finishes — the server has no JS to run the injector, but it *can* render this component, since it's just JSX. Put it as high in `<head>` as your framework allows; the snippet above (right after `ThemeProvider` opens) works everywhere `<head>` isn't directly reachable.
|
|
60
|
+
|
|
61
|
+
That's the whole setup. `@kbach/react` ships its own `"use client"` directive, so both of these work directly in a Next.js App Router Server Component tree — no manual client wrapper needed.
|
|
57
62
|
|
|
58
|
-
###
|
|
63
|
+
### 2b. Static CSS setup (recommended for production / SSR, Vite only)
|
|
59
64
|
|
|
60
|
-
|
|
65
|
+
Zero runtime cost: a Vite plugin scans your source at build time and writes real CSS into a file you import, so styles ship as an ordinary stylesheet with no client-side generation step at all — nothing to flash-of-unstyled before. This is the better choice for any Vite-based SSR framework (React Router, SvelteKit-style meta-frameworks, etc.) over the Quick setup + `<KbachReset />` combination, since it covers *every* class, not just the base reset.
|
|
61
66
|
|
|
62
67
|
```ts
|
|
63
68
|
// vite.config.ts
|
|
@@ -88,15 +93,26 @@ Then create an empty `kbach.css` anywhere in your project and import it once in
|
|
|
88
93
|
import './kbach.css';
|
|
89
94
|
```
|
|
90
95
|
|
|
96
|
+
```jsx
|
|
97
|
+
import { ThemeProvider } from '@kbach/react';
|
|
98
|
+
// No <KbachReset /> needed — kbach.css already includes the same base reset.
|
|
99
|
+
|
|
100
|
+
export default function Root() {
|
|
101
|
+
return (
|
|
102
|
+
<ThemeProvider defaultMode="system">
|
|
103
|
+
<App />
|
|
104
|
+
</ThemeProvider>
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
91
109
|
The plugin scans your source files and writes generated CSS between the `/* kbach:start */`/`/* kbach:end */` markers. Importing `kbach.css` automatically disables runtime injection — all styles come from the file instead. On HMR, only the changed file is rescanned; unchanged tokens reuse cached CSS.
|
|
92
110
|
|
|
93
111
|
While it's scanning, the plugin also indexes every `.css`/`.scss`/`.sass`/`.less` file under the same directories and warns in the terminal (not the browser console) for any class that's neither a real Kbach utility nor defined anywhere in those stylesheets — likely a typo. A class you've defined yourself elsewhere (CSS Modules, styled-components, a third-party component's class) is recognized as soon as something in the project literally has a `.that-class-name` rule, so it won't get flagged just because Kbach itself doesn't know it. Each warning includes a `file:line:column` location that most terminals (VS Code's integrated terminal included) turn into a clickable link straight to that class.
|
|
94
112
|
|
|
95
113
|
## Next.js
|
|
96
114
|
|
|
97
|
-
Step 1 (tsconfig `jsxImportSource`)
|
|
98
|
-
|
|
99
|
-
The "Optional: static CSS" step above doesn't apply — Next.js builds with webpack/Turbopack, not Vite, so there's currently no static-CSS build step for it. Styles fall back to runtime injection, which means the same first-paint FOUC note above applies: expect a brief flash of unstyled content before hydration completes. This is a known limitation, not a per-project bug to work around.
|
|
115
|
+
Step 1 (tsconfig `jsxImportSource`) above applies as-is — Next.js's SWC compiler reads `jsxImportSource` from `tsconfig.json` the same way Vite does. For step 2, use **Quick setup (2a)** — Next.js builds with webpack/Turbopack, not Vite, so the static-CSS plugin (2b) doesn't apply. Render `<KbachReset />` once in the root App Router `layout.tsx` (inside `<head>`, or right after `<ThemeProvider>` opens) so Server Component HTML gets the base reset without waiting on hydration; `@kbach/react` shipping its own `"use client"` directive means both `ThemeProvider` and `KbachReset` work directly in that Server Component tree with no wrapper of your own needed.
|
|
100
116
|
|
|
101
117
|
## React Router
|
|
102
118
|
|
|
@@ -117,6 +133,8 @@ export default defineConfig({
|
|
|
117
133
|
|
|
118
134
|
If you do add `kbach()` to `vite.config.ts` and it detects both plugins active together, it prints a warning explaining exactly this at dev-server startup — so this doesn't have to be a silent, hard-to-diagnose blank page.
|
|
119
135
|
|
|
136
|
+
Framework mode is SSR, so skipping the static-CSS plugin (2b) in favor of Quick setup (2a) means the initial server-rendered HTML has no CSS at all until hydration — render `<KbachReset />` in `root.tsx`'s `<Layout>` (inside `<head>`, alongside `<Links />`/`<Meta />`) if you go that route, otherwise expect raw browser defaults (e.g. the native `<button>` border) on first paint.
|
|
137
|
+
|
|
120
138
|
**Library mode (client-only, `createBrowserRouter`/`<BrowserRouter>`):** no SSR involved — set it up exactly like any other Vite + React app. Since there's no meta-framework Vite plugin providing JSX handling here, you likely do need `@vitejs/plugin-react({ jsxImportSource: '@kbach/react' })` (or rely on tsconfig alone — Vite's default esbuild-based transform reads it too).
|
|
121
139
|
|
|
122
140
|
## API
|
|
@@ -355,7 +373,7 @@ Opacity modifier: `bg-blue-6/50` (50% alpha), `bg-blue-6/[0.15]` (arbitrary)
|
|
|
355
373
|
|
|
356
374
|
## CSS resets
|
|
357
375
|
|
|
358
|
-
Included automatically in `kbach.css
|
|
376
|
+
Included automatically in `kbach.css`, in runtime injection, and in `<KbachReset />` (all three render the exact same rules — pick whichever setup you're using from [Setup](#setup) above):
|
|
359
377
|
|
|
360
378
|
- `*, *::before, *::after { box-sizing: border-box; border-width: 0; border-style: solid; border-color: currentColor }` — border utilities like `border-2 border-gray-4` work on any element without also needing `border-solid`
|
|
361
379
|
- `body { margin: 0; padding: 0 }`
|
|
@@ -363,8 +381,9 @@ Included automatically in `kbach.css` and in runtime injection:
|
|
|
363
381
|
- `p`, `ul`, `ol` — margin and list style cleared
|
|
364
382
|
- `a` — color and underline cleared (inherit from parent)
|
|
365
383
|
- `img`, `video`, `svg` — `display: block; max-width: 100%`
|
|
366
|
-
- `
|
|
367
|
-
- `
|
|
384
|
+
- `button`, text-like `input`s (not checkbox/radio), `textarea` — appearance, border, padding cleared, so `border-`/`bg-`/`rounded-`/`p-` utilities fully restyle them
|
|
385
|
+
- `input[type=checkbox]`, `input[type=radio]`, `select` — native rendering kept (stripping it would hide the checkmark/dot/dropdown-arrow with nothing to replace them); only typography and spacing are normalized, and checkbox/radio/range get `accent-color: currentColor` so they still pick up your text color instead of the OS default blue
|
|
386
|
+
- `fieldset`, `table` — padding/margin/border-collapse cleared
|
|
368
387
|
|
|
369
388
|
## Configuration
|
|
370
389
|
|
|
@@ -2549,6 +2549,7 @@ function findOuterColon(s) {
|
|
|
2549
2549
|
}
|
|
2550
2550
|
|
|
2551
2551
|
// src/core/reset.ts
|
|
2552
|
+
var RESET_STYLE_ID = "kbach-reset";
|
|
2552
2553
|
var BASE_RESET = [
|
|
2553
2554
|
// border-style: solid means border-N utilities show a visible border without an extra border-solid class.
|
|
2554
2555
|
// border-width: 0 keeps all elements borderless by default.
|
|
@@ -2752,7 +2753,7 @@ function getGlobalStyleEl() {
|
|
|
2752
2753
|
}
|
|
2753
2754
|
function injectGlobalStyles(theme) {
|
|
2754
2755
|
if (typeof document === "undefined" || isRuntimeCSSDisabled()) return;
|
|
2755
|
-
const rules = [BASE_RESET];
|
|
2756
|
+
const rules = document.getElementById(RESET_STYLE_ID) ? [] : [BASE_RESET];
|
|
2756
2757
|
const ff = theme.fontFamily;
|
|
2757
2758
|
if (ff?.sans && ff.sans !== "System") {
|
|
2758
2759
|
const family = Array.isArray(ff.sans) ? ff.sans.join(", ") : ff.sans;
|
|
@@ -3693,19 +3694,24 @@ var InteractiveWrapper = forwardRef(
|
|
|
3693
3694
|
...checked !== void 0 ? { checked } : {},
|
|
3694
3695
|
style: finalStyle,
|
|
3695
3696
|
...!isNative && className ? { className } : {},
|
|
3696
|
-
// On web, onPointerDown/Up drive the wrapper's own pressed state (covers mouse + touch)
|
|
3697
|
-
//
|
|
3698
|
-
//
|
|
3699
|
-
//
|
|
3700
|
-
//
|
|
3701
|
-
//
|
|
3702
|
-
//
|
|
3697
|
+
// On web, onPointerDown/Up drive the wrapper's own pressed state (covers mouse + touch) —
|
|
3698
|
+
// onPressIn/onPressOut are RN-only prop names and are never forwarded here, even when
|
|
3699
|
+
// Component isn't a literal HTML tag string. A non-string Component on web is just as
|
|
3700
|
+
// likely to be an ordinary web component (React Router's <Link>, Next.js's <Link>, any
|
|
3701
|
+
// custom wrapper) as an actual react-native-web primitive — "not a string" alone was never
|
|
3702
|
+
// a reliable signal that onPressIn/onPressOut are wanted, and forwarding them
|
|
3703
|
+
// unconditionally made React DOM warn "Unknown event handler property" the moment any web
|
|
3704
|
+
// component got an interactive modifier (hover:, active:, …), which is the common case,
|
|
3705
|
+
// not the exception. (A real react-native-web primitive would additionally have this pair
|
|
3706
|
+
// of props silently vanish after hydration anyway, once the browser-only web-substitution
|
|
3707
|
+
// in jsx-runtime.tsx swaps it for a plain host tag — so keeping them pre-hydration would
|
|
3708
|
+
// only have traded one prop-mismatch warning for another.) Genuinely native code paths
|
|
3709
|
+
// still get them via the isNative branch below.
|
|
3703
3710
|
...!isNative ? {
|
|
3704
3711
|
onPointerDown: handlePointerDown,
|
|
3705
3712
|
onPointerUp: handlePointerUp,
|
|
3706
3713
|
onPointerLeave: handlePointerLeave,
|
|
3707
|
-
onPointerCancel: handlePointerCancel
|
|
3708
|
-
...typeof Component !== "string" ? { onPressIn, onPressOut } : {}
|
|
3714
|
+
onPointerCancel: handlePointerCancel
|
|
3709
3715
|
} : { onPressIn: handlePressIn, onPressOut: handlePressOut },
|
|
3710
3716
|
onMouseEnter: handleMouseEnter,
|
|
3711
3717
|
onMouseLeave: handleMouseLeave,
|
|
@@ -3720,6 +3726,8 @@ InteractiveWrapper.displayName = "Kbach.InteractiveWrapper";
|
|
|
3720
3726
|
export {
|
|
3721
3727
|
defaultColors,
|
|
3722
3728
|
defaultTheme,
|
|
3729
|
+
RESET_STYLE_ID,
|
|
3730
|
+
BASE_RESET,
|
|
3723
3731
|
isWeb,
|
|
3724
3732
|
isNative,
|
|
3725
3733
|
setResolveTarget,
|
package/dist/index.d.mts
CHANGED
|
@@ -271,6 +271,24 @@ interface ThemeProviderProps {
|
|
|
271
271
|
}
|
|
272
272
|
declare function ThemeProvider({ children, defaultMode, colorScheme, windowWidth: windowWidthProp, config: configOverride, disablePersistence, }: ThemeProviderProps): React__default.JSX.Element;
|
|
273
273
|
|
|
274
|
+
/**
|
|
275
|
+
* Renders Kbach's base browser-default reset (borderless button/input,
|
|
276
|
+
* visible checkbox/radio, no arrow-less <select>, etc.) as a plain <style>
|
|
277
|
+
* tag so it's part of the page's initial HTML.
|
|
278
|
+
*
|
|
279
|
+
* Runtime-only setups (no Vite plugin / static kbach.css) otherwise only get
|
|
280
|
+
* this reset once ThemeProvider's client-side effect runs — fine for a plain
|
|
281
|
+
* CSR app, but under SSR the server has no JS to run it, so the first paint
|
|
282
|
+
* ships with raw browser defaults (e.g. the native button border) until
|
|
283
|
+
* hydration catches up. Render this once, as high in <head> as your
|
|
284
|
+
* framework allows, to close that gap.
|
|
285
|
+
*
|
|
286
|
+
* Not needed if you're on the static-CSS setup — kbach.css already includes
|
|
287
|
+
* the same reset, and the runtime injector detects this tag and skips adding
|
|
288
|
+
* it a second time either way.
|
|
289
|
+
*/
|
|
290
|
+
declare function KbachReset(): React.JSX.Element | null;
|
|
291
|
+
|
|
274
292
|
interface StyledProps {
|
|
275
293
|
/** Additional utility classes applied on top of the base classes */
|
|
276
294
|
kb?: string;
|
|
@@ -417,4 +435,4 @@ declare function kb(classString: string, isDark?: boolean): StyleValue | string;
|
|
|
417
435
|
*/
|
|
418
436
|
declare function cx(...classes: Array<string | false | null | undefined>): string;
|
|
419
437
|
|
|
420
|
-
export { type ColorScale, type ColorsAPI, type FrameworkConfig, type InteractionState, InteractiveWrapper, type InteractiveWrapperProps, type ParsedClass, type PluginAPI, type ResolvedConfig, type ResolvedStyle, type StyleValue, type StyledProps, type ThemeConfig, ThemeContext, type ThemeContextValue, type ThemeMode, ThemeProvider, type ThemeProviderProps, buildConfig, clearCache, cx, defaultColors, defaultTheme, disableRuntimeCSS, flatten, getConfig, initConfig, kb, normalizeClassString, parseClass, parseClasses, resolve, setResolveTarget, splitClassTokens, styled, updateConfig, useBreakpoint, useColors, useGlobalDarkMode, useIsDark, useResolvedStyle, useResponsive, useStyles, useTheme, wrapColors };
|
|
438
|
+
export { type ColorScale, type ColorsAPI, type FrameworkConfig, type InteractionState, InteractiveWrapper, type InteractiveWrapperProps, KbachReset, type ParsedClass, type PluginAPI, type ResolvedConfig, type ResolvedStyle, type StyleValue, type StyledProps, type ThemeConfig, ThemeContext, type ThemeContextValue, type ThemeMode, ThemeProvider, type ThemeProviderProps, buildConfig, clearCache, cx, defaultColors, defaultTheme, disableRuntimeCSS, flatten, getConfig, initConfig, kb, normalizeClassString, parseClass, parseClasses, resolve, setResolveTarget, splitClassTokens, styled, updateConfig, useBreakpoint, useColors, useGlobalDarkMode, useIsDark, useResolvedStyle, useResponsive, useStyles, useTheme, wrapColors };
|
package/dist/index.d.ts
CHANGED
|
@@ -271,6 +271,24 @@ interface ThemeProviderProps {
|
|
|
271
271
|
}
|
|
272
272
|
declare function ThemeProvider({ children, defaultMode, colorScheme, windowWidth: windowWidthProp, config: configOverride, disablePersistence, }: ThemeProviderProps): React__default.JSX.Element;
|
|
273
273
|
|
|
274
|
+
/**
|
|
275
|
+
* Renders Kbach's base browser-default reset (borderless button/input,
|
|
276
|
+
* visible checkbox/radio, no arrow-less <select>, etc.) as a plain <style>
|
|
277
|
+
* tag so it's part of the page's initial HTML.
|
|
278
|
+
*
|
|
279
|
+
* Runtime-only setups (no Vite plugin / static kbach.css) otherwise only get
|
|
280
|
+
* this reset once ThemeProvider's client-side effect runs — fine for a plain
|
|
281
|
+
* CSR app, but under SSR the server has no JS to run it, so the first paint
|
|
282
|
+
* ships with raw browser defaults (e.g. the native button border) until
|
|
283
|
+
* hydration catches up. Render this once, as high in <head> as your
|
|
284
|
+
* framework allows, to close that gap.
|
|
285
|
+
*
|
|
286
|
+
* Not needed if you're on the static-CSS setup — kbach.css already includes
|
|
287
|
+
* the same reset, and the runtime injector detects this tag and skips adding
|
|
288
|
+
* it a second time either way.
|
|
289
|
+
*/
|
|
290
|
+
declare function KbachReset(): React.JSX.Element | null;
|
|
291
|
+
|
|
274
292
|
interface StyledProps {
|
|
275
293
|
/** Additional utility classes applied on top of the base classes */
|
|
276
294
|
kb?: string;
|
|
@@ -417,4 +435,4 @@ declare function kb(classString: string, isDark?: boolean): StyleValue | string;
|
|
|
417
435
|
*/
|
|
418
436
|
declare function cx(...classes: Array<string | false | null | undefined>): string;
|
|
419
437
|
|
|
420
|
-
export { type ColorScale, type ColorsAPI, type FrameworkConfig, type InteractionState, InteractiveWrapper, type InteractiveWrapperProps, type ParsedClass, type PluginAPI, type ResolvedConfig, type ResolvedStyle, type StyleValue, type StyledProps, type ThemeConfig, ThemeContext, type ThemeContextValue, type ThemeMode, ThemeProvider, type ThemeProviderProps, buildConfig, clearCache, cx, defaultColors, defaultTheme, disableRuntimeCSS, flatten, getConfig, initConfig, kb, normalizeClassString, parseClass, parseClasses, resolve, setResolveTarget, splitClassTokens, styled, updateConfig, useBreakpoint, useColors, useGlobalDarkMode, useIsDark, useResolvedStyle, useResponsive, useStyles, useTheme, wrapColors };
|
|
438
|
+
export { type ColorScale, type ColorsAPI, type FrameworkConfig, type InteractionState, InteractiveWrapper, type InteractiveWrapperProps, KbachReset, type ParsedClass, type PluginAPI, type ResolvedConfig, type ResolvedStyle, type StyleValue, type StyledProps, type ThemeConfig, ThemeContext, type ThemeContextValue, type ThemeMode, ThemeProvider, type ThemeProviderProps, buildConfig, clearCache, cx, defaultColors, defaultTheme, disableRuntimeCSS, flatten, getConfig, initConfig, kb, normalizeClassString, parseClass, parseClasses, resolve, setResolveTarget, splitClassTokens, styled, updateConfig, useBreakpoint, useColors, useGlobalDarkMode, useIsDark, useResolvedStyle, useResponsive, useStyles, useTheme, wrapColors };
|
package/dist/index.js
CHANGED
|
@@ -32,6 +32,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
32
32
|
var index_exports = {};
|
|
33
33
|
__export(index_exports, {
|
|
34
34
|
InteractiveWrapper: () => InteractiveWrapper,
|
|
35
|
+
KbachReset: () => KbachReset,
|
|
35
36
|
ThemeContext: () => ThemeContext,
|
|
36
37
|
ThemeProvider: () => ThemeProvider,
|
|
37
38
|
buildConfig: () => buildConfig,
|
|
@@ -627,6 +628,47 @@ var defaultTheme = {
|
|
|
627
628
|
}
|
|
628
629
|
};
|
|
629
630
|
|
|
631
|
+
// src/core/reset.ts
|
|
632
|
+
var RESET_STYLE_ID = "kbach-reset";
|
|
633
|
+
var BASE_RESET = [
|
|
634
|
+
// border-style: solid means border-N utilities show a visible border without an extra border-solid class.
|
|
635
|
+
// border-width: 0 keeps all elements borderless by default.
|
|
636
|
+
"*, *::before, *::after { box-sizing: border-box; border-width: 0; border-style: solid; border-color: currentColor; }",
|
|
637
|
+
"body { margin: 0; padding: 0; }",
|
|
638
|
+
"h1, h2, h3, h4, h5, h6 { margin: 0; font-size: inherit; font-weight: inherit; }",
|
|
639
|
+
"p { margin: 0; }",
|
|
640
|
+
"a { color: inherit; text-decoration: none; }",
|
|
641
|
+
"ul, ol { margin: 0; padding: 0; list-style: none; }",
|
|
642
|
+
"img, video, svg { display: block; max-width: 100%; }",
|
|
643
|
+
// appearance: none is deliberately NOT applied to checkbox/radio/select below —
|
|
644
|
+
// stripping it hides their native checkmark/arrow with nothing rendered in its
|
|
645
|
+
// place, leaving an invisible checkbox or an arrow-less <select> that looks like
|
|
646
|
+
// plain text. Text-like inputs, textarea, and button don't have that problem
|
|
647
|
+
// (their native chrome is just a skin around content utilities can fully
|
|
648
|
+
// restyle), so they keep the blank-canvas treatment.
|
|
649
|
+
"input:not([type='checkbox']):not([type='radio']), textarea { appearance: none; -webkit-appearance: none; background: transparent; padding: 0; margin: 0; font: inherit; color: inherit; line-height: inherit; }",
|
|
650
|
+
// Native checkbox/radio/range still get typography + spacing normalized, and
|
|
651
|
+
// accent-color re-themes their native indicator to the current text color
|
|
652
|
+
// instead of the browser/OS default blue, so they stay on-brand without
|
|
653
|
+
// needing to be rebuilt from scratch.
|
|
654
|
+
"input[type='checkbox'], input[type='radio'], input[type='range'] { margin: 0; font: inherit; accent-color: currentColor; }",
|
|
655
|
+
// select keeps its native chrome (border/background/arrow are all part of the
|
|
656
|
+
// same OS-drawn widget that appearance: none would blank out) — only typography
|
|
657
|
+
// and spacing are normalized so it still matches surrounding text.
|
|
658
|
+
"select { margin: 0; font: inherit; color: inherit; line-height: inherit; }",
|
|
659
|
+
"button { appearance: none; -webkit-appearance: none; background: transparent; padding: 0; margin: 0; font: inherit; color: inherit; cursor: pointer; line-height: inherit; text-align: inherit; }",
|
|
660
|
+
"button, [role='button'] { cursor: pointer; }",
|
|
661
|
+
":disabled { cursor: default; }",
|
|
662
|
+
"textarea { resize: vertical; }",
|
|
663
|
+
// Firefox renders placeholders at ~54% opacity by default; every other browser uses 1 —
|
|
664
|
+
// normalize to 1 so placeholder color is consistent and fully controlled by the placeholder: modifier.
|
|
665
|
+
"::placeholder { opacity: 1; }",
|
|
666
|
+
"input[type='number']::-webkit-inner-spin-button, input[type='number']::-webkit-outer-spin-button { margin: 0; }",
|
|
667
|
+
"input[type='search']::-webkit-search-decoration, input[type='search']::-webkit-search-cancel-button { -webkit-appearance: none; }",
|
|
668
|
+
"fieldset { padding: 0; margin: 0; }",
|
|
669
|
+
"table { border-collapse: collapse; border-spacing: 0; }"
|
|
670
|
+
].join("\n");
|
|
671
|
+
|
|
630
672
|
// src/core/cache.ts
|
|
631
673
|
var LRUCache = class {
|
|
632
674
|
constructor(capacity = 1e4, onEvict) {
|
|
@@ -2667,46 +2709,6 @@ function findOuterColon(s) {
|
|
|
2667
2709
|
return -1;
|
|
2668
2710
|
}
|
|
2669
2711
|
|
|
2670
|
-
// src/core/reset.ts
|
|
2671
|
-
var BASE_RESET = [
|
|
2672
|
-
// border-style: solid means border-N utilities show a visible border without an extra border-solid class.
|
|
2673
|
-
// border-width: 0 keeps all elements borderless by default.
|
|
2674
|
-
"*, *::before, *::after { box-sizing: border-box; border-width: 0; border-style: solid; border-color: currentColor; }",
|
|
2675
|
-
"body { margin: 0; padding: 0; }",
|
|
2676
|
-
"h1, h2, h3, h4, h5, h6 { margin: 0; font-size: inherit; font-weight: inherit; }",
|
|
2677
|
-
"p { margin: 0; }",
|
|
2678
|
-
"a { color: inherit; text-decoration: none; }",
|
|
2679
|
-
"ul, ol { margin: 0; padding: 0; list-style: none; }",
|
|
2680
|
-
"img, video, svg { display: block; max-width: 100%; }",
|
|
2681
|
-
// appearance: none is deliberately NOT applied to checkbox/radio/select below —
|
|
2682
|
-
// stripping it hides their native checkmark/arrow with nothing rendered in its
|
|
2683
|
-
// place, leaving an invisible checkbox or an arrow-less <select> that looks like
|
|
2684
|
-
// plain text. Text-like inputs, textarea, and button don't have that problem
|
|
2685
|
-
// (their native chrome is just a skin around content utilities can fully
|
|
2686
|
-
// restyle), so they keep the blank-canvas treatment.
|
|
2687
|
-
"input:not([type='checkbox']):not([type='radio']), textarea { appearance: none; -webkit-appearance: none; background: transparent; padding: 0; margin: 0; font: inherit; color: inherit; line-height: inherit; }",
|
|
2688
|
-
// Native checkbox/radio/range still get typography + spacing normalized, and
|
|
2689
|
-
// accent-color re-themes their native indicator to the current text color
|
|
2690
|
-
// instead of the browser/OS default blue, so they stay on-brand without
|
|
2691
|
-
// needing to be rebuilt from scratch.
|
|
2692
|
-
"input[type='checkbox'], input[type='radio'], input[type='range'] { margin: 0; font: inherit; accent-color: currentColor; }",
|
|
2693
|
-
// select keeps its native chrome (border/background/arrow are all part of the
|
|
2694
|
-
// same OS-drawn widget that appearance: none would blank out) — only typography
|
|
2695
|
-
// and spacing are normalized so it still matches surrounding text.
|
|
2696
|
-
"select { margin: 0; font: inherit; color: inherit; line-height: inherit; }",
|
|
2697
|
-
"button { appearance: none; -webkit-appearance: none; background: transparent; padding: 0; margin: 0; font: inherit; color: inherit; cursor: pointer; line-height: inherit; text-align: inherit; }",
|
|
2698
|
-
"button, [role='button'] { cursor: pointer; }",
|
|
2699
|
-
":disabled { cursor: default; }",
|
|
2700
|
-
"textarea { resize: vertical; }",
|
|
2701
|
-
// Firefox renders placeholders at ~54% opacity by default; every other browser uses 1 —
|
|
2702
|
-
// normalize to 1 so placeholder color is consistent and fully controlled by the placeholder: modifier.
|
|
2703
|
-
"::placeholder { opacity: 1; }",
|
|
2704
|
-
"input[type='number']::-webkit-inner-spin-button, input[type='number']::-webkit-outer-spin-button { margin: 0; }",
|
|
2705
|
-
"input[type='search']::-webkit-search-decoration, input[type='search']::-webkit-search-cancel-button { -webkit-appearance: none; }",
|
|
2706
|
-
"fieldset { padding: 0; margin: 0; }",
|
|
2707
|
-
"table { border-collapse: collapse; border-spacing: 0; }"
|
|
2708
|
-
].join("\n");
|
|
2709
|
-
|
|
2710
2712
|
// src/core/responsiveStore.ts
|
|
2711
2713
|
var RESPONSIVE_KEY = "__kbach_responsive__";
|
|
2712
2714
|
function getStore() {
|
|
@@ -2830,7 +2832,7 @@ function getGlobalStyleEl() {
|
|
|
2830
2832
|
}
|
|
2831
2833
|
function injectGlobalStyles(theme) {
|
|
2832
2834
|
if (typeof document === "undefined" || isRuntimeCSSDisabled()) return;
|
|
2833
|
-
const rules = [BASE_RESET];
|
|
2835
|
+
const rules = document.getElementById(RESET_STYLE_ID) ? [] : [BASE_RESET];
|
|
2834
2836
|
const ff = theme.fontFamily;
|
|
2835
2837
|
if (ff?.sans && ff.sans !== "System") {
|
|
2836
2838
|
const family = Array.isArray(ff.sans) ? ff.sans.join(", ") : ff.sans;
|
|
@@ -3524,6 +3526,13 @@ function ThemeProvider({
|
|
|
3524
3526
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ThemeContext.Provider, { value: contextValue, children });
|
|
3525
3527
|
}
|
|
3526
3528
|
|
|
3529
|
+
// src/KbachReset.tsx
|
|
3530
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
3531
|
+
function KbachReset() {
|
|
3532
|
+
if (isNative) return null;
|
|
3533
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("style", { id: RESET_STYLE_ID, children: BASE_RESET });
|
|
3534
|
+
}
|
|
3535
|
+
|
|
3527
3536
|
// src/styled.tsx
|
|
3528
3537
|
var import_react5 = __toESM(require("react"));
|
|
3529
3538
|
|
|
@@ -3979,25 +3988,28 @@ function styled(Component, baseClasses = "") {
|
|
|
3979
3988
|
...isWeb && combined ? { className: normalizeClassString(combined) } : {},
|
|
3980
3989
|
// Only attach state-tracking handlers when interactive modifiers are present.
|
|
3981
3990
|
// Always forward user-provided handlers to avoid silently swallowing them.
|
|
3982
|
-
//
|
|
3983
|
-
//
|
|
3984
|
-
//
|
|
3985
|
-
// string
|
|
3986
|
-
//
|
|
3987
|
-
//
|
|
3988
|
-
//
|
|
3989
|
-
|
|
3991
|
+
// Gated on isNative, not isWeb: isWeb is false during SSR too (no `window` there),
|
|
3992
|
+
// and onPressIn/onPressOut must stay excluded there as well — SSR is exactly where
|
|
3993
|
+
// getWebTag() above is skipped (it's isWeb-gated), so effectiveComponent may still be
|
|
3994
|
+
// a non-string RN-style reference server-side, and this used to forward onPressIn/
|
|
3995
|
+
// onPressOut to it unconditionally in that case (isWeb ? ... : ...'s false branch
|
|
3996
|
+
// covered both native AND SSR). onPressIn/onPressOut are RN-only prop names — a
|
|
3997
|
+
// non-string effectiveComponent on the web/SSR side is just as likely to be an
|
|
3998
|
+
// ordinary web component (React Router's <Link>, Next.js's <Link>, any custom
|
|
3999
|
+
// wrapper) as an actual react-native-web primitive, and "not a string" alone isn't a
|
|
4000
|
+
// reliable signal either way. Forwarding them made React DOM warn "Unknown event
|
|
4001
|
+
// handler property" the moment any such component got an interactive modifier
|
|
4002
|
+
// (hover:, active:, …), which is the common case, not the exception.
|
|
4003
|
+
...!isNative ? hasInteractive ? {
|
|
3990
4004
|
onPointerDown: handlePointerDown,
|
|
3991
4005
|
onPointerUp: handlePointerUp,
|
|
3992
4006
|
onPointerLeave: handlePointerLeave,
|
|
3993
|
-
onPointerCancel: handlePointerCancel
|
|
3994
|
-
...typeof effectiveComponent !== "string" ? { onPressIn, onPressOut } : {}
|
|
4007
|
+
onPointerCancel: handlePointerCancel
|
|
3995
4008
|
} : {
|
|
3996
4009
|
onPointerDown,
|
|
3997
4010
|
onPointerUp,
|
|
3998
4011
|
onPointerLeave,
|
|
3999
|
-
onPointerCancel
|
|
4000
|
-
...typeof effectiveComponent !== "string" ? { onPressIn, onPressOut } : {}
|
|
4012
|
+
onPointerCancel
|
|
4001
4013
|
} : hasInteractive ? { onPressIn: handlePressIn, onPressOut: handlePressOut } : { onPressIn, onPressOut },
|
|
4002
4014
|
onMouseEnter: hasInteractive ? handleMouseEnter : onMouseEnter,
|
|
4003
4015
|
onMouseLeave: hasInteractive ? handleMouseLeave : onMouseLeave,
|
|
@@ -4118,19 +4130,24 @@ var InteractiveWrapper = (0, import_react8.forwardRef)(
|
|
|
4118
4130
|
...checked !== void 0 ? { checked } : {},
|
|
4119
4131
|
style: finalStyle,
|
|
4120
4132
|
...!isNative && className ? { className } : {},
|
|
4121
|
-
// On web, onPointerDown/Up drive the wrapper's own pressed state (covers mouse + touch)
|
|
4122
|
-
//
|
|
4123
|
-
//
|
|
4124
|
-
//
|
|
4125
|
-
//
|
|
4126
|
-
//
|
|
4127
|
-
//
|
|
4133
|
+
// On web, onPointerDown/Up drive the wrapper's own pressed state (covers mouse + touch) —
|
|
4134
|
+
// onPressIn/onPressOut are RN-only prop names and are never forwarded here, even when
|
|
4135
|
+
// Component isn't a literal HTML tag string. A non-string Component on web is just as
|
|
4136
|
+
// likely to be an ordinary web component (React Router's <Link>, Next.js's <Link>, any
|
|
4137
|
+
// custom wrapper) as an actual react-native-web primitive — "not a string" alone was never
|
|
4138
|
+
// a reliable signal that onPressIn/onPressOut are wanted, and forwarding them
|
|
4139
|
+
// unconditionally made React DOM warn "Unknown event handler property" the moment any web
|
|
4140
|
+
// component got an interactive modifier (hover:, active:, …), which is the common case,
|
|
4141
|
+
// not the exception. (A real react-native-web primitive would additionally have this pair
|
|
4142
|
+
// of props silently vanish after hydration anyway, once the browser-only web-substitution
|
|
4143
|
+
// in jsx-runtime.tsx swaps it for a plain host tag — so keeping them pre-hydration would
|
|
4144
|
+
// only have traded one prop-mismatch warning for another.) Genuinely native code paths
|
|
4145
|
+
// still get them via the isNative branch below.
|
|
4128
4146
|
...!isNative ? {
|
|
4129
4147
|
onPointerDown: handlePointerDown,
|
|
4130
4148
|
onPointerUp: handlePointerUp,
|
|
4131
4149
|
onPointerLeave: handlePointerLeave,
|
|
4132
|
-
onPointerCancel: handlePointerCancel
|
|
4133
|
-
...typeof Component !== "string" ? { onPressIn, onPressOut } : {}
|
|
4150
|
+
onPointerCancel: handlePointerCancel
|
|
4134
4151
|
} : { onPressIn: handlePressIn, onPressOut: handlePressOut },
|
|
4135
4152
|
onMouseEnter: handleMouseEnter,
|
|
4136
4153
|
onMouseLeave: handleMouseLeave,
|
|
@@ -4157,6 +4174,7 @@ function cx(...classes) {
|
|
|
4157
4174
|
// Annotate the CommonJS export names for ESM import in node:
|
|
4158
4175
|
0 && (module.exports = {
|
|
4159
4176
|
InteractiveWrapper,
|
|
4177
|
+
KbachReset,
|
|
4160
4178
|
ThemeContext,
|
|
4161
4179
|
ThemeProvider,
|
|
4162
4180
|
buildConfig,
|
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import {
|
|
3
|
+
BASE_RESET,
|
|
3
4
|
EMPTY_BREAKPOINTS,
|
|
4
5
|
InteractiveWrapper,
|
|
6
|
+
RESET_STYLE_ID,
|
|
5
7
|
buildConfig,
|
|
6
8
|
chain,
|
|
7
9
|
clearCache,
|
|
@@ -15,6 +17,7 @@ import {
|
|
|
15
17
|
hasInteractiveBuckets,
|
|
16
18
|
hasResponsiveBuckets,
|
|
17
19
|
initConfig,
|
|
20
|
+
isNative,
|
|
18
21
|
isWeb,
|
|
19
22
|
normalizeClassString,
|
|
20
23
|
onConfigChange,
|
|
@@ -36,7 +39,7 @@ import {
|
|
|
36
39
|
useGlobalDarkMode,
|
|
37
40
|
useGlobalWidth,
|
|
38
41
|
useSyncExternalStore
|
|
39
|
-
} from "./chunk-
|
|
42
|
+
} from "./chunk-OWJUMH2V.mjs";
|
|
40
43
|
|
|
41
44
|
// src/context.tsx
|
|
42
45
|
import { createContext, useContext } from "react";
|
|
@@ -262,6 +265,13 @@ function ThemeProvider({
|
|
|
262
265
|
return /* @__PURE__ */ jsx(ThemeContext.Provider, { value: contextValue, children });
|
|
263
266
|
}
|
|
264
267
|
|
|
268
|
+
// src/KbachReset.tsx
|
|
269
|
+
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
270
|
+
function KbachReset() {
|
|
271
|
+
if (isNative) return null;
|
|
272
|
+
return /* @__PURE__ */ jsx2("style", { id: RESET_STYLE_ID, children: BASE_RESET });
|
|
273
|
+
}
|
|
274
|
+
|
|
265
275
|
// src/styled.tsx
|
|
266
276
|
import React2, {
|
|
267
277
|
forwardRef,
|
|
@@ -329,25 +339,28 @@ function styled(Component, baseClasses = "") {
|
|
|
329
339
|
...isWeb && combined ? { className: normalizeClassString(combined) } : {},
|
|
330
340
|
// Only attach state-tracking handlers when interactive modifiers are present.
|
|
331
341
|
// Always forward user-provided handlers to avoid silently swallowing them.
|
|
332
|
-
//
|
|
333
|
-
//
|
|
334
|
-
//
|
|
335
|
-
// string
|
|
336
|
-
//
|
|
337
|
-
//
|
|
338
|
-
//
|
|
339
|
-
|
|
342
|
+
// Gated on isNative, not isWeb: isWeb is false during SSR too (no `window` there),
|
|
343
|
+
// and onPressIn/onPressOut must stay excluded there as well — SSR is exactly where
|
|
344
|
+
// getWebTag() above is skipped (it's isWeb-gated), so effectiveComponent may still be
|
|
345
|
+
// a non-string RN-style reference server-side, and this used to forward onPressIn/
|
|
346
|
+
// onPressOut to it unconditionally in that case (isWeb ? ... : ...'s false branch
|
|
347
|
+
// covered both native AND SSR). onPressIn/onPressOut are RN-only prop names — a
|
|
348
|
+
// non-string effectiveComponent on the web/SSR side is just as likely to be an
|
|
349
|
+
// ordinary web component (React Router's <Link>, Next.js's <Link>, any custom
|
|
350
|
+
// wrapper) as an actual react-native-web primitive, and "not a string" alone isn't a
|
|
351
|
+
// reliable signal either way. Forwarding them made React DOM warn "Unknown event
|
|
352
|
+
// handler property" the moment any such component got an interactive modifier
|
|
353
|
+
// (hover:, active:, …), which is the common case, not the exception.
|
|
354
|
+
...!isNative ? hasInteractive ? {
|
|
340
355
|
onPointerDown: handlePointerDown,
|
|
341
356
|
onPointerUp: handlePointerUp,
|
|
342
357
|
onPointerLeave: handlePointerLeave,
|
|
343
|
-
onPointerCancel: handlePointerCancel
|
|
344
|
-
...typeof effectiveComponent !== "string" ? { onPressIn, onPressOut } : {}
|
|
358
|
+
onPointerCancel: handlePointerCancel
|
|
345
359
|
} : {
|
|
346
360
|
onPointerDown,
|
|
347
361
|
onPointerUp,
|
|
348
362
|
onPointerLeave,
|
|
349
|
-
onPointerCancel
|
|
350
|
-
...typeof effectiveComponent !== "string" ? { onPressIn, onPressOut } : {}
|
|
363
|
+
onPointerCancel
|
|
351
364
|
} : hasInteractive ? { onPressIn: handlePressIn, onPressOut: handlePressOut } : { onPressIn, onPressOut },
|
|
352
365
|
onMouseEnter: hasInteractive ? handleMouseEnter : onMouseEnter,
|
|
353
366
|
onMouseLeave: hasInteractive ? handleMouseLeave : onMouseLeave,
|
|
@@ -425,6 +438,7 @@ function cx(...classes) {
|
|
|
425
438
|
}
|
|
426
439
|
export {
|
|
427
440
|
InteractiveWrapper,
|
|
441
|
+
KbachReset,
|
|
428
442
|
ThemeContext,
|
|
429
443
|
ThemeProvider,
|
|
430
444
|
buildConfig,
|
package/dist/jsx-dev-runtime.js
CHANGED
|
@@ -583,6 +583,47 @@ var defaultTheme = {
|
|
|
583
583
|
}
|
|
584
584
|
};
|
|
585
585
|
|
|
586
|
+
// src/core/reset.ts
|
|
587
|
+
var RESET_STYLE_ID = "kbach-reset";
|
|
588
|
+
var BASE_RESET = [
|
|
589
|
+
// border-style: solid means border-N utilities show a visible border without an extra border-solid class.
|
|
590
|
+
// border-width: 0 keeps all elements borderless by default.
|
|
591
|
+
"*, *::before, *::after { box-sizing: border-box; border-width: 0; border-style: solid; border-color: currentColor; }",
|
|
592
|
+
"body { margin: 0; padding: 0; }",
|
|
593
|
+
"h1, h2, h3, h4, h5, h6 { margin: 0; font-size: inherit; font-weight: inherit; }",
|
|
594
|
+
"p { margin: 0; }",
|
|
595
|
+
"a { color: inherit; text-decoration: none; }",
|
|
596
|
+
"ul, ol { margin: 0; padding: 0; list-style: none; }",
|
|
597
|
+
"img, video, svg { display: block; max-width: 100%; }",
|
|
598
|
+
// appearance: none is deliberately NOT applied to checkbox/radio/select below —
|
|
599
|
+
// stripping it hides their native checkmark/arrow with nothing rendered in its
|
|
600
|
+
// place, leaving an invisible checkbox or an arrow-less <select> that looks like
|
|
601
|
+
// plain text. Text-like inputs, textarea, and button don't have that problem
|
|
602
|
+
// (their native chrome is just a skin around content utilities can fully
|
|
603
|
+
// restyle), so they keep the blank-canvas treatment.
|
|
604
|
+
"input:not([type='checkbox']):not([type='radio']), textarea { appearance: none; -webkit-appearance: none; background: transparent; padding: 0; margin: 0; font: inherit; color: inherit; line-height: inherit; }",
|
|
605
|
+
// Native checkbox/radio/range still get typography + spacing normalized, and
|
|
606
|
+
// accent-color re-themes their native indicator to the current text color
|
|
607
|
+
// instead of the browser/OS default blue, so they stay on-brand without
|
|
608
|
+
// needing to be rebuilt from scratch.
|
|
609
|
+
"input[type='checkbox'], input[type='radio'], input[type='range'] { margin: 0; font: inherit; accent-color: currentColor; }",
|
|
610
|
+
// select keeps its native chrome (border/background/arrow are all part of the
|
|
611
|
+
// same OS-drawn widget that appearance: none would blank out) — only typography
|
|
612
|
+
// and spacing are normalized so it still matches surrounding text.
|
|
613
|
+
"select { margin: 0; font: inherit; color: inherit; line-height: inherit; }",
|
|
614
|
+
"button { appearance: none; -webkit-appearance: none; background: transparent; padding: 0; margin: 0; font: inherit; color: inherit; cursor: pointer; line-height: inherit; text-align: inherit; }",
|
|
615
|
+
"button, [role='button'] { cursor: pointer; }",
|
|
616
|
+
":disabled { cursor: default; }",
|
|
617
|
+
"textarea { resize: vertical; }",
|
|
618
|
+
// Firefox renders placeholders at ~54% opacity by default; every other browser uses 1 —
|
|
619
|
+
// normalize to 1 so placeholder color is consistent and fully controlled by the placeholder: modifier.
|
|
620
|
+
"::placeholder { opacity: 1; }",
|
|
621
|
+
"input[type='number']::-webkit-inner-spin-button, input[type='number']::-webkit-outer-spin-button { margin: 0; }",
|
|
622
|
+
"input[type='search']::-webkit-search-decoration, input[type='search']::-webkit-search-cancel-button { -webkit-appearance: none; }",
|
|
623
|
+
"fieldset { padding: 0; margin: 0; }",
|
|
624
|
+
"table { border-collapse: collapse; border-spacing: 0; }"
|
|
625
|
+
].join("\n");
|
|
626
|
+
|
|
586
627
|
// src/core/cache.ts
|
|
587
628
|
var LRUCache = class {
|
|
588
629
|
constructor(capacity = 1e4, onEvict) {
|
|
@@ -2626,46 +2667,6 @@ function findOuterColon(s) {
|
|
|
2626
2667
|
return -1;
|
|
2627
2668
|
}
|
|
2628
2669
|
|
|
2629
|
-
// src/core/reset.ts
|
|
2630
|
-
var BASE_RESET = [
|
|
2631
|
-
// border-style: solid means border-N utilities show a visible border without an extra border-solid class.
|
|
2632
|
-
// border-width: 0 keeps all elements borderless by default.
|
|
2633
|
-
"*, *::before, *::after { box-sizing: border-box; border-width: 0; border-style: solid; border-color: currentColor; }",
|
|
2634
|
-
"body { margin: 0; padding: 0; }",
|
|
2635
|
-
"h1, h2, h3, h4, h5, h6 { margin: 0; font-size: inherit; font-weight: inherit; }",
|
|
2636
|
-
"p { margin: 0; }",
|
|
2637
|
-
"a { color: inherit; text-decoration: none; }",
|
|
2638
|
-
"ul, ol { margin: 0; padding: 0; list-style: none; }",
|
|
2639
|
-
"img, video, svg { display: block; max-width: 100%; }",
|
|
2640
|
-
// appearance: none is deliberately NOT applied to checkbox/radio/select below —
|
|
2641
|
-
// stripping it hides their native checkmark/arrow with nothing rendered in its
|
|
2642
|
-
// place, leaving an invisible checkbox or an arrow-less <select> that looks like
|
|
2643
|
-
// plain text. Text-like inputs, textarea, and button don't have that problem
|
|
2644
|
-
// (their native chrome is just a skin around content utilities can fully
|
|
2645
|
-
// restyle), so they keep the blank-canvas treatment.
|
|
2646
|
-
"input:not([type='checkbox']):not([type='radio']), textarea { appearance: none; -webkit-appearance: none; background: transparent; padding: 0; margin: 0; font: inherit; color: inherit; line-height: inherit; }",
|
|
2647
|
-
// Native checkbox/radio/range still get typography + spacing normalized, and
|
|
2648
|
-
// accent-color re-themes their native indicator to the current text color
|
|
2649
|
-
// instead of the browser/OS default blue, so they stay on-brand without
|
|
2650
|
-
// needing to be rebuilt from scratch.
|
|
2651
|
-
"input[type='checkbox'], input[type='radio'], input[type='range'] { margin: 0; font: inherit; accent-color: currentColor; }",
|
|
2652
|
-
// select keeps its native chrome (border/background/arrow are all part of the
|
|
2653
|
-
// same OS-drawn widget that appearance: none would blank out) — only typography
|
|
2654
|
-
// and spacing are normalized so it still matches surrounding text.
|
|
2655
|
-
"select { margin: 0; font: inherit; color: inherit; line-height: inherit; }",
|
|
2656
|
-
"button { appearance: none; -webkit-appearance: none; background: transparent; padding: 0; margin: 0; font: inherit; color: inherit; cursor: pointer; line-height: inherit; text-align: inherit; }",
|
|
2657
|
-
"button, [role='button'] { cursor: pointer; }",
|
|
2658
|
-
":disabled { cursor: default; }",
|
|
2659
|
-
"textarea { resize: vertical; }",
|
|
2660
|
-
// Firefox renders placeholders at ~54% opacity by default; every other browser uses 1 —
|
|
2661
|
-
// normalize to 1 so placeholder color is consistent and fully controlled by the placeholder: modifier.
|
|
2662
|
-
"::placeholder { opacity: 1; }",
|
|
2663
|
-
"input[type='number']::-webkit-inner-spin-button, input[type='number']::-webkit-outer-spin-button { margin: 0; }",
|
|
2664
|
-
"input[type='search']::-webkit-search-decoration, input[type='search']::-webkit-search-cancel-button { -webkit-appearance: none; }",
|
|
2665
|
-
"fieldset { padding: 0; margin: 0; }",
|
|
2666
|
-
"table { border-collapse: collapse; border-spacing: 0; }"
|
|
2667
|
-
].join("\n");
|
|
2668
|
-
|
|
2669
2670
|
// src/core/responsiveStore.ts
|
|
2670
2671
|
var RESPONSIVE_KEY = "__kbach_responsive__";
|
|
2671
2672
|
function getStore() {
|
|
@@ -2774,7 +2775,7 @@ function getGlobalStyleEl() {
|
|
|
2774
2775
|
}
|
|
2775
2776
|
function injectGlobalStyles(theme) {
|
|
2776
2777
|
if (typeof document === "undefined" || isRuntimeCSSDisabled()) return;
|
|
2777
|
-
const rules = [BASE_RESET];
|
|
2778
|
+
const rules = document.getElementById(RESET_STYLE_ID) ? [] : [BASE_RESET];
|
|
2778
2779
|
const ff = theme.fontFamily;
|
|
2779
2780
|
if (ff?.sans && ff.sans !== "System") {
|
|
2780
2781
|
const family = Array.isArray(ff.sans) ? ff.sans.join(", ") : ff.sans;
|
|
@@ -3390,19 +3391,24 @@ var InteractiveWrapper = (0, import_react2.forwardRef)(
|
|
|
3390
3391
|
...checked !== void 0 ? { checked } : {},
|
|
3391
3392
|
style: finalStyle,
|
|
3392
3393
|
...!isNative && className ? { className } : {},
|
|
3393
|
-
// On web, onPointerDown/Up drive the wrapper's own pressed state (covers mouse + touch)
|
|
3394
|
-
//
|
|
3395
|
-
//
|
|
3396
|
-
//
|
|
3397
|
-
//
|
|
3398
|
-
//
|
|
3399
|
-
//
|
|
3394
|
+
// On web, onPointerDown/Up drive the wrapper's own pressed state (covers mouse + touch) —
|
|
3395
|
+
// onPressIn/onPressOut are RN-only prop names and are never forwarded here, even when
|
|
3396
|
+
// Component isn't a literal HTML tag string. A non-string Component on web is just as
|
|
3397
|
+
// likely to be an ordinary web component (React Router's <Link>, Next.js's <Link>, any
|
|
3398
|
+
// custom wrapper) as an actual react-native-web primitive — "not a string" alone was never
|
|
3399
|
+
// a reliable signal that onPressIn/onPressOut are wanted, and forwarding them
|
|
3400
|
+
// unconditionally made React DOM warn "Unknown event handler property" the moment any web
|
|
3401
|
+
// component got an interactive modifier (hover:, active:, …), which is the common case,
|
|
3402
|
+
// not the exception. (A real react-native-web primitive would additionally have this pair
|
|
3403
|
+
// of props silently vanish after hydration anyway, once the browser-only web-substitution
|
|
3404
|
+
// in jsx-runtime.tsx swaps it for a plain host tag — so keeping them pre-hydration would
|
|
3405
|
+
// only have traded one prop-mismatch warning for another.) Genuinely native code paths
|
|
3406
|
+
// still get them via the isNative branch below.
|
|
3400
3407
|
...!isNative ? {
|
|
3401
3408
|
onPointerDown: handlePointerDown,
|
|
3402
3409
|
onPointerUp: handlePointerUp,
|
|
3403
3410
|
onPointerLeave: handlePointerLeave,
|
|
3404
|
-
onPointerCancel: handlePointerCancel
|
|
3405
|
-
...typeof Component !== "string" ? { onPressIn, onPressOut } : {}
|
|
3411
|
+
onPointerCancel: handlePointerCancel
|
|
3406
3412
|
} : { onPressIn: handlePressIn, onPressOut: handlePressOut },
|
|
3407
3413
|
onMouseEnter: handleMouseEnter,
|
|
3408
3414
|
onMouseLeave: handleMouseLeave,
|
package/dist/jsx-dev-runtime.mjs
CHANGED
|
@@ -3,8 +3,8 @@ import {
|
|
|
3
3
|
Fragment,
|
|
4
4
|
jsx,
|
|
5
5
|
jsxs
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-Z5SUFJ53.mjs";
|
|
7
|
+
import "./chunk-OWJUMH2V.mjs";
|
|
8
8
|
|
|
9
9
|
// src/jsx-dev-runtime.tsx
|
|
10
10
|
function jsxDEV(type, props, key, isStaticChildren, source, self) {
|
package/dist/jsx-runtime.js
CHANGED
|
@@ -584,6 +584,47 @@ var defaultTheme = {
|
|
|
584
584
|
}
|
|
585
585
|
};
|
|
586
586
|
|
|
587
|
+
// src/core/reset.ts
|
|
588
|
+
var RESET_STYLE_ID = "kbach-reset";
|
|
589
|
+
var BASE_RESET = [
|
|
590
|
+
// border-style: solid means border-N utilities show a visible border without an extra border-solid class.
|
|
591
|
+
// border-width: 0 keeps all elements borderless by default.
|
|
592
|
+
"*, *::before, *::after { box-sizing: border-box; border-width: 0; border-style: solid; border-color: currentColor; }",
|
|
593
|
+
"body { margin: 0; padding: 0; }",
|
|
594
|
+
"h1, h2, h3, h4, h5, h6 { margin: 0; font-size: inherit; font-weight: inherit; }",
|
|
595
|
+
"p { margin: 0; }",
|
|
596
|
+
"a { color: inherit; text-decoration: none; }",
|
|
597
|
+
"ul, ol { margin: 0; padding: 0; list-style: none; }",
|
|
598
|
+
"img, video, svg { display: block; max-width: 100%; }",
|
|
599
|
+
// appearance: none is deliberately NOT applied to checkbox/radio/select below —
|
|
600
|
+
// stripping it hides their native checkmark/arrow with nothing rendered in its
|
|
601
|
+
// place, leaving an invisible checkbox or an arrow-less <select> that looks like
|
|
602
|
+
// plain text. Text-like inputs, textarea, and button don't have that problem
|
|
603
|
+
// (their native chrome is just a skin around content utilities can fully
|
|
604
|
+
// restyle), so they keep the blank-canvas treatment.
|
|
605
|
+
"input:not([type='checkbox']):not([type='radio']), textarea { appearance: none; -webkit-appearance: none; background: transparent; padding: 0; margin: 0; font: inherit; color: inherit; line-height: inherit; }",
|
|
606
|
+
// Native checkbox/radio/range still get typography + spacing normalized, and
|
|
607
|
+
// accent-color re-themes their native indicator to the current text color
|
|
608
|
+
// instead of the browser/OS default blue, so they stay on-brand without
|
|
609
|
+
// needing to be rebuilt from scratch.
|
|
610
|
+
"input[type='checkbox'], input[type='radio'], input[type='range'] { margin: 0; font: inherit; accent-color: currentColor; }",
|
|
611
|
+
// select keeps its native chrome (border/background/arrow are all part of the
|
|
612
|
+
// same OS-drawn widget that appearance: none would blank out) — only typography
|
|
613
|
+
// and spacing are normalized so it still matches surrounding text.
|
|
614
|
+
"select { margin: 0; font: inherit; color: inherit; line-height: inherit; }",
|
|
615
|
+
"button { appearance: none; -webkit-appearance: none; background: transparent; padding: 0; margin: 0; font: inherit; color: inherit; cursor: pointer; line-height: inherit; text-align: inherit; }",
|
|
616
|
+
"button, [role='button'] { cursor: pointer; }",
|
|
617
|
+
":disabled { cursor: default; }",
|
|
618
|
+
"textarea { resize: vertical; }",
|
|
619
|
+
// Firefox renders placeholders at ~54% opacity by default; every other browser uses 1 —
|
|
620
|
+
// normalize to 1 so placeholder color is consistent and fully controlled by the placeholder: modifier.
|
|
621
|
+
"::placeholder { opacity: 1; }",
|
|
622
|
+
"input[type='number']::-webkit-inner-spin-button, input[type='number']::-webkit-outer-spin-button { margin: 0; }",
|
|
623
|
+
"input[type='search']::-webkit-search-decoration, input[type='search']::-webkit-search-cancel-button { -webkit-appearance: none; }",
|
|
624
|
+
"fieldset { padding: 0; margin: 0; }",
|
|
625
|
+
"table { border-collapse: collapse; border-spacing: 0; }"
|
|
626
|
+
].join("\n");
|
|
627
|
+
|
|
587
628
|
// src/core/cache.ts
|
|
588
629
|
var LRUCache = class {
|
|
589
630
|
constructor(capacity = 1e4, onEvict) {
|
|
@@ -2627,46 +2668,6 @@ function findOuterColon(s) {
|
|
|
2627
2668
|
return -1;
|
|
2628
2669
|
}
|
|
2629
2670
|
|
|
2630
|
-
// src/core/reset.ts
|
|
2631
|
-
var BASE_RESET = [
|
|
2632
|
-
// border-style: solid means border-N utilities show a visible border without an extra border-solid class.
|
|
2633
|
-
// border-width: 0 keeps all elements borderless by default.
|
|
2634
|
-
"*, *::before, *::after { box-sizing: border-box; border-width: 0; border-style: solid; border-color: currentColor; }",
|
|
2635
|
-
"body { margin: 0; padding: 0; }",
|
|
2636
|
-
"h1, h2, h3, h4, h5, h6 { margin: 0; font-size: inherit; font-weight: inherit; }",
|
|
2637
|
-
"p { margin: 0; }",
|
|
2638
|
-
"a { color: inherit; text-decoration: none; }",
|
|
2639
|
-
"ul, ol { margin: 0; padding: 0; list-style: none; }",
|
|
2640
|
-
"img, video, svg { display: block; max-width: 100%; }",
|
|
2641
|
-
// appearance: none is deliberately NOT applied to checkbox/radio/select below —
|
|
2642
|
-
// stripping it hides their native checkmark/arrow with nothing rendered in its
|
|
2643
|
-
// place, leaving an invisible checkbox or an arrow-less <select> that looks like
|
|
2644
|
-
// plain text. Text-like inputs, textarea, and button don't have that problem
|
|
2645
|
-
// (their native chrome is just a skin around content utilities can fully
|
|
2646
|
-
// restyle), so they keep the blank-canvas treatment.
|
|
2647
|
-
"input:not([type='checkbox']):not([type='radio']), textarea { appearance: none; -webkit-appearance: none; background: transparent; padding: 0; margin: 0; font: inherit; color: inherit; line-height: inherit; }",
|
|
2648
|
-
// Native checkbox/radio/range still get typography + spacing normalized, and
|
|
2649
|
-
// accent-color re-themes their native indicator to the current text color
|
|
2650
|
-
// instead of the browser/OS default blue, so they stay on-brand without
|
|
2651
|
-
// needing to be rebuilt from scratch.
|
|
2652
|
-
"input[type='checkbox'], input[type='radio'], input[type='range'] { margin: 0; font: inherit; accent-color: currentColor; }",
|
|
2653
|
-
// select keeps its native chrome (border/background/arrow are all part of the
|
|
2654
|
-
// same OS-drawn widget that appearance: none would blank out) — only typography
|
|
2655
|
-
// and spacing are normalized so it still matches surrounding text.
|
|
2656
|
-
"select { margin: 0; font: inherit; color: inherit; line-height: inherit; }",
|
|
2657
|
-
"button { appearance: none; -webkit-appearance: none; background: transparent; padding: 0; margin: 0; font: inherit; color: inherit; cursor: pointer; line-height: inherit; text-align: inherit; }",
|
|
2658
|
-
"button, [role='button'] { cursor: pointer; }",
|
|
2659
|
-
":disabled { cursor: default; }",
|
|
2660
|
-
"textarea { resize: vertical; }",
|
|
2661
|
-
// Firefox renders placeholders at ~54% opacity by default; every other browser uses 1 —
|
|
2662
|
-
// normalize to 1 so placeholder color is consistent and fully controlled by the placeholder: modifier.
|
|
2663
|
-
"::placeholder { opacity: 1; }",
|
|
2664
|
-
"input[type='number']::-webkit-inner-spin-button, input[type='number']::-webkit-outer-spin-button { margin: 0; }",
|
|
2665
|
-
"input[type='search']::-webkit-search-decoration, input[type='search']::-webkit-search-cancel-button { -webkit-appearance: none; }",
|
|
2666
|
-
"fieldset { padding: 0; margin: 0; }",
|
|
2667
|
-
"table { border-collapse: collapse; border-spacing: 0; }"
|
|
2668
|
-
].join("\n");
|
|
2669
|
-
|
|
2670
2671
|
// src/core/responsiveStore.ts
|
|
2671
2672
|
var RESPONSIVE_KEY = "__kbach_responsive__";
|
|
2672
2673
|
function getStore() {
|
|
@@ -2775,7 +2776,7 @@ function getGlobalStyleEl() {
|
|
|
2775
2776
|
}
|
|
2776
2777
|
function injectGlobalStyles(theme) {
|
|
2777
2778
|
if (typeof document === "undefined" || isRuntimeCSSDisabled()) return;
|
|
2778
|
-
const rules = [BASE_RESET];
|
|
2779
|
+
const rules = document.getElementById(RESET_STYLE_ID) ? [] : [BASE_RESET];
|
|
2779
2780
|
const ff = theme.fontFamily;
|
|
2780
2781
|
if (ff?.sans && ff.sans !== "System") {
|
|
2781
2782
|
const family = Array.isArray(ff.sans) ? ff.sans.join(", ") : ff.sans;
|
|
@@ -3391,19 +3392,24 @@ var InteractiveWrapper = (0, import_react2.forwardRef)(
|
|
|
3391
3392
|
...checked !== void 0 ? { checked } : {},
|
|
3392
3393
|
style: finalStyle,
|
|
3393
3394
|
...!isNative && className ? { className } : {},
|
|
3394
|
-
// On web, onPointerDown/Up drive the wrapper's own pressed state (covers mouse + touch)
|
|
3395
|
-
//
|
|
3396
|
-
//
|
|
3397
|
-
//
|
|
3398
|
-
//
|
|
3399
|
-
//
|
|
3400
|
-
//
|
|
3395
|
+
// On web, onPointerDown/Up drive the wrapper's own pressed state (covers mouse + touch) —
|
|
3396
|
+
// onPressIn/onPressOut are RN-only prop names and are never forwarded here, even when
|
|
3397
|
+
// Component isn't a literal HTML tag string. A non-string Component on web is just as
|
|
3398
|
+
// likely to be an ordinary web component (React Router's <Link>, Next.js's <Link>, any
|
|
3399
|
+
// custom wrapper) as an actual react-native-web primitive — "not a string" alone was never
|
|
3400
|
+
// a reliable signal that onPressIn/onPressOut are wanted, and forwarding them
|
|
3401
|
+
// unconditionally made React DOM warn "Unknown event handler property" the moment any web
|
|
3402
|
+
// component got an interactive modifier (hover:, active:, …), which is the common case,
|
|
3403
|
+
// not the exception. (A real react-native-web primitive would additionally have this pair
|
|
3404
|
+
// of props silently vanish after hydration anyway, once the browser-only web-substitution
|
|
3405
|
+
// in jsx-runtime.tsx swaps it for a plain host tag — so keeping them pre-hydration would
|
|
3406
|
+
// only have traded one prop-mismatch warning for another.) Genuinely native code paths
|
|
3407
|
+
// still get them via the isNative branch below.
|
|
3401
3408
|
...!isNative ? {
|
|
3402
3409
|
onPointerDown: handlePointerDown,
|
|
3403
3410
|
onPointerUp: handlePointerUp,
|
|
3404
3411
|
onPointerLeave: handlePointerLeave,
|
|
3405
|
-
onPointerCancel: handlePointerCancel
|
|
3406
|
-
...typeof Component !== "string" ? { onPressIn, onPressOut } : {}
|
|
3412
|
+
onPointerCancel: handlePointerCancel
|
|
3407
3413
|
} : { onPressIn: handlePressIn, onPressOut: handlePressOut },
|
|
3408
3414
|
onMouseEnter: handleMouseEnter,
|
|
3409
3415
|
onMouseLeave: handleMouseLeave,
|
package/dist/jsx-runtime.mjs
CHANGED
|
@@ -4,10 +4,10 @@ import {
|
|
|
4
4
|
_invalidateDefaultFontCache,
|
|
5
5
|
jsx,
|
|
6
6
|
jsxs
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-Z5SUFJ53.mjs";
|
|
8
8
|
import {
|
|
9
9
|
registerWebElement
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-OWJUMH2V.mjs";
|
|
11
11
|
export {
|
|
12
12
|
Fragment,
|
|
13
13
|
_invalidateDefaultFontCache,
|
package/dist/vite-plugin.js
CHANGED
|
@@ -60,6 +60,7 @@ function escapeCSSSelector(cls) {
|
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
// src/core/reset.ts
|
|
63
|
+
var RESET_STYLE_ID = "kbach-reset";
|
|
63
64
|
var BASE_RESET = [
|
|
64
65
|
// border-style: solid means border-N utilities show a visible border without an extra border-solid class.
|
|
65
66
|
// border-width: 0 keeps all elements borderless by default.
|
|
@@ -2677,7 +2678,7 @@ function getGlobalStyleEl() {
|
|
|
2677
2678
|
}
|
|
2678
2679
|
function injectGlobalStyles(theme) {
|
|
2679
2680
|
if (typeof document === "undefined" || isRuntimeCSSDisabled()) return;
|
|
2680
|
-
const rules = [BASE_RESET];
|
|
2681
|
+
const rules = document.getElementById(RESET_STYLE_ID) ? [] : [BASE_RESET];
|
|
2681
2682
|
const ff = theme.fontFamily;
|
|
2682
2683
|
if (ff?.sans && ff.sans !== "System") {
|
|
2683
2684
|
const family = Array.isArray(ff.sans) ? ff.sans.join(", ") : ff.sans;
|
package/dist/vite-plugin.mjs
CHANGED
|
@@ -26,6 +26,7 @@ function escapeCSSSelector(cls) {
|
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
// src/core/reset.ts
|
|
29
|
+
var RESET_STYLE_ID = "kbach-reset";
|
|
29
30
|
var BASE_RESET = [
|
|
30
31
|
// border-style: solid means border-N utilities show a visible border without an extra border-solid class.
|
|
31
32
|
// border-width: 0 keeps all elements borderless by default.
|
|
@@ -2643,7 +2644,7 @@ function getGlobalStyleEl() {
|
|
|
2643
2644
|
}
|
|
2644
2645
|
function injectGlobalStyles(theme) {
|
|
2645
2646
|
if (typeof document === "undefined" || isRuntimeCSSDisabled()) return;
|
|
2646
|
-
const rules = [BASE_RESET];
|
|
2647
|
+
const rules = document.getElementById(RESET_STYLE_ID) ? [] : [BASE_RESET];
|
|
2647
2648
|
const ff = theme.fontFamily;
|
|
2648
2649
|
if (ff?.sans && ff.sans !== "System") {
|
|
2649
2650
|
const family = Array.isArray(ff.sans) ? ff.sans.join(", ") : ff.sans;
|