@true-kit/ui 0.1.0 → 0.1.1

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/dist/index.css ADDED
@@ -0,0 +1,38 @@
1
+ /* src/components/Button/Button.css */
2
+ .ui-button {
3
+ border: 0;
4
+ font-family: var(--ui-font-family);
5
+ font-size: var(--ui-font-size-md);
6
+ border-radius: var(--ui-radius-md);
7
+ cursor: pointer;
8
+ transition: background-color 150ms ease, opacity 150ms ease;
9
+ }
10
+ .ui-button--sm {
11
+ padding: var(--ui-spacing-xs) var(--ui-spacing-sm);
12
+ }
13
+ .ui-button--md {
14
+ padding: var(--ui-spacing-sm) var(--ui-spacing-md);
15
+ }
16
+ .ui-button--lg {
17
+ padding: var(--ui-spacing-md) var(--ui-spacing-lg);
18
+ }
19
+ .ui-button--primary {
20
+ background: var(--ui-color-primary);
21
+ color: var(--ui-color-primary-foreground);
22
+ }
23
+ .ui-button--primary:hover:not(:disabled) {
24
+ background: var(--ui-color-primary-hover);
25
+ }
26
+ .ui-button--secondary {
27
+ background: var(--ui-color-secondary);
28
+ color: var(--ui-color-secondary-foreground);
29
+ }
30
+ .ui-button--danger {
31
+ background: var(--ui-color-danger);
32
+ color: #ffffff;
33
+ }
34
+ .ui-button:disabled {
35
+ opacity: 0.5;
36
+ cursor: not-allowed;
37
+ }
38
+ /*# sourceMappingURL=index.css.map */
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/Button/Button.css"],"sourcesContent":[".ui-button {\r\n border: 0;\r\n\r\n font-family: var(--ui-font-family);\r\n font-size: var(--ui-font-size-md);\r\n\r\n border-radius: var(--ui-radius-md);\r\n\r\n cursor: pointer;\r\n\r\n transition:\r\n background-color 150ms ease,\r\n opacity 150ms ease;\r\n}\r\n\r\n.ui-button--sm {\r\n padding:\r\n var(--ui-spacing-xs) var(--ui-spacing-sm);\r\n}\r\n\r\n.ui-button--md {\r\n padding:\r\n var(--ui-spacing-sm) var(--ui-spacing-md);\r\n}\r\n\r\n.ui-button--lg {\r\n padding:\r\n var(--ui-spacing-md) var(--ui-spacing-lg);\r\n}\r\n\r\n.ui-button--primary {\r\n background: var(--ui-color-primary);\r\n color: var(--ui-color-primary-foreground);\r\n}\r\n\r\n.ui-button--primary:hover:not(:disabled) {\r\n background: var(--ui-color-primary-hover);\r\n}\r\n\r\n.ui-button--secondary {\r\n background: var(--ui-color-secondary);\r\n color: var(--ui-color-secondary-foreground);\r\n}\r\n\r\n.ui-button--danger {\r\n background: var(--ui-color-danger);\r\n color: #ffffff;\r\n}\r\n\r\n.ui-button:disabled {\r\n opacity: 0.5;\r\n cursor: not-allowed;\r\n}"],"mappings":";AAAA,CAAC;AACG,UAAQ;AAER,eAAa,IAAI;AACjB,aAAW,IAAI;AAEf,iBAAe,IAAI;AAEnB,UAAQ;AAER,cACI,iBAAiB,MAAM,IAAI,EAC3B,QAAQ,MAAM;AACtB;AAEA,CAAC;AACG,WACI,IAAI,iBAAiB,IAAI;AACjC;AAEA,CAAC;AACG,WACI,IAAI,iBAAiB,IAAI;AACjC;AAEA,CAAC;AACG,WACI,IAAI,iBAAiB,IAAI;AACjC;AAEA,CAAC;AACG,cAAY,IAAI;AAChB,SAAO,IAAI;AACf;AAEA,CALC,kBAKkB,MAAM,KAAK;AAC1B,cAAY,IAAI;AACpB;AAEA,CAAC;AACG,cAAY,IAAI;AAChB,SAAO,IAAI;AACf;AAEA,CAAC;AACG,cAAY,IAAI;AAChB,SAAO;AACX;AAEA,CAjDC,SAiDS;AACN,WAAS;AACT,UAAQ;AACZ;","names":[]}
@@ -0,0 +1,69 @@
1
+ import * as react from 'react';
2
+ import { ReactNode, ButtonHTMLAttributes } from 'react';
3
+
4
+ interface UITheme {
5
+ color?: {
6
+ primary?: string;
7
+ primaryHover?: string;
8
+ primaryActive?: string;
9
+ primaryForeground?: string;
10
+ secondary?: string;
11
+ secondaryHover?: string;
12
+ secondaryForeground?: string;
13
+ background?: string;
14
+ foreground?: string;
15
+ surface?: string;
16
+ border?: string;
17
+ muted?: string;
18
+ success?: string;
19
+ warning?: string;
20
+ danger?: string;
21
+ };
22
+ radius?: {
23
+ sm?: string;
24
+ md?: string;
25
+ lg?: string;
26
+ xl?: string;
27
+ full?: string;
28
+ };
29
+ spacing?: {
30
+ xs?: string;
31
+ sm?: string;
32
+ md?: string;
33
+ lg?: string;
34
+ xl?: string;
35
+ };
36
+ font?: {
37
+ family?: string;
38
+ size?: {
39
+ sm?: string;
40
+ md?: string;
41
+ lg?: string;
42
+ xl?: string;
43
+ };
44
+ };
45
+ shadow?: {
46
+ sm?: string;
47
+ md?: string;
48
+ lg?: string;
49
+ };
50
+ }
51
+
52
+ interface UIProviderProps {
53
+ children: ReactNode;
54
+ theme?: UITheme;
55
+ }
56
+ declare function UIProvider({ children, theme, }: UIProviderProps): react.JSX.Element;
57
+ declare function useUITheme(): UITheme;
58
+
59
+ interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
60
+ children: ReactNode;
61
+ variant?: "primary" | "secondary" | "danger";
62
+ size?: "sm" | "md" | "lg";
63
+ loading?: boolean;
64
+ disabled?: boolean;
65
+ }
66
+
67
+ declare function Button({ children, variant, size, loading, disabled, className, ...props }: ButtonProps): react.JSX.Element;
68
+
69
+ export { Button, type ButtonProps, UIProvider, type UITheme, useUITheme };
@@ -0,0 +1,69 @@
1
+ import * as react from 'react';
2
+ import { ReactNode, ButtonHTMLAttributes } from 'react';
3
+
4
+ interface UITheme {
5
+ color?: {
6
+ primary?: string;
7
+ primaryHover?: string;
8
+ primaryActive?: string;
9
+ primaryForeground?: string;
10
+ secondary?: string;
11
+ secondaryHover?: string;
12
+ secondaryForeground?: string;
13
+ background?: string;
14
+ foreground?: string;
15
+ surface?: string;
16
+ border?: string;
17
+ muted?: string;
18
+ success?: string;
19
+ warning?: string;
20
+ danger?: string;
21
+ };
22
+ radius?: {
23
+ sm?: string;
24
+ md?: string;
25
+ lg?: string;
26
+ xl?: string;
27
+ full?: string;
28
+ };
29
+ spacing?: {
30
+ xs?: string;
31
+ sm?: string;
32
+ md?: string;
33
+ lg?: string;
34
+ xl?: string;
35
+ };
36
+ font?: {
37
+ family?: string;
38
+ size?: {
39
+ sm?: string;
40
+ md?: string;
41
+ lg?: string;
42
+ xl?: string;
43
+ };
44
+ };
45
+ shadow?: {
46
+ sm?: string;
47
+ md?: string;
48
+ lg?: string;
49
+ };
50
+ }
51
+
52
+ interface UIProviderProps {
53
+ children: ReactNode;
54
+ theme?: UITheme;
55
+ }
56
+ declare function UIProvider({ children, theme, }: UIProviderProps): react.JSX.Element;
57
+ declare function useUITheme(): UITheme;
58
+
59
+ interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
60
+ children: ReactNode;
61
+ variant?: "primary" | "secondary" | "danger";
62
+ size?: "sm" | "md" | "lg";
63
+ loading?: boolean;
64
+ disabled?: boolean;
65
+ }
66
+
67
+ declare function Button({ children, variant, size, loading, disabled, className, ...props }: ButtonProps): react.JSX.Element;
68
+
69
+ export { Button, type ButtonProps, UIProvider, type UITheme, useUITheme };
package/dist/index.js ADDED
@@ -0,0 +1,178 @@
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 __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ Button: () => Button,
24
+ UIProvider: () => UIProvider,
25
+ useUITheme: () => useUITheme
26
+ });
27
+ module.exports = __toCommonJS(index_exports);
28
+
29
+ // src/theme/UIProvider.tsx
30
+ var import_react = require("react");
31
+
32
+ // src/theme/defaultTheme.ts
33
+ var defaultTheme = {
34
+ color: {
35
+ primary: "#2563eb",
36
+ primaryHover: "#1d4ed8",
37
+ primaryActive: "#1e40af",
38
+ primaryForeground: "#ffffff",
39
+ secondary: "#64748b",
40
+ secondaryHover: "#475569",
41
+ secondaryForeground: "#ffffff",
42
+ background: "#ffffff",
43
+ foreground: "#0f172a",
44
+ surface: "#f8fafc",
45
+ border: "#e2e8f0",
46
+ muted: "#64748b",
47
+ success: "#16a34a",
48
+ warning: "#d97706",
49
+ danger: "#dc2626"
50
+ },
51
+ radius: {
52
+ sm: "4px",
53
+ md: "8px",
54
+ lg: "12px",
55
+ xl: "16px",
56
+ full: "9999px"
57
+ },
58
+ spacing: {
59
+ xs: "4px",
60
+ sm: "8px",
61
+ md: "16px",
62
+ lg: "24px",
63
+ xl: "32px"
64
+ },
65
+ font: {
66
+ family: "inherit",
67
+ size: {
68
+ sm: "12px",
69
+ md: "14px",
70
+ lg: "16px",
71
+ xl: "20px"
72
+ }
73
+ },
74
+ shadow: {
75
+ sm: "0 1px 2px rgba(0,0,0,0.05)",
76
+ md: "0 4px 6px rgba(0,0,0,0.1)",
77
+ lg: "0 10px 15px rgba(0,0,0,0.1)"
78
+ }
79
+ };
80
+
81
+ // src/theme/utils.ts
82
+ var camelToKebab = (value) => value.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
83
+ function themeToCSSVariables(theme, prefix = "ui") {
84
+ const variables = {};
85
+ const walk = (object, path = []) => {
86
+ Object.entries(object).forEach(([key, value]) => {
87
+ if (value === void 0 || value === null) return;
88
+ const nextPath = [...path, camelToKebab(key)];
89
+ if (typeof value === "object" && !Array.isArray(value)) {
90
+ walk(value, nextPath);
91
+ return;
92
+ }
93
+ variables[`--${prefix}-${nextPath.join("-")}`] = String(value);
94
+ });
95
+ };
96
+ walk(theme);
97
+ return variables;
98
+ }
99
+ function mergeTheme(target, source) {
100
+ if (!source) {
101
+ return { ...target };
102
+ }
103
+ const result = { ...target };
104
+ Object.entries(source).forEach(([key, sourceValue]) => {
105
+ const targetValue = result[key];
106
+ if (sourceValue !== null && typeof sourceValue === "object" && !Array.isArray(sourceValue)) {
107
+ result[key] = mergeTheme(
108
+ targetValue ?? {},
109
+ sourceValue
110
+ );
111
+ } else if (sourceValue !== void 0) {
112
+ result[key] = sourceValue;
113
+ }
114
+ });
115
+ return result;
116
+ }
117
+
118
+ // src/theme/UIProvider.tsx
119
+ var import_jsx_runtime = require("react/jsx-runtime");
120
+ var ThemeContext = (0, import_react.createContext)(defaultTheme);
121
+ function UIProvider({
122
+ children,
123
+ theme
124
+ }) {
125
+ const mergedTheme = (0, import_react.useMemo)(
126
+ () => mergeTheme(defaultTheme, theme),
127
+ [theme]
128
+ );
129
+ const cssVariables = (0, import_react.useMemo)(
130
+ () => themeToCSSVariables(mergedTheme),
131
+ [mergedTheme]
132
+ );
133
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ThemeContext.Provider, { value: mergedTheme, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
134
+ "div",
135
+ {
136
+ "data-ui-provider": "",
137
+ style: cssVariables,
138
+ children
139
+ }
140
+ ) });
141
+ }
142
+ function useUITheme() {
143
+ return (0, import_react.useContext)(ThemeContext);
144
+ }
145
+
146
+ // src/components/Button/Button.tsx
147
+ var import_jsx_runtime2 = require("react/jsx-runtime");
148
+ function Button({
149
+ children,
150
+ variant = "primary",
151
+ size = "md",
152
+ loading = false,
153
+ disabled,
154
+ className = "",
155
+ ...props
156
+ }) {
157
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
158
+ "button",
159
+ {
160
+ ...props,
161
+ disabled: disabled || loading,
162
+ className: [
163
+ "ui-button",
164
+ `ui-button--${variant}`,
165
+ `ui-button--${size}`,
166
+ className
167
+ ].filter(Boolean).join(" "),
168
+ children: loading ? "Loading..." : children
169
+ }
170
+ );
171
+ }
172
+ // Annotate the CommonJS export names for ESM import in node:
173
+ 0 && (module.exports = {
174
+ Button,
175
+ UIProvider,
176
+ useUITheme
177
+ });
178
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/theme/UIProvider.tsx","../src/theme/defaultTheme.ts","../src/theme/utils.ts","../src/components/Button/Button.tsx"],"sourcesContent":["export {\r\n UIProvider,\r\n useUITheme,\r\n} from \"./theme/UIProvider\";\r\n\r\nexport type {\r\n UITheme,\r\n} from \"./theme/types\";\r\n\r\nexport {\r\n Button,\r\n} from \"./components/Button\";\r\n\r\nexport type {\r\n ButtonProps,\r\n} from \"./components/Button\";","import {\r\n createContext,\r\n useContext,\r\n useMemo,\r\n type CSSProperties,\r\n type ReactNode,\r\n} from \"react\";\r\n\r\nimport { defaultTheme } from \"./defaultTheme\";\r\nimport { mergeTheme, themeToCSSVariables } from \"./utils\";\r\nimport type { UITheme } from \"./types\";\r\n\r\ninterface UIProviderProps {\r\n children: ReactNode;\r\n theme?: UITheme;\r\n}\r\n\r\nconst ThemeContext = createContext<UITheme>(defaultTheme);\r\n\r\nexport function UIProvider({\r\n children,\r\n theme,\r\n}: UIProviderProps) {\r\n const mergedTheme = useMemo(\r\n () => mergeTheme(defaultTheme as any, theme),\r\n [theme]\r\n );\r\n\r\n const cssVariables = useMemo(\r\n () => themeToCSSVariables(mergedTheme),\r\n [mergedTheme]\r\n );\r\n\r\n return (\r\n <ThemeContext.Provider value={mergedTheme}>\r\n <div\r\n data-ui-provider=\"\"\r\n style={cssVariables as CSSProperties}\r\n >\r\n {children}\r\n </div>\r\n </ThemeContext.Provider>\r\n );\r\n}\r\n\r\nexport function useUITheme() {\r\n return useContext(ThemeContext);\r\n}","import type { UITheme } from \"./types\";\r\n\r\nexport const defaultTheme: UITheme = {\r\n color: {\r\n primary: \"#2563eb\",\r\n primaryHover: \"#1d4ed8\",\r\n primaryActive: \"#1e40af\",\r\n primaryForeground: \"#ffffff\",\r\n\r\n secondary: \"#64748b\",\r\n secondaryHover: \"#475569\",\r\n secondaryForeground: \"#ffffff\",\r\n\r\n background: \"#ffffff\",\r\n foreground: \"#0f172a\",\r\n surface: \"#f8fafc\",\r\n border: \"#e2e8f0\",\r\n muted: \"#64748b\",\r\n\r\n success: \"#16a34a\",\r\n warning: \"#d97706\",\r\n danger: \"#dc2626\",\r\n },\r\n\r\n radius: {\r\n sm: \"4px\",\r\n md: \"8px\",\r\n lg: \"12px\",\r\n xl: \"16px\",\r\n full: \"9999px\",\r\n },\r\n\r\n spacing: {\r\n xs: \"4px\",\r\n sm: \"8px\",\r\n md: \"16px\",\r\n lg: \"24px\",\r\n xl: \"32px\",\r\n },\r\n\r\n font: {\r\n family: \"inherit\",\r\n\r\n size: {\r\n sm: \"12px\",\r\n md: \"14px\",\r\n lg: \"16px\",\r\n xl: \"20px\",\r\n },\r\n },\r\n\r\n shadow: {\r\n sm: \"0 1px 2px rgba(0,0,0,0.05)\",\r\n md: \"0 4px 6px rgba(0,0,0,0.1)\",\r\n lg: \"0 10px 15px rgba(0,0,0,0.1)\",\r\n },\r\n};","import type { CSSProperties } from \"react\";\r\nimport type { UITheme } from \"./types\";\r\n\r\ntype CSSVariables = CSSProperties & Record<`--ui-${string}`, string>;\r\n\r\nconst camelToKebab = (value: string) =>\r\n value.replace(/([a-z0-9])([A-Z])/g, \"$1-$2\").toLowerCase();\r\n\r\nexport function themeToCSSVariables(\r\n theme: UITheme,\r\n prefix = \"ui\"\r\n): CSSVariables {\r\n const variables: Record<string, string> = {};\r\n\r\n const walk = (\r\n object: Record<string, unknown>,\r\n path: string[] = []\r\n ) => {\r\n Object.entries(object).forEach(([key, value]) => {\r\n if (value === undefined || value === null) return;\r\n\r\n const nextPath = [...path, camelToKebab(key)];\r\n\r\n if (typeof value === \"object\" && !Array.isArray(value)) {\r\n walk(value as Record<string, unknown>, nextPath);\r\n return;\r\n }\r\n\r\n variables[\r\n `--${prefix}-${nextPath.join(\"-\")}`\r\n ] = String(value);\r\n });\r\n };\r\n\r\n walk(theme as Record<string, unknown>);\r\n\r\n return variables as CSSVariables;\r\n}\r\n\r\nexport function mergeTheme<T extends Record<string, unknown>>(\r\n target: T,\r\n source?: Partial<T>\r\n): T {\r\n if (!source) {\r\n return { ...target };\r\n }\r\n\r\n const result: Record<string, unknown> = { ...target };\r\n\r\n Object.entries(source).forEach(([key, sourceValue]) => {\r\n const targetValue = result[key];\r\n\r\n if (\r\n sourceValue !== null &&\r\n typeof sourceValue === \"object\" &&\r\n !Array.isArray(sourceValue)\r\n ) {\r\n result[key] = mergeTheme(\r\n (targetValue ?? {}) as Record<string, unknown>,\r\n sourceValue as Record<string, unknown>\r\n );\r\n } else if (sourceValue !== undefined) {\r\n result[key] = sourceValue;\r\n }\r\n });\r\n\r\n return result as T;\r\n}","import type { ButtonProps } from \"./Button.types\";\r\n\r\nimport \"./Button.css\";\r\n\r\nexport function Button({\r\n children,\r\n variant = \"primary\",\r\n size = \"md\",\r\n loading = false,\r\n disabled,\r\n className = \"\",\r\n ...props\r\n}: ButtonProps) {\r\n return (\r\n <button\r\n {...props}\r\n disabled={disabled || loading}\r\n className={[\r\n \"ui-button\",\r\n `ui-button--${variant}`,\r\n `ui-button--${size}`,\r\n className,\r\n ]\r\n .filter(Boolean)\r\n .join(\" \")}\r\n >\r\n {loading ? \"Loading...\" : children}\r\n </button>\r\n );\r\n}"],"mappings":"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","names":["import_jsx_runtime"]}
package/dist/index.mjs ADDED
@@ -0,0 +1,153 @@
1
+ // src/theme/UIProvider.tsx
2
+ import {
3
+ createContext,
4
+ useContext,
5
+ useMemo
6
+ } from "react";
7
+
8
+ // src/theme/defaultTheme.ts
9
+ var defaultTheme = {
10
+ color: {
11
+ primary: "#2563eb",
12
+ primaryHover: "#1d4ed8",
13
+ primaryActive: "#1e40af",
14
+ primaryForeground: "#ffffff",
15
+ secondary: "#64748b",
16
+ secondaryHover: "#475569",
17
+ secondaryForeground: "#ffffff",
18
+ background: "#ffffff",
19
+ foreground: "#0f172a",
20
+ surface: "#f8fafc",
21
+ border: "#e2e8f0",
22
+ muted: "#64748b",
23
+ success: "#16a34a",
24
+ warning: "#d97706",
25
+ danger: "#dc2626"
26
+ },
27
+ radius: {
28
+ sm: "4px",
29
+ md: "8px",
30
+ lg: "12px",
31
+ xl: "16px",
32
+ full: "9999px"
33
+ },
34
+ spacing: {
35
+ xs: "4px",
36
+ sm: "8px",
37
+ md: "16px",
38
+ lg: "24px",
39
+ xl: "32px"
40
+ },
41
+ font: {
42
+ family: "inherit",
43
+ size: {
44
+ sm: "12px",
45
+ md: "14px",
46
+ lg: "16px",
47
+ xl: "20px"
48
+ }
49
+ },
50
+ shadow: {
51
+ sm: "0 1px 2px rgba(0,0,0,0.05)",
52
+ md: "0 4px 6px rgba(0,0,0,0.1)",
53
+ lg: "0 10px 15px rgba(0,0,0,0.1)"
54
+ }
55
+ };
56
+
57
+ // src/theme/utils.ts
58
+ var camelToKebab = (value) => value.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
59
+ function themeToCSSVariables(theme, prefix = "ui") {
60
+ const variables = {};
61
+ const walk = (object, path = []) => {
62
+ Object.entries(object).forEach(([key, value]) => {
63
+ if (value === void 0 || value === null) return;
64
+ const nextPath = [...path, camelToKebab(key)];
65
+ if (typeof value === "object" && !Array.isArray(value)) {
66
+ walk(value, nextPath);
67
+ return;
68
+ }
69
+ variables[`--${prefix}-${nextPath.join("-")}`] = String(value);
70
+ });
71
+ };
72
+ walk(theme);
73
+ return variables;
74
+ }
75
+ function mergeTheme(target, source) {
76
+ if (!source) {
77
+ return { ...target };
78
+ }
79
+ const result = { ...target };
80
+ Object.entries(source).forEach(([key, sourceValue]) => {
81
+ const targetValue = result[key];
82
+ if (sourceValue !== null && typeof sourceValue === "object" && !Array.isArray(sourceValue)) {
83
+ result[key] = mergeTheme(
84
+ targetValue ?? {},
85
+ sourceValue
86
+ );
87
+ } else if (sourceValue !== void 0) {
88
+ result[key] = sourceValue;
89
+ }
90
+ });
91
+ return result;
92
+ }
93
+
94
+ // src/theme/UIProvider.tsx
95
+ import { jsx } from "react/jsx-runtime";
96
+ var ThemeContext = createContext(defaultTheme);
97
+ function UIProvider({
98
+ children,
99
+ theme
100
+ }) {
101
+ const mergedTheme = useMemo(
102
+ () => mergeTheme(defaultTheme, theme),
103
+ [theme]
104
+ );
105
+ const cssVariables = useMemo(
106
+ () => themeToCSSVariables(mergedTheme),
107
+ [mergedTheme]
108
+ );
109
+ return /* @__PURE__ */ jsx(ThemeContext.Provider, { value: mergedTheme, children: /* @__PURE__ */ jsx(
110
+ "div",
111
+ {
112
+ "data-ui-provider": "",
113
+ style: cssVariables,
114
+ children
115
+ }
116
+ ) });
117
+ }
118
+ function useUITheme() {
119
+ return useContext(ThemeContext);
120
+ }
121
+
122
+ // src/components/Button/Button.tsx
123
+ import { jsx as jsx2 } from "react/jsx-runtime";
124
+ function Button({
125
+ children,
126
+ variant = "primary",
127
+ size = "md",
128
+ loading = false,
129
+ disabled,
130
+ className = "",
131
+ ...props
132
+ }) {
133
+ return /* @__PURE__ */ jsx2(
134
+ "button",
135
+ {
136
+ ...props,
137
+ disabled: disabled || loading,
138
+ className: [
139
+ "ui-button",
140
+ `ui-button--${variant}`,
141
+ `ui-button--${size}`,
142
+ className
143
+ ].filter(Boolean).join(" "),
144
+ children: loading ? "Loading..." : children
145
+ }
146
+ );
147
+ }
148
+ export {
149
+ Button,
150
+ UIProvider,
151
+ useUITheme
152
+ };
153
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/theme/UIProvider.tsx","../src/theme/defaultTheme.ts","../src/theme/utils.ts","../src/components/Button/Button.tsx"],"sourcesContent":["import {\r\n createContext,\r\n useContext,\r\n useMemo,\r\n type CSSProperties,\r\n type ReactNode,\r\n} from \"react\";\r\n\r\nimport { defaultTheme } from \"./defaultTheme\";\r\nimport { mergeTheme, themeToCSSVariables } from \"./utils\";\r\nimport type { UITheme } from \"./types\";\r\n\r\ninterface UIProviderProps {\r\n children: ReactNode;\r\n theme?: UITheme;\r\n}\r\n\r\nconst ThemeContext = createContext<UITheme>(defaultTheme);\r\n\r\nexport function UIProvider({\r\n children,\r\n theme,\r\n}: UIProviderProps) {\r\n const mergedTheme = useMemo(\r\n () => mergeTheme(defaultTheme as any, theme),\r\n [theme]\r\n );\r\n\r\n const cssVariables = useMemo(\r\n () => themeToCSSVariables(mergedTheme),\r\n [mergedTheme]\r\n );\r\n\r\n return (\r\n <ThemeContext.Provider value={mergedTheme}>\r\n <div\r\n data-ui-provider=\"\"\r\n style={cssVariables as CSSProperties}\r\n >\r\n {children}\r\n </div>\r\n </ThemeContext.Provider>\r\n );\r\n}\r\n\r\nexport function useUITheme() {\r\n return useContext(ThemeContext);\r\n}","import type { UITheme } from \"./types\";\r\n\r\nexport const defaultTheme: UITheme = {\r\n color: {\r\n primary: \"#2563eb\",\r\n primaryHover: \"#1d4ed8\",\r\n primaryActive: \"#1e40af\",\r\n primaryForeground: \"#ffffff\",\r\n\r\n secondary: \"#64748b\",\r\n secondaryHover: \"#475569\",\r\n secondaryForeground: \"#ffffff\",\r\n\r\n background: \"#ffffff\",\r\n foreground: \"#0f172a\",\r\n surface: \"#f8fafc\",\r\n border: \"#e2e8f0\",\r\n muted: \"#64748b\",\r\n\r\n success: \"#16a34a\",\r\n warning: \"#d97706\",\r\n danger: \"#dc2626\",\r\n },\r\n\r\n radius: {\r\n sm: \"4px\",\r\n md: \"8px\",\r\n lg: \"12px\",\r\n xl: \"16px\",\r\n full: \"9999px\",\r\n },\r\n\r\n spacing: {\r\n xs: \"4px\",\r\n sm: \"8px\",\r\n md: \"16px\",\r\n lg: \"24px\",\r\n xl: \"32px\",\r\n },\r\n\r\n font: {\r\n family: \"inherit\",\r\n\r\n size: {\r\n sm: \"12px\",\r\n md: \"14px\",\r\n lg: \"16px\",\r\n xl: \"20px\",\r\n },\r\n },\r\n\r\n shadow: {\r\n sm: \"0 1px 2px rgba(0,0,0,0.05)\",\r\n md: \"0 4px 6px rgba(0,0,0,0.1)\",\r\n lg: \"0 10px 15px rgba(0,0,0,0.1)\",\r\n },\r\n};","import type { CSSProperties } from \"react\";\r\nimport type { UITheme } from \"./types\";\r\n\r\ntype CSSVariables = CSSProperties & Record<`--ui-${string}`, string>;\r\n\r\nconst camelToKebab = (value: string) =>\r\n value.replace(/([a-z0-9])([A-Z])/g, \"$1-$2\").toLowerCase();\r\n\r\nexport function themeToCSSVariables(\r\n theme: UITheme,\r\n prefix = \"ui\"\r\n): CSSVariables {\r\n const variables: Record<string, string> = {};\r\n\r\n const walk = (\r\n object: Record<string, unknown>,\r\n path: string[] = []\r\n ) => {\r\n Object.entries(object).forEach(([key, value]) => {\r\n if (value === undefined || value === null) return;\r\n\r\n const nextPath = [...path, camelToKebab(key)];\r\n\r\n if (typeof value === \"object\" && !Array.isArray(value)) {\r\n walk(value as Record<string, unknown>, nextPath);\r\n return;\r\n }\r\n\r\n variables[\r\n `--${prefix}-${nextPath.join(\"-\")}`\r\n ] = String(value);\r\n });\r\n };\r\n\r\n walk(theme as Record<string, unknown>);\r\n\r\n return variables as CSSVariables;\r\n}\r\n\r\nexport function mergeTheme<T extends Record<string, unknown>>(\r\n target: T,\r\n source?: Partial<T>\r\n): T {\r\n if (!source) {\r\n return { ...target };\r\n }\r\n\r\n const result: Record<string, unknown> = { ...target };\r\n\r\n Object.entries(source).forEach(([key, sourceValue]) => {\r\n const targetValue = result[key];\r\n\r\n if (\r\n sourceValue !== null &&\r\n typeof sourceValue === \"object\" &&\r\n !Array.isArray(sourceValue)\r\n ) {\r\n result[key] = mergeTheme(\r\n (targetValue ?? {}) as Record<string, unknown>,\r\n sourceValue as Record<string, unknown>\r\n );\r\n } else if (sourceValue !== undefined) {\r\n result[key] = sourceValue;\r\n }\r\n });\r\n\r\n return result as T;\r\n}","import type { ButtonProps } from \"./Button.types\";\r\n\r\nimport \"./Button.css\";\r\n\r\nexport function Button({\r\n children,\r\n variant = \"primary\",\r\n size = \"md\",\r\n loading = false,\r\n disabled,\r\n className = \"\",\r\n ...props\r\n}: ButtonProps) {\r\n return (\r\n <button\r\n {...props}\r\n disabled={disabled || loading}\r\n className={[\r\n \"ui-button\",\r\n `ui-button--${variant}`,\r\n `ui-button--${size}`,\r\n className,\r\n ]\r\n .filter(Boolean)\r\n .join(\" \")}\r\n >\r\n {loading ? \"Loading...\" : children}\r\n </button>\r\n );\r\n}"],"mappings":"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","names":["jsx"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@true-kit/ui",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Reusable React UI components",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -32,4 +32,4 @@
32
32
  "publishConfig": {
33
33
  "access": "public"
34
34
  }
35
- }
35
+ }