Skip to content

Commit

Permalink
chore(svelte): add multi and range datepickers (#1505)
Browse files Browse the repository at this point in the history
* chore(svelte): add multi and range datepickers

* chore: month values

* chore: month values
  • Loading branch information
anubra266 authored May 20, 2024
1 parent 8ee1635 commit 1a7f0bf
Show file tree
Hide file tree
Showing 3 changed files with 284 additions and 0 deletions.
4 changes: 4 additions & 0 deletions examples/svelte-ts/src/App.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
import Combobox from "./routes/combobox.svelte"
import ContextMenu from "./routes/context-menu.svelte"
import DatePicker from "./routes/date-picker.svelte"
import DatePickerMulti from "./routes/date-picker-multi.svelte"
import DatePickerRange from "./routes/date-picker-range.svelte"
import Dialog from "./routes/dialog.svelte"
import Editable from "./routes/editable.svelte"
import FileUpload from "./routes/file-upload.svelte"
Expand Down Expand Up @@ -57,6 +59,8 @@
{ path: "/combobox", component: Combobox },
{ path: "/context-menu", component: ContextMenu },
{ path: "/date-picker", component: DatePicker },
{ path: "/date-picker-multi", component: DatePickerMulti },
{ path: "/date-picker-range", component: DatePickerRange },
{ path: "/dialog", component: Dialog },
{ path: "/editable", component: Editable },
{ path: "/file-upload", component: FileUpload },
Expand Down
141 changes: 141 additions & 0 deletions examples/svelte-ts/src/routes/date-picker-multi.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
<script lang="ts">
import StateVisualizer from "$lib/components/state-visualizer.svelte"
import Toolbar from "$lib/components/toolbar.svelte"
import { useControls } from "$lib/use-controls.svelte"
import * as datePicker from "@zag-js/date-picker"
import { getYearsRange } from "@zag-js/date-utils"
import { datePickerControls } from "@zag-js/shared"
import { normalizeProps, useMachine } from "@zag-js/svelte"
const controls = useControls(datePickerControls)
const [snapshot, send] = useMachine(
datePicker.machine({
id: "1",
locale: "en",
selectionMode: "multiple",
}),
{
context: controls.context,
},
)
const api = $derived(datePicker.connect(snapshot, send, normalizeProps))
</script>

<main class="date-picker">
<div>
<button>Outside Element</button>
</div>
<p>{`Visible range: ${api.visibleRangeText.formatted}`}</p>

<output class="date-output">
<div>Selected: {api.valueAsString ?? "-"}</div>
<div>Focused: {api.focusedValueAsString}</div>
</output>

<div {...api.controlProps}>
<input {...api.getInputProps()} />
<button {...api.clearTriggerProps}>❌</button>
<button {...api.triggerProps}>🗓</button>
</div>

<div {...api.positionerProps}>
<div {...api.contentProps}>
<div style="margin-bottom: 20px">
<select {...api.monthSelectProps}>
{#each api.getMonths() as month, i (i)}
<option value={month.value}>{month.label}</option>
{/each}
</select>

<select {...api.yearSelectProps}>
{#each getYearsRange({ from: 1_000, to: 4_000 }) as year, i (i)}
<option value={year}>{year}</option>
{/each}
</select>
</div>

<div hidden={api.view !== "day"}>
<div {...api.getViewControlProps({ view: "year" })}>
<button {...api.getPrevTriggerProps()}>Prev</button>
<button {...api.getViewTriggerProps()}>{api.visibleRangeText.start}</button>
<button {...api.getNextTriggerProps()}>Next</button>
</div>

<table {...api.getTableProps({ view: "day" })}>
<thead {...api.getTableHeaderProps({ view: "day" })}>
<tr {...api.getTableRowProps({ view: "day" })}>
{#each api.weekDays as day, i (i)}
<th scope="col" aria-label={day.long}>{day.narrow}</th>
{/each}
</tr>
</thead>
<tbody {...api.getTableBodyProps({ view: "day" })}>
{#each api.weeks as week, i (i)}
<tr {...api.getTableRowProps({ view: "day" })}>
{#each week as value, i (i)}
<td {...api.getDayTableCellProps({ value })}>
<div {...api.getDayTableCellTriggerProps({ value })}>{value.day}</div>
</td>
{/each}
</tr>
{/each}
</tbody>
</table>
</div>

<div style="display:flex; gap:40px;">
<div hidden={api.view !== "month"} style="width:100%;">
<div {...api.getViewControlProps({ view: "month" })}>
<button {...api.getPrevTriggerProps({ view: "month" })}>Prev</button>
<span {...api.getViewTriggerProps({ view: "month" })}>{api.visibleRange.start.year}</span>
<button {...api.getNextTriggerProps({ view: "month" })}>Next</button>
</div>

<table {...api.getTableProps({ view: "month", columns: 4 })}>
<tbody {...api.getTableBodyProps({ view: "month" })}>
{#each api.getMonthsGrid({ columns: 4, format: "short" }) as months, row (row)}
<tr {...api.getTableRowProps({ view: "month" })}>
{#each months as month, index (index)}
<td {...api.getMonthTableCellProps({ ...month, columns: 4 })}>
<div {...api.getMonthTableCellTriggerProps({ ...month, columns: 4 })}>{month.label}</div>
</td>
{/each}
</tr>
{/each}
</tbody>
</table>
</div>

<div hidden={api.view !== "year"} style="width:100%;">
<div {...api.getViewControlProps({ view: "year" })}>
<button {...api.getPrevTriggerProps({ view: "year" })}>Prev</button>
<span>
{api.getDecade().start} - {api.getDecade().end}
</span>
<button {...api.getNextTriggerProps({ view: "year" })}>Next</button>
</div>

<table {...api.getTableProps({ view: "year", columns: 4 })}>
<tbody {...api.getTableBodyProps()}>
{#each api.getYearsGrid({ columns: 4 }) as years, row (row)}
<tr {...api.getTableRowProps({ view: "year" })}>
{#each years as year, index (index)}
<td {...api.getYearTableCellProps({ ...year, columns: 4 })}>
<div {...api.getYearTableCellTriggerProps({ ...year, columns: 4 })}>{year.label}</div>
</td>
{/each}
</tr>
{/each}
</tbody>
</table>
</div>
</div>
</div>
</div>
</main>

<Toolbar viz {controls}>
<StateVisualizer state={snapshot} omit={["weeks"]} />
</Toolbar>
139 changes: 139 additions & 0 deletions examples/svelte-ts/src/routes/date-picker-range.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
<script lang="ts">
import StateVisualizer from "$lib/components/state-visualizer.svelte"
import Toolbar from "$lib/components/toolbar.svelte"
import { useControls } from "$lib/use-controls.svelte"
import * as datePicker from "@zag-js/date-picker"
import { getYearsRange } from "@zag-js/date-utils"
import { datePickerControls } from "@zag-js/shared"
import { normalizeProps, useMachine } from "@zag-js/svelte"
const controls = useControls(datePickerControls)
const [snapshot, send] = useMachine(
datePicker.machine({
id: "1",
name: "date[]",
locale: "en",
numOfMonths: 2,
selectionMode: "range",
}),
{
context: controls.context,
},
)
const api = $derived(datePicker.connect(snapshot, send, normalizeProps))
const offset = $derived(api.getOffset({ months: 1 }))
</script>

<main class="date-picker">
<div>
<button>Outside Element</button>
</div>
<p>{`Visible range: ${api.visibleRangeText.formatted}`}</p>

<output class="date-output">
<div>Selected: {api.valueAsString.join(", ") ?? "-"}</div>
<div>Focused: {api.focusedValueAsString}</div>
</output>

<div {...api.controlProps}>
<input {...api.getInputProps({ index: 0 })} />
<input {...api.getInputProps({ index: 1 })} />
<button {...api.clearTriggerProps}>❌</button>
<button {...api.triggerProps}>🗓</button>
</div>

<div {...api.positionerProps}>
<div {...api.contentProps}>
<div style="margin-bottom: 20px">
<select {...api.monthSelectProps}>
{#each api.getMonths() as month, i (i)}
<option value={month.value}>{month.label}</option>
{/each}
</select>

<select {...api.yearSelectProps}>
{#each getYearsRange({ from: 1_000, to: 4_000 }) as year, i (i)}
<option value={year}>{year}</option>
{/each}
</select>
</div>

<div>
<div {...api.getViewControlProps({ view: "year" })}>
<button {...api.getPrevTriggerProps()}>Prev</button>

<span>
{api.visibleRangeText.start} - {api.visibleRangeText.end}
</span>

<button {...api.getNextTriggerProps()}>Next</button>
</div>

<div style="display: flex; gap: 24px;">
<table {...api.getTableProps({ id: "0" })}>
<thead {...api.getTableHeaderProps()}>
<tr {...api.getTableRowProps()}>
{#each api.weekDays as day, i (i)}
<th scope="col" aria-label={day.long}>
{day.narrow}
</th>
{/each}
</tr>
</thead>
<tbody {...api.getTableBodyProps()}>
{#each api.weeks as week, i (i)}
<tr {...api.getTableRowProps()}>
{#each week as value, i (i)}
<td {...api.getDayTableCellProps({ value })}>
<div {...api.getDayTableCellTriggerProps({ value })}>{value.day}</div>
</td>
{/each}
</tr>
{/each}
</tbody>
</table>

<table {...api.getTableProps({ id: "1" })}>
<thead {...api.getTableHeaderProps()}>
<tr {...api.getTableRowProps()}>
{#each api.weekDays as day, i (i)}
<th scope="col" aria-label={day.long}>
{day.narrow}
</th>
{/each}
</tr>
</thead>
<tbody {...api.getTableBodyProps()}>
{#each offset.weeks as week, i (i)}
<tr {...api.getTableRowProps()}>
{#each week as value, i (i)}
<td {...api.getDayTableCellProps({ value, visibleRange: offset.visibleRange })}>
<div {...api.getDayTableCellTriggerProps({ value, visibleRange: offset.visibleRange })}>
{value.day}
</div>
</td>
{/each}
</tr>
{/each}
</tbody>
</table>

<div style="min-width:80px; display: flex; flex-direction: column; gap: 4px;">
<b>Presets</b>
<button {...api.getPresetTriggerProps({ value: "last3Days" })}>Last 3 Days</button>
<button {...api.getPresetTriggerProps({ value: "last7Days" })}>Last 7 Days</button>
<button {...api.getPresetTriggerProps({ value: "last14Days" })}>Last 14 Days</button>
<button {...api.getPresetTriggerProps({ value: "last30Days" })}>Last 30 Days</button>
<button {...api.getPresetTriggerProps({ value: "last90Days" })}>Last 90 Days</button>
</div>
</div>
</div>
</div>
</div>
</main>

<Toolbar viz {controls}>
<StateVisualizer state={snapshot} omit={["weeks"]} />
</Toolbar>

0 comments on commit 1a7f0bf

Please sign in to comment.