diff --git a/packages/frameworks/svelte/src/merge-props.ts b/packages/frameworks/svelte/src/merge-props.ts index d9f4da9b22..a783c20691 100644 --- a/packages/frameworks/svelte/src/merge-props.ts +++ b/packages/frameworks/svelte/src/merge-props.ts @@ -14,8 +14,77 @@ const serialize = (style: string): CSSObject => { return res } +type ClassValue = ClassValue[] | Record | string | number | bigint | null | boolean | undefined + +const classValueToString = (mix: ClassValue) => { + let i: any + let j: any + + let str = "" + + if (typeof mix === "string" || typeof mix === "number") { + str += mix + } else if (typeof mix === "object") { + if (Array.isArray(mix)) { + const len = mix.length + + for (i = 0; i < len; i++) { + if (mix[i]) { + if ((j = classValueToString(mix[i]))) { + str && (str += " ") + str += j + } + } + } + } else { + for (j in mix) { + if (mix![j]) { + str && (str += " ") + str += j + } + } + } + } + + return str +} + +const clsx = (...args: ClassValue[]) => { + let idx = 0 + let tmp: ClassValue + let cls: string + let str = "" + let len = args.length + + for (; idx < len; idx++) { + if ((tmp = args[idx])) { + if ((cls = classValueToString(tmp))) { + str && (str += " ") + str += cls + } + } + } + + return str +} + export function mergeProps(...args: Record[]) { - const merged = zagMergeProps(...args) + const copy = args.map((arg) => Object.assign({}, arg)) + const classes: ClassValue[] = [] + + for (const arg of copy) { + if ("class" in arg) { + classes.push(arg.class) + delete arg.class + } + + if ("className" in arg) { + classes.push(arg.className) + delete arg.className + } + } + + const merged = zagMergeProps(...copy) if ("style" in merged) { if (typeof merged.style === "string") { @@ -24,5 +93,6 @@ export function mergeProps(...args: Record[]) { merged.style = toStyleString(merged.style) } + classes.length && (merged.class = clsx(...classes)) return merged } diff --git a/packages/frameworks/svelte/tests/merge-props.test.ts b/packages/frameworks/svelte/tests/merge-props.test.ts index b65e20904b..c5b775bd0c 100644 --- a/packages/frameworks/svelte/tests/merge-props.test.ts +++ b/packages/frameworks/svelte/tests/merge-props.test.ts @@ -1,4 +1,4 @@ -import { describe, it, expect, vi } from "vitest" +import { describe, expect, it, vi } from "vitest" import { mergeProps } from "../src" describe("mergeProps for Svelte", () => { @@ -10,7 +10,7 @@ describe("mergeProps for Svelte", () => { const props = mergeProps({ onClick, className, id }) expect(props.onClick).toBe(onClick) - expect(props.className).toBe(className) + expect(props.class).toBe(className) expect(props.id).toBe(id) }) @@ -29,14 +29,18 @@ describe("mergeProps for Svelte", () => { it("combines css classes", () => { const className1 = "primary" - const className2 = "hover" - const className3 = "focus" + const className2 = ["hover", { focus: true }, null, undefined] + const className3 = { + md: false, + lg: true, + xl: false, + } const props = mergeProps({ class: className1 }, { class: className2 }, { class: className3 }) - expect(props.class).toBe("primary hover focus") + expect(props.class).toBe("primary hover focus lg") const props2 = mergeProps({ className: className1 }, { className: className2 }, { className: className3 }) - expect(props2.className).toBe("primary hover focus") + expect(props2.class).toBe("primary hover focus lg") }) it("combines styles", () => {