Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: simplify vanilla samples #1516

Merged
merged 3 commits into from
May 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions examples/vanilla-ts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@
"@zag-js/utils": "workspace:*",
"form-serialize": "0.7.2",
"match-sorter": "6.3.4",
"nanoid": "^5.0.7",
"typescript": "^5.4.5",
"vite": "^5.2.11"
}
Expand Down
43 changes: 11 additions & 32 deletions examples/vanilla-ts/src/accordion.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,22 @@
import * as accordion from "@zag-js/accordion"
import { normalizeProps } from "./normalize-props"
import { spreadProps } from "./spread-props"
import { Component } from "./component"

export class Accordion {
rootEl: HTMLElement
service: ReturnType<typeof accordion.machine>
api: accordion.Api<any>

constructor(rootEl: HTMLElement | null, context: accordion.Context) {
if (!rootEl) throw new Error("Root element not found")
this.rootEl = rootEl

this.service = accordion.machine(context)
this.api = accordion.connect(this.service.state, this.service.send, normalizeProps)
export class Accordion extends Component<accordion.Context, accordion.Api> {
initService(context: accordion.Context) {
return accordion.machine(context)
}

init = () => {
const { service } = this
this.render()
this.service.subscribe(() => {
this.api = accordion.connect(service.state, service.send, normalizeProps)
this.render()
})
this.service.start()
initApi() {
return accordion.connect(this.service.state, this.service.send, normalizeProps)
}

destroy = () => {
this.service.stop()
render = () => {
spreadProps(this.rootEl, this.api.rootProps)
this.items.forEach((itemEl) => {
this.renderItem(itemEl)
})
}

private get items() {
Expand All @@ -36,23 +26,12 @@ export class Accordion {
private renderItem = (itemEl: HTMLElement) => {
const value = itemEl.dataset.value
if (!value) throw new Error("Expected value to be defined")

const itemTriggerEl = itemEl.querySelector<HTMLButtonElement>(".accordion-trigger")
const itemContentEl = itemEl.querySelector<HTMLElement>(".accordion-content")

if (!itemTriggerEl) throw new Error("Expected triggerEl to be defined")
if (!itemContentEl) throw new Error("Expected contentEl to be defined")

spreadProps(itemEl, this.api.getItemProps({ value }))
spreadProps(itemTriggerEl, this.api.getItemTriggerProps({ value }))
spreadProps(itemContentEl, this.api.getItemContentProps({ value }))
}

render = () => {
spreadProps(this.rootEl, this.api.rootProps)

this.items.forEach((itemEl) => {
this.renderItem(itemEl)
})
}
}
32 changes: 6 additions & 26 deletions examples/vanilla-ts/src/avatar.ts
Original file line number Diff line number Diff line change
@@ -1,42 +1,22 @@
import * as avatar from "@zag-js/avatar"
import { normalizeProps } from "./normalize-props"
import { spreadProps } from "./spread-props"
import { Component } from "./component"

export class Avatar {
rootEl: HTMLElement
service: ReturnType<typeof avatar.machine>
api: avatar.Api<any>

constructor(rootEl: HTMLElement | null, context: avatar.Context) {
if (!rootEl) throw new Error("Root element not found")
this.rootEl = rootEl

this.service = avatar.machine(context)
this.api = avatar.connect(this.service.state, this.service.send, normalizeProps)
export class Avatar extends Component<avatar.Context, avatar.Api> {
initService(context: avatar.Context) {
return avatar.machine(context)
}

init = () => {
const { service } = this
this.render()
this.service.subscribe(() => {
this.api = avatar.connect(service.state, service.send, normalizeProps)
this.render()
})

this.service.start()
}

destroy = () => {
this.service.stop()
initApi() {
return avatar.connect(this.service.state, this.service.send, normalizeProps)
}

render = () => {
const rootEl = this.rootEl
spreadProps(this.rootEl, this.api.rootProps)

const imageEl = rootEl.querySelector<HTMLElement>(".avatar-image")
if (imageEl) spreadProps(imageEl, this.api.imageProps)

const fallbackEl = rootEl.querySelector<HTMLElement>(".avatar-fallback")
if (fallbackEl) spreadProps(fallbackEl, this.api.fallbackProps)
}
Expand Down
33 changes: 6 additions & 27 deletions examples/vanilla-ts/src/checkbox.ts
Original file line number Diff line number Diff line change
@@ -1,45 +1,24 @@
import * as checkbox from "@zag-js/checkbox"
import { normalizeProps } from "./normalize-props"
import { spreadProps } from "./spread-props"
import { Component } from "./component"

export class Checkbox {
rootEl: HTMLElement
service: ReturnType<typeof checkbox.machine>
api: checkbox.Api<any>

constructor(rootEl: HTMLElement | null, context: checkbox.Context) {
if (!rootEl) throw new Error("Root element not found")
this.rootEl = rootEl

this.service = checkbox.machine(context)
this.api = checkbox.connect(this.service.state, this.service.send, normalizeProps)
}

init = () => {
const { service } = this
this.render()
this.service.subscribe(() => {
this.api = checkbox.connect(service.state, service.send, normalizeProps)
this.render()
})

this.service.start()
export class Checkbox extends Component<checkbox.Context, checkbox.Api> {
initService(context: checkbox.Context) {
return checkbox.machine(context)
}

destroy = () => {
this.service.stop()
initApi() {
return checkbox.connect(this.service.state, this.service.send, normalizeProps)
}

render = () => {
const rootEl = this.rootEl
spreadProps(this.rootEl, this.api.rootProps)

const controlEl = rootEl.querySelector<HTMLElement>(".checkbox-control")
if (controlEl) spreadProps(controlEl, this.api.controlProps)

const labelEl = rootEl.querySelector<HTMLElement>(".checkbox-label")
if (labelEl) spreadProps(labelEl, this.api.labelProps)

const inputEl = rootEl.querySelector<HTMLInputElement>(".checkbox-input")
if (inputEl) spreadProps(inputEl, this.api.hiddenInputProps)
}
Expand Down
42 changes: 42 additions & 0 deletions examples/vanilla-ts/src/component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { Machine } from "@zag-js/core"

interface ComponentInterface<Api> {
rootEl: HTMLElement
service: ReturnType<any>
api: Api

init(): void
destroy(): void
render(): void
}

export abstract class Component<Context, Api> implements ComponentInterface<Api> {
rootEl: HTMLElement
service: ReturnType<any>
api: Api

constructor(rootEl: HTMLElement | null, context: Context) {
if (!rootEl) throw new Error("Root element not found")
this.rootEl = rootEl
this.service = this.initService(context)
this.api = this.initApi()
}

abstract initService(context: Context): Machine<any, any, any>
abstract initApi(): Api

init = () => {
this.render()
this.service.subscribe(() => {
this.api = this.initApi()
this.render()
})
this.service.start()
}

destroy = () => {
this.service.stop()
}

abstract render(): void
}
33 changes: 6 additions & 27 deletions examples/vanilla-ts/src/popover.ts
Original file line number Diff line number Diff line change
@@ -1,44 +1,23 @@
import * as popover from "@zag-js/popover"
import { normalizeProps } from "./normalize-props"
import { spreadProps } from "./spread-props"
import { Component } from "./component"

export class Popover {
rootEl: HTMLElement
service: ReturnType<typeof popover.machine>
api: popover.Api<any>

constructor(rootEl: HTMLElement | null, context: popover.Context) {
if (!rootEl) throw new Error("Root element not found")
this.rootEl = rootEl

this.service = popover.machine(context)
this.api = popover.connect(this.service.state, this.service.send, normalizeProps)
}

init = () => {
const { service } = this
this.render()
this.service.subscribe(() => {
this.api = popover.connect(service.state, service.send, normalizeProps)
this.render()
})

this.service.start()
export class Popover extends Component<popover.Context, popover.Api> {
initService(context: popover.Context) {
return popover.machine(context)
}

destroy = () => {
this.service.stop()
initApi() {
return popover.connect(this.service.state, this.service.send, normalizeProps)
}

render = () => {
const rootEl = this.rootEl

const triggerEl = rootEl.querySelector<HTMLElement>(".popover-trigger")
if (triggerEl) spreadProps(triggerEl, this.api.triggerProps)

const contentEl = rootEl.querySelector<HTMLElement>(".popover-content")
if (contentEl) spreadProps(contentEl, this.api.contentProps)

const positionerEl = rootEl.querySelector<HTMLElement>(".popover-positioner")
if (positionerEl) spreadProps(positionerEl, this.api.positionerProps)
}
Expand Down
Loading
Loading