@grimoire-intel/yetzirah-svelte
v1.0.0
Published
Svelte wrappers for Yetzirah Web Components
Maintainers
Readme
@grimoire-intel/yetzirah-svelte
Svelte wrappers for Yetzirah Web Components.
Installation
pnpm add @grimoire-intel/yetzirah-svelte @grimoire-intel/yetzirahUsage
Svelte has excellent Web Component support out of the box. These wrappers provide:
- TypeScript definitions
- Svelte-idiomatic component APIs
- Reactive property bindings
Direct Web Component Usage
You can use Yetzirah Web Components directly in Svelte:
<script>
import '@grimoire-intel/yetzirah/button'
</script>
<ytz-button on:click={() => console.log('clicked')}>
Click me
</ytz-button>Using Svelte Wrappers
Or use the Svelte wrappers for better type safety:
<script>
import { Button } from '@grimoire-intel/yetzirah-svelte'
</script>
<Button on:click={() => console.log('clicked')}>
Click me
</Button>Why Thin Wrappers?
Svelte's compiler has first-class Web Component support:
- Automatic event forwarding
- Two-way data binding with custom elements
- No runtime overhead
Our wrappers are intentionally minimal, primarily providing TypeScript definitions and following Svelte conventions.
Available Components (Tier 1)
All Tier 1 core components are available with Svelte-idiomatic bindings:
| Component | Import | Binding Support |
|-----------|--------|-----------------|
| Button | Button | - |
| Dialog | Dialog | bind:open |
| Drawer | Drawer | bind:open |
| Tabs | Tabs, TabList, Tab, TabPanel | - |
| Menu | Menu, MenuItem, MenuTrigger | - |
| Accordion | Accordion, AccordionItem | - |
| Disclosure | Disclosure | bind:open |
| Tooltip | Tooltip | - |
| Popover | Popover | bind:open |
| Autocomplete | Autocomplete, AutocompleteOption | bind:value |
| Listbox | Listbox, ListboxOption | bind:value |
| Select | Select, SelectOption | bind:value |
Dialog
<script>
import { Dialog, Button } from '@grimoire-intel/yetzirah-svelte'
let isOpen = false
</script>
<Button on:click={() => isOpen = true}>Open Dialog</Button>
<Dialog bind:open={isOpen}>
<div class="pa4 bg-white br3">
<h2>Dialog Title</h2>
<p>Dialog content goes here.</p>
<Button on:click={() => isOpen = false}>Close</Button>
</div>
</Dialog>| Prop | Type | Default | Description |
|------|------|---------|-------------|
| open | boolean | false | Two-way bindable open state |
| isStatic | boolean | false | Prevent backdrop dismiss |
Select
<script>
import { Select, SelectOption } from '@grimoire-intel/yetzirah-svelte'
let selected = ''
</script>
<Select bind:value={selected} placeholder="Choose an option...">
<SelectOption value="1">Option 1</SelectOption>
<SelectOption value="2">Option 2</SelectOption>
<SelectOption value="3">Option 3</SelectOption>
</Select>| Prop | Type | Default | Description |
|------|------|---------|-------------|
| value | string \| string[] | '' | Two-way bindable value |
| multiple | boolean | false | Enable multi-select |
| disabled | boolean | false | Disable the select |
| placeholder | string | - | Placeholder text |
Tabs
<script>
import { Tabs, TabList, Tab, TabPanel } from '@grimoire-intel/yetzirah-svelte'
</script>
<Tabs>
<TabList>
<Tab>Tab 1</Tab>
<Tab>Tab 2</Tab>
<Tab>Tab 3</Tab>
</TabList>
<TabPanel>Content for Tab 1</TabPanel>
<TabPanel>Content for Tab 2</TabPanel>
<TabPanel>Content for Tab 3</TabPanel>
</Tabs>Menu
<script>
import { Menu, MenuTrigger, MenuItem, Button } from '@grimoire-intel/yetzirah-svelte'
</script>
<Menu>
<MenuTrigger>
<Button>Open Menu</Button>
</MenuTrigger>
<MenuItem on:click={handleEdit}>Edit</MenuItem>
<MenuItem on:click={handleDelete}>Delete</MenuItem>
</Menu>Autocomplete
<script>
import { Autocomplete, AutocompleteOption } from '@grimoire-intel/yetzirah-svelte'
let value = ''
const options = ['Apple', 'Banana', 'Cherry', 'Date']
</script>
<Autocomplete bind:value placeholder="Search fruits...">
{#each options as option}
<AutocompleteOption value={option}>{option}</AutocompleteOption>
{/each}
</Autocomplete>Available Components (Tier 2)
The following Tier 2 components are available with Svelte-idiomatic bindings:
| Component | Import | Binding Support |
|-----------|--------|-----------------|
| Toggle | Toggle | bind:checked |
| Chip | Chip | - |
| IconButton | IconButton | - |
| Slider | Slider | bind:value |
| DataGrid | DataGrid, DataGridColumn | - |
| ThemeToggle | ThemeToggle | - |
Component API
Toggle
<script>
import { Toggle } from '@grimoire-intel/yetzirah-svelte'
let enabled = false
</script>
<Toggle bind:checked={enabled} disabled={false} on:change={(e) => console.log(e)} />| Prop | Type | Default | Description |
|------|------|---------|-------------|
| checked | boolean | false | Two-way bindable checked state |
| disabled | boolean | false | Disables the toggle |
| Event | Detail | Description |
|-------|--------|-------------|
| change | Event | Fires when checked state changes |
Chip
<script>
import { Chip } from '@grimoire-intel/yetzirah-svelte'
</script>
<Chip deletable on:delete={() => console.log('deleted')}>Tag Name</Chip>| Prop | Type | Default | Description |
|------|------|---------|-------------|
| deletable | boolean | false | Shows delete button |
| disabled | boolean | false | Disables the chip |
| Event | Detail | Description |
|-------|--------|-------------|
| delete | Event | Delete button clicked |
IconButton
<script>
import { IconButton } from '@grimoire-intel/yetzirah-svelte'
</script>
<IconButton aria-label="Close" tooltip="Close dialog" on:click={() => console.log('clicked')}>
<svg><!-- icon --></svg>
</IconButton>| Prop | Type | Default | Description |
|------|------|---------|-------------|
| aria-label | string | required | Accessible label |
| tooltip | string | - | Tooltip text |
| disabled | boolean | false | Disables the button |
Slider
<script>
import { Slider } from '@grimoire-intel/yetzirah-svelte'
let volume = 50
</script>
<Slider bind:value={volume} min={0} max={100} step={1} />| Prop | Type | Default | Description |
|------|------|---------|-------------|
| value | number | 0 | Two-way bindable value |
| min | number | 0 | Minimum value |
| max | number | 100 | Maximum value |
| step | number | 1 | Step increment |
| disabled | boolean | false | Disables the slider |
| Event | Detail | Description |
|-------|--------|-------------|
| input | Event | Live value change during drag |
| change | Event | Committed value change on release |
DataGrid
<script>
import { DataGrid, DataGridColumn } from '@grimoire-intel/yetzirah-svelte'
const data = [
{ id: 1, name: 'Alice', email: '[email protected]' },
{ id: 2, name: 'Bob', email: '[email protected]' }
]
</script>
<DataGrid {data} rowHeight={40} on:sort={(e) => console.log(e.detail)} on:rowselect={(e) => console.log(e.detail)}>
<DataGridColumn field="id" header="ID" width={80} />
<DataGridColumn field="name" header="Name" sortable />
<DataGridColumn field="email" header="Email" />
</DataGrid>| Prop | Type | Default | Description |
|------|------|---------|-------------|
| data | any[] | [] | Row data array |
| columns | Column[] | [] | Column definitions (alternative to children) |
| rowHeight | number | 40 | Row height in pixels |
| Event | Detail | Description |
|-------|--------|-------------|
| sort | { column, direction } | Sort requested |
| rowselect | { row, index } | Row selected |
| rowactivate | { row, index } | Row double-clicked |
ThemeToggle
<script>
import { ThemeToggle } from '@grimoire-intel/yetzirah-svelte'
</script>
<ThemeToggle storageKey="my-app-theme" on:themechange={(e) => console.log(e.detail)} />| Prop | Type | Default | Description |
|------|------|---------|-------------|
| storageKey | string | 'theme' | localStorage key (maps to storage-key) |
| noPersist | boolean | false | Disable persistence (maps to no-persist) |
| Event | Detail | Description |
|-------|--------|-------------|
| themechange | { theme, isDark } | Theme changed |
Development
# Build the package
pnpm build
# Watch for changes
pnpm devTesting
# Run all tests
pnpm test
# Run tests in watch mode
pnpm test:watch
# Run with coverage
pnpm test:coverageTests use Vitest with @testing-library/svelte and happy-dom for DOM simulation.
How It Works
Svelte has excellent native Web Component support. These wrappers primarily provide:
- TypeScript definitions: Full type safety for props and events
bind:support: Two-way binding foropen,checked,value- Event forwarding: Component events forwarded via
on:*syntax
See @grimoire-intel/yetzirah for full component documentation.
License
MIT
