Skip to content

Commit

Permalink
refactor: streamline form-utils
Browse files Browse the repository at this point in the history
  • Loading branch information
segunadebayo committed Jan 13, 2025
1 parent 884973b commit e9313a3
Show file tree
Hide file tree
Showing 44 changed files with 96 additions and 890 deletions.
5 changes: 5 additions & 0 deletions .changeset/fuzzy-nails-marry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@zag-js/dom-query": patch
---

Don't reset form fields if reset event is cancelled.
1 change: 0 additions & 1 deletion examples/lit-ts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@
"@zag-js/floating-panel": "workspace:*",
"@zag-js/focus-trap": "workspace:*",
"@zag-js/focus-visible": "workspace:*",
"@zag-js/form-utils": "workspace:*",
"@zag-js/highlight-word": "workspace:*",
"@zag-js/hover-card": "workspace:*",
"@zag-js/i18n-utils": "workspace:*",
Expand Down
1 change: 0 additions & 1 deletion examples/next-ts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@
"@zag-js/floating-panel": "workspace:*",
"@zag-js/focus-trap": "workspace:*",
"@zag-js/focus-visible": "workspace:*",
"@zag-js/form-utils": "workspace:*",
"@zag-js/highlight-word": "workspace:*",
"@zag-js/hover-card": "workspace:*",
"@zag-js/i18n-utils": "workspace:*",
Expand Down
1 change: 0 additions & 1 deletion examples/nuxt-ts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@
"@zag-js/floating-panel": "workspace:*",
"@zag-js/focus-trap": "workspace:*",
"@zag-js/focus-visible": "workspace:*",
"@zag-js/form-utils": "workspace:*",
"@zag-js/highlight-word": "workspace:*",
"@zag-js/hover-card": "workspace:*",
"@zag-js/i18n-utils": "workspace:*",
Expand Down
1 change: 0 additions & 1 deletion examples/preact-ts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@
"@zag-js/floating-panel": "workspace:*",
"@zag-js/focus-trap": "workspace:*",
"@zag-js/focus-visible": "workspace:*",
"@zag-js/form-utils": "workspace:*",
"@zag-js/highlight-word": "workspace:*",
"@zag-js/hover-card": "workspace:*",
"@zag-js/i18n-utils": "workspace:*",
Expand Down
1 change: 0 additions & 1 deletion examples/react-19/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@
"@zag-js/floating-panel": "workspace:*",
"@zag-js/focus-trap": "workspace:*",
"@zag-js/focus-visible": "workspace:*",
"@zag-js/form-utils": "workspace:*",
"@zag-js/highlight-word": "workspace:*",
"@zag-js/hover-card": "workspace:*",
"@zag-js/i18n-utils": "workspace:*",
Expand Down
1 change: 0 additions & 1 deletion examples/solid-ts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@
"@zag-js/floating-panel": "workspace:*",
"@zag-js/focus-trap": "workspace:*",
"@zag-js/focus-visible": "workspace:*",
"@zag-js/form-utils": "workspace:*",
"@zag-js/highlight-word": "workspace:*",
"@zag-js/hover-card": "workspace:*",
"@zag-js/i18n-utils": "workspace:*",
Expand Down
1 change: 0 additions & 1 deletion examples/svelte-ts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@
"@zag-js/floating-panel": "workspace:*",
"@zag-js/focus-trap": "workspace:*",
"@zag-js/focus-visible": "workspace:*",
"@zag-js/form-utils": "workspace:*",
"@zag-js/highlight-word": "workspace:*",
"@zag-js/hover-card": "workspace:*",
"@zag-js/i18n-utils": "workspace:*",
Expand Down
1 change: 0 additions & 1 deletion examples/vanilla-ts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@
"@zag-js/floating-panel": "workspace:*",
"@zag-js/focus-trap": "workspace:*",
"@zag-js/focus-visible": "workspace:*",
"@zag-js/form-utils": "workspace:*",
"@zag-js/highlight-word": "workspace:*",
"@zag-js/hover-card": "workspace:*",
"@zag-js/i18n-utils": "workspace:*",
Expand Down
1 change: 0 additions & 1 deletion packages/machines/checkbox/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@
"@zag-js/types": "workspace:*",
"@zag-js/dom-query": "workspace:*",
"@zag-js/focus-visible": "workspace:*",
"@zag-js/form-utils": "workspace:*",
"@zag-js/utils": "workspace:*"
},
"devDependencies": {
Expand Down
3 changes: 1 addition & 2 deletions packages/machines/checkbox/src/checkbox.machine.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { createMachine, guards } from "@zag-js/core"
import { trackPress } from "@zag-js/dom-query"
import { dispatchInputCheckedEvent, setElementChecked, trackFormControl, trackPress } from "@zag-js/dom-query"
import { trackFocusVisible } from "@zag-js/focus-visible"
import { dispatchInputCheckedEvent, setElementChecked, trackFormControl } from "@zag-js/form-utils"
import { compact, isEqual } from "@zag-js/utils"
import { dom } from "./checkbox.dom"
import type { CheckedState, MachineContext, MachineState, UserDefinedContext } from "./checkbox.types"
Expand Down
1 change: 0 additions & 1 deletion packages/machines/color-picker/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@
"@zag-js/dom-query": "workspace:*",
"@zag-js/dismissable": "workspace:*",
"@zag-js/utils": "workspace:*",
"@zag-js/form-utils": "workspace:*",
"@zag-js/color-utils": "workspace:*",
"@zag-js/popper": "workspace:*",
"@zag-js/types": "workspace:*"
Expand Down
10 changes: 8 additions & 2 deletions packages/machines/color-picker/src/color-picker.machine.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
import { parseColor, type Color } from "@zag-js/color-utils"
import { createMachine, guards } from "@zag-js/core"
import { trackDismissableElement } from "@zag-js/dismissable"
import { getInitialFocus, raf, trackPointerMove, disableTextSelection } from "@zag-js/dom-query"
import { dispatchInputValueEvent, trackFormControl } from "@zag-js/form-utils"
import {
disableTextSelection,
dispatchInputValueEvent,
getInitialFocus,
raf,
trackFormControl,
trackPointerMove,
} from "@zag-js/dom-query"
import { getPlacement } from "@zag-js/popper"
import { compact, tryCatch } from "@zag-js/utils"
import { dom } from "./color-picker.dom"
Expand Down
1 change: 0 additions & 1 deletion packages/machines/date-picker/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@
"@zag-js/types": "workspace:*",
"@zag-js/date-utils": "workspace:*",
"@zag-js/dom-query": "workspace:*",
"@zag-js/form-utils": "workspace:*",
"@zag-js/popper": "workspace:*",
"@zag-js/utils": "workspace:*"
},
Expand Down
1 change: 0 additions & 1 deletion packages/machines/editable/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
"@zag-js/interact-outside": "workspace:*",
"@zag-js/utils": "workspace:*",
"@zag-js/dom-query": "workspace:*",
"@zag-js/form-utils": "workspace:*",
"@zag-js/types": "workspace:*"
},
"devDependencies": {
Expand Down
1 change: 0 additions & 1 deletion packages/machines/number-input/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
"@zag-js/anatomy": "workspace:*",
"@zag-js/core": "workspace:*",
"@zag-js/dom-query": "workspace:*",
"@zag-js/form-utils": "workspace:*",
"@zag-js/types": "workspace:*",
"@zag-js/utils": "workspace:*"
},
Expand Down
11 changes: 9 additions & 2 deletions packages/machines/number-input/src/number-input.machine.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import { choose, createMachine, guards } from "@zag-js/core"
import { addDomEvent, isSafari, observeAttributes, raf, requestPointerLock } from "@zag-js/dom-query"
import { setElementValue, trackFormControl } from "@zag-js/form-utils"
import {
addDomEvent,
isSafari,
observeAttributes,
raf,
requestPointerLock,
setElementValue,
trackFormControl,
} from "@zag-js/dom-query"
import {
callAll,
clampValue,
Expand Down
1 change: 0 additions & 1 deletion packages/machines/pin-input/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
"dependencies": {
"@zag-js/anatomy": "workspace:*",
"@zag-js/dom-query": "workspace:*",
"@zag-js/form-utils": "workspace:*",
"@zag-js/utils": "workspace:*",
"@zag-js/core": "workspace:*",
"@zag-js/types": "workspace:*"
Expand Down
3 changes: 1 addition & 2 deletions packages/machines/pin-input/src/pin-input.machine.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { choose, createMachine } from "@zag-js/core"
import { raf } from "@zag-js/dom-query"
import { dispatchInputValueEvent } from "@zag-js/form-utils"
import { dispatchInputValueEvent, raf } from "@zag-js/dom-query"
import { compact, isEqual } from "@zag-js/utils"
import { dom } from "./pin-input.dom"
import type { MachineContext, MachineState, UserDefinedContext } from "./pin-input.types"
Expand Down
1 change: 0 additions & 1 deletion packages/machines/radio-group/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@
"@zag-js/dom-query": "workspace:*",
"@zag-js/element-rect": "workspace:*",
"@zag-js/focus-visible": "workspace:*",
"@zag-js/form-utils": "workspace:*",
"@zag-js/utils": "workspace:*",
"@zag-js/core": "workspace:*",
"@zag-js/types": "workspace:*"
Expand Down
3 changes: 1 addition & 2 deletions packages/machines/radio-group/src/radio-group.machine.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { createMachine, guards } from "@zag-js/core"
import { nextTick } from "@zag-js/dom-query"
import { dispatchInputCheckedEvent, nextTick, trackFormControl } from "@zag-js/dom-query"
import { trackElementRect } from "@zag-js/element-rect"
import { trackFocusVisible } from "@zag-js/focus-visible"
import { dispatchInputCheckedEvent, trackFormControl } from "@zag-js/form-utils"
import { compact, isEqual, isString } from "@zag-js/utils"
import { dom } from "./radio-group.dom"
import type { MachineContext, MachineState, UserDefinedContext } from "./radio-group.types"
Expand Down
1 change: 0 additions & 1 deletion packages/machines/rating-group/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
"dependencies": {
"@zag-js/anatomy": "workspace:*",
"@zag-js/dom-query": "workspace:*",
"@zag-js/form-utils": "workspace:*",
"@zag-js/utils": "workspace:*",
"@zag-js/core": "workspace:*",
"@zag-js/types": "workspace:*"
Expand Down
3 changes: 1 addition & 2 deletions packages/machines/rating-group/src/rating-group.dom.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { createScope, query } from "@zag-js/dom-query"
import { dispatchInputValueEvent } from "@zag-js/form-utils"
import { createScope, dispatchInputValueEvent, query } from "@zag-js/dom-query"
import type { MachineContext as Ctx } from "./rating-group.types"

export const dom = createScope({
Expand Down
3 changes: 1 addition & 2 deletions packages/machines/rating-group/src/rating-group.machine.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { createMachine } from "@zag-js/core"
import { raf } from "@zag-js/dom-query"
import { trackFormControl } from "@zag-js/form-utils"
import { raf, trackFormControl } from "@zag-js/dom-query"
import { compact, isEqual } from "@zag-js/utils"
import { dom } from "./rating-group.dom"
import type { MachineContext, MachineState, UserDefinedContext } from "./rating-group.types"
Expand Down
1 change: 0 additions & 1 deletion packages/machines/select/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@
"@zag-js/popper": "workspace:*",
"@zag-js/dom-query": "workspace:*",
"@zag-js/collection": "workspace:*",
"@zag-js/form-utils": "workspace:*",
"@zag-js/utils": "workspace:*",
"@zag-js/dismissable": "workspace:*",
"@zag-js/types": "workspace:*"
Expand Down
10 changes: 8 additions & 2 deletions packages/machines/select/src/select.machine.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
import { createMachine, guards } from "@zag-js/core"
import { trackDismissableElement } from "@zag-js/dismissable"
import { getByTypeahead, getInitialFocus, observeAttributes, raf, scrollIntoView } from "@zag-js/dom-query"
import { trackFormControl } from "@zag-js/form-utils"
import {
getByTypeahead,
getInitialFocus,
observeAttributes,
raf,
scrollIntoView,
trackFormControl,
} from "@zag-js/dom-query"
import { getPlacement } from "@zag-js/popper"
import { addOrRemove, compact, isEqual } from "@zag-js/utils"
import { collection } from "./select.collection"
Expand Down
1 change: 0 additions & 1 deletion packages/machines/slider/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
"dependencies": {
"@zag-js/anatomy": "workspace:*",
"@zag-js/core": "workspace:*",
"@zag-js/form-utils": "workspace:*",
"@zag-js/dom-query": "workspace:*",
"@zag-js/utils": "workspace:*",
"@zag-js/element-size": "workspace:*",
Expand Down
3 changes: 1 addition & 2 deletions packages/machines/slider/src/slider.dom.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { createScope, getRelativePoint, queryAll } from "@zag-js/dom-query"
import { dispatchInputValueEvent } from "@zag-js/form-utils"
import { createScope, dispatchInputValueEvent, getRelativePoint, queryAll } from "@zag-js/dom-query"
import type { Point } from "@zag-js/types"
import { getPercentValue } from "@zag-js/utils"
import { styleGetterFns } from "./slider.style"
Expand Down
3 changes: 1 addition & 2 deletions packages/machines/slider/src/slider.machine.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { createMachine } from "@zag-js/core"
import { raf, trackPointerMove } from "@zag-js/dom-query"
import { raf, trackFormControl, trackPointerMove } from "@zag-js/dom-query"
import { trackElementsSize, type ElementSize } from "@zag-js/element-size"
import { trackFormControl } from "@zag-js/form-utils"
import { compact, getValuePercent, isEqual } from "@zag-js/utils"
import { dom } from "./slider.dom"
import type { MachineContext, MachineState, UserDefinedContext } from "./slider.types"
Expand Down
1 change: 0 additions & 1 deletion packages/machines/switch/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@
"@zag-js/core": "workspace:*",
"@zag-js/dom-query": "workspace:*",
"@zag-js/focus-visible": "workspace:*",
"@zag-js/form-utils": "workspace:*",
"@zag-js/utils": "workspace:*",
"@zag-js/types": "workspace:*"
},
Expand Down
3 changes: 1 addition & 2 deletions packages/machines/switch/src/switch.machine.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { createMachine, guards } from "@zag-js/core"
import { trackPress } from "@zag-js/dom-query"
import { dispatchInputCheckedEvent, trackFormControl, trackPress } from "@zag-js/dom-query"
import { trackFocusVisible } from "@zag-js/focus-visible"
import { dispatchInputCheckedEvent, trackFormControl } from "@zag-js/form-utils"
import { compact, isEqual } from "@zag-js/utils"
import { dom } from "./switch.dom"
import type { MachineContext, MachineState, UserDefinedContext } from "./switch.types"
Expand Down
1 change: 0 additions & 1 deletion packages/machines/tags-input/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
"@zag-js/interact-outside": "workspace:*",
"@zag-js/live-region": "workspace:*",
"@zag-js/dom-query": "workspace:*",
"@zag-js/form-utils": "workspace:*",
"@zag-js/utils": "workspace:*",
"@zag-js/types": "workspace:*"
},
Expand Down
3 changes: 1 addition & 2 deletions packages/machines/tags-input/src/tags-input.dom.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { createScope, indexOfId, nextById, prevById, queryAll } from "@zag-js/dom-query"
import { dispatchInputValueEvent } from "@zag-js/form-utils"
import { createScope, dispatchInputValueEvent, indexOfId, nextById, prevById, queryAll } from "@zag-js/dom-query"
import type { MachineContext as Ctx, ItemProps } from "./tags-input.types"

export const dom = createScope({
Expand Down
3 changes: 1 addition & 2 deletions packages/machines/tags-input/src/tags-input.machine.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { autoResizeInput } from "@zag-js/auto-resize"
import { createMachine, guards } from "@zag-js/core"
import { contains, raf } from "@zag-js/dom-query"
import { trackFormControl } from "@zag-js/form-utils"
import { contains, raf, trackFormControl } from "@zag-js/dom-query"
import { trackInteractOutside } from "@zag-js/interact-outside"
import { createLiveRegion } from "@zag-js/live-region"
import { compact, isEqual, removeAt, uniq, warn } from "@zag-js/utils"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { getWindow } from "./node"

interface DescriptorOptions {
type?: "HTMLInputElement" | "HTMLTextAreaElement" | "HTMLSelectElement" | undefined
property?: "value" | "checked" | undefined
}

const getWindow = (el: HTMLElement) => el.ownerDocument.defaultView || window

function getDescriptor(el: HTMLElement, options: DescriptorOptions) {
const { type = "HTMLInputElement", property = "value" } = options
const proto = getWindow(el)[type].prototype
Expand All @@ -26,12 +26,12 @@ export function setElementChecked(el: HTMLElement, checked: boolean) {
else el.removeAttribute("checked")
}

export type InputEventOptions = {
export interface InputValueEventOptions {
value: string | number
bubbles?: boolean
}

export function dispatchInputValueEvent(el: HTMLElement | null, options: InputEventOptions) {
export function dispatchInputValueEvent(el: HTMLElement | null, options: InputValueEventOptions) {
const { value, bubbles = true } = options

if (!el) return
Expand All @@ -43,19 +43,60 @@ export function dispatchInputValueEvent(el: HTMLElement | null, options: InputEv
el.dispatchEvent(new win.Event("input", { bubbles }))
}

export type CheckedEventOptions = {
export interface CheckedEventOptions {
checked: boolean
bubbles?: boolean
}

export function dispatchInputCheckedEvent(el: HTMLElement | null, options: CheckedEventOptions) {
const { checked, bubbles = true } = options

if (!el) return

const win = getWindow(el)
if (!(el instanceof win.HTMLInputElement)) return

setElementChecked(el, checked)
el.dispatchEvent(new win.Event("click", { bubbles }))
}

function getClosestForm(el: HTMLElement) {
return isFormElement(el) ? el.form : el.closest("form")
}

function isFormElement(el: HTMLElement): el is HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement {
return el.matches("textarea, input, select, button")
}

function trackFormReset(el: HTMLElement | null | undefined, callback: () => void) {
if (!el) return
const form = getClosestForm(el)
const onReset = (e: Event) => {
if (e.defaultPrevented) return
callback()
}
form?.addEventListener("reset", onReset, { passive: true })
return () => form?.removeEventListener("reset", onReset)
}

function trackFieldsetDisabled(el: HTMLElement | null | undefined, callback: (disabled: boolean) => void) {
const fieldset = el?.closest("fieldset")
if (!fieldset) return
callback(fieldset.disabled)
const win = getWindow(fieldset)
const obs = new win.MutationObserver(() => callback(fieldset.disabled))
obs.observe(fieldset, {
attributes: true,
attributeFilter: ["disabled"],
})
return () => obs.disconnect()
}

export interface TrackFormControlOptions {
onFieldsetDisabledChange: (disabled: boolean) => void
onFormReset: () => void
}

export function trackFormControl(el: HTMLElement | null, options: TrackFormControlOptions) {
if (!el) return
const { onFieldsetDisabledChange, onFormReset } = options
const cleanups = [trackFormReset(el, onFormReset), trackFieldsetDisabled(el, onFieldsetDisabledChange)]
return () => cleanups.forEach((cleanup) => cleanup?.())
}
1 change: 1 addition & 0 deletions packages/utilities/dom-query/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export * from "./computed-style"
export * from "./data-url"
export * from "./event"
export * from "./form"
export * from "./initial-focus"
export * from "./mutation-observer"
export * from "./navigate"
Expand Down
Loading

0 comments on commit e9313a3

Please sign in to comment.