Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 71 additions & 1 deletion packages/frameworks/svelte/src/merge-props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,77 @@ const serialize = (style: string): CSSObject => {
return res
}

type ClassValue = ClassValue[] | Record<string, any> | 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<string, any>[]) {
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") {
Expand All @@ -24,5 +93,6 @@ export function mergeProps(...args: Record<string, any>[]) {
merged.style = toStyleString(merged.style)
}

classes.length && (merged.class = clsx(...classes))
return merged
}
16 changes: 10 additions & 6 deletions packages/frameworks/svelte/tests/merge-props.test.ts
Original file line number Diff line number Diff line change
@@ -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", () => {
Expand All @@ -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)
})

Expand All @@ -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", () => {
Expand Down