@grimoire-intel/yetzirah-alpine
v1.0.0
Published
Alpine.js plugin for Yetzirah Web Components
Maintainers
Readme
@grimoire-intel/yetzirah-alpine
Alpine.js plugin for Yetzirah Web Components.
Installation
npm install @grimoire-intel/yetzirah-alpine
# or
pnpm add @grimoire-intel/yetzirah-alpine
# or
yarn add @grimoire-intel/yetzirah-alpineRequirements
- Alpine.js 3.0 or higher
Usage
Register the plugin with Alpine before calling Alpine.start():
import Alpine from 'alpinejs'
import { yetzirahPlugin } from '@grimoire-intel/yetzirah-alpine'
Alpine.plugin(yetzirahPlugin)
Alpine.start()Basic Example
<div x-data="{ dialogOpen: false, volume: 50 }">
<ytz-button @click="dialogOpen = true">Open Settings</ytz-button>
<ytz-dialog x-ytz-dialog="dialogOpen">
<h2>Settings</h2>
<ytz-slider x-ytz-slider="volume"></ytz-slider>
<p>Volume: <span x-text="volume"></span></p>
<ytz-button @click="dialogOpen = false">Close</ytz-button>
</ytz-dialog>
</div>Using $ytz Magic
The plugin provides a $ytz magic for programmatic component control:
<div x-data>
<ytz-button @click="$ytz.open('#my-dialog')">Open Dialog</ytz-button>
<ytz-button @click="$ytz.toggleTheme()">Toggle Theme</ytz-button>
<ytz-dialog id="my-dialog">
<p>Dialog content</p>
<ytz-button @click="$ytz.close('#my-dialog')">Close</ytz-button>
</ytz-dialog>
</div>Directives Reference
The plugin registers directives for two-way binding with Yetzirah components.
Component Directives
| Directive | Component | Synced Attribute | Events |
|-----------|-----------|------------------|--------|
| x-ytz-dialog | <ytz-dialog> | open | close |
| x-ytz-drawer | <ytz-drawer> | open | close |
| x-ytz-tabs | <ytz-tabs> | default-tab | change |
| x-ytz-toggle | <ytz-toggle> | checked | change |
| x-ytz-slider | <ytz-slider> | value | change |
| x-ytz-select | <ytz-select> | value | change |
| x-ytz-disclosure | <ytz-disclosure> | open | toggle |
| x-ytz-accordion-item | <ytz-accordion-item> | open | toggle |
| x-ytz-popover | <ytz-popover> | open | toggle |
| x-ytz-autocomplete | <ytz-autocomplete> | value | input, select |
| x-ytz-listbox | <ytz-listbox> | value | change |
| x-ytz-menu | <ytz-menu> | open | close |
| x-ytz-progress | <ytz-progress> | value | - |
| x-ytz-snackbar | <ytz-snackbar> | open | close |
| x-ytz-chip | <ytz-chip> | - | remove |
| x-ytz-badge | <ytz-badge> | count | - |
| x-ytz-init | Any | - | ytz:ready |
Directive Modifiers
| Modifier | Description | Supported Directives |
|----------|-------------|---------------------|
| .once | Only sync initial value, no reactive updates | All directives |
| .lazy | Debounce updates (150ms) | x-ytz-slider, x-ytz-autocomplete |
| .number | Coerce value to number | x-ytz-slider, x-ytz-progress, x-ytz-badge |
Examples
Dialog
<div x-data="{ isOpen: false }">
<ytz-button @click="isOpen = true">Open</ytz-button>
<ytz-dialog x-ytz-dialog="isOpen">
<p>Dialog content</p>
</ytz-dialog>
</div>Toggle
<div x-data="{ enabled: false }">
<ytz-toggle x-ytz-toggle="enabled"></ytz-toggle>
<span x-text="enabled ? 'On' : 'Off'"></span>
</div>Slider with Modifiers
<div x-data="{ volume: 50 }">
<!-- Debounce updates and ensure numeric value -->
<ytz-slider x-ytz-slider.lazy.number="volume"></ytz-slider>
<span x-text="volume"></span>
</div>Tabs
<div x-data="{ activeTab: 'tab-1' }">
<ytz-tabs x-ytz-tabs="activeTab">
<ytz-tab-list>
<ytz-tab value="tab-1">Tab 1</ytz-tab>
<ytz-tab value="tab-2">Tab 2</ytz-tab>
</ytz-tab-list>
<ytz-tab-panel value="tab-1">Content 1</ytz-tab-panel>
<ytz-tab-panel value="tab-2">Content 2</ytz-tab-panel>
</ytz-tabs>
</div>Init Callback
<div x-data="{ ready: false }">
<ytz-slider x-ytz-init="ready = true"></ytz-slider>
<span x-show="ready">Slider is ready!</span>
</div>x-ytz:model Directive
The x-ytz:model directive provides unified two-way binding that auto-detects the component type:
<div x-data="{ volume: 50, enabled: false, query: '' }">
<!-- Auto-detects ytz-slider, binds to value -->
<ytz-slider x-ytz:model="volume"></ytz-slider>
<!-- Auto-detects ytz-toggle, binds to checked -->
<ytz-toggle x-ytz:model="enabled"></ytz-toggle>
<!-- Auto-detects ytz-autocomplete, binds to value -->
<ytz-autocomplete x-ytz:model="query"></ytz-autocomplete>
</div>Supported Components
| Component | Bound Attribute | Events Listened |
|-----------|-----------------|-----------------|
| ytz-slider | value | change |
| ytz-select | value | change |
| ytz-toggle | checked | change |
| ytz-autocomplete | value | input, select |
| ytz-listbox | value | change |
| ytz-dialog | open | close |
| ytz-drawer | open | close |
| ytz-disclosure | open | toggle |
| ytz-popover | open | toggle |
| ytz-accordion-item | open | toggle |
| ytz-tabs | default-tab | change |
| ytz-progress | value | - |
| ytz-badge | count | - |
| ytz-snackbar | open | close |
| ytz-menu | open | close |
Modifiers
| Modifier | Description |
|----------|-------------|
| .lazy | Debounce updates (150ms) |
| .number | Coerce value to number |
| .trim | Trim whitespace from string values |
<!-- Debounced slider updates -->
<ytz-slider x-ytz:model.lazy="volume"></ytz-slider>
<!-- Trimmed autocomplete input -->
<ytz-autocomplete x-ytz:model.trim="query"></ytz-autocomplete>
<!-- Multiple modifiers -->
<ytz-slider x-ytz:model.lazy.number="volume"></ytz-slider>$ytz Magic Methods
The $ytz magic provides utilities for programmatic component control.
Methods
| Method | Description |
|--------|-------------|
| open(target) | Open a dialog, drawer, menu, or popover |
| close(target) | Close a component |
| toggle(target) | Toggle component open state |
| show(target, message?) | Show a snackbar, optionally with a message |
| snackbar(message, options?) | Create and show a programmatic snackbar |
| openDialog(target) | Open a dialog (alias) |
| closeDialog(target) | Close a dialog (alias) |
| openDrawer(target) | Open a drawer (alias) |
| closeDrawer(target) | Close a drawer (alias) |
| getTheme() | Get current theme ('light' or 'dark') |
| setTheme(theme) | Set theme to 'light' or 'dark' |
| toggleTheme() | Toggle between light and dark theme |
Usage Examples
<div x-data>
<!-- Open/close by selector -->
<ytz-button @click="$ytz.open('#my-dialog')">Open</ytz-button>
<ytz-button @click="$ytz.close('#my-dialog')">Close</ytz-button>
<ytz-button @click="$ytz.toggle('#my-drawer')">Toggle Drawer</ytz-button>
<!-- Theme control -->
<ytz-button @click="$ytz.toggleTheme()">Toggle Theme</ytz-button>
<span x-text="$ytz.getTheme()"></span>
<!-- Programmatic snackbar -->
<ytz-button @click="$ytz.snackbar('Item saved!', { duration: 3000 })">
Save
</ytz-button>
<!-- Show existing snackbar with message -->
<ytz-button @click="$ytz.show('#notification', 'New message!')">
Notify
</ytz-button>
<ytz-dialog id="my-dialog">...</ytz-dialog>
<ytz-drawer id="my-drawer">...</ytz-drawer>
<ytz-snackbar id="notification"></ytz-snackbar>
</div>Snackbar Options
interface SnackbarOptions {
duration?: number // Auto-dismiss time in ms
position?: 'top' | 'bottom' | 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'
}Configuration
Custom Prefix
Use a custom directive prefix instead of the default ytz:
Alpine.plugin((Alpine) => yetzirahPlugin(Alpine, { prefix: 'custom' }))This registers directives as x-custom-dialog, x-custom:model, etc.
Development
# Install dependencies
pnpm install
# Build the package
pnpm build
# Watch mode for development
pnpm devTesting
# Run all tests
pnpm test
# Run tests in watch mode
pnpm test:watch
# Run with coverage
pnpm test:coverageTests use Vitest with happy-dom for DOM simulation.
TypeScript
This package includes full TypeScript definitions:
import type { YtzMagic, SnackbarOptions, YetzirahAlpineOptions } from '@grimoire-intel/yetzirah-alpine'How It Works
The plugin bridges Alpine's reactive system with Yetzirah's web components:
effect(): Syncs Alpine state to component attributes- Event listeners: Sync component events back to Alpine state
cleanup(): Removes listeners when components are destroyed
See @grimoire-intel/yetzirah for full component documentation.
License
MIT
