Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: alpinejs/alpine
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v3.13.3
Choose a base ref
...
head repository: alpinejs/alpine
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v3.13.4
Choose a head ref

Commits on Nov 19, 2023

  1. wip

    calebporzio committed Nov 19, 2023
    Copy the full SHA
    dc5ce15 View commit details

Commits on Nov 29, 2023

  1. Fix x-disclosure when used with x-collapse transitioning in on the pa…

    …ge load instead of showing up instantly
    calebporzio committed Nov 29, 2023
    Copy the full SHA
    1212d22 View commit details
  2. wip

    calebporzio committed Nov 29, 2023
    Copy the full SHA
    afefff6 View commit details
  3. wip

    calebporzio committed Nov 29, 2023
    Copy the full SHA
    d2ceeb4 View commit details

Commits on Dec 1, 2023

  1. Improve combobox performance (#3898)

    * Refactor activeKey to switchboard for faster mouse hovers
    
    * Optimize destroyed items performance on row removal
    
    * Fix and optimize the unregisterItem method further
    
    * fix bug
    
    * Optimize item registration
    
    * Fix listbox
    calebporzio authored Dec 1, 2023
    Copy the full SHA
    c767c97 View commit details
  2. Copy the full SHA
    e902beb View commit details

Commits on Dec 3, 2023

  1. Expose Alpine.watch

    calebporzio committed Dec 3, 2023
    Copy the full SHA
    b7bfd88 View commit details

Commits on Dec 4, 2023

  1. Fix watch

    calebporzio committed Dec 4, 2023
    Copy the full SHA
    1a3a8b7 View commit details

Commits on Dec 11, 2023

  1. Copy the full SHA
    3d75916 View commit details

Commits on Dec 12, 2023

  1. Fix x-id when used with morph (#3919)

    * fix x-id when used with morph
    
    * fix $id caching mechanism
    
    * remove .only
    
    * fix tests
    calebporzio authored Dec 12, 2023
    Copy the full SHA
    0effdae View commit details

Commits on Dec 15, 2023

  1. rework (#3929)

    calebporzio authored Dec 15, 2023
    Copy the full SHA
    018e9ce View commit details
  2. add explanation of passing an object to x-for (#3928)

    `x-for` also accepts objects in addition to arrays. the docs currently only mention arrays, so users might not be sure if objects are allowed. this explicitly states they are and gives an example how to use them.
    browner12 authored Dec 15, 2023
    Copy the full SHA
    c780cad View commit details
  3. Copy the full SHA
    0115f8b View commit details
  4. Update refs.md (#3851)

    * Update refs.md
    
    Added details on $refs not supporting dynamic binding anymore in V3
    
    * Update refs.md
    
    Fixed logic of the example to reflect the actual evaluation of $refs
    Simsz authored Dec 15, 2023
    Copy the full SHA
    b24d8be View commit details

Commits on Jan 3, 2024

  1. fix: already init component

    Matsa59 committed Jan 3, 2024
    Copy the full SHA
    2bb702f View commit details

Commits on Jan 4, 2024

  1. Add CSP-friendly Alpine build (#3959)

    * refactor csp build
    
    * document
    calebporzio authored Jan 4, 2024
    Copy the full SHA
    8c1511a View commit details
  2. Add csp build to release

    calebporzio committed Jan 4, 2024
    Copy the full SHA
    1c2c675 View commit details
  3. bump version

    calebporzio committed Jan 4, 2024
    Copy the full SHA
    e597a3f View commit details
  4. fix docs for csp

    calebporzio committed Jan 4, 2024
    Copy the full SHA
    bac758e View commit details

Commits on Jan 5, 2024

  1. docs: typo (#3960)

    mhanberg authored Jan 5, 2024
    Copy the full SHA
    5397565 View commit details
  2. Copy the full SHA
    e3738a3 View commit details

Commits on Jan 10, 2024

  1. Revert to previous stage

    The only way to apply this on the node is to execute it on the
    mutation. Otherwise, we have to rewrite a big part of the lifecycle
    system.
    Matsa59 committed Jan 10, 2024
    Copy the full SHA
    83456d3 View commit details

Commits on Jan 19, 2024

  1. Copy the full SHA
    f9d47f2 View commit details
  2. Copy the full SHA
    622d2e2 View commit details
  3. Copy the full SHA
    9cfc4f7 View commit details
  4. move everything to lifecycle

    Matsa59 committed Jan 19, 2024
    Copy the full SHA
    c68aba0 View commit details

Commits on Jan 20, 2024

  1. Fix typo (#3932)

    aerni authored Jan 20, 2024
    Copy the full SHA
    67eb587 View commit details
  2. Copy the full SHA
    4b198d5 View commit details
  3. wip

    calebporzio committed Jan 20, 2024
    Copy the full SHA
    6a14bbe View commit details

Commits on Jan 21, 2024

  1. Copy the full SHA
    650de45 View commit details
  2. Fix issue where error message would not print directive name properly (

    …#3572)
    
    * Fix issue where error message would not print directive name properly
    
    * Fix bind specs
    mattvague authored Jan 21, 2024
    Copy the full SHA
    97ebbad View commit details
  3. Add named exports to build files (#3644)

    * Add named exports to build files
    
    * wip
    
    ---------
    
    Co-authored-by: Caleb Porzio <calebporzio@gmail.com>
    ypconstante and calebporzio authored Jan 21, 2024
    Copy the full SHA
    aed412b View commit details
  4. fix: reset input on init so default value is displayed (#3881)

    * fix: reset input on init so default value is displayed
    
    * fix: revert format changes from prettier
    
    * refactor: maintain original formatting
    
    * fix
    
    ---------
    
    Co-authored-by: Caleb Porzio <calebporzio@gmail.com>
    coder2000 and calebporzio authored Jan 21, 2024
    Copy the full SHA
    ae16eb3 View commit details
  5. Clear combobox bugfix (#3934)

    * Add failing tests
    
    * Fix clearing (or setting) selected
    gdebrauwer authored Jan 21, 2024
    Copy the full SHA
    c2e56bc View commit details
  6. wip

    calebporzio committed Jan 21, 2024
    Copy the full SHA
    88be3ec View commit details
  7. Copy the full SHA
    35f9ac1 View commit details
  8. tweak implementation

    calebporzio committed Jan 21, 2024
    Copy the full SHA
    3196c6a View commit details
  9. Copy the full SHA
    cb1e3ac View commit details
  10. Copy the full SHA
    2a64880 View commit details
  11. Listbox compare null value bugfix (#3962)

    * Add test
    
    * Handle null values in listbox __compare
    gdebrauwer authored Jan 21, 2024
    Copy the full SHA
    4fceb4c View commit details
  12. Fix error message (#3965)

    gdebrauwer authored Jan 21, 2024
    Copy the full SHA
    79fd16b View commit details
  13. Add x-trap noinitialfocus modifier (#3977)

    * Add x-trap noinitialfocus modifier
    
    Adds a new x-trap modifier: .noinitialfocus to trap focus without
    giving focus to the first element in the focus trap
    
    Test included
    
    Relates to discussion #2806
    
    * tweak addition
    
    ---------
    
    Co-authored-by: Caleb Porzio <calebporzio@gmail.com>
    richcarni and calebporzio authored Jan 21, 2024
    Copy the full SHA
    ad94a86 View commit details

Commits on Jan 22, 2024

  1. remove console.log

    calebporzio committed Jan 22, 2024
    Copy the full SHA
    aa3375a View commit details
  2. Combobox and listbox: Save optionKey in x-data to fix usage in Livewi…

    …re (#3990)
    
    * Save optionKey in x-data
    
    When optionKey is not saved in x-data, the value is lost after a Livewire update
    
    * Fix typos
    
    * refactor
    
    * more fixes
    
    ---------
    
    Co-authored-by: Caleb Porzio <calebporzio@gmail.com>
    gdebrauwer and calebporzio authored Jan 22, 2024
    Copy the full SHA
    5fe438f View commit details
  3. bump to 3.13.4

    calebporzio committed Jan 22, 2024
    Copy the full SHA
    6918d96 View commit details
Showing with 851 additions and 210 deletions.
  1. +2 −0 packages/alpinejs/builds/module.js
  2. +1 −1 packages/alpinejs/package.json
  3. +2 −1 packages/alpinejs/src/alpine.js
  4. +1 −4 packages/alpinejs/src/directives.js
  5. +12 −1 packages/alpinejs/src/directives/x-id.js
  6. +1 −1 packages/alpinejs/src/directives/x-model.js
  7. +40 −8 packages/alpinejs/src/magics/$id.js
  8. +10 −25 packages/alpinejs/src/magics/$watch.js
  9. +18 −25 packages/alpinejs/src/mutation.js
  10. +29 −0 packages/alpinejs/src/reactivity.js
  11. +4 −2 packages/alpinejs/src/utils/error.js
  12. +2 −0 packages/anchor/builds/module.js
  13. +1 −1 packages/anchor/package.json
  14. +2 −0 packages/collapse/builds/module.js
  15. +1 −1 packages/collapse/package.json
  16. +2 −0 packages/csp/builds/module.js
  17. +3 −3 packages/csp/package.json
  18. +50 −0 packages/csp/src/evaluator.js
  19. +28 −29 packages/csp/src/index.js
  20. +1 −1 packages/docs/package.json
  21. +63 −22 packages/docs/src/en/advanced/csp.md
  22. +2 −2 packages/docs/src/en/advanced/extending.md
  23. +1 −1 packages/docs/src/en/advanced/reactivity.md
  24. +24 −0 packages/docs/src/en/directives/for.md
  25. +21 −0 packages/docs/src/en/directives/model.md
  26. +1 −1 packages/docs/src/en/essentials/installation.md
  27. +1 −1 packages/docs/src/en/globals/alpine-data.md
  28. +15 −0 packages/docs/src/en/magics/refs.md
  29. +1 −1 packages/docs/src/en/plugins/anchor.md
  30. +7 −0 packages/docs/src/en/plugins/focus.md
  31. +4 −2 packages/focus/builds/module.js
  32. +1 −1 packages/focus/package.json
  33. +6 −2 packages/focus/src/index.js
  34. +2 −1 packages/history/builds/module.js
  35. +2 −0 packages/intersect/builds/module.js
  36. +1 −1 packages/intersect/package.json
  37. +3 −3 packages/mask/builds/module.js
  38. +1 −1 packages/mask/package.json
  39. +16 −4 packages/mask/src/index.js
  40. +2 −2 packages/morph/builds/module.js
  41. +1 −1 packages/morph/package.json
  42. +2 −0 packages/navigate/builds/module.js
  43. +2 −0 packages/persist/builds/module.js
  44. +1 −1 packages/persist/package.json
  45. +2 −0 packages/ui/builds/module.js
  46. +1 −1 packages/ui/package.json
  47. +15 −7 packages/ui/src/combobox.js
  48. +9 −5 packages/ui/src/disclosure.js
  49. +109 −31 packages/ui/src/list-context.js
  50. +23 −10 packages/ui/src/listbox.js
  51. +6 −0 scripts/release.js
  52. +5 −2 tests/cypress/integration/directives/x-model.spec.js
  53. +32 −1 tests/cypress/integration/magics/$id.spec.js
  54. +28 −0 tests/cypress/integration/plugins/focus.spec.js
  55. +16 −0 tests/cypress/integration/plugins/mask.spec.js
  56. +110 −2 tests/cypress/integration/plugins/ui/combobox.spec.js
  57. +93 −1 tests/cypress/integration/plugins/ui/listbox.spec.js
  58. +12 −0 tests/cypress/utils.js
2 changes: 2 additions & 0 deletions packages/alpinejs/builds/module.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import Alpine from './../src/index'

export default Alpine

export { Alpine }
2 changes: 1 addition & 1 deletion packages/alpinejs/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "alpinejs",
"version": "3.13.3",
"version": "3.13.4",
"description": "The rugged, minimal JavaScript framework",
"homepage": "https://alpinejs.dev",
"repository": {
3 changes: 2 additions & 1 deletion packages/alpinejs/src/alpine.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { setReactivityEngine, disableEffectScheduling, reactive, effect, release, raw } from './reactivity'
import { setReactivityEngine, disableEffectScheduling, reactive, effect, release, raw, watch } from './reactivity'
import { mapAttributes, directive, setPrefix as prefix, prefix as prefixed } from './directives'
import { start, addRootSelector, addInitSelector, closestRoot, findClosest, initTree, destroyTree, interceptInit } from './lifecycle'
import { onElRemoved, onAttributeRemoved, onAttributesAdded, mutateDom, deferMutations, flushAndStopDeferringMutations, startObservingMutations, stopObservingMutations } from './mutation'
@@ -73,6 +73,7 @@ let Alpine = {
cloneNode, // INTERNAL
bound,
$data,
watch,
walk,
data,
bind,
5 changes: 1 addition & 4 deletions packages/alpinejs/src/directives.js
Original file line number Diff line number Diff line change
@@ -21,10 +21,7 @@ export function directive(name, callback) {
return {
before(directive) {
if (!directiveHandlers[directive]) {
console.warn(
"Cannot find directive `${directive}`. "
+ "`${name}` will use the default order of execution"
);
console.warn(String.raw`Cannot find directive \`${directive}\`. \`${name}\` will use the default order of execution`);
return;
}
const pos = directiveOrder.indexOf(directive);
13 changes: 12 additions & 1 deletion packages/alpinejs/src/directives/x-id.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,19 @@
import { interceptClone } from "../clone"
import { directive } from "../directives"
import { setIdRoot } from '../ids'

directive('id', (el, { expression }, { evaluate }) => {
let names = evaluate(expression)

names.forEach(name => setIdRoot(el, name))
})

interceptClone((from, to) => {
// Transfer over existing ID registrations from
// the existing dom tree over to the new one
// so that there aren't ID mismatches...
if (from._x_ids) {
to._x_ids = from._x_ids
}
})

2 changes: 1 addition & 1 deletion packages/alpinejs/src/directives/x-model.js
Original file line number Diff line number Diff line change
@@ -71,7 +71,7 @@ directive('model', (el, { modifiers, expression }, { effect, cleanup }) => {
})

if (modifiers.includes('fill'))
if ([null, ''].includes(getValue())
if ([undefined, null, ''].includes(getValue())
|| (el.type === 'checkbox' && Array.isArray(getValue()))) {
el.dispatchEvent(new Event(event, {}));
}
48 changes: 40 additions & 8 deletions packages/alpinejs/src/magics/$id.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,46 @@
import { magic } from '../magics'
import { closestIdRoot, findAndIncrementId } from '../ids'
import { interceptClone } from '../clone'

magic('id', el => (name, key = null) => {
let root = closestIdRoot(el, name)
magic('id', (el, { cleanup }) => (name, key = null) => {
let cacheKey = `${name}${key ? `-${key}` : ''}`

let id = root
? root._x_ids[name]
: findAndIncrementId(name)
return cacheIdByNameOnElement(el, cacheKey, cleanup, () => {
let root = closestIdRoot(el, name)

return key
? `${name}-${id}-${key}`
: `${name}-${id}`
let id = root
? root._x_ids[name]
: findAndIncrementId(name)

return key
? `${name}-${id}-${key}`
: `${name}-${id}`
})
})

interceptClone((from, to) => {
// Transfer over existing ID registrations from
// the existing dom tree over to the new one
// so that there aren't ID mismatches...
if (from._x_id) {
to._x_id = from._x_id
}
})

function cacheIdByNameOnElement(el, cacheKey, cleanup, callback)
{
if (! el._x_id) el._x_id = {}

// We only want $id to run once per an element's lifecycle...
if (el._x_id[cacheKey]) return el._x_id[cacheKey]

let output = callback()

el._x_id[cacheKey] = output

cleanup(() => {
delete el._x_id[cacheKey]
})

return output
}
35 changes: 10 additions & 25 deletions packages/alpinejs/src/magics/$watch.js
Original file line number Diff line number Diff line change
@@ -1,34 +1,19 @@
import { magic } from '../magics'
import { effect, release, watch } from '../reactivity'

magic('watch', (el, { evaluateLater, effect }) => (key, callback) => {
magic('watch', (el, { evaluateLater, cleanup }) => (key, callback) => {
let evaluate = evaluateLater(key)

let firstTime = true
let getter = () => {
let value

let oldValue
evaluate(i => value = i)

let effectReference = effect(() => evaluate(value => {
// JSON.stringify touches every single property at any level enabling deep watching
JSON.stringify(value)
return value
}

if (! firstTime) {
// We have to queue this watcher as a microtask so that
// the watcher doesn't pick up its own dependencies.
queueMicrotask(() => {
callback(value, oldValue)
let unwatch = watch(getter, callback)

oldValue = value
})
} else {
oldValue = value
}

firstTime = false
}))

// We want to remove this effect from the list of effects
// stored on an element. Livewire uses that list to
// "re-run" Alpine effects after a page load. A "watcher"
// shuldn't be re-run like that. It will cause infinite loops.
el._x_effects.delete(effectReference)
cleanup(unwatch)
})

43 changes: 18 additions & 25 deletions packages/alpinejs/src/mutation.js
Original file line number Diff line number Diff line change
@@ -65,27 +65,24 @@ export function stopObservingMutations() {
currentlyObserving = false
}

let recordQueue = []
let willProcessRecordQueue = false
let queuedMutations = []

export function flushObserver() {
recordQueue = recordQueue.concat(observer.takeRecords())
let records = observer.takeRecords()

if (recordQueue.length && ! willProcessRecordQueue) {
willProcessRecordQueue = true
queuedMutations.push(() => records.length > 0 && onMutate(records))

queueMicrotask(() => {
processRecordQueue()
let queueLengthWhenTriggered = queuedMutations.length

willProcessRecordQueue = false
})
}
}

function processRecordQueue() {
onMutate(recordQueue)

recordQueue.length = 0
queueMicrotask(() => {
// If these two lengths match, then we KNOW that this is the LAST
// flush in the current event loop. This way, we can process
// all mutations in one batch at the end of everything...
if (queuedMutations.length === queueLengthWhenTriggered) {
// Now Alpine can process all the mutations...
while (queuedMutations.length > 0) queuedMutations.shift()()
}
})
}

export function mutateDom(callback) {
@@ -122,17 +119,17 @@ function onMutate(mutations) {
return
}

let addedNodes = []
let removedNodes = []
let addedNodes = new Set
let removedNodes = new Set
let addedAttributes = new Map
let removedAttributes = new Map

for (let i = 0; i < mutations.length; i++) {
if (mutations[i].target._x_ignoreMutationObserver) continue

if (mutations[i].type === 'childList') {
mutations[i].addedNodes.forEach(node => node.nodeType === 1 && addedNodes.push(node))
mutations[i].removedNodes.forEach(node => node.nodeType === 1 && removedNodes.push(node))
mutations[i].addedNodes.forEach(node => node.nodeType === 1 && addedNodes.add(node))
mutations[i].removedNodes.forEach(node => node.nodeType === 1 && removedNodes.add(node))
}

if (mutations[i].type === 'attributes') {
@@ -177,7 +174,7 @@ function onMutate(mutations) {
for (let node of removedNodes) {
// If an element gets moved on a page, it's registered
// as both an "add" and "remove", so we want to skip those.
if (addedNodes.includes(node)) continue
if (addedNodes.has(node)) continue

onElRemoveds.forEach(i => i(node))

@@ -197,10 +194,6 @@ function onMutate(mutations) {
node._x_ignore = true
})
for (let node of addedNodes) {
// If an element gets moved on a page, it's registered
// as both an "add" and "remove", so we want to skip those.
if (removedNodes.includes(node)) continue

// If the node was eventually removed as part of one of his
// parent mutations, skip it
if (! node.isConnected) continue
29 changes: 29 additions & 0 deletions packages/alpinejs/src/reactivity.js
Original file line number Diff line number Diff line change
@@ -56,6 +56,35 @@ export function elementBoundEffect(el) {
return [wrappedEffect, () => { cleanup() }]
}

export function watch(getter, callback) {
let firstTime = true

let oldValue

let effectReference = effect(() => {
let value = getter()

// JSON.stringify touches every single property at any level enabling deep watching
JSON.stringify(value)

if (! firstTime) {
// We have to queue this watcher as a microtask so that
// the watcher doesn't pick up its own dependencies.
queueMicrotask(() => {
callback(value, oldValue)

oldValue = value
})
} else {
oldValue = value
}

firstTime = false
})

return () => release(effectReference)
}

export {
release,
reactive,
6 changes: 4 additions & 2 deletions packages/alpinejs/src/utils/error.js
Original file line number Diff line number Diff line change
@@ -6,8 +6,10 @@ export function tryCatch(el, expression, callback, ...args) {
}
}

export function handleError(error, el, expression = undefined) {
Object.assign( error, { el, expression } )
export function handleError(error , el, expression = undefined) {
error = Object.assign(
error ?? { message: 'No error message given.' },
{ el, expression } )

console.warn(`Alpine Expression Error: ${error.message}\n\n${ expression ? 'Expression: \"' + expression + '\"\n\n' : '' }`, el)

2 changes: 2 additions & 0 deletions packages/anchor/builds/module.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import anchor from '../src/index.js'

export default anchor

export { anchor }
2 changes: 1 addition & 1 deletion packages/anchor/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@alpinejs/anchor",
"version": "3.13.3",
"version": "3.13.4",
"description": "Anchor an element's position relative to another",
"homepage": "https://alpinejs.dev/plugins/anchor",
"repository": {
2 changes: 2 additions & 0 deletions packages/collapse/builds/module.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import collapse from '../src/index.js'

export default collapse

export { collapse }
2 changes: 1 addition & 1 deletion packages/collapse/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@alpinejs/collapse",
"version": "3.13.3",
"version": "3.13.4",
"description": "Collapse and expand elements with robust animations",
"homepage": "https://alpinejs.dev/plugins/collapse",
"repository": {
2 changes: 2 additions & 0 deletions packages/csp/builds/module.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import Alpine from './../src/index'

export default Alpine

export { Alpine }
6 changes: 3 additions & 3 deletions packages/csp/package.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
{
"name": "@alpinejs/csp",
"version": "3.0.0-alpha.0",
"description": "A CSP compatible build of Alpine",
"version": "3.13.4",
"description": "A CSP-friendly build of AlpineJS",
"author": "Caleb Porzio",
"license": "MIT",
"main": "dist/module.cjs.js",
"module": "dist/module.esm.js",
"dependencies": {
"@vue/reactivity": "^3.0.2"
"@vue/reactivity": "~3.1.1"
}
}
Loading