Skip to content

Commit

Permalink
Merge branch 'main' of https://github.com/chakra-ui/zag into cascader
Browse files Browse the repository at this point in the history
  • Loading branch information
anubra266 committed Jan 7, 2025
2 parents 225c995 + 7559a8f commit 600481d
Show file tree
Hide file tree
Showing 31 changed files with 693 additions and 432 deletions.
5 changes: 5 additions & 0 deletions .changeset/few-dragons-develop.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@zag-js/vue": patch
---

Fix issue where svg `viewBox` attribute handling between client and server
6 changes: 6 additions & 0 deletions .changeset/smart-spies-brake.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@zag-js/progress": minor
"@zag-js/qr-code": minor
---

Add support for `onValueChange` callback
3 changes: 3 additions & 0 deletions .xstate/qr-code.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ const fetchMachine = createMachine({
on: {
"VALUE.SET": {
actions: ["setValue"]
},
"DOWNLOAD_TRIGGER.CLICK": {
actions: ["downloadQrCode"]
}
}
}, {
Expand Down
2 changes: 1 addition & 1 deletion examples/lit-ts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,6 @@
},
"devDependencies": {
"typescript": "^5.7.2",
"vite": "^6.0.5"
"vite": "^6.0.7"
}
}
2 changes: 1 addition & 1 deletion examples/next-ts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@
"@atlaskit/pragmatic-drag-and-drop-flourish": "1.1.2",
"@atlaskit/pragmatic-drag-and-drop-hitbox": "1.0.3",
"@types/form-serialize": "0.7.4",
"@types/node": "22.10.2",
"@types/node": "22.10.5",
"@types/react": "^18",
"@types/react-dom": "^18",
"eslint-plugin-react": "7.37.2",
Expand Down
2 changes: 1 addition & 1 deletion examples/next-ts/pages/compositions
1 change: 0 additions & 1 deletion examples/next-ts/pages/qr-code.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
/* eslint-disable jsx-a11y/alt-text */
import * as qrCode from "@zag-js/qr-code"
import { useMachine, normalizeProps } from "@zag-js/react"
import { qrCodeControls } from "@zag-js/shared"
Expand Down
1 change: 1 addition & 0 deletions examples/nuxt-ts/nuxt.config.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
devtools: { enabled: true },
compatibilityDate: "2025-01-07",
})
2 changes: 1 addition & 1 deletion examples/nuxt-ts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@
"devDependencies": {
"@nuxt/devtools": "latest",
"@types/form-serialize": "0.7.4",
"@types/node": "22.10.2",
"@types/node": "22.10.5",
"nuxt": "3.14.1592"
}
}
2 changes: 1 addition & 1 deletion examples/preact-ts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,6 @@
"eslint": "9.13.0",
"eslint-config-preact": "1.5.0",
"typescript": "5.7.2",
"vite": "6.0.5"
"vite": "6.0.7"
}
}
2 changes: 1 addition & 1 deletion examples/react-19/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,6 @@
"globals": "^15.9.0",
"typescript": "^5.7.2",
"typescript-eslint": "^8.7.0",
"vite": "^6.0.5"
"vite": "^6.0.7"
}
}
4 changes: 2 additions & 2 deletions examples/svelte-ts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -92,11 +92,11 @@
"@sveltejs/vite-plugin-svelte": "5.0.1",
"@tsconfig/svelte": "5.0.4",
"@types/form-serialize": "0.7.4",
"svelte": "5.16.0",
"svelte": "5.16.5",
"svelte-check": "4.1.1",
"tslib": "2.7.0",
"typescript": "5.7.2",
"vite": "6.0.5",
"vite": "6.0.7",
"vite-tsconfig-paths": "5.1.4"
}
}
2 changes: 1 addition & 1 deletion examples/vanilla-ts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
},
"devDependencies": {
"typescript": "^5.7.2",
"vite": "^6.0.5"
"vite": "^6.0.7"
},
"dependencies": {
"@internationalized/date": "3.6.0",
Expand Down
14 changes: 7 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,10 @@
"@swc/core": "1.10.4",
"@types/babel__generator": "7.6.8",
"@types/babel__traverse": "7.20.6",
"@types/node": "22.10.2",
"@types/node": "22.10.5",
"@types/signale": "1.4.7",
"@typescript-eslint/eslint-plugin": "8.18.2",
"@typescript-eslint/parser": "8.18.2",
"@typescript-eslint/eslint-plugin": "8.19.1",
"@typescript-eslint/parser": "8.19.1",
"axe-core": "4.10.2",
"commitlint": "19.6.1",
"cross-env": "^7.0.3",
Expand All @@ -85,7 +85,7 @@
"eslint-config-prettier": "9.1.0",
"eslint-plugin-import": "2.31.0",
"eslint-plugin-prettier": "5.2.1",
"fast-glob": "3.3.2",
"fast-glob": "3.3.3",
"find-packages": "10.0.4",
"husky": "9.1.7",
"lint-staged": "15.3.0",
Expand All @@ -94,17 +94,17 @@
"prettier": "3.4.2",
"prettier-plugin-svelte": "3.3.2",
"signale": "1.4.0",
"ts-morph": "24.0.0",
"ts-morph": "25.0.0",
"tsup": "8.3.5",
"tsx": "4.19.2",
"typescript": "5.7.2",
"vercel-submodules": "1.0.10",
"vite": "6.0.6",
"vite": "6.0.7",
"vite-plugin-dts": "4.4.0",
"vitest": "2.1.8"
},
"engines": {
"node": ">=18.0.0"
},
"packageManager": "[email protected].2"
"packageManager": "[email protected].3"
}
2 changes: 1 addition & 1 deletion packages/frameworks/svelte/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"devDependencies": {
"@sveltejs/package": "2.3.7",
"clean-package": "2.2.0",
"svelte": "5.16.0"
"svelte": "5.16.5"
},
"peerDependencies": {
"svelte": "^5.0.0-next.1"
Expand Down
12 changes: 7 additions & 5 deletions packages/frameworks/vue/src/normalize-props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,15 @@ const propMap: Record<string, string> = {
defaultChecked: "checked",
}

const preserveKeys =
"viewBox,className,preserveAspectRatio,fillRule,clipPath,clipRule,strokeWidth,strokeLinecap,strokeLinejoin,strokeDasharray,strokeDashoffset,strokeMiterlimit".split(
",",
)

function toVueProp(prop: string) {
if (prop in propMap) return propMap[prop]

if (prop.startsWith("on")) {
return `on${toCase(prop.substr(2))}`
}

if (prop.startsWith("on")) return `on${toCase(prop.substr(2))}`
if (preserveKeys.includes(prop)) return prop
return prop.toLowerCase()
}

Expand Down
1 change: 1 addition & 0 deletions packages/machines/progress/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export type {
Orientation,
ProgressState,
Service,
ValueChangeDetails,
ValueTranslationDetails,
ViewProps,
} from "./progress.types"
12 changes: 10 additions & 2 deletions packages/machines/progress/src/progress.machine.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { createMachine } from "@zag-js/core"
import { compact, isNumber } from "@zag-js/utils"
import { compact, isEqual, isNumber } from "@zag-js/utils"
import type { MachineContext, MachineState, UserDefinedContext } from "./progress.types"

function midValue(min: number, max: number) {
Expand Down Expand Up @@ -50,7 +50,7 @@ export function machine(userContext: UserDefinedContext) {
{
actions: {
setValue: (ctx, evt) => {
ctx.value = evt.value === null ? null : Math.max(0, Math.min(evt.value, ctx.max))
set.value(ctx, evt.value)
},
validateContext: (ctx) => {
if (ctx.value == null) return
Expand Down Expand Up @@ -83,3 +83,11 @@ function isValidMax(value: number, max: number) {
function isValidMin(value: number, min: number) {
return isValidNumber(value) && value >= min
}

const set = {
value(ctx: MachineContext, value: number | null) {
if (isEqual(ctx.value, value)) return
ctx.value = value === null ? null : Math.max(0, Math.min(value, ctx.max))
ctx.onValueChange?.({ value })
},
}
1 change: 1 addition & 0 deletions packages/machines/progress/src/progress.props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export const props = createProps<UserDefinedContext>()([
"orientation",
"translations",
"value",
"onValueChange",
])

export const splitProps = createSplitProps<Partial<UserDefinedContext>>(props)
8 changes: 8 additions & 0 deletions packages/machines/progress/src/progress.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ export interface ValueTranslationDetails {
percent: number
}

export interface ValueChangeDetails {
value: number | null
}

export interface IntlTranslations {
value(details: ValueTranslationDetails): string
}
Expand Down Expand Up @@ -60,6 +64,10 @@ interface PublicContext extends DirectionProperty, CommonProperties, Orientation
* The localized messages to use.
*/
translations: IntlTranslations
/**
* Callback fired when the value changes.
*/
onValueChange?: ((details: ValueChangeDetails) => void) | undefined
}

interface PrivateContext {}
Expand Down
2 changes: 2 additions & 0 deletions packages/machines/qr-code/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ export * from "./qr-code.props"
export type {
MachineApi as Api,
UserDefinedContext as Context,
DownloadTriggerProps,
ElementIds,
QrCodeGenerateOptions,
QrCodeGenerateResult,
Service,
ValueChangeDetails,
} from "./qr-code.types"
2 changes: 1 addition & 1 deletion packages/machines/qr-code/src/qr-code.anatomy.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { createAnatomy } from "@zag-js/anatomy"

export const anatomy = createAnatomy("qr-code").parts("root", "frame", "pattern", "overlay")
export const anatomy = createAnatomy("qr-code").parts("root", "frame", "pattern", "overlay", "downloadTrigger")

export const parts = anatomy.build()
11 changes: 11 additions & 0 deletions packages/machines/qr-code/src/qr-code.connect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,5 +73,16 @@ export function connect<T extends PropTypes>(state: State, send: Send, normalize
},
})
},

getDownloadTriggerProps(props) {
return normalize.button({
type: "button",
...parts.downloadTrigger.attrs,
onClick(event) {
if (event.defaultPrevented) return
send({ type: "DOWNLOAD_TRIGGER.CLICK", ...props })
},
})
},
}
}
34 changes: 31 additions & 3 deletions packages/machines/qr-code/src/qr-code.machine.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { createMachine } from "@zag-js/core"
import { compact } from "@zag-js/utils"
import { getDataUrl } from "@zag-js/dom-query"
import { compact, isEqual } from "@zag-js/utils"
import { memoize } from "proxy-memoize"
import { encode } from "uqr"
import { dom } from "./qr-code.dom"
import type { MachineContext, MachineState, UserDefinedContext } from "./qr-code.types"

export function machine(userContext: UserDefinedContext) {
Expand All @@ -24,14 +26,40 @@ export function machine(userContext: UserDefinedContext) {
"VALUE.SET": {
actions: ["setValue"],
},
"DOWNLOAD_TRIGGER.CLICK": {
actions: ["downloadQrCode"],
},
},
},
{
actions: {
setValue: (ctx, e) => {
ctx.value = e.value
setValue(ctx, evt) {
set.value(ctx, evt.value)
},
downloadQrCode(ctx, evt) {
const { mimeType, quality, fileName } = evt
const svgEl = dom.getFrameEl(ctx)
const doc = dom.getDoc(ctx)
getDataUrl(svgEl, { type: mimeType, quality }).then((dataUri) => {
const a = doc.createElement("a")
a.href = dataUri
a.rel = "noopener"
a.download = fileName
a.click()
setTimeout(() => {
a.remove()
}, 0)
})
},
},
},
)
}

