508 lines
21 KiB
HTML
508 lines
21 KiB
HTML
<html>
|
|
<head>
|
|
<meta charset="utf-8"/>
|
|
<style>
|
|
.hidden { display: none; }
|
|
[x-cloak] { display: none; }
|
|
.opacity-0 { opacity: 0; }
|
|
.opacity-100 { opacity: 1; }
|
|
.transition-slow { transition-duration: 300ms; }
|
|
.transition-medium { transition-duration: 200ms; }
|
|
.transition-faster { transition-duration: 100ms; }
|
|
.scale-90 { transform: scale(0.9); }
|
|
.scale-100 { transform: scale(1); }
|
|
.ease-in { transition-timing-function: cubic-bezier(0.4, 0, 1, 1); }
|
|
.ease-out { transition-timing-function: cubic-bezier(0, 0, 0.2, 1); }
|
|
|
|
/** Thanks Animate.css */
|
|
.animation {animation-duration: 1000ms; --animate-duration: 1000ms; }
|
|
@keyframes jackInTheBox {
|
|
from { opacity: 0; transform: scale(0.1) rotate(30deg); transform-origin: center bottom; }
|
|
50% { transform: rotate(-10deg); }
|
|
70% { transform: rotate(3deg); }
|
|
to { opacity: 1; transform: scale(1); }
|
|
}
|
|
@keyframes hinge {
|
|
0% {animation-timing-function: ease-in-out;}
|
|
20%, 60% { transform: rotate3d(0, 0, 1, 80deg); animation-timing-function: ease-in-out; }
|
|
40%, 80% { transform: rotate3d(0, 0, 1, 60deg); animation-timing-function: ease-in-out; opacity: 1; }
|
|
to { transform: translate3d(0, 700px, 0); opacity: 0; }
|
|
}
|
|
.jackInTheBox {animation-name: jackInTheBox;}
|
|
.hinge {
|
|
animation-duration: calc(var(--animate-duration) * 2);
|
|
animation-name: hinge;
|
|
transform-origin: top left;
|
|
}
|
|
</style>
|
|
|
|
<script src="/dist/alpine.js" defer></script>
|
|
<!-- <script src="https://cdn.jsdelivr.net/gh/alpinejs/alpine@v2.x.x/dist/alpine.min.js" defer></script> -->
|
|
</head>
|
|
<body>
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>Feature</th>
|
|
<th>Demo</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td>Broken Components</td>
|
|
<td>
|
|
<div x-data="some.bad.expression()">I'm a broken component</div>
|
|
<button x-data x-on:click="something()">I break on click</button>
|
|
<div x-data x-spread="not.good">Broken x-spread</div>
|
|
</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td>Simple x-if</td>
|
|
<td>
|
|
<div x-data="{ show: false }">
|
|
<template x-if="show">
|
|
<span>hey</span>
|
|
</template>
|
|
|
|
<button @click="show = ! show">Show</button>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td>Dropdown</td>
|
|
<td>
|
|
<div x-data="{ open: false }">
|
|
<button x-on:click="open= true">Open Dropdown</button>
|
|
<ul
|
|
x-bind:class="{ 'hidden': ! open }"
|
|
x-on:click.away="open= false"
|
|
x-cloak>
|
|
Dropdown Body
|
|
</ul>6
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td>Tabs</td>
|
|
<td>
|
|
<div x-data="{ currentTab: 'tab1' }">
|
|
<button x-bind:class="{ 'active': currentTab ===
|
|
'tab1' }" x-on:click="currentTab= 'tab1'">Foo</button>
|
|
<button x-bind:class="{ 'active': currentTab ===
|
|
'tab2' }" x-on:click="currentTab= 'tab2'">Bar</button>
|
|
<div x-bind:class="{ 'hidden': currentTab !== 'tab1'
|
|
}">Tab Foo</div>
|
|
<div class="hidden" x-bind:class="{ 'hidden':
|
|
currentTab !== 'tab2' }">Tab Bar</div>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td>Data Binding</td>
|
|
<td>
|
|
<div x-data="{ text: 'foo', checkbox: ['foo'], radio:
|
|
'foo', select: 'foo', 'multiselect': ['foo'] }">
|
|
Text:
|
|
<span x-text="JSON.stringify(text)"></span>
|
|
<input type="text" x-model="text">
|
|
Checkbox:
|
|
<span x-text="JSON.stringify(checkbox)"></span>
|
|
<input type="checkbox" x-model="checkbox"
|
|
value="foo">
|
|
<input type="checkbox" x-model="checkbox"
|
|
:value="0">
|
|
<input type="checkbox" x-model="checkbox"
|
|
value="bar">
|
|
Radio:
|
|
<span x-text="JSON.stringify(radio)"></span>
|
|
<input type="radio" x-model="radio" value="foo">
|
|
<input type="radio" x-model="radio" value="bar">
|
|
Select:
|
|
<span x-text="JSON.stringify(select)"></span>
|
|
<select x-model="select">
|
|
<option>foo</option>
|
|
<option>bar</option>
|
|
</select>
|
|
Multiple Select:
|
|
<span x-text="JSON.stringify(multiselect)"></span>
|
|
<select x-model="multiselect" multiple>
|
|
<option>foo</option>
|
|
<option>bar</option>
|
|
</select>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td>Cast to number</td>
|
|
<td>
|
|
<div x-data="{ number: 1 }">
|
|
<div x-text="JSON.stringify($data.number)"></div>
|
|
<input type="text" x-model.number="number">
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td>Nested Binding</td>
|
|
<td>
|
|
<div x-data="{ foo: { bar: 'baz' } }">
|
|
<div x-text="foo.bar"></div>
|
|
<input type="text" x-model="foo.bar">
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td>On Click</td>
|
|
<td>
|
|
<div x-data="{ show: false }">
|
|
<div x-show="show">Hi There!</div>
|
|
|
|
<button x-on:click="show= ! show">Show/Hide</button>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td>Refs</td>
|
|
<td>
|
|
<div x-data="{ someText: 'bar' }">
|
|
<div x-ref="remove-target">Remove Me</div>
|
|
|
|
<button
|
|
x-on:click="$refs['remove-target'].remove()">Remove</button>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td>x-on:click.stop</td>
|
|
<td>
|
|
<div x-data="{ someText: 'bar' }">
|
|
<span x-text="someText"></span>
|
|
|
|
<div x-on:click="someText= 'baz'">
|
|
<button x-on:click.stop>Shouldn't change to baz</button>
|
|
</div>
|
|
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td>x-on:click (with return false)</td>
|
|
<td>
|
|
<div x-data>
|
|
<label for="checkbox-frozen">I should be frozen on un-checked</label>
|
|
<input id="checkbox-frozen" type="checkbox" @click="return false"></input>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td>x-on:click.prevent</td>
|
|
<td>
|
|
<div x-data="{}">
|
|
<a href="https://google.com" x-on:click.prevent>Shouldn't
|
|
go to Google</a>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td>x-on:click.once</td>
|
|
<td>
|
|
<div x-data="{ count: 0 }">
|
|
<button x-on:click.once="count++">I've been clicked:
|
|
<span x-text="count"></span></button>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td>Append DOM</td>
|
|
<td>
|
|
<div id="goHere">Click me.</div>
|
|
<script>
|
|
const thing = document.querySelector('#goHere')
|
|
const handler = (e) => {
|
|
thing.removeEventListener('click', handler)
|
|
|
|
const div = document.createElement('div')
|
|
div.setAttribute('x-data', '{hey: "there"}')
|
|
div.innerHTML = '<input type="text" x-model="hey"><h1 x-text="hey"></h1>'
|
|
e.target.appendChild(div)
|
|
}
|
|
|
|
var listener = thing.addEventListener('click', handler)
|
|
</script>
|
|
</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td>Append Nested DOM</td>
|
|
<td>
|
|
<div id="goHere2">Click me.</div>
|
|
<script>
|
|
const thing2 = document.querySelector('#goHere2')
|
|
const handler2 = (e) => {
|
|
thing2.removeEventListener('click', handler2)
|
|
|
|
e.target.innerHTML = `
|
|
<article>
|
|
<div x-data="{hey: 'there'}">
|
|
<input type="text" x-model="hey"><h1 x-text="hey"></h1>
|
|
</div>
|
|
</article>
|
|
`
|
|
}
|
|
|
|
var listener = thing2.addEventListener('click', handler2)
|
|
</script>
|
|
</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td>x-for</td>
|
|
<td>
|
|
<div x-data="{ items: ['foo', 'bar'], foo: 'bar' }">
|
|
<input type="checkbox" x-model="items" value="foo">
|
|
<input type="checkbox" x-model="items" value="bar">
|
|
<input type="checkbox" x-model="items" value="baz">
|
|
|
|
<button @click="items = ['bar', 'bob']">hey</button>
|
|
|
|
<template x-for="item in items" :key="item">
|
|
<div x-text="item" x-transition:enter-start="opacity-0 scale-90"
|
|
x-transition:enter="ease-out transition-medium"
|
|
x-transition:enter-end="opacity-100 scale-100"
|
|
x-transition:leave-start="opacity-100 scale-100"
|
|
x-transition:leave="ease-in transition-faster"
|
|
x-transition:leave-end="opacity-0 scale-90"
|
|
></div>
|
|
</template>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td>Nested x-for</td>
|
|
<td>
|
|
<div x-data="{ foos: [{bars: [{bobs: ['one', 'two']}, {bobs: ['three', 'four']}]}, {bars: [{bobs: ['five', 'six']}, {bobs: ['seven', 'eight']}]}] }">
|
|
<template x-for="foo in foos">
|
|
<div>
|
|
<template x-for="bar in foo.bars">
|
|
<div>
|
|
<template x-for="bob in bar.bobs">
|
|
<span x-text="bob"></span>
|
|
</template>
|
|
</div>
|
|
</template>
|
|
</div>
|
|
</template>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td>x-for over a range using <code>i in 10</code> syntax</td>
|
|
<td>
|
|
<div x-data>
|
|
<template x-for="i in 10" :key="i">
|
|
<span x-text="i"></span>
|
|
</template>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td>x-for over a range using <code>i in 10</code> syntax and data property</td>
|
|
<td>
|
|
<div x-data="{ count: 10 }">
|
|
<template x-for="i in count" :key="i">
|
|
<span x-text="i"></span>
|
|
</template>
|
|
<button type="button" @click="count++">Increment count</button>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td>Transitions</td>
|
|
<td>
|
|
<div x-data="{ open: false }">
|
|
<button x-on:click="open= ! open">
|
|
Open Modal
|
|
</button>
|
|
|
|
<div x-show="open"
|
|
x-transition:enter="transition-medium"
|
|
x-transition:leave="transition-medium">
|
|
<div x-show="open"
|
|
x-transition:enter="transition-medium"
|
|
x-transition:enter-start="opacity-0"
|
|
x-transition:leave-end="opacity-0"
|
|
x-transition:leave="transition-medium"></div>
|
|
<div x-show="open"
|
|
x-transition:enter-start="opacity-0 scale-90"
|
|
x-transition:enter="ease-out transition-medium"
|
|
x-transition:enter-end="opacity-100 scale-100"
|
|
x-transition:leave-start="opacity-100 scale-100"
|
|
x-transition:leave="ease-in transition-faster"
|
|
x-transition:leave-end="opacity-0 scale-90">
|
|
<div>
|
|
hey
|
|
</div>
|
|
<div>
|
|
<button x-on:click="open= false" type="button">
|
|
Cancel
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td>CSS animations</td>
|
|
<td>
|
|
<div x-data="{ open: false }">
|
|
<button x-on:click="open= ! open">
|
|
Open Modal
|
|
</button>
|
|
|
|
<div x-show="open"
|
|
x-transition:enter="animation jackInTheBox"
|
|
x-transition:leave="animation hinge">
|
|
<div>
|
|
hey
|
|
</div>
|
|
<div>
|
|
<button x-on:click="open= false" type="button">
|
|
Cancel
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td>Transitions (with x-if)</td>
|
|
<td>
|
|
<div x-data="{ open: false }">
|
|
<button x-on:click="open= ! open">
|
|
Open Modal
|
|
</button>
|
|
|
|
<template x-if="open">
|
|
<div x-transition:enter-start="opacity-0 scale-90"
|
|
x-transition:enter="ease-out transition-medium"
|
|
x-transition:enter-end="opacity-100 scale-100"
|
|
x-transition:leave-start="opacity-100 scale-100"
|
|
x-transition:leave="ease-in transition-faster"
|
|
x-transition:leave-end="opacity-0 scale-90">
|
|
hey
|
|
</div>
|
|
</template>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td>Nested Transitions (with x-show)</td>
|
|
<td>
|
|
<div x-data="{ open: false }">
|
|
<button x-on:click="open= ! open">
|
|
Open Modal
|
|
</button>
|
|
|
|
<div x-show="open">
|
|
I shouldn't leave until the transition finishes.
|
|
<div x-show="open"
|
|
x-transition:leave-start="opacity-100 scale-100"
|
|
x-transition:leave="ease-in transition-slow"
|
|
x-transition:leave-end="opacity-0 scale-90">
|
|
I'm transitioning
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td>Init function callback access refs and mutate data</td>
|
|
<td>
|
|
<div x-data="initialData()" x-init="init()">
|
|
<div :style="'width: '+width+'px; background: purple;'">hey</div>
|
|
|
|
<button x-ref="inc">increase</button>
|
|
</div>
|
|
|
|
<script>
|
|
function initialData() {
|
|
return {
|
|
width: 20,
|
|
init() {
|
|
this.$refs.inc.addEventListener('click', () => {
|
|
this.width = this.width + 20
|
|
})
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td>Dispatch</td>
|
|
<td>
|
|
<div x-data="{ foo: 'bar' }" x-on:custom-event="foo = $event.detail.newValue">
|
|
<span x-text="foo"></span>
|
|
|
|
<button x-on:click="$dispatch('custom-event', {newValue: 'baz'})">Turn 'bar' to 'baz'</button>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td>x-bind spread</td>
|
|
<td>
|
|
<div x-data="modal()">
|
|
I should be "hey": <span x-spread="bound"></span>
|
|
</div>
|
|
|
|
<script>
|
|
function modal() {
|
|
return {
|
|
foo: { bar: 'hey' },
|
|
bound: {
|
|
['x-text']() { return this.foo.bar }
|
|
},
|
|
}
|
|
}
|
|
</script>
|
|
|
|
</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td>Cloak</td>
|
|
<td>
|
|
<div x-data="{}" x-cloak>
|
|
I'm cloaked
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</body>
|
|
</html>
|