@true-kit/ui 0.1.3 → 0.1.6

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.d.mts CHANGED
@@ -1,5 +1,6 @@
1
1
  import * as react from 'react';
2
- import { ReactNode, ButtonHTMLAttributes } from 'react';
2
+ import { ReactNode, ButtonHTMLAttributes, InputHTMLAttributes } from 'react';
3
+ import { FieldValues, Control, FieldPath } from 'react-hook-form';
3
4
 
4
5
  interface UITheme {
5
6
  color?: {
@@ -66,4 +67,21 @@ interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
66
67
 
67
68
  declare function Button({ children, variant, size, loading, disabled, className, ...props }: ButtonProps): react.JSX.Element;
68
69
 
69
- export { Button, type ButtonProps, UIProvider, type UITheme, useUITheme };
70
+ interface InputControllerClasses {
71
+ root?: string;
72
+ label?: string;
73
+ input?: string;
74
+ error?: string;
75
+ }
76
+ interface InputControllerProps<TFieldValues extends FieldValues = FieldValues> extends Omit<InputHTMLAttributes<HTMLInputElement>, "name"> {
77
+ label?: ReactNode;
78
+ placeholder?: string;
79
+ control: Control<TFieldValues>;
80
+ name: FieldPath<TFieldValues>;
81
+ classes?: InputControllerClasses;
82
+ showError?: boolean;
83
+ }
84
+
85
+ declare function InputController<TFieldValues extends Record<string, unknown>>({ label, placeholder, control, name, classes, showError, id, ...props }: InputControllerProps<TFieldValues>): react.JSX.Element;
86
+
87
+ export { Button, type ButtonProps, InputController, type InputControllerClasses, type InputControllerProps, UIProvider, type UITheme, useUITheme };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import * as react from 'react';
2
- import { ReactNode, ButtonHTMLAttributes } from 'react';
2
+ import { ReactNode, ButtonHTMLAttributes, InputHTMLAttributes } from 'react';
3
+ import { FieldValues, Control, FieldPath } from 'react-hook-form';
3
4
 
4
5
  interface UITheme {
5
6
  color?: {
@@ -66,4 +67,21 @@ interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
66
67
 
67
68
  declare function Button({ children, variant, size, loading, disabled, className, ...props }: ButtonProps): react.JSX.Element;
68
69
 
69
- export { Button, type ButtonProps, UIProvider, type UITheme, useUITheme };
70
+ interface InputControllerClasses {
71
+ root?: string;
72
+ label?: string;
73
+ input?: string;
74
+ error?: string;
75
+ }
76
+ interface InputControllerProps<TFieldValues extends FieldValues = FieldValues> extends Omit<InputHTMLAttributes<HTMLInputElement>, "name"> {
77
+ label?: ReactNode;
78
+ placeholder?: string;
79
+ control: Control<TFieldValues>;
80
+ name: FieldPath<TFieldValues>;
81
+ classes?: InputControllerClasses;
82
+ showError?: boolean;
83
+ }
84
+
85
+ declare function InputController<TFieldValues extends Record<string, unknown>>({ label, placeholder, control, name, classes, showError, id, ...props }: InputControllerProps<TFieldValues>): react.JSX.Element;
86
+
87
+ export { Button, type ButtonProps, InputController, type InputControllerClasses, type InputControllerProps, UIProvider, type UITheme, useUITheme };
package/dist/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  "use strict";
2
+ "use client";
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
@@ -21,6 +22,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
22
  var index_exports = {};
22
23
  __export(index_exports, {
23
24
  Button: () => Button,
25
+ InputController: () => InputController,
24
26
  UIProvider: () => UIProvider,
25
27
  useUITheme: () => useUITheme
26
28
  });
@@ -143,6 +145,31 @@ function useUITheme() {
143
145
  return (0, import_react.useContext)(ThemeContext);
144
146
  }
145
147
 
148
+ // #style-inject:#style-inject
149
+ function styleInject(css, { insertAt } = {}) {
150
+ if (!css || typeof document === "undefined") return;
151
+ const head = document.head || document.getElementsByTagName("head")[0];
152
+ const style = document.createElement("style");
153
+ style.type = "text/css";
154
+ if (insertAt === "top") {
155
+ if (head.firstChild) {
156
+ head.insertBefore(style, head.firstChild);
157
+ } else {
158
+ head.appendChild(style);
159
+ }
160
+ } else {
161
+ head.appendChild(style);
162
+ }
163
+ if (style.styleSheet) {
164
+ style.styleSheet.cssText = css;
165
+ } else {
166
+ style.appendChild(document.createTextNode(css));
167
+ }
168
+ }
169
+
170
+ // src/components/Button/Button.css
171
+ styleInject(".ui-button {\n border: 0;\n font-family: var(--ui-font-family);\n font-size: var(--ui-font-size-md);\n border-radius: var(--ui-radius-md);\n cursor: pointer;\n transition: background-color 150ms ease, opacity 150ms ease;\n}\n.ui-button--sm {\n padding: var(--ui-spacing-xs) var(--ui-spacing-sm);\n}\n.ui-button--md {\n padding: var(--ui-spacing-sm) var(--ui-spacing-md);\n}\n.ui-button--lg {\n padding: var(--ui-spacing-md) var(--ui-spacing-lg);\n}\n.ui-button--primary {\n background: var(--ui-color-primary);\n color: var(--ui-color-primary-foreground);\n}\n.ui-button--primary:hover:not(:disabled) {\n background: var(--ui-color-primary-hover);\n}\n.ui-button--secondary {\n background: var(--ui-color-secondary);\n color: var(--ui-color-secondary-foreground);\n}\n.ui-button--danger {\n background: var(--ui-color-danger);\n color: #ffffff;\n}\n.ui-button:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n");
172
+
146
173
  // src/components/Button/Button.tsx
147
174
  var import_jsx_runtime2 = require("react/jsx-runtime");
148
175
  function Button({
@@ -169,9 +196,99 @@ function Button({
169
196
  }
170
197
  );
171
198
  }
199
+
200
+ // src/components/InputController/Controller.tsx
201
+ var import_react_hook_form = require("react-hook-form");
202
+
203
+ // src/components/InputController/Controller.css
204
+ styleInject(".ui-input-controller {\n display: flex;\n flex-direction: column;\n gap: var(--ui-spacing-xs);\n}\n.ui-input-controller__label {\n font-family: var(--ui-font-family);\n font-size: var(--ui-font-size-sm);\n color: var(--ui-color-foreground);\n cursor: pointer;\n}\n.ui-input-controller__input {\n width: 100%;\n box-sizing: border-box;\n padding: var(--ui-spacing-sm) var(--ui-spacing-md);\n font-family: var(--ui-font-family);\n font-size: var(--ui-font-size-md);\n color: var(--ui-color-foreground);\n background: var(--ui-color-background);\n border: 1px solid var(--ui-color-border);\n border-radius: var(--ui-radius-md);\n outline: none;\n transition:\n border-color 150ms ease,\n box-shadow 150ms ease,\n opacity 150ms ease;\n}\n.ui-input-controller__input::placeholder {\n color: var(--ui-color-muted-foreground);\n}\n.ui-input-controller__input:hover:not(:disabled) {\n border-color: var(--ui-color-primary);\n}\n.ui-input-controller__input:focus {\n border-color: var(--ui-color-primary);\n box-shadow: 0 0 0 2px color-mix(in srgb, var(--ui-color-primary) 15%, transparent);\n}\n.ui-input-controller__input--error {\n border-color: var(--ui-color-danger);\n}\n.ui-input-controller__input--error:focus {\n border-color: var(--ui-color-danger);\n box-shadow: 0 0 0 2px color-mix(in srgb, var(--ui-color-danger) 15%, transparent);\n}\n.ui-input-controller__input--disabled,\n.ui-input-controller__input:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n.ui-input-controller__error {\n font-family: var(--ui-font-family);\n font-size: var(--ui-font-size-sm);\n color: var(--ui-color-danger);\n}\n");
205
+
206
+ // src/components/InputController/Controller.tsx
207
+ var import_jsx_runtime3 = require("react/jsx-runtime");
208
+ function InputController({
209
+ label,
210
+ placeholder,
211
+ control,
212
+ name,
213
+ classes = {},
214
+ showError = true,
215
+ id,
216
+ ...props
217
+ }) {
218
+ const inputId = id ?? String(name);
219
+ const errorId = `${inputId}-error`;
220
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
221
+ import_react_hook_form.Controller,
222
+ {
223
+ name,
224
+ control,
225
+ render: ({
226
+ field,
227
+ fieldState
228
+ }) => {
229
+ const hasError = Boolean(fieldState.error);
230
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
231
+ "div",
232
+ {
233
+ className: [
234
+ "ui-input-controller",
235
+ classes.root
236
+ ].filter(Boolean).join(" "),
237
+ children: [
238
+ label && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
239
+ "label",
240
+ {
241
+ htmlFor: inputId,
242
+ className: [
243
+ "ui-input-controller__label",
244
+ classes.label
245
+ ].filter(Boolean).join(" "),
246
+ children: label
247
+ }
248
+ ),
249
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
250
+ "input",
251
+ {
252
+ ...props,
253
+ ...field,
254
+ id: inputId,
255
+ name: field.name,
256
+ placeholder,
257
+ value: field.value ?? "",
258
+ "aria-invalid": hasError,
259
+ "aria-describedby": hasError && showError ? errorId : void 0,
260
+ disabled: props.disabled || field.disabled,
261
+ className: [
262
+ "ui-input-controller__input",
263
+ hasError ? "ui-input-controller__input--error" : "",
264
+ props.disabled ? "ui-input-controller__input--disabled" : "",
265
+ classes.input
266
+ ].filter(Boolean).join(" ")
267
+ }
268
+ ),
269
+ hasError && showError && fieldState.error?.message && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
270
+ "span",
271
+ {
272
+ id: errorId,
273
+ role: "alert",
274
+ className: [
275
+ "ui-input-controller__error",
276
+ classes.error
277
+ ].filter(Boolean).join(" "),
278
+ children: fieldState.error.message
279
+ }
280
+ )
281
+ ]
282
+ }
283
+ );
284
+ }
285
+ }
286
+ );
287
+ }
172
288
  // Annotate the CommonJS export names for ESM import in node:
