Caleb Porzio 3 gadi atpakaļ
vecāks
revīzija
1093565a3d

+ 8 - 153
index.html

@@ -11,158 +11,13 @@
     <script src="//cdn.tailwindcss.com"></script>
     <!-- <script src="https://unpkg.com/@popperjs/core@2"></script> -->
 
-    <div x-data x-tabs>
-        <div x-tabs:list>
-            <div><button x-tabs:tab>Hey!</button></div>
-            <div><button x-tabs:tab>There!</button></div>
-            <div><button x-tabs:tab>You!</button></div>
-        </div>
-
-        <div x-tabs:panels>
-            <div x-tabs:panel>
-                <h1>Hey!</h1>
-            </div>
-            <div x-tabs:panel>
-                <h1>There!</h1>
-            </div>
-            <div x-tabs:panel>
-                <h1>You!</h1>
-            </div>
-        </div>
-    </div>
-
-    <div x-data="{ open: false }">
-        <button @click="open = ! open">Open</button>
-
-        <div x-dialog x-model="open">
-            <div x-dialog:panel>
-                Hey!
-            </div>
-        </div>
+    <div x-data="{}">
+        <a href="#hello" x-bind:href="null">null</a>
+        <a href="#hello" x-bind:href="false">false</a>
+        <a href="#hello" x-bind:href="undefined">undefined</a>
+        <!-- custom attribute see https://github.com/alpinejs/alpine/issues/280 -->
+        <span visible="true" x-bind:visible="null">null</span>
+        <span visible="true" x-bind:visible="false">false</span>
+        <span visible="true" x-bind:visible="undefined">undefined</span>
     </div>