const set = {
value(ctx: MachineContext, value: string) {
if (isEqual(ctx.value, value)) return
ctx.value = value
ctx.onValueChange?.({ value })
},
}
10 changes: 9 additions & 1 deletion packages/machines/qr-code/src/qr-code.props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@ import { createProps } from "@zag-js/types"
import { createSplitProps } from "@zag-js/utils"
import type { UserDefinedContext } from "./qr-code.types"

export const props = createProps<UserDefinedContext>()(["ids", "value", "id", "encoding", "dir", "getRootNode"])
export const props = createProps<UserDefinedContext>()([
"ids",
"value",
"id",
"encoding",
"dir",
"getRootNode",
"onValueChange",
])

export const splitProps = createSplitProps<Partial<UserDefinedContext>>(props)
24 changes: 24 additions & 0 deletions packages/machines/qr-code/src/qr-code.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ export type ElementIds = Partial<{
frame: string
}>

export interface ValueChangeDetails {
value: string
}

interface PublicContext extends DirectionProperty, CommonProperties {
/**
* The value to encode.
Expand All @@ -21,6 +25,10 @@ interface PublicContext extends DirectionProperty, CommonProperties {
* The qr code encoding options.
*/
encoding?: QrCodeGenerateOptions | undefined
/**
* Callback fired when the value changes.
*/
onValueChange?: ((details: ValueChangeDetails) => void) | undefined
}

interface PrivateContext {
Expand Down Expand Up @@ -52,6 +60,21 @@ export type Service = Machine<MachineContext, MachineState, S.AnyEventObject>
* Component API
* -----------------------------------------------------------------------------*/

export interface DownloadTriggerProps {
/**
* The mime type of the image.
*/
mimeType: DataUrlType
/**
* The quality of the image.
*/
quality?: number
/**
* The name of the file.
*/
fileName: string
}

export interface MachineApi<T extends PropTypes = PropTypes> {
/**
* The value to encode.
Expand All @@ -70,6 +93,7 @@ export interface MachineApi<T extends PropTypes = PropTypes> {
getFrameProps(): T["svg"]
getPatternProps(): T["path"]
getOverlayProps(): T["element"]
getDownloadTriggerProps(props: DownloadTriggerProps): T["button"]
}

export type { QrCodeGenerateOptions, QrCodeGenerateResult } from "uqr"
Loading

0 comments on commit 600481d

Please sign in to comment.