Files
parcoursup/node_modules/@riotjs/dom-bindings/src/bindings/slot.js
lalBi94 7bc56c09b5 $
2023-03-05 13:23:23 +01:00

103 lines
2.7 KiB
JavaScript

import {cleanNode, insertBefore, removeChild} from '@riotjs/util/dom'
import {PARENT_KEY_SYMBOL} from '@riotjs/util/constants'
import {evaluateAttributeExpressions} from '@riotjs/util/misc'
import template from '../template'
function extendParentScope(attributes, scope, parentScope) {
if (!attributes || !attributes.length) return parentScope
const expressions = attributes.map(attr => ({
...attr,
value: attr.evaluate(scope)
}))
return Object.assign(
Object.create(parentScope || null),
evaluateAttributeExpressions(expressions)
)
}
// this function is only meant to fix an edge case
// https://github.com/riot/riot/issues/2842
const getRealParent = (scope, parentScope) => scope[PARENT_KEY_SYMBOL] || parentScope
export const SlotBinding = {
// dynamic binding properties
// node: null,
// name: null,
attributes: [],
// template: null,
getTemplateScope(scope, parentScope) {
return extendParentScope(this.attributes, scope, parentScope)
},
// API methods
mount(scope, parentScope) {
const templateData = scope.slots ? scope.slots.find(({id}) => id === this.name) : false
const {parentNode} = this.node
const realParent = getRealParent(scope, parentScope)
this.template = templateData && template(
templateData.html,
templateData.bindings
).createDOM(parentNode)
if (this.template) {
cleanNode(this.node)
this.template.mount(this.node, this.getTemplateScope(scope, realParent), realParent)
this.template.children = Array.from(this.node.childNodes)
}
moveSlotInnerContent(this.node)
removeChild(this.node)
return this
},
update(scope, parentScope) {
if (this.template) {
const realParent = getRealParent(scope, parentScope)
this.template.update(this.getTemplateScope(scope, realParent), realParent)
}
return this
},
unmount(scope, parentScope, mustRemoveRoot) {
if (this.template) {
this.template.unmount(this.getTemplateScope(scope, parentScope), null, mustRemoveRoot)
}
return this
}
}
/**
* Move the inner content of the slots outside of them
* @param {HTMLElement} slot - slot node
* @returns {undefined} it's a void method ¯\_(ツ)_/¯
*/
function moveSlotInnerContent(slot) {
const child = slot && slot.firstChild
if (!child) return
insertBefore(child, slot)
moveSlotInnerContent(slot)
}
/**
* Create a single slot binding
* @param {HTMLElement} node - slot node
* @param {string} name - slot id
* @param {AttributeExpressionData[]} attributes - slot attributes
* @returns {Object} Slot binding object
*/
export default function createSlot(node, { name, attributes }) {
return {
...SlotBinding,
attributes,
node,
name
}
}