@echojs-ecosystem/ui 0.1.0

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.
Files changed (58) hide show
  1. package/README.md +102 -0
  2. package/dist/button.d.ts +20 -0
  3. package/dist/button.js +559 -0
  4. package/dist/button.js.map +1 -0
  5. package/dist/button.types-B0SrEYRV.d.ts +27 -0
  6. package/dist/checkbox.d.ts +42 -0
  7. package/dist/checkbox.js +388 -0
  8. package/dist/checkbox.js.map +1 -0
  9. package/dist/cn-rGlUI2mx.d.ts +16 -0
  10. package/dist/core.d.ts +16 -0
  11. package/dist/core.js +294 -0
  12. package/dist/core.js.map +1 -0
  13. package/dist/field.d.ts +72 -0
  14. package/dist/field.js +479 -0
  15. package/dist/field.js.map +1 -0
  16. package/dist/field.types-BSyhu0Cf.d.ts +24 -0
  17. package/dist/icon-button.d.ts +15 -0
  18. package/dist/icon-button.js +606 -0
  19. package/dist/icon-button.js.map +1 -0
  20. package/dist/index-BhC5sVej.d.ts +35 -0
  21. package/dist/index.d.ts +87 -0
  22. package/dist/index.js +1604 -0
  23. package/dist/index.js.map +1 -0
  24. package/dist/input-mask.d.ts +5 -0
  25. package/dist/input-mask.js +568 -0
  26. package/dist/input-mask.js.map +1 -0
  27. package/dist/input-otp.d.ts +16 -0
  28. package/dist/input-otp.js +475 -0
  29. package/dist/input-otp.js.map +1 -0
  30. package/dist/input-tags.d.ts +16 -0
  31. package/dist/input-tags.js +549 -0
  32. package/dist/input-tags.js.map +1 -0
  33. package/dist/input.d.ts +14 -0
  34. package/dist/input.js +466 -0
  35. package/dist/input.js.map +1 -0
  36. package/dist/label.d.ts +17 -0
  37. package/dist/label.js +345 -0
  38. package/dist/label.js.map +1 -0
  39. package/dist/primitives.d.ts +23 -0
  40. package/dist/primitives.js +301 -0
  41. package/dist/primitives.js.map +1 -0
  42. package/dist/provider.d.ts +19 -0
  43. package/dist/provider.js +124 -0
  44. package/dist/provider.js.map +1 -0
  45. package/dist/slots-D2y1YgGz.d.ts +58 -0
  46. package/dist/textarea.d.ts +27 -0
  47. package/dist/textarea.js +361 -0
  48. package/dist/textarea.js.map +1 -0
  49. package/dist/theme-context-CyY95LK0.d.ts +39 -0
  50. package/dist/theme.d.ts +20 -0
  51. package/dist/theme.js +155 -0
  52. package/dist/theme.js.map +1 -0
  53. package/dist/types-CSHcGa_F.d.ts +13 -0
  54. package/dist/utils.d.ts +36 -0
  55. package/dist/utils.js +101 -0
  56. package/dist/utils.js.map +1 -0
  57. package/dist/variants-Bj38CFcH.d.ts +51 -0
  58. package/package.json +134 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/theme/default-theme.ts","../src/theme/create-theme.ts","../src/theme/theme-context.ts","../src/theme/variants.ts"],"names":[],"mappings":"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","file":"theme.js","sourcesContent":["import type { UITheme } from \"./types\";\n\n/** Built-in theme used when no provider is mounted. */\nexport const defaultTheme: UITheme = {\n prefix: \"echo\",\n headless: false,\n components: {\n button: {\n defaultVariants: {\n variant: \"primary\",\n size: \"md\",\n radius: \"full\",\n },\n },\n input: {\n defaultVariants: {\n variant: \"outline\",\n size: \"md\",\n },\n },\n inputMask: {\n defaultVariants: {\n variant: \"outline\",\n size: \"md\",\n },\n },\n inputOtp: {\n defaultVariants: {\n variant: \"outline\",\n size: \"md\",\n },\n },\n inputTags: {\n defaultVariants: {\n variant: \"outline\",\n size: \"md\",\n },\n },\n textarea: {\n defaultVariants: {\n variant: \"outline\",\n size: \"md\",\n resize: \"vertical\",\n },\n },\n checkbox: {\n defaultVariants: {\n size: \"md\",\n },\n },\n iconButton: {\n defaultVariants: {\n variant: \"ghost\",\n size: \"md\",\n },\n },\n },\n};\n","import { defaultTheme } from \"./default-theme\";\nimport type { ComponentThemeConfig, UITheme } from \"./types\";\n\nconst mergeComponentConfig = (\n base: ComponentThemeConfig | undefined,\n next: ComponentThemeConfig | undefined,\n): ComponentThemeConfig | undefined => {\n if (!base && !next) return undefined;\n if (!base) return next ? { ...next } : undefined;\n if (!next) return { ...base };\n\n return {\n baseClass: next.baseClass ?? base.baseClass,\n className: next.className ?? base.className,\n defaultProps: { ...base.defaultProps, ...next.defaultProps },\n defaultVariants: { ...base.defaultVariants, ...next.defaultVariants },\n variants: { ...base.variants, ...next.variants },\n };\n};\n\nconst mergeComponents = (\n base: UITheme[\"components\"],\n next: UITheme[\"components\"],\n): UITheme[\"components\"] => {\n const keys = new Set([...Object.keys(base ?? {}), ...Object.keys(next ?? {})]);\n const merged: Record<string, ComponentThemeConfig> = {};\n\n for (const key of keys) {\n const slice = mergeComponentConfig(base?.[key], next?.[key]);\n if (slice) merged[key] = slice;\n }\n\n return merged;\n};\n\n/**\n * Merges partial theme config into a base theme (defaults to {@link defaultTheme}).\n */\nexport const createTheme = (input: Partial<UITheme>, base: UITheme = defaultTheme): UITheme => ({\n prefix: input.prefix ?? base.prefix,\n headless: input.headless ?? base.headless,\n components: mergeComponents(base.components, input.components),\n});\n","import { createTheme } from \"./create-theme\";\nimport { defaultTheme } from \"./default-theme\";\nimport type { UITheme } from \"./types\";\n\n/** Resolved runtime configuration from {@link UIProvider}. */\nexport type UIContextValue = {\n theme: UITheme;\n headless: boolean;\n};\n\nconst stack: UIContextValue[] = [];\n\n/** Returns the active UI context or `undefined` outside a provider. */\nexport const getUIContext = (): UIContextValue | undefined => stack[stack.length - 1];\n\n/** Returns the active UI context, falling back to defaults. */\nexport const getUIContextOrDefault = (): UIContextValue => getUIContext() ?? createUIContextValue({});\n\nexport type CreateUIContextInput = {\n theme?: Partial<UITheme>;\n headless?: boolean;\n};\n\n/** Builds a fully resolved context value from partial provider props. */\nexport const createUIContextValue = (\n input: CreateUIContextInput,\n parent: UIContextValue | undefined = getUIContext(),\n): UIContextValue => {\n const parentTheme = parent?.theme ?? defaultTheme;\n const theme = createTheme(input.theme ?? {}, parentTheme);\n\n const headless = input.headless ?? theme.headless ?? parent?.headless ?? false;\n\n return {\n theme: { ...theme, headless },\n headless,\n };\n};\n\n/** Runs `fn` with `value` pushed onto the UI context stack. */\nexport const runWithUIContext = <T>(value: UIContextValue, fn: () => T): T => {\n stack.push(value);\n try {\n return fn();\n } finally {\n stack.pop();\n }\n};\n\n/** @internal Resets the context stack — for tests only. */\nexport const resetUIContextStack = (): void => {\n stack.length = 0;\n};\n","/**\n * Stage 1 note:\n * We keep a small abstraction layer around variant class resolution so we can\n * plug `tailwind-variants` later without changing component code.\n */\n\nexport type TVVariantsShape = Record<string, Record<string, string>>;\nexport type TVBooleanVariantShape = Record<string, { true?: string; false?: string }>;\n\nexport type TVCompoundVariant = Record<string, string | boolean> & { class: string };\n\nexport type TVConfig = {\n base?: string;\n variants?: TVVariantsShape & TVBooleanVariantShape;\n compoundVariants?: TVCompoundVariant[];\n defaultVariants?: Record<string, string | boolean>;\n slots?: Record<string, string>;\n};\n\nexport type TVSlotResult<T extends TVConfig & { slots: Record<string, string> }> = {\n [K in keyof T[\"slots\"]]: (slotOptions?: Record<string, unknown>) => string;\n} & { _config: T };\n\nexport type TVResult<T extends TVConfig> = T extends { slots: Record<string, any> }\n ? TVSlotResult<T & { slots: Record<string, string> }>\n : ((options?: Record<string, unknown>) => string) & { _config: T };\n\n/** Roughly compatible `tv()` subset (Stage 2). */\nexport const tv = <T extends TVConfig>(config: T): TVResult<T> => {\n const resolve = (options?: Record<string, unknown>): string => {\n const parts: string[] = [];\n if (config.base) parts.push(config.base);\n\n const resolved = { ...(config.defaultVariants ?? {}), ...(options ?? {}) } as Record<\n string,\n string | boolean | undefined\n >;\n\n const variants = config.variants ?? {};\n for (const [variantName, map] of Object.entries(variants)) {\n const value = resolved[variantName];\n if (value === undefined) continue;\n\n const key = typeof value === \"boolean\" ? (value ? \"true\" : \"false\") : String(value);\n const cls = (map as any)[key] as string | undefined;\n if (cls) parts.push(cls);\n }\n\n for (const compound of config.compoundVariants ?? []) {\n const { class: compoundClass, ...conditions } = compound;\n const matches = Object.entries(conditions).every(([name, value]) => resolved[name] === value);\n if (matches && compoundClass) parts.push(compoundClass);\n }\n\n return parts.filter(Boolean).join(\" \");\n };\n\n if (config.slots) {\n const slotFns: any = {};\n for (const [slot, slotBase] of Object.entries(config.slots)) {\n slotFns[slot] = (slotOptions?: Record<string, unknown>) => {\n const composed = [slotBase, resolve(slotOptions)].filter(Boolean).join(\" \");\n return composed.trim();\n };\n }\n slotFns._config = config;\n return slotFns as TVResult<T>;\n }\n\n const fn: any = (options?: Record<string, unknown>) => resolve(options);\n fn._config = config;\n return fn as TVResult<T>;\n};\n\nexport type VariantProps<T> = T extends { _config: infer C }\n ? C extends { variants: infer V }\n ? {\n [K in keyof V]?: V[K] extends Record<infer Key, any>\n ? Key extends \"true\" | \"false\"\n ? boolean\n : Key\n : never;\n }\n : Record<string, never>\n : Record<string, never>;\n\n/** Compatibility export (mirrors tailwind-variants). */\nexport const createComponentVariants = tv;\n\n/**\n * Resolves variant classes when styling is enabled.\n */\nexport const resolveVariantClasses = (\n variantFn: ((options?: Record<string, unknown>) => string) | undefined,\n options: Record<string, unknown> | undefined,\n headless: boolean,\n): string | undefined => {\n if (headless || !variantFn) return undefined;\n return variantFn(options);\n};\n"]}
