@xaui/hybrid 0.0.8 → 0.0.9

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.
@@ -0,0 +1,2 @@
1
+ export { A as Alert, a as AlertProps, c as AlertRadius, b as AlertVariant } from '../index-CMptPfU-.js';
2
+ import 'react';
@@ -0,0 +1,6 @@
1
+ import {
2
+ Alert
3
+ } from "../chunk-7HVBAJHB.js";
4
+ export {
5
+ Alert
6
+ };
@@ -0,0 +1,326 @@
1
+ // src/components/alert/alert.style.ts
2
+ import { tv } from "tailwind-variants";
3
+ var alertStyles = tv({
4
+ slots: {
5
+ container: "xui-alert flex flex-row items-center w-full gap-3 bg-[var(--xui-alert-bg)] [border-width:var(--xui-alert-border-width)] [border-color:var(--xui-alert-border-color)] px-[var(--xui-spacing-md)] py-[var(--xui-spacing-sm)]",
6
+ mainWrapper: "flex-1 flex-col justify-center gap-0.5",
7
+ iconWrapper: "size-7 rounded-full flex items-center justify-center shrink-0 text-[var(--xui-alert-text)] bg-[var(--xui-alert-icon-bg)] [border-width:var(--xui-alert-icon-border-width)] [border-color:var(--xui-alert-icon-border-color)]",
8
+ title: "m-0 leading-tight text-[var(--xui-alert-text)] text-[length:var(--xui-text-sm)] font-[var(--xui-font-semibold)]",
9
+ description: "m-0 mt-1 leading-none text-[var(--xui-alert-description)] text-[length:var(--xui-text-xs)] font-[var(--xui-font-normal)]",
10
+ iconText: "font-[var(--xui-font-semibold)]",
11
+ closeButton: "self-start p-1 cursor-pointer bg-transparent border-0 rounded flex text-[var(--xui-alert-text)]",
12
+ extraContent: "mt-1"
13
+ },
14
+ variants: {
15
+ themeColor: {
16
+ default: {
17
+ container: "[--xui-alert-main:var(--xui-default)] [--xui-alert-fg:var(--xui-default-fg)] [--xui-alert-bg-base:var(--xui-default-bg)] [--xui-alert-text-base:var(--xui-foreground)] [--xui-alert-accent:var(--xui-foreground)]"
18
+ },
19
+ primary: {
20
+ container: "[--xui-alert-main:var(--xui-primary)] [--xui-alert-fg:var(--xui-primary-fg)] [--xui-alert-bg-base:var(--xui-primary-bg)] [--xui-alert-text-base:var(--xui-primary)] [--xui-alert-accent:var(--xui-primary)]"
21
+ },
22
+ secondary: {
23
+ container: "[--xui-alert-main:var(--xui-secondary)] [--xui-alert-fg:var(--xui-secondary-fg)] [--xui-alert-bg-base:var(--xui-secondary-bg)] [--xui-alert-text-base:var(--xui-secondary)] [--xui-alert-accent:var(--xui-secondary)]"
24
+ },
25
+ tertiary: {
26
+ container: "[--xui-alert-main:var(--xui-tertiary)] [--xui-alert-fg:var(--xui-tertiary-fg)] [--xui-alert-bg-base:var(--xui-tertiary-bg)] [--xui-alert-text-base:var(--xui-tertiary)] [--xui-alert-accent:var(--xui-tertiary)]"
27
+ },
28
+ success: {
29
+ container: "[--xui-alert-main:var(--xui-success)] [--xui-alert-fg:var(--xui-success-fg)] [--xui-alert-bg-base:var(--xui-success-bg)] [--xui-alert-text-base:var(--xui-success)] [--xui-alert-accent:var(--xui-success)]"
30
+ },
31
+ warning: {
32
+ container: "[--xui-alert-main:var(--xui-warning)] [--xui-alert-fg:var(--xui-warning-fg)] [--xui-alert-bg-base:var(--xui-warning-bg)] [--xui-alert-text-base:var(--xui-warning)] [--xui-alert-accent:var(--xui-warning)]"
33
+ },
34
+ danger: {
35
+ container: "[--xui-alert-main:var(--xui-danger)] [--xui-alert-fg:var(--xui-danger-fg)] [--xui-alert-bg-base:var(--xui-danger-bg)] [--xui-alert-text-base:var(--xui-danger)] [--xui-alert-accent:var(--xui-danger)]"
36
+ }
37
+ },
38
+ variant: {
39
+ solid: {
40
+ container: "[--xui-alert-bg:var(--xui-alert-solid-bg)] [--xui-alert-text:var(--xui-alert-solid-text)] [--xui-alert-description:color-mix(in_srgb,var(--xui-alert-solid-text)_75%,transparent)] [--xui-alert-border-width:0px] [--xui-alert-border-color:transparent]",
41
+ iconWrapper: "[--xui-alert-icon-bg:var(--xui-alert-solid-icon-bg)] [--xui-alert-icon-border-width:0px] [--xui-alert-icon-border-color:transparent]"
42
+ },
43
+ flat: {
44
+ container: "[--xui-alert-bg:var(--xui-alert-flat-bg)] [--xui-alert-text:var(--xui-alert-text-base)] [--xui-alert-description:color-mix(in_srgb,var(--xui-alert-text-base)_75%,transparent)] [--xui-alert-border-width:0px] [--xui-alert-border-color:transparent]",
45
+ iconWrapper: "[--xui-alert-icon-bg:color-mix(in_srgb,var(--xui-alert-accent)_12%,transparent)] [--xui-alert-icon-border-width:0px] [--xui-alert-icon-border-color:transparent]"
46
+ },
47
+ bordered: {
48
+ container: "border-solid [--xui-alert-bg:transparent] [--xui-alert-text:var(--xui-alert-text-base)] [--xui-alert-description:color-mix(in_srgb,var(--xui-alert-text-base)_75%,transparent)] [--xui-alert-border-width:var(--xui-border-md)] [--xui-alert-border-color:color-mix(in_srgb,var(--xui-alert-main)_75%,transparent)]",
49
+ iconWrapper: "border-solid [--xui-alert-icon-bg:color-mix(in_srgb,var(--xui-alert-accent)_12%,transparent)] [--xui-alert-icon-border-width:var(--xui-border-xs)] [--xui-alert-icon-border-color:color-mix(in_srgb,var(--xui-alert-accent)_20%,transparent)]"
50
+ },
51
+ faded: {
52
+ container: "border-solid [--xui-alert-bg:color-mix(in_srgb,var(--xui-alert-bg-base)_75%,transparent)] [--xui-alert-text:var(--xui-alert-text-base)] [--xui-alert-description:color-mix(in_srgb,var(--xui-alert-text-base)_75%,transparent)] [--xui-alert-border-width:var(--xui-border-md)] [--xui-alert-border-color:color-mix(in_srgb,var(--xui-alert-accent)_25%,transparent)]",
53
+ iconWrapper: "border-solid [--xui-alert-icon-bg:color-mix(in_srgb,var(--xui-alert-accent)_12%,transparent)] [--xui-alert-icon-border-width:var(--xui-border-xs)] [--xui-alert-icon-border-color:color-mix(in_srgb,var(--xui-alert-accent)_20%,transparent)]"
54
+ }
55
+ },
56
+ radius: {
57
+ none: { container: "rounded-[var(--xui-radius-none)]" },
58
+ sm: { container: "rounded-[var(--xui-radius-sm)]" },
59
+ md: { container: "rounded-[var(--xui-radius-md)]" },
60
+ lg: { container: "rounded-[var(--xui-radius-lg)]" },
61
+ full: { container: "rounded-[var(--xui-radius-full)]" }
62
+ }
63
+ },
64
+ defaultVariants: {
65
+ themeColor: "default",
66
+ variant: "flat",
67
+ radius: "md"
68
+ }
69
+ });
70
+
71
+ // src/components/alert/alert.hook.tsx
72
+ import {
73
+ cloneElement,
74
+ isValidElement,
75
+ useCallback,
76
+ useEffect,
77
+ useMemo,
78
+ useRef,
79
+ useState
80
+ } from "react";
81
+
82
+ // src/components/alert/alert-icons.tsx
83
+ import { jsx, jsxs } from "react/jsx-runtime";
84
+ function InfoIcon({ color, size }) {
85
+ return /* @__PURE__ */ jsxs("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", overflow: "hidden", children: [
86
+ /* @__PURE__ */ jsx("circle", { cx: 12, cy: 12, r: 10, stroke: color, strokeWidth: 2 }),
87
+ /* @__PURE__ */ jsx("line", { x1: 12, y1: 10, x2: 12, y2: 16, stroke: color, strokeWidth: 2, strokeLinecap: "round" }),
88
+ /* @__PURE__ */ jsx("circle", { cx: 12, cy: 7, r: 1, fill: color })
89
+ ] });
90
+ }
91
+ function SuccessIcon({ color, size }) {
92
+ return /* @__PURE__ */ jsxs("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", overflow: "hidden", children: [
93
+ /* @__PURE__ */ jsx("circle", { cx: 12, cy: 12, r: 10, stroke: color, strokeWidth: 2 }),
94
+ /* @__PURE__ */ jsx(
95
+ "path",
96
+ {
97
+ d: "M7 12.5L10.2 15.5L17 9",
98
+ stroke: color,
99
+ strokeWidth: 2,
100
+ strokeLinecap: "round",
101
+ strokeLinejoin: "round"
102
+ }
103
+ )
104
+ ] });
105
+ }
106
+ function WarningIcon({ color, size }) {
107
+ return /* @__PURE__ */ jsxs("svg", { width: size, height: size, viewBox: "0 0 26 26", fill: "none", overflow: "hidden", children: [
108
+ /* @__PURE__ */ jsx(
109
+ "path",
110
+ {
111
+ d: "M13 3.5L22.5 21H3.5L13 3.5Z",
112
+ stroke: color,
113
+ strokeWidth: 2,
114
+ strokeLinejoin: "round"
115
+ }
116
+ ),
117
+ /* @__PURE__ */ jsx("line", { x1: 13, y1: 10, x2: 13, y2: 15, stroke: color, strokeWidth: 2, strokeLinecap: "round" }),
118
+ /* @__PURE__ */ jsx("circle", { cx: 13, cy: 18, r: 1, fill: color })
119
+ ] });
120
+ }
121
+ function DangerIcon({ color, size }) {
122
+ return /* @__PURE__ */ jsxs("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", overflow: "hidden", children: [
123
+ /* @__PURE__ */ jsx("circle", { cx: 12, cy: 12, r: 10, stroke: color, strokeWidth: 2 }),
124
+ /* @__PURE__ */ jsx("line", { x1: 9, y1: 9, x2: 15, y2: 15, stroke: color, strokeWidth: 2, strokeLinecap: "round" }),
125
+ /* @__PURE__ */ jsx("line", { x1: 15, y1: 9, x2: 9, y2: 15, stroke: color, strokeWidth: 2, strokeLinecap: "round" })
126
+ ] });
127
+ }
128
+ function CloseIcon({ color, size }) {
129
+ return /* @__PURE__ */ jsxs("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", overflow: "hidden", children: [
130
+ /* @__PURE__ */ jsx("line", { x1: 18, y1: 6, x2: 6, y2: 18, stroke: color, strokeWidth: 2, strokeLinecap: "round" }),
131
+ /* @__PURE__ */ jsx("line", { x1: 6, y1: 6, x2: 18, y2: 18, stroke: color, strokeWidth: 2, strokeLinecap: "round" })
132
+ ] });
133
+ }
134
+
135
+ // src/components/alert/alert.hook.tsx
136
+ import { jsx as jsx2 } from "react/jsx-runtime";
137
+ var iconMap = {
138
+ default: InfoIcon,
139
+ primary: InfoIcon,
140
+ secondary: InfoIcon,
141
+ tertiary: InfoIcon,
142
+ success: SuccessIcon,
143
+ warning: WarningIcon,
144
+ danger: DangerIcon
145
+ };
146
+ var useAlertVisibility = ({
147
+ isVisible,
148
+ onClose,
149
+ onVisibleChange
150
+ }) => {
151
+ const [internalVisible, setInternalVisible] = useState(isVisible ?? true);
152
+ const [shouldRender, setShouldRender] = useState(isVisible ?? true);
153
+ const [animState, setAnimState] = useState("open");
154
+ const isInitialMount = useRef(true);
155
+ const isControlled = typeof isVisible === "boolean";
156
+ const visible = isControlled ? isVisible : internalVisible;
157
+ const finishClosing = useCallback(() => {
158
+ setShouldRender(false);
159
+ if (!isControlled) {
160
+ setInternalVisible(false);
161
+ }
162
+ onVisibleChange?.(false);
163
+ onClose?.();
164
+ }, [isControlled, onClose, onVisibleChange]);
165
+ const handleClose = useCallback(() => {
166
+ if (!visible) return;
167
+ setAnimState("closed");
168
+ }, [visible]);
169
+ const handleAnimationEnd = useCallback(() => {
170
+ if (animState === "closed") {
171
+ finishClosing();
172
+ }
173
+ }, [animState, finishClosing]);
174
+ useEffect(() => {
175
+ if (isInitialMount.current) {
176
+ isInitialMount.current = false;
177
+ return;
178
+ }
179
+ if (visible && !shouldRender) {
180
+ setShouldRender(true);
181
+ setAnimState("open");
182
+ return;
183
+ }
184
+ if (!visible && shouldRender) {
185
+ handleClose();
186
+ }
187
+ }, [visible, shouldRender, handleClose]);
188
+ return {
189
+ shouldRender,
190
+ animState,
191
+ handleClose,
192
+ handleAnimationEnd
193
+ };
194
+ };
195
+ var useAlertIconNode = ({
196
+ hideIcon,
197
+ icon,
198
+ themeColor,
199
+ slots
200
+ }) => {
201
+ return useMemo(() => {
202
+ if (hideIcon) return null;
203
+ if (icon && isValidElement(icon)) {
204
+ return cloneElement(icon, { color: "currentColor", size: 18 });
205
+ }
206
+ if (icon) {
207
+ return /* @__PURE__ */ jsx2("span", { className: slots.iconText(), children: icon });
208
+ }
209
+ const IconComponent = iconMap[themeColor ?? "default"] ?? InfoIcon;
210
+ return /* @__PURE__ */ jsx2(IconComponent, { color: "currentColor", size: 18 });
211
+ }, [hideIcon, icon, slots, themeColor]);
212
+ };
213
+ var useAlertContentNodes = ({
214
+ title,
215
+ description,
216
+ children,
217
+ customAppearance,
218
+ slots
219
+ }) => {
220
+ const renderContentText = useCallback(
221
+ (content) => {
222
+ if (content === null || content === void 0) return null;
223
+ if (typeof content === "string" || typeof content === "number") {
224
+ return /* @__PURE__ */ jsx2("p", { className: slots.description(), style: customAppearance?.description, children: content });
225
+ }
226
+ return content;
227
+ },
228
+ [customAppearance?.description, slots]
229
+ );
230
+ const titleNode = useMemo(() => {
231
+ if (title === null || title === void 0) return null;
232
+ if (typeof title === "string" || typeof title === "number") {
233
+ return /* @__PURE__ */ jsx2("p", { className: slots.title(), style: customAppearance?.title, children: title });
234
+ }
235
+ return title;
236
+ }, [title, customAppearance?.title, slots]);
237
+ const descriptionNode = renderContentText(description);
238
+ const childrenNode = renderContentText(children);
239
+ return { titleNode, descriptionNode, childrenNode };
240
+ };
241
+ var useAlertCloseButtonNode = ({
242
+ closeButton,
243
+ handleClose
244
+ }) => {
245
+ return useMemo(() => {
246
+ if (!closeButton) return null;
247
+ if (!isValidElement(closeButton)) return closeButton;
248
+ const existingOnClick = closeButton.props.onClick;
249
+ return cloneElement(closeButton, {
250
+ onClick: (e) => {
251
+ existingOnClick?.(e);
252
+ handleClose();
253
+ }
254
+ });
255
+ }, [closeButton, handleClose]);
256
+ };
257
+ var DefaultAlertCloseButton = ({
258
+ onClick,
259
+ className
260
+ }) => /* @__PURE__ */ jsx2("button", { type: "button", "aria-label": "Close", onClick, className, children: /* @__PURE__ */ jsx2(CloseIcon, { size: 20, color: "currentColor" }) });
261
+
262
+ // src/components/alert/alert.tsx
263
+ import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
264
+ var Alert = ({
265
+ title,
266
+ description,
267
+ icon,
268
+ themeColor = "default",
269
+ variant = "flat",
270
+ radius = "md",
271
+ isClosable = false,
272
+ hideIcon = false,
273
+ closeButton,
274
+ isVisible,
275
+ customAppearance,
276
+ children,
277
+ onClose,
278
+ onVisibleChange
279
+ }) => {
280
+ const slots = alertStyles({ variant, themeColor, radius });
281
+ const { shouldRender, animState, handleClose, handleAnimationEnd } = useAlertVisibility({
282
+ isVisible,
283
+ onClose,
284
+ onVisibleChange
285
+ });
286
+ const shouldShowClose = Boolean(closeButton || isClosable || onClose);
287
+ const iconNode = useAlertIconNode({ hideIcon, icon, themeColor, slots });
288
+ const { titleNode, descriptionNode, childrenNode } = useAlertContentNodes({
289
+ title,
290
+ description,
291
+ children,
292
+ customAppearance,
293
+ slots
294
+ });
295
+ const closeButtonNode = useAlertCloseButtonNode({ closeButton, handleClose });
296
+ if (!shouldRender) return null;
297
+ return /* @__PURE__ */ jsxs2(
298
+ "div",
299
+ {
300
+ role: "alert",
301
+ "data-xui-state": animState,
302
+ className: slots.container(),
303
+ style: customAppearance?.container,
304
+ onAnimationEnd: handleAnimationEnd,
305
+ children: [
306
+ !hideIcon && /* @__PURE__ */ jsx3("div", { className: slots.iconWrapper(), children: iconNode }),
307
+ /* @__PURE__ */ jsxs2("div", { className: slots.mainWrapper(), children: [
308
+ titleNode,
309
+ descriptionNode,
310
+ childrenNode && /* @__PURE__ */ jsx3("div", { className: slots.extraContent(), children: childrenNode })
311
+ ] }),
312
+ shouldShowClose && /* @__PURE__ */ jsx3("div", { children: closeButtonNode ?? /* @__PURE__ */ jsx3(
313
+ DefaultAlertCloseButton,
314
+ {
315
+ onClick: handleClose,
316
+ className: slots.closeButton()
317
+ }
318
+ ) })
319
+ ]
320
+ }
321
+ );
322
+ };
323
+
324
+ export {
325
+ Alert
326
+ };
@@ -0,0 +1,177 @@
1
+ // src/core/theme-provider.tsx
2
+ import { useEffect } from "react";
3
+ import { Fragment, jsx } from "react/jsx-runtime";
4
+ var getSystemColorMode = () => {
5
+ if (typeof globalThis === "undefined" || !globalThis.matchMedia) return "light";
6
+ return globalThis.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
7
+ };
8
+ function XUIProvider({
9
+ children,
10
+ colorScheme,
11
+ target = "html",
12
+ variables,
13
+ darkVariables
14
+ }) {
15
+ useEffect(() => {
16
+ if (typeof document === "undefined") return;
17
+ const root = document.documentElement;
18
+ const styleTarget = target === "body" ? document.body : root;
19
+ if (!styleTarget) return;
20
+ const resolvedMode = colorScheme ?? getSystemColorMode();
21
+ root.dataset.colorScheme = resolvedMode;
22
+ const activeVars = resolvedMode === "dark" ? { ...variables, ...darkVariables } : variables;
23
+ if (!activeVars) return;
24
+ const appliedKeys = [];
25
+ for (const [key, value] of Object.entries(activeVars)) {
26
+ if (value === void 0 || value === null) continue;
27
+ styleTarget.style.setProperty(key, String(value));
28
+ appliedKeys.push(key);
29
+ }
30
+ return () => {
31
+ for (const key of appliedKeys) {
32
+ styleTarget.style.removeProperty(key);
33
+ }
34
+ };
35
+ }, [colorScheme, darkVariables, target, variables]);
36
+ return /* @__PURE__ */ jsx(Fragment, { children });
37
+ }
38
+
39
+ // src/core/theme-hooks.ts
40
+ import { useEffect as useEffect2, useMemo, useState } from "react";
41
+ var getDocumentColorMode = () => {
42
+ if (typeof document === "undefined") return null;
43
+ const scheme = document.documentElement.dataset.colorScheme;
44
+ return scheme === "dark" || scheme === "light" ? scheme : null;
45
+ };
46
+ var getWebColorMode = () => {
47
+ if (typeof globalThis === "undefined") return "light";
48
+ const globalScope = globalThis;
49
+ if (!globalScope.matchMedia) return "light";
50
+ return globalScope.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
51
+ };
52
+ function useColorMode() {
53
+ const [webScheme, setWebScheme] = useState(() => getWebColorMode());
54
+ useEffect2(() => {
55
+ if (typeof globalThis === "undefined") return;
56
+ const globalScope = globalThis;
57
+ if (!globalScope.matchMedia) return;
58
+ const media = globalScope.matchMedia("(prefers-color-scheme: dark)");
59
+ const handleChange = () => {
60
+ setWebScheme(media.matches ? "dark" : "light");
61
+ };
62
+ handleChange();
63
+ if (typeof media.addEventListener === "function") {
64
+ media.addEventListener("change", handleChange);
65
+ return () => media.removeEventListener?.("change", handleChange);
66
+ }
67
+ const legacyMedia = media;
68
+ legacyMedia.addListener?.(handleChange);
69
+ return () => legacyMedia.removeListener?.(handleChange);
70
+ }, []);
71
+ return webScheme;
72
+ }
73
+ function useXUITheme() {
74
+ const systemScheme = useColorMode();
75
+ const [documentScheme, setDocumentScheme] = useState(
76
+ () => getDocumentColorMode()
77
+ );
78
+ useEffect2(() => {
79
+ if (typeof document === "undefined") return;
80
+ const node = document.documentElement;
81
+ const update = () => setDocumentScheme(getDocumentColorMode());
82
+ update();
83
+ const observer = new MutationObserver(update);
84
+ observer.observe(node, {
85
+ attributes: true,
86
+ attributeFilter: ["data-color-scheme"]
87
+ });
88
+ return () => observer.disconnect();
89
+ }, []);
90
+ const resolvedScheme = documentScheme ?? systemScheme;
91
+ return useMemo(
92
+ () => ({
93
+ mode: resolvedScheme,
94
+ palette: {
95
+ primary: "var(--xui-primary)",
96
+ secondary: "var(--xui-secondary)",
97
+ tertiary: "var(--xui-tertiary)",
98
+ danger: "var(--xui-danger)",
99
+ warning: "var(--xui-warning)",
100
+ success: "var(--xui-success)",
101
+ default: "var(--xui-default)"
102
+ },
103
+ colors: {
104
+ primary: {
105
+ main: "var(--xui-primary)",
106
+ foreground: "var(--xui-primary-fg)",
107
+ background: "var(--xui-primary-bg)"
108
+ },
109
+ secondary: {
110
+ main: "var(--xui-secondary)",
111
+ foreground: "var(--xui-secondary-fg)",
112
+ background: "var(--xui-secondary-bg)"
113
+ },
114
+ tertiary: {
115
+ main: "var(--xui-tertiary)",
116
+ foreground: "var(--xui-tertiary-fg)",
117
+ background: "var(--xui-tertiary-bg)"
118
+ },
119
+ danger: {
120
+ main: "var(--xui-danger)",
121
+ foreground: "var(--xui-danger-fg)",
122
+ background: "var(--xui-danger-bg)"
123
+ },
124
+ warning: {
125
+ main: "var(--xui-warning)",
126
+ foreground: "var(--xui-warning-fg)",
127
+ background: "var(--xui-warning-bg)"
128
+ },
129
+ success: {
130
+ main: "var(--xui-success)",
131
+ foreground: "var(--xui-success-fg)",
132
+ background: "var(--xui-success-bg)"
133
+ },
134
+ default: {
135
+ main: "var(--xui-default)",
136
+ foreground: "var(--xui-default-fg)",
137
+ background: "var(--xui-default-bg)"
138
+ },
139
+ background: "var(--xui-background)",
140
+ foreground: "var(--xui-foreground)"
141
+ },
142
+ borderRadius: {
143
+ none: "var(--xui-radius-none)",
144
+ sm: "var(--xui-radius-sm)",
145
+ md: "var(--xui-radius-md)",
146
+ lg: "var(--xui-radius-lg)",
147
+ full: "var(--xui-radius-full)"
148
+ }
149
+ }),
150
+ [resolvedScheme]
151
+ );
152
+ }
153
+ function useXUIColors() {
154
+ const theme = useXUITheme();
155
+ return theme.colors;
156
+ }
157
+ function useXUIPalette() {
158
+ const theme = useXUITheme();
159
+ return useMemo(() => theme.palette, [theme]);
160
+ }
161
+ function useBorderRadiusStyles(radius) {
162
+ return useMemo(
163
+ () => ({
164
+ borderRadius: `var(--xui-radius-${radius})`
165
+ }),
166
+ [radius]
167
+ );
168
+ }
169
+
170
+ export {
171
+ XUIProvider,
172
+ useColorMode,
173
+ useXUITheme,
174
+ useXUIColors,
175
+ useXUIPalette,
176
+ useBorderRadiusStyles
177
+ };
@@ -1,20 +1,3 @@
1
- import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { ReactNode } from 'react';
3
- import { XUITheme } from '@xaui/core/theme';
4
-
5
- type DeepPartial<T> = {
6
- [P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
7
- };
8
- interface XUIProviderProps {
9
- children: ReactNode;
10
- theme?: DeepPartial<XUITheme>;
11
- darkTheme?: DeepPartial<XUITheme>;
12
- }
13
- declare function XUIProvider({ children, theme: lightTheme, darkTheme, }: XUIProviderProps): react_jsx_runtime.JSX.Element;
14
-
15
- type ColorMode = 'light' | 'dark';
16
- declare function useColorMode(): ColorMode;
17
- declare function useXUITheme(): XUITheme;
18
- declare function useXUIColors(): XUITheme['colors'];
19
-
20
- export { XUIProvider, useColorMode, useXUIColors, useXUITheme };
1
+ export { X as XUIProvider, a as XUIProviderProps, b as XUIVariables, f as useBorderRadiusStyles, u as useColorMode, d as useXUIColors, e as useXUIPalette, c as useXUITheme } from '../index-5BCfEjU-.js';
2
+ import 'react/jsx-runtime';
3
+ import 'react';
@@ -1,85 +1,16 @@
1
- // src/core/theme-context.tsx
2
- import React, { createContext } from "react";
3
-
4
- // src/core/theme-hooks.ts
5
- import { useContext, useEffect, useState } from "react";
6
- var getWebColorMode = () => {
7
- if (typeof globalThis === "undefined") return "light";
8
- const globalScope = globalThis;
9
- if (!globalScope.matchMedia) {
10
- return "light";
11
- }
12
- return globalScope.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
13
- };
14
- function useColorMode() {
15
- const [webScheme, setWebScheme] = useState(() => getWebColorMode());
16
- useEffect(() => {
17
- if (typeof globalThis === "undefined") return;
18
- const globalScope = globalThis;
19
- if (!globalScope.matchMedia) return;
20
- const media = globalScope.matchMedia("(prefers-color-scheme: dark)");
21
- const handleChange = () => {
22
- setWebScheme(media.matches ? "dark" : "light");
23
- };
24
- handleChange();
25
- if (typeof media.addEventListener === "function") {
26
- media.addEventListener("change", handleChange);
27
- return () => media.removeEventListener?.("change", handleChange);
28
- }
29
- const legacyMedia = media;
30
- legacyMedia.addListener?.(handleChange);
31
- return () => legacyMedia.removeListener?.(handleChange);
32
- }, []);
33
- return webScheme;
34
- }
35
- function useXUITheme() {
36
- const theme = useContext(XUIThemeContext);
37
- if (!theme) {
38
- throw new Error("useXUITheme must be used within XUIProvider");
39
- }
40
- return theme;
41
- }
42
- function useXUIColors() {
43
- const theme = useXUITheme();
44
- return theme.colors;
45
- }
46
-
47
- // src/core/theme-context.tsx
48
- import { defaultTheme } from "@xaui/core/theme";
49
- import { jsx } from "react/jsx-runtime";
50
- var XUIThemeContext = createContext(null);
51
- function XUIProvider({
52
- children,
53
- theme: lightTheme,
54
- darkTheme
55
- }) {
56
- const colorScheme = useColorMode();
57
- const theme = React.useMemo(() => {
58
- if (!darkTheme && !lightTheme) return defaultTheme;
59
- const activeTheme = colorScheme === "dark" && darkTheme ? darkTheme : lightTheme;
60
- if (!activeTheme) return defaultTheme;
61
- return {
62
- ...defaultTheme,
63
- ...activeTheme,
64
- colors: {
65
- ...defaultTheme.colors,
66
- ...activeTheme.colors
67
- },
68
- fontFamilies: {
69
- ...defaultTheme.fontFamilies,
70
- ...activeTheme.fontFamilies
71
- },
72
- fontSizes: {
73
- ...defaultTheme.fontSizes,
74
- ...activeTheme.fontSizes
75
- }
76
- };
77
- }, [lightTheme, darkTheme, colorScheme]);
78
- return /* @__PURE__ */ jsx(XUIThemeContext.Provider, { value: theme, children });
79
- }
1
+ import {
2
+ XUIProvider,
3
+ useBorderRadiusStyles,
4
+ useColorMode,
5
+ useXUIColors,
6
+ useXUIPalette,
7
+ useXUITheme
8
+ } from "../chunk-YJF3QRMW.js";
80
9
  export {
81
10
  XUIProvider,
11
+ useBorderRadiusStyles,
82
12
  useColorMode,
83
13
  useXUIColors,
14
+ useXUIPalette,
84
15
  useXUITheme
85
16
  };
@@ -0,0 +1,63 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { ReactNode } from 'react';
3
+
4
+ type ColorMode$1 = 'light' | 'dark';
5
+ type CSSVarValue = string | number;
6
+ type XUIVariables = Record<`--xui-${string}`, CSSVarValue>;
7
+ interface XUIProviderProps {
8
+ children: ReactNode;
9
+ colorScheme?: ColorMode$1;
10
+ target?: 'html' | 'body';
11
+ variables?: Partial<XUIVariables>;
12
+ darkVariables?: Partial<XUIVariables>;
13
+ }
14
+ declare function XUIProvider({ children, colorScheme, target, variables, darkVariables, }: XUIProviderProps): react_jsx_runtime.JSX.Element;
15
+
16
+ type Size = 'xs' | 'sm' | 'md' | 'lg';
17
+ type Radius = 'none' | 'sm' | 'md' | 'lg' | 'full';
18
+ type SizeValues = {
19
+ xs: number;
20
+ sm: number;
21
+ md: number;
22
+ lg: number;
23
+ };
24
+ type RadiusValues = {
25
+ none: number;
26
+ sm: number;
27
+ md: number;
28
+ lg: number;
29
+ full: number;
30
+ };
31
+
32
+ type ColorMode = 'light' | 'dark';
33
+ type CSSVarString = `var(--${string})`;
34
+ type CSSColorScheme = {
35
+ main: CSSVarString;
36
+ foreground: CSSVarString;
37
+ background: CSSVarString;
38
+ };
39
+ type HybridXUITheme = {
40
+ mode: ColorMode;
41
+ palette: Record<string, CSSVarString>;
42
+ colors: {
43
+ primary: CSSColorScheme;
44
+ secondary: CSSColorScheme;
45
+ tertiary: CSSColorScheme;
46
+ danger: CSSColorScheme;
47
+ warning: CSSColorScheme;
48
+ success: CSSColorScheme;
49
+ default: CSSColorScheme;
50
+ background: CSSVarString;
51
+ foreground: CSSVarString;
52
+ };
53
+ borderRadius: Record<Radius, CSSVarString>;
54
+ };
55
+ declare function useColorMode(): ColorMode;
56
+ declare function useXUITheme(): HybridXUITheme;
57
+ declare function useXUIColors(): HybridXUITheme['colors'];
58
+ declare function useXUIPalette(): HybridXUITheme['palette'];
59
+ declare function useBorderRadiusStyles(radius: Radius): {
60
+ borderRadius: string;
61
+ };
62
+
63
+ export { type Radius as R, type Size as S, XUIProvider as X, type XUIProviderProps as a, type XUIVariables as b, useXUITheme as c, useXUIColors as d, useXUIPalette as e, useBorderRadiusStyles as f, type SizeValues as g, type RadiusValues as h, useColorMode as u };
@@ -0,0 +1,51 @@
1
+ import React, { ReactNode, CSSProperties } from 'react';
2
+
3
+ type ThemeColor = 'primary' | 'secondary' | 'tertiary' | 'danger' | 'warning' | 'success' | 'default';
4
+
5
+ type AlertVariant = 'solid' | 'bordered' | 'flat' | 'faded';
6
+ type AlertRadius = 'none' | 'sm' | 'md' | 'lg' | 'full';
7
+ type AlertEvents = {
8
+ onClose?: () => void;
9
+ onVisibleChange?: (isVisible: boolean) => void;
10
+ };
11
+ type AlertCustomAppearance = {
12
+ container?: CSSProperties;
13
+ title?: CSSProperties;
14
+ description?: CSSProperties;
15
+ };
16
+ type AlertProps = {
17
+ title?: ReactNode;
18
+ description?: ReactNode;
19
+ icon?: ReactNode;
20
+ /**
21
+ * @default 'default'
22
+ */
23
+ themeColor?: ThemeColor;
24
+ /**
25
+ * @default 'flat'
26
+ */
27
+ variant?: AlertVariant;
28
+ /**
29
+ * @default 'md'
30
+ */
31
+ radius?: AlertRadius;
32
+ /**
33
+ * @default false
34
+ */
35
+ isClosable?: boolean;
36
+ /**
37
+ * @default false
38
+ */
39
+ hideIcon?: boolean;
40
+ closeButton?: ReactNode;
41
+ /**
42
+ * @default true
43
+ */
44
+ isVisible?: boolean;
45
+ customAppearance?: AlertCustomAppearance;
46
+ children?: ReactNode;
47
+ } & AlertEvents;
48
+
49
+ declare const Alert: React.FC<AlertProps>;
50
+
51
+ export { Alert as A, type ThemeColor as T, type AlertProps as a, type AlertVariant as b, type AlertRadius as c };
package/dist/index.css ADDED
@@ -0,0 +1,305 @@
1
+ /* XUI Design System
2
+ * Import this file once in your app's root CSS:
3
+ * @import "@xaui/hybrid/dist/index.css";
4
+ *
5
+ * All --xui-* variables can be overridden to customize the theme.
6
+ */
7
+
8
+ :root {
9
+ /* Primary */
10
+ --xui-primary: #6b21a8;
11
+ --xui-primary-fg: #ffffff;
12
+ --xui-primary-bg: #e9d5ff;
13
+
14
+ /* Secondary */
15
+ --xui-secondary: #71717a;
16
+ --xui-secondary-fg: #ffffff;
17
+ --xui-secondary-bg: #e4e4e7;
18
+
19
+ /* Tertiary */
20
+ --xui-tertiary: #78716c;
21
+ --xui-tertiary-fg: #ffffff;
22
+ --xui-tertiary-bg: #f5f5f4;
23
+
24
+ /* Danger */
25
+ --xui-danger: #b91c1c;
26
+ --xui-danger-fg: #ffffff;
27
+ --xui-danger-bg: #fecdd3;
28
+
29
+ /* Warning */
30
+ --xui-warning: #d97706;
31
+ --xui-warning-fg: #111827;
32
+ --xui-warning-bg: #fef3c7;
33
+
34
+ /* Success */
35
+ --xui-success: #16a34a;
36
+ --xui-success-fg: #ffffff;
37
+ --xui-success-bg: #dcfce7;
38
+
39
+ /* Default */
40
+ --xui-default: #18181b;
41
+ --xui-default-fg: #ffffff;
42
+ --xui-default-bg: #e4e4e7;
43
+
44
+ /* Global */
45
+ --xui-background: #ffffff;
46
+ --xui-foreground: #18181b;
47
+
48
+ /* Spacing */
49
+ --xui-spacing-xs: 4px;
50
+ --xui-spacing-sm: 8px;
51
+ --xui-spacing-md: 16px;
52
+ --xui-spacing-lg: 24px;
53
+ --xui-spacing-xl: 32px;
54
+ --xui-spacing-2xl: 48px;
55
+ --xui-spacing-3xl: 64px;
56
+
57
+ /* Border radius */
58
+ --xui-radius-none: 0px;
59
+ --xui-radius-sm: 4px;
60
+ --xui-radius-md: 8px;
61
+ --xui-radius-lg: 12px;
62
+ --xui-radius-xl: 16px;
63
+ --xui-radius-2xl: 24px;
64
+ --xui-radius-3xl: 32px;
65
+ --xui-radius-full: 9999px;
66
+
67
+ /* Border width */
68
+ --xui-border-none: 0px;
69
+ --xui-border-xs: 0.5px;
70
+ --xui-border-sm: 1px;
71
+ --xui-border-md: 1.75px;
72
+ --xui-border-lg: 2.5px;
73
+ --xui-border-xl: 3px;
74
+
75
+ /* Font sizes */
76
+ --xui-text-xs: 12px;
77
+ --xui-text-sm: 14px;
78
+ --xui-text-md: 16px;
79
+ --xui-text-lg: 18px;
80
+ --xui-text-xl: 20px;
81
+ --xui-text-2xl: 24px;
82
+ --xui-text-3xl: 30px;
83
+ --xui-text-4xl: 36px;
84
+
85
+ /* Font weights */
86
+ --xui-font-light: 300;
87
+ --xui-font-normal: 400;
88
+ --xui-font-medium: 500;
89
+ --xui-font-semibold: 600;
90
+ --xui-font-bold: 700;
91
+ --xui-font-extrabold: 800;
92
+
93
+ /* Component sizes */
94
+ --xui-size-xs: 38px;
95
+ --xui-size-sm: 42px;
96
+ --xui-size-md: 46px;
97
+ --xui-size-lg: 50px;
98
+ }
99
+
100
+ /* Dark mode — toggled by setting data-color-scheme on <html> */
101
+ [data-color-scheme='dark'] {
102
+ --xui-primary: #d8b4fe;
103
+ --xui-primary-fg: #3b0764;
104
+ --xui-primary-bg: #4c1d95;
105
+
106
+ --xui-secondary: #d4d4d8;
107
+ --xui-secondary-fg: #3f3f46;
108
+ --xui-secondary-bg: #52525b;
109
+
110
+ --xui-tertiary: #fecaca;
111
+ --xui-tertiary-fg: #500724;
112
+ --xui-tertiary-bg: #57534e;
113
+
114
+ --xui-danger: #fca5a5;
115
+ --xui-danger-fg: #4c0519;
116
+ --xui-danger-bg: #991b1b;
117
+
118
+ --xui-warning: #fbbf24;
119
+ --xui-warning-fg: #f9fafb;
120
+ --xui-warning-bg: #78350f;
121
+
122
+ --xui-success: #4ade80;
123
+ --xui-success-fg: #f9fafb;
124
+ --xui-success-bg: #14532d;
125
+
126
+ --xui-default: #e7e5e4;
127
+ --xui-default-fg: #18181b;
128
+ --xui-default-bg: #3f3f46;
129
+
130
+ --xui-background: #18181b;
131
+ --xui-foreground: #e7e5e4;
132
+ }
133
+
134
+ /* SSR/no-JS fallback: honor OS dark mode until data-color-scheme is set */
135
+ @media (prefers-color-scheme: dark) {
136
+ :root:not([data-color-scheme]) {
137
+ --xui-primary: #d8b4fe;
138
+ --xui-primary-fg: #3b0764;
139
+ --xui-primary-bg: #4c1d95;
140
+
141
+ --xui-secondary: #d4d4d8;
142
+ --xui-secondary-fg: #3f3f46;
143
+ --xui-secondary-bg: #52525b;
144
+
145
+ --xui-tertiary: #fecaca;
146
+ --xui-tertiary-fg: #500724;
147
+ --xui-tertiary-bg: #57534e;
148
+
149
+ --xui-danger: #fca5a5;
150
+ --xui-danger-fg: #4c0519;
151
+ --xui-danger-bg: #991b1b;
152
+
153
+ --xui-warning: #fbbf24;
154
+ --xui-warning-fg: #f9fafb;
155
+ --xui-warning-bg: #78350f;
156
+
157
+ --xui-success: #4ade80;
158
+ --xui-success-fg: #f9fafb;
159
+ --xui-success-bg: #14532d;
160
+
161
+ --xui-default: #e7e5e4;
162
+ --xui-default-fg: #18181b;
163
+ --xui-default-bg: #3f3f46;
164
+
165
+ --xui-background: #18181b;
166
+ --xui-foreground: #e7e5e4;
167
+ }
168
+ }
169
+
170
+ /* Animations CSS — used via data-xui-state attribute */
171
+ @keyframes xui-fade-in {
172
+ from {
173
+ opacity: 0;
174
+ transform: scale(0.95);
175
+ }
176
+ to {
177
+ opacity: 1;
178
+ transform: scale(1);
179
+ }
180
+ }
181
+
182
+ @keyframes xui-fade-out {
183
+ from {
184
+ opacity: 1;
185
+ transform: scale(1);
186
+ }
187
+ to {
188
+ opacity: 0;
189
+ transform: scale(0.95);
190
+ }
191
+ }
192
+
193
+ [data-xui-state='open'] {
194
+ animation: xui-fade-in 250ms ease forwards;
195
+ }
196
+
197
+ [data-xui-state='closed'] {
198
+ animation: xui-fade-out 250ms ease forwards;
199
+ }
200
+
201
+ /* Alert mode tokens derived from selected --xui-alert-* role vars */
202
+ .xui-alert {
203
+ --xui-alert-solid-bg: var(--xui-alert-main);
204
+ --xui-alert-solid-text: #ffffff;
205
+ --xui-alert-solid-icon-bg: color-mix(in srgb, #ffffff 16%, transparent);
206
+ --xui-alert-flat-bg: var(--xui-alert-bg-base);
207
+ }
208
+
209
+ [data-color-scheme='dark'] .xui-alert {
210
+ --xui-alert-solid-bg: var(--xui-alert-bg-base);
211
+ --xui-alert-solid-text: var(--xui-alert-main);
212
+ --xui-alert-solid-icon-bg: color-mix(in srgb, var(--xui-alert-main) 16%, transparent);
213
+ --xui-alert-flat-bg: color-mix(in srgb, var(--xui-alert-bg-base) 50%, transparent);
214
+ }
215
+
216
+ @media (prefers-color-scheme: dark) {
217
+ :root:not([data-color-scheme]) .xui-alert {
218
+ --xui-alert-solid-bg: var(--xui-alert-bg-base);
219
+ --xui-alert-solid-text: var(--xui-alert-main);
220
+ --xui-alert-solid-icon-bg: color-mix(in srgb, var(--xui-alert-main) 16%, transparent);
221
+ --xui-alert-flat-bg: color-mix(in srgb, var(--xui-alert-bg-base) 50%, transparent);
222
+ }
223
+ }
224
+
225
+ /* Tailwind v4 — register XUI tokens as utilities via @theme inline.
226
+ * Colors become: bg-primary, text-primary-fg, border-danger, etc.
227
+ * Spacing becomes: p-xui-md, m-xui-lg, gap-xui-sm, etc.
228
+ * Radius becomes: rounded-xui-md, rounded-xui-full, etc.
229
+ */
230
+ @theme inline {
231
+ /* Colors */
232
+ --color-primary: var(--xui-primary);
233
+ --color-primary-fg: var(--xui-primary-fg);
234
+ --color-primary-bg: var(--xui-primary-bg);
235
+
236
+ --color-secondary: var(--xui-secondary);
237
+ --color-secondary-fg: var(--xui-secondary-fg);
238
+ --color-secondary-bg: var(--xui-secondary-bg);
239
+
240
+ --color-tertiary: var(--xui-tertiary);
241
+ --color-tertiary-fg: var(--xui-tertiary-fg);
242
+ --color-tertiary-bg: var(--xui-tertiary-bg);
243
+
244
+ --color-danger: var(--xui-danger);
245
+ --color-danger-fg: var(--xui-danger-fg);
246
+ --color-danger-bg: var(--xui-danger-bg);
247
+
248
+ --color-warning: var(--xui-warning);
249
+ --color-warning-fg: var(--xui-warning-fg);
250
+ --color-warning-bg: var(--xui-warning-bg);
251
+
252
+ --color-success: var(--xui-success);
253
+ --color-success-fg: var(--xui-success-fg);
254
+ --color-success-bg: var(--xui-success-bg);
255
+
256
+ --color-default: var(--xui-default);
257
+ --color-default-fg: var(--xui-default-fg);
258
+ --color-default-bg: var(--xui-default-bg);
259
+
260
+ --color-xui-background: var(--xui-background);
261
+ --color-xui-foreground: var(--xui-foreground);
262
+
263
+ /* Spacing */
264
+ --spacing-xui-xs: var(--xui-spacing-xs);
265
+ --spacing-xui-sm: var(--xui-spacing-sm);
266
+ --spacing-xui-md: var(--xui-spacing-md);
267
+ --spacing-xui-lg: var(--xui-spacing-lg);
268
+ --spacing-xui-xl: var(--xui-spacing-xl);
269
+ --spacing-xui-2xl: var(--xui-spacing-2xl);
270
+ --spacing-xui-3xl: var(--xui-spacing-3xl);
271
+
272
+ /* Border radius */
273
+ --radius-xui-none: var(--xui-radius-none);
274
+ --radius-xui-sm: var(--xui-radius-sm);
275
+ --radius-xui-md: var(--xui-radius-md);
276
+ --radius-xui-lg: var(--xui-radius-lg);
277
+ --radius-xui-xl: var(--xui-radius-xl);
278
+ --radius-xui-2xl: var(--xui-radius-2xl);
279
+ --radius-xui-3xl: var(--xui-radius-3xl);
280
+ --radius-xui-full: var(--xui-radius-full);
281
+
282
+ /* Font sizes */
283
+ --text-xui-xs: var(--xui-text-xs);
284
+ --text-xui-sm: var(--xui-text-sm);
285
+ --text-xui-md: var(--xui-text-md);
286
+ --text-xui-lg: var(--xui-text-lg);
287
+ --text-xui-xl: var(--xui-text-xl);
288
+ --text-xui-2xl: var(--xui-text-2xl);
289
+ --text-xui-3xl: var(--xui-text-3xl);
290
+ --text-xui-4xl: var(--xui-text-4xl);
291
+
292
+ /* Font weights */
293
+ --font-weight-xui-light: var(--xui-font-light);
294
+ --font-weight-xui-normal: var(--xui-font-normal);
295
+ --font-weight-xui-medium: var(--xui-font-medium);
296
+ --font-weight-xui-semibold: var(--xui-font-semibold);
297
+ --font-weight-xui-bold: var(--xui-font-bold);
298
+ --font-weight-xui-extrabold: var(--xui-font-extrabold);
299
+
300
+ /* Component sizes (as spacing — usable as w-xui-size-md, h-xui-size-lg, etc.) */
301
+ --spacing-xui-size-xs: var(--xui-size-xs);
302
+ --spacing-xui-size-sm: var(--xui-size-sm);
303
+ --spacing-xui-size-md: var(--xui-size-md);
304
+ --spacing-xui-size-lg: var(--xui-size-lg);
305
+ }
package/dist/index.d.ts CHANGED
@@ -1,2 +1,13 @@
1
+ export { R as Radius, h as RadiusValues, S as Size, g as SizeValues, X as XUIProvider, a as XUIProviderProps, b as XUIVariables, f as useBorderRadiusStyles, u as useColorMode, d as useXUIColors, e as useXUIPalette, c as useXUITheme } from './index-5BCfEjU-.js';
2
+ import { ClassValue } from 'clsx';
3
+ export { A as Alert, a as AlertProps, c as AlertRadius, b as AlertVariant, T as ThemeColor } from './index-CMptPfU-.js';
4
+ import 'react/jsx-runtime';
5
+ import 'react';
1
6
 
2
- export { }
7
+ /**
8
+ * Merges class names using clsx and tailwind-merge.
9
+ * Useful for handling conditional classes and resolving Tailwind conflicts.
10
+ */
11
+ declare function cn(...inputs: ClassValue[]): string;
12
+
13
+ export { cn };
package/dist/index.js CHANGED
@@ -0,0 +1,28 @@
1
+ import {
2
+ XUIProvider,
3
+ useBorderRadiusStyles,
4
+ useColorMode,
5
+ useXUIColors,
6
+ useXUIPalette,
7
+ useXUITheme
8
+ } from "./chunk-YJF3QRMW.js";
9
+ import {
10
+ Alert
11
+ } from "./chunk-7HVBAJHB.js";
12
+
13
+ // src/utils/cn.ts
14
+ import { clsx } from "clsx";
15
+ import { twMerge } from "tailwind-merge";
16
+ function cn(...inputs) {
17
+ return twMerge(clsx(inputs));
18
+ }
19
+ export {
20
+ Alert,
21
+ XUIProvider,
22
+ cn,
23
+ useBorderRadiusStyles,
24
+ useColorMode,
25
+ useXUIColors,
26
+ useXUIPalette,
27
+ useXUITheme
28
+ };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@xaui/hybrid",
3
- "version": "0.0.8",
4
- "description": "Flutter-inspired React UI components for web and mobile webview applications with Framer Motion animations and Tailwind CSS styling",
3
+ "version": "0.0.9",
4
+ "description": "Flutter-inspired React UI components for web and mobile webview with Tailwind CSS styling and CSS animations",
5
5
  "keywords": [
6
6
  "react",
7
7
  "web",
@@ -10,7 +10,6 @@
10
10
  "ui",
11
11
  "components",
12
12
  "flutter",
13
- "framer-motion",
14
13
  "tailwindcss",
15
14
  "xaui"
16
15
  ],
@@ -20,28 +19,15 @@
20
19
  "exports": {
21
20
  ".": {
22
21
  "types": "./dist/index.d.ts",
23
- "import": "./dist/index.js",
24
- "require": "./dist/index.js"
22
+ "import": "./dist/index.js"
25
23
  },
26
24
  "./core": {
27
25
  "types": "./dist/core/index.d.ts",
28
- "import": "./dist/core/index.js",
29
- "require": "./dist/core/index.js"
26
+ "import": "./dist/core/index.js"
30
27
  },
31
- "./button": {
32
- "types": "./dist/button/index.d.ts",
33
- "import": "./dist/button/index.js",
34
- "require": "./dist/button/index.js"
35
- },
36
- "./progress": {
37
- "types": "./dist/progress/index.d.ts",
38
- "import": "./dist/progress/index.js",
39
- "require": "./dist/progress/index.js"
40
- },
41
- "./indicator": {
42
- "types": "./dist/indicator/index.d.ts",
43
- "import": "./dist/indicator/index.js",
44
- "require": "./dist/indicator/index.js"
28
+ "./alert": {
29
+ "types": "./dist/alert/index.d.ts",
30
+ "import": "./dist/alert/index.js"
45
31
  },
46
32
  "./dist/index.css": "./dist/index.css"
47
33
  },
@@ -68,7 +54,6 @@
68
54
  "devDependencies": {
69
55
  "@types/react": "^19.1.0",
70
56
  "@types/react-dom": "^19.1.0",
71
- "esbuild-sass-plugin": "^3.6.0",
72
57
  "react": "19.1.0",
73
58
  "react-dom": "19.1.0",
74
59
  "tsup": "^8.5.1",
@@ -1,125 +0,0 @@
1
- "use strict";
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __export = (target, all) => {
9
- for (var name in all)
10
- __defProp(target, name, { get: all[name], enumerable: true });
11
- };
12
- var __copyProps = (to, from, except, desc) => {
13
- if (from && typeof from === "object" || typeof from === "function") {
14
- for (let key of __getOwnPropNames(from))
15
- if (!__hasOwnProp.call(to, key) && key !== except)
16
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
- }
18
- return to;
19
- };
20
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
- // If the importer is in node compatibility mode or this is not an ESM
22
- // file that has been converted to a CommonJS file using a Babel-
23
- // compatible transform (i.e. "__esModule" has not been set), then set
24
- // "default" to the CommonJS "module.exports" for node compatibility.
25
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
- mod
27
- ));
28
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
-
30
- // src/core/index.ts
31
- var core_exports = {};
32
- __export(core_exports, {
33
- XUIProvider: () => XUIProvider,
34
- useColorMode: () => useColorMode,
35
- useXUIColors: () => useXUIColors,
36
- useXUITheme: () => useXUITheme
37
- });
38
- module.exports = __toCommonJS(core_exports);
39
-
40
- // src/core/theme-context.tsx
41
- var import_react2 = __toESM(require("react"), 1);
42
-
43
- // src/core/theme-hooks.ts
44
- var import_react = require("react");
45
- var getWebColorMode = () => {
46
- if (typeof globalThis === "undefined") return "light";
47
- const globalScope = globalThis;
48
- if (!globalScope.matchMedia) {
49
- return "light";
50
- }
51
- return globalScope.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
52
- };
53
- function useColorMode() {
54
- const [webScheme, setWebScheme] = (0, import_react.useState)(() => getWebColorMode());
55
- (0, import_react.useEffect)(() => {
56
- if (typeof globalThis === "undefined") return;
57
- const globalScope = globalThis;
58
- if (!globalScope.matchMedia) return;
59
- const media = globalScope.matchMedia("(prefers-color-scheme: dark)");
60
- const handleChange = () => {
61
- setWebScheme(media.matches ? "dark" : "light");
62
- };
63
- handleChange();
64
- if (typeof media.addEventListener === "function") {
65
- media.addEventListener("change", handleChange);
66
- return () => media.removeEventListener?.("change", handleChange);
67
- }
68
- const legacyMedia = media;
69
- legacyMedia.addListener?.(handleChange);
70
- return () => legacyMedia.removeListener?.(handleChange);
71
- }, []);
72
- return webScheme;
73
- }
74
- function useXUITheme() {
75
- const theme = (0, import_react.useContext)(XUIThemeContext);
76
- if (!theme) {
77
- throw new Error("useXUITheme must be used within XUIProvider");
78
- }
79
- return theme;
80
- }
81
- function useXUIColors() {
82
- const theme = useXUITheme();
83
- return theme.colors;
84
- }
85
-
86
- // src/core/theme-context.tsx
87
- var import_theme = require("@xaui/core/theme");
88
- var import_jsx_runtime = require("react/jsx-runtime");
89
- var XUIThemeContext = (0, import_react2.createContext)(null);
90
- function XUIProvider({
91
- children,
92
- theme: lightTheme,
93
- darkTheme
94
- }) {
95
- const colorScheme = useColorMode();
96
- const theme = import_react2.default.useMemo(() => {
97
- if (!darkTheme && !lightTheme) return import_theme.defaultTheme;
98
- const activeTheme = colorScheme === "dark" && darkTheme ? darkTheme : lightTheme;
99
- if (!activeTheme) return import_theme.defaultTheme;
100
- return {
101
- ...import_theme.defaultTheme,
102
- ...activeTheme,
103
- colors: {
104
- ...import_theme.defaultTheme.colors,
105
- ...activeTheme.colors
106
- },
107
- fontFamilies: {
108
- ...import_theme.defaultTheme.fontFamilies,
109
- ...activeTheme.fontFamilies
110
- },
111
- fontSizes: {
112
- ...import_theme.defaultTheme.fontSizes,
113
- ...activeTheme.fontSizes
114
- }
115
- };
116
- }, [lightTheme, darkTheme, colorScheme]);
117
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(XUIThemeContext.Provider, { value: theme, children });
118
- }
119
- // Annotate the CommonJS export names for ESM import in node:
120
- 0 && (module.exports = {
121
- XUIProvider,
122
- useColorMode,
123
- useXUIColors,
124
- useXUITheme
125
- });
@@ -1,20 +0,0 @@
1
- import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { ReactNode } from 'react';
3
- import { XUITheme } from '@xaui/core/theme';
4
-
5
- type DeepPartial<T> = {
6
- [P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
7
- };
8
- interface XUIProviderProps {
9
- children: ReactNode;
10
- theme?: DeepPartial<XUITheme>;
11
- darkTheme?: DeepPartial<XUITheme>;
12
- }
13
- declare function XUIProvider({ children, theme: lightTheme, darkTheme, }: XUIProviderProps): react_jsx_runtime.JSX.Element;
14
-
15
- type ColorMode = 'light' | 'dark';
16
- declare function useColorMode(): ColorMode;
17
- declare function useXUITheme(): XUITheme;
18
- declare function useXUIColors(): XUITheme['colors'];
19
-
20
- export { XUIProvider, useColorMode, useXUIColors, useXUITheme };
package/dist/index.cjs DELETED
@@ -1,18 +0,0 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __copyProps = (to, from, except, desc) => {
7
- if (from && typeof from === "object" || typeof from === "function") {
8
- for (let key of __getOwnPropNames(from))
9
- if (!__hasOwnProp.call(to, key) && key !== except)
10
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
11
- }
12
- return to;
13
- };
14
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
15
-
16
- // src/index.ts
17
- var src_exports = {};
18
- module.exports = __toCommonJS(src_exports);
package/dist/index.d.cts DELETED
@@ -1,2 +0,0 @@
1
-
2
- export { }