@kbach/react-native 1.0.0-beta.3 → 1.0.0-beta.31
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 +303 -95
- package/android/src/main/jniLibs/arm64-v8a/libkbach_core_engine.so +0 -0
- package/android/src/main/jniLibs/x86_64/libkbach_core_engine.so +0 -0
- package/dist/chunk-FLPPVP5G.mjs +40 -0
- package/dist/chunk-XPVSILI4.mjs +112 -0
- package/dist/chunk-ZYE4VIZE.mjs +564 -0
- package/dist/clsx-BCXALPGh.d.ts +239 -0
- package/dist/darkModeStore.d.ts +73 -0
- package/dist/darkModeStore.js +118 -0
- package/dist/dynamicTokens.d.ts +36 -0
- package/dist/dynamicTokens.js +75 -0
- package/dist/index.d.ts +11 -156
- package/dist/index.js +1994 -393
- package/dist/index.web.d.ts +18 -0
- package/dist/index.web.js +505 -0
- package/dist/index.web.mjs +266 -0
- package/dist/jsx-dev-runtime.d.ts +3 -12
- package/dist/jsx-dev-runtime.js +2143 -350
- package/dist/jsx-dev-runtime.web.d.ts +10 -0
- package/dist/jsx-dev-runtime.web.js +282 -0
- package/dist/jsx-dev-runtime.web.mjs +29 -0
- package/dist/jsx-runtime.d.ts +3 -26
- package/dist/jsx-runtime.js +2134 -342
- package/dist/jsx-runtime.web.d.ts +7 -0
- package/dist/jsx-runtime.web.js +264 -0
- package/dist/{jsx-runtime.mjs → jsx-runtime.web.mjs} +2 -2
- package/dist/theme.d.ts +54 -0
- package/dist/{chunk-7KUNKZBM.mjs → theme.js} +87 -72
- package/package.json +56 -11
- package/src/babel-plugin.js +74 -2
- package/dist/chunk-UP5ZN7CN.mjs +0 -44
- package/dist/index.d.mts +0 -161
- package/dist/index.mjs +0 -80
- package/dist/jsx-dev-runtime.d.mts +0 -19
- package/dist/jsx-dev-runtime.mjs +0 -20
- package/dist/jsx-runtime.d.mts +0 -30
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
import {
|
|
2
|
+
deleteDynamicToken,
|
|
3
|
+
getDynamicToken,
|
|
4
|
+
getGlobalDarkMode,
|
|
5
|
+
getGlobalThemeMode,
|
|
6
|
+
resyncDomWithActiveTheme,
|
|
7
|
+
seedDefaultMode,
|
|
8
|
+
setDynamicToken,
|
|
9
|
+
setGlobalThemeMode,
|
|
10
|
+
subscribeDynamicTokens,
|
|
11
|
+
subscribeGlobalDarkMode,
|
|
12
|
+
toggleGlobalDarkMode
|
|
13
|
+
} from "./chunk-XPVSILI4.mjs";
|
|
14
|
+
import {
|
|
15
|
+
defaultTheme,
|
|
16
|
+
getTheme,
|
|
17
|
+
resolveClassName,
|
|
18
|
+
setTheme
|
|
19
|
+
} from "./chunk-ZYE4VIZE.mjs";
|
|
20
|
+
|
|
21
|
+
// src/config.ts
|
|
22
|
+
function parseHexRgb(hex) {
|
|
23
|
+
const m = /^#([0-9a-f]{3}|[0-9a-f]{6})$/i.exec(hex.trim());
|
|
24
|
+
if (!m) return null;
|
|
25
|
+
let h = m[1];
|
|
26
|
+
if (h.length === 3) h = h.split("").map((c) => c + c).join("");
|
|
27
|
+
const n = parseInt(h, 16);
|
|
28
|
+
return [n >> 16 & 255, n >> 8 & 255, n & 255];
|
|
29
|
+
}
|
|
30
|
+
function applyOpacityToHex(hex, opacityText) {
|
|
31
|
+
const rgb = parseHexRgb(hex);
|
|
32
|
+
if (!rgb) return hex;
|
|
33
|
+
const a = Number(opacityText) / 100;
|
|
34
|
+
const clamped = Number.isFinite(a) ? Math.min(1, Math.max(0, a)) : 1;
|
|
35
|
+
return `rgba(${rgb.join(",")},${clamped})`;
|
|
36
|
+
}
|
|
37
|
+
function resolveColorEntry(value, lookup) {
|
|
38
|
+
const slash = value.indexOf("/");
|
|
39
|
+
const name = slash === -1 ? value : value.slice(0, slash);
|
|
40
|
+
const opacity = slash === -1 ? void 0 : value.slice(slash + 1);
|
|
41
|
+
const base = lookup(name);
|
|
42
|
+
if (base === void 0) return value;
|
|
43
|
+
return opacity === void 0 ? base : applyOpacityToHex(base, opacity);
|
|
44
|
+
}
|
|
45
|
+
function resolveColors(extend, existing) {
|
|
46
|
+
const resolved = {};
|
|
47
|
+
const lookup = (name) => {
|
|
48
|
+
const found = resolved[name] ?? existing[name];
|
|
49
|
+
return typeof found === "string" ? found : void 0;
|
|
50
|
+
};
|
|
51
|
+
for (const [name, value] of Object.entries(extend)) {
|
|
52
|
+
resolved[name] = resolveColorEntry(value, lookup);
|
|
53
|
+
}
|
|
54
|
+
return resolved;
|
|
55
|
+
}
|
|
56
|
+
function resolveKbachConfig(config) {
|
|
57
|
+
let theme = { ...defaultTheme, ...config.theme };
|
|
58
|
+
if (config.extend?.colors) {
|
|
59
|
+
theme = { ...theme, colors: { ...theme.colors, ...resolveColors(config.extend.colors, theme.colors) } };
|
|
60
|
+
}
|
|
61
|
+
if (config.extend?.spacing) {
|
|
62
|
+
theme = { ...theme, spacing: { ...theme.spacing, ...config.extend.spacing } };
|
|
63
|
+
}
|
|
64
|
+
if (config.extend?.screens) {
|
|
65
|
+
theme = { ...theme, screens: { ...theme.screens, ...config.extend.screens } };
|
|
66
|
+
}
|
|
67
|
+
if (config.extend?.fontFamily) {
|
|
68
|
+
theme = { ...theme, fontFamily: { ...theme.fontFamily, ...config.extend.fontFamily } };
|
|
69
|
+
}
|
|
70
|
+
if (config.extend?.container) {
|
|
71
|
+
theme = { ...theme, container: { ...theme.container, ...config.extend.container } };
|
|
72
|
+
}
|
|
73
|
+
if (config.darkMode) {
|
|
74
|
+
theme = { ...theme, darkMode: config.darkMode };
|
|
75
|
+
}
|
|
76
|
+
return theme;
|
|
77
|
+
}
|
|
78
|
+
function applyKbachConfig(config) {
|
|
79
|
+
const theme = resolveKbachConfig(config);
|
|
80
|
+
setTheme(theme);
|
|
81
|
+
resyncDomWithActiveTheme();
|
|
82
|
+
return theme;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// src/useTheme.ts
|
|
86
|
+
import { useMemo, useSyncExternalStore } from "react";
|
|
87
|
+
function useTheme() {
|
|
88
|
+
const isDark = useSyncExternalStore(subscribeGlobalDarkMode, getGlobalDarkMode);
|
|
89
|
+
const mode = useSyncExternalStore(subscribeGlobalDarkMode, getGlobalThemeMode);
|
|
90
|
+
return useMemo(
|
|
91
|
+
() => ({ mode, isDark, setMode: setGlobalThemeMode, toggle: toggleGlobalDarkMode }),
|
|
92
|
+
[mode, isDark]
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// src/ThemeProvider.tsx
|
|
97
|
+
import { useEffect, useRef } from "react";
|
|
98
|
+
import { Fragment, jsx } from "react/jsx-runtime";
|
|
99
|
+
var PERSIST_STORAGE_KEY = "kbach-theme";
|
|
100
|
+
function isThemeMode(value) {
|
|
101
|
+
return value === "light" || value === "dark" || value === "system";
|
|
102
|
+
}
|
|
103
|
+
var mountedProviderCount = 0;
|
|
104
|
+
var warnedMultipleProviders = false;
|
|
105
|
+
function ThemeProvider({ children, defaultMode = "system", persist = false }) {
|
|
106
|
+
useEffect(() => {
|
|
107
|
+
mountedProviderCount++;
|
|
108
|
+
if (mountedProviderCount > 1 && !warnedMultipleProviders) {
|
|
109
|
+
warnedMultipleProviders = true;
|
|
110
|
+
console.warn(
|
|
111
|
+
"[Kbach] Multiple <ThemeProvider> instances are mounted at once.\nDark mode is one global store \u2014 useTheme() reads it everywhere, not scoped per provider \u2014 so their defaultMode/persist seeds will fight over the same state.\nMount exactly one <ThemeProvider>, as high in the tree as convenient."
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
return () => {
|
|
115
|
+
mountedProviderCount--;
|
|
116
|
+
};
|
|
117
|
+
}, []);
|
|
118
|
+
const seeded = useRef(false);
|
|
119
|
+
useEffect(() => {
|
|
120
|
+
if (seeded.current) return;
|
|
121
|
+
seeded.current = true;
|
|
122
|
+
if (!persist) {
|
|
123
|
+
seedDefaultMode(defaultMode);
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
let cancelled = false;
|
|
127
|
+
persist.getItem(PERSIST_STORAGE_KEY).then((stored) => {
|
|
128
|
+
if (cancelled) return;
|
|
129
|
+
if (isThemeMode(stored)) seedDefaultMode(stored);
|
|
130
|
+
else seedDefaultMode(defaultMode);
|
|
131
|
+
}).catch(() => {
|
|
132
|
+
if (!cancelled) seedDefaultMode(defaultMode);
|
|
133
|
+
});
|
|
134
|
+
return () => {
|
|
135
|
+
cancelled = true;
|
|
136
|
+
};
|
|
137
|
+
}, []);
|
|
138
|
+
useEffect(() => {
|
|
139
|
+
if (!persist) return;
|
|
140
|
+
return subscribeGlobalDarkMode(() => {
|
|
141
|
+
persist.setItem(PERSIST_STORAGE_KEY, getGlobalThemeMode()).catch(() => {
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
}, [persist]);
|
|
145
|
+
return /* @__PURE__ */ jsx(Fragment, { children });
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// src/useColors.ts
|
|
149
|
+
import { useMemo as useMemo2 } from "react";
|
|
150
|
+
function parseHexRgb2(hex) {
|
|
151
|
+
const m = /^#([0-9a-f]{3}|[0-9a-f]{6})$/i.exec(hex.trim());
|
|
152
|
+
if (!m) return null;
|
|
153
|
+
let h = m[1];
|
|
154
|
+
if (h.length === 3) h = h.split("").map((c) => c + c).join("");
|
|
155
|
+
const n = parseInt(h, 16);
|
|
156
|
+
return [n >> 16 & 255, n >> 8 & 255, n & 255];
|
|
157
|
+
}
|
|
158
|
+
function applyOpacity(color, opacity) {
|
|
159
|
+
const a = Math.max(0, Math.min(1, opacity / 100));
|
|
160
|
+
if (color.startsWith("#")) {
|
|
161
|
+
const rgb = parseHexRgb2(color);
|
|
162
|
+
return rgb ? `rgba(${rgb.join(",")},${a})` : color;
|
|
163
|
+
}
|
|
164
|
+
if (color.startsWith("rgb(")) return color.replace("rgb(", "rgba(").replace(")", `,${a})`);
|
|
165
|
+
if (color.startsWith("rgba(")) return color.replace(/,\s*[\d.]+\)$/, `,${a})`);
|
|
166
|
+
return color;
|
|
167
|
+
}
|
|
168
|
+
function resolveEntry(entry, isDark) {
|
|
169
|
+
return typeof entry === "string" ? entry : isDark ? entry.dark : entry.light;
|
|
170
|
+
}
|
|
171
|
+
function makeColorsProxy(theme, isDark) {
|
|
172
|
+
const alpha = (color, opacity) => opacity === void 0 ? color : applyOpacity(color, opacity);
|
|
173
|
+
const cache = /* @__PURE__ */ new Map();
|
|
174
|
+
function resolveNamed(key) {
|
|
175
|
+
let name = key;
|
|
176
|
+
let opacity;
|
|
177
|
+
if (key.includes("/")) {
|
|
178
|
+
const slash = key.indexOf("/");
|
|
179
|
+
name = key.slice(0, slash);
|
|
180
|
+
opacity = Number(key.slice(slash + 1));
|
|
181
|
+
}
|
|
182
|
+
const entry = theme.colors[name];
|
|
183
|
+
if (entry === void 0) return void 0;
|
|
184
|
+
const value = resolveEntry(entry, isDark);
|
|
185
|
+
return opacity === void 0 ? value : applyOpacity(value, opacity);
|
|
186
|
+
}
|
|
187
|
+
function makeFamilyProxy(family) {
|
|
188
|
+
return new Proxy({}, {
|
|
189
|
+
get(_, prop) {
|
|
190
|
+
const key = String(prop);
|
|
191
|
+
if (key === "then") return void 0;
|
|
192
|
+
return resolveNamed(`${family}-${key}`);
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
return new Proxy({ alpha }, {
|
|
197
|
+
get(_, prop) {
|
|
198
|
+
const key = String(prop);
|
|
199
|
+
if (key === "then") return void 0;
|
|
200
|
+
if (key === "alpha") return alpha;
|
|
201
|
+
const direct = resolveNamed(key);
|
|
202
|
+
if (direct !== void 0) return direct;
|
|
203
|
+
if (!cache.has(key)) cache.set(key, makeFamilyProxy(key));
|
|
204
|
+
return cache.get(key);
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
function useColors() {
|
|
209
|
+
const { isDark } = useTheme();
|
|
210
|
+
const theme = getTheme();
|
|
211
|
+
return useMemo2(() => makeColorsProxy(theme, isDark), [theme, isDark]);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// src/useDynamicToken.ts
|
|
215
|
+
import { useSyncExternalStore as useSyncExternalStore2 } from "react";
|
|
216
|
+
function useDynamicToken(name) {
|
|
217
|
+
return useSyncExternalStore2(subscribeDynamicTokens, () => getDynamicToken(name));
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// src/clsx.ts
|
|
221
|
+
function clsx(...inputs) {
|
|
222
|
+
let out = "";
|
|
223
|
+
for (const input of inputs) {
|
|
224
|
+
const piece = resolveClassValue(input);
|
|
225
|
+
if (piece) out = out ? `${out} ${piece}` : piece;
|
|
226
|
+
}
|
|
227
|
+
return out;
|
|
228
|
+
}
|
|
229
|
+
function resolveClassValue(value) {
|
|
230
|
+
if (!value) return "";
|
|
231
|
+
const type = typeof value;
|
|
232
|
+
if (type === "string" || type === "number" || type === "bigint") return String(value);
|
|
233
|
+
if (Array.isArray(value)) return clsx(...value);
|
|
234
|
+
if (type === "object") {
|
|
235
|
+
let out = "";
|
|
236
|
+
for (const key in value) {
|
|
237
|
+
if (Object.prototype.hasOwnProperty.call(value, key) && value[key]) {
|
|
238
|
+
out = out ? `${out} ${key}` : key;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
return out;
|
|
242
|
+
}
|
|
243
|
+
return "";
|
|
244
|
+
}
|
|
245
|
+
export {
|
|
246
|
+
ThemeProvider,
|
|
247
|
+
applyKbachConfig,
|
|
248
|
+
clsx,
|
|
249
|
+
defaultTheme,
|
|
250
|
+
deleteDynamicToken,
|
|
251
|
+
getDynamicToken,
|
|
252
|
+
getGlobalDarkMode,
|
|
253
|
+
getGlobalThemeMode,
|
|
254
|
+
getTheme,
|
|
255
|
+
resolveClassName,
|
|
256
|
+
resolveKbachConfig,
|
|
257
|
+
setDynamicToken,
|
|
258
|
+
setGlobalThemeMode,
|
|
259
|
+
setTheme,
|
|
260
|
+
subscribeDynamicTokens,
|
|
261
|
+
subscribeGlobalDarkMode,
|
|
262
|
+
toggleGlobalDarkMode,
|
|
263
|
+
useColors,
|
|
264
|
+
useDynamicToken,
|
|
265
|
+
useTheme
|
|
266
|
+
};
|
|
@@ -1,19 +1,10 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as react from 'react';
|
|
2
2
|
export { Fragment } from 'react';
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
* @kbach/react-native/jsx-dev-runtime
|
|
6
|
-
*
|
|
7
|
-
* Development variant — Metro calls jsxDEV instead of jsx/jsxs in dev
|
|
8
|
-
* builds. Same pattern as @kbach/react/jsx-dev-runtime (Phase 3): reuses
|
|
9
|
-
* jsx/jsxs for the actual interception, then patches _source/_self onto
|
|
10
|
-
* the result so React DevTools shows the original file/line.
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
declare function jsxDEV(type: unknown, props: Record<string, unknown> | null, key?: string, isStaticChildren?: boolean, source?: {
|
|
4
|
+
declare const jsxDEV: (type: unknown, props: Record<string, unknown> | null, key?: string, isStaticChildren?: boolean, source?: {
|
|
14
5
|
fileName: string;
|
|
15
6
|
lineNumber: number;
|
|
16
7
|
columnNumber: number;
|
|
17
|
-
}, self?: unknown)
|
|
8
|
+
}, self?: unknown) => react.ReactElement;
|
|
18
9
|
|
|
19
10
|
export { jsxDEV };
|