173
289
  0 && (module.exports = {
174
290
  Button,
291
+ InputController,
175
292
  UIProvider,
176
293
  useUITheme
177
294
  });
package/dist/index.js.map CHANGED
@@ -1 +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\";","\"use client\";\r\nimport {\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"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/theme/UIProvider.tsx","../src/theme/defaultTheme.ts","../src/theme/utils.ts","#style-inject:#style-inject","../src/components/Button/Button.css","../src/components/Button/Button.tsx","../src/components/InputController/Controller.tsx","../src/components/InputController/Controller.css"],"sourcesContent":["\"use client\";\r\n\r\n// UI Provider\r\nexport { UIProvider, useUITheme } from \"./theme/UIProvider\";\r\nexport type { UITheme } from \"./theme/types\";\r\n\r\n// Buttons\r\nexport { Button } from \"./components/Button\";\r\nexport type { ButtonProps } from \"./components/Button\";\r\n\r\n// Controllers\r\nexport { InputController } from \"./components/InputController\"\r\nexport type { InputControllerClasses, InputControllerProps } from \"./components/InputController\"","\"use client\";\r\nimport {\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}","\n export default function styleInject(css, { insertAt } = {}) {\n if (!css || typeof document === 'undefined') return\n \n const head = document.head || document.getElementsByTagName('head')[0]\n const style = document.createElement('style')\n style.type = 'text/css'\n \n if (insertAt === 'top') {\n if (head.firstChild) {\n head.insertBefore(style, head.firstChild)\n } else {\n head.appendChild(style)\n }\n } else {\n head.appendChild(style)\n }\n \n if (style.styleSheet) {\n style.styleSheet.cssText = css\n } else {\n style.appendChild(document.createTextNode(css))\n }\n }\n ","import styleInject from '#style-inject';styleInject(\".ui-button {\\n border: 0;\\n font-family: var(--ui-font-family);\\n font-size: var(--ui-font-size-md);\\n border-radius: var(--ui-radius-md);\\n cursor: pointer;\\n transition: background-color 150ms ease, opacity 150ms ease;\\n}\\n.ui-button--sm {\\n padding: var(--ui-spacing-xs) var(--ui-spacing-sm);\\n}\\n.ui-button--md {\\n padding: var(--ui-spacing-sm) var(--ui-spacing-md);\\n}\\n.ui-button--lg {\\n padding: var(--ui-spacing-md) var(--ui-spacing-lg);\\n}\\n.ui-button--primary {\\n background: var(--ui-color-primary);\\n color: var(--ui-color-primary-foreground);\\n}\\n.ui-button--primary:hover:not(:disabled) {\\n background: var(--ui-color-primary-hover);\\n}\\n.ui-button--secondary {\\n background: var(--ui-color-secondary);\\n color: var(--ui-color-secondary-foreground);\\n}\\n.ui-button--danger {\\n background: var(--ui-color-danger);\\n color: #ffffff;\\n}\\n.ui-button:disabled {\\n opacity: 0.5;\\n cursor: not-allowed;\\n}\\n\")","import type { ButtonProps } from \"./Button.types\";\r\nimport \"./Button.css\";\r\n\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}","\"use client\";\r\n\r\nimport { Controller } from \"react-hook-form\";\r\n\r\nimport type { InputControllerProps } from \"./Controller.types\";\r\n\r\nimport \"./Controller.css\";\r\n\r\nexport function InputController<\r\n TFieldValues extends Record<string, unknown>,\r\n>({\r\n label,\r\n placeholder,\r\n control,\r\n name,\r\n classes = {},\r\n showError = true,\r\n id,\r\n ...props\r\n}: InputControllerProps<TFieldValues>) {\r\n const inputId = id ?? String(name);\r\n const errorId = `${inputId}-error`;\r\n\r\n return (\r\n <Controller\r\n name={name}\r\n control={control}\r\n render={({\r\n field,\r\n fieldState,\r\n }) => {\r\n const hasError = Boolean(fieldState.error);\r\n\r\n return (\r\n <div\r\n className={[\r\n \"ui-input-controller\",\r\n classes.root,\r\n ]\r\n .filter(Boolean)\r\n .join(\" \")}\r\n >\r\n {label && (\r\n <label\r\n htmlFor={inputId}\r\n className={[\r\n \"ui-input-controller__label\",\r\n classes.label,\r\n ]\r\n .filter(Boolean)\r\n .join(\" \")}\r\n >\r\n {label}\r\n </label>\r\n )}\r\n\r\n <input\r\n {...props}\r\n {...field}\r\n id={inputId}\r\n name={field.name}\r\n placeholder={placeholder}\r\n value={field.value ?? \"\" as any}\r\n aria-invalid={\r\n hasError\r\n }\r\n aria-describedby={\r\n hasError && showError\r\n ? errorId\r\n : undefined\r\n }\r\n disabled={\r\n props.disabled ||\r\n field.disabled\r\n }\r\n className={[\r\n \"ui-input-controller__input\",\r\n hasError\r\n ? \"ui-input-controller__input--error\"\r\n : \"\",\r\n props.disabled\r\n ? \"ui-input-controller__input--disabled\"\r\n : \"\",\r\n classes.input,\r\n ]\r\n .filter(Boolean)\r\n .join(\" \")}\r\n />\r\n\r\n {hasError &&\r\n showError &&\r\n fieldState.error?.message && (\r\n <span\r\n id={errorId}\r\n role=\"alert\"\r\n className={[\r\n \"ui-input-controller__error\",\r\n classes.error,\r\n ]\r\n .filter(Boolean)\r\n .join(\" \")}\r\n >\r\n {\r\n fieldState\r\n .error\r\n .message\r\n }\r\n </span>\r\n )}\r\n </div>\r\n );\r\n }}\r\n />\r\n );\r\n}","import styleInject from '#style-inject';styleInject(\".ui-input-controller {\\n display: flex;\\n flex-direction: column;\\n gap: var(--ui-spacing-xs);\\n}\\n.ui-input-controller__label {\\n font-family: var(--ui-font-family);\\n font-size: var(--ui-font-size-sm);\\n color: var(--ui-color-foreground);\\n cursor: pointer;\\n}\\n.ui-input-controller__input {\\n width: 100%;\\n box-sizing: border-box;\\n padding: var(--ui-spacing-sm) var(--ui-spacing-md);\\n font-family: var(--ui-font-family);\\n font-size: var(--ui-font-size-md);\\n color: var(--ui-color-foreground);\\n background: var(--ui-color-background);\\n border: 1px solid var(--ui-color-border);\\n border-radius: var(--ui-radius-md);\\n outline: none;\\n transition:\\n border-color 150ms ease,\\n box-shadow 150ms ease,\\n opacity 150ms ease;\\n}\\n.ui-input-controller__input::placeholder {\\n color: var(--ui-color-muted-foreground);\\n}\\n.ui-input-controller__input:hover:not(:disabled) {\\n border-color: var(--ui-color-primary);\\n}\\n.ui-input-controller__input:focus {\\n border-color: var(--ui-color-primary);\\n box-shadow: 0 0 0 2px color-mix(in srgb, var(--ui-color-primary) 15%, transparent);\\n}\\n.ui-input-controller__input--error {\\n border-color: var(--ui-color-danger);\\n}\\n.ui-input-controller__input--error:focus {\\n border-color: var(--ui-color-danger);\\n box-shadow: 0 0 0 2px color-mix(in srgb, var(--ui-color-danger) 15%, transparent);\\n}\\n.ui-input-controller__input--disabled,\\n.ui-input-controller__input:disabled {\\n opacity: 0.5;\\n cursor: not-allowed;\\n}\\n.ui-input-controller__error {\\n font-family: var(--ui-font-family);\\n font-size: var(--ui-font-size-sm);\\n color: var(--ui-color-danger);\\n}\\n\")"],"mappings":"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","names":["import_jsx_runtime","import_jsx_runtime"]}
package/dist/index.mjs CHANGED
@@ -1,3 +1,5 @@
1
+ "use client";
2
+
1
3
  // src/theme/UIProvider.tsx