-
-    <div x-data x-popover:group>
-        <div x-data x-popover>
-            <button x-popover:button>Open</button>
-            <ul x-popover:panel>
-                <li><button>yo</button></li>
-                <li><button>there</button></li>
-                <li><button>you</button></li>
-            </ul>
-        </div>
-        <div x-data x-popover>
-            <button x-popover:button>Open 2</button>
-            <ul x-popover:panel>
-                <li><button>yo</button></li>
-                <li><button>yins</button></li>
-                <li><button>yack</button></li>
-            </ul>
-        </div>
-    </div>
-
-    <div></div>
-
-    <!-- <div x-data x-tabs>
-        <button x-tabs:button>Open</button>
-
-        <ul x-tabs:panel>
-            hey
-        </ul>
-    </div> -->
-
-    <button>focus away</button>
-
-    <button id="hey">
-        hey
-    </button>
-
-    <script>
-        document.addEventListener('alpine:init', () => {
-            Alpine.bind(document.querySelector('#hey'), {
-                '@keyup.esc'() { console.log(this.$el); return 'there' }
-            })
-        })
-    </script>
-
-    <!-- <main class="flex-1 overflow-auto bg-gray-50 h-screen">
-        <div class="flex justify-center items-center space-x-12 p-12">
-            <button>Previous</button>
-            <nav
-                x-data="{ links: ['First', 'Second', 'Third', 'Fourth'] }"
-                x-popover:group
-                aria-label="Mythical University"
-                class="flex space-x-3"
-            >
-                <div x-popover class="relative">
-                    <div
-                        x-popover:overlay
-                        x-transition:enter="transition ease-out duration-300 transform"
-                        x-transition:enter-start="opacity-0"
-                        x-transition:enter-end="opacity-100"
-                        x-transition:leave="transition ease-in duration-300 transform"
-                        x-transition:leave-start="opacity-100"
-                        x-transition:leave-end="opacity-0"
-                        class="bg-opacity-75 bg-gray-500 fixed inset-0 z-20"
-                    ></div>
-                    <button
-                        x-popover:button
-                        class="px-3 py-2 bg-gray-300 border-2 border-transparent focus:outline-none focus:border-blue-900 relative z-30"
-                    >Normal</button>
-                    <div x-popover:panel class="absolute flex flex-col w-64 bg-gray-100 border-2 border-blue-900 z-30">
-                        <template x-for="(link, i) of links">
-                            <a :hidden="i === 2" href="/" class="px-3 py-2 border-2 border-transparent hover:bg-gray-200 focus:bg-gray-200 focus:outline-none focus:border-blue-900">
-                                Normal - <span x-text="link"></span>
-                            </a>
-                        </template>
-                    </div>
-                </div>
-                <div x-popover class="relative">
-                    <button x-popover:button class="px-3 py-2 bg-gray-300 border-2 border-transparent focus:outline-none focus:border-blue-900">Focus</button>
-                    <div x-popover:panel :focus="true" class="absolute flex flex-col w-64 bg-gray-100 border-2 border-blue-900">
-                        <template x-for="(link, i) of links">
-                            <a href="/" class="px-3 py-2 border-2 border-transparent hover:bg-gray-200 focus:bg-gray-200 focus:outline-none focus:border-blue-900">
-                                Focus - <span x-text="link"></span>
-                            </a>
-                        </template>
-                    </div>
-                </div>
-
-                <div
-                    x-popover
-                    class="relative"
-                    x-init="$nextTick(() => Popper.createPopper($refs.trigger1, $refs.container1, { placement: 'bottom-start', strategy: 'fixed' }))"
-                >
-                    <button x-popover:button x-ref="trigger1" class="px-3 py-2 bg-gray-300 border-2 border-transparent focus:outline-none focus:border-blue-900">Portal</button>
-                    <template x-teleport="body">
-                        <div x-popover:panel x-ref="container1" class="flex flex-col w-64 bg-gray-100 border-2 border-blue-900">
-                            <template x-for="(link, i) of links">
-                                <a href="/" class="px-3 py-2 border-2 border-transparent hover:bg-gray-200 focus:bg-gray-200 focus:outline-none focus:border-blue-900">
-                                    Portal - <span x-text="link"></span>
-                                </a>
-                            </template>
-                        </div>
-                    </template>
-                </div>
-
-                <div
-                    x-popover
-                    class="relative"
-                    x-init="$nextTick(() => Popper.createPopper($refs.trigger2, $refs.container2, { placement: 'bottom-start', strategy: 'fixed' }))"
-                >
-                    <button x-popover:button x-ref="trigger2" class="px-3 py-2 bg-gray-300 border-2 border-transparent focus:outline-none focus:border-blue-900">Focus in portal</button>
-
-                    <template x-teleport="body">
-                        <div x-popover:panel :focus="true" x-ref="container2" class="flex flex-col w-64 bg-gray-100 border-2 border-blue-900">
-                            <template x-for="(link, i) of links">
-                                <a href="/" class="px-3 py-2 border-2 border-transparent hover:bg-gray-200 focus:bg-gray-200 focus:outline-none focus:border-blue-900">
-                                    Focus in Portal - <span x-text="link"></span>
-                                </a>
-                            </template>
-                        </div>
-                    </template>
-                </div>
-            </nav>
-            <button>Next</button>
-        </div>
-    </main> -->
 </html>

+ 0 - 2
packages/alpinejs/src/alpine.js

@@ -16,7 +16,6 @@ import { plugin } from './plugin'
 import { magic } from './magics'
 import { store } from './store'
 import { bind } from './binds'
