Skip to content

Commit

Permalink
Merge branch 'main' into renovate/swc-monorepo
Browse files Browse the repository at this point in the history
  • Loading branch information
segunadebayo authored Nov 27, 2024
2 parents e53fb2e + 5945325 commit 6ba1039
Show file tree
Hide file tree
Showing 10 changed files with 161 additions and 41 deletions.
5 changes: 5 additions & 0 deletions .changeset/clever-oranges-deny.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@zag-js/angle-slider": patch
---

Fix angle slider max value
2 changes: 1 addition & 1 deletion packages/frameworks/preact/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
"@zag-js/core": "workspace:*",
"@zag-js/store": "workspace:*",
"@zag-js/types": "workspace:*",
"proxy-compare": "3.0.0"
"proxy-compare": "3.0.1"
},
"devDependencies": {
"@types/react-dom": "18.3.1",
Expand Down
2 changes: 1 addition & 1 deletion packages/frameworks/react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
"@zag-js/core": "workspace:*",
"@zag-js/store": "workspace:*",
"@zag-js/types": "workspace:*",
"proxy-compare": "3.0.0"
"proxy-compare": "3.0.1"
},
"devDependencies": {
"@types/react": "18.3.12",
Expand Down
16 changes: 5 additions & 11 deletions packages/frameworks/svelte/src/merge-props.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { mergeProps as zagMergeProps } from "@zag-js/core"
import { toStyleString } from "./normalize-props"

const CSS_REGEX = /((?:--)?(?:\w+-?)+)\s*:\s*([^;]*)/g

Expand All @@ -13,21 +14,14 @@ const serialize = (style: string): CSSObject => {
return res
}

const css = (style: CSSObject | string | undefined): string => {
if (typeof style === "string") style = serialize(style)

const mergedString = Object.entries(style as CSSObject)
.map(([key, value]) => `${key}: ${value}`)
.join("; ")

return mergedString
}

export function mergeProps(...args: Record<string, any>[]) {
const merged = zagMergeProps(...args)

if ("style" in merged) {
merged.style = css(merged.style)
if (typeof merged.style === "string") {
merged.style = serialize(merged.style)
}
merged.style = toStyleString(merged.style)
}

return merged
Expand Down
2 changes: 1 addition & 1 deletion packages/frameworks/svelte/src/normalize-props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export type PropTypes = SvelteHTMLElements & {
style?: HTMLAttributes<HTMLElement>["style"]
}

function toStyleString(style: Record<string, number | string>) {
export function toStyleString(style: Record<string, number | string>) {
let string = ""

for (let key in style) {
Expand Down
89 changes: 89 additions & 0 deletions packages/frameworks/svelte/tests/merge-props.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import { describe, it, expect, vi } from "vitest"
import { mergeProps } from "../src"

describe("mergeProps for Svelte", () => {
it("handles one argument", () => {
const onClick = () => {}
const className = "primary"
const id = "test_id"

const props = mergeProps({ onClick, className, id })

expect(props.onClick).toBe(onClick)
expect(props.className).toBe(className)
expect(props.id).toBe(id)
})

it("combines handlers", () => {
let count = 0
const mockFn = vi.fn(() => {
count++
})

const props = mergeProps({ onClick: mockFn }, { onClick: mockFn }, { onClick: mockFn })

props.onClick()
expect(mockFn).toHaveBeenCalledTimes(3)
expect(count).toBe(3)
})

it("combines css classes", () => {
const className1 = "primary"
const className2 = "hover"
const className3 = "focus"

const props = mergeProps({ class: className1 }, { class: className2 }, { class: className3 })
expect(props.class).toBe("primary hover focus")

const props2 = mergeProps({ className: className1 }, { className: className2 }, { className: className3 })
expect(props2.className).toBe("primary hover focus")
})

it("combines styles", () => {
const apiStyles =
'margin:24px;padding:2;background-image:url("http://example.com/image.png");border:1px solid #123456;--x:123;'

const objStyles = {
margin: "10px",
fontSize: "2rem",
}
const stringStyles = "margin:10px;font-size:2rem;"

const propsFromObj = mergeProps({ style: apiStyles }, { style: objStyles })
const propsFromString = mergeProps({ style: apiStyles }, { style: stringStyles })

const result =
'margin:10px;padding:2;background-image:url("http://example.com/image.png");border:1px solid #123456;--x:123;font-size:2rem;'

expect(propsFromObj.style).toBe(result)
expect(propsFromString.style).toBe(result)
})

it("last value overwrites the event listeners", () => {
const mockFn = vi.fn()
const message1 = "click1"
const message2 = "click2"

const props = mergeProps(
{ onEvent: () => mockFn(message1) },
{ onEvent: () => mockFn(message2) },
{ onEvent: "overwrites" },
)

expect(props.onEvent).toBe("overwrites")
})

it("works with Svelte-specific props", () => {
const cb1 = vi.fn()
const cb2 = vi.fn()

const combined = mergeProps({ onClick: cb1 }, { onClick: cb2 })

combined.onClick("foo")

expect(cb1).toHaveBeenCalledTimes(1)
expect(cb1).toHaveBeenCalledWith("foo")
expect(cb2).toHaveBeenCalledTimes(1)
expect(cb2).toHaveBeenCalledWith("foo")
})
})
4 changes: 3 additions & 1 deletion packages/machines/angle-slider/src/angle-slider.machine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { dom } from "./angle-slider.dom"
import type { MachineContext, MachineState, UserDefinedContext } from "./angle-slider.types"

const MIN_VALUE = 0
const MAX_VALUE = 360
const MAX_VALUE = 359

export function machine(userContext: UserDefinedContext) {
const ctx = compact(userContext)
Expand Down Expand Up @@ -176,6 +176,8 @@ const invoke = {
const set = {
value: (ctx: MachineContext, value: number) => {
if (ctx.value === value) return
if (value < MIN_VALUE || value > MAX_VALUE) return

ctx.value = value
invoke.valueChange(ctx)
},
Expand Down
2 changes: 1 addition & 1 deletion packages/store/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"url": "https://github.com/chakra-ui/zag/issues"
},
"dependencies": {
"proxy-compare": "3.0.0"
"proxy-compare": "3.0.1"
},
"clean-package": "../../clean-package.config.json",
"main": "src/index.ts",
Expand Down
44 changes: 22 additions & 22 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

36 changes: 33 additions & 3 deletions website/data/components/file-upload.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -170,10 +170,12 @@ const [state, send] = useMachine(
## Applying custom validation

To apply custom validation, set the `validate` attribute to a function that
returns an array of errors.
returns an **array of error strings**.

The returned error must be one of `TOO_MANY_FILES`, `FILE_INVALID_TYPE`
,`FILE_TOO_LARGE`, or `FILE_TOO_SMALL`
The returned array can contain any string as an error message. While zagjs
supports default errors such as `TOO_MANY_FILES`, `FILE_INVALID_TYPE`,
`FILE_TOO_LARGE`, or `FILE_TOO_SMALL`, you can return any string that represents
your custom validation errors.

```jsx
const [state, send] = useMachine(
Expand All @@ -188,6 +190,34 @@ const [state, send] = useMachine(
)
```

Apply multiple validation errors:

```js
const [state, send] = useMachine(
fileUpload.machine({
validate(file) {
const errors = []

if (file.size > 1024 * 1024 * 10) {
errors.push("FILE_TOO_LARGE") // Default error enum
}

if (!file.name.endsWith(".pdf")) {
errors.push("ONLY_PDF_ALLOWED") // Custom error
}

if (file.size < 1024) {
errors.push("FILE_TOO_SMALL") // Default error enum
}

return errors.length > 0 ? errors : null
},
}),
)
```

> Return `null` if no validation errors are detected.
## Disabling drag and drop

To disable the drag and drop functionalty, set the `allowDrop` context property
Expand Down

0 comments on commit 6ba1039

Please sign in to comment.