diff --git a/.changeset/smart-spies-brake.md b/.changeset/smart-spies-brake.md new file mode 100644 index 0000000000..515834a70d --- /dev/null +++ b/.changeset/smart-spies-brake.md @@ -0,0 +1,6 @@ +--- +"@zag-js/progress": minor +"@zag-js/qr-code": minor +--- + +Add support for `onValueChange` callback diff --git a/packages/machines/progress/src/index.ts b/packages/machines/progress/src/index.ts index 338284235e..693c20b864 100644 --- a/packages/machines/progress/src/index.ts +++ b/packages/machines/progress/src/index.ts @@ -10,6 +10,7 @@ export type { Orientation, ProgressState, Service, + ValueChangeDetails, ValueTranslationDetails, ViewProps, } from "./progress.types" diff --git a/packages/machines/progress/src/progress.machine.ts b/packages/machines/progress/src/progress.machine.ts index f4d9fdc837..d102bc94cc 100644 --- a/packages/machines/progress/src/progress.machine.ts +++ b/packages/machines/progress/src/progress.machine.ts @@ -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) { @@ -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 @@ -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 }) + }, +} diff --git a/packages/machines/progress/src/progress.props.ts b/packages/machines/progress/src/progress.props.ts index 77a767c088..33bf3b1b6c 100644 --- a/packages/machines/progress/src/progress.props.ts +++ b/packages/machines/progress/src/progress.props.ts @@ -12,6 +12,7 @@ export const props = createProps()([ "orientation", "translations", "value", + "onValueChange", ]) export const splitProps = createSplitProps>(props) diff --git a/packages/machines/progress/src/progress.types.ts b/packages/machines/progress/src/progress.types.ts index 275e473e7d..db46554216 100644 --- a/packages/machines/progress/src/progress.types.ts +++ b/packages/machines/progress/src/progress.types.ts @@ -21,6 +21,10 @@ export interface ValueTranslationDetails { percent: number } +export interface ValueChangeDetails { + value: number | null +} + export interface IntlTranslations { value(details: ValueTranslationDetails): string } @@ -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 {} diff --git a/packages/machines/qr-code/src/index.ts b/packages/machines/qr-code/src/index.ts index b108783354..2442b38661 100644 --- a/packages/machines/qr-code/src/index.ts +++ b/packages/machines/qr-code/src/index.ts @@ -9,4 +9,5 @@ export type { QrCodeGenerateOptions, QrCodeGenerateResult, Service, + ValueChangeDetails, } from "./qr-code.types" diff --git a/packages/machines/qr-code/src/qr-code.machine.ts b/packages/machines/qr-code/src/qr-code.machine.ts index 1e91e4bfec..b4222c1d63 100644 --- a/packages/machines/qr-code/src/qr-code.machine.ts +++ b/packages/machines/qr-code/src/qr-code.machine.ts @@ -1,5 +1,5 @@ import { createMachine } from "@zag-js/core" -import { compact } from "@zag-js/utils" +import { compact, isEqual } from "@zag-js/utils" import { memoize } from "proxy-memoize" import { encode } from "uqr" import type { MachineContext, MachineState, UserDefinedContext } from "./qr-code.types" @@ -28,10 +28,18 @@ export function machine(userContext: UserDefinedContext) { }, { actions: { - setValue: (ctx, e) => { - ctx.value = e.value + setValue(ctx, evt) { + set.value(ctx, evt.value) }, }, }, ) } + +const set = { + value(ctx: MachineContext, value: string) { + if (isEqual(ctx.value, value)) return + ctx.value = value + ctx.onValueChange?.({ value }) + }, +} diff --git a/packages/machines/qr-code/src/qr-code.props.ts b/packages/machines/qr-code/src/qr-code.props.ts index d26cc115b1..a3a6848616 100644 --- a/packages/machines/qr-code/src/qr-code.props.ts +++ b/packages/machines/qr-code/src/qr-code.props.ts @@ -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()(["ids", "value", "id", "encoding", "dir", "getRootNode"]) +export const props = createProps()([ + "ids", + "value", + "id", + "encoding", + "dir", + "getRootNode", + "onValueChange", +]) export const splitProps = createSplitProps>(props) diff --git a/packages/machines/qr-code/src/qr-code.types.ts b/packages/machines/qr-code/src/qr-code.types.ts index 86a4cdc46a..ee248596f5 100644 --- a/packages/machines/qr-code/src/qr-code.types.ts +++ b/packages/machines/qr-code/src/qr-code.types.ts @@ -8,6 +8,10 @@ export type ElementIds = Partial<{ frame: string }> +export interface ValueChangeDetails { + value: string +} + interface PublicContext extends DirectionProperty, CommonProperties { /** * The value to encode. @@ -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 {