@kbach/react 1.0.0-beta.1 → 1.0.0-beta.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 +230 -73
- package/dist/chunk-4Y2QXNJY.mjs +115 -0
- package/dist/{chunk-FOQWQDF4.mjs → chunk-EOSN5CYG.mjs} +36 -9
- package/dist/chunk-J2M6QWJW.mjs +1385 -0
- package/dist/{chunk-AD3G6RHY.mjs → chunk-L6B4DTLD.mjs} +1 -1
- package/dist/{chunk-ROZXCQSM.mjs → chunk-ROKZPEHA.mjs} +1 -1
- package/dist/config-BQ_b-qxF.d.mts +105 -0
- package/dist/config-BQ_b-qxF.d.ts +105 -0
- package/dist/index.d.mts +65 -34
- package/dist/index.d.ts +65 -34
- package/dist/index.js +227 -43
- package/dist/index.mjs +90 -33
- package/dist/jsx-dev-runtime.js +36 -9
- package/dist/jsx-dev-runtime.mjs +3 -3
- package/dist/jsx-runtime.js +36 -9
- package/dist/jsx-runtime.mjs +3 -3
- package/dist/postcss-plugin.d.mts +36 -0
- package/dist/postcss-plugin.d.ts +36 -0
- package/dist/postcss-plugin.js +1152 -0
- package/dist/postcss-plugin.mjs +79 -0
- package/dist/vite-plugin.d.mts +108 -6
- package/dist/vite-plugin.d.ts +108 -6
- package/dist/vite-plugin.js +512 -225
- package/dist/vite-plugin.mjs +15 -1181
- package/package.json +13 -2
- package/dist/theme-BKAb78KP.d.mts +0 -20
- package/dist/theme-BKAb78KP.d.ts +0 -20
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/** A plain hex color, or a mode-aware pair auto-expanded into a light/dark class pair by the Rust engine. */
|
|
2
|
+
type ColorEntry = string | {
|
|
3
|
+
light: string;
|
|
4
|
+
dark: string;
|
|
5
|
+
};
|
|
6
|
+
type DarkModeStrategy = 'attribute' | 'class' | 'media';
|
|
7
|
+
/**
|
|
8
|
+
* Real Tailwind's `theme.container` config, mirroring
|
|
9
|
+
* `packages/core-engine/src/theme.rs`'s `ContainerConfig` exactly (same
|
|
10
|
+
* field names, `camelCase` on both sides via serde). `padding` is one
|
|
11
|
+
* uniform value applied at every breakpoint (including below the smallest
|
|
12
|
+
* one) rather than real Tailwind's optional per-breakpoint object form —
|
|
13
|
+
* the common case in practice, and simpler to reason about; a
|
|
14
|
+
* per-breakpoint padding map is a natural follow-up if ever needed.
|
|
15
|
+
*/
|
|
16
|
+
interface ContainerConfig {
|
|
17
|
+
center?: boolean;
|
|
18
|
+
padding?: string;
|
|
19
|
+
}
|
|
20
|
+
interface ThemeConfig {
|
|
21
|
+
/** e.g. "blue-6" -> "#2563eb", or "surface" -> { light, dark } */
|
|
22
|
+
colors: Record<string, ColorEntry>;
|
|
23
|
+
/** e.g. "4" -> 16 (px) */
|
|
24
|
+
spacing: Record<string, number>;
|
|
25
|
+
/** e.g. "sm" -> 640 (min-width px) */
|
|
26
|
+
screens: Record<string, number>;
|
|
27
|
+
/**
|
|
28
|
+
* e.g. "sans" -> "ui-sans-serif, system-ui, ...". Optional — the Rust
|
|
29
|
+
* engine's own `font_family_value` already carries a hardcoded fallback
|
|
30
|
+
* for "sans"/"serif"/"mono" (see its own doc comment) for when a theme
|
|
31
|
+
* omits this field (or a name within it) entirely, matching this field's
|
|
32
|
+
* `#[serde(default)]` on the Rust side. `defaultTheme` below still
|
|
33
|
+
* populates all three explicitly, matching the Rust fallback strings
|
|
34
|
+
* byte-for-byte, so a caller reading `defaultTheme.fontFamily.sans`
|
|
35
|
+
* (e.g. to extend rather than replace it) gets the real value rather
|
|
36
|
+
* than needing to already know the Rust-side fallback text.
|
|
37
|
+
*/
|
|
38
|
+
fontFamily?: Record<string, string>;
|
|
39
|
+
darkMode: DarkModeStrategy;
|
|
40
|
+
/** Optional, matching `ContainerConfig`'s own `#[serde(default)]` on the Rust side — an omitted theme.container behaves exactly like `{}`. */
|
|
41
|
+
container?: ContainerConfig;
|
|
42
|
+
}
|
|
43
|
+
declare const defaultTheme: ThemeConfig;
|
|
44
|
+
declare function setTheme(theme: ThemeConfig): void;
|
|
45
|
+
declare function getTheme(): ThemeConfig;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* A `kbach.config.js`-style theme customization, in one plain object — same
|
|
49
|
+
* `theme`/`extend`/`darkMode` shape real Tailwind's own config file uses,
|
|
50
|
+
* simplified from old-kbach's version (no plugins, no color alias chains
|
|
51
|
+
* with cycle detection, no live-update-listener store): a config object
|
|
52
|
+
* goes in, a resolved `ThemeConfig` comes out, via one PURE function
|
|
53
|
+
* (`resolveKbachConfig`) — same input always produces the same output, so
|
|
54
|
+
* nothing needs to stay "in sync" the way old-kbach's Babel-injected config
|
|
55
|
+
* singleton did. Call it identically from a Node.js build script
|
|
56
|
+
* (`vite.config.ts`) and from browser/app code (`applyKbachConfig`) and
|
|
57
|
+
* both get the exact same theme, no synchronization mechanism required.
|
|
58
|
+
*/
|
|
59
|
+
interface KbachConfig {
|
|
60
|
+
/** Applied on top of `defaultTheme`; `undefined` means "keep the default". */
|
|
61
|
+
darkMode?: DarkModeStrategy;
|
|
62
|
+
/**
|
|
63
|
+
* REPLACES the named section of `defaultTheme` entirely (e.g. supplying
|
|
64
|
+
* `theme.colors` drops the rest of the default palette) — use `extend`
|
|
65
|
+
* instead to add to the defaults rather than replace them. `container`
|
|
66
|
+
* isn't here (only under `extend` below) — it has no "defaults to
|
|
67
|
+
* replace" the way colors/spacing/screens/fontFamily do, since real
|
|
68
|
+
* Tailwind's own container config is inherently additive (center/padding
|
|
69
|
+
* on top of the always-present breakpoint ladder), so there's no
|
|
70
|
+
* meaningful distinction between "replace" and "extend" for it.
|
|
71
|
+
*/
|
|
72
|
+
theme?: Partial<Pick<ThemeConfig, 'colors' | 'spacing' | 'screens' | 'fontFamily'>>;
|
|
73
|
+
/** Merges INTO `defaultTheme` (or `theme` above, if also supplied) — the common case. */
|
|
74
|
+
extend?: {
|
|
75
|
+
/**
|
|
76
|
+
* A value is either a literal color (a hex string, or `{ light, dark }`
|
|
77
|
+
* — same mode-aware shape `useColors()`/`useTheme()` already support)
|
|
78
|
+
* or a REFERENCE to another color name, optionally with an opacity
|
|
79
|
+
* suffix. Two things can be referenced:
|
|
80
|
+
* - A BUILT-IN palette color, always available regardless of ordering
|
|
81
|
+
* (`accent: 'orange-5'`, `accentSoft: 'orange-5/50'`).
|
|
82
|
+
* - A custom color defined EARLIER in this same object
|
|
83
|
+
* (`{ brand: '#ff6b35', brandSoft: 'brand/30' }` — `brandSoft`
|
|
84
|
+
* resolves to `brand`'s own value at 30% opacity, computed once here
|
|
85
|
+
* rather than needing a `colors.alpha()` call at every use site).
|
|
86
|
+
* A string that doesn't match any known color name (built-in or
|
|
87
|
+
* already-defined-above) is treated as a literal CSS value instead
|
|
88
|
+
* (`accent: 'red'` — REAL CSS `red`, since there's no color named "red"
|
|
89
|
+
* to alias), never an error either way.
|
|
90
|
+
*/
|
|
91
|
+
colors?: Record<string, ColorEntry | string>;
|
|
92
|
+
spacing?: Record<string, number>;
|
|
93
|
+
screens?: Record<string, number>;
|
|
94
|
+
/** Named font stacks, e.g. `{ display: '"Cal Sans", sans-serif' }` — adds to (or overrides one of) `defaultTheme.fontFamily`'s three names. */
|
|
95
|
+
fontFamily?: Record<string, string>;
|
|
96
|
+
/** `{ center: true, padding: '2rem' }` — see `ContainerConfig`'s own doc comment. */
|
|
97
|
+
container?: ContainerConfig;
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
/** Merges a `KbachConfig` into `defaultTheme` — a pure function, no side effects. */
|
|
101
|
+
declare function resolveKbachConfig(config: KbachConfig): ThemeConfig;
|
|
102
|
+
/** `resolveKbachConfig()` + `setTheme()` in one call — the usual entry point from app code. Returns the resolved theme (e.g. to also hand to the Vite plugin's own `theme` option). */
|
|
103
|
+
declare function applyKbachConfig(config: KbachConfig): ThemeConfig;
|
|
104
|
+
|
|
105
|
+
export { type ColorEntry as C, type DarkModeStrategy as D, type KbachConfig as K, type ThemeConfig as T, type ContainerConfig as a, applyKbachConfig as b, defaultTheme as d, getTheme as g, resolveKbachConfig as r, setTheme as s };
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/** A plain hex color, or a mode-aware pair auto-expanded into a light/dark class pair by the Rust engine. */
|
|
2
|
+
type ColorEntry = string | {
|
|
3
|
+
light: string;
|
|
4
|
+
dark: string;
|
|
5
|
+
};
|
|
6
|
+
type DarkModeStrategy = 'attribute' | 'class' | 'media';
|
|
7
|
+
/**
|
|
8
|
+
* Real Tailwind's `theme.container` config, mirroring
|
|
9
|
+
* `packages/core-engine/src/theme.rs`'s `ContainerConfig` exactly (same
|
|
10
|
+
* field names, `camelCase` on both sides via serde). `padding` is one
|
|
11
|
+
* uniform value applied at every breakpoint (including below the smallest
|
|
12
|
+
* one) rather than real Tailwind's optional per-breakpoint object form —
|
|
13
|
+
* the common case in practice, and simpler to reason about; a
|
|
14
|
+
* per-breakpoint padding map is a natural follow-up if ever needed.
|
|
15
|
+
*/
|
|
16
|
+
interface ContainerConfig {
|
|
17
|
+
center?: boolean;
|
|
18
|
+
padding?: string;
|
|
19
|
+
}
|
|
20
|
+
interface ThemeConfig {
|
|
21
|
+
/** e.g. "blue-6" -> "#2563eb", or "surface" -> { light, dark } */
|
|
22
|
+
colors: Record<string, ColorEntry>;
|
|
23
|
+
/** e.g. "4" -> 16 (px) */
|
|
24
|
+
spacing: Record<string, number>;
|
|
25
|
+
/** e.g. "sm" -> 640 (min-width px) */
|
|
26
|
+
screens: Record<string, number>;
|
|
27
|
+
/**
|
|
28
|
+
* e.g. "sans" -> "ui-sans-serif, system-ui, ...". Optional — the Rust
|
|
29
|
+
* engine's own `font_family_value` already carries a hardcoded fallback
|
|
30
|
+
* for "sans"/"serif"/"mono" (see its own doc comment) for when a theme
|
|
31
|
+
* omits this field (or a name within it) entirely, matching this field's
|
|
32
|
+
* `#[serde(default)]` on the Rust side. `defaultTheme` below still
|
|
33
|
+
* populates all three explicitly, matching the Rust fallback strings
|
|
34
|
+
* byte-for-byte, so a caller reading `defaultTheme.fontFamily.sans`
|
|
35
|
+
* (e.g. to extend rather than replace it) gets the real value rather
|
|
36
|
+
* than needing to already know the Rust-side fallback text.
|
|
37
|
+
*/
|
|
38
|
+
fontFamily?: Record<string, string>;
|
|
39
|
+
darkMode: DarkModeStrategy;
|
|
40
|
+
/** Optional, matching `ContainerConfig`'s own `#[serde(default)]` on the Rust side — an omitted theme.container behaves exactly like `{}`. */
|
|
41
|
+
container?: ContainerConfig;
|
|
42
|
+
}
|
|
43
|
+
declare const defaultTheme: ThemeConfig;
|
|
44
|
+
declare function setTheme(theme: ThemeConfig): void;
|
|
45
|
+
declare function getTheme(): ThemeConfig;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* A `kbach.config.js`-style theme customization, in one plain object — same
|
|
49
|
+
* `theme`/`extend`/`darkMode` shape real Tailwind's own config file uses,
|
|
50
|
+
* simplified from old-kbach's version (no plugins, no color alias chains
|
|
51
|
+
* with cycle detection, no live-update-listener store): a config object
|
|
52
|
+
* goes in, a resolved `ThemeConfig` comes out, via one PURE function
|
|
53
|
+
* (`resolveKbachConfig`) — same input always produces the same output, so
|
|
54
|
+
* nothing needs to stay "in sync" the way old-kbach's Babel-injected config
|
|
55
|
+
* singleton did. Call it identically from a Node.js build script
|
|
56
|
+
* (`vite.config.ts`) and from browser/app code (`applyKbachConfig`) and
|
|
57
|
+
* both get the exact same theme, no synchronization mechanism required.
|
|
58
|
+
*/
|
|
59
|
+
interface KbachConfig {
|
|
60
|
+
/** Applied on top of `defaultTheme`; `undefined` means "keep the default". */
|
|
61
|
+
darkMode?: DarkModeStrategy;
|
|
62
|
+
/**
|
|
63
|
+
* REPLACES the named section of `defaultTheme` entirely (e.g. supplying
|
|
64
|
+
* `theme.colors` drops the rest of the default palette) — use `extend`
|
|
65
|
+
* instead to add to the defaults rather than replace them. `container`
|
|
66
|
+
* isn't here (only under `extend` below) — it has no "defaults to
|
|
67
|
+
* replace" the way colors/spacing/screens/fontFamily do, since real
|
|
68
|
+
* Tailwind's own container config is inherently additive (center/padding
|
|
69
|
+
* on top of the always-present breakpoint ladder), so there's no
|
|
70
|
+
* meaningful distinction between "replace" and "extend" for it.
|
|
71
|
+
*/
|
|
72
|
+
theme?: Partial<Pick<ThemeConfig, 'colors' | 'spacing' | 'screens' | 'fontFamily'>>;
|
|
73
|
+
/** Merges INTO `defaultTheme` (or `theme` above, if also supplied) — the common case. */
|
|
74
|
+
extend?: {
|
|
75
|
+
/**
|
|
76
|
+
* A value is either a literal color (a hex string, or `{ light, dark }`
|
|
77
|
+
* — same mode-aware shape `useColors()`/`useTheme()` already support)
|
|
78
|
+
* or a REFERENCE to another color name, optionally with an opacity
|
|
79
|
+
* suffix. Two things can be referenced:
|
|
80
|
+
* - A BUILT-IN palette color, always available regardless of ordering
|
|
81
|
+
* (`accent: 'orange-5'`, `accentSoft: 'orange-5/50'`).
|
|
82
|
+
* - A custom color defined EARLIER in this same object
|
|
83
|
+
* (`{ brand: '#ff6b35', brandSoft: 'brand/30' }` — `brandSoft`
|
|
84
|
+
* resolves to `brand`'s own value at 30% opacity, computed once here
|
|
85
|
+
* rather than needing a `colors.alpha()` call at every use site).
|
|
86
|
+
* A string that doesn't match any known color name (built-in or
|
|
87
|
+
* already-defined-above) is treated as a literal CSS value instead
|
|
88
|
+
* (`accent: 'red'` — REAL CSS `red`, since there's no color named "red"
|
|
89
|
+
* to alias), never an error either way.
|
|
90
|
+
*/
|
|
91
|
+
colors?: Record<string, ColorEntry | string>;
|
|
92
|
+
spacing?: Record<string, number>;
|
|
93
|
+
screens?: Record<string, number>;
|
|
94
|
+
/** Named font stacks, e.g. `{ display: '"Cal Sans", sans-serif' }` — adds to (or overrides one of) `defaultTheme.fontFamily`'s three names. */
|
|
95
|
+
fontFamily?: Record<string, string>;
|
|
96
|
+
/** `{ center: true, padding: '2rem' }` — see `ContainerConfig`'s own doc comment. */
|
|
97
|
+
container?: ContainerConfig;
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
/** Merges a `KbachConfig` into `defaultTheme` — a pure function, no side effects. */
|
|
101
|
+
declare function resolveKbachConfig(config: KbachConfig): ThemeConfig;
|
|
102
|
+
/** `resolveKbachConfig()` + `setTheme()` in one call — the usual entry point from app code. Returns the resolved theme (e.g. to also hand to the Vite plugin's own `theme` option). */
|
|
103
|
+
declare function applyKbachConfig(config: KbachConfig): ThemeConfig;
|
|
104
|
+
|
|
105
|
+
export { type ColorEntry as C, type DarkModeStrategy as D, type KbachConfig as K, type ThemeConfig as T, type ContainerConfig as a, applyKbachConfig as b, defaultTheme as d, getTheme as g, resolveKbachConfig as r, setTheme as s };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { T as ThemeConfig, d as defaultTheme, g as getTheme, s as setTheme } from './
|
|
1
|
+
export { C as ColorEntry, a as ContainerConfig, D as DarkModeStrategy, K as KbachConfig, T as ThemeConfig, b as applyKbachConfig, d as defaultTheme, g as getTheme, r as resolveKbachConfig, s as setTheme } from './config-BQ_b-qxF.mjs';
|
|
2
2
|
import * as react from 'react';
|
|
3
3
|
import { ReactNode } from 'react';
|
|
4
4
|
|
|
@@ -61,16 +61,23 @@ declare function setGlobalThemeMode(nextMode: ThemeMode): void;
|
|
|
61
61
|
declare function toggleGlobalDarkMode(): void;
|
|
62
62
|
declare function subscribeGlobalDarkMode(listener: () => void): () => void;
|
|
63
63
|
|
|
64
|
+
interface ThemeState {
|
|
65
|
+
mode: ThemeMode;
|
|
66
|
+
isDark: boolean;
|
|
67
|
+
setMode: (mode: ThemeMode) => void;
|
|
68
|
+
toggle: () => void;
|
|
69
|
+
}
|
|
64
70
|
/**
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
71
|
+
* The one hook for reading and writing Kbach's dark-mode state. Reads
|
|
72
|
+
* `darkModeStore.ts`'s global store directly via `useSyncExternalStore` —
|
|
73
|
+
* that module-level store, not React Context, is the actual source of
|
|
74
|
+
* truth (every provider used to just mirror it into a Context value), so
|
|
75
|
+
* this works from ANY component, with or without a `<ThemeProvider>`
|
|
76
|
+
* mounted anywhere in the tree. `<ThemeProvider>` still exists, but purely
|
|
77
|
+
* as an optional convenience for seeding an app's initial `defaultMode` —
|
|
78
|
+
* see its own doc comment.
|
|
72
79
|
*/
|
|
73
|
-
declare function
|
|
80
|
+
declare function useTheme(): ThemeState;
|
|
74
81
|
|
|
75
82
|
interface ThemeProviderProps {
|
|
76
83
|
children: ReactNode;
|
|
@@ -82,36 +89,60 @@ interface ThemeProviderProps {
|
|
|
82
89
|
defaultMode?: ThemeMode;
|
|
83
90
|
}
|
|
84
91
|
/**
|
|
85
|
-
* Optional
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
* environments where it's unavailable).
|
|
92
|
+
* Optional — `useTheme()` reads `darkModeStore.ts`'s global store directly
|
|
93
|
+
* and works anywhere without this mounted at all. The only thing this
|
|
94
|
+
* component does is seed that store's initial `defaultMode` once, for apps
|
|
95
|
+
* that want to declare a startup default in JSX rather than calling
|
|
96
|
+
* `setGlobalThemeMode()` imperatively before their first render. It
|
|
97
|
+
* renders `children` as-is — no Context.Provider, since there's no value
|
|
98
|
+
* left to distribute; `useTheme()` never reads from Context.
|
|
93
99
|
*
|
|
94
|
-
* Because the store is global, MULTIPLE mounted providers
|
|
95
|
-
* same
|
|
96
|
-
*
|
|
97
|
-
*
|
|
98
|
-
* in dev, matching old-kbach's identical guard.
|
|
100
|
+
* Because the store is global, MULTIPLE mounted providers would each try
|
|
101
|
+
* to seed the exact same store rather than getting their own scoped
|
|
102
|
+
* state — mounting more than one is very likely a mistake, so this warns
|
|
103
|
+
* once in dev.
|
|
99
104
|
*/
|
|
100
105
|
declare function ThemeProvider({ children, defaultMode }: ThemeProviderProps): react.JSX.Element;
|
|
101
106
|
|
|
102
|
-
interface
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
+
interface ColorScale {
|
|
108
|
+
/** `colors.blue[6]` -> raw value */
|
|
109
|
+
readonly [shade: number]: string;
|
|
110
|
+
/** `colors.blue['6/50']` -> shade 6 at 50% opacity */
|
|
111
|
+
readonly [key: string]: string;
|
|
107
112
|
}
|
|
113
|
+
type ColorsAPI = {
|
|
114
|
+
/** `colors.white`, `colors.blue` (a shade family), `colors.surface`, ... */
|
|
115
|
+
readonly [name: string]: string | ColorScale;
|
|
116
|
+
} & {
|
|
117
|
+
/**
|
|
118
|
+
* Applies an opacity (0–100) to any color string this hook can return —
|
|
119
|
+
* a hex, `rgb()`/`rgba()`, or one of this hook's own
|
|
120
|
+
* `rgb(var(--kb-color-x))` mode-aware references.
|
|
121
|
+
*/
|
|
122
|
+
readonly alpha: (color: string, opacity?: number) => string;
|
|
123
|
+
};
|
|
108
124
|
/**
|
|
109
|
-
*
|
|
110
|
-
*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
*
|
|
125
|
+
* Resolved theme colors as real values — for anywhere you need an actual
|
|
126
|
+
* color (an SVG `fill`, a canvas context, a chart library prop), not a
|
|
127
|
+
* `className`. Ported from old-kbach's `useColors()`
|
|
128
|
+
* (`old-kbach/packages/ui/src/useColors.ts`), adapted to this engine's flat
|
|
129
|
+
* `"blue-6"`-keyed palette (`colors.blue[6]` looks up `"blue-6"`).
|
|
130
|
+
*
|
|
131
|
+
* Any color — a shade-family entry like `"blue-6"` or a standalone name
|
|
132
|
+
* like `"surface"` — can be defined in the theme as either a plain string
|
|
133
|
+
* (static, same in both modes) or a `{ light, dark }` pair — fully manual,
|
|
134
|
+
* no automatic shade-shifting or other assumption about what a "dark
|
|
135
|
+
* variant" should be; see `resolveEntry`'s own doc comment for how a
|
|
136
|
+
* `{ light, dark }` entry resolves.
|
|
137
|
+
*
|
|
138
|
+
* ```ts
|
|
139
|
+
* const colors = useColors();
|
|
140
|
+
* colors.blue[6]; // "#3b82f6" — static, same value in both modes
|
|
141
|
+
* colors.blue['6/50']; // same, at 50% opacity
|
|
142
|
+
* colors.surface; // "rgb(var(--kb-color-surface))" if defined as { light, dark }
|
|
143
|
+
* colors.alpha(colors.surface, 50); // "rgba(var(--kb-color-surface), 0.5)"
|
|
144
|
+
* ```
|
|
114
145
|
*/
|
|
115
|
-
declare function
|
|
146
|
+
declare function useColors(): ColorsAPI;
|
|
116
147
|
|
|
117
|
-
export {
|
|
148
|
+
export { type ColorScale, type ColorsAPI, KbachReset, type ThemeMode, ThemeProvider, type ThemeProviderProps, type ThemeState, disableRuntimeCSS, getGlobalDarkMode, getGlobalThemeMode, initKbach, isKbachReady, isRuntimeCSSDisabled, kb, setGlobalThemeMode, subscribeGlobalDarkMode, toggleGlobalDarkMode, useColors, useTheme };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { T as ThemeConfig, d as defaultTheme, g as getTheme, s as setTheme } from './
|
|
1
|
+
export { C as ColorEntry, a as ContainerConfig, D as DarkModeStrategy, K as KbachConfig, T as ThemeConfig, b as applyKbachConfig, d as defaultTheme, g as getTheme, r as resolveKbachConfig, s as setTheme } from './config-BQ_b-qxF.js';
|
|
2
2
|
import * as react from 'react';
|
|
3
3
|
import { ReactNode } from 'react';
|
|
4
4
|
|
|
@@ -61,16 +61,23 @@ declare function setGlobalThemeMode(nextMode: ThemeMode): void;
|
|
|
61
61
|
declare function toggleGlobalDarkMode(): void;
|
|
62
62
|
declare function subscribeGlobalDarkMode(listener: () => void): () => void;
|
|
63
63
|
|
|
64
|
+
interface ThemeState {
|
|
65
|
+
mode: ThemeMode;
|
|
66
|
+
isDark: boolean;
|
|
67
|
+
setMode: (mode: ThemeMode) => void;
|
|
68
|
+
toggle: () => void;
|
|
69
|
+
}
|
|
64
70
|
/**
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
71
|
+
* The one hook for reading and writing Kbach's dark-mode state. Reads
|
|
72
|
+
* `darkModeStore.ts`'s global store directly via `useSyncExternalStore` —
|
|
73
|
+
* that module-level store, not React Context, is the actual source of
|
|
74
|
+
* truth (every provider used to just mirror it into a Context value), so
|
|
75
|
+
* this works from ANY component, with or without a `<ThemeProvider>`
|
|
76
|
+
* mounted anywhere in the tree. `<ThemeProvider>` still exists, but purely
|
|
77
|
+
* as an optional convenience for seeding an app's initial `defaultMode` —
|
|
78
|
+
* see its own doc comment.
|
|
72
79
|
*/
|
|
73
|
-
declare function
|
|
80
|
+
declare function useTheme(): ThemeState;
|
|
74
81
|
|
|
75
82
|
interface ThemeProviderProps {
|
|
76
83
|
children: ReactNode;
|
|
@@ -82,36 +89,60 @@ interface ThemeProviderProps {
|
|
|
82
89
|
defaultMode?: ThemeMode;
|
|
83
90
|
}
|
|
84
91
|
/**
|
|
85
|
-
* Optional
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
* environments where it's unavailable).
|
|
92
|
+
* Optional — `useTheme()` reads `darkModeStore.ts`'s global store directly
|
|
93
|
+
* and works anywhere without this mounted at all. The only thing this
|
|
94
|
+
* component does is seed that store's initial `defaultMode` once, for apps
|
|
95
|
+
* that want to declare a startup default in JSX rather than calling
|
|
96
|
+
* `setGlobalThemeMode()` imperatively before their first render. It
|
|
97
|
+
* renders `children` as-is — no Context.Provider, since there's no value
|
|
98
|
+
* left to distribute; `useTheme()` never reads from Context.
|
|
93
99
|
*
|
|
94
|
-
* Because the store is global, MULTIPLE mounted providers
|
|
95
|
-
* same
|
|
96
|
-
*
|
|
97
|
-
*
|
|
98
|
-
* in dev, matching old-kbach's identical guard.
|
|
100
|
+
* Because the store is global, MULTIPLE mounted providers would each try
|
|
101
|
+
* to seed the exact same store rather than getting their own scoped
|
|
102
|
+
* state — mounting more than one is very likely a mistake, so this warns
|
|
103
|
+
* once in dev.
|
|
99
104
|
*/
|
|
100
105
|
declare function ThemeProvider({ children, defaultMode }: ThemeProviderProps): react.JSX.Element;
|
|
101
106
|
|
|
102
|
-
interface
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
+
interface ColorScale {
|
|
108
|
+
/** `colors.blue[6]` -> raw value */
|
|
109
|
+
readonly [shade: number]: string;
|
|
110
|
+
/** `colors.blue['6/50']` -> shade 6 at 50% opacity */
|
|
111
|
+
readonly [key: string]: string;
|
|
107
112
|
}
|
|
113
|
+
type ColorsAPI = {
|
|
114
|
+
/** `colors.white`, `colors.blue` (a shade family), `colors.surface`, ... */
|
|
115
|
+
readonly [name: string]: string | ColorScale;
|
|
116
|
+
} & {
|
|
117
|
+
/**
|
|
118
|
+
* Applies an opacity (0–100) to any color string this hook can return —
|
|
119
|
+
* a hex, `rgb()`/`rgba()`, or one of this hook's own
|
|
120
|
+
* `rgb(var(--kb-color-x))` mode-aware references.
|
|
121
|
+
*/
|
|
122
|
+
readonly alpha: (color: string, opacity?: number) => string;
|
|
123
|
+
};
|
|
108
124
|
/**
|
|
109
|
-
*
|
|
110
|
-
*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
*
|
|
125
|
+
* Resolved theme colors as real values — for anywhere you need an actual
|
|
126
|
+
* color (an SVG `fill`, a canvas context, a chart library prop), not a
|
|
127
|
+
* `className`. Ported from old-kbach's `useColors()`
|
|
128
|
+
* (`old-kbach/packages/ui/src/useColors.ts`), adapted to this engine's flat
|
|
129
|
+
* `"blue-6"`-keyed palette (`colors.blue[6]` looks up `"blue-6"`).
|
|
130
|
+
*
|
|
131
|
+
* Any color — a shade-family entry like `"blue-6"` or a standalone name
|
|
132
|
+
* like `"surface"` — can be defined in the theme as either a plain string
|
|
133
|
+
* (static, same in both modes) or a `{ light, dark }` pair — fully manual,
|
|
134
|
+
* no automatic shade-shifting or other assumption about what a "dark
|
|
135
|
+
* variant" should be; see `resolveEntry`'s own doc comment for how a
|
|
136
|
+
* `{ light, dark }` entry resolves.
|
|
137
|
+
*
|
|
138
|
+
* ```ts
|
|
139
|
+
* const colors = useColors();
|
|
140
|
+
* colors.blue[6]; // "#3b82f6" — static, same value in both modes
|
|
141
|
+
* colors.blue['6/50']; // same, at 50% opacity
|
|
142
|
+
* colors.surface; // "rgb(var(--kb-color-surface))" if defined as { light, dark }
|
|
143
|
+
* colors.alpha(colors.surface, 50); // "rgba(var(--kb-color-surface), 0.5)"
|
|
144
|
+
* ```
|
|
114
145
|
*/
|
|
115
|
-
declare function
|
|
146
|
+
declare function useColors(): ColorsAPI;
|
|
116
147
|
|
|
117
|
-
export {
|
|
148
|
+
export { type ColorScale, type ColorsAPI, KbachReset, type ThemeMode, ThemeProvider, type ThemeProviderProps, type ThemeState, disableRuntimeCSS, getGlobalDarkMode, getGlobalThemeMode, initKbach, isKbachReady, isRuntimeCSSDisabled, kb, setGlobalThemeMode, subscribeGlobalDarkMode, toggleGlobalDarkMode, useColors, useTheme };
|