-import { registerElement as element } from './elements'
 import { data } from './datas'
 
 let Alpine = {
@@ -52,7 +51,6 @@ let Alpine = {
     initTree,
     nextTick,
     prefixed,
-    element,
     prefix,
     plugin,
     magic,

+ 0 - 20
packages/alpinejs/src/directives.js

@@ -22,26 +22,6 @@ export function directive(name, callback) {
 export function directives(el, attributes, originalAttributeOverride) {
     attributes = Array.from(attributes)
 
-    if (el._x_virtualDirectives) {
-        let vAttributes = Object.entries(el._x_virtualDirectives).map(([name, value]) => ({ name, value }))
-
-        let staticAttributes = attributesOnly(vAttributes)
-
-        // Handle binding normal HTML attributes (non-Alpine directives).
-        vAttributes = vAttributes.map(attribute => {
-            if (staticAttributes.find(attr => attr.name === attribute.name)) {
-                return {
-                    name: `x-bind:${attribute.name}`,
-                    value: `"${attribute.value}"`,
-                }
-            }
-
-            return attribute
-        })
-
-        attributes = attributes.concat(vAttributes)
-    }
-
     let transformedAttributeMap = {}
 
     let directives = attributes

+ 6 - 6
packages/alpinejs/src/utils/bind.js

@@ -7,7 +7,7 @@ export default function bind(el, name, value, modifiers = []) {
     if (! el._x_bindings) el._x_bindings = reactive({})
 
     el._x_bindings[name] = value
-   
+
     name = modifiers.includes('camel') ? camelCase(name) : name
 
     switch (name) {
@@ -129,21 +129,21 @@ function attributeShouldntBePreservedIfFalsy(name) {
 }
 
 export function getBinding(el, name, fallback) {
-    // First let's get it out of Alpine bound data. 
+    // First let's get it out of Alpine bound data.
     if (el._x_bindings && el._x_bindings[name] !== undefined) return el._x_bindings[name]
 
-    // If not, we'll return the literal attribute. 
+    // If not, we'll return the literal attribute.
     let attr = el.getAttribute(name)
 
     // Nothing bound:
     if (attr === null) return typeof fallback === 'function' ? fallback() : fallback
-   
+
     if (isBooleanAttr(name)) {
         return !! [name, 'true'].includes(attr)
     }
 
-    // The case of a custom attribute with no value. Ex: <div manual> 
+    // The case of a custom attribute with no value. Ex: <div manual>
     if (attr === '') return true
-   
+
     return attr
 }

+ 1 - 0
packages/ui/src/dialog.js

@@ -46,6 +46,7 @@ function handleRoot(el, Alpine) {
                     else this.__isOpenState = false
                 },
                 get __isOpen() {
+                    console.log('foo', Alpine.bound(el, 'static', this.__isOpenState))
                     return Alpine.bound(el, 'static', this.__isOpenState)
                 },
             }

+ 0 - 4
packages/ui/src/index.js

@@ -1,9 +1,5 @@
 import dialog from './dialog'
-import popover from './popover'
-import tabs from './tabs'
 
 export default function (Alpine) {
     dialog(Alpine)
-    popover(Alpine)
-    tabs(Alpine)
 }

+ 6 - 6
tests/cypress/integration/directives/x-bind.spec.js

@@ -49,12 +49,12 @@ test('non-boolean attributes set to null/undefined/false are removed from the el
         </div>
     `,
     ({ get }) => {
-        get('a:nth-child(1)').should(notHaveAttribute('href'))
-        get('a:nth-child(2)').should(notHaveAttribute('href'))
-        get('a:nth-child(3)').should(notHaveAttribute('href'))
-        get('span:nth-child(1)').should(notHaveAttribute('visible'))
-        get('span:nth-child(2)').should(notHaveAttribute('visible'))
-        get('span:nth-child(3)').should(notHaveAttribute('visible'))
+        get('a:nth-of-type(1)').should(notHaveAttribute('href'))
+        get('a:nth-of-type(2)').should(notHaveAttribute('href'))
+        get('a:nth-of-type(3)').should(notHaveAttribute('href'))
+        get('span:nth-of-type(1)').should(notHaveAttribute('visible'))
+        get('span:nth-of-type(2)').should(notHaveAttribute('visible'))
+        get('span:nth-of-type(3)').should(notHaveAttribute('visible'))
     }
 )
 

+ 21 - 21
tests/cypress/integration/directives/x-for.spec.js

@@ -1,4 +1,4 @@
-import { beVisible, haveLength, haveText, html, notBeVisible, test } from '../../utils'
+import { exist, haveLength, haveText, html, notExist, test } from '../../utils'
 
 test('renders loops with x-for',
     html`
@@ -12,7 +12,7 @@ test('renders loops with x-for',
     `,
     ({ get }) => {
         get('span:nth-of-type(1)').should(haveText('foo'))
-        get('span:nth-of-type(2)').should(notBeVisible())
+        get('span:nth-of-type(2)').should(notExist())
         get('button').click()
         get('span:nth-of-type(1)').should(haveText('foo'))
         get('span:nth-of-type(2)').should(haveText('bar'))
@@ -47,9 +47,9 @@ test('renders loops with x-for that have space or newline',
     `,
     ({ get }) => {
         get('#1 span:nth-of-type(1)').should(haveText('foo'))
-        get('#1 span:nth-of-type(2)').should(notBeVisible())
+        get('#1 span:nth-of-type(2)').should(notExist())
         get('#2 span:nth-of-type(1)').should(haveText('foo'))
-        get('#2 span:nth-of-type(2)').should(notBeVisible())
+        get('#2 span:nth-of-type(2)').should(notExist())
         get('button').click()
         get('#1 span:nth-of-type(1)').should(haveText('foo'))
         get('#1 span:nth-of-type(2)').should(haveText('bar'))
@@ -107,9 +107,9 @@ test('removes all elements when array is empty and previously had one item',
         </div>
     `,
     ({ get }) => {
-        get('span').should(beVisible())
+        get('span').should(exist())
         get('button').click()
-        get('span').should(notBeVisible())
+        get('span').should(notExist())
     }
 )
 
@@ -124,13 +124,13 @@ test('removes all elements when array is empty and previously had multiple items
         </div>
     `,
     ({ get }) => {
-        get('span:nth-of-type(1)').should(beVisible())
-        get('span:nth-of-type(2)').should(beVisible())
-        get('span:nth-of-type(3)').should(beVisible())
+        get('span:nth-of-type(1)').should(exist())
+        get('span:nth-of-type(2)').should(exist())
+        get('span:nth-of-type(3)').should(exist())
         get('button').click()
-        get('span:nth-of-type(1)').should(notBeVisible())
-        get('span:nth-of-type(2)').should(notBeVisible())
-        get('span:nth-of-type(3)').should(notBeVisible())
+        get('span:nth-of-type(1)').should(notExist())
+        get('span:nth-of-type(2)').should(notExist())
+        get('span:nth-of-type(3)').should(notExist())
     }
 )
 
@@ -148,11 +148,11 @@ test('elements inside of loop are reactive',
         </div>
     `,
     ({ get }) => {
-        get('span').should(beVisible())
+        get('span').should(exist())
         get('h1').should(haveText('first'))
         get('h2').should(haveText('bar'))
         get('button').click()
-        get('span').should(beVisible())
+        get('span').should(exist())
         get('h1').should(haveText('first'))
         get('h2').should(haveText('baz'))
     }
@@ -315,13 +315,13 @@ test('nested x-for',
         </div>
     `,
     ({ get }) => {
-        get('h1:nth-of-type(1) h2:nth-of-type(1)').should(beVisible())
-        get('h1:nth-of-type(1) h2:nth-of-type(2)').should(beVisible())
-        get('h1:nth-of-type(2) h2:nth-of-type(1)').should(notBeVisible())
+        get('h1:nth-of-type(1) h2:nth-of-type(1)').should(exist())
+        get('h1:nth-of-type(1) h2:nth-of-type(2)').should(exist())
+        get('h1:nth-of-type(2) h2:nth-of-type(1)').should(notExist())
         get('button').click()
-        get('h1:nth-of-type(1) h2:nth-of-type(1)').should(beVisible())
-        get('h1:nth-of-type(1) h2:nth-of-type(2)').should(beVisible())
-        get('h1:nth-of-type(2) h2:nth-of-type(1)').should(beVisible())
+        get('h1:nth-of-type(1) h2:nth-of-type(1)').should(exist())
+        get('h1:nth-of-type(1) h2:nth-of-type(2)').should(exist())
+        get('h1:nth-of-type(2) h2:nth-of-type(1)').should(exist())
     }
 )
 
@@ -538,7 +538,7 @@ test('x-for removed dom node does not evaluate child expressions after being rem
         get('span').should(haveText('lebowski'))
 
         /** Clicking button sets users=[] and thus x-for loop will remove all children.
-            If the sub-expression x-text="users[idx].name" is evaluated, the button click  
+            If the sub-expression x-text="users[idx].name" is evaluated, the button click
             will produce an error because users[idx] is no longer defined and the test will fail
         **/
         get('button').click()

+ 8 - 8
tests/cypress/integration/directives/x-if.spec.js

@@ -1,4 +1,4 @@
-import { beVisible, haveText, html, notBeVisible, test } from '../../utils'
+import { exist, haveText, html, notExist, test } from '../../utils'
 
 test('x-if',
     html`
@@ -11,11 +11,11 @@ test('x-if',
         </div>
     `,
     ({ get }) => {
-        get('h1').should(notBeVisible())
+        get('h1').should(notExist())
         get('button').click()
-        get('h1').should(beVisible())
+        get('h1').should(exist())
         get('button').click()
-        get('h1').should(notBeVisible())
+        get('h1').should(notExist())
     }
 )
 
@@ -65,11 +65,11 @@ test('x-if removed dom does not evaluate reactive expressions in dom tree',
     `,
     ({ get }) => {
         get('span').should(haveText('lebowski'))
-        
-        // Clicking button sets user=null and thus x-if="user" will evaluate to false. 
-        // If the sub-expression x-text="user.name" is evaluated, the button click  
+
+        // Clicking button sets user=null and thus x-if="user" will evaluate to false.
+        // If the sub-expression x-text="user.name" is evaluated, the button click
         // will produce an error because user is no longer defined and the test will fail
         get('button').click()
-        get('span').should('not.exist')
+        get('span').should(notExist())
     }
 )

+ 6 - 6
tests/cypress/integration/directives/x-teleport.spec.js

@@ -1,4 +1,4 @@
-import { beEqualTo, beVisible, haveText, html, notBeVisible, test } from '../../utils'
+import { exist, haveText, html, notExist, test } from '../../utils'
 
 test('can use a x-teleport',
     [html`
@@ -78,9 +78,9 @@ test('removing teleport source removes teleported target',
         <div id="b"></div>
     `],
     ({ get }) => {
-        get('#b h1').should(beVisible())
+        get('#b h1').should(exist())
         get('button').click()
-        get('#b h1').should(notBeVisible())
+        get('#b h1').should(notExist())
     },
 )
 
@@ -97,9 +97,9 @@ test('$refs inside teleport can be accessed outside',
         <div id="b"></div>
     `],
     ({ get }) => {
-        get('#b h1').should(beVisible())
+        get('#b h1').should(exist())
         get('button').click()
-        get('#b h1').should(notBeVisible())
+        get('#b h1').should(notExist())
     },
 )
 
@@ -114,7 +114,7 @@ test('$root is accessed outside teleport',
         <div id="b"></div>
     `],
     ({ get }) => {
-        get('#b h1').should(beVisible())
+        get('#b h1').should(exist())
         get('#b h1').should(haveText('a'))
     },
 )

+ 16 - 16
tests/cypress/integration/plugins/persist.spec.js

@@ -1,4 +1,4 @@
-import { beEqualTo, beVisible, haveText, html, notBeVisible, test } from '../../utils'
+import { beEqualTo, exist, haveText, html, notExist, test } from '../../utils'
 
 test('can persist number',
     [html`
@@ -83,11 +83,11 @@ test('can persist boolean',
         </div>
     `],
     ({ get }, reload) => {
-        get('span').should(notBeVisible())
+        get('span').should(notExist())
         get('button').click()
-        get('span').should(beVisible())
+        get('span').should(exist())
         reload()
-        get('span').should(beVisible())
+        get('span').should(exist())
     },
 )
 
@@ -128,14 +128,14 @@ test('can persist using an alias',
         </div>
     `],
     ({ get }, reload) => {
-        get('span#one').should(notBeVisible())
-        get('span#two').should(notBeVisible())
+        get('span#one').should(notExist())
+        get('span#two').should(notExist())
         get('button').click()
-        get('span#one').should(notBeVisible())
-        get('span#two').should(beVisible())
+        get('span#one').should(notExist())
+        get('span#two').should(exist())
         reload()
-        get('span#one').should(notBeVisible())
-        get('span#two').should(beVisible())
+        get('span#one').should(notExist())
+        get('span#two').should(exist())
     },
 )
 
@@ -155,14 +155,14 @@ test('aliases do not affect other $persist calls',
         </div>
     `],
     ({ get }, reload) => {
-        get('span#one').should(notBeVisible())
-        get('span#two').should(notBeVisible())
+        get('span#one').should(notExist())
+        get('span#two').should(notExist())
         get('button').click()
-        get('span#one').should(notBeVisible())
-        get('span#two').should(beVisible())
+        get('span#one').should(notExist())
+        get('span#two').should(exist())
         reload()
-        get('span#one').should(notBeVisible())
-        get('span#two').should(beVisible())
+        get('span#one').should(notExist())
+        get('span#two').should(exist())
     },
 )
 

+ 2 - 2
tests/cypress/integration/plugins/ui/dialog.spec.js

@@ -1,4 +1,4 @@
-import { beVisible, haveAttribute, haveText, html, notBeVisible, test } from '../../../utils'
+import { beVisible, haveAttribute, haveText, html, notBeVisible, notExist, test } from '../../../utils'
 
 test('has accessibility attributes',
     [html`
@@ -65,7 +65,7 @@ test('works with static prop',
         </div>
     `],
     ({ get }) => {
-        get('article').should(notBeVisible())
+        get('article').should(notExist())
         get('button').click()
         get('article').should(beVisible())
     },

+ 0 - 0
tests/cypress/integration/plugins/ui/popover.spec.js → tests/cypress/integration/plugins/ui/popover.spec._js


+ 1 - 1
tests/cypress/integration/plugins/ui/tabs.spec.js → tests/cypress/integration/plugins/ui/tabs._spec._js

@@ -55,7 +55,7 @@ test('can use arrow keys to cycle through tabs',
     },
 )
 
-test.only('cant tab through tabs, can only use arrows',
+test('cant tab through tabs, can only use arrows',
     [html`
         <div>
             <button button-1>first focusable</button>

+ 5 - 1
tests/cypress/utils.js

@@ -77,7 +77,7 @@ function injectHtmlAndBootAlpine(cy, templateAndPotentiallyScripts, callback, pa
 
         cy.window().then(window => {
             callback(cy, reload, window, window.document)
-        }) 
+        })
     })
 }
 
@@ -105,6 +105,10 @@ export let beVisible = () => el => expect(el).to.be.visible
 
 export let notBeVisible = () => el => expect(el).not.to.be.visible
 
+export let exist = () => el => expect(el).to.exist
+
+export let notExist = () => el => expect(el).not.to.exist
+
 export let beHidden = () => el => expect(el).to.be.hidden
 
 export let haveClasses = classes => el => classes.forEach(aClass => expect(el).to.have.class(aClass))