2
4
  import {
3
5
  createContext,
@@ -119,6 +121,31 @@ function useUITheme() {
119
121
  return useContext(ThemeContext);
120
122
  }
121
123
 
124
+ // #style-inject:#style-inject
125
+ function styleInject(css, { insertAt } = {}) {
126
+ if (!css || typeof document === "undefined") return;
127
+ const head = document.head || document.getElementsByTagName("head")[0];
128
+ const style = document.createElement("style");
129
+ style.type = "text/css";
130
+ if (insertAt === "top") {
131
+ if (head.firstChild) {
132
+ head.insertBefore(style, head.firstChild);
133
+ } else {
134
+ head.appendChild(style);
135
+ }
136
+ } else {
137
+ head.appendChild(style);
138
+ }
139
+ if (style.styleSheet) {
140
+ style.styleSheet.cssText = css;
141
+ } else {
142
+ style.appendChild(document.createTextNode(css));
143
+ }
144
+ }
145
+
146
+ // src/components/Button/Button.css
147
+ styleInject(".ui-button {\n border: 0;\n font-family: var(--ui-font-family);\n font-size: var(--ui-font-size-md);\n border-radius: var(--ui-radius-md);\n cursor: pointer;\n transition: background-color 150ms ease, opacity 150ms ease;\n}\n.ui-button--sm {\n padding: var(--ui-spacing-xs) var(--ui-spacing-sm);\n}\n.ui-button--md {\n padding: var(--ui-spacing-sm) var(--ui-spacing-md);\n}\n.ui-button--lg {\n padding: var(--ui-spacing-md) var(--ui-spacing-lg);\n}\n.ui-button--primary {\n background: var(--ui-color-primary);\n color: var(--ui-color-primary-foreground);\n}\n.ui-button--primary:hover:not(:disabled) {\n background: var(--ui-color-primary-hover);\n}\n.ui-button--secondary {\n background: var(--ui-color-secondary);\n color: var(--ui-color-secondary-foreground);\n}\n.ui-button--danger {\n background: var(--ui-color-danger);\n color: #ffffff;\n}\n.ui-button:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n");
148
+
122
149
  // src/components/Button/Button.tsx
123
150
  import { jsx as jsx2 } from "react/jsx-runtime";
124
151
  function Button({
@@ -145,8 +172,98 @@ function Button({
145
172
  }
146
173
  );
147
174
  }
175
+
176
+ // src/components/InputController/Controller.tsx
177
+ import { Controller } from "react-hook-form";
178
+
179
+ // src/components/InputController/Controller.css
180
+ styleInject(".ui-input-controller {\n display: flex;\n flex-direction: column;\n gap: var(--ui-spacing-xs);\n}\n.ui-input-controller__label {\n font-family: var(--ui-font-family);\n font-size: var(--ui-font-size-sm);\n color: var(--ui-color-foreground);\n cursor: pointer;\n}\n.ui-input-controller__input {\n width: 100%;\n box-sizing: border-box;\n padding: var(--ui-spacing-sm) var(--ui-spacing-md);\n font-family: var(--ui-font-family);\n font-size: var(--ui-font-size-md);\n color: var(--ui-color-foreground);\n background: var(--ui-color-background);\n border: 1px solid var(--ui-color-border);\n border-radius: var(--ui-radius-md);\n outline: none;\n transition:\n border-color 150ms ease,\n box-shadow 150ms ease,\n opacity 150ms ease;\n}\n.ui-input-controller__input::placeholder {\n color: var(--ui-color-muted-foreground);\n}\n.ui-input-controller__input:hover:not(:disabled) {\n border-color: var(--ui-color-primary);\n}\n.ui-input-controller__input:focus {\n border-color: var(--ui-color-primary);\n box-shadow: 0 0 0 2px color-mix(in srgb, var(--ui-color-primary) 15%, transparent);\n}\n.ui-input-controller__input--error {\n border-color: var(--ui-color-danger);\n}\n.ui-input-controller__input--error:focus {\n border-color: var(--ui-color-danger);\n box-shadow: 0 0 0 2px color-mix(in srgb, var(--ui-color-danger) 15%, transparent);\n}\n.ui-input-controller__input--disabled,\n.ui-input-controller__input:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n.ui-input-controller__error {\n font-family: var(--ui-font-family);\n font-size: var(--ui-font-size-sm);\n color: var(--ui-color-danger);\n}\n");
181
+
182
+ // src/components/InputController/Controller.tsx
183
+ import { jsx as jsx3, jsxs } from "react/jsx-runtime";
184
+ function InputController({
185
+ label,
186
+ placeholder,
187
+ control,
188
+ name,
189
+ classes = {},
190
+ showError = true,
191
+ id,
192
+ ...props
193
+ }) {
194
+ const inputId = id ?? String(name);
195
+ const errorId = `${inputId}-error`;
196
+ return /* @__PURE__ */ jsx3(
197
+ Controller,
198
+ {
199
+ name,
200
+ control,
201
+ render: ({
202
+ field,
203
+ fieldState
204
+ }) => {
205
+ const hasError = Boolean(fieldState.error);
206
+ return /* @__PURE__ */ jsxs(
207
+ "div",
208
+ {
209
+ className: [
210
+ "ui-input-controller",
211
+ classes.root
212
+ ].filter(Boolean).join(" "),
213
+ children: [
214
+ label && /* @__PURE__ */ jsx3(
215
+ "label",
216
+ {
217
+ htmlFor: inputId,
218
+ className: [
219
+ "ui-input-controller__label",
220
+ classes.label
221
+ ].filter(Boolean).join(" "),
222
+ children: label
223
+ }
224
+ ),
225
+ /* @__PURE__ */ jsx3(
226
+ "input",
227
+ {
228
+ ...props,
229
+ ...field,
230
+ id: inputId,
231
+ name: field.name,
232
+ placeholder,
233
+ value: field.value ?? "",
234
+ "aria-invalid": hasError,
235
+ "aria-describedby": hasError && showError ? errorId : void 0,
236
+ disabled: props.disabled || field.disabled,
237
+ className: [
238
+ "ui-input-controller__input",
239
+ hasError ? "ui-input-controller__input--error" : "",
240
+ props.disabled ? "ui-input-controller__input--disabled" : "",
241
+ classes.input
242
+ ].filter(Boolean).join(" ")
243
+ }
244
+ ),
245
+ hasError && showError && fieldState.error?.message && /* @__PURE__ */ jsx3(
246
+ "span",
247
+ {
248
+ id: errorId,
249
+ role: "alert",
250
+ className: [
251
+ "ui-input-controller__error",
252
+ classes.error
253
+ ].filter(Boolean).join(" "),
254
+ children: fieldState.error.message
255
+ }
256
+ )
257
+ ]
258
+ }
259
+ );
260
+ }
261
+ }
262
+ );
263
+ }
148
264
  export {
149
265
  Button,
266
+ InputController,
150
267
  UIProvider,
151
268
  useUITheme
152
269
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/theme/UIProvider.tsx","../src/theme/defaultTheme.ts","../src/theme/utils.ts","../src/components/Button/Button.tsx"],"sourcesContent":["\"use client\";\r\nimport {\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"]}
1
+ {"version":3,"sources":["../src/theme/UIProvider.tsx","../src/theme/defaultTheme.ts","../src/theme/utils.ts","#style-inject:#style-inject","../src/components/Button/Button.css","../src/components/Button/Button.tsx","../src/components/InputController/Controller.tsx","../src/components/InputController/Controller.css"],"sourcesContent":["\"use client\";\r\nimport {\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}","\n export default function styleInject(css, { insertAt } = {}) {\n if (!css || typeof document === 'undefined') return\n \n const head = document.head || document.getElementsByTagName('head')[0]\n const style = document.createElement('style')\n style.type = 'text/css'\n \n if (insertAt === 'top') {\n if (head.firstChild) {\n head.insertBefore(style, head.firstChild)\n } else {\n head.appendChild(style)\n }\n } else {\n head.appendChild(style)\n }\n \n if (style.styleSheet) {\n style.styleSheet.cssText = css\n } else {\n style.appendChild(document.createTextNode(css))\n }\n }\n ","import styleInject from '#style-inject';styleInject(\".ui-button {\\n border: 0;\\n font-family: var(--ui-font-family);\\n font-size: var(--ui-font-size-md);\\n border-radius: var(--ui-radius-md);\\n cursor: pointer;\\n transition: background-color 150ms ease, opacity 150ms ease;\\n}\\n.ui-button--sm {\\n padding: var(--ui-spacing-xs) var(--ui-spacing-sm);\\n}\\n.ui-button--md {\\n padding: var(--ui-spacing-sm) var(--ui-spacing-md);\\n}\\n.ui-button--lg {\\n padding: var(--ui-spacing-md) var(--ui-spacing-lg);\\n}\\n.ui-button--primary {\\n background: var(--ui-color-primary);\\n color: var(--ui-color-primary-foreground);\\n}\\n.ui-button--primary:hover:not(:disabled) {\\n background: var(--ui-color-primary-hover);\\n}\\n.ui-button--secondary {\\n background: var(--ui-color-secondary);\\n color: var(--ui-color-secondary-foreground);\\n}\\n.ui-button--danger {\\n background: var(--ui-color-danger);\\n color: #ffffff;\\n}\\n.ui-button:disabled {\\n opacity: 0.5;\\n cursor: not-allowed;\\n}\\n\")","import type { ButtonProps } from \"./Button.types\";\r\nimport \"./Button.css\";\r\n\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}","\"use client\";\r\n\r\nimport { Controller } from \"react-hook-form\";\r\n\r\nimport type { InputControllerProps } from \"./Controller.types\";\r\n\r\nimport \"./Controller.css\";\r\n\r\nexport function InputController<\r\n TFieldValues extends Record<string, unknown>,\r\n>({\r\n label,\r\n placeholder,\r\n control,\r\n name,\r\n classes = {},\r\n showError = true,\r\n id,\r\n ...props\r\n}: InputControllerProps<TFieldValues>) {\r\n const inputId = id ?? String(name);\r\n const errorId = `${inputId}-error`;\r\n\r\n return (\r\n <Controller\r\n name={name}\r\n control={control}\r\n render={({\r\n field,\r\n fieldState,\r\n }) => {\r\n const hasError = Boolean(fieldState.error);\r\n\r\n return (\r\n <div\r\n className={[\r\n \"ui-input-controller\",\r\n classes.root,\r\n ]\r\n .filter(Boolean)\r\n .join(\" \")}\r\n >\r\n {label && (\r\n <label\r\n htmlFor={inputId}\r\n className={[\r\n \"ui-input-controller__label\",\r\n classes.label,\r\n ]\r\n .filter(Boolean)\r\n .join(\" \")}\r\n >\r\n {label}\r\n </label>\r\n )}\r\n\r\n <input\r\n {...props}\r\n {...field}\r\n id={inputId}\r\n name={field.name}\r\n placeholder={placeholder}\r\n value={field.value ?? \"\" as any}\r\n aria-invalid={\r\n hasError\r\n }\r\n aria-describedby={\r\n hasError && showError\r\n ? errorId\r\n : undefined\r\n }\r\n disabled={\r\n props.disabled ||\r\n field.disabled\r\n }\r\n className={[\r\n \"ui-input-controller__input\",\r\n hasError\r\n ? \"ui-input-controller__input--error\"\r\n : \"\",\r\n props.disabled\r\n ? \"ui-input-controller__input--disabled\"\r\n : \"\",\r\n classes.input,\r\n ]\r\n .filter(Boolean)\r\n .join(\" \")}\r\n />\r\n\r\n {hasError &&\r\n showError &&\r\n fieldState.error?.message && (\r\n <span\r\n id={errorId}\r\n role=\"alert\"\r\n className={[\r\n \"ui-input-controller__error\",\r\n classes.error,\r\n ]\r\n .filter(Boolean)\r\n .join(\" \")}\r\n >\r\n {\r\n fieldState\r\n .error\r\n .message\r\n }\r\n </span>\r\n )}\r\n </div>\r\n );\r\n }}\r\n />\r\n );\r\n}","import styleInject from '#style-inject';styleInject(\".ui-input-controller {\\n display: flex;\\n flex-direction: column;\\n gap: var(--ui-spacing-xs);\\n}\\n.ui-input-controller__label {\\n font-family: var(--ui-font-family);\\n font-size: var(--ui-font-size-sm);\\n color: var(--ui-color-foreground);\\n cursor: pointer;\\n}\\n.ui-input-controller__input {\\n width: 100%;\\n box-sizing: border-box;\\n padding: var(--ui-spacing-sm) var(--ui-spacing-md);\\n font-family: var(--ui-font-family);\\n font-size: var(--ui-font-size-md);\\n color: var(--ui-color-foreground);\\n background: var(--ui-color-background);\\n border: 1px solid var(--ui-color-border);\\n border-radius: var(--ui-radius-md);\\n outline: none;\\n transition:\\n border-color 150ms ease,\\n box-shadow 150ms ease,\\n opacity 150ms ease;\\n}\\n.ui-input-controller__input::placeholder {\\n color: var(--ui-color-muted-foreground);\\n}\\n.ui-input-controller__input:hover:not(:disabled) {\\n border-color: var(--ui-color-primary);\\n}\\n.ui-input-controller__input:focus {\\n border-color: var(--ui-color-primary);\\n box-shadow: 0 0 0 2px color-mix(in srgb, var(--ui-color-primary) 15%, transparent);\\n}\\n.ui-input-controller__input--error {\\n border-color: var(--ui-color-danger);\\n}\\n.ui-input-controller__input--error:focus {\\n border-color: var(--ui-color-danger);\\n box-shadow: 0 0 0 2px color-mix(in srgb, var(--ui-color-danger) 15%, transparent);\\n}\\n.ui-input-controller__input--disabled,\\n.ui-input-controller__input:disabled {\\n opacity: 0.5;\\n cursor: not-allowed;\\n}\\n.ui-input-controller__error {\\n font-family: var(--ui-font-family);\\n font-size: var(--ui-font-size-sm);\\n color: var(--ui-color-danger);\\n}\\n\")"],"mappings":"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","names":["jsx","jsx"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@true-kit/ui",
3
- "version": "0.1.3",
3
+ "version": "0.1.6",
4
4
  "description": "Reusable React UI components",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -21,13 +21,15 @@
21
21
  },
22
22
  "peerDependencies": {
23
23
  "react": ">=18",
24
- "react-dom": ">=18"
24
+ "react-dom": ">=18",
25
+ "react-hook-form": ">=7"
25
26
  },
26
27
  "devDependencies": {
27
28
  "@types/react": "^19.0.0",
28
29
  "@types/react-dom": "^19.0.0",
29
30
  "tsup": "^8.0.0",
30
- "typescript": "^5.0.0"
31
+ "typescript": "^5.0.0",
32
+ "react-hook-form": "^7.87.0"
31
33
  },
32
34
  "publishConfig": {
33
35
  "access": "public"
package/dist/index.css DELETED
@@ -1,38 +0,0 @@
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 */
@@ -1 +0,0 @@
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":[]}