@@ -0,0 +1,13 @@
1
+ import { Child } from '@echojs-ecosystem/hyperdom';
2
+ import { C as ClassValue } from './cn-rGlUI2mx.js';
3
+
4
+ /** Base props supported by all UI components. */
5
+ type UIComponentBaseProps = {
6
+ /** Skip visual/theme classes while keeping semantics and behavior. */
7
+ headless?: boolean;
8
+ class?: ClassValue;
9
+ className?: ClassValue;
10
+ children?: Child;
11
+ };
12
+
13
+ export type { UIComponentBaseProps as U };
@@ -0,0 +1,36 @@
1
+ export { a as ClassDictionary, b as ClassNameMerger, C as ClassValue, c as cn, r as resetClassNameMerger, s as setClassNameMerger } from './cn-rGlUI2mx.js';
2
+
3
+ type MergeableProps = Record<string, unknown>;
4
+ /**
5
+ * Merges props with priority (lowest → highest): `defaultProps`, `providerProps`, `componentProps`.
6
+ *
7
+ * `class` / `className` are joined; event handlers are composed.
8
+ */
9
+ declare const mergeProps: <T extends MergeableProps>(defaultProps: MergeableProps | undefined, providerProps: MergeableProps | undefined, componentProps: T) => T;
10
+
11
+ type RefCallback<T> = (instance: T | null) => void;
12
+ type RefValue<T> = RefCallback<T> | null | undefined;
13
+ /**
14
+ * Merges multiple ref callbacks into one.
15
+ */
16
+ declare const mergeRefs: <T>(...refs: RefValue<T>[]) => RefCallback<T> | undefined;
17
+
18
+ type ComposeEventHandlersOptions = {
19
+ /** When true, skips `internalHandler` if `userHandler` called `preventDefault`. */
20
+ checkDefaultPrevented?: boolean;
21
+ };
22
+ type EventHandler<E extends Event = Event> = (event: E) => void;
23
+ /**
24
+ * Composes two event handlers. `userHandler` runs first.
25
+ */
26
+ declare const composeEventHandlers: <E extends Event>(userHandler: EventHandler<E> | undefined, internalHandler: EventHandler<E> | undefined, options?: ComposeEventHandlersOptions) => EventHandler<E> | undefined;
27
+
28
+ type DataAttributeProps = Record<`data-${string}`, string | number | boolean | undefined>;
29
+ /** `data-state` helper for styling hooks. */
30
+ declare const dataState: (value: string) => DataAttributeProps;
31
+ /** `data-disabled` — present when disabled. */
32
+ declare const dataDisabled: (disabled?: boolean) => DataAttributeProps;
33
+ /** `data-invalid` — present when invalid. */
34
+ declare const dataInvalid: (invalid?: boolean) => DataAttributeProps;
35
+
36
+ export { type ComposeEventHandlersOptions, type MergeableProps, composeEventHandlers, dataDisabled, dataInvalid, dataState, mergeProps, mergeRefs };
package/dist/utils.js ADDED
@@ -0,0 +1,101 @@
1
+ // src/utils/cn.ts
2
+ var defaultClassNameMerger = (...values) => {
3
+ const out = [];
4
+ const walk = (value) => {
5
+ if (value == null || value === false) return;
6
+ if (typeof value === "string") {
7
+ if (value) out.push(value);
8
+ return;
9
+ }
10
+ if (Array.isArray(value)) {
11
+ for (const item of value) walk(item);
12
+ return;
13
+ }
14
+ for (const [key, enabled] of Object.entries(value)) {
15
+ if (enabled) out.push(key);
16
+ }
17
+ };
18
+ for (const value of values) walk(value);
19
+ return out.join(" ");
20
+ };
21
+ var classNameMerger = defaultClassNameMerger;
22
+ var setClassNameMerger = (merger) => {
23
+ classNameMerger = merger;
24
+ };
25
+ var resetClassNameMerger = () => {
26
+ classNameMerger = defaultClassNameMerger;
27
+ };
28
+ var cn = (...values) => classNameMerger(...values);
29
+
30
+ // src/utils/compose-event-handlers.ts
31
+ var composeEventHandlers = (userHandler, internalHandler, options = {}) => {
32
+ if (!userHandler && !internalHandler) return void 0;
33
+ if (!userHandler) return internalHandler;
34
+ if (!internalHandler) return userHandler;
35
+ const { checkDefaultPrevented = false } = options;
36
+ return (event) => {
37
+ userHandler(event);
38
+ if (checkDefaultPrevented && event?.defaultPrevented) return;
39
+ internalHandler(event);
40
+ };
41
+ };
42
+
43
+ // src/utils/merge-props.ts
44
+ var CLASS_KEYS = /* @__PURE__ */ new Set(["class", "className"]);
45
+ var isEventHandlerKey = (key) => key.startsWith("on") || key.startsWith("on:");
46
+ var mergeClassValues = (...values) => {
47
+ const merged = cn(...values);
48
+ return merged || void 0;
49
+ };
50
+ var mergePair = (target, source) => {
51
+ if (!source) return;
52
+ for (const [key, value] of Object.entries(source)) {
53
+ if (value === void 0) continue;
54
+ if (CLASS_KEYS.has(key)) {
55
+ const mergedClass = mergeClassValues(target.className, value);
56
+ if (mergedClass !== void 0) {
57
+ target.className = mergedClass;
58
+ target.class = mergedClass;
59
+ }
60
+ continue;
61
+ }
62
+ if (isEventHandlerKey(key)) {
63
+ const existing = target[key];
64
+ target[key] = composeEventHandlers(
65
+ value,
66
+ existing,
67
+ { checkDefaultPrevented: true }
68
+ );
69
+ continue;
70
+ }
71
+ target[key] = value;
72
+ }
73
+ };
74
+ var mergeProps = (defaultProps, providerProps, componentProps) => {
75
+ const merged = {};
76
+ mergePair(merged, defaultProps);
77
+ mergePair(merged, providerProps);
78
+ mergePair(merged, componentProps);
79
+ return merged;
80
+ };
81
+
82
+ // src/utils/merge-refs.ts
83
+ var mergeRefs = (...refs) => {
84
+ const filtered = refs.filter(Boolean);
85
+ if (filtered.length === 0) return void 0;
86
+ if (filtered.length === 1) return filtered[0];
87
+ return (instance) => {
88
+ for (const ref of filtered) ref(instance);
89
+ };
90
+ };
91
+
92
+ // src/utils/data-attributes.ts
93
+ var dataState = (value) => ({
94
+ "data-state": value
95
+ });
96
+ var dataDisabled = (disabled) => disabled ? { "data-disabled": "" } : {};
97
+ var dataInvalid = (invalid) => invalid ? { "data-invalid": "" } : {};
98
+
99
+ export { cn, composeEventHandlers, dataDisabled, dataInvalid, dataState, mergeProps, mergeRefs, resetClassNameMerger, setClassNameMerger };
100
+ //# sourceMappingURL=utils.js.map
101
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils/cn.ts","../src/utils/compose-event-handlers.ts","../src/utils/merge-props.ts","../src/utils/merge-refs.ts","../src/utils/data-attributes.ts"],"names":[],"mappings":"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","file":"utils.js","sourcesContent":["export type ClassDictionary = Record<string, boolean | null | undefined>;\nexport type ClassValue =\n | string\n | null\n | undefined\n | false\n | ClassDictionary\n | readonly ClassValue[];\n\n/** Optional hook to swap in tailwind-merge later. */\nexport type ClassNameMerger = (...values: ClassValue[]) => string;\n\nconst defaultClassNameMerger: ClassNameMerger = (...values) => {\n const out: string[] = [];\n\n const walk = (value: ClassValue): void => {\n if (value == null || value === false) return;\n\n if (typeof value === \"string\") {\n if (value) out.push(value);\n return;\n }\n\n if (Array.isArray(value)) {\n for (const item of value) walk(item);\n return;\n }\n\n for (const [key, enabled] of Object.entries(value)) {\n if (enabled) out.push(key);\n }\n };\n\n for (const value of values) walk(value);\n return out.join(\" \");\n};\n\nlet classNameMerger: ClassNameMerger = defaultClassNameMerger;\n\n/** Replaces the global className merger (e.g. with tailwind-merge). */\nexport const setClassNameMerger = (merger: ClassNameMerger): void => {\n classNameMerger = merger;\n};\n\n/** Resets the className merger to the built-in implementation. */\nexport const resetClassNameMerger = (): void => {\n classNameMerger = defaultClassNameMerger;\n};\n\n/**\n * Joins class name fragments.\n *\n * Supports strings, arrays, conditional maps, and falsy values.\n */\nexport const cn: ClassNameMerger = (...values) => classNameMerger(...values);\n","export type ComposeEventHandlersOptions = {\n /** When true, skips `internalHandler` if `userHandler` called `preventDefault`. */\n checkDefaultPrevented?: boolean;\n};\n\ntype EventHandler<E extends Event = Event> = (event: E) => void;\n\n/**\n * Composes two event handlers. `userHandler` runs first.\n */\nexport const composeEventHandlers = <E extends Event>(\n userHandler: EventHandler<E> | undefined,\n internalHandler: EventHandler<E> | undefined,\n options: ComposeEventHandlersOptions = {},\n): EventHandler<E> | undefined => {\n if (!userHandler && !internalHandler) return undefined;\n if (!userHandler) return internalHandler;\n if (!internalHandler) return userHandler;\n\n const { checkDefaultPrevented = false } = options;\n\n return (event) => {\n userHandler(event);\n if (checkDefaultPrevented && event?.defaultPrevented) return;\n internalHandler(event);\n };\n};\n","import { composeEventHandlers } from \"./compose-event-handlers\";\nimport { cn, type ClassValue } from \"./cn\";\n\nexport type MergeableProps = Record<string, unknown>;\n\nconst CLASS_KEYS = new Set([\"class\", \"className\"]);\n\nconst isEventHandlerKey = (key: string): boolean =>\n key.startsWith(\"on\") || key.startsWith(\"on:\");\n\nconst mergeClassValues = (...values: unknown[]): string | undefined => {\n const merged = cn(...(values as ClassValue[]));\n return merged || undefined;\n};\n\nconst mergePair = (target: MergeableProps, source: MergeableProps | undefined): void => {\n if (!source) return;\n\n for (const [key, value] of Object.entries(source)) {\n if (value === undefined) continue;\n\n if (CLASS_KEYS.has(key)) {\n const mergedClass = mergeClassValues(target.className, value);\n if (mergedClass !== undefined) {\n target.className = mergedClass;\n target.class = mergedClass;\n }\n continue;\n }\n\n if (isEventHandlerKey(key)) {\n const existing = target[key];\n target[key] = composeEventHandlers(\n value as (...args: never[]) => void,\n existing as (...args: never[]) => void,\n { checkDefaultPrevented: true },\n );\n continue;\n }\n\n target[key] = value;\n }\n};\n\n/**\n * Merges props with priority (lowest → highest): `defaultProps`, `providerProps`, `componentProps`.\n *\n * `class` / `className` are joined; event handlers are composed.\n */\nexport const mergeProps = <T extends MergeableProps>(\n defaultProps: MergeableProps | undefined,\n providerProps: MergeableProps | undefined,\n componentProps: T,\n): T => {\n const merged: MergeableProps = {};\n\n mergePair(merged, defaultProps);\n mergePair(merged, providerProps);\n mergePair(merged, componentProps);\n\n return merged as T;\n};\n","export type RefCallback<T> = (instance: T | null) => void;\nexport type RefValue<T> = RefCallback<T> | null | undefined;\n\n/**\n * Merges multiple ref callbacks into one.\n */\nexport const mergeRefs =\n <T>(...refs: RefValue<T>[]): RefCallback<T> | undefined => {\n const filtered = refs.filter(Boolean) as RefCallback<T>[];\n if (filtered.length === 0) return undefined;\n if (filtered.length === 1) return filtered[0];\n\n return (instance) => {\n for (const ref of filtered) ref(instance);\n };\n };\n","export type DataAttributeProps = Record<`data-${string}`, string | number | boolean | undefined>;\n\n/** `data-state` helper for styling hooks. */\nexport const dataState = (value: string): DataAttributeProps => ({\n \"data-state\": value,\n});\n\n/** `data-disabled` — present when disabled. */\nexport const dataDisabled = (disabled?: boolean): DataAttributeProps =>\n disabled ? { \"data-disabled\": \"\" } : {};\n\n/** `data-invalid` — present when invalid. */\nexport const dataInvalid = (invalid?: boolean): DataAttributeProps =>\n invalid ? { \"data-invalid\": \"\" } : {};\n\n/** `data-pending` — present while async action is in progress (HeroUI-style). */\nexport const dataPending = (pending?: boolean): DataAttributeProps =>\n pending ? { \"data-pending\": \"\" } : {};\n"]}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Stage 1 note:
3
+ * We keep a small abstraction layer around variant class resolution so we can
4
+ * plug `tailwind-variants` later without changing component code.
5
+ */
6
+ type TVVariantsShape = Record<string, Record<string, string>>;
7
+ type TVBooleanVariantShape = Record<string, {
8
+ true?: string;
9
+ false?: string;
10
+ }>;
11
+ type TVCompoundVariant = Record<string, string | boolean> & {
12
+ class: string;
13
+ };
14
+ type TVConfig = {
15
+ base?: string;
16
+ variants?: TVVariantsShape & TVBooleanVariantShape;
17
+ compoundVariants?: TVCompoundVariant[];
18
+ defaultVariants?: Record<string, string | boolean>;
19
+ slots?: Record<string, string>;
20
+ };
21
+ type TVSlotResult<T extends TVConfig & {
22
+ slots: Record<string, string>;
23
+ }> = {
24
+ [K in keyof T["slots"]]: (slotOptions?: Record<string, unknown>) => string;
25
+ } & {
26
+ _config: T;
27
+ };
28
+ type TVResult<T extends TVConfig> = T extends {
29
+ slots: Record<string, any>;
30
+ } ? TVSlotResult<T & {
31
+ slots: Record<string, string>;
32
+ }> : ((options?: Record<string, unknown>) => string) & {
33
+ _config: T;
34
+ };
35
+ /** Roughly compatible `tv()` subset (Stage 2). */
36
+ declare const tv: <T extends TVConfig>(config: T) => TVResult<T>;
37
+ type VariantProps<T> = T extends {
38
+ _config: infer C;
39
+ } ? C extends {
40
+ variants: infer V;
41
+ } ? {
42
+ [K in keyof V]?: V[K] extends Record<infer Key, any> ? Key extends "true" | "false" ? boolean : Key : never;
43
+ } : Record<string, never> : Record<string, never>;
44
+ /** Compatibility export (mirrors tailwind-variants). */
45
+ declare const createComponentVariants: <T extends TVConfig>(config: T) => TVResult<T>;
46
+ /**
47
+ * Resolves variant classes when styling is enabled.
48
+ */
49
+ declare const resolveVariantClasses: (variantFn: ((options?: Record<string, unknown>) => string) | undefined, options: Record<string, unknown> | undefined, headless: boolean) => string | undefined;
50
+
51
+ export { type TVConfig as T, type VariantProps as V, type TVSlotResult as a, createComponentVariants as c, resolveVariantClasses as r, tv as t };
package/package.json ADDED
@@ -0,0 +1,134 @@
1
+ {
2
+ "name": "@echojs-ecosystem/ui",
3
+ "version": "0.1.0",
4
+ "files": [
5
+ "dist"
6
+ ],
7
+ "type": "module",
8
+ "sideEffects": false,
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js",
13
+ "default": "./dist/index.js"
14
+ },
15
+ "./button": {
16
+ "types": "./dist/button.d.ts",
17
+ "import": "./dist/button.js",
18
+ "default": "./dist/button.js"
19
+ },
20
+ "./icon-button": {
21
+ "types": "./dist/icon-button.d.ts",
22
+ "import": "./dist/icon-button.js",
23
+ "default": "./dist/icon-button.js"
24
+ },
25
+ "./input": {
26
+ "types": "./dist/input.d.ts",
27
+ "import": "./dist/input.js",
28
+ "default": "./dist/input.js"
29
+ },
30
+ "./input-mask": {
31
+ "types": "./dist/input-mask.d.ts",
32
+ "import": "./dist/input-mask.js",
33
+ "default": "./dist/input-mask.js"
34
+ },
35
+ "./input-otp": {
36
+ "types": "./dist/input-otp.d.ts",
37
+ "import": "./dist/input-otp.js",
38
+ "default": "./dist/input-otp.js"
39
+ },
40
+ "./input-tags": {
41
+ "types": "./dist/input-tags.d.ts",
42
+ "import": "./dist/input-tags.js",
43
+ "default": "./dist/input-tags.js"
44
+ },
45
+ "./textarea": {
46
+ "types": "./dist/textarea.d.ts",
47
+ "import": "./dist/textarea.js",
48
+ "default": "./dist/textarea.js"
49
+ },
50
+ "./label": {
51
+ "types": "./dist/label.d.ts",
52
+ "import": "./dist/label.js",
53
+ "default": "./dist/label.js"
54
+ },
55
+ "./field": {
56
+ "types": "./dist/field.d.ts",
57
+ "import": "./dist/field.js",
58
+ "default": "./dist/field.js"
59
+ },
60
+ "./checkbox": {
61
+ "types": "./dist/checkbox.d.ts",
62
+ "import": "./dist/checkbox.js",
63
+ "default": "./dist/checkbox.js"
64
+ },
65
+ "./provider": {
66
+ "types": "./dist/provider.d.ts",
67
+ "import": "./dist/provider.js",
68
+ "default": "./dist/provider.js"
69
+ },
70
+ "./theme": {
71
+ "types": "./dist/theme.d.ts",
72
+ "import": "./dist/theme.js",
73
+ "default": "./dist/theme.js"
74
+ },
75
+ "./core": {
76
+ "types": "./dist/core.d.ts",
77
+ "import": "./dist/core.js",
78
+ "default": "./dist/core.js"
79
+ },
80
+ "./utils": {
81
+ "types": "./dist/utils.d.ts",
82
+ "import": "./dist/utils.js",
83
+ "default": "./dist/utils.js"
84
+ },
85
+ "./primitives": {
86
+ "types": "./dist/primitives.d.ts",
87
+ "import": "./dist/primitives.js",
88
+ "default": "./dist/primitives.js"
89
+ },
90
+ "./package.json": "./package.json"
91
+ },
92
+ "scripts": {
93
+ "build": "tsup",
94
+ "check-types": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.typing.json --noEmit",
95
+ "typecheck": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.typing.json --noEmit",
96
+ "test:types": "tsc -p tsconfig.typing.json --noEmit",
97
+ "lint": "oxlint .",
98
+ "lint:fix": "oxlint . --fix",
99
+ "format": "oxfmt --check .",
100
+ "format:fix": "oxfmt .",
101
+ "test": "vitest run",
102
+ "test:watch": "vitest",
103
+ "test:vitest:run": "vitest run",
104
+ "test:coverage": "vitest run --coverage",
105
+ "storybook": "storybook dev -p 6006",
106
+ "storybook:build": "storybook build -o storybook-static"
107
+ },
108
+ "dependencies": {
109
+ "@echojs-ecosystem/hyperdom": "workspace:*"
110
+ },
111
+ "devDependencies": {
112
+ "@echojs-ecosystem/oxc-config": "workspace:*",
113
+ "@storybook/addon-a11y": "^8.6.14",
114
+ "@storybook/addon-essentials": "^8.6.14",
115
+ "@storybook/addon-links": "^8.6.14",
116
+ "@storybook/html": "^8.6.14",
117
+ "@storybook/html-vite": "^8.6.14",
118
+ "@tailwindcss/vite": "^4.1.8",
119
+ "jsdom": "^26.1.0",
120
+ "storybook": "^8.6.14",
121
+ "tailwindcss": "^4.1.8",
122
+ "typescript": "5.9.2",
123
+ "vite": "^6.0.0",
124
+ "vitest": "^4.1.4"
125
+ },
126
+ "publishConfig": {
127
+ "access": "public"
128
+ },
129
+ "repository": {
130
+ "type": "git",
131
+ "url": "https://github.com/echojs-ecosystem/echojs-core.git",
132
+ "directory": "packages/ui"
133
+ }
134
+ }