0.0.3: Exotic Type Gymnastics #3
76
src/main.ts
76
src/main.ts
|
@ -47,80 +47,22 @@ export default (options: ComponentOptions) => {
|
||||||
this._initialize()
|
this._initialize()
|
||||||
}
|
}
|
||||||
|
|
||||||
private _initState() {
|
private _initialize() {
|
||||||
// copy state from options
|
// initialize state
|
||||||
this._states = new Proxy(
|
this._states = utils.initState(
|
||||||
{ ...(states || {}) },
|
|
||||||
{
|
{
|
||||||
set: (
|
|
||||||
target: Record<string, unknown>,
|
|
||||||
keyPath: string,
|
|
||||||
value: unknown,
|
|
||||||
) => {
|
|
||||||
const valueRoute = keyPath.split('.')
|
|
||||||
let currentTarget = target
|
|
||||||
for (const i in valueRoute) {
|
|
||||||
const key = valueRoute[i]
|
|
||||||
if (Number.parseInt(i) === valueRoute.length - 1) {
|
|
||||||
currentTarget[key] = value
|
|
||||||
} else {
|
|
||||||
if (!currentTarget[key]) currentTarget[key] = {}
|
|
||||||
currentTarget = currentTarget[key] as Record<string, unknown>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// trigger dom updates
|
|
||||||
utils.triggerDomUpdates(keyPath, {
|
|
||||||
stateToElementsMap: this._stateToElementsMap,
|
stateToElementsMap: this._stateToElementsMap,
|
||||||
textBindings: this._textBindings,
|
textBindings: this._textBindings,
|
||||||
attributeBindings: this._attributeBindings,
|
attributeBindings: this._attributeBindings,
|
||||||
updateTextNode: this._updateTextNode.bind(this),
|
updateTextNode: (node: Text, value: string) => this._updateTextNode(node, value, value),
|
||||||
getNestedState: this._getNestedState.bind(this),
|
getNestedState: (keyPath: string) => this._getNestedState(keyPath),
|
||||||
scheduleUpdate: this._scheduleUpdate.bind(this),
|
scheduleUpdate: this._scheduleUpdate.bind(this),
|
||||||
})
|
statesListeners: this._statesListeners,
|
||||||
if (this._statesListeners[keyPath])
|
conditionalElements: this._conditionalElements,
|
||||||
this._statesListeners[keyPath](value)
|
evaluateIfCondition: this._evaluateIfCondition.bind(this),
|
||||||
|
|
||||||
// trigger %if macros
|
|
||||||
if (this._conditionalElements.size > 0)
|
|
||||||
this._conditionalElements.forEach((info, element) => {
|
|
||||||
if (info.expr.includes(keyPath))
|
|
||||||
this._evaluateIfCondition(element, info.expr)
|
|
||||||
})
|
|
||||||
|
|
||||||
// trigger state update events
|
|
||||||
statesListeners?.[keyPath]?.(value)
|
|
||||||
|
|
||||||
return true
|
|
||||||
},
|
},
|
||||||
get: (target: Record<string, unknown>, keyPath: string) => {
|
options.states,
|
||||||
// collect state dependencies
|
|
||||||
if (this._currentRenderingElement) {
|
|
||||||
if (!this._stateToElementsMap[keyPath])
|
|
||||||
this._stateToElementsMap[keyPath] = new Set()
|
|
||||||
this._stateToElementsMap[keyPath].add(
|
|
||||||
this._currentRenderingElement,
|
|
||||||
)
|
)
|
||||||
}
|
|
||||||
|
|
||||||
const valueRoute = keyPath.split('.')
|
|
||||||
let currentTarget = target
|
|
||||||
for (const i in valueRoute) {
|
|
||||||
const key = valueRoute[i]
|
|
||||||
if (Number.parseInt(i) === valueRoute.length - 1)
|
|
||||||
return currentTarget[key]
|
|
||||||
|
|
||||||
if (!currentTarget[key]) currentTarget[key] = {}
|
|
||||||
currentTarget = currentTarget[key] as Record<string, unknown>
|
|
||||||
}
|
|
||||||
return undefined
|
|
||||||
},
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private _initialize() {
|
|
||||||
// initialize state
|
|
||||||
this._initState()
|
|
||||||
|
|
||||||
// initialize shadow dom
|
// initialize shadow dom
|
||||||
const shadow = this.attachShadow({ mode: 'open' })
|
const shadow = this.attachShadow({ mode: 'open' })
|
||||||
|
|
|
@ -2,10 +2,12 @@ import parseTemplate from './parseTemplate'
|
||||||
import processTemplateMacros from './processTemplateMarcos'
|
import processTemplateMacros from './processTemplateMarcos'
|
||||||
import setupArrowFunctionHandler from './setupArrowFunctionHandler'
|
import setupArrowFunctionHandler from './setupArrowFunctionHandler'
|
||||||
import triggerDomUpdates from './triggerDomUpdates'
|
import triggerDomUpdates from './triggerDomUpdates'
|
||||||
|
import initState from './initState'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
parseTemplate,
|
parseTemplate,
|
||||||
processTemplateMacros,
|
processTemplateMacros,
|
||||||
setupArrowFunctionHandler,
|
setupArrowFunctionHandler,
|
||||||
triggerDomUpdates,
|
triggerDomUpdates,
|
||||||
|
initState,
|
||||||
}
|
}
|
||||||
|
|
103
src/utils/initState.ts
Normal file
103
src/utils/initState.ts
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
import triggerDomUpdates from "./triggerDomUpdates"
|
||||||
|
|
||||||
|
export default function initState(
|
||||||
|
ops: {
|
||||||
|
stateToElementsMap: Record<string, Set<HTMLElement>>
|
||||||
|
textBindings: Array<{
|
||||||
|
node: Text
|
||||||
|
expr: string
|
||||||
|
originalContent: string
|
||||||
|
}>
|
||||||
|
attributeBindings: Array<{
|
||||||
|
element: Element
|
||||||
|
attrName: string
|
||||||
|
expr: string
|
||||||
|
template: string
|
||||||
|
}>
|
||||||
|
updateTextNode: (node: Text, value: string) => void
|
||||||
|
getNestedState: (keyPath: string) => unknown
|
||||||
|
scheduleUpdate: (elements: Set<HTMLElement>) => void
|
||||||
|
statesListeners: Record<string, (value: unknown) => void>
|
||||||
|
conditionalElements: Map<
|
||||||
|
Element,
|
||||||
|
{
|
||||||
|
expr: string
|
||||||
|
placeholder: Comment
|
||||||
|
isPresent: boolean
|
||||||
|
}
|
||||||
|
>
|
||||||
|
evaluateIfCondition: (element: Element, expr: string) => void
|
||||||
|
currentRenderingElement?: HTMLElement
|
||||||
|
},
|
||||||
|
states?: Record<string, unknown>,
|
||||||
|
) {
|
||||||
|
console.log(states)
|
||||||
|
// copy state from options
|
||||||
|
return new Proxy(
|
||||||
|
{ ...(states || {}) },
|
||||||
|
{
|
||||||
|
set: (
|
||||||
|
target: Record<string, unknown>,
|
||||||
|
keyPath: string,
|
||||||
|
value: unknown,
|
||||||
|
) => {
|
||||||
|
const valueRoute = keyPath.split('.')
|
||||||
|
let currentTarget = target
|
||||||
|
for (const i in valueRoute) {
|
||||||
|
const key = valueRoute[i]
|
||||||
|
if (Number.parseInt(i) === valueRoute.length - 1) {
|
||||||
|
currentTarget[key] = value
|
||||||
|
} else {
|
||||||
|
if (!currentTarget[key]) currentTarget[key] = {}
|
||||||
|
currentTarget = currentTarget[key] as Record<string, unknown>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// trigger dom updates
|
||||||
|
triggerDomUpdates(keyPath, {
|
||||||
|
stateToElementsMap: ops.stateToElementsMap,
|
||||||
|
textBindings: ops.textBindings,
|
||||||
|
attributeBindings: ops.attributeBindings,
|
||||||
|
updateTextNode: ops.updateTextNode,
|
||||||
|
getNestedState: ops.getNestedState,
|
||||||
|
scheduleUpdate: ops.scheduleUpdate,
|
||||||
|
})
|
||||||
|
if (ops.statesListeners[keyPath])
|
||||||
|
ops.statesListeners[keyPath](value)
|
||||||
|
|
||||||
|
// trigger %if macros
|
||||||
|
if (ops.conditionalElements.size > 0)
|
||||||
|
ops.conditionalElements.forEach((info, element) => {
|
||||||
|
if (info.expr.includes(keyPath))
|
||||||
|
ops.evaluateIfCondition(element, info.expr)
|
||||||
|
})
|
||||||
|
|
||||||
|
// trigger state update events
|
||||||
|
ops.statesListeners?.[keyPath]?.(value)
|
||||||
|
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
get: (target: Record<string, unknown>, keyPath: string) => {
|
||||||
|
// collect state dependencies
|
||||||
|
if (ops.currentRenderingElement) {
|
||||||
|
if (!ops.stateToElementsMap[keyPath])
|
||||||
|
ops.stateToElementsMap[keyPath] = new Set()
|
||||||
|
ops.stateToElementsMap[keyPath].add(
|
||||||
|
ops.currentRenderingElement,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const valueRoute = keyPath.split('.')
|
||||||
|
let currentTarget = target
|
||||||
|
for (const i in valueRoute) {
|
||||||
|
const key = valueRoute[i]
|
||||||
|
if (Number.parseInt(i) === valueRoute.length - 1)
|
||||||
|
return currentTarget[key]
|
||||||
|
|
||||||
|
if (!currentTarget[key]) currentTarget[key] = {}
|
||||||
|
currentTarget = currentTarget[key] as Record<string, unknown>
|
||||||
|
}
|
||||||
|
return undefined
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user