diff --git a/examples/alpine-ts/.gitignore b/examples/alpine-ts/.gitignore new file mode 100644 index 0000000000..a547bf36d8 --- /dev/null +++ b/examples/alpine-ts/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/examples/alpine-ts/index.html b/examples/alpine-ts/index.html new file mode 100644 index 0000000000..ea25053491 --- /dev/null +++ b/examples/alpine-ts/index.html @@ -0,0 +1,36 @@ + + + + + + + Vite + TS + + +

Alpine.js + Zag

+ + + + diff --git a/examples/alpine-ts/package.json b/examples/alpine-ts/package.json new file mode 100644 index 0000000000..f4df8be5f8 --- /dev/null +++ b/examples/alpine-ts/package.json @@ -0,0 +1,31 @@ +{ + "name": "alpine-ts", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc && vite build", + "preview": "vite preview" + }, + "devDependencies": { + "@types/alpinejs": "^3.13.11", + "typescript": "~5.8.3", + "vite": "^7.1.7" + }, + "dependencies": { + "@zag-js/accordion": "workspace:*", + "@zag-js/angle-slider": "workspace:*", + "@zag-js/avatar": "workspace:*", + "@zag-js/checkbox": "workspace:*", + "@zag-js/collection": "workspace:*", + "@zag-js/combobox": "workspace:*", + "@zag-js/core": "workspace:*", + "@zag-js/dialog": "workspace:*", + "@zag-js/popover": "workspace:*", + "@zag-js/shared": "workspace:*", + "@zag-js/types": "workspace:*", + "@zag-js/utils": "workspace:*", + "alpinejs": "^3.15.0" + } +} diff --git a/examples/alpine-ts/pages/accordion.html b/examples/alpine-ts/pages/accordion.html new file mode 100644 index 0000000000..4fe0a0388b --- /dev/null +++ b/examples/alpine-ts/pages/accordion.html @@ -0,0 +1,35 @@ + + + + + + + Vite + TS + + + +

Accordion

+ +
+
+ + +
+
+ + +
+ +
+ +
+
+ + diff --git a/examples/alpine-ts/pages/accordion.ts b/examples/alpine-ts/pages/accordion.ts new file mode 100644 index 0000000000..2479f1ccda --- /dev/null +++ b/examples/alpine-ts/pages/accordion.ts @@ -0,0 +1,11 @@ +import "@zag-js/shared/src/style.css" + +import Alpine from "alpinejs" +import * as accordion from "@zag-js/accordion" +import { createZagPlugin } from "../src/plugin" + +Alpine.plugin(createZagPlugin("accordion", accordion)) +// @ts-ignore +window.Alpine = Alpine +// @ts-ignore +window.Alpine.start() diff --git a/examples/alpine-ts/pages/angle-slider.html b/examples/alpine-ts/pages/angle-slider.html new file mode 100644 index 0000000000..6ad4c2ae4a --- /dev/null +++ b/examples/alpine-ts/pages/angle-slider.html @@ -0,0 +1,47 @@ + + + + + + + Vite + TS + + + +

Angle Slider

+ +
+
+ + +
+
+ + +
+
+ + +
+ +
+ +
+
+
+ +
+
+ +
+
+ + diff --git a/examples/alpine-ts/pages/angle-slider.ts b/examples/alpine-ts/pages/angle-slider.ts new file mode 100644 index 0000000000..b762dc5434 --- /dev/null +++ b/examples/alpine-ts/pages/angle-slider.ts @@ -0,0 +1,11 @@ +import "@zag-js/shared/src/style.css" + +import Alpine from "alpinejs" +import * as angleSlider from "@zag-js/angle-slider" +import { createZagPlugin } from "../src/plugin" + +Alpine.plugin(createZagPlugin("angle-slider", angleSlider)) +// @ts-ignore +window.Alpine = Alpine +// @ts-ignore +window.Alpine.start() diff --git a/examples/alpine-ts/pages/avatar.html b/examples/alpine-ts/pages/avatar.html new file mode 100644 index 0000000000..0061a39ebb --- /dev/null +++ b/examples/alpine-ts/pages/avatar.html @@ -0,0 +1,31 @@ + + + + + + + Vite + TS + + + +

Avatar

+ +
+
+ + +
+
+ + +
+ +
+ + PA +
+
+ + diff --git a/examples/alpine-ts/pages/avatar.ts b/examples/alpine-ts/pages/avatar.ts new file mode 100644 index 0000000000..b1892a8d21 --- /dev/null +++ b/examples/alpine-ts/pages/avatar.ts @@ -0,0 +1,11 @@ +import "@zag-js/shared/src/style.css" + +import Alpine from "alpinejs" +import * as avatar from "@zag-js/avatar" +import { createZagPlugin } from "../src/plugin" + +Alpine.plugin(createZagPlugin("avatar", avatar)) +// @ts-ignore +window.Alpine = Alpine +// @ts-ignore +window.Alpine.start() diff --git a/examples/alpine-ts/pages/checkbox.html b/examples/alpine-ts/pages/checkbox.html new file mode 100644 index 0000000000..5de46c82a7 --- /dev/null +++ b/examples/alpine-ts/pages/checkbox.html @@ -0,0 +1,36 @@ + + + + + + + Vite + TS + + + +

Checkbox

+ +
+
+ + +
+
+ + +
+ + + + +
+ + diff --git a/examples/alpine-ts/pages/checkbox.ts b/examples/alpine-ts/pages/checkbox.ts new file mode 100644 index 0000000000..3c6934e6b7 --- /dev/null +++ b/examples/alpine-ts/pages/checkbox.ts @@ -0,0 +1,11 @@ +import "@zag-js/shared/src/style.css" + +import Alpine from "alpinejs" +import * as checkbox from "@zag-js/checkbox" +import { createZagPlugin } from "../src/plugin" + +Alpine.plugin(createZagPlugin("checkbox", checkbox)) +// @ts-ignore +window.Alpine = Alpine +// @ts-ignore +window.Alpine.start() diff --git a/examples/alpine-ts/pages/combobox.html b/examples/alpine-ts/pages/combobox.html new file mode 100644 index 0000000000..e36fe6f3c9 --- /dev/null +++ b/examples/alpine-ts/pages/combobox.html @@ -0,0 +1,78 @@ + + + + + + + Vite + TS + + + +

Combobox

+ +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ +
+
+ +
+ + +
+
+
+
    + +
+
+
+
+ + diff --git a/examples/alpine-ts/pages/combobox.ts b/examples/alpine-ts/pages/combobox.ts new file mode 100644 index 0000000000..3b263f4f20 --- /dev/null +++ b/examples/alpine-ts/pages/combobox.ts @@ -0,0 +1,11 @@ +import "@zag-js/shared/src/style.css" + +import Alpine from "alpinejs" +import * as combobox from "@zag-js/combobox" +import { createZagPlugin } from "../src/plugin" + +Alpine.plugin(createZagPlugin("combobox", combobox)) +// @ts-ignore +window.Alpine = Alpine +// @ts-ignore +window.Alpine.start() diff --git a/examples/alpine-ts/pages/dialog.html b/examples/alpine-ts/pages/dialog.html new file mode 100644 index 0000000000..9637e36770 --- /dev/null +++ b/examples/alpine-ts/pages/dialog.html @@ -0,0 +1,56 @@ + + + + + + + Vite + TS + + + +

Popover

+ +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ +
+ + +
+
+ + diff --git a/examples/alpine-ts/pages/dialog.ts b/examples/alpine-ts/pages/dialog.ts new file mode 100644 index 0000000000..c2283e3ba3 --- /dev/null +++ b/examples/alpine-ts/pages/dialog.ts @@ -0,0 +1,11 @@ +import "@zag-js/shared/src/style.css" + +import Alpine from "alpinejs" +import * as dialog from "@zag-js/dialog" +import { createZagPlugin } from "../src/plugin" + +Alpine.plugin(createZagPlugin("dialog", dialog)) +// @ts-ignore +window.Alpine = Alpine +// @ts-ignore +window.Alpine.start() diff --git a/examples/alpine-ts/pages/popover.html b/examples/alpine-ts/pages/popover.html new file mode 100644 index 0000000000..ddf552fb9b --- /dev/null +++ b/examples/alpine-ts/pages/popover.html @@ -0,0 +1,57 @@ + + + + + + + Vite + TS + + + +

Popover

+ +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ +
+ + +
+
+ + diff --git a/examples/alpine-ts/pages/popover.ts b/examples/alpine-ts/pages/popover.ts new file mode 100644 index 0000000000..a077776956 --- /dev/null +++ b/examples/alpine-ts/pages/popover.ts @@ -0,0 +1,11 @@ +import "@zag-js/shared/src/style.css" + +import Alpine from "alpinejs" +import * as popover from "@zag-js/popover" +import { createZagPlugin } from "../src/plugin" + +Alpine.plugin(createZagPlugin("popover", popover)) +// @ts-ignore +window.Alpine = Alpine +// @ts-ignore +window.Alpine.start() diff --git a/examples/alpine-ts/public/vite.svg b/examples/alpine-ts/public/vite.svg new file mode 100644 index 0000000000..e7b8dfb1b2 --- /dev/null +++ b/examples/alpine-ts/public/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/examples/alpine-ts/src/lib/bindable.ts b/examples/alpine-ts/src/lib/bindable.ts new file mode 100644 index 0000000000..602e8f956e --- /dev/null +++ b/examples/alpine-ts/src/lib/bindable.ts @@ -0,0 +1,53 @@ +import type { Bindable, BindableParams } from "@zag-js/core" +import { isFunction } from "@zag-js/utils" +import Alpine from "alpinejs" + +export function bindable(props: () => BindableParams): Bindable { + const initial = props().defaultValue ?? props().value + const eq = props().isEqual ?? Object.is + + const v = Alpine.reactive({ value: initial as T }) + + const controlled = () => props().value !== undefined + + return { + initial, + ref: v, + get() { + return controlled() ? (props().value as T) : v.value + }, + set(val: T | ((prev: T) => T)) { + const prev = controlled() ? (props().value as T) : v.value + const next = isFunction(val) ? val(prev) : val + + if (props().debug) { + console.log(`[bindable > ${props().debug}] setValue`, { next, prev }) + } + + if (!controlled()) v.value = next + if (!eq(next, prev)) { + props().onChange?.(next, prev) + } + }, + invoke(nextValue: T, prevValue: T) { + props().onChange?.(nextValue, prevValue) + }, + hash(value: T) { + return props().hash?.(value) ?? String(value) + }, + } +} + +bindable.cleanup = (_fn: VoidFunction) => { + // No-op in vanilla implementation +} + +bindable.ref = (defaultValue: T) => { + let value = defaultValue + return { + get: () => value, + set: (next: T) => { + value = next + }, + } +} diff --git a/examples/alpine-ts/src/lib/index.ts b/examples/alpine-ts/src/lib/index.ts new file mode 100644 index 0000000000..e0d86db4f4 --- /dev/null +++ b/examples/alpine-ts/src/lib/index.ts @@ -0,0 +1,3 @@ +export { mergeProps } from "@zag-js/core" +export * from "./normalize-props" +export * from "./machine" diff --git a/examples/alpine-ts/src/lib/machine.ts b/examples/alpine-ts/src/lib/machine.ts new file mode 100644 index 0000000000..b50bc97c0f --- /dev/null +++ b/examples/alpine-ts/src/lib/machine.ts @@ -0,0 +1,312 @@ +import type { + ActionsOrFn, + Bindable, + BindableContext, + BindableRefs, + ChooseFn, + ComputedFn, + EffectsOrFn, + GuardFn, + Machine, + MachineSchema, + Params, + PropFn, + Scope, + Service, +} from "@zag-js/core" +import { createScope, INIT_STATE, MachineStatus } from "@zag-js/core" +import { compact, isFunction, isString, toArray, warn } from "@zag-js/utils" +import Alpine from "alpinejs" +import { bindable } from "./bindable" +import { createRefs } from "./refs" +import { track } from "./track" + +export class AlpineMachine implements Service { + scope: Scope = null as any + ctx: BindableContext + prop: PropFn + private _state: Bindable + refs: BindableRefs + computed: ComputedFn + + private _event: any = { type: "" } + private previousEvent: any = null + + private effects = new Map() + private transition: any = null + + private status = MachineStatus.NotStarted + + private getEvent() { + return { + ...this._event, + current: () => this._event, + previous: () => this.previousEvent, + } + } + + get event(): any { + return this.getEvent() + } + + getStatus(): MachineStatus { + return this.status + } + + get context(): BindableContext { + return this.ctx + } + + get state(): Bindable & { + matches: (...values: T["state"][]) => boolean + hasTag: (tag: T["tag"]) => boolean + } { + return this.getState() + } + + private getState(): Bindable & { + matches: (...values: T["state"][]) => boolean + hasTag: (tag: T["tag"]) => boolean + } { + return { + ...this._state, + matches: (...values: T["state"][]) => values.includes(this._state.get()), + hasTag: (tag: T["tag"]) => !!this.machine.states[this._state.get()]?.tags?.includes(tag), + } + } + + private debug(...args: any[]) { + if (this.machine.debug) console.log(...args) + } + + constructor( + private machine: Machine, + evaluateProps: (callback: (userProps: Partial) => void) => void, + ) { + // create scope + evaluateProps((userProps) => { + const { id, ids, getRootNode } = userProps as any + this.scope = createScope({ id, ids, getRootNode }) + }) + + // create prop + this.prop = (key) => { + let value + evaluateProps((userProps) => { + const props = + machine.props?.({ + props: compact(userProps), + scope: this.scope, + }) ?? userProps + value = props[key] + }) + return value as T["props"][typeof key] + } + + // create context + const _context = machine.context?.({ + prop: this.prop, + bindable, + scope: this.scope, + flush() {}, + getContext: () => this.ctx, + getComputed: () => this.computed, + getRefs: () => this.refs, + getEvent: this.getEvent.bind(this), + }) + + // context function + this.ctx = { + get(key) { + return _context?.[key].get() as T["context"][typeof key] + }, + set(key, value) { + _context?.[key].set(value) + }, + initial(key) { + return _context?.[key].initial as T["context"][typeof key] + }, + hash(key) { + const current = _context?.[key].get() as T["context"][typeof key] + return _context?.[key].hash(current) as string + }, + } + + // create computed + this.computed = (key) => + machine.computed?.[key]({ + context: this.ctx, + event: this.getEvent(), + prop: this.prop, + refs: this.refs, + scope: this.scope, + computed: this.computed, + }) ?? ({} as any) + + // create refs + this.refs = createRefs(machine.refs?.({ prop: this.prop, context: this.ctx })) + + // create state + this._state = bindable(() => ({ + defaultValue: machine.initialState({ prop: this.prop }), + onChange: (nextState, prevState) => { + // compute effects: exit -> transition -> enter + + // exit effects + if (prevState) { + const exitEffects = this.effects.get(prevState) + exitEffects?.() + this.effects.delete(prevState) + } + + // exit actions + if (prevState) { + this.action(machine.states[prevState]?.exit) + } + + // transition actions + this.action(this.transition?.actions) + + // enter effect + const cleanup = this.effect(machine.states[nextState]?.effects) + if (cleanup) this.effects.set(nextState as string, cleanup) + + // root entry actions + if (prevState === INIT_STATE) { + this.action(machine.entry) + const cleanup = this.effect(machine.effects) + if (cleanup) this.effects.set(INIT_STATE, cleanup) + } + + // enter actions + this.action(machine.states[nextState]?.entry) + }, + })) + } + + send = (event: any) => { + if (this.status !== MachineStatus.Started) return + + this.previousEvent = this._event + this._event = event + + this.debug("send", event) + + const currentState = this.state.get() + + const transitions = + // @ts-ignore transition + this.machine.states[currentState].on?.[event.type] ?? + // @ts-ignore transition + this.machine.on?.[event.type] + + const transition = this.choose(transitions) + if (!transition) return + + // save current transition + this.transition = transition + const target = transition.target ?? currentState + + this.debug("transition", transition) + + const changed = target !== currentState + if (changed) { + // state change is high priority + this.state.set(target) + } else if (transition.reenter && !changed) { + // reenter will re-invoke the current state + this.state.invoke(currentState, currentState) + } else { + // call transition actions + this.action(transition.actions) + } + } + + private action = (keys: ActionsOrFn | undefined) => { + const strs = isFunction(keys) ? keys(this.getParams()) : keys + if (!strs) return + const fns = strs.map((s) => { + const fn = this.machine.implementations?.actions?.[s] + if (!fn) { + warn(`[zag-js] No implementation found for action "${JSON.stringify(s)}"`) + } + return fn + }) + for (const fn of fns) { + fn?.(this.getParams()) + } + } + + private guard = (str: T["guard"] | GuardFn) => { + if (isFunction(str)) return str(this.getParams()) + return this.machine.implementations?.guards?.[str](this.getParams()) + } + + private effect = (keys: EffectsOrFn | undefined) => { + const strs = isFunction(keys) ? keys(this.getParams()) : keys + if (!strs) return + const fns = strs.map((s) => { + const fn = this.machine.implementations?.effects?.[s] + if (!fn) { + warn(`[zag-js] No implementation found for effect "${JSON.stringify(s)}"`) + } + return fn + }) + const cleanups: VoidFunction[] = [] + for (const fn of fns) { + const cleanup = fn?.(this.getParams()) + if (cleanup) cleanups.push(cleanup) + } + return () => cleanups.forEach((fn) => fn?.()) + } + + private choose: ChooseFn = (transitions) => { + return toArray(transitions).find((t) => { + let result = !t.guard + if (isString(t.guard)) result = !!this.guard(t.guard) + else if (isFunction(t.guard)) result = t.guard(this.getParams()) + return result + }) + } + + init() { + this.status = MachineStatus.Started + this.debug("initializing...") + this.state.invoke(this.state.initial, INIT_STATE) + this.machine.watch?.(this.getParams()) + } + + destroy() { + this.effects.forEach((fn) => fn?.()) + this.effects.clear() + this.transition = null + this.action(this.machine.exit) + + this.status = MachineStatus.Stopped + this.debug("unmounting...") + } + + getParams(): Params { + return { + state: this.getState(), + context: this.ctx, + event: this.getEvent(), + prop: this.prop, + send: this.send, + action: this.action, + guard: this.guard, + track, + refs: this.refs, + computed: this.computed, + flush, + scope: this.scope, + choose: this.choose, + } + } +} + +const flush = (fn: VoidFunction) => { + Alpine.nextTick(() => { + fn() + }) +} diff --git a/examples/alpine-ts/src/lib/normalize-props.ts b/examples/alpine-ts/src/lib/normalize-props.ts new file mode 100644 index 0000000000..df1bcb593f --- /dev/null +++ b/examples/alpine-ts/src/lib/normalize-props.ts @@ -0,0 +1,26 @@ +import { createNormalizer } from "@zag-js/types" + +const propMap: Record = { + onFocus: "onFocusin", + onBlur: "onFocusout", + onChange: "onInput", + onDoubleClick: "onDblclick", + htmlFor: "for", + className: "class", + defaultValue: "value", + defaultChecked: "checked", +} + +export const normalizeProps = createNormalizer((props) => { + return Object.entries(props).reduce>((acc, [key, value]) => { + if (key in propMap) { + key = propMap[key] + } + if (key.startsWith("on")) { + acc["@" + key.substring(2).toLowerCase()] = value + return acc + } + acc[":" + key.toLowerCase()] = () => value + return acc + }, {}) +}) diff --git a/examples/alpine-ts/src/lib/refs.ts b/examples/alpine-ts/src/lib/refs.ts new file mode 100644 index 0000000000..81057207f3 --- /dev/null +++ b/examples/alpine-ts/src/lib/refs.ts @@ -0,0 +1,11 @@ +export function createRefs(refs: T) { + const ref = { current: refs } + return { + get(key: K): T[K] { + return ref.current[key] + }, + set(key: K, value: T[K]) { + ref.current[key] = value + }, + } +} diff --git a/examples/alpine-ts/src/lib/track.ts b/examples/alpine-ts/src/lib/track.ts new file mode 100644 index 0000000000..b3768ecec6 --- /dev/null +++ b/examples/alpine-ts/src/lib/track.ts @@ -0,0 +1,30 @@ +import Alpine from "alpinejs" +import { isEqual, isFunction } from "@zag-js/utils" + +function access(value: any) { + if (isFunction(value)) return value() + return value +} + +export const track = (deps: any[], effect: VoidFunction) => { + let prevDeps: any[] = [] + let isFirstRun = true + Alpine.effect(() => { + if (isFirstRun) { + prevDeps = deps.map((d) => access(d)) + isFirstRun = false + return + } + let changed = false + for (let i = 0; i < deps.length; i++) { + if (!isEqual(prevDeps[i], access(deps[i]))) { + changed = true + break + } + } + if (changed) { + prevDeps = deps.map((d) => access(d)) + effect() + } + }) +} diff --git a/examples/alpine-ts/src/plugin.ts b/examples/alpine-ts/src/plugin.ts new file mode 100644 index 0000000000..0daa8b5e08 --- /dev/null +++ b/examples/alpine-ts/src/plugin.ts @@ -0,0 +1,89 @@ +import type { Alpine, ElementWithXAttributes } from "alpinejs" +import type { Machine, MachineSchema, Service } from "@zag-js/core" +import type { NormalizeProps, PropTypes } from "@zag-js/types" +import type { ListCollection, CollectionItem, CollectionOptions } from "@zag-js/collection" +import { AlpineMachine, normalizeProps } from "./lib" + +export function createZagPlugin( + name: string, + component: { + machine: Machine + connect: (service: Service, normalizeProps: NormalizeProps) => any + collection?: (options: CollectionOptions) => ListCollection + }, +) { + const underScore = name.replaceAll("-", "_") + const api = `_${underScore}_api` + const bindings = `_${underScore}_bindings` + + return function (Alpine: Alpine) { + Alpine.directive(name, (el, { expression, value }, { evaluateLater, evaluate }) => { + if (!value) { + const service = new AlpineMachine(component.machine, evaluateLater(expression)) + Alpine.bind(el, { + "x-data"() { + return { + [api]: component.connect(service, normalizeProps), + [bindings]: [] as { + el: ElementWithXAttributes + getProps: string + props: any + cleanup: () => void + }[], + init() { + queueMicrotask(() => { + Alpine.effect(() => { + this[api] = component.connect(service, normalizeProps) + + for (const binding of this[bindings]) { + // 'spread props' by cleaning up and re-binding + binding.cleanup() + binding.cleanup = Alpine.bind(binding.el, this[api][binding.getProps](binding.props)) + } + }) + }) + service.init() + }, + destroy() { + for (const binding of this[bindings]) { + binding.cleanup() + } + service.destroy() + }, + } + }, + }) + } else if (value === "collection") { + Alpine.bind(el, { + "x-data"() { + return { + get collection() { + return component.collection?.(evaluate(expression) as any) + }, + } + }, + }) + } else { + ;(Alpine.$data(el) as any)[bindings].push({ + el, + getProps: `get${value + .split("-") + .map((v) => v.at(0)?.toUpperCase() + v.substring(1).toLowerCase()) + .join("")}Props`, + get props() { + return expression ? evaluate(expression) : {} + }, + cleanup: () => {}, + }) + } + }).before("bind") + + Alpine.magic( + name + .split("-") + .map((str, i) => (i === 0 ? str : str.at(0)?.toUpperCase() + str.substring(1).toLowerCase())) + .join(""), + (el) => (Alpine.$data(el) as any)[api], + ) + } +} diff --git a/examples/alpine-ts/src/typescript.svg b/examples/alpine-ts/src/typescript.svg new file mode 100644 index 0000000000..d91c910cc3 --- /dev/null +++ b/examples/alpine-ts/src/typescript.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/examples/alpine-ts/tsconfig.json b/examples/alpine-ts/tsconfig.json new file mode 100644 index 0000000000..6feba115c2 --- /dev/null +++ b/examples/alpine-ts/tsconfig.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "target": "ES2022", + "useDefineForClassFields": true, + "module": "ESNext", + "lib": ["ES2022", "DOM", "DOM.Iterable"], + "types": ["vite/client"], + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "verbatimModuleSyntax": true, + "moduleDetection": "force", + "noEmit": true, + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true, + "noUncheckedSideEffectImports": true + }, + "include": ["src"] +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 58b5341c31..c50165e89d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -132,6 +132,58 @@ importers: specifier: 3.2.4 version: 3.2.4(@types/debug@4.1.12)(@types/node@24.7.0)(jiti@2.6.1)(jsdom@27.0.0(postcss@8.5.6))(lightningcss@1.25.1)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1) + examples/alpine-ts: + dependencies: + '@zag-js/accordion': + specifier: workspace:* + version: link:../../packages/machines/accordion + '@zag-js/angle-slider': + specifier: workspace:* + version: link:../../packages/machines/angle-slider + '@zag-js/avatar': + specifier: workspace:* + version: link:../../packages/machines/avatar + '@zag-js/checkbox': + specifier: workspace:* + version: link:../../packages/machines/checkbox + '@zag-js/collection': + specifier: workspace:* + version: link:../../packages/utilities/collection + '@zag-js/combobox': + specifier: workspace:* + version: link:../../packages/machines/combobox + '@zag-js/core': + specifier: workspace:* + version: link:../../packages/core + '@zag-js/dialog': + specifier: workspace:* + version: link:../../packages/machines/dialog + '@zag-js/popover': + specifier: workspace:* + version: link:../../packages/machines/popover + '@zag-js/shared': + specifier: workspace:* + version: link:../../shared + '@zag-js/types': + specifier: workspace:* + version: link:../../packages/types + '@zag-js/utils': + specifier: workspace:* + version: link:../../packages/utilities/core + alpinejs: + specifier: ^3.15.0 + version: 3.15.0 + devDependencies: + '@types/alpinejs': + specifier: ^3.13.11 + version: 3.13.11 + typescript: + specifier: ~5.8.3 + version: 5.8.3 + vite: + specifier: ^7.1.7 + version: 7.1.7(@types/node@24.5.2)(jiti@2.6.0)(lightningcss@1.25.1)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1) + examples/next-ts: dependencies: '@internationalized/date': @@ -5941,6 +5993,9 @@ packages: '@tybys/wasm-util@0.10.1': resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} + '@types/alpinejs@3.13.11': + resolution: {integrity: sha512-3KhGkDixCPiLdL3Z/ok1GxHwLxEWqQOKJccgaQL01wc0EVM2tCTaqlC3NIedmxAXkVzt/V6VTM8qPgnOHKJ1MA==} + '@types/argparse@1.0.38': resolution: {integrity: sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA==} @@ -6479,6 +6534,9 @@ packages: peerDependencies: vue: 3.5.22 + '@vue/shared@3.1.5': + resolution: {integrity: sha512-oJ4F3TnvpXaQwZJNF3ZK+kLPHKarDmJjJ6jyzVNDKH9md1dptjC7lWR//jrGuLdek/U6iltWxqAnYOu8gCiOvA==} + '@vue/shared@3.4.19': resolution: {integrity: sha512-/KliRRHMF6LoiThEy+4c1Z4KB/gbPrGjWwJR+crg2otgrf/egKzRaCPvJ51S5oetgsgXLfc4Rm5ZgrKHZrtMSw==} @@ -6564,6 +6622,9 @@ packages: engines: {node: '>=4'} hasBin: true + alpinejs@3.15.0: + resolution: {integrity: sha512-lpokA5okCF1BKh10LG8YjqhfpxyHBk4gE7boIgVHltJzYoM7O9nK3M7VlntLEJGsVmu7U/RzUWajmHREGT38Eg==} + ansi-align@3.0.1: resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==} @@ -14649,6 +14710,8 @@ snapshots: tslib: 2.8.1 optional: true + '@types/alpinejs@3.13.11': {} + '@types/argparse@1.0.38': {} '@types/aria-query@5.0.4': {} @@ -15430,6 +15493,8 @@ snapshots: '@vue/shared': 3.5.22 vue: 3.5.22(typescript@5.9.3) + '@vue/shared@3.1.5': {} + '@vue/shared@3.4.19': {} '@vue/shared@3.5.22': {} @@ -15522,6 +15587,10 @@ snapshots: transitivePeerDependencies: - encoding + alpinejs@3.15.0: + dependencies: + '@vue/reactivity': 3.1.5 + ansi-align@3.0.1: dependencies: string-width: 4.2.3