Comparing version 0.3.5 to 0.3.6
@@ -67,18 +67,10 @@ 'use strict'; | ||
var DIRECTIVE_PREFIX = 'l-'; | ||
var LUCIA_COMPILE_REQUEST = '%LUCIA_COMPILE_REQUEST%'; | ||
var LUCIA_FIRST_RENDER = '%LUCIA_FIRST_RENDER%'; | ||
var DIRECTIVE_SHORTHANDS; | ||
(function (DIRECTIVE_SHORTHANDS) { | ||
DIRECTIVE_SHORTHANDS["@"] = "ON"; | ||
DIRECTIVE_SHORTHANDS[":"] = "BIND"; | ||
DIRECTIVE_SHORTHANDS["@"] = "on"; | ||
DIRECTIVE_SHORTHANDS[":"] = "bind"; | ||
})(DIRECTIVE_SHORTHANDS || (DIRECTIVE_SHORTHANDS = {})); | ||
var VNodeTypes; | ||
(function (VNodeTypes) { | ||
VNodeTypes[VNodeTypes["STATIC"] = 0] = "STATIC"; | ||
VNodeTypes[VNodeTypes["NEEDS_PATCH"] = 1] = "NEEDS_PATCH"; | ||
VNodeTypes[VNodeTypes["DYNAMIC"] = 2] = "DYNAMIC"; | ||
})(VNodeTypes || (VNodeTypes = {})); | ||
var rawDirectiveSplitPattern = /:|\./; | ||
var selectorSplitPattern = /(?=\.)|(?=#)|(?=\[)/; | ||
var keyPattern = function (key, hasThis) { | ||
@@ -89,42 +81,195 @@ if (hasThis === void 0) { hasThis = true; } | ||
var h = function (selector, children, props) { | ||
var e_1, _a; | ||
var tokens = selector.split(selectorSplitPattern); | ||
var tag = tokens[0]; | ||
var attributes = __assign({}, props === null || props === void 0 ? void 0 : props.attributes); | ||
var directives = __assign({}, props === null || props === void 0 ? void 0 : props.directives); | ||
if (tokens.length > 1) { | ||
tokens.shift(); | ||
try { | ||
for (var tokens_1 = __values(tokens), tokens_1_1 = tokens_1.next(); !tokens_1_1.done; tokens_1_1 = tokens_1.next()) { | ||
var token = tokens_1_1.value; | ||
switch (token[0]) { | ||
case '#': | ||
attributes.id = token.slice(1); | ||
break; | ||
case '.': | ||
if (!attributes.className) | ||
attributes.className = ''; | ||
attributes.className += token.slice(1) + " "; | ||
break; | ||
case '[': | ||
var _b = __read(token.slice(1, -1).split('='), 2), key = _b[0], value = _b[1]; | ||
if (key.startsWith(DIRECTIVE_PREFIX)) { | ||
directives[key.slice(DIRECTIVE_PREFIX.length)] = value; | ||
} | ||
else { | ||
attributes[key] = value; | ||
} | ||
break; | ||
var bindDirective = function (_a) { | ||
var el = _a.el, name = _a.name, data = _a.data, app = _a.app; | ||
switch (name.split(':')[1]) { | ||
case 'class': | ||
var hydratedClasses = data.compute(app.state); | ||
if (typeof hydratedClasses === 'string') { | ||
return el.setAttribute('class', (el.className + " " + hydratedClasses).trim()); | ||
} | ||
else if (hydratedClasses instanceof Array) { | ||
return el.setAttribute('class', (el.className + " " + hydratedClasses.join(' ')).trim()); | ||
} | ||
else { | ||
var classes = []; | ||
for (var key in hydratedClasses) { | ||
if (hydratedClasses[key]) | ||
classes.push(key); | ||
} | ||
if (classes.length > 0) { | ||
return el.setAttribute('class', (el.className + " " + classes.join(' ').trim()).trim()); | ||
} | ||
else if (el.className.trim().length > 0) { | ||
return el.setAttribute('class', el.className); | ||
} | ||
else { | ||
return el.removeAttribute('class'); | ||
} | ||
} | ||
} | ||
catch (e_1_1) { e_1 = { error: e_1_1 }; } | ||
finally { | ||
try { | ||
if (tokens_1_1 && !tokens_1_1.done && (_a = tokens_1.return)) _a.call(tokens_1); | ||
case 'style': | ||
var hydratedStyles = data.compute(app.state); | ||
el.removeAttribute('style'); | ||
for (var key in hydratedStyles) { | ||
el.style[key] = hydratedStyles[key]; | ||
} | ||
finally { if (e_1) throw e_1.error; } | ||
break; | ||
default: | ||
var hydratedAttributes = data.compute(app.state); | ||
if (typeof hydratedAttributes === 'object' && hydratedAttributes !== null) { | ||
for (var key in hydratedAttributes) { | ||
if (hydratedAttributes[key]) { | ||
el.setAttribute(key, hydratedAttributes[key]); | ||
} | ||
else { | ||
el.removeAttribute(key); | ||
} | ||
} | ||
} | ||
else if (hydratedAttributes) { | ||
el.setAttribute(name.split(':')[1], hydratedAttributes); | ||
} | ||
else { | ||
el.removeAttribute(name.split(':')[1]); | ||
} | ||
break; | ||
} | ||
}; | ||
var htmlDirective = function (_a) { | ||
var _b; | ||
var el = _a.el, data = _a.data, app = _a.app; | ||
el.innerHTML = (_b = data.compute(app.state)) !== null && _b !== void 0 ? _b : data.value; | ||
var scope = createApp(__assign({}, app.state)); | ||
Object.entries(app.directives || {}).map(function (_a) { | ||
var _b = __read(_a, 2), name = _b[0], evaluationCallback = _b[1]; | ||
scope.directive(name, evaluationCallback); | ||
}); | ||
Object.entries(app.components || {}).map(function (_a) { | ||
var _b = __read(_a, 2), name = _b[0], templateCallback = _b[1]; | ||
scope.component(name, templateCallback); | ||
}); | ||
scope.mount(el); | ||
}; | ||
var ifDirective = function (_a) { | ||
var el = _a.el, data = _a.data, app = _a.app; | ||
var hydratedConditional = data.compute(app.state); | ||
if (hydratedConditional) { | ||
el.style.removeProperty('display'); | ||
} | ||
else { | ||
el.style.display = 'none'; | ||
} | ||
}; | ||
function createComputeFunction(state) { | ||
try { | ||
var expression = this.returnable ? "return " + this.expression : this.expression; | ||
return new (Function.bind.apply(Function, __spread([void 0], Object.keys(this.argsKV), [expression])))().bind(state).apply(void 0, __spread(Object.values(this.argsKV))); | ||
} | ||
catch (err) { | ||
console.warn("Lucia Error: \"" + err + "\"\n\nExpression: \"" + this.expression + "\"\nElement:", this.argsKV.$el); | ||
} | ||
} | ||
var compute = function (expression, data, returnable) { | ||
if (returnable === void 0) { returnable = true; } | ||
return createComputeFunction.bind({ expression: expression, argsKV: { $el: data.$el }, returnable: returnable }); | ||
}; | ||
var joinDirective = function (_a) { | ||
var el = _a.el, data = _a.data, app = _a.app; | ||
var _b = __read(data.value.split(/ as | by /), 3), array = _b[0], contentType = _b[1], delimiter = _b[2]; | ||
var hydratedArray = compute(array, { $el: el })(app.state); | ||
var accessProp = contentType === 'text' ? 'innerText' : 'innerHTML'; | ||
el[accessProp] = hydratedArray.join(delimiter || ''); | ||
var scope = createApp(__assign({}, app.state)); | ||
Object.entries(app.directives || {}).map(function (_a) { | ||
var _b = __read(_a, 2), name = _b[0], evaluationCallback = _b[1]; | ||
scope.directive(name, evaluationCallback); | ||
}); | ||
Object.entries(app.components || {}).map(function (_a) { | ||
var _b = __read(_a, 2), name = _b[0], templateCallback = _b[1]; | ||
scope.component(name, templateCallback); | ||
}); | ||
scope.mount(el); | ||
}; | ||
var modelDirective = function (_a) { | ||
var awaitingTypecastEl = _a.el, data = _a.data, app = _a.app; | ||
var el = awaitingTypecastEl; | ||
var hydratedValue = compute(data.compute(), { $el: el })(app.state); | ||
if (el.value !== hydratedValue) { | ||
el.value = hydratedValue; | ||
} | ||
el.oninput = function () { | ||
var isNumber = typeof hydratedValue === 'number' && !isNaN(el.value); | ||
var isBoolean = typeof hydratedValue === 'boolean' && (el.value === 'true' || el.value === 'false'); | ||
var isNullish = (hydratedValue === null || hydratedValue === undefined) && | ||
(el.value === 'null' || el.value === 'undefined'); | ||
var payload; | ||
if (isNumber) { | ||
payload = "Number('" + el.value + "').toPrecision()"; | ||
} | ||
} | ||
else if (isBoolean) { | ||
payload = "Boolean('" + el.value + "')"; | ||
} | ||
else if (isNullish) { | ||
if (el.value === 'null') | ||
payload = null; | ||
else | ||
payload = undefined; | ||
} | ||
else { | ||
payload = "'" + el.value + "'"; | ||
} | ||
compute(data.value + " = " + payload, { $el: el }, false)(app.state); | ||
}; | ||
}; | ||
var onDirective = function (_a) { | ||
var el = _a.el, name = _a.name, data = _a.data, app = _a.app; | ||
var _b = __read(name.split('.'), 2), directiveAndEventName = _b[0], prop = _b[1]; | ||
var eventName = directiveAndEventName.split(':')[1]; | ||
var eventProp = prop || null; | ||
el["on" + eventName] = function ($event) { | ||
if (eventProp === 'prevent') | ||
$event.preventDefault(); | ||
if (eventProp === 'stop') | ||
$event.stopPropagation(); | ||
data.compute(app.state); | ||
}; | ||
}; | ||
var textDirective = function (_a) { | ||
var _b; | ||
var el = _a.el, data = _a.data, app = _a.app; | ||
el.textContent = (_b = data.compute(app.state)) !== null && _b !== void 0 ? _b : data.value; | ||
}; | ||
var directives = { | ||
BIND: bindDirective, | ||
JOIN: joinDirective, | ||
HTML: htmlDirective, | ||
IF: ifDirective, | ||
MODEL: modelDirective, | ||
ON: onDirective, | ||
TEXT: textDirective, | ||
}; | ||
var renderDirective = function (props, directives) { | ||
var name = props.name.split(rawDirectiveSplitPattern)[0]; | ||
directives[name.toUpperCase()](props); | ||
}; | ||
var VNodeTypes; | ||
(function (VNodeTypes) { | ||
VNodeTypes[VNodeTypes["STATIC"] = 0] = "STATIC"; | ||
VNodeTypes[VNodeTypes["NEEDS_PATCH"] = 1] = "NEEDS_PATCH"; | ||
VNodeTypes[VNodeTypes["DYNAMIC"] = 2] = "DYNAMIC"; | ||
})(VNodeTypes || (VNodeTypes = {})); | ||
var h = function (tag, children, props) { | ||
if (children === void 0) { children = []; } | ||
var attributes = __assign({}, props === null || props === void 0 ? void 0 : props.attributes); | ||
var directives = __assign({}, props === null || props === void 0 ? void 0 : props.directives); | ||
children = children instanceof Array ? children : [children]; | ||
if (attributes.className) | ||
@@ -134,3 +279,3 @@ attributes.className = attributes.className.trim(); | ||
tag: tag, | ||
children: typeof children === 'string' ? [children] : children ? children : [], | ||
children: children, | ||
props: { | ||
@@ -153,7 +298,8 @@ attributes: attributes, | ||
var _d = _c.value, name_1 = _d.name, value = _d.value; | ||
var directiveData = { compute: compute(value, { $el: el }), value: value }; | ||
if (name_1.startsWith(DIRECTIVE_PREFIX)) { | ||
directives[name_1.slice(DIRECTIVE_PREFIX.length)] = value; | ||
directives[name_1.slice(DIRECTIVE_PREFIX.length)] = directiveData; | ||
} | ||
else if (Object.keys(DIRECTIVE_SHORTHANDS).includes(name_1[0])) { | ||
directives[DIRECTIVE_SHORTHANDS[name_1[0]] + ":" + name_1.slice(1)] = value; | ||
directives[DIRECTIVE_SHORTHANDS[name_1[0]] + ":" + name_1.slice(1)] = directiveData; | ||
} | ||
@@ -180,3 +326,4 @@ else { | ||
var hasDirectives = Object.keys(directives).length > 0; | ||
var hasKeyInDirectives = Object.values(directives).some(function (value) { | ||
var hasKeyInDirectives = Object.values(directives).some(function (_a) { | ||
var value = _a.value; | ||
return Object.keys(state).some(function (key) { return keyPattern(key, false).test(value); }); | ||
@@ -225,4 +372,4 @@ }); | ||
for (var _e = (e_2 = void 0, __values(Object.entries(props(child).directives))), _f = _e.next(); !_f.done; _f = _e.next()) { | ||
var _g = __read(_f.value, 2), key = _g[0], value = _g[1]; | ||
(_d = container.firstElementChild) === null || _d === void 0 ? void 0 : _d.setAttribute("" + DIRECTIVE_PREFIX + key, value); | ||
var _g = __read(_f.value, 2), key = _g[0], data = _g[1]; | ||
(_d = container.firstElementChild) === null || _d === void 0 ? void 0 : _d.setAttribute("" + DIRECTIVE_PREFIX + key, data.value); | ||
} | ||
@@ -321,162 +468,2 @@ } | ||
var safeEval = function (expression, argsKV, bindKV, returnable) { | ||
if (argsKV === void 0) { argsKV = {}; } | ||
if (bindKV === void 0) { bindKV = {}; } | ||
if (returnable === void 0) { returnable = true; } | ||
return new (Function.bind.apply(Function, __spread([void 0], Object.keys(argsKV), [returnable ? "return " + expression : expression])))().bind(bindKV).apply(void 0, __spread(Object.values(argsKV))); | ||
}; | ||
var computeProperties = function (expression, data, returnable) { | ||
if (returnable === void 0) { returnable = true; } | ||
return safeEval(expression, { $el: data.$el }, data.$state, returnable); | ||
}; | ||
var bindDirective = function (_a) { | ||
var el = _a.el, name = _a.name, value = _a.value, state = _a.state; | ||
switch (name.split(':')[1]) { | ||
case 'class': | ||
var classState = computeProperties(value, { $state: state, $el: el }); | ||
if (typeof classState === 'string') { | ||
return el.setAttribute('class', (el.className + " " + classState).trim()); | ||
} | ||
if (classState instanceof Array) { | ||
return el.setAttribute('class', (el.className + " " + classState.join(' ')).trim()); | ||
} | ||
else { | ||
var classes = []; | ||
for (var key in classState) { | ||
if (classState[key]) | ||
classes.push(key); | ||
} | ||
if (classes.length > 0) { | ||
return el.setAttribute('class', (el.className + " " + classes.join(' ').trim()).trim()); | ||
} | ||
else if (el.className.trim().length > 0) { | ||
return el.setAttribute('class', el.className); | ||
} | ||
else { | ||
return el.removeAttribute('class'); | ||
} | ||
} | ||
case 'style': | ||
var styleState = computeProperties(value, { $state: state, $el: el }); | ||
el.removeAttribute('style'); | ||
for (var key in styleState) { | ||
el.style[key] = styleState[key]; | ||
} | ||
break; | ||
default: | ||
var out = computeProperties(value, { $state: state, $el: el }); | ||
if (out) { | ||
el.setAttribute(name.split(':')[1], out); | ||
} | ||
else { | ||
el.removeAttribute(name.split(':')[1]); | ||
} | ||
break; | ||
} | ||
}; | ||
var htmlDirective = function (_a) { | ||
var el = _a.el, value = _a.value, state = _a.state; | ||
var app = createApp(__assign({}, state)); | ||
app.mount(el, true); | ||
try { | ||
el.innerHTML = computeProperties(value, { $state: state, $el: el }); | ||
} | ||
catch (_b) { | ||
el.innerHTML = value; | ||
} | ||
}; | ||
var ifDirective = function (_a) { | ||
var el = _a.el, value = _a.value, state = _a.state; | ||
var out = computeProperties(value, { $state: state, $el: el }); | ||
if (out) { | ||
el.style.removeProperty('display'); | ||
} | ||
else { | ||
el.style.display = 'none'; | ||
} | ||
}; | ||
var joinDirective = function (_a) { | ||
var el = _a.el, value = _a.value, state = _a.state; | ||
var _b = __read(value.split(/ as | by /), 3), array = _b[0], contentType = _b[1], delimiter = _b[2]; | ||
var out = computeProperties(array, { $state: state, $el: el }); | ||
var accessProp = contentType === 'text' ? 'innerText' : 'innerHTML'; | ||
el[accessProp] = out.join(delimiter || ''); | ||
var app = createApp(__assign({}, state)); | ||
app.mount(el, true); | ||
}; | ||
var modelDirective = function (_a) { | ||
var awaitingTypecastEl = _a.el, value = _a.value, state = _a.state; | ||
var el = awaitingTypecastEl; | ||
var out = computeProperties(value, { $state: state, $el: el }); | ||
if (el.value !== out) { | ||
el.value = out; | ||
} | ||
el.oninput = function () { | ||
var isNumber = typeof out === 'number' && !isNaN(el.value); | ||
var isBoolean = typeof out === 'boolean' && (el.value === 'true' || el.value === 'false'); | ||
var isNullish = (out === null || out === undefined) && (el.value === 'null' || el.value === 'undefined'); | ||
var payload; | ||
if (isNumber) { | ||
payload = "Number('" + el.value + "').toPrecision()"; | ||
} | ||
else if (isBoolean) { | ||
payload = "Boolean('" + el.value + "')"; | ||
} | ||
else if (isNullish) { | ||
if (el.value === 'null') | ||
payload = null; | ||
else | ||
payload = undefined; | ||
} | ||
else { | ||
payload = "'" + el.value + "'"; | ||
} | ||
computeProperties(value + " = " + payload, { $state: state, $el: el }, false); | ||
}; | ||
}; | ||
var onDirective = function (_a) { | ||
var el = _a.el, name = _a.name, value = _a.value, state = _a.state; | ||
var _b = __read(name.split('.'), 2), directiveAndEventName = _b[0], prop = _b[1]; | ||
var eventName = directiveAndEventName.split(':')[1]; | ||
var eventProp = prop || null; | ||
el["on" + eventName] = function ($event) { | ||
if (eventProp === 'prevent') | ||
$event.preventDefault(); | ||
if (eventProp === 'stop') | ||
$event.stopPropagation(); | ||
computeProperties(value, { $state: state, $el: el }, false); | ||
}; | ||
}; | ||
var textDirective = function (_a) { | ||
var el = _a.el, value = _a.value, state = _a.state; | ||
try { | ||
el.innerHTML = computeProperties(value, { $state: state, $el: el }); | ||
} | ||
catch (_b) { | ||
el.innerHTML = value; | ||
} | ||
}; | ||
var directives = { | ||
BIND: bindDirective, | ||
JOIN: joinDirective, | ||
HTML: htmlDirective, | ||
IF: ifDirective, | ||
MODEL: modelDirective, | ||
ON: onDirective, | ||
TEXT: textDirective, | ||
}; | ||
var renderDirective = function (_a, directives) { | ||
var el = _a.el, name = _a.name, value = _a.value, state = _a.state; | ||
var rootName = name.split(rawDirectiveSplitPattern)[0]; | ||
directives[rootName.toUpperCase()]({ el: el, name: name, value: value, state: state }); | ||
}; | ||
var arrayEquals = function (firstArray, secondArray) { | ||
@@ -489,3 +476,4 @@ return (firstArray instanceof Array && | ||
var handleArray = function (target, key, state, patch) { | ||
var handlePatch = function (target, key, state, patch, needsUpdate) { | ||
if (needsUpdate === void 0) { needsUpdate = false; } | ||
if (key === 'length') { | ||
@@ -500,3 +488,4 @@ var affectedKeys = Object.keys(state).filter(function (k) { | ||
else { | ||
patch([key]); | ||
if (needsUpdate) | ||
patch([key]); | ||
return false; | ||
@@ -516,4 +505,7 @@ } | ||
set: function (target, key, value) { | ||
target[key] = value; | ||
handleArray(target, key, state, patch); | ||
var needsUpdate = target[key] !== value; | ||
if (needsUpdate) { | ||
target[key] = value; | ||
} | ||
handlePatch(target, key, state, patch, needsUpdate); | ||
return true; | ||
@@ -523,3 +515,3 @@ }, | ||
delete target[key]; | ||
handleArray(target, key, state, patch); | ||
handlePatch(target, key, state, patch); | ||
return true; | ||
@@ -531,7 +523,7 @@ }, | ||
var patch = function (rootVNode, state, directiveKV, keys) { | ||
var patch = function (rootVNode, app, keys) { | ||
var e_1, _a; | ||
if (state === void 0) { state = {}; } | ||
if (directiveKV === void 0) { directiveKV = {}; } | ||
var compileRequest = false; | ||
if (app === void 0) { app = {}; } | ||
var firstRender = false; | ||
var state = app.state || {}; | ||
if (!rootVNode) | ||
@@ -541,4 +533,4 @@ return; | ||
keys = Object.keys(state); | ||
if (keys[0] === LUCIA_COMPILE_REQUEST) | ||
compileRequest = true; | ||
if (keys[0] === LUCIA_FIRST_RENDER) | ||
firstRender = true; | ||
var _loop_1 = function (node) { | ||
@@ -550,10 +542,9 @@ if (typeof node === 'string') | ||
var affectedDirectives = []; | ||
if (!compileRequest) { | ||
if (!firstRender) { | ||
var _loop_2 = function (name_1) { | ||
var value = directives_1[name_1]; | ||
var needsInit = type === 1; | ||
var hasKey = keys.some(function (key) { return keyPattern(key).test(value.toString()); }); | ||
var hasKey = keys.some(function (key) { return keyPattern(key).test(String(directives_1[name_1].value)); }); | ||
var hasKeyInFunction = Object.keys(state).some(function (key) { | ||
var iterKeysInFunction = keys.some(function (k) { | ||
return keyPattern(k).test(state[key].toString()); | ||
return keyPattern(k).test(String(state[key])); | ||
}); | ||
@@ -571,13 +562,13 @@ return typeof state[key] === 'function' && iterKeysInFunction; | ||
node.props.type = type === VNodeTypes.NEEDS_PATCH ? VNodeTypes.STATIC : type; | ||
var directivesToRender = compileRequest | ||
var directivesToRender = firstRender | ||
? Object.keys(directives_1) | ||
: affectedDirectives; | ||
directivesToRender.map(function (name) { | ||
var value = directives_1[name]; | ||
var data = directives_1[name]; | ||
var el = (attributes_1.id ? document.getElementById(attributes_1.id) : ref_1); | ||
renderDirective({ el: el, name: name, value: value, state: state }, __assign({}, directiveKV)); | ||
renderDirective({ el: el, name: name, data: data, app: app }, __assign({}, app.directives)); | ||
}); | ||
} | ||
if (node.children.length > 0) | ||
patch(node, state, directiveKV, keys); | ||
patch(node, state, keys); | ||
}; | ||
@@ -600,31 +591,35 @@ try { | ||
var App = (function () { | ||
function App(state) { | ||
function App(state, mountHook) { | ||
if (state === void 0) { state = {}; } | ||
this.vdom = null; | ||
this.state = state; | ||
this.directives = {}; | ||
this.components = {}; | ||
this.mounted = false; | ||
this.mountHook = mountHook; | ||
} | ||
App.prototype.mount = function (el, shallow) { | ||
if (shallow === void 0) { shallow = false; } | ||
this.vdom = this.compile((typeof el === 'string' ? document.querySelector(el) : el)); | ||
var rootEl = typeof el === 'string' ? document.querySelector(el) : el; | ||
this.vdom = this.compile(rootEl); | ||
if (!shallow) { | ||
this.state = reactive(this.state, this.patch.bind(this)); | ||
this.directives = directives; | ||
this.directives = __assign(__assign({}, this.directives), directives); | ||
} | ||
this.mounted = true; | ||
this.patch([LUCIA_COMPILE_REQUEST]); | ||
this.patch([LUCIA_FIRST_RENDER]); | ||
if (this.mountHook) | ||
this.mountHook(this.state); | ||
return this.state; | ||
}; | ||
App.prototype.component = function (name, fn) { | ||
this.components[name.toUpperCase()] = fn; | ||
App.prototype.component = function (name, templateCallback) { | ||
this.components[name.toUpperCase()] = templateCallback; | ||
}; | ||
App.prototype.directive = function (name, fn) { | ||
this.directives[name.toUpperCase()] = fn; | ||
App.prototype.directive = function (name, evaluationCallback) { | ||
this.directives[name.toUpperCase()] = evaluationCallback; | ||
}; | ||
App.prototype.patch = function (keys) { | ||
if (!this.mounted) | ||
throw new Error('App is not mounted.'); | ||
patch(this.vdom, this.state, this.directives, keys); | ||
var app = { | ||
state: this.state, | ||
directives: this.directives, | ||
components: this.components, | ||
}; | ||
patch(this.vdom, app, keys); | ||
}; | ||
@@ -636,24 +631,46 @@ App.prototype.compile = function (el) { | ||
}()); | ||
var createApp = function (state) { | ||
return new App(state); | ||
var createApp = function (state, mountHook) { | ||
return new App(state, mountHook); | ||
}; | ||
var init = function (element, directive) { | ||
var stateDirective = DIRECTIVE_PREFIX + "state"; | ||
var init = function (element) { | ||
if (element === void 0) { element = document; } | ||
if (directive === void 0) { directive = 'use'; } | ||
var elements = __spread(element.querySelectorAll("[" + (DIRECTIVE_PREFIX + directive) + "]")); | ||
var apps = []; | ||
elements.map(function (el) { | ||
var state = el.getAttribute(DIRECTIVE_PREFIX + directive); | ||
if (state === null) | ||
return; | ||
var elements = __spread(element.querySelectorAll("[" + stateDirective + "]")); | ||
elements | ||
.filter(function (el) { return el.__l === undefined; }) | ||
.map(function (el) { | ||
var expression = el.getAttribute(stateDirective); | ||
try { | ||
var app = createApp(safeEval(state)); | ||
var state = new Function("return " + expression)(); | ||
var app = createApp(state); | ||
app.mount(el); | ||
apps.push(app); | ||
el.__l = app; | ||
} | ||
catch (err) { } | ||
catch (err) { | ||
console.warn("Lucia Error: \"" + err + "\"\n\nExpression: \"" + expression + "\"\nElement:", el); | ||
} | ||
}); | ||
return apps; | ||
}; | ||
var listen = function (callback, element, config) { | ||
if (element === void 0) { element = document; } | ||
var observer = new MutationObserver(function (mutations) { | ||
mutations.map(function (mut) { | ||
if (mut.addedNodes.length > 0) { | ||
mut.addedNodes.forEach(function (node) { | ||
if (node.nodeType !== 1) | ||
return; | ||
if (node.parentElement && node.parentElement.closest("[" + stateDirective + "]")) | ||
return; | ||
callback(node.parentElement); | ||
}); | ||
} | ||
}); | ||
observer.observe(element, config || { | ||
childList: true, | ||
attributes: true, | ||
subtree: true, | ||
}); | ||
}); | ||
}; | ||
@@ -665,4 +682,5 @@ exports.compile = compile; | ||
exports.init = init; | ||
exports.listen = listen; | ||
exports.patch = patch; | ||
exports.reactive = reactive; | ||
exports.renderDirective = renderDirective; |
@@ -1,1 +0,1 @@ | ||
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=function(){return(e=Object.assign||function(e){for(var t,r=1,n=arguments.length;r<n;r++)for(var i in t=arguments[r])Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i]);return e}).apply(this,arguments)};function t(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")}function r(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,i,o=r.call(e),a=[];try{for(;(void 0===t||t-- >0)&&!(n=o.next()).done;)a.push(n.value)}catch(e){i={error:e}}finally{try{n&&!n.done&&(r=o.return)&&r.call(o)}finally{if(i)throw i.error}}return a}function n(){for(var e=[],t=0;t<arguments.length;t++)e=e.concat(r(arguments[t]));return e}var i,o;!function(e){e["@"]="ON",e[":"]="BIND"}(i||(i={})),function(e){e[e.STATIC=0]="STATIC",e[e.NEEDS_PATCH=1]="NEEDS_PATCH",e[e.DYNAMIC=2]="DYNAMIC"}(o||(o={}));var a=/:|\./,l=/(?=\.)|(?=#)|(?=\[)/,s=function(e,t){return void 0===t&&(t=!0),new RegExp((t?"this\\.":"")+e+"\\b")},u=function(n,i,o){var a,s,u=n.split(l),c=u[0],v=e({},null==o?void 0:o.attributes),f=e({},null==o?void 0:o.directives);if(u.length>1){u.shift();try{for(var p=t(u),d=p.next();!d.done;d=p.next()){var y=d.value;switch(y[0]){case"#":v.id=y.slice(1);break;case".":v.className||(v.className=""),v.className+=y.slice(1)+" ";break;case"[":var h=r(y.slice(1,-1).split("="),2),m=h[0],b=h[1];m.startsWith("l-")?f[m.slice("l-".length)]=b:v[m]=b}}}catch(e){a={error:e}}finally{try{d&&!d.done&&(s=p.return)&&s.call(p)}finally{if(a)throw a.error}}}return v.className&&(v.className=v.className.trim()),{tag:c,children:"string"==typeof i?[i]:i||[],props:{attributes:v,directives:f,ref:(null==o?void 0:o.ref)||void 0,type:(null==o?void 0:o.type)||0}}},c=function(e){var r,o,a={},l={};if(e.attributes)try{for(var s=t(n(e.attributes)),u=s.next();!u.done;u=s.next()){var c=u.value,v=c.name,f=c.value;v.startsWith("l-")?l[v.slice("l-".length)]=f:Object.keys(i).includes(v[0])?l[i[v[0]]+":"+v.slice(1)]=f:a[v]=f}}catch(e){r={error:e}}finally{try{u&&!u.done&&(o=s.return)&&o.call(s)}finally{if(r)throw r.error}}return{attributes:a,directives:l}},v=function(e,t,r){var n=c(e),i=n.attributes,a=n.directives,l=o.STATIC,v=Object.keys(a).length>0,f=Object.values(a).some((function(e){return Object.keys(t).some((function(t){return s(t,!1).test(e)}))}));return v&&(l=o.NEEDS_PATCH),f&&(l=o.DYNAMIC),u(e.tagName.toLowerCase(),r,{attributes:i,directives:a,ref:l===o.STATIC||i.id?void 0:e,type:l})},f=function(e,n,i,o,a){var l,s,u,d,y,h,m;if(void 0===n&&(n={}),void 0===i&&(i={}),void 0===o&&(o=!1),void 0===a&&(a=!1),!e)throw new Error("Please provide a Element");var b=[],T=Array.prototype.slice.call(e.childNodes);try{for(var N=t(T),g=N.next();!g.done;g=N.next()){var A=g.value;switch(A.nodeType){case Node.TEXT_NODE:!o&&A.nodeValue&&b.push(A.nodeValue);break;case Node.ELEMENT_NODE:if(Object.keys(i).includes(A.tagName)){var x=document.createElement("div"),E=i[A.tagName]({children:A.innerHTML,state:n});x.innerHTML=E;try{for(var w=(u=void 0,t(Object.entries(c(A).directives))),O=w.next();!O.done;O=w.next()){var C=r(O.value,2),$=C[0],j=C[1];null===(m=x.firstElementChild)||void 0===m||m.setAttribute("l-"+$,j)}}catch(e){u={error:e}}finally{try{O&&!O.done&&(d=w.return)&&d.call(w)}finally{if(u)throw u.error}}if(!o||x.outerHTML.includes(" l-")){var S=f(x,n,i,o,!0);try{for(var I=(y=void 0,t(S)),M=I.next();!M.done;M=I.next()){var L=M.value;b.push(L)}}catch(e){y={error:e}}finally{try{M&&!M.done&&(h=I.return)&&h.call(I)}finally{if(y)throw y.error}}}e.replaceChild(x.firstElementChild,A)}else if(!o||A.outerHTML.includes(" l-")){S=f(A,n,i,o,!0);var P=v(A,n,S);b.push(P)}}}}catch(e){l={error:e}}finally{try{g&&!g.done&&(s=N.return)&&s.call(N)}finally{if(l)throw l.error}}if(a)return b;var D=v(e,n,b);return o?p(D):D},p=function(r){var n,i,o,a,l=e({},r);l.children.filter((function(e){return"object"==typeof e&&e.props.type>0}));try{for(var s=t(r.children),u=s.next();!u.done;u=s.next()){var c=u.value;if("string"!=typeof c&&c.children.length>0)try{for(var v=(o=void 0,t(p(c).children)),f=v.next();!f.done;f=v.next()){var d=f.value;"string"!=typeof d&&(0!==d.props.type&&l.children.push(d))}}catch(e){o={error:e}}finally{try{f&&!f.done&&(a=v.return)&&a.call(v)}finally{if(o)throw o.error}}}}catch(e){n={error:e}}finally{try{u&&!u.done&&(i=s.return)&&i.call(s)}finally{if(n)throw n.error}}return l},d=function(e,t,r,i){return void 0===t&&(t={}),void 0===r&&(r={}),void 0===i&&(i=!0),(new(Function.bind.apply(Function,n([void 0],Object.keys(t),[i?"return "+e:e])))).bind(r).apply(void 0,n(Object.values(t)))},y=function(e,t,r){return void 0===r&&(r=!0),d(e,{$el:t.$el},t.$state,r)},h={BIND:function(e){var t=e.el,r=e.name,n=e.value,i=e.state;switch(r.split(":")[1]){case"class":var o=y(n,{$state:i,$el:t});if("string"==typeof o)return t.setAttribute("class",(t.className+" "+o).trim());if(o instanceof Array)return t.setAttribute("class",(t.className+" "+o.join(" ")).trim());var a=[];for(var l in o)o[l]&&a.push(l);return a.length>0?t.setAttribute("class",(t.className+" "+a.join(" ").trim()).trim()):t.className.trim().length>0?t.setAttribute("class",t.className):t.removeAttribute("class");case"style":var s=y(n,{$state:i,$el:t});for(var l in t.removeAttribute("style"),s)t.style[l]=s[l];break;default:var u=y(n,{$state:i,$el:t});u?t.setAttribute(r.split(":")[1],u):t.removeAttribute(r.split(":")[1])}},JOIN:function(t){var n=t.el,i=t.value,o=t.state,a=r(i.split(/ as | by /),3),l=a[0],s=a[1],u=a[2],c=y(l,{$state:o,$el:n});n["text"===s?"innerText":"innerHTML"]=c.join(u||""),A(e({},o)).mount(n,!0)},HTML:function(t){var r=t.el,n=t.value,i=t.state;A(e({},i)).mount(r,!0);try{r.innerHTML=y(n,{$state:i,$el:r})}catch(e){r.innerHTML=n}},IF:function(e){var t=e.el,r=e.value,n=e.state;y(r,{$state:n,$el:t})?t.style.removeProperty("display"):t.style.display="none"},MODEL:function(e){var t=e.el,r=e.value,n=e.state,i=t,o=y(r,{$state:n,$el:i});i.value!==o&&(i.value=o),i.oninput=function(){var e,t="number"==typeof o&&!isNaN(i.value),a="boolean"==typeof o&&("true"===i.value||"false"===i.value),l=null==o&&("null"===i.value||"undefined"===i.value);e=t?"Number('"+i.value+"').toPrecision()":a?"Boolean('"+i.value+"')":l?"null"===i.value?null:void 0:"'"+i.value+"'",y(r+" = "+e,{$state:n,$el:i},!1)}},ON:function(e){var t=e.el,n=e.name,i=e.value,o=e.state,a=r(n.split("."),2),l=a[0],s=a[1],u=l.split(":")[1],c=s||null;t["on"+u]=function(e){"prevent"===c&&e.preventDefault(),"stop"===c&&e.stopPropagation(),y(i,{$state:o,$el:t},!1)}},TEXT:function(e){var t=e.el,r=e.value,n=e.state;try{t.innerHTML=y(r,{$state:n,$el:t})}catch(e){t.innerHTML=r}}},m=function(e,t){var r=e.el,n=e.name,i=e.value,o=e.state;t[n.split(a)[0].toUpperCase()]({el:r,name:n,value:i,state:o})},b=function(e,t,r,n){if("length"===t){var i=Object.keys(r).filter((function(t){return r[t]instanceof Array&&(n=e,i=r[t],n instanceof Array&&i instanceof Array&&n.length===i.length&&n.every((function(e,t){return e===i[t]})));var n,i}));return 0!==i.length&&n(i),!0}return n([t]),!1},T=function(e,t){var r={get:function(e,t){return"object"==typeof e[t]&&null!==e[t]?new Proxy(e[t],r):e[t]},set:function(r,n,i){return r[n]=i,b(r,n,e,t),!0},deleteProperty:function(r,n){return delete r[n],b(r,n,e,t),!0}};return new Proxy(e,r)},N=function(r,n,i,a){var l,u;void 0===n&&(n={}),void 0===i&&(i={});var c=!1;if(r){a||(a=Object.keys(n)),"%LUCIA_COMPILE_REQUEST%"===a[0]&&(c=!0);var v=function(t){if("string"==typeof t)return"continue";if(t.props.type>o.STATIC){var r=t.props,l=r.attributes,u=r.directives,v=r.ref,f=r.type,p=[];if(!c){var d=function(e){var t=u[e],r=1===f,i=a.some((function(e){return s(e).test(t.toString())})),o=Object.keys(n).some((function(e){var t=a.some((function(t){return s(t).test(n[e].toString())}));return"function"==typeof n[e]&&t}));(r||i||o)&&p.push(e)};for(var y in u)d(y)}t.props.type=f===o.NEEDS_PATCH?o.STATIC:f,(c?Object.keys(u):p).map((function(t){var r=u[t],o=l.id?document.getElementById(l.id):v;m({el:o,name:t,value:r,state:n},e({},i))}))}t.children.length>0&&N(t,n,i,a)};try{for(var f=t(r.children),p=f.next();!p.done;p=f.next()){v(p.value)}}catch(e){l={error:e}}finally{try{p&&!p.done&&(u=f.return)&&u.call(f)}finally{if(l)throw l.error}}}},g=function(){function e(e){void 0===e&&(e={}),this.vdom=null,this.state=e,this.directives={},this.components={},this.mounted=!1}return e.prototype.mount=function(e,t){return void 0===t&&(t=!1),this.vdom=this.compile("string"==typeof e?document.querySelector(e):e),t||(this.state=T(this.state,this.patch.bind(this)),this.directives=h),this.mounted=!0,this.patch(["%LUCIA_COMPILE_REQUEST%"]),this.state},e.prototype.component=function(e,t){this.components[e.toUpperCase()]=t},e.prototype.directive=function(e,t){this.directives[e.toUpperCase()]=t},e.prototype.patch=function(e){if(!this.mounted)throw new Error("App is not mounted.");N(this.vdom,this.state,this.directives,e)},e.prototype.compile=function(e){return f(e,this.state,this.components,!0)},e}(),A=function(e){return new g(e)};exports.compile=f,exports.createApp=A,exports.directives=h,exports.h=u,exports.init=function(e,t){void 0===e&&(e=document),void 0===t&&(t="use");var r=n(e.querySelectorAll("[l-"+t+"]")),i=[];return r.map((function(e){var r=e.getAttribute("l-"+t);if(null!==r)try{var n=A(d(r));n.mount(e),i.push(n)}catch(e){}})),i},exports.patch=N,exports.reactive=T,exports.renderDirective=m; | ||
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var t=function(){return(t=Object.assign||function(t){for(var e,r=1,n=arguments.length;r<n;r++)for(var i in e=arguments[r])Object.prototype.hasOwnProperty.call(e,i)&&(t[i]=e[i]);return t}).apply(this,arguments)};function e(t){var e="function"==typeof Symbol&&Symbol.iterator,r=e&&t[e],n=0;if(r)return r.call(t);if(t&&"number"==typeof t.length)return{next:function(){return t&&n>=t.length&&(t=void 0),{value:t&&t[n++],done:!t}}};throw new TypeError(e?"Object is not iterable.":"Symbol.iterator is not defined.")}function r(t,e){var r="function"==typeof Symbol&&t[Symbol.iterator];if(!r)return t;var n,i,o=r.call(t),a=[];try{for(;(void 0===e||e-- >0)&&!(n=o.next()).done;)a.push(n.value)}catch(t){i={error:t}}finally{try{n&&!n.done&&(r=o.return)&&r.call(o)}finally{if(i)throw i.error}}return a}function n(){for(var t=[],e=0;e<arguments.length;e++)t=t.concat(r(arguments[e]));return t}var i;!function(t){t["@"]="on",t[":"]="bind"}(i||(i={}));var o=/:|\./,a=function(t,e){return void 0===e&&(e=!0),new RegExp((e?"this\\.":"")+t+"\\b")};function s(t){try{var e=this.returnable?"return "+this.expression:this.expression;return(new(Function.bind.apply(Function,n([void 0],Object.keys(this.argsKV),[e])))).bind(t).apply(void 0,n(Object.values(this.argsKV)))}catch(t){console.warn('Lucia Error: "'+t+'"\n\nExpression: "'+this.expression+'"\nElement:',this.argsKV.$el)}}var l,u=function(t,e,r){return void 0===r&&(r=!0),s.bind({expression:t,argsKV:{$el:e.$el},returnable:r})},c={BIND:function(t){var e=t.el,r=t.name,n=t.data,i=t.app;switch(r.split(":")[1]){case"class":var o=n.compute(i.state);if("string"==typeof o)return e.setAttribute("class",(e.className+" "+o).trim());if(o instanceof Array)return e.setAttribute("class",(e.className+" "+o.join(" ")).trim());var a=[];for(var s in o)o[s]&&a.push(s);return a.length>0?e.setAttribute("class",(e.className+" "+a.join(" ").trim()).trim()):e.className.trim().length>0?e.setAttribute("class",e.className):e.removeAttribute("class");case"style":var l=n.compute(i.state);for(var s in e.removeAttribute("style"),l)e.style[s]=l[s];break;default:var u=n.compute(i.state);if("object"==typeof u&&null!==u)for(var s in u)u[s]?e.setAttribute(s,u[s]):e.removeAttribute(s);else u?e.setAttribute(r.split(":")[1],u):e.removeAttribute(r.split(":")[1])}},JOIN:function(e){var n=e.el,i=e.data,o=e.app,a=r(i.value.split(/ as | by /),3),s=a[0],l=a[1],c=a[2],v=u(s,{$el:n})(o.state);n["text"===l?"innerText":"innerHTML"]=v.join(c||"");var p=g(t({},o.state));Object.entries(o.directives||{}).map((function(t){var e=r(t,2),n=e[0],i=e[1];p.directive(n,i)})),Object.entries(o.components||{}).map((function(t){var e=r(t,2),n=e[0],i=e[1];p.component(n,i)})),p.mount(n)},HTML:function(e){var n,i=e.el,o=e.data,a=e.app;i.innerHTML=null!==(n=o.compute(a.state))&&void 0!==n?n:o.value;var s=g(t({},a.state));Object.entries(a.directives||{}).map((function(t){var e=r(t,2),n=e[0],i=e[1];s.directive(n,i)})),Object.entries(a.components||{}).map((function(t){var e=r(t,2),n=e[0],i=e[1];s.component(n,i)})),s.mount(i)},IF:function(t){var e=t.el,r=t.data,n=t.app;r.compute(n.state)?e.style.removeProperty("display"):e.style.display="none"},MODEL:function(t){var e=t.el,r=t.data,n=t.app,i=e,o=u(r.compute(),{$el:i})(n.state);i.value!==o&&(i.value=o),i.oninput=function(){var t,e="number"==typeof o&&!isNaN(i.value),a="boolean"==typeof o&&("true"===i.value||"false"===i.value),s=null==o&&("null"===i.value||"undefined"===i.value);t=e?"Number('"+i.value+"').toPrecision()":a?"Boolean('"+i.value+"')":s?"null"===i.value?null:void 0:"'"+i.value+"'",u(r.value+" = "+t,{$el:i},!1)(n.state)}},ON:function(t){var e=t.el,n=t.name,i=t.data,o=t.app,a=r(n.split("."),2),s=a[0],l=a[1],u=s.split(":")[1],c=l||null;e["on"+u]=function(t){"prevent"===c&&t.preventDefault(),"stop"===c&&t.stopPropagation(),i.compute(o.state)}},TEXT:function(t){var e,r=t.el,n=t.data,i=t.app;r.textContent=null!==(e=n.compute(i.state))&&void 0!==e?e:n.value}},v=function(t,e){e[t.name.split(o)[0].toUpperCase()](t)};!function(t){t[t.STATIC=0]="STATIC",t[t.NEEDS_PATCH=1]="NEEDS_PATCH",t[t.DYNAMIC=2]="DYNAMIC"}(l||(l={}));var p=function(e,r,n){void 0===r&&(r=[]);var i=t({},null==n?void 0:n.attributes),o=t({},null==n?void 0:n.directives);return r=r instanceof Array?r:[r],i.className&&(i.className=i.className.trim()),{tag:e,children:r,props:{attributes:i,directives:o,ref:(null==n?void 0:n.ref)||void 0,type:(null==n?void 0:n.type)||0}}},f=function(t){var r,o,a={},s={};if(t.attributes)try{for(var l=e(n(t.attributes)),c=l.next();!c.done;c=l.next()){var v=c.value,p=v.name,f=v.value,d={compute:u(f,{$el:t}),value:f};p.startsWith("l-")?s[p.slice("l-".length)]=d:Object.keys(i).includes(p[0])?s[i[p[0]]+":"+p.slice(1)]=d:a[p]=f}}catch(t){r={error:t}}finally{try{c&&!c.done&&(o=l.return)&&o.call(l)}finally{if(r)throw r.error}}return{attributes:a,directives:s}},d=function(t,e,r){var n=f(t),i=n.attributes,o=n.directives,s=l.STATIC,u=Object.keys(o).length>0,c=Object.values(o).some((function(t){var r=t.value;return Object.keys(e).some((function(t){return a(t,!1).test(r)}))}));return u&&(s=l.NEEDS_PATCH),c&&(s=l.DYNAMIC),p(t.tagName.toLowerCase(),r,{attributes:i,directives:o,ref:s===l.STATIC||i.id?void 0:t,type:s})},y=function(t,n,i,o,a){var s,l,u,c,v,p,m;if(void 0===n&&(n={}),void 0===i&&(i={}),void 0===o&&(o=!1),void 0===a&&(a=!1),!t)throw new Error("Please provide a Element");var b=[],x=Array.prototype.slice.call(t.childNodes);try{for(var E=e(x),g=E.next();!g.done;g=E.next()){var A=g.value;switch(A.nodeType){case Node.TEXT_NODE:!o&&A.nodeValue&&b.push(A.nodeValue);break;case Node.ELEMENT_NODE:if(Object.keys(i).includes(A.tagName)){var N=document.createElement("div"),T=i[A.tagName]({children:A.innerHTML,state:n});N.innerHTML=T;try{for(var O=(u=void 0,e(Object.entries(f(A).directives))),j=O.next();!j.done;j=O.next()){var w=r(j.value,2),C=w[0],S=w[1];null===(m=N.firstElementChild)||void 0===m||m.setAttribute("l-"+C,S.value)}}catch(t){u={error:t}}finally{try{j&&!j.done&&(c=O.return)&&c.call(O)}finally{if(u)throw u.error}}if(!o||N.outerHTML.includes(" l-")){var I=y(N,n,i,o,!0);try{for(var _=(v=void 0,e(I)),D=_.next();!D.done;D=_.next()){var L=D.value;b.push(L)}}catch(t){v={error:t}}finally{try{D&&!D.done&&(p=_.return)&&p.call(_)}finally{if(v)throw v.error}}}t.replaceChild(N.firstElementChild,A)}else if(!o||A.outerHTML.includes(" l-")){I=y(A,n,i,o,!0);var k=d(A,n,I);b.push(k)}}}}catch(t){s={error:t}}finally{try{g&&!g.done&&(l=E.return)&&l.call(E)}finally{if(s)throw s.error}}if(a)return b;var H=d(t,n,b);return o?h(H):H},h=function(r){var n,i,o,a,s=t({},r);s.children.filter((function(t){return"object"==typeof t&&t.props.type>0}));try{for(var l=e(r.children),u=l.next();!u.done;u=l.next()){var c=u.value;if("string"!=typeof c&&c.children.length>0)try{for(var v=(o=void 0,e(h(c).children)),p=v.next();!p.done;p=v.next()){var f=p.value;"string"!=typeof f&&(0!==f.props.type&&s.children.push(f))}}catch(t){o={error:t}}finally{try{p&&!p.done&&(a=v.return)&&a.call(v)}finally{if(o)throw o.error}}}}catch(t){n={error:t}}finally{try{u&&!u.done&&(i=l.return)&&i.call(l)}finally{if(n)throw n.error}}return s},m=function(t,e,r,n,i){if(void 0===i&&(i=!1),"length"===e){var o=Object.keys(r).filter((function(e){return r[e]instanceof Array&&(n=t,i=r[e],n instanceof Array&&i instanceof Array&&n.length===i.length&&n.every((function(t,e){return t===i[e]})));var n,i}));return 0!==o.length&&n(o),!0}return i&&n([e]),!1},b=function(t,e){var r={get:function(t,e){return"object"==typeof t[e]&&null!==t[e]?new Proxy(t[e],r):t[e]},set:function(r,n,i){var o=r[n]!==i;return o&&(r[n]=i),m(r,n,t,e,o),!0},deleteProperty:function(r,n){return delete r[n],m(r,n,t,e),!0}};return new Proxy(t,r)},x=function(r,n,i){var o,s;void 0===n&&(n={});var u=!1,c=n.state||{};if(r){i||(i=Object.keys(c)),"%LUCIA_FIRST_RENDER%"===i[0]&&(u=!0);var p=function(e){if("string"==typeof e)return"continue";if(e.props.type>l.STATIC){var r=e.props,o=r.attributes,s=r.directives,p=r.ref,f=r.type,d=[];if(!u){var y=function(t){var e=1===f,r=i.some((function(e){return a(e).test(String(s[t].value))})),n=Object.keys(c).some((function(t){var e=i.some((function(e){return a(e).test(String(c[t]))}));return"function"==typeof c[t]&&e}));(e||r||n)&&d.push(t)};for(var h in s)y(h)}e.props.type=f===l.NEEDS_PATCH?l.STATIC:f,(u?Object.keys(s):d).map((function(e){var r=s[e],i=o.id?document.getElementById(o.id):p;v({el:i,name:e,data:r,app:n},t({},n.directives))}))}e.children.length>0&&x(e,c,i)};try{for(var f=e(r.children),d=f.next();!d.done;d=f.next()){p(d.value)}}catch(t){o={error:t}}finally{try{d&&!d.done&&(s=f.return)&&s.call(f)}finally{if(o)throw o.error}}}},E=function(){function e(t,e){void 0===t&&(t={}),this.state=t,this.directives={},this.components={},this.mountHook=e}return e.prototype.mount=function(e,r){void 0===r&&(r=!1);var n="string"==typeof e?document.querySelector(e):e;return this.vdom=this.compile(n),r||(this.state=b(this.state,this.patch.bind(this)),this.directives=t(t({},this.directives),c)),this.patch(["%LUCIA_FIRST_RENDER%"]),this.mountHook&&this.mountHook(this.state),this.state},e.prototype.component=function(t,e){this.components[t.toUpperCase()]=e},e.prototype.directive=function(t,e){this.directives[t.toUpperCase()]=e},e.prototype.patch=function(t){var e={state:this.state,directives:this.directives,components:this.components};x(this.vdom,e,t)},e.prototype.compile=function(t){return y(t,this.state,this.components,!0)},e}(),g=function(t,e){return new E(t,e)};exports.compile=y,exports.createApp=g,exports.directives=c,exports.h=p,exports.init=function(t){void 0===t&&(t=document),n(t.querySelectorAll("[l-state]")).filter((function(t){return void 0===t.__l})).map((function(t){var e=t.getAttribute("l-state");try{var r=new Function("return "+e)(),n=g(r);n.mount(t),t.__l=n}catch(r){console.warn('Lucia Error: "'+r+'"\n\nExpression: "'+e+'"\nElement:',t)}}))},exports.listen=function(t,e,r){void 0===e&&(e=document);var n=new MutationObserver((function(i){i.map((function(e){e.addedNodes.length>0&&e.addedNodes.forEach((function(e){1===e.nodeType&&(e.parentElement&&e.parentElement.closest("[l-state]")||t(e.parentElement))}))})),n.observe(e,r||{childList:!0,attributes:!0,subtree:!0})}))},exports.patch=x,exports.reactive=b,exports.renderDirective=v; |
@@ -63,18 +63,10 @@ /*! ***************************************************************************** | ||
var DIRECTIVE_PREFIX = 'l-'; | ||
var LUCIA_COMPILE_REQUEST = '%LUCIA_COMPILE_REQUEST%'; | ||
var LUCIA_FIRST_RENDER = '%LUCIA_FIRST_RENDER%'; | ||
var DIRECTIVE_SHORTHANDS; | ||
(function (DIRECTIVE_SHORTHANDS) { | ||
DIRECTIVE_SHORTHANDS["@"] = "ON"; | ||
DIRECTIVE_SHORTHANDS[":"] = "BIND"; | ||
DIRECTIVE_SHORTHANDS["@"] = "on"; | ||
DIRECTIVE_SHORTHANDS[":"] = "bind"; | ||
})(DIRECTIVE_SHORTHANDS || (DIRECTIVE_SHORTHANDS = {})); | ||
var VNodeTypes; | ||
(function (VNodeTypes) { | ||
VNodeTypes[VNodeTypes["STATIC"] = 0] = "STATIC"; | ||
VNodeTypes[VNodeTypes["NEEDS_PATCH"] = 1] = "NEEDS_PATCH"; | ||
VNodeTypes[VNodeTypes["DYNAMIC"] = 2] = "DYNAMIC"; | ||
})(VNodeTypes || (VNodeTypes = {})); | ||
var rawDirectiveSplitPattern = /:|\./; | ||
var selectorSplitPattern = /(?=\.)|(?=#)|(?=\[)/; | ||
var keyPattern = function (key, hasThis) { | ||
@@ -85,42 +77,195 @@ if (hasThis === void 0) { hasThis = true; } | ||
var h = function (selector, children, props) { | ||
var e_1, _a; | ||
var tokens = selector.split(selectorSplitPattern); | ||
var tag = tokens[0]; | ||
var attributes = __assign({}, props === null || props === void 0 ? void 0 : props.attributes); | ||
var directives = __assign({}, props === null || props === void 0 ? void 0 : props.directives); | ||
if (tokens.length > 1) { | ||
tokens.shift(); | ||
try { | ||
for (var tokens_1 = __values(tokens), tokens_1_1 = tokens_1.next(); !tokens_1_1.done; tokens_1_1 = tokens_1.next()) { | ||
var token = tokens_1_1.value; | ||
switch (token[0]) { | ||
case '#': | ||
attributes.id = token.slice(1); | ||
break; | ||
case '.': | ||
if (!attributes.className) | ||
attributes.className = ''; | ||
attributes.className += token.slice(1) + " "; | ||
break; | ||
case '[': | ||
var _b = __read(token.slice(1, -1).split('='), 2), key = _b[0], value = _b[1]; | ||
if (key.startsWith(DIRECTIVE_PREFIX)) { | ||
directives[key.slice(DIRECTIVE_PREFIX.length)] = value; | ||
} | ||
else { | ||
attributes[key] = value; | ||
} | ||
break; | ||
var bindDirective = function (_a) { | ||
var el = _a.el, name = _a.name, data = _a.data, app = _a.app; | ||
switch (name.split(':')[1]) { | ||
case 'class': | ||
var hydratedClasses = data.compute(app.state); | ||
if (typeof hydratedClasses === 'string') { | ||
return el.setAttribute('class', (el.className + " " + hydratedClasses).trim()); | ||
} | ||
else if (hydratedClasses instanceof Array) { | ||
return el.setAttribute('class', (el.className + " " + hydratedClasses.join(' ')).trim()); | ||
} | ||
else { | ||
var classes = []; | ||
for (var key in hydratedClasses) { | ||
if (hydratedClasses[key]) | ||
classes.push(key); | ||
} | ||
if (classes.length > 0) { | ||
return el.setAttribute('class', (el.className + " " + classes.join(' ').trim()).trim()); | ||
} | ||
else if (el.className.trim().length > 0) { | ||
return el.setAttribute('class', el.className); | ||
} | ||
else { | ||
return el.removeAttribute('class'); | ||
} | ||
} | ||
} | ||
catch (e_1_1) { e_1 = { error: e_1_1 }; } | ||
finally { | ||
try { | ||
if (tokens_1_1 && !tokens_1_1.done && (_a = tokens_1.return)) _a.call(tokens_1); | ||
case 'style': | ||
var hydratedStyles = data.compute(app.state); | ||
el.removeAttribute('style'); | ||
for (var key in hydratedStyles) { | ||
el.style[key] = hydratedStyles[key]; | ||
} | ||
finally { if (e_1) throw e_1.error; } | ||
break; | ||
default: | ||
var hydratedAttributes = data.compute(app.state); | ||
if (typeof hydratedAttributes === 'object' && hydratedAttributes !== null) { | ||
for (var key in hydratedAttributes) { | ||
if (hydratedAttributes[key]) { | ||
el.setAttribute(key, hydratedAttributes[key]); | ||
} | ||
else { | ||
el.removeAttribute(key); | ||
} | ||
} | ||
} | ||
else if (hydratedAttributes) { | ||
el.setAttribute(name.split(':')[1], hydratedAttributes); | ||
} | ||
else { | ||
el.removeAttribute(name.split(':')[1]); | ||
} | ||
break; | ||
} | ||
}; | ||
var htmlDirective = function (_a) { | ||
var _b; | ||
var el = _a.el, data = _a.data, app = _a.app; | ||
el.innerHTML = (_b = data.compute(app.state)) !== null && _b !== void 0 ? _b : data.value; | ||
var scope = createApp(__assign({}, app.state)); | ||
Object.entries(app.directives || {}).map(function (_a) { | ||
var _b = __read(_a, 2), name = _b[0], evaluationCallback = _b[1]; | ||
scope.directive(name, evaluationCallback); | ||
}); | ||
Object.entries(app.components || {}).map(function (_a) { | ||
var _b = __read(_a, 2), name = _b[0], templateCallback = _b[1]; | ||
scope.component(name, templateCallback); | ||
}); | ||
scope.mount(el); | ||
}; | ||
var ifDirective = function (_a) { | ||
var el = _a.el, data = _a.data, app = _a.app; | ||
var hydratedConditional = data.compute(app.state); | ||
if (hydratedConditional) { | ||
el.style.removeProperty('display'); | ||
} | ||
else { | ||
el.style.display = 'none'; | ||
} | ||
}; | ||
function createComputeFunction(state) { | ||
try { | ||
var expression = this.returnable ? "return " + this.expression : this.expression; | ||
return new (Function.bind.apply(Function, __spread([void 0], Object.keys(this.argsKV), [expression])))().bind(state).apply(void 0, __spread(Object.values(this.argsKV))); | ||
} | ||
catch (err) { | ||
console.warn("Lucia Error: \"" + err + "\"\n\nExpression: \"" + this.expression + "\"\nElement:", this.argsKV.$el); | ||
} | ||
} | ||
var compute = function (expression, data, returnable) { | ||
if (returnable === void 0) { returnable = true; } | ||
return createComputeFunction.bind({ expression: expression, argsKV: { $el: data.$el }, returnable: returnable }); | ||
}; | ||
var joinDirective = function (_a) { | ||
var el = _a.el, data = _a.data, app = _a.app; | ||
var _b = __read(data.value.split(/ as | by /), 3), array = _b[0], contentType = _b[1], delimiter = _b[2]; | ||
var hydratedArray = compute(array, { $el: el })(app.state); | ||
var accessProp = contentType === 'text' ? 'innerText' : 'innerHTML'; | ||
el[accessProp] = hydratedArray.join(delimiter || ''); | ||
var scope = createApp(__assign({}, app.state)); | ||
Object.entries(app.directives || {}).map(function (_a) { | ||
var _b = __read(_a, 2), name = _b[0], evaluationCallback = _b[1]; | ||
scope.directive(name, evaluationCallback); | ||
}); | ||
Object.entries(app.components || {}).map(function (_a) { | ||
var _b = __read(_a, 2), name = _b[0], templateCallback = _b[1]; | ||
scope.component(name, templateCallback); | ||
}); | ||
scope.mount(el); | ||
}; | ||
var modelDirective = function (_a) { | ||
var awaitingTypecastEl = _a.el, data = _a.data, app = _a.app; | ||
var el = awaitingTypecastEl; | ||
var hydratedValue = compute(data.compute(), { $el: el })(app.state); | ||
if (el.value !== hydratedValue) { | ||
el.value = hydratedValue; | ||
} | ||
el.oninput = function () { | ||
var isNumber = typeof hydratedValue === 'number' && !isNaN(el.value); | ||
var isBoolean = typeof hydratedValue === 'boolean' && (el.value === 'true' || el.value === 'false'); | ||
var isNullish = (hydratedValue === null || hydratedValue === undefined) && | ||
(el.value === 'null' || el.value === 'undefined'); | ||
var payload; | ||
if (isNumber) { | ||
payload = "Number('" + el.value + "').toPrecision()"; | ||
} | ||
} | ||
else if (isBoolean) { | ||
payload = "Boolean('" + el.value + "')"; | ||
} | ||
else if (isNullish) { | ||
if (el.value === 'null') | ||
payload = null; | ||
else | ||
payload = undefined; | ||
} | ||
else { | ||
payload = "'" + el.value + "'"; | ||
} | ||
compute(data.value + " = " + payload, { $el: el }, false)(app.state); | ||
}; | ||
}; | ||
var onDirective = function (_a) { | ||
var el = _a.el, name = _a.name, data = _a.data, app = _a.app; | ||
var _b = __read(name.split('.'), 2), directiveAndEventName = _b[0], prop = _b[1]; | ||
var eventName = directiveAndEventName.split(':')[1]; | ||
var eventProp = prop || null; | ||
el["on" + eventName] = function ($event) { | ||
if (eventProp === 'prevent') | ||
$event.preventDefault(); | ||
if (eventProp === 'stop') | ||
$event.stopPropagation(); | ||
data.compute(app.state); | ||
}; | ||
}; | ||
var textDirective = function (_a) { | ||
var _b; | ||
var el = _a.el, data = _a.data, app = _a.app; | ||
el.textContent = (_b = data.compute(app.state)) !== null && _b !== void 0 ? _b : data.value; | ||
}; | ||
var directives = { | ||
BIND: bindDirective, | ||
JOIN: joinDirective, | ||
HTML: htmlDirective, | ||
IF: ifDirective, | ||
MODEL: modelDirective, | ||
ON: onDirective, | ||
TEXT: textDirective, | ||
}; | ||
var renderDirective = function (props, directives) { | ||
var name = props.name.split(rawDirectiveSplitPattern)[0]; | ||
directives[name.toUpperCase()](props); | ||
}; | ||
var VNodeTypes; | ||
(function (VNodeTypes) { | ||
VNodeTypes[VNodeTypes["STATIC"] = 0] = "STATIC"; | ||
VNodeTypes[VNodeTypes["NEEDS_PATCH"] = 1] = "NEEDS_PATCH"; | ||
VNodeTypes[VNodeTypes["DYNAMIC"] = 2] = "DYNAMIC"; | ||
})(VNodeTypes || (VNodeTypes = {})); | ||
var h = function (tag, children, props) { | ||
if (children === void 0) { children = []; } | ||
var attributes = __assign({}, props === null || props === void 0 ? void 0 : props.attributes); | ||
var directives = __assign({}, props === null || props === void 0 ? void 0 : props.directives); | ||
children = children instanceof Array ? children : [children]; | ||
if (attributes.className) | ||
@@ -130,3 +275,3 @@ attributes.className = attributes.className.trim(); | ||
tag: tag, | ||
children: typeof children === 'string' ? [children] : children ? children : [], | ||
children: children, | ||
props: { | ||
@@ -149,7 +294,8 @@ attributes: attributes, | ||
var _d = _c.value, name_1 = _d.name, value = _d.value; | ||
var directiveData = { compute: compute(value, { $el: el }), value: value }; | ||
if (name_1.startsWith(DIRECTIVE_PREFIX)) { | ||
directives[name_1.slice(DIRECTIVE_PREFIX.length)] = value; | ||
directives[name_1.slice(DIRECTIVE_PREFIX.length)] = directiveData; | ||
} | ||
else if (Object.keys(DIRECTIVE_SHORTHANDS).includes(name_1[0])) { | ||
directives[DIRECTIVE_SHORTHANDS[name_1[0]] + ":" + name_1.slice(1)] = value; | ||
directives[DIRECTIVE_SHORTHANDS[name_1[0]] + ":" + name_1.slice(1)] = directiveData; | ||
} | ||
@@ -176,3 +322,4 @@ else { | ||
var hasDirectives = Object.keys(directives).length > 0; | ||
var hasKeyInDirectives = Object.values(directives).some(function (value) { | ||
var hasKeyInDirectives = Object.values(directives).some(function (_a) { | ||
var value = _a.value; | ||
return Object.keys(state).some(function (key) { return keyPattern(key, false).test(value); }); | ||
@@ -221,4 +368,4 @@ }); | ||
for (var _e = (e_2 = void 0, __values(Object.entries(props(child).directives))), _f = _e.next(); !_f.done; _f = _e.next()) { | ||
var _g = __read(_f.value, 2), key = _g[0], value = _g[1]; | ||
(_d = container.firstElementChild) === null || _d === void 0 ? void 0 : _d.setAttribute("" + DIRECTIVE_PREFIX + key, value); | ||
var _g = __read(_f.value, 2), key = _g[0], data = _g[1]; | ||
(_d = container.firstElementChild) === null || _d === void 0 ? void 0 : _d.setAttribute("" + DIRECTIVE_PREFIX + key, data.value); | ||
} | ||
@@ -317,162 +464,2 @@ } | ||
var safeEval = function (expression, argsKV, bindKV, returnable) { | ||
if (argsKV === void 0) { argsKV = {}; } | ||
if (bindKV === void 0) { bindKV = {}; } | ||
if (returnable === void 0) { returnable = true; } | ||
return new (Function.bind.apply(Function, __spread([void 0], Object.keys(argsKV), [returnable ? "return " + expression : expression])))().bind(bindKV).apply(void 0, __spread(Object.values(argsKV))); | ||
}; | ||
var computeProperties = function (expression, data, returnable) { | ||
if (returnable === void 0) { returnable = true; } | ||
return safeEval(expression, { $el: data.$el }, data.$state, returnable); | ||
}; | ||
var bindDirective = function (_a) { | ||
var el = _a.el, name = _a.name, value = _a.value, state = _a.state; | ||
switch (name.split(':')[1]) { | ||
case 'class': | ||
var classState = computeProperties(value, { $state: state, $el: el }); | ||
if (typeof classState === 'string') { | ||
return el.setAttribute('class', (el.className + " " + classState).trim()); | ||
} | ||
if (classState instanceof Array) { | ||
return el.setAttribute('class', (el.className + " " + classState.join(' ')).trim()); | ||
} | ||
else { | ||
var classes = []; | ||
for (var key in classState) { | ||
if (classState[key]) | ||
classes.push(key); | ||
} | ||
if (classes.length > 0) { | ||
return el.setAttribute('class', (el.className + " " + classes.join(' ').trim()).trim()); | ||
} | ||
else if (el.className.trim().length > 0) { | ||
return el.setAttribute('class', el.className); | ||
} | ||
else { | ||
return el.removeAttribute('class'); | ||
} | ||
} | ||
case 'style': | ||
var styleState = computeProperties(value, { $state: state, $el: el }); | ||
el.removeAttribute('style'); | ||
for (var key in styleState) { | ||
el.style[key] = styleState[key]; | ||
} | ||
break; | ||
default: | ||
var out = computeProperties(value, { $state: state, $el: el }); | ||
if (out) { | ||
el.setAttribute(name.split(':')[1], out); | ||
} | ||
else { | ||
el.removeAttribute(name.split(':')[1]); | ||
} | ||
break; | ||
} | ||
}; | ||
var htmlDirective = function (_a) { | ||
var el = _a.el, value = _a.value, state = _a.state; | ||
var app = createApp(__assign({}, state)); | ||
app.mount(el, true); | ||
try { | ||
el.innerHTML = computeProperties(value, { $state: state, $el: el }); | ||
} | ||
catch (_b) { | ||
el.innerHTML = value; | ||
} | ||
}; | ||
var ifDirective = function (_a) { | ||
var el = _a.el, value = _a.value, state = _a.state; | ||
var out = computeProperties(value, { $state: state, $el: el }); | ||
if (out) { | ||
el.style.removeProperty('display'); | ||
} | ||
else { | ||
el.style.display = 'none'; | ||
} | ||
}; | ||
var joinDirective = function (_a) { | ||
var el = _a.el, value = _a.value, state = _a.state; | ||
var _b = __read(value.split(/ as | by /), 3), array = _b[0], contentType = _b[1], delimiter = _b[2]; | ||
var out = computeProperties(array, { $state: state, $el: el }); | ||
var accessProp = contentType === 'text' ? 'innerText' : 'innerHTML'; | ||
el[accessProp] = out.join(delimiter || ''); | ||
var app = createApp(__assign({}, state)); | ||
app.mount(el, true); | ||
}; | ||
var modelDirective = function (_a) { | ||
var awaitingTypecastEl = _a.el, value = _a.value, state = _a.state; | ||
var el = awaitingTypecastEl; | ||
var out = computeProperties(value, { $state: state, $el: el }); | ||
if (el.value !== out) { | ||
el.value = out; | ||
} | ||
el.oninput = function () { | ||
var isNumber = typeof out === 'number' && !isNaN(el.value); | ||
var isBoolean = typeof out === 'boolean' && (el.value === 'true' || el.value === 'false'); | ||
var isNullish = (out === null || out === undefined) && (el.value === 'null' || el.value === 'undefined'); | ||
var payload; | ||
if (isNumber) { | ||
payload = "Number('" + el.value + "').toPrecision()"; | ||
} | ||
else if (isBoolean) { | ||
payload = "Boolean('" + el.value + "')"; | ||
} | ||
else if (isNullish) { | ||
if (el.value === 'null') | ||
payload = null; | ||
else | ||
payload = undefined; | ||
} | ||
else { | ||
payload = "'" + el.value + "'"; | ||
} | ||
computeProperties(value + " = " + payload, { $state: state, $el: el }, false); | ||
}; | ||
}; | ||
var onDirective = function (_a) { | ||
var el = _a.el, name = _a.name, value = _a.value, state = _a.state; | ||
var _b = __read(name.split('.'), 2), directiveAndEventName = _b[0], prop = _b[1]; | ||
var eventName = directiveAndEventName.split(':')[1]; | ||
var eventProp = prop || null; | ||
el["on" + eventName] = function ($event) { | ||
if (eventProp === 'prevent') | ||
$event.preventDefault(); | ||
if (eventProp === 'stop') | ||
$event.stopPropagation(); | ||
computeProperties(value, { $state: state, $el: el }, false); | ||
}; | ||
}; | ||
var textDirective = function (_a) { | ||
var el = _a.el, value = _a.value, state = _a.state; | ||
try { | ||
el.innerHTML = computeProperties(value, { $state: state, $el: el }); | ||
} | ||
catch (_b) { | ||
el.innerHTML = value; | ||
} | ||
}; | ||
var directives = { | ||
BIND: bindDirective, | ||
JOIN: joinDirective, | ||
HTML: htmlDirective, | ||
IF: ifDirective, | ||
MODEL: modelDirective, | ||
ON: onDirective, | ||
TEXT: textDirective, | ||
}; | ||
var renderDirective = function (_a, directives) { | ||
var el = _a.el, name = _a.name, value = _a.value, state = _a.state; | ||
var rootName = name.split(rawDirectiveSplitPattern)[0]; | ||
directives[rootName.toUpperCase()]({ el: el, name: name, value: value, state: state }); | ||
}; | ||
var arrayEquals = function (firstArray, secondArray) { | ||
@@ -485,3 +472,4 @@ return (firstArray instanceof Array && | ||
var handleArray = function (target, key, state, patch) { | ||
var handlePatch = function (target, key, state, patch, needsUpdate) { | ||
if (needsUpdate === void 0) { needsUpdate = false; } | ||
if (key === 'length') { | ||
@@ -496,3 +484,4 @@ var affectedKeys = Object.keys(state).filter(function (k) { | ||
else { | ||
patch([key]); | ||
if (needsUpdate) | ||
patch([key]); | ||
return false; | ||
@@ -512,4 +501,7 @@ } | ||
set: function (target, key, value) { | ||
target[key] = value; | ||
handleArray(target, key, state, patch); | ||
var needsUpdate = target[key] !== value; | ||
if (needsUpdate) { | ||
target[key] = value; | ||
} | ||
handlePatch(target, key, state, patch, needsUpdate); | ||
return true; | ||
@@ -519,3 +511,3 @@ }, | ||
delete target[key]; | ||
handleArray(target, key, state, patch); | ||
handlePatch(target, key, state, patch); | ||
return true; | ||
@@ -527,7 +519,7 @@ }, | ||
var patch = function (rootVNode, state, directiveKV, keys) { | ||
var patch = function (rootVNode, app, keys) { | ||
var e_1, _a; | ||
if (state === void 0) { state = {}; } | ||
if (directiveKV === void 0) { directiveKV = {}; } | ||
var compileRequest = false; | ||
if (app === void 0) { app = {}; } | ||
var firstRender = false; | ||
var state = app.state || {}; | ||
if (!rootVNode) | ||
@@ -537,4 +529,4 @@ return; | ||
keys = Object.keys(state); | ||
if (keys[0] === LUCIA_COMPILE_REQUEST) | ||
compileRequest = true; | ||
if (keys[0] === LUCIA_FIRST_RENDER) | ||
firstRender = true; | ||
var _loop_1 = function (node) { | ||
@@ -546,10 +538,9 @@ if (typeof node === 'string') | ||
var affectedDirectives = []; | ||
if (!compileRequest) { | ||
if (!firstRender) { | ||
var _loop_2 = function (name_1) { | ||
var value = directives_1[name_1]; | ||
var needsInit = type === 1; | ||
var hasKey = keys.some(function (key) { return keyPattern(key).test(value.toString()); }); | ||
var hasKey = keys.some(function (key) { return keyPattern(key).test(String(directives_1[name_1].value)); }); | ||
var hasKeyInFunction = Object.keys(state).some(function (key) { | ||
var iterKeysInFunction = keys.some(function (k) { | ||
return keyPattern(k).test(state[key].toString()); | ||
return keyPattern(k).test(String(state[key])); | ||
}); | ||
@@ -567,13 +558,13 @@ return typeof state[key] === 'function' && iterKeysInFunction; | ||
node.props.type = type === VNodeTypes.NEEDS_PATCH ? VNodeTypes.STATIC : type; | ||
var directivesToRender = compileRequest | ||
var directivesToRender = firstRender | ||
? Object.keys(directives_1) | ||
: affectedDirectives; | ||
directivesToRender.map(function (name) { | ||
var value = directives_1[name]; | ||
var data = directives_1[name]; | ||
var el = (attributes_1.id ? document.getElementById(attributes_1.id) : ref_1); | ||
renderDirective({ el: el, name: name, value: value, state: state }, __assign({}, directiveKV)); | ||
renderDirective({ el: el, name: name, data: data, app: app }, __assign({}, app.directives)); | ||
}); | ||
} | ||
if (node.children.length > 0) | ||
patch(node, state, directiveKV, keys); | ||
patch(node, state, keys); | ||
}; | ||
@@ -596,31 +587,35 @@ try { | ||
var App = (function () { | ||
function App(state) { | ||
function App(state, mountHook) { | ||
if (state === void 0) { state = {}; } | ||
this.vdom = null; | ||
this.state = state; | ||
this.directives = {}; | ||
this.components = {}; | ||
this.mounted = false; | ||
this.mountHook = mountHook; | ||
} | ||
App.prototype.mount = function (el, shallow) { | ||
if (shallow === void 0) { shallow = false; } | ||
this.vdom = this.compile((typeof el === 'string' ? document.querySelector(el) : el)); | ||
var rootEl = typeof el === 'string' ? document.querySelector(el) : el; | ||
this.vdom = this.compile(rootEl); | ||
if (!shallow) { | ||
this.state = reactive(this.state, this.patch.bind(this)); | ||
this.directives = directives; | ||
this.directives = __assign(__assign({}, this.directives), directives); | ||
} | ||
this.mounted = true; | ||
this.patch([LUCIA_COMPILE_REQUEST]); | ||
this.patch([LUCIA_FIRST_RENDER]); | ||
if (this.mountHook) | ||
this.mountHook(this.state); | ||
return this.state; | ||
}; | ||
App.prototype.component = function (name, fn) { | ||
this.components[name.toUpperCase()] = fn; | ||
App.prototype.component = function (name, templateCallback) { | ||
this.components[name.toUpperCase()] = templateCallback; | ||
}; | ||
App.prototype.directive = function (name, fn) { | ||
this.directives[name.toUpperCase()] = fn; | ||
App.prototype.directive = function (name, evaluationCallback) { | ||
this.directives[name.toUpperCase()] = evaluationCallback; | ||
}; | ||
App.prototype.patch = function (keys) { | ||
if (!this.mounted) | ||
throw new Error('App is not mounted.'); | ||
patch(this.vdom, this.state, this.directives, keys); | ||
var app = { | ||
state: this.state, | ||
directives: this.directives, | ||
components: this.components, | ||
}; | ||
patch(this.vdom, app, keys); | ||
}; | ||
@@ -632,25 +627,47 @@ App.prototype.compile = function (el) { | ||
}()); | ||
var createApp = function (state) { | ||
return new App(state); | ||
var createApp = function (state, mountHook) { | ||
return new App(state, mountHook); | ||
}; | ||
var init = function (element, directive) { | ||
var stateDirective = DIRECTIVE_PREFIX + "state"; | ||
var init = function (element) { | ||
if (element === void 0) { element = document; } | ||
if (directive === void 0) { directive = 'use'; } | ||
var elements = __spread(element.querySelectorAll("[" + (DIRECTIVE_PREFIX + directive) + "]")); | ||
var apps = []; | ||
elements.map(function (el) { | ||
var state = el.getAttribute(DIRECTIVE_PREFIX + directive); | ||
if (state === null) | ||
return; | ||
var elements = __spread(element.querySelectorAll("[" + stateDirective + "]")); | ||
elements | ||
.filter(function (el) { return el.__l === undefined; }) | ||
.map(function (el) { | ||
var expression = el.getAttribute(stateDirective); | ||
try { | ||
var app = createApp(safeEval(state)); | ||
var state = new Function("return " + expression)(); | ||
var app = createApp(state); | ||
app.mount(el); | ||
apps.push(app); | ||
el.__l = app; | ||
} | ||
catch (err) { } | ||
catch (err) { | ||
console.warn("Lucia Error: \"" + err + "\"\n\nExpression: \"" + expression + "\"\nElement:", el); | ||
} | ||
}); | ||
return apps; | ||
}; | ||
var listen = function (callback, element, config) { | ||
if (element === void 0) { element = document; } | ||
var observer = new MutationObserver(function (mutations) { | ||
mutations.map(function (mut) { | ||
if (mut.addedNodes.length > 0) { | ||
mut.addedNodes.forEach(function (node) { | ||
if (node.nodeType !== 1) | ||
return; | ||
if (node.parentElement && node.parentElement.closest("[" + stateDirective + "]")) | ||
return; | ||
callback(node.parentElement); | ||
}); | ||
} | ||
}); | ||
observer.observe(element, config || { | ||
childList: true, | ||
attributes: true, | ||
subtree: true, | ||
}); | ||
}); | ||
}; | ||
export { compile, createApp, directives, h, init, patch, reactive, renderDirective }; | ||
export { compile, createApp, directives, h, init, listen, patch, reactive, renderDirective }; |
@@ -1,1 +0,1 @@ | ||
var t=function(){return(t=Object.assign||function(t){for(var e,r=1,n=arguments.length;r<n;r++)for(var i in e=arguments[r])Object.prototype.hasOwnProperty.call(e,i)&&(t[i]=e[i]);return t}).apply(this,arguments)};function e(t){var e="function"==typeof Symbol&&Symbol.iterator,r=e&&t[e],n=0;if(r)return r.call(t);if(t&&"number"==typeof t.length)return{next:function(){return t&&n>=t.length&&(t=void 0),{value:t&&t[n++],done:!t}}};throw new TypeError(e?"Object is not iterable.":"Symbol.iterator is not defined.")}function r(t,e){var r="function"==typeof Symbol&&t[Symbol.iterator];if(!r)return t;var n,i,o=r.call(t),a=[];try{for(;(void 0===e||e-- >0)&&!(n=o.next()).done;)a.push(n.value)}catch(t){i={error:t}}finally{try{n&&!n.done&&(r=o.return)&&r.call(o)}finally{if(i)throw i.error}}return a}function n(){for(var t=[],e=0;e<arguments.length;e++)t=t.concat(r(arguments[e]));return t}var i,o;!function(t){t["@"]="ON",t[":"]="BIND"}(i||(i={})),function(t){t[t.STATIC=0]="STATIC",t[t.NEEDS_PATCH=1]="NEEDS_PATCH",t[t.DYNAMIC=2]="DYNAMIC"}(o||(o={}));var a=/:|\./,l=/(?=\.)|(?=#)|(?=\[)/,s=function(t,e){return void 0===e&&(e=!0),new RegExp((e?"this\\.":"")+t+"\\b")},u=function(n,i,o){var a,s,u=n.split(l),c=u[0],v=t({},null==o?void 0:o.attributes),f=t({},null==o?void 0:o.directives);if(u.length>1){u.shift();try{for(var d=e(u),y=d.next();!y.done;y=d.next()){var p=y.value;switch(p[0]){case"#":v.id=p.slice(1);break;case".":v.className||(v.className=""),v.className+=p.slice(1)+" ";break;case"[":var h=r(p.slice(1,-1).split("="),2),m=h[0],b=h[1];m.startsWith("l-")?f[m.slice("l-".length)]=b:v[m]=b}}}catch(t){a={error:t}}finally{try{y&&!y.done&&(s=d.return)&&s.call(d)}finally{if(a)throw a.error}}}return v.className&&(v.className=v.className.trim()),{tag:c,children:"string"==typeof i?[i]:i||[],props:{attributes:v,directives:f,ref:(null==o?void 0:o.ref)||void 0,type:(null==o?void 0:o.type)||0}}},c=function(t){var r,o,a={},l={};if(t.attributes)try{for(var s=e(n(t.attributes)),u=s.next();!u.done;u=s.next()){var c=u.value,v=c.name,f=c.value;v.startsWith("l-")?l[v.slice("l-".length)]=f:Object.keys(i).includes(v[0])?l[i[v[0]]+":"+v.slice(1)]=f:a[v]=f}}catch(t){r={error:t}}finally{try{u&&!u.done&&(o=s.return)&&o.call(s)}finally{if(r)throw r.error}}return{attributes:a,directives:l}},v=function(t,e,r){var n=c(t),i=n.attributes,a=n.directives,l=o.STATIC,v=Object.keys(a).length>0,f=Object.values(a).some((function(t){return Object.keys(e).some((function(e){return s(e,!1).test(t)}))}));return v&&(l=o.NEEDS_PATCH),f&&(l=o.DYNAMIC),u(t.tagName.toLowerCase(),r,{attributes:i,directives:a,ref:l===o.STATIC||i.id?void 0:t,type:l})},f=function(t,n,i,o,a){var l,s,u,y,p,h,m;if(void 0===n&&(n={}),void 0===i&&(i={}),void 0===o&&(o=!1),void 0===a&&(a=!1),!t)throw new Error("Please provide a Element");var b=[],T=Array.prototype.slice.call(t.childNodes);try{for(var N=e(T),g=N.next();!g.done;g=N.next()){var A=g.value;switch(A.nodeType){case Node.TEXT_NODE:!o&&A.nodeValue&&b.push(A.nodeValue);break;case Node.ELEMENT_NODE:if(Object.keys(i).includes(A.tagName)){var E=document.createElement("div"),w=i[A.tagName]({children:A.innerHTML,state:n});E.innerHTML=w;try{for(var x=(u=void 0,e(Object.entries(c(A).directives))),C=x.next();!C.done;C=x.next()){var O=r(C.value,2),$=O[0],S=O[1];null===(m=E.firstElementChild)||void 0===m||m.setAttribute("l-"+$,S)}}catch(t){u={error:t}}finally{try{C&&!C.done&&(y=x.return)&&y.call(x)}finally{if(u)throw u.error}}if(!o||E.outerHTML.includes(" l-")){var j=f(E,n,i,o,!0);try{for(var I=(p=void 0,e(j)),L=I.next();!L.done;L=I.next()){var M=L.value;b.push(M)}}catch(t){p={error:t}}finally{try{L&&!L.done&&(h=I.return)&&h.call(I)}finally{if(p)throw p.error}}}t.replaceChild(E.firstElementChild,A)}else if(!o||A.outerHTML.includes(" l-")){j=f(A,n,i,o,!0);var H=v(A,n,j);b.push(H)}}}}catch(t){l={error:t}}finally{try{g&&!g.done&&(s=N.return)&&s.call(N)}finally{if(l)throw l.error}}if(a)return b;var P=v(t,n,b);return o?d(P):P},d=function(r){var n,i,o,a,l=t({},r);l.children.filter((function(t){return"object"==typeof t&&t.props.type>0}));try{for(var s=e(r.children),u=s.next();!u.done;u=s.next()){var c=u.value;if("string"!=typeof c&&c.children.length>0)try{for(var v=(o=void 0,e(d(c).children)),f=v.next();!f.done;f=v.next()){var y=f.value;"string"!=typeof y&&(0!==y.props.type&&l.children.push(y))}}catch(t){o={error:t}}finally{try{f&&!f.done&&(a=v.return)&&a.call(v)}finally{if(o)throw o.error}}}}catch(t){n={error:t}}finally{try{u&&!u.done&&(i=s.return)&&i.call(s)}finally{if(n)throw n.error}}return l},y=function(t,e,r,i){return void 0===e&&(e={}),void 0===r&&(r={}),void 0===i&&(i=!0),(new(Function.bind.apply(Function,n([void 0],Object.keys(e),[i?"return "+t:t])))).bind(r).apply(void 0,n(Object.values(e)))},p=function(t,e,r){return void 0===r&&(r=!0),y(t,{$el:e.$el},e.$state,r)},h={BIND:function(t){var e=t.el,r=t.name,n=t.value,i=t.state;switch(r.split(":")[1]){case"class":var o=p(n,{$state:i,$el:e});if("string"==typeof o)return e.setAttribute("class",(e.className+" "+o).trim());if(o instanceof Array)return e.setAttribute("class",(e.className+" "+o.join(" ")).trim());var a=[];for(var l in o)o[l]&&a.push(l);return a.length>0?e.setAttribute("class",(e.className+" "+a.join(" ").trim()).trim()):e.className.trim().length>0?e.setAttribute("class",e.className):e.removeAttribute("class");case"style":var s=p(n,{$state:i,$el:e});for(var l in e.removeAttribute("style"),s)e.style[l]=s[l];break;default:var u=p(n,{$state:i,$el:e});u?e.setAttribute(r.split(":")[1],u):e.removeAttribute(r.split(":")[1])}},JOIN:function(e){var n=e.el,i=e.value,o=e.state,a=r(i.split(/ as | by /),3),l=a[0],s=a[1],u=a[2],c=p(l,{$state:o,$el:n});n["text"===s?"innerText":"innerHTML"]=c.join(u||""),A(t({},o)).mount(n,!0)},HTML:function(e){var r=e.el,n=e.value,i=e.state;A(t({},i)).mount(r,!0);try{r.innerHTML=p(n,{$state:i,$el:r})}catch(t){r.innerHTML=n}},IF:function(t){var e=t.el,r=t.value,n=t.state;p(r,{$state:n,$el:e})?e.style.removeProperty("display"):e.style.display="none"},MODEL:function(t){var e=t.el,r=t.value,n=t.state,i=e,o=p(r,{$state:n,$el:i});i.value!==o&&(i.value=o),i.oninput=function(){var t,e="number"==typeof o&&!isNaN(i.value),a="boolean"==typeof o&&("true"===i.value||"false"===i.value),l=null==o&&("null"===i.value||"undefined"===i.value);t=e?"Number('"+i.value+"').toPrecision()":a?"Boolean('"+i.value+"')":l?"null"===i.value?null:void 0:"'"+i.value+"'",p(r+" = "+t,{$state:n,$el:i},!1)}},ON:function(t){var e=t.el,n=t.name,i=t.value,o=t.state,a=r(n.split("."),2),l=a[0],s=a[1],u=l.split(":")[1],c=s||null;e["on"+u]=function(t){"prevent"===c&&t.preventDefault(),"stop"===c&&t.stopPropagation(),p(i,{$state:o,$el:e},!1)}},TEXT:function(t){var e=t.el,r=t.value,n=t.state;try{e.innerHTML=p(r,{$state:n,$el:e})}catch(t){e.innerHTML=r}}},m=function(t,e){var r=t.el,n=t.name,i=t.value,o=t.state;e[n.split(a)[0].toUpperCase()]({el:r,name:n,value:i,state:o})},b=function(t,e,r,n){if("length"===e){var i=Object.keys(r).filter((function(e){return r[e]instanceof Array&&(n=t,i=r[e],n instanceof Array&&i instanceof Array&&n.length===i.length&&n.every((function(t,e){return t===i[e]})));var n,i}));return 0!==i.length&&n(i),!0}return n([e]),!1},T=function(t,e){var r={get:function(t,e){return"object"==typeof t[e]&&null!==t[e]?new Proxy(t[e],r):t[e]},set:function(r,n,i){return r[n]=i,b(r,n,t,e),!0},deleteProperty:function(r,n){return delete r[n],b(r,n,t,e),!0}};return new Proxy(t,r)},N=function(r,n,i,a){var l,u;void 0===n&&(n={}),void 0===i&&(i={});var c=!1;if(r){a||(a=Object.keys(n)),"%LUCIA_COMPILE_REQUEST%"===a[0]&&(c=!0);var v=function(e){if("string"==typeof e)return"continue";if(e.props.type>o.STATIC){var r=e.props,l=r.attributes,u=r.directives,v=r.ref,f=r.type,d=[];if(!c){var y=function(t){var e=u[t],r=1===f,i=a.some((function(t){return s(t).test(e.toString())})),o=Object.keys(n).some((function(t){var e=a.some((function(e){return s(e).test(n[t].toString())}));return"function"==typeof n[t]&&e}));(r||i||o)&&d.push(t)};for(var p in u)y(p)}e.props.type=f===o.NEEDS_PATCH?o.STATIC:f,(c?Object.keys(u):d).map((function(e){var r=u[e],o=l.id?document.getElementById(l.id):v;m({el:o,name:e,value:r,state:n},t({},i))}))}e.children.length>0&&N(e,n,i,a)};try{for(var f=e(r.children),d=f.next();!d.done;d=f.next()){v(d.value)}}catch(t){l={error:t}}finally{try{d&&!d.done&&(u=f.return)&&u.call(f)}finally{if(l)throw l.error}}}},g=function(){function t(t){void 0===t&&(t={}),this.vdom=null,this.state=t,this.directives={},this.components={},this.mounted=!1}return t.prototype.mount=function(t,e){return void 0===e&&(e=!1),this.vdom=this.compile("string"==typeof t?document.querySelector(t):t),e||(this.state=T(this.state,this.patch.bind(this)),this.directives=h),this.mounted=!0,this.patch(["%LUCIA_COMPILE_REQUEST%"]),this.state},t.prototype.component=function(t,e){this.components[t.toUpperCase()]=e},t.prototype.directive=function(t,e){this.directives[t.toUpperCase()]=e},t.prototype.patch=function(t){if(!this.mounted)throw new Error("App is not mounted.");N(this.vdom,this.state,this.directives,t)},t.prototype.compile=function(t){return f(t,this.state,this.components,!0)},t}(),A=function(t){return new g(t)},E=function(t,e){void 0===t&&(t=document),void 0===e&&(e="use");var r=n(t.querySelectorAll("[l-"+e+"]")),i=[];return r.map((function(t){var r=t.getAttribute("l-"+e);if(null!==r)try{var n=A(y(r));n.mount(t),i.push(n)}catch(t){}})),i};export{f as compile,A as createApp,h as directives,u as h,E as init,N as patch,T as reactive,m as renderDirective}; | ||
var t=function(){return(t=Object.assign||function(t){for(var e,r=1,n=arguments.length;r<n;r++)for(var i in e=arguments[r])Object.prototype.hasOwnProperty.call(e,i)&&(t[i]=e[i]);return t}).apply(this,arguments)};function e(t){var e="function"==typeof Symbol&&Symbol.iterator,r=e&&t[e],n=0;if(r)return r.call(t);if(t&&"number"==typeof t.length)return{next:function(){return t&&n>=t.length&&(t=void 0),{value:t&&t[n++],done:!t}}};throw new TypeError(e?"Object is not iterable.":"Symbol.iterator is not defined.")}function r(t,e){var r="function"==typeof Symbol&&t[Symbol.iterator];if(!r)return t;var n,i,o=r.call(t),a=[];try{for(;(void 0===e||e-- >0)&&!(n=o.next()).done;)a.push(n.value)}catch(t){i={error:t}}finally{try{n&&!n.done&&(r=o.return)&&r.call(o)}finally{if(i)throw i.error}}return a}function n(){for(var t=[],e=0;e<arguments.length;e++)t=t.concat(r(arguments[e]));return t}var i;!function(t){t["@"]="on",t[":"]="bind"}(i||(i={}));var o=/:|\./,a=function(t,e){return void 0===e&&(e=!0),new RegExp((e?"this\\.":"")+t+"\\b")};function l(t){try{var e=this.returnable?"return "+this.expression:this.expression;return(new(Function.bind.apply(Function,n([void 0],Object.keys(this.argsKV),[e])))).bind(t).apply(void 0,n(Object.values(this.argsKV)))}catch(t){console.warn('Lucia Error: "'+t+'"\n\nExpression: "'+this.expression+'"\nElement:',this.argsKV.$el)}}var s,u=function(t,e,r){return void 0===r&&(r=!0),l.bind({expression:t,argsKV:{$el:e.$el},returnable:r})},c={BIND:function(t){var e=t.el,r=t.name,n=t.data,i=t.app;switch(r.split(":")[1]){case"class":var o=n.compute(i.state);if("string"==typeof o)return e.setAttribute("class",(e.className+" "+o).trim());if(o instanceof Array)return e.setAttribute("class",(e.className+" "+o.join(" ")).trim());var a=[];for(var l in o)o[l]&&a.push(l);return a.length>0?e.setAttribute("class",(e.className+" "+a.join(" ").trim()).trim()):e.className.trim().length>0?e.setAttribute("class",e.className):e.removeAttribute("class");case"style":var s=n.compute(i.state);for(var l in e.removeAttribute("style"),s)e.style[l]=s[l];break;default:var u=n.compute(i.state);if("object"==typeof u&&null!==u)for(var l in u)u[l]?e.setAttribute(l,u[l]):e.removeAttribute(l);else u?e.setAttribute(r.split(":")[1],u):e.removeAttribute(r.split(":")[1])}},JOIN:function(e){var n=e.el,i=e.data,o=e.app,a=r(i.value.split(/ as | by /),3),l=a[0],s=a[1],c=a[2],v=u(l,{$el:n})(o.state);n["text"===s?"innerText":"innerHTML"]=v.join(c||"");var f=A(t({},o.state));Object.entries(o.directives||{}).map((function(t){var e=r(t,2),n=e[0],i=e[1];f.directive(n,i)})),Object.entries(o.components||{}).map((function(t){var e=r(t,2),n=e[0],i=e[1];f.component(n,i)})),f.mount(n)},HTML:function(e){var n,i=e.el,o=e.data,a=e.app;i.innerHTML=null!==(n=o.compute(a.state))&&void 0!==n?n:o.value;var l=A(t({},a.state));Object.entries(a.directives||{}).map((function(t){var e=r(t,2),n=e[0],i=e[1];l.directive(n,i)})),Object.entries(a.components||{}).map((function(t){var e=r(t,2),n=e[0],i=e[1];l.component(n,i)})),l.mount(i)},IF:function(t){var e=t.el,r=t.data,n=t.app;r.compute(n.state)?e.style.removeProperty("display"):e.style.display="none"},MODEL:function(t){var e=t.el,r=t.data,n=t.app,i=e,o=u(r.compute(),{$el:i})(n.state);i.value!==o&&(i.value=o),i.oninput=function(){var t,e="number"==typeof o&&!isNaN(i.value),a="boolean"==typeof o&&("true"===i.value||"false"===i.value),l=null==o&&("null"===i.value||"undefined"===i.value);t=e?"Number('"+i.value+"').toPrecision()":a?"Boolean('"+i.value+"')":l?"null"===i.value?null:void 0:"'"+i.value+"'",u(r.value+" = "+t,{$el:i},!1)(n.state)}},ON:function(t){var e=t.el,n=t.name,i=t.data,o=t.app,a=r(n.split("."),2),l=a[0],s=a[1],u=l.split(":")[1],c=s||null;e["on"+u]=function(t){"prevent"===c&&t.preventDefault(),"stop"===c&&t.stopPropagation(),i.compute(o.state)}},TEXT:function(t){var e,r=t.el,n=t.data,i=t.app;r.textContent=null!==(e=n.compute(i.state))&&void 0!==e?e:n.value}},v=function(t,e){e[t.name.split(o)[0].toUpperCase()](t)};!function(t){t[t.STATIC=0]="STATIC",t[t.NEEDS_PATCH=1]="NEEDS_PATCH",t[t.DYNAMIC=2]="DYNAMIC"}(s||(s={}));var f=function(e,r,n){void 0===r&&(r=[]);var i=t({},null==n?void 0:n.attributes),o=t({},null==n?void 0:n.directives);return r=r instanceof Array?r:[r],i.className&&(i.className=i.className.trim()),{tag:e,children:r,props:{attributes:i,directives:o,ref:(null==n?void 0:n.ref)||void 0,type:(null==n?void 0:n.type)||0}}},p=function(t){var r,o,a={},l={};if(t.attributes)try{for(var s=e(n(t.attributes)),c=s.next();!c.done;c=s.next()){var v=c.value,f=v.name,p=v.value,d={compute:u(p,{$el:t}),value:p};f.startsWith("l-")?l[f.slice("l-".length)]=d:Object.keys(i).includes(f[0])?l[i[f[0]]+":"+f.slice(1)]=d:a[f]=p}}catch(t){r={error:t}}finally{try{c&&!c.done&&(o=s.return)&&o.call(s)}finally{if(r)throw r.error}}return{attributes:a,directives:l}},d=function(t,e,r){var n=p(t),i=n.attributes,o=n.directives,l=s.STATIC,u=Object.keys(o).length>0,c=Object.values(o).some((function(t){var r=t.value;return Object.keys(e).some((function(t){return a(t,!1).test(r)}))}));return u&&(l=s.NEEDS_PATCH),c&&(l=s.DYNAMIC),f(t.tagName.toLowerCase(),r,{attributes:i,directives:o,ref:l===s.STATIC||i.id?void 0:t,type:l})},y=function(t,n,i,o,a){var l,s,u,c,v,f,m;if(void 0===n&&(n={}),void 0===i&&(i={}),void 0===o&&(o=!1),void 0===a&&(a=!1),!t)throw new Error("Please provide a Element");var b=[],E=Array.prototype.slice.call(t.childNodes);try{for(var g=e(E),A=g.next();!A.done;A=g.next()){var N=A.value;switch(N.nodeType){case Node.TEXT_NODE:!o&&N.nodeValue&&b.push(N.nodeValue);break;case Node.ELEMENT_NODE:if(Object.keys(i).includes(N.tagName)){var T=document.createElement("div"),x=i[N.tagName]({children:N.innerHTML,state:n});T.innerHTML=x;try{for(var O=(u=void 0,e(Object.entries(p(N).directives))),j=O.next();!j.done;j=O.next()){var w=r(j.value,2),C=w[0],S=w[1];null===(m=T.firstElementChild)||void 0===m||m.setAttribute("l-"+C,S.value)}}catch(t){u={error:t}}finally{try{j&&!j.done&&(c=O.return)&&c.call(O)}finally{if(u)throw u.error}}if(!o||T.outerHTML.includes(" l-")){var I=y(T,n,i,o,!0);try{for(var L=(v=void 0,e(I)),k=L.next();!k.done;k=L.next()){var D=k.value;b.push(D)}}catch(t){v={error:t}}finally{try{k&&!k.done&&(f=L.return)&&f.call(L)}finally{if(v)throw v.error}}}t.replaceChild(T.firstElementChild,N)}else if(!o||N.outerHTML.includes(" l-")){I=y(N,n,i,o,!0);var H=d(N,n,I);b.push(H)}}}}catch(t){l={error:t}}finally{try{A&&!A.done&&(s=g.return)&&s.call(g)}finally{if(l)throw l.error}}if(a)return b;var _=d(t,n,b);return o?h(_):_},h=function(r){var n,i,o,a,l=t({},r);l.children.filter((function(t){return"object"==typeof t&&t.props.type>0}));try{for(var s=e(r.children),u=s.next();!u.done;u=s.next()){var c=u.value;if("string"!=typeof c&&c.children.length>0)try{for(var v=(o=void 0,e(h(c).children)),f=v.next();!f.done;f=v.next()){var p=f.value;"string"!=typeof p&&(0!==p.props.type&&l.children.push(p))}}catch(t){o={error:t}}finally{try{f&&!f.done&&(a=v.return)&&a.call(v)}finally{if(o)throw o.error}}}}catch(t){n={error:t}}finally{try{u&&!u.done&&(i=s.return)&&i.call(s)}finally{if(n)throw n.error}}return l},m=function(t,e,r,n,i){if(void 0===i&&(i=!1),"length"===e){var o=Object.keys(r).filter((function(e){return r[e]instanceof Array&&(n=t,i=r[e],n instanceof Array&&i instanceof Array&&n.length===i.length&&n.every((function(t,e){return t===i[e]})));var n,i}));return 0!==o.length&&n(o),!0}return i&&n([e]),!1},b=function(t,e){var r={get:function(t,e){return"object"==typeof t[e]&&null!==t[e]?new Proxy(t[e],r):t[e]},set:function(r,n,i){var o=r[n]!==i;return o&&(r[n]=i),m(r,n,t,e,o),!0},deleteProperty:function(r,n){return delete r[n],m(r,n,t,e),!0}};return new Proxy(t,r)},E=function(r,n,i){var o,l;void 0===n&&(n={});var u=!1,c=n.state||{};if(r){i||(i=Object.keys(c)),"%LUCIA_FIRST_RENDER%"===i[0]&&(u=!0);var f=function(e){if("string"==typeof e)return"continue";if(e.props.type>s.STATIC){var r=e.props,o=r.attributes,l=r.directives,f=r.ref,p=r.type,d=[];if(!u){var y=function(t){var e=1===p,r=i.some((function(e){return a(e).test(String(l[t].value))})),n=Object.keys(c).some((function(t){var e=i.some((function(e){return a(e).test(String(c[t]))}));return"function"==typeof c[t]&&e}));(e||r||n)&&d.push(t)};for(var h in l)y(h)}e.props.type=p===s.NEEDS_PATCH?s.STATIC:p,(u?Object.keys(l):d).map((function(e){var r=l[e],i=o.id?document.getElementById(o.id):f;v({el:i,name:e,data:r,app:n},t({},n.directives))}))}e.children.length>0&&E(e,c,i)};try{for(var p=e(r.children),d=p.next();!d.done;d=p.next()){f(d.value)}}catch(t){o={error:t}}finally{try{d&&!d.done&&(l=p.return)&&l.call(p)}finally{if(o)throw o.error}}}},g=function(){function e(t,e){void 0===t&&(t={}),this.state=t,this.directives={},this.components={},this.mountHook=e}return e.prototype.mount=function(e,r){void 0===r&&(r=!1);var n="string"==typeof e?document.querySelector(e):e;return this.vdom=this.compile(n),r||(this.state=b(this.state,this.patch.bind(this)),this.directives=t(t({},this.directives),c)),this.patch(["%LUCIA_FIRST_RENDER%"]),this.mountHook&&this.mountHook(this.state),this.state},e.prototype.component=function(t,e){this.components[t.toUpperCase()]=e},e.prototype.directive=function(t,e){this.directives[t.toUpperCase()]=e},e.prototype.patch=function(t){var e={state:this.state,directives:this.directives,components:this.components};E(this.vdom,e,t)},e.prototype.compile=function(t){return y(t,this.state,this.components,!0)},e}(),A=function(t,e){return new g(t,e)},N=function(t){void 0===t&&(t=document),n(t.querySelectorAll("[l-state]")).filter((function(t){return void 0===t.__l})).map((function(t){var e=t.getAttribute("l-state");try{var r=new Function("return "+e)(),n=A(r);n.mount(t),t.__l=n}catch(r){console.warn('Lucia Error: "'+r+'"\n\nExpression: "'+e+'"\nElement:',t)}}))},T=function(t,e,r){void 0===e&&(e=document);var n=new MutationObserver((function(i){i.map((function(e){e.addedNodes.length>0&&e.addedNodes.forEach((function(e){1===e.nodeType&&(e.parentElement&&e.parentElement.closest("[l-state]")||t(e.parentElement))}))})),n.observe(e,r||{childList:!0,attributes:!0,subtree:!0})}))};export{y as compile,A as createApp,c as directives,f as h,N as init,T as listen,E as patch,b as reactive,v as renderDirective}; |
@@ -69,18 +69,10 @@ (function (global, factory) { | ||
var DIRECTIVE_PREFIX = 'l-'; | ||
var LUCIA_COMPILE_REQUEST = '%LUCIA_COMPILE_REQUEST%'; | ||
var LUCIA_FIRST_RENDER = '%LUCIA_FIRST_RENDER%'; | ||
var DIRECTIVE_SHORTHANDS; | ||
(function (DIRECTIVE_SHORTHANDS) { | ||
DIRECTIVE_SHORTHANDS["@"] = "ON"; | ||
DIRECTIVE_SHORTHANDS[":"] = "BIND"; | ||
DIRECTIVE_SHORTHANDS["@"] = "on"; | ||
DIRECTIVE_SHORTHANDS[":"] = "bind"; | ||
})(DIRECTIVE_SHORTHANDS || (DIRECTIVE_SHORTHANDS = {})); | ||
var VNodeTypes; | ||
(function (VNodeTypes) { | ||
VNodeTypes[VNodeTypes["STATIC"] = 0] = "STATIC"; | ||
VNodeTypes[VNodeTypes["NEEDS_PATCH"] = 1] = "NEEDS_PATCH"; | ||
VNodeTypes[VNodeTypes["DYNAMIC"] = 2] = "DYNAMIC"; | ||
})(VNodeTypes || (VNodeTypes = {})); | ||
var rawDirectiveSplitPattern = /:|\./; | ||
var selectorSplitPattern = /(?=\.)|(?=#)|(?=\[)/; | ||
var keyPattern = function (key, hasThis) { | ||
@@ -91,42 +83,195 @@ if (hasThis === void 0) { hasThis = true; } | ||
var h = function (selector, children, props) { | ||
var e_1, _a; | ||
var tokens = selector.split(selectorSplitPattern); | ||
var tag = tokens[0]; | ||
var attributes = __assign({}, props === null || props === void 0 ? void 0 : props.attributes); | ||
var directives = __assign({}, props === null || props === void 0 ? void 0 : props.directives); | ||
if (tokens.length > 1) { | ||
tokens.shift(); | ||
try { | ||
for (var tokens_1 = __values(tokens), tokens_1_1 = tokens_1.next(); !tokens_1_1.done; tokens_1_1 = tokens_1.next()) { | ||
var token = tokens_1_1.value; | ||
switch (token[0]) { | ||
case '#': | ||
attributes.id = token.slice(1); | ||
break; | ||
case '.': | ||
if (!attributes.className) | ||
attributes.className = ''; | ||
attributes.className += token.slice(1) + " "; | ||
break; | ||
case '[': | ||
var _b = __read(token.slice(1, -1).split('='), 2), key = _b[0], value = _b[1]; | ||
if (key.startsWith(DIRECTIVE_PREFIX)) { | ||
directives[key.slice(DIRECTIVE_PREFIX.length)] = value; | ||
} | ||
else { | ||
attributes[key] = value; | ||
} | ||
break; | ||
var bindDirective = function (_a) { | ||
var el = _a.el, name = _a.name, data = _a.data, app = _a.app; | ||
switch (name.split(':')[1]) { | ||
case 'class': | ||
var hydratedClasses = data.compute(app.state); | ||
if (typeof hydratedClasses === 'string') { | ||
return el.setAttribute('class', (el.className + " " + hydratedClasses).trim()); | ||
} | ||
else if (hydratedClasses instanceof Array) { | ||
return el.setAttribute('class', (el.className + " " + hydratedClasses.join(' ')).trim()); | ||
} | ||
else { | ||
var classes = []; | ||
for (var key in hydratedClasses) { | ||
if (hydratedClasses[key]) | ||
classes.push(key); | ||
} | ||
if (classes.length > 0) { | ||
return el.setAttribute('class', (el.className + " " + classes.join(' ').trim()).trim()); | ||
} | ||
else if (el.className.trim().length > 0) { | ||
return el.setAttribute('class', el.className); | ||
} | ||
else { | ||
return el.removeAttribute('class'); | ||
} | ||
} | ||
} | ||
catch (e_1_1) { e_1 = { error: e_1_1 }; } | ||
finally { | ||
try { | ||
if (tokens_1_1 && !tokens_1_1.done && (_a = tokens_1.return)) _a.call(tokens_1); | ||
case 'style': | ||
var hydratedStyles = data.compute(app.state); | ||
el.removeAttribute('style'); | ||
for (var key in hydratedStyles) { | ||
el.style[key] = hydratedStyles[key]; | ||
} | ||
finally { if (e_1) throw e_1.error; } | ||
break; | ||
default: | ||
var hydratedAttributes = data.compute(app.state); | ||
if (typeof hydratedAttributes === 'object' && hydratedAttributes !== null) { | ||
for (var key in hydratedAttributes) { | ||
if (hydratedAttributes[key]) { | ||
el.setAttribute(key, hydratedAttributes[key]); | ||
} | ||
else { | ||
el.removeAttribute(key); | ||
} | ||
} | ||
} | ||
else if (hydratedAttributes) { | ||
el.setAttribute(name.split(':')[1], hydratedAttributes); | ||
} | ||
else { | ||
el.removeAttribute(name.split(':')[1]); | ||
} | ||
break; | ||
} | ||
}; | ||
var htmlDirective = function (_a) { | ||
var _b; | ||
var el = _a.el, data = _a.data, app = _a.app; | ||
el.innerHTML = (_b = data.compute(app.state)) !== null && _b !== void 0 ? _b : data.value; | ||
var scope = createApp(__assign({}, app.state)); | ||
Object.entries(app.directives || {}).map(function (_a) { | ||
var _b = __read(_a, 2), name = _b[0], evaluationCallback = _b[1]; | ||
scope.directive(name, evaluationCallback); | ||
}); | ||
Object.entries(app.components || {}).map(function (_a) { | ||
var _b = __read(_a, 2), name = _b[0], templateCallback = _b[1]; | ||
scope.component(name, templateCallback); | ||
}); | ||
scope.mount(el); | ||
}; | ||
var ifDirective = function (_a) { | ||
var el = _a.el, data = _a.data, app = _a.app; | ||
var hydratedConditional = data.compute(app.state); | ||
if (hydratedConditional) { | ||
el.style.removeProperty('display'); | ||
} | ||
else { | ||
el.style.display = 'none'; | ||
} | ||
}; | ||
function createComputeFunction(state) { | ||
try { | ||
var expression = this.returnable ? "return " + this.expression : this.expression; | ||
return new (Function.bind.apply(Function, __spread([void 0], Object.keys(this.argsKV), [expression])))().bind(state).apply(void 0, __spread(Object.values(this.argsKV))); | ||
} | ||
catch (err) { | ||
console.warn("Lucia Error: \"" + err + "\"\n\nExpression: \"" + this.expression + "\"\nElement:", this.argsKV.$el); | ||
} | ||
} | ||
var compute = function (expression, data, returnable) { | ||
if (returnable === void 0) { returnable = true; } | ||
return createComputeFunction.bind({ expression: expression, argsKV: { $el: data.$el }, returnable: returnable }); | ||
}; | ||
var joinDirective = function (_a) { | ||
var el = _a.el, data = _a.data, app = _a.app; | ||
var _b = __read(data.value.split(/ as | by /), 3), array = _b[0], contentType = _b[1], delimiter = _b[2]; | ||
var hydratedArray = compute(array, { $el: el })(app.state); | ||
var accessProp = contentType === 'text' ? 'innerText' : 'innerHTML'; | ||
el[accessProp] = hydratedArray.join(delimiter || ''); | ||
var scope = createApp(__assign({}, app.state)); | ||
Object.entries(app.directives || {}).map(function (_a) { | ||
var _b = __read(_a, 2), name = _b[0], evaluationCallback = _b[1]; | ||
scope.directive(name, evaluationCallback); | ||
}); | ||
Object.entries(app.components || {}).map(function (_a) { | ||
var _b = __read(_a, 2), name = _b[0], templateCallback = _b[1]; | ||
scope.component(name, templateCallback); | ||
}); | ||
scope.mount(el); | ||
}; | ||
var modelDirective = function (_a) { | ||
var awaitingTypecastEl = _a.el, data = _a.data, app = _a.app; | ||
var el = awaitingTypecastEl; | ||
var hydratedValue = compute(data.compute(), { $el: el })(app.state); | ||
if (el.value !== hydratedValue) { | ||
el.value = hydratedValue; | ||
} | ||
el.oninput = function () { | ||
var isNumber = typeof hydratedValue === 'number' && !isNaN(el.value); | ||
var isBoolean = typeof hydratedValue === 'boolean' && (el.value === 'true' || el.value === 'false'); | ||
var isNullish = (hydratedValue === null || hydratedValue === undefined) && | ||
(el.value === 'null' || el.value === 'undefined'); | ||
var payload; | ||
if (isNumber) { | ||
payload = "Number('" + el.value + "').toPrecision()"; | ||
} | ||
} | ||
else if (isBoolean) { | ||
payload = "Boolean('" + el.value + "')"; | ||
} | ||
else if (isNullish) { | ||
if (el.value === 'null') | ||
payload = null; | ||
else | ||
payload = undefined; | ||
} | ||
else { | ||
payload = "'" + el.value + "'"; | ||
} | ||
compute(data.value + " = " + payload, { $el: el }, false)(app.state); | ||
}; | ||
}; | ||
var onDirective = function (_a) { | ||
var el = _a.el, name = _a.name, data = _a.data, app = _a.app; | ||
var _b = __read(name.split('.'), 2), directiveAndEventName = _b[0], prop = _b[1]; | ||
var eventName = directiveAndEventName.split(':')[1]; | ||
var eventProp = prop || null; | ||
el["on" + eventName] = function ($event) { | ||
if (eventProp === 'prevent') | ||
$event.preventDefault(); | ||
if (eventProp === 'stop') | ||
$event.stopPropagation(); | ||
data.compute(app.state); | ||
}; | ||
}; | ||
var textDirective = function (_a) { | ||
var _b; | ||
var el = _a.el, data = _a.data, app = _a.app; | ||
el.textContent = (_b = data.compute(app.state)) !== null && _b !== void 0 ? _b : data.value; | ||
}; | ||
var directives = { | ||
BIND: bindDirective, | ||
JOIN: joinDirective, | ||
HTML: htmlDirective, | ||
IF: ifDirective, | ||
MODEL: modelDirective, | ||
ON: onDirective, | ||
TEXT: textDirective, | ||
}; | ||
var renderDirective = function (props, directives) { | ||
var name = props.name.split(rawDirectiveSplitPattern)[0]; | ||
directives[name.toUpperCase()](props); | ||
}; | ||
var VNodeTypes; | ||
(function (VNodeTypes) { | ||
VNodeTypes[VNodeTypes["STATIC"] = 0] = "STATIC"; | ||
VNodeTypes[VNodeTypes["NEEDS_PATCH"] = 1] = "NEEDS_PATCH"; | ||
VNodeTypes[VNodeTypes["DYNAMIC"] = 2] = "DYNAMIC"; | ||
})(VNodeTypes || (VNodeTypes = {})); | ||
var h = function (tag, children, props) { | ||
if (children === void 0) { children = []; } | ||
var attributes = __assign({}, props === null || props === void 0 ? void 0 : props.attributes); | ||
var directives = __assign({}, props === null || props === void 0 ? void 0 : props.directives); | ||
children = children instanceof Array ? children : [children]; | ||
if (attributes.className) | ||
@@ -136,3 +281,3 @@ attributes.className = attributes.className.trim(); | ||
tag: tag, | ||
children: typeof children === 'string' ? [children] : children ? children : [], | ||
children: children, | ||
props: { | ||
@@ -155,7 +300,8 @@ attributes: attributes, | ||
var _d = _c.value, name_1 = _d.name, value = _d.value; | ||
var directiveData = { compute: compute(value, { $el: el }), value: value }; | ||
if (name_1.startsWith(DIRECTIVE_PREFIX)) { | ||
directives[name_1.slice(DIRECTIVE_PREFIX.length)] = value; | ||
directives[name_1.slice(DIRECTIVE_PREFIX.length)] = directiveData; | ||
} | ||
else if (Object.keys(DIRECTIVE_SHORTHANDS).includes(name_1[0])) { | ||
directives[DIRECTIVE_SHORTHANDS[name_1[0]] + ":" + name_1.slice(1)] = value; | ||
directives[DIRECTIVE_SHORTHANDS[name_1[0]] + ":" + name_1.slice(1)] = directiveData; | ||
} | ||
@@ -182,3 +328,4 @@ else { | ||
var hasDirectives = Object.keys(directives).length > 0; | ||
var hasKeyInDirectives = Object.values(directives).some(function (value) { | ||
var hasKeyInDirectives = Object.values(directives).some(function (_a) { | ||
var value = _a.value; | ||
return Object.keys(state).some(function (key) { return keyPattern(key, false).test(value); }); | ||
@@ -227,4 +374,4 @@ }); | ||
for (var _e = (e_2 = void 0, __values(Object.entries(props(child).directives))), _f = _e.next(); !_f.done; _f = _e.next()) { | ||
var _g = __read(_f.value, 2), key = _g[0], value = _g[1]; | ||
(_d = container.firstElementChild) === null || _d === void 0 ? void 0 : _d.setAttribute("" + DIRECTIVE_PREFIX + key, value); | ||
var _g = __read(_f.value, 2), key = _g[0], data = _g[1]; | ||
(_d = container.firstElementChild) === null || _d === void 0 ? void 0 : _d.setAttribute("" + DIRECTIVE_PREFIX + key, data.value); | ||
} | ||
@@ -323,162 +470,2 @@ } | ||
var safeEval = function (expression, argsKV, bindKV, returnable) { | ||
if (argsKV === void 0) { argsKV = {}; } | ||
if (bindKV === void 0) { bindKV = {}; } | ||
if (returnable === void 0) { returnable = true; } | ||
return new (Function.bind.apply(Function, __spread([void 0], Object.keys(argsKV), [returnable ? "return " + expression : expression])))().bind(bindKV).apply(void 0, __spread(Object.values(argsKV))); | ||
}; | ||
var computeProperties = function (expression, data, returnable) { | ||
if (returnable === void 0) { returnable = true; } | ||
return safeEval(expression, { $el: data.$el }, data.$state, returnable); | ||
}; | ||
var bindDirective = function (_a) { | ||
var el = _a.el, name = _a.name, value = _a.value, state = _a.state; | ||
switch (name.split(':')[1]) { | ||
case 'class': | ||
var classState = computeProperties(value, { $state: state, $el: el }); | ||
if (typeof classState === 'string') { | ||
return el.setAttribute('class', (el.className + " " + classState).trim()); | ||
} | ||
if (classState instanceof Array) { | ||
return el.setAttribute('class', (el.className + " " + classState.join(' ')).trim()); | ||
} | ||
else { | ||
var classes = []; | ||
for (var key in classState) { | ||
if (classState[key]) | ||
classes.push(key); | ||
} | ||
if (classes.length > 0) { | ||
return el.setAttribute('class', (el.className + " " + classes.join(' ').trim()).trim()); | ||
} | ||
else if (el.className.trim().length > 0) { | ||
return el.setAttribute('class', el.className); | ||
} | ||
else { | ||
return el.removeAttribute('class'); | ||
} | ||
} | ||
case 'style': | ||
var styleState = computeProperties(value, { $state: state, $el: el }); | ||
el.removeAttribute('style'); | ||
for (var key in styleState) { | ||
el.style[key] = styleState[key]; | ||
} | ||
break; | ||
default: | ||
var out = computeProperties(value, { $state: state, $el: el }); | ||
if (out) { | ||
el.setAttribute(name.split(':')[1], out); | ||
} | ||
else { | ||
el.removeAttribute(name.split(':')[1]); | ||
} | ||
break; | ||
} | ||
}; | ||
var htmlDirective = function (_a) { | ||
var el = _a.el, value = _a.value, state = _a.state; | ||
var app = createApp(__assign({}, state)); | ||
app.mount(el, true); | ||
try { | ||
el.innerHTML = computeProperties(value, { $state: state, $el: el }); | ||
} | ||
catch (_b) { | ||
el.innerHTML = value; | ||
} | ||
}; | ||
var ifDirective = function (_a) { | ||
var el = _a.el, value = _a.value, state = _a.state; | ||
var out = computeProperties(value, { $state: state, $el: el }); | ||
if (out) { | ||
el.style.removeProperty('display'); | ||
} | ||
else { | ||
el.style.display = 'none'; | ||
} | ||
}; | ||
var joinDirective = function (_a) { | ||
var el = _a.el, value = _a.value, state = _a.state; | ||
var _b = __read(value.split(/ as | by /), 3), array = _b[0], contentType = _b[1], delimiter = _b[2]; | ||
var out = computeProperties(array, { $state: state, $el: el }); | ||
var accessProp = contentType === 'text' ? 'innerText' : 'innerHTML'; | ||
el[accessProp] = out.join(delimiter || ''); | ||
var app = createApp(__assign({}, state)); | ||
app.mount(el, true); | ||
}; | ||
var modelDirective = function (_a) { | ||
var awaitingTypecastEl = _a.el, value = _a.value, state = _a.state; | ||
var el = awaitingTypecastEl; | ||
var out = computeProperties(value, { $state: state, $el: el }); | ||
if (el.value !== out) { | ||
el.value = out; | ||
} | ||
el.oninput = function () { | ||
var isNumber = typeof out === 'number' && !isNaN(el.value); | ||
var isBoolean = typeof out === 'boolean' && (el.value === 'true' || el.value === 'false'); | ||
var isNullish = (out === null || out === undefined) && (el.value === 'null' || el.value === 'undefined'); | ||
var payload; | ||
if (isNumber) { | ||
payload = "Number('" + el.value + "').toPrecision()"; | ||
} | ||
else if (isBoolean) { | ||
payload = "Boolean('" + el.value + "')"; | ||
} | ||
else if (isNullish) { | ||
if (el.value === 'null') | ||
payload = null; | ||
else | ||
payload = undefined; | ||
} | ||
else { | ||
payload = "'" + el.value + "'"; | ||
} | ||
computeProperties(value + " = " + payload, { $state: state, $el: el }, false); | ||
}; | ||
}; | ||
var onDirective = function (_a) { | ||
var el = _a.el, name = _a.name, value = _a.value, state = _a.state; | ||
var _b = __read(name.split('.'), 2), directiveAndEventName = _b[0], prop = _b[1]; | ||
var eventName = directiveAndEventName.split(':')[1]; | ||
var eventProp = prop || null; | ||
el["on" + eventName] = function ($event) { | ||
if (eventProp === 'prevent') | ||
$event.preventDefault(); | ||
if (eventProp === 'stop') | ||
$event.stopPropagation(); | ||
computeProperties(value, { $state: state, $el: el }, false); | ||
}; | ||
}; | ||
var textDirective = function (_a) { | ||
var el = _a.el, value = _a.value, state = _a.state; | ||
try { | ||
el.innerHTML = computeProperties(value, { $state: state, $el: el }); | ||
} | ||
catch (_b) { | ||
el.innerHTML = value; | ||
} | ||
}; | ||
var directives = { | ||
BIND: bindDirective, | ||
JOIN: joinDirective, | ||
HTML: htmlDirective, | ||
IF: ifDirective, | ||
MODEL: modelDirective, | ||
ON: onDirective, | ||
TEXT: textDirective, | ||
}; | ||
var renderDirective = function (_a, directives) { | ||
var el = _a.el, name = _a.name, value = _a.value, state = _a.state; | ||
var rootName = name.split(rawDirectiveSplitPattern)[0]; | ||
directives[rootName.toUpperCase()]({ el: el, name: name, value: value, state: state }); | ||
}; | ||
var arrayEquals = function (firstArray, secondArray) { | ||
@@ -491,3 +478,4 @@ return (firstArray instanceof Array && | ||
var handleArray = function (target, key, state, patch) { | ||
var handlePatch = function (target, key, state, patch, needsUpdate) { | ||
if (needsUpdate === void 0) { needsUpdate = false; } | ||
if (key === 'length') { | ||
@@ -502,3 +490,4 @@ var affectedKeys = Object.keys(state).filter(function (k) { | ||
else { | ||
patch([key]); | ||
if (needsUpdate) | ||
patch([key]); | ||
return false; | ||
@@ -518,4 +507,7 @@ } | ||
set: function (target, key, value) { | ||
target[key] = value; | ||
handleArray(target, key, state, patch); | ||
var needsUpdate = target[key] !== value; | ||
if (needsUpdate) { | ||
target[key] = value; | ||
} | ||
handlePatch(target, key, state, patch, needsUpdate); | ||
return true; | ||
@@ -525,3 +517,3 @@ }, | ||
delete target[key]; | ||
handleArray(target, key, state, patch); | ||
handlePatch(target, key, state, patch); | ||
return true; | ||
@@ -533,7 +525,7 @@ }, | ||
var patch = function (rootVNode, state, directiveKV, keys) { | ||
var patch = function (rootVNode, app, keys) { | ||
var e_1, _a; | ||
if (state === void 0) { state = {}; } | ||
if (directiveKV === void 0) { directiveKV = {}; } | ||
var compileRequest = false; | ||
if (app === void 0) { app = {}; } | ||
var firstRender = false; | ||
var state = app.state || {}; | ||
if (!rootVNode) | ||
@@ -543,4 +535,4 @@ return; | ||
keys = Object.keys(state); | ||
if (keys[0] === LUCIA_COMPILE_REQUEST) | ||
compileRequest = true; | ||
if (keys[0] === LUCIA_FIRST_RENDER) | ||
firstRender = true; | ||
var _loop_1 = function (node) { | ||
@@ -552,10 +544,9 @@ if (typeof node === 'string') | ||
var affectedDirectives = []; | ||
if (!compileRequest) { | ||
if (!firstRender) { | ||
var _loop_2 = function (name_1) { | ||
var value = directives_1[name_1]; | ||
var needsInit = type === 1; | ||
var hasKey = keys.some(function (key) { return keyPattern(key).test(value.toString()); }); | ||
var hasKey = keys.some(function (key) { return keyPattern(key).test(String(directives_1[name_1].value)); }); | ||
var hasKeyInFunction = Object.keys(state).some(function (key) { | ||
var iterKeysInFunction = keys.some(function (k) { | ||
return keyPattern(k).test(state[key].toString()); | ||
return keyPattern(k).test(String(state[key])); | ||
}); | ||
@@ -573,13 +564,13 @@ return typeof state[key] === 'function' && iterKeysInFunction; | ||
node.props.type = type === VNodeTypes.NEEDS_PATCH ? VNodeTypes.STATIC : type; | ||
var directivesToRender = compileRequest | ||
var directivesToRender = firstRender | ||
? Object.keys(directives_1) | ||
: affectedDirectives; | ||
directivesToRender.map(function (name) { | ||
var value = directives_1[name]; | ||
var data = directives_1[name]; | ||
var el = (attributes_1.id ? document.getElementById(attributes_1.id) : ref_1); | ||
renderDirective({ el: el, name: name, value: value, state: state }, __assign({}, directiveKV)); | ||
renderDirective({ el: el, name: name, data: data, app: app }, __assign({}, app.directives)); | ||
}); | ||
} | ||
if (node.children.length > 0) | ||
patch(node, state, directiveKV, keys); | ||
patch(node, state, keys); | ||
}; | ||
@@ -602,31 +593,35 @@ try { | ||
var App = (function () { | ||
function App(state) { | ||
function App(state, mountHook) { | ||
if (state === void 0) { state = {}; } | ||
this.vdom = null; | ||
this.state = state; | ||
this.directives = {}; | ||
this.components = {}; | ||
this.mounted = false; | ||
this.mountHook = mountHook; | ||
} | ||
App.prototype.mount = function (el, shallow) { | ||
if (shallow === void 0) { shallow = false; } | ||
this.vdom = this.compile((typeof el === 'string' ? document.querySelector(el) : el)); | ||
var rootEl = typeof el === 'string' ? document.querySelector(el) : el; | ||
this.vdom = this.compile(rootEl); | ||
if (!shallow) { | ||
this.state = reactive(this.state, this.patch.bind(this)); | ||
this.directives = directives; | ||
this.directives = __assign(__assign({}, this.directives), directives); | ||
} | ||
this.mounted = true; | ||
this.patch([LUCIA_COMPILE_REQUEST]); | ||
this.patch([LUCIA_FIRST_RENDER]); | ||
if (this.mountHook) | ||
this.mountHook(this.state); | ||
return this.state; | ||
}; | ||
App.prototype.component = function (name, fn) { | ||
this.components[name.toUpperCase()] = fn; | ||
App.prototype.component = function (name, templateCallback) { | ||
this.components[name.toUpperCase()] = templateCallback; | ||
}; | ||
App.prototype.directive = function (name, fn) { | ||
this.directives[name.toUpperCase()] = fn; | ||
App.prototype.directive = function (name, evaluationCallback) { | ||
this.directives[name.toUpperCase()] = evaluationCallback; | ||
}; | ||
App.prototype.patch = function (keys) { | ||
if (!this.mounted) | ||
throw new Error('App is not mounted.'); | ||
patch(this.vdom, this.state, this.directives, keys); | ||
var app = { | ||
state: this.state, | ||
directives: this.directives, | ||
components: this.components, | ||
}; | ||
patch(this.vdom, app, keys); | ||
}; | ||
@@ -638,24 +633,46 @@ App.prototype.compile = function (el) { | ||
}()); | ||
var createApp = function (state) { | ||
return new App(state); | ||
var createApp = function (state, mountHook) { | ||
return new App(state, mountHook); | ||
}; | ||
var init = function (element, directive) { | ||
var stateDirective = DIRECTIVE_PREFIX + "state"; | ||
var init = function (element) { | ||
if (element === void 0) { element = document; } | ||
if (directive === void 0) { directive = 'use'; } | ||
var elements = __spread(element.querySelectorAll("[" + (DIRECTIVE_PREFIX + directive) + "]")); | ||
var apps = []; | ||
elements.map(function (el) { | ||
var state = el.getAttribute(DIRECTIVE_PREFIX + directive); | ||
if (state === null) | ||
return; | ||
var elements = __spread(element.querySelectorAll("[" + stateDirective + "]")); | ||
elements | ||
.filter(function (el) { return el.__l === undefined; }) | ||
.map(function (el) { | ||
var expression = el.getAttribute(stateDirective); | ||
try { | ||
var app = createApp(safeEval(state)); | ||
var state = new Function("return " + expression)(); | ||
var app = createApp(state); | ||
app.mount(el); | ||
apps.push(app); | ||
el.__l = app; | ||
} | ||
catch (err) { } | ||
catch (err) { | ||
console.warn("Lucia Error: \"" + err + "\"\n\nExpression: \"" + expression + "\"\nElement:", el); | ||
} | ||
}); | ||
return apps; | ||
}; | ||
var listen = function (callback, element, config) { | ||
if (element === void 0) { element = document; } | ||
var observer = new MutationObserver(function (mutations) { | ||
mutations.map(function (mut) { | ||
if (mut.addedNodes.length > 0) { | ||
mut.addedNodes.forEach(function (node) { | ||
if (node.nodeType !== 1) | ||
return; | ||
if (node.parentElement && node.parentElement.closest("[" + stateDirective + "]")) | ||
return; | ||
callback(node.parentElement); | ||
}); | ||
} | ||
}); | ||
observer.observe(element, config || { | ||
childList: true, | ||
attributes: true, | ||
subtree: true, | ||
}); | ||
}); | ||
}; | ||
@@ -671,6 +688,9 @@ var Lucia = /*#__PURE__*/Object.freeze({ | ||
renderDirective: renderDirective, | ||
init: init | ||
init: init, | ||
listen: listen | ||
}); | ||
document.addEventListener('DOMContentLoaded', function () { return init(document, 'init'); }); | ||
document.addEventListener('DOMContentLoaded', function () { return init(); }); | ||
document.addEventListener('turbolinks:load', function () { return init(); }); | ||
listen(function (el) { return init(el); }); | ||
@@ -677,0 +697,0 @@ return Lucia; |
@@ -1,1 +0,1 @@ | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).Lucia=t()}(this,(function(){"use strict";var e=function(){return(e=Object.assign||function(e){for(var t,r=1,n=arguments.length;r<n;r++)for(var i in t=arguments[r])Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i]);return e}).apply(this,arguments)};function t(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")}function r(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,i,o=r.call(e),a=[];try{for(;(void 0===t||t-- >0)&&!(n=o.next()).done;)a.push(n.value)}catch(e){i={error:e}}finally{try{n&&!n.done&&(r=o.return)&&r.call(o)}finally{if(i)throw i.error}}return a}function n(){for(var e=[],t=0;t<arguments.length;t++)e=e.concat(r(arguments[t]));return e}var i,o,a="l-",l="%LUCIA_COMPILE_REQUEST%";!function(e){e["@"]="ON",e[":"]="BIND"}(i||(i={})),function(e){e[e.STATIC=0]="STATIC",e[e.NEEDS_PATCH=1]="NEEDS_PATCH",e[e.DYNAMIC=2]="DYNAMIC"}(o||(o={}));var s=/:|\./,u=/(?=\.)|(?=#)|(?=\[)/,c=function(e,t){return void 0===t&&(t=!0),new RegExp((t?"this\\.":"")+e+"\\b")},f=function(n,i,o){var l,s,c=n.split(u),f=c[0],v=e({},null==o?void 0:o.attributes),d=e({},null==o?void 0:o.directives);if(c.length>1){c.shift();try{for(var p=t(c),y=p.next();!y.done;y=p.next()){var h=y.value;switch(h[0]){case"#":v.id=h.slice(1);break;case".":v.className||(v.className=""),v.className+=h.slice(1)+" ";break;case"[":var m=r(h.slice(1,-1).split("="),2),b=m[0],T=m[1];b.startsWith(a)?d[b.slice(a.length)]=T:v[b]=T}}}catch(e){l={error:e}}finally{try{y&&!y.done&&(s=p.return)&&s.call(p)}finally{if(l)throw l.error}}}return v.className&&(v.className=v.className.trim()),{tag:f,children:"string"==typeof i?[i]:i||[],props:{attributes:v,directives:d,ref:(null==o?void 0:o.ref)||void 0,type:(null==o?void 0:o.type)||0}}},v=function(e){var r,o,l={},s={};if(e.attributes)try{for(var u=t(n(e.attributes)),c=u.next();!c.done;c=u.next()){var f=c.value,v=f.name,d=f.value;v.startsWith(a)?s[v.slice(a.length)]=d:Object.keys(i).includes(v[0])?s[i[v[0]]+":"+v.slice(1)]=d:l[v]=d}}catch(e){r={error:e}}finally{try{c&&!c.done&&(o=u.return)&&o.call(u)}finally{if(r)throw r.error}}return{attributes:l,directives:s}},d=function(e,t,r){var n=v(e),i=n.attributes,a=n.directives,l=o.STATIC,s=Object.keys(a).length>0,u=Object.values(a).some((function(e){return Object.keys(t).some((function(t){return c(t,!1).test(e)}))}));return s&&(l=o.NEEDS_PATCH),u&&(l=o.DYNAMIC),f(e.tagName.toLowerCase(),r,{attributes:i,directives:a,ref:l===o.STATIC||i.id?void 0:e,type:l})},p=function(e,n,i,o,a){var l,s,u,c,f,h,m;if(void 0===n&&(n={}),void 0===i&&(i={}),void 0===o&&(o=!1),void 0===a&&(a=!1),!e)throw new Error("Please provide a Element");var b=[],T=Array.prototype.slice.call(e.childNodes);try{for(var g=t(T),N=g.next();!N.done;N=g.next()){var A=N.value;switch(A.nodeType){case Node.TEXT_NODE:!o&&A.nodeValue&&b.push(A.nodeValue);break;case Node.ELEMENT_NODE:if(Object.keys(i).includes(A.tagName)){var E=document.createElement("div"),w=i[A.tagName]({children:A.innerHTML,state:n});E.innerHTML=w;try{for(var x=(u=void 0,t(Object.entries(v(A).directives))),O=x.next();!O.done;O=x.next()){var C=r(O.value,2),$=C[0],j=C[1];null===(m=E.firstElementChild)||void 0===m||m.setAttribute("l-"+$,j)}}catch(e){u={error:e}}finally{try{O&&!O.done&&(c=x.return)&&c.call(x)}finally{if(u)throw u.error}}if(!o||E.outerHTML.includes(" l-")){var S=p(E,n,i,o,!0);try{for(var L=(f=void 0,t(S)),M=L.next();!M.done;M=L.next()){var I=M.value;b.push(I)}}catch(e){f={error:e}}finally{try{M&&!M.done&&(h=L.return)&&h.call(L)}finally{if(f)throw f.error}}}e.replaceChild(E.firstElementChild,A)}else if(!o||A.outerHTML.includes(" l-")){S=p(A,n,i,o,!0);var D=d(A,n,S);b.push(D)}}}}catch(e){l={error:e}}finally{try{N&&!N.done&&(s=g.return)&&s.call(g)}finally{if(l)throw l.error}}if(a)return b;var H=d(e,n,b);return o?y(H):H},y=function(r){var n,i,o,a,l=e({},r);l.children.filter((function(e){return"object"==typeof e&&e.props.type>0}));try{for(var s=t(r.children),u=s.next();!u.done;u=s.next()){var c=u.value;if("string"!=typeof c&&c.children.length>0)try{for(var f=(o=void 0,t(y(c).children)),v=f.next();!v.done;v=f.next()){var d=v.value;"string"!=typeof d&&(0!==d.props.type&&l.children.push(d))}}catch(e){o={error:e}}finally{try{v&&!v.done&&(a=f.return)&&a.call(f)}finally{if(o)throw o.error}}}}catch(e){n={error:e}}finally{try{u&&!u.done&&(i=s.return)&&i.call(s)}finally{if(n)throw n.error}}return l},h=function(e,t,r,i){return void 0===t&&(t={}),void 0===r&&(r={}),void 0===i&&(i=!0),(new(Function.bind.apply(Function,n([void 0],Object.keys(t),[i?"return "+e:e])))).bind(r).apply(void 0,n(Object.values(t)))},m=function(e,t,r){return void 0===r&&(r=!0),h(e,{$el:t.$el},t.$state,r)},b={BIND:function(e){var t=e.el,r=e.name,n=e.value,i=e.state;switch(r.split(":")[1]){case"class":var o=m(n,{$state:i,$el:t});if("string"==typeof o)return t.setAttribute("class",(t.className+" "+o).trim());if(o instanceof Array)return t.setAttribute("class",(t.className+" "+o.join(" ")).trim());var a=[];for(var l in o)o[l]&&a.push(l);return a.length>0?t.setAttribute("class",(t.className+" "+a.join(" ").trim()).trim()):t.className.trim().length>0?t.setAttribute("class",t.className):t.removeAttribute("class");case"style":var s=m(n,{$state:i,$el:t});for(var l in t.removeAttribute("style"),s)t.style[l]=s[l];break;default:var u=m(n,{$state:i,$el:t});u?t.setAttribute(r.split(":")[1],u):t.removeAttribute(r.split(":")[1])}},JOIN:function(t){var n=t.el,i=t.value,o=t.state,a=r(i.split(/ as | by /),3),l=a[0],s=a[1],u=a[2],c=m(l,{$state:o,$el:n});n["text"===s?"innerText":"innerHTML"]=c.join(u||""),w(e({},o)).mount(n,!0)},HTML:function(t){var r=t.el,n=t.value,i=t.state;w(e({},i)).mount(r,!0);try{r.innerHTML=m(n,{$state:i,$el:r})}catch(e){r.innerHTML=n}},IF:function(e){var t=e.el,r=e.value,n=e.state;m(r,{$state:n,$el:t})?t.style.removeProperty("display"):t.style.display="none"},MODEL:function(e){var t=e.el,r=e.value,n=e.state,i=t,o=m(r,{$state:n,$el:i});i.value!==o&&(i.value=o),i.oninput=function(){var e,t="number"==typeof o&&!isNaN(i.value),a="boolean"==typeof o&&("true"===i.value||"false"===i.value),l=null==o&&("null"===i.value||"undefined"===i.value);e=t?"Number('"+i.value+"').toPrecision()":a?"Boolean('"+i.value+"')":l?"null"===i.value?null:void 0:"'"+i.value+"'",m(r+" = "+e,{$state:n,$el:i},!1)}},ON:function(e){var t=e.el,n=e.name,i=e.value,o=e.state,a=r(n.split("."),2),l=a[0],s=a[1],u=l.split(":")[1],c=s||null;t["on"+u]=function(e){"prevent"===c&&e.preventDefault(),"stop"===c&&e.stopPropagation(),m(i,{$state:o,$el:t},!1)}},TEXT:function(e){var t=e.el,r=e.value,n=e.state;try{t.innerHTML=m(r,{$state:n,$el:t})}catch(e){t.innerHTML=r}}},T=function(e,t){var r=e.el,n=e.name,i=e.value,o=e.state;t[n.split(s)[0].toUpperCase()]({el:r,name:n,value:i,state:o})},g=function(e,t,r,n){if("length"===t){var i=Object.keys(r).filter((function(t){return r[t]instanceof Array&&(n=e,i=r[t],n instanceof Array&&i instanceof Array&&n.length===i.length&&n.every((function(e,t){return e===i[t]})));var n,i}));return 0!==i.length&&n(i),!0}return n([t]),!1},N=function(e,t){var r={get:function(e,t){return"object"==typeof e[t]&&null!==e[t]?new Proxy(e[t],r):e[t]},set:function(r,n,i){return r[n]=i,g(r,n,e,t),!0},deleteProperty:function(r,n){return delete r[n],g(r,n,e,t),!0}};return new Proxy(e,r)},A=function(r,n,i,a){var s,u;void 0===n&&(n={}),void 0===i&&(i={});var f=!1;if(r){a||(a=Object.keys(n)),a[0]===l&&(f=!0);var v=function(t){if("string"==typeof t)return"continue";if(t.props.type>o.STATIC){var r=t.props,l=r.attributes,s=r.directives,u=r.ref,v=r.type,d=[];if(!f){var p=function(e){var t=s[e],r=1===v,i=a.some((function(e){return c(e).test(t.toString())})),o=Object.keys(n).some((function(e){var t=a.some((function(t){return c(t).test(n[e].toString())}));return"function"==typeof n[e]&&t}));(r||i||o)&&d.push(e)};for(var y in s)p(y)}t.props.type=v===o.NEEDS_PATCH?o.STATIC:v,(f?Object.keys(s):d).map((function(t){var r=s[t],o=l.id?document.getElementById(l.id):u;T({el:o,name:t,value:r,state:n},e({},i))}))}t.children.length>0&&A(t,n,i,a)};try{for(var d=t(r.children),p=d.next();!p.done;p=d.next()){v(p.value)}}catch(e){s={error:e}}finally{try{p&&!p.done&&(u=d.return)&&u.call(d)}finally{if(s)throw s.error}}}},E=function(){function e(e){void 0===e&&(e={}),this.vdom=null,this.state=e,this.directives={},this.components={},this.mounted=!1}return e.prototype.mount=function(e,t){return void 0===t&&(t=!1),this.vdom=this.compile("string"==typeof e?document.querySelector(e):e),t||(this.state=N(this.state,this.patch.bind(this)),this.directives=b),this.mounted=!0,this.patch([l]),this.state},e.prototype.component=function(e,t){this.components[e.toUpperCase()]=t},e.prototype.directive=function(e,t){this.directives[e.toUpperCase()]=t},e.prototype.patch=function(e){if(!this.mounted)throw new Error("App is not mounted.");A(this.vdom,this.state,this.directives,e)},e.prototype.compile=function(e){return p(e,this.state,this.components,!0)},e}(),w=function(e){return new E(e)},x=function(e,t){void 0===e&&(e=document),void 0===t&&(t="use");var r=n(e.querySelectorAll("["+(a+t)+"]")),i=[];return r.map((function(e){var r=e.getAttribute(a+t);if(null!==r)try{var n=w(h(r));n.mount(e),i.push(n)}catch(e){}})),i},O=Object.freeze({__proto__:null,createApp:w,h:f,compile:p,patch:A,reactive:N,directives:b,renderDirective:T,init:x});return document.addEventListener("DOMContentLoaded",(function(){return x(document,"init")})),O})); | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).Lucia=t()}(this,(function(){"use strict";var e=function(){return(e=Object.assign||function(e){for(var t,r=1,n=arguments.length;r<n;r++)for(var i in t=arguments[r])Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i]);return e}).apply(this,arguments)};function t(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")}function r(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,i,o=r.call(e),a=[];try{for(;(void 0===t||t-- >0)&&!(n=o.next()).done;)a.push(n.value)}catch(e){i={error:e}}finally{try{n&&!n.done&&(r=o.return)&&r.call(o)}finally{if(i)throw i.error}}return a}function n(){for(var e=[],t=0;t<arguments.length;t++)e=e.concat(r(arguments[t]));return e}var i,o="l-",a="%LUCIA_FIRST_RENDER%";!function(e){e["@"]="on",e[":"]="bind"}(i||(i={}));var s=/:|\./,l=function(e,t){return void 0===t&&(t=!0),new RegExp((t?"this\\.":"")+e+"\\b")};function u(e){try{var t=this.returnable?"return "+this.expression:this.expression;return(new(Function.bind.apply(Function,n([void 0],Object.keys(this.argsKV),[t])))).bind(e).apply(void 0,n(Object.values(this.argsKV)))}catch(e){console.warn('Lucia Error: "'+e+'"\n\nExpression: "'+this.expression+'"\nElement:',this.argsKV.$el)}}var c,v=function(e,t,r){return void 0===r&&(r=!0),u.bind({expression:e,argsKV:{$el:t.$el},returnable:r})},f={BIND:function(e){var t=e.el,r=e.name,n=e.data,i=e.app;switch(r.split(":")[1]){case"class":var o=n.compute(i.state);if("string"==typeof o)return t.setAttribute("class",(t.className+" "+o).trim());if(o instanceof Array)return t.setAttribute("class",(t.className+" "+o.join(" ")).trim());var a=[];for(var s in o)o[s]&&a.push(s);return a.length>0?t.setAttribute("class",(t.className+" "+a.join(" ").trim()).trim()):t.className.trim().length>0?t.setAttribute("class",t.className):t.removeAttribute("class");case"style":var l=n.compute(i.state);for(var s in t.removeAttribute("style"),l)t.style[s]=l[s];break;default:var u=n.compute(i.state);if("object"==typeof u&&null!==u)for(var s in u)u[s]?t.setAttribute(s,u[s]):t.removeAttribute(s);else u?t.setAttribute(r.split(":")[1],u):t.removeAttribute(r.split(":")[1])}},JOIN:function(t){var n=t.el,i=t.data,o=t.app,a=r(i.value.split(/ as | by /),3),s=a[0],l=a[1],u=a[2],c=v(s,{$el:n})(o.state);n["text"===l?"innerText":"innerHTML"]=c.join(u||"");var f=N(e({},o.state));Object.entries(o.directives||{}).map((function(e){var t=r(e,2),n=t[0],i=t[1];f.directive(n,i)})),Object.entries(o.components||{}).map((function(e){var t=r(e,2),n=t[0],i=t[1];f.component(n,i)})),f.mount(n)},HTML:function(t){var n,i=t.el,o=t.data,a=t.app;i.innerHTML=null!==(n=o.compute(a.state))&&void 0!==n?n:o.value;var s=N(e({},a.state));Object.entries(a.directives||{}).map((function(e){var t=r(e,2),n=t[0],i=t[1];s.directive(n,i)})),Object.entries(a.components||{}).map((function(e){var t=r(e,2),n=t[0],i=t[1];s.component(n,i)})),s.mount(i)},IF:function(e){var t=e.el,r=e.data,n=e.app;r.compute(n.state)?t.style.removeProperty("display"):t.style.display="none"},MODEL:function(e){var t=e.el,r=e.data,n=e.app,i=t,o=v(r.compute(),{$el:i})(n.state);i.value!==o&&(i.value=o),i.oninput=function(){var e,t="number"==typeof o&&!isNaN(i.value),a="boolean"==typeof o&&("true"===i.value||"false"===i.value),s=null==o&&("null"===i.value||"undefined"===i.value);e=t?"Number('"+i.value+"').toPrecision()":a?"Boolean('"+i.value+"')":s?"null"===i.value?null:void 0:"'"+i.value+"'",v(r.value+" = "+e,{$el:i},!1)(n.state)}},ON:function(e){var t=e.el,n=e.name,i=e.data,o=e.app,a=r(n.split("."),2),s=a[0],l=a[1],u=s.split(":")[1],c=l||null;t["on"+u]=function(e){"prevent"===c&&e.preventDefault(),"stop"===c&&e.stopPropagation(),i.compute(o.state)}},TEXT:function(e){var t,r=e.el,n=e.data,i=e.app;r.textContent=null!==(t=n.compute(i.state))&&void 0!==t?t:n.value}},p=function(e,t){t[e.name.split(s)[0].toUpperCase()](e)};!function(e){e[e.STATIC=0]="STATIC",e[e.NEEDS_PATCH=1]="NEEDS_PATCH",e[e.DYNAMIC=2]="DYNAMIC"}(c||(c={}));var d=function(t,r,n){void 0===r&&(r=[]);var i=e({},null==n?void 0:n.attributes),o=e({},null==n?void 0:n.directives);return r=r instanceof Array?r:[r],i.className&&(i.className=i.className.trim()),{tag:t,children:r,props:{attributes:i,directives:o,ref:(null==n?void 0:n.ref)||void 0,type:(null==n?void 0:n.type)||0}}},y=function(e){var r,a,s={},l={};if(e.attributes)try{for(var u=t(n(e.attributes)),c=u.next();!c.done;c=u.next()){var f=c.value,p=f.name,d=f.value,y={compute:v(d,{$el:e}),value:d};p.startsWith(o)?l[p.slice(o.length)]=y:Object.keys(i).includes(p[0])?l[i[p[0]]+":"+p.slice(1)]=y:s[p]=d}}catch(e){r={error:e}}finally{try{c&&!c.done&&(a=u.return)&&a.call(u)}finally{if(r)throw r.error}}return{attributes:s,directives:l}},h=function(e,t,r){var n=y(e),i=n.attributes,o=n.directives,a=c.STATIC,s=Object.keys(o).length>0,u=Object.values(o).some((function(e){var r=e.value;return Object.keys(t).some((function(e){return l(e,!1).test(r)}))}));return s&&(a=c.NEEDS_PATCH),u&&(a=c.DYNAMIC),d(e.tagName.toLowerCase(),r,{attributes:i,directives:o,ref:a===c.STATIC||i.id?void 0:e,type:a})},m=function(e,n,i,o,a){var s,l,u,c,v,f,p;if(void 0===n&&(n={}),void 0===i&&(i={}),void 0===o&&(o=!1),void 0===a&&(a=!1),!e)throw new Error("Please provide a Element");var d=[],g=Array.prototype.slice.call(e.childNodes);try{for(var E=t(g),T=E.next();!T.done;T=E.next()){var A=T.value;switch(A.nodeType){case Node.TEXT_NODE:!o&&A.nodeValue&&d.push(A.nodeValue);break;case Node.ELEMENT_NODE:if(Object.keys(i).includes(A.tagName)){var N=document.createElement("div"),x=i[A.tagName]({children:A.innerHTML,state:n});N.innerHTML=x;try{for(var O=(u=void 0,t(Object.entries(y(A).directives))),j=O.next();!j.done;j=O.next()){var w=r(j.value,2),C=w[0],S=w[1];null===(p=N.firstElementChild)||void 0===p||p.setAttribute("l-"+C,S.value)}}catch(e){u={error:e}}finally{try{j&&!j.done&&(c=O.return)&&c.call(O)}finally{if(u)throw u.error}}if(!o||N.outerHTML.includes(" l-")){var L=m(N,n,i,o,!0);try{for(var _=(v=void 0,t(L)),k=_.next();!k.done;k=_.next()){var D=k.value;d.push(D)}}catch(e){v={error:e}}finally{try{k&&!k.done&&(f=_.return)&&f.call(_)}finally{if(v)throw v.error}}}e.replaceChild(N.firstElementChild,A)}else if(!o||A.outerHTML.includes(" l-")){L=m(A,n,i,o,!0);var I=h(A,n,L);d.push(I)}}}}catch(e){s={error:e}}finally{try{T&&!T.done&&(l=E.return)&&l.call(E)}finally{if(s)throw s.error}}if(a)return d;var H=h(e,n,d);return o?b(H):H},b=function(r){var n,i,o,a,s=e({},r);s.children.filter((function(e){return"object"==typeof e&&e.props.type>0}));try{for(var l=t(r.children),u=l.next();!u.done;u=l.next()){var c=u.value;if("string"!=typeof c&&c.children.length>0)try{for(var v=(o=void 0,t(b(c).children)),f=v.next();!f.done;f=v.next()){var p=f.value;"string"!=typeof p&&(0!==p.props.type&&s.children.push(p))}}catch(e){o={error:e}}finally{try{f&&!f.done&&(a=v.return)&&a.call(v)}finally{if(o)throw o.error}}}}catch(e){n={error:e}}finally{try{u&&!u.done&&(i=l.return)&&i.call(l)}finally{if(n)throw n.error}}return s},g=function(e,t,r,n,i){if(void 0===i&&(i=!1),"length"===t){var o=Object.keys(r).filter((function(t){return r[t]instanceof Array&&(n=e,i=r[t],n instanceof Array&&i instanceof Array&&n.length===i.length&&n.every((function(e,t){return e===i[t]})));var n,i}));return 0!==o.length&&n(o),!0}return i&&n([t]),!1},E=function(e,t){var r={get:function(e,t){return"object"==typeof e[t]&&null!==e[t]?new Proxy(e[t],r):e[t]},set:function(r,n,i){var o=r[n]!==i;return o&&(r[n]=i),g(r,n,e,t,o),!0},deleteProperty:function(r,n){return delete r[n],g(r,n,e,t),!0}};return new Proxy(e,r)},T=function(r,n,i){var o,s;void 0===n&&(n={});var u=!1,v=n.state||{};if(r){i||(i=Object.keys(v)),i[0]===a&&(u=!0);var f=function(t){if("string"==typeof t)return"continue";if(t.props.type>c.STATIC){var r=t.props,o=r.attributes,a=r.directives,s=r.ref,f=r.type,d=[];if(!u){var y=function(e){var t=1===f,r=i.some((function(t){return l(t).test(String(a[e].value))})),n=Object.keys(v).some((function(e){var t=i.some((function(t){return l(t).test(String(v[e]))}));return"function"==typeof v[e]&&t}));(t||r||n)&&d.push(e)};for(var h in a)y(h)}t.props.type=f===c.NEEDS_PATCH?c.STATIC:f,(u?Object.keys(a):d).map((function(t){var r=a[t],i=o.id?document.getElementById(o.id):s;p({el:i,name:t,data:r,app:n},e({},n.directives))}))}t.children.length>0&&T(t,v,i)};try{for(var d=t(r.children),y=d.next();!y.done;y=d.next()){f(y.value)}}catch(e){o={error:e}}finally{try{y&&!y.done&&(s=d.return)&&s.call(d)}finally{if(o)throw o.error}}}},A=function(){function t(e,t){void 0===e&&(e={}),this.state=e,this.directives={},this.components={},this.mountHook=t}return t.prototype.mount=function(t,r){void 0===r&&(r=!1);var n="string"==typeof t?document.querySelector(t):t;return this.vdom=this.compile(n),r||(this.state=E(this.state,this.patch.bind(this)),this.directives=e(e({},this.directives),f)),this.patch([a]),this.mountHook&&this.mountHook(this.state),this.state},t.prototype.component=function(e,t){this.components[e.toUpperCase()]=t},t.prototype.directive=function(e,t){this.directives[e.toUpperCase()]=t},t.prototype.patch=function(e){var t={state:this.state,directives:this.directives,components:this.components};T(this.vdom,t,e)},t.prototype.compile=function(e){return m(e,this.state,this.components,!0)},t}(),N=function(e,t){return new A(e,t)},x="l-state",O=function(e){void 0===e&&(e=document),n(e.querySelectorAll("[l-state]")).filter((function(e){return void 0===e.__l})).map((function(e){var t=e.getAttribute(x);try{var r=new Function("return "+t)(),n=N(r);n.mount(e),e.__l=n}catch(r){console.warn('Lucia Error: "'+r+'"\n\nExpression: "'+t+'"\nElement:',e)}}))},j=function(e,t,r){void 0===t&&(t=document);var n=new MutationObserver((function(i){i.map((function(t){t.addedNodes.length>0&&t.addedNodes.forEach((function(t){1===t.nodeType&&(t.parentElement&&t.parentElement.closest("[l-state]")||e(t.parentElement))}))})),n.observe(t,r||{childList:!0,attributes:!0,subtree:!0})}))},w=Object.freeze({__proto__:null,createApp:N,h:d,compile:m,patch:T,reactive:E,directives:f,renderDirective:p,init:O,listen:j});return document.addEventListener("DOMContentLoaded",(function(){return O()})),document.addEventListener("turbolinks:load",(function(){return O()})),j((function(e){return O(e)})),w})); |
@@ -6,18 +6,10 @@ 'use strict'; | ||
const DIRECTIVE_PREFIX = 'l-'; | ||
const LUCIA_COMPILE_REQUEST = '%LUCIA_COMPILE_REQUEST%'; | ||
const LUCIA_FIRST_RENDER = '%LUCIA_FIRST_RENDER%'; | ||
var DIRECTIVE_SHORTHANDS; | ||
(function (DIRECTIVE_SHORTHANDS) { | ||
DIRECTIVE_SHORTHANDS["@"] = "ON"; | ||
DIRECTIVE_SHORTHANDS[":"] = "BIND"; | ||
DIRECTIVE_SHORTHANDS["@"] = "on"; | ||
DIRECTIVE_SHORTHANDS[":"] = "bind"; | ||
})(DIRECTIVE_SHORTHANDS || (DIRECTIVE_SHORTHANDS = {})); | ||
var VNodeTypes; | ||
(function (VNodeTypes) { | ||
VNodeTypes[VNodeTypes["STATIC"] = 0] = "STATIC"; | ||
VNodeTypes[VNodeTypes["NEEDS_PATCH"] = 1] = "NEEDS_PATCH"; | ||
VNodeTypes[VNodeTypes["DYNAMIC"] = 2] = "DYNAMIC"; | ||
})(VNodeTypes || (VNodeTypes = {})); | ||
const rawDirectiveSplitPattern = /:|\./; | ||
const selectorSplitPattern = /(?=\.)|(?=#)|(?=\[)/; | ||
const keyPattern = (key, hasThis = true) => { | ||
@@ -27,31 +19,182 @@ return new RegExp(`${hasThis ? 'this\\.' : ''}${key}\\b`); | ||
const h = (selector, children, props) => { | ||
const tokens = selector.split(selectorSplitPattern); | ||
const tag = tokens[0]; | ||
const attributes = Object.assign({}, props === null || props === void 0 ? void 0 : props.attributes); | ||
const directives = Object.assign({}, props === null || props === void 0 ? void 0 : props.directives); | ||
if (tokens.length > 1) { | ||
tokens.shift(); | ||
for (const token of tokens) { | ||
switch (token[0]) { | ||
case '#': | ||
attributes.id = token.slice(1); | ||
break; | ||
case '.': | ||
if (!attributes.className) | ||
attributes.className = ''; | ||
attributes.className += `${token.slice(1)} `; | ||
break; | ||
case '[': | ||
const [key, value] = token.slice(1, -1).split('='); | ||
if (key.startsWith(DIRECTIVE_PREFIX)) { | ||
directives[key.slice(DIRECTIVE_PREFIX.length)] = value; | ||
const bindDirective = ({ el, name, data, app }) => { | ||
switch (name.split(':')[1]) { | ||
case 'class': | ||
const hydratedClasses = data.compute(app.state); | ||
if (typeof hydratedClasses === 'string') { | ||
return el.setAttribute('class', `${el.className} ${hydratedClasses}`.trim()); | ||
} | ||
else if (hydratedClasses instanceof Array) { | ||
return el.setAttribute('class', `${el.className} ${hydratedClasses.join(' ')}`.trim()); | ||
} | ||
else { | ||
const classes = []; | ||
for (const key in hydratedClasses) { | ||
if (hydratedClasses[key]) | ||
classes.push(key); | ||
} | ||
if (classes.length > 0) { | ||
return el.setAttribute('class', `${el.className} ${classes.join(' ').trim()}`.trim()); | ||
} | ||
else if (el.className.trim().length > 0) { | ||
return el.setAttribute('class', el.className); | ||
} | ||
else { | ||
return el.removeAttribute('class'); | ||
} | ||
} | ||
case 'style': | ||
const hydratedStyles = data.compute(app.state); | ||
el.removeAttribute('style'); | ||
for (const key in hydratedStyles) { | ||
el.style[key] = hydratedStyles[key]; | ||
} | ||
break; | ||
default: | ||
const hydratedAttributes = data.compute(app.state); | ||
if (typeof hydratedAttributes === 'object' && hydratedAttributes !== null) { | ||
for (const key in hydratedAttributes) { | ||
if (hydratedAttributes[key]) { | ||
el.setAttribute(key, hydratedAttributes[key]); | ||
} | ||
else { | ||
attributes[key] = value; | ||
el.removeAttribute(key); | ||
} | ||
break; | ||
} | ||
} | ||
else if (hydratedAttributes) { | ||
el.setAttribute(name.split(':')[1], hydratedAttributes); | ||
} | ||
else { | ||
el.removeAttribute(name.split(':')[1]); | ||
} | ||
break; | ||
} | ||
}; | ||
const htmlDirective = ({ el, data, app }) => { | ||
var _a; | ||
el.innerHTML = (_a = data.compute(app.state)) !== null && _a !== void 0 ? _a : data.value; | ||
const scope = createApp(Object.assign({}, app.state)); | ||
Object.entries(app.directives || {}).map(([name, evaluationCallback]) => { | ||
scope.directive(name, evaluationCallback); | ||
}); | ||
Object.entries(app.components || {}).map(([name, templateCallback]) => { | ||
scope.component(name, templateCallback); | ||
}); | ||
scope.mount(el); | ||
}; | ||
const ifDirective = ({ el, data, app }) => { | ||
const hydratedConditional = data.compute(app.state); | ||
if (hydratedConditional) { | ||
el.style.removeProperty('display'); | ||
} | ||
else { | ||
el.style.display = 'none'; | ||
} | ||
}; | ||
function createComputeFunction(state) { | ||
try { | ||
const expression = this.returnable ? `return ${this.expression}` : this.expression; | ||
return new Function(...Object.keys(this.argsKV), expression).bind(state)(...Object.values(this.argsKV)); | ||
} | ||
catch (err) { | ||
console.warn(`Lucia Error: "${err}"\n\nExpression: "${this.expression}"\nElement:`, this.argsKV.$el); | ||
} | ||
} | ||
const compute = (expression, data, returnable = true) => { | ||
return createComputeFunction.bind({ expression, argsKV: { $el: data.$el }, returnable }); | ||
}; | ||
const joinDirective = ({ el, data, app }) => { | ||
const [array, contentType, delimiter] = data.value.split(/ as | by /); | ||
const hydratedArray = compute(array, { $el: el })(app.state); | ||
const accessProp = contentType === 'text' ? 'innerText' : 'innerHTML'; | ||
el[accessProp] = hydratedArray.join(delimiter || ''); | ||
const scope = createApp(Object.assign({}, app.state)); | ||
Object.entries(app.directives || {}).map(([name, evaluationCallback]) => { | ||
scope.directive(name, evaluationCallback); | ||
}); | ||
Object.entries(app.components || {}).map(([name, templateCallback]) => { | ||
scope.component(name, templateCallback); | ||
}); | ||
scope.mount(el); | ||
}; | ||
const modelDirective = ({ el: awaitingTypecastEl, data, app }) => { | ||
const el = awaitingTypecastEl; | ||
const hydratedValue = compute(data.compute(), { $el: el })(app.state); | ||
if (el.value !== hydratedValue) { | ||
el.value = hydratedValue; | ||
} | ||
el.oninput = () => { | ||
const isNumber = typeof hydratedValue === 'number' && !isNaN(el.value); | ||
const isBoolean = typeof hydratedValue === 'boolean' && (el.value === 'true' || el.value === 'false'); | ||
const isNullish = (hydratedValue === null || hydratedValue === undefined) && | ||
(el.value === 'null' || el.value === 'undefined'); | ||
let payload; | ||
if (isNumber) { | ||
payload = `Number('${el.value}').toPrecision()`; | ||
} | ||
} | ||
else if (isBoolean) { | ||
payload = `Boolean('${el.value}')`; | ||
} | ||
else if (isNullish) { | ||
if (el.value === 'null') | ||
payload = null; | ||
else | ||
payload = undefined; | ||
} | ||
else { | ||
payload = `'${el.value}'`; | ||
} | ||
compute(`${data.value} = ${payload}`, { $el: el }, false)(app.state); | ||
}; | ||
}; | ||
const onDirective = ({ el, name, data, app }) => { | ||
const [directiveAndEventName, prop] = name.split('.'); | ||
const eventName = directiveAndEventName.split(':')[1]; | ||
const eventProp = prop || null; | ||
el[`on${eventName}`] = ($event) => { | ||
if (eventProp === 'prevent') | ||
$event.preventDefault(); | ||
if (eventProp === 'stop') | ||
$event.stopPropagation(); | ||
data.compute(app.state); | ||
}; | ||
}; | ||
const textDirective = ({ el, data, app }) => { | ||
var _a; | ||
el.textContent = (_a = data.compute(app.state)) !== null && _a !== void 0 ? _a : data.value; | ||
}; | ||
const directives = { | ||
BIND: bindDirective, | ||
JOIN: joinDirective, | ||
HTML: htmlDirective, | ||
IF: ifDirective, | ||
MODEL: modelDirective, | ||
ON: onDirective, | ||
TEXT: textDirective, | ||
}; | ||
const renderDirective = (props, directives) => { | ||
const name = props.name.split(rawDirectiveSplitPattern)[0]; | ||
directives[name.toUpperCase()](props); | ||
}; | ||
var VNodeTypes; | ||
(function (VNodeTypes) { | ||
VNodeTypes[VNodeTypes["STATIC"] = 0] = "STATIC"; | ||
VNodeTypes[VNodeTypes["NEEDS_PATCH"] = 1] = "NEEDS_PATCH"; | ||
VNodeTypes[VNodeTypes["DYNAMIC"] = 2] = "DYNAMIC"; | ||
})(VNodeTypes || (VNodeTypes = {})); | ||
const h = (tag, children = [], props) => { | ||
const attributes = Object.assign({}, props === null || props === void 0 ? void 0 : props.attributes); | ||
const directives = Object.assign({}, props === null || props === void 0 ? void 0 : props.directives); | ||
children = children instanceof Array ? children : [children]; | ||
if (attributes.className) | ||
@@ -61,3 +204,3 @@ attributes.className = attributes.className.trim(); | ||
tag, | ||
children: typeof children === 'string' ? [children] : children ? children : [], | ||
children, | ||
props: { | ||
@@ -77,7 +220,8 @@ attributes, | ||
for (const { name, value } of [...el.attributes]) { | ||
const directiveData = { compute: compute(value, { $el: el }), value }; | ||
if (name.startsWith(DIRECTIVE_PREFIX)) { | ||
directives[name.slice(DIRECTIVE_PREFIX.length)] = value; | ||
directives[name.slice(DIRECTIVE_PREFIX.length)] = directiveData; | ||
} | ||
else if (Object.keys(DIRECTIVE_SHORTHANDS).includes(name[0])) { | ||
directives[`${DIRECTIVE_SHORTHANDS[name[0]]}:${name.slice(1)}`] = value; | ||
directives[`${DIRECTIVE_SHORTHANDS[name[0]]}:${name.slice(1)}`] = directiveData; | ||
} | ||
@@ -96,3 +240,3 @@ else { | ||
const hasDirectives = Object.keys(directives).length > 0; | ||
const hasKeyInDirectives = Object.values(directives).some((value) => Object.keys(state).some((key) => keyPattern(key, false).test(value))); | ||
const hasKeyInDirectives = Object.values(directives).some(({ value }) => Object.keys(state).some((key) => keyPattern(key, false).test(value))); | ||
if (hasDirectives) | ||
@@ -103,4 +247,4 @@ type = VNodeTypes.NEEDS_PATCH; | ||
return h(el.tagName.toLowerCase(), children, { | ||
attributes, | ||
directives, | ||
attributes: attributes, | ||
directives: directives, | ||
ref: type === VNodeTypes.STATIC || attributes.id ? undefined : el, | ||
@@ -131,4 +275,4 @@ type, | ||
container.innerHTML = template; | ||
for (const [key, value] of Object.entries(props(child).directives)) { | ||
(_a = container.firstElementChild) === null || _a === void 0 ? void 0 : _a.setAttribute(`${DIRECTIVE_PREFIX}${key}`, value); | ||
for (const [key, data] of Object.entries(props(child).directives)) { | ||
(_a = container.firstElementChild) === null || _a === void 0 ? void 0 : _a.setAttribute(`${DIRECTIVE_PREFIX}${key}`, data.value); | ||
} | ||
@@ -180,150 +324,2 @@ if (!strip || container.outerHTML.includes(` ${DIRECTIVE_PREFIX}`)) { | ||
const safeEval = (expression, argsKV = {}, bindKV = {}, returnable = true) => { | ||
return new Function(...Object.keys(argsKV), returnable ? `return ${expression}` : expression).bind(bindKV)(...Object.values(argsKV)); | ||
}; | ||
const computeProperties = (expression, data, returnable = true) => { | ||
return safeEval(expression, { $el: data.$el }, data.$state, returnable); | ||
}; | ||
const bindDirective = ({ el, name, value, state }) => { | ||
switch (name.split(':')[1]) { | ||
case 'class': | ||
const classState = computeProperties(value, { $state: state, $el: el }); | ||
if (typeof classState === 'string') { | ||
return el.setAttribute('class', `${el.className} ${classState}`.trim()); | ||
} | ||
if (classState instanceof Array) { | ||
return el.setAttribute('class', `${el.className} ${classState.join(' ')}`.trim()); | ||
} | ||
else { | ||
const classes = []; | ||
for (const key in classState) { | ||
if (classState[key]) | ||
classes.push(key); | ||
} | ||
if (classes.length > 0) { | ||
return el.setAttribute('class', `${el.className} ${classes.join(' ').trim()}`.trim()); | ||
} | ||
else if (el.className.trim().length > 0) { | ||
return el.setAttribute('class', el.className); | ||
} | ||
else { | ||
return el.removeAttribute('class'); | ||
} | ||
} | ||
case 'style': | ||
const styleState = computeProperties(value, { $state: state, $el: el }); | ||
el.removeAttribute('style'); | ||
for (const key in styleState) { | ||
el.style[key] = styleState[key]; | ||
} | ||
break; | ||
default: | ||
const out = computeProperties(value, { $state: state, $el: el }); | ||
if (out) { | ||
el.setAttribute(name.split(':')[1], out); | ||
} | ||
else { | ||
el.removeAttribute(name.split(':')[1]); | ||
} | ||
break; | ||
} | ||
}; | ||
const htmlDirective = ({ el, value, state }) => { | ||
const app = createApp(Object.assign({}, state)); | ||
app.mount(el, true); | ||
try { | ||
el.innerHTML = computeProperties(value, { $state: state, $el: el }); | ||
} | ||
catch (_a) { | ||
el.innerHTML = value; | ||
} | ||
}; | ||
const ifDirective = ({ el, value, state }) => { | ||
const out = computeProperties(value, { $state: state, $el: el }); | ||
if (out) { | ||
el.style.removeProperty('display'); | ||
} | ||
else { | ||
el.style.display = 'none'; | ||
} | ||
}; | ||
const joinDirective = ({ el, value, state }) => { | ||
const [array, contentType, delimiter] = value.split(/ as | by /); | ||
const out = computeProperties(array, { $state: state, $el: el }); | ||
const accessProp = contentType === 'text' ? 'innerText' : 'innerHTML'; | ||
el[accessProp] = out.join(delimiter || ''); | ||
const app = createApp(Object.assign({}, state)); | ||
app.mount(el, true); | ||
}; | ||
const modelDirective = ({ el: awaitingTypecastEl, value, state }) => { | ||
const el = awaitingTypecastEl; | ||
const out = computeProperties(value, { $state: state, $el: el }); | ||
if (el.value !== out) { | ||
el.value = out; | ||
} | ||
el.oninput = () => { | ||
const isNumber = typeof out === 'number' && !isNaN(el.value); | ||
const isBoolean = typeof out === 'boolean' && (el.value === 'true' || el.value === 'false'); | ||
const isNullish = (out === null || out === undefined) && (el.value === 'null' || el.value === 'undefined'); | ||
let payload; | ||
if (isNumber) { | ||
payload = `Number('${el.value}').toPrecision()`; | ||
} | ||
else if (isBoolean) { | ||
payload = `Boolean('${el.value}')`; | ||
} | ||
else if (isNullish) { | ||
if (el.value === 'null') | ||
payload = null; | ||
else | ||
payload = undefined; | ||
} | ||
else { | ||
payload = `'${el.value}'`; | ||
} | ||
computeProperties(`${value} = ${payload}`, { $state: state, $el: el }, false); | ||
}; | ||
}; | ||
const onDirective = ({ el, name, value, state }) => { | ||
const [directiveAndEventName, prop] = name.split('.'); | ||
const eventName = directiveAndEventName.split(':')[1]; | ||
const eventProp = prop || null; | ||
el[`on${eventName}`] = ($event) => { | ||
if (eventProp === 'prevent') | ||
$event.preventDefault(); | ||
if (eventProp === 'stop') | ||
$event.stopPropagation(); | ||
computeProperties(value, { $state: state, $el: el }, false); | ||
}; | ||
}; | ||
const textDirective = ({ el, value, state }) => { | ||
try { | ||
el.innerHTML = computeProperties(value, { $state: state, $el: el }); | ||
} | ||
catch (_a) { | ||
el.innerHTML = value; | ||
} | ||
}; | ||
const directives = { | ||
BIND: bindDirective, | ||
JOIN: joinDirective, | ||
HTML: htmlDirective, | ||
IF: ifDirective, | ||
MODEL: modelDirective, | ||
ON: onDirective, | ||
TEXT: textDirective, | ||
}; | ||
const renderDirective = ({ el, name, value, state }, directives) => { | ||
const rootName = name.split(rawDirectiveSplitPattern)[0]; | ||
directives[rootName.toUpperCase()]({ el, name, value, state }); | ||
}; | ||
const arrayEquals = (firstArray, secondArray) => { | ||
@@ -336,3 +332,3 @@ return (firstArray instanceof Array && | ||
const handleArray = (target, key, state, patch) => { | ||
const handlePatch = (target, key, state, patch, needsUpdate = false) => { | ||
if (key === 'length') { | ||
@@ -347,3 +343,4 @@ const affectedKeys = Object.keys(state).filter((k) => { | ||
else { | ||
patch([key]); | ||
if (needsUpdate) | ||
patch([key]); | ||
return false; | ||
@@ -363,4 +360,7 @@ } | ||
set(target, key, value) { | ||
target[key] = value; | ||
handleArray(target, key, state, patch); | ||
const needsUpdate = target[key] !== value; | ||
if (needsUpdate) { | ||
target[key] = value; | ||
} | ||
handlePatch(target, key, state, patch, needsUpdate); | ||
return true; | ||
@@ -370,3 +370,3 @@ }, | ||
delete target[key]; | ||
handleArray(target, key, state, patch); | ||
handlePatch(target, key, state, patch); | ||
return true; | ||
@@ -378,4 +378,5 @@ }, | ||
const patch = (rootVNode, state = {}, directiveKV = {}, keys) => { | ||
let compileRequest = false; | ||
const patch = (rootVNode, app = {}, keys) => { | ||
let firstRender = false; | ||
const state = app.state || {}; | ||
if (!rootVNode) | ||
@@ -385,4 +386,4 @@ return; | ||
keys = Object.keys(state); | ||
if (keys[0] === LUCIA_COMPILE_REQUEST) | ||
compileRequest = true; | ||
if (keys[0] === LUCIA_FIRST_RENDER) | ||
firstRender = true; | ||
for (let node of rootVNode.children) { | ||
@@ -394,9 +395,8 @@ if (typeof node === 'string') | ||
let affectedDirectives = []; | ||
if (!compileRequest) { | ||
if (!firstRender) { | ||
for (const name in directives) { | ||
const value = directives[name]; | ||
const needsInit = type === 1; | ||
const hasKey = keys.some((key) => keyPattern(key).test(value.toString())); | ||
const hasKey = keys.some((key) => keyPattern(key).test(String(directives[name].value))); | ||
const hasKeyInFunction = Object.keys(state).some((key) => { | ||
const iterKeysInFunction = keys.some((k) => keyPattern(k).test(state[key].toString())); | ||
const iterKeysInFunction = keys.some((k) => keyPattern(k).test(String(state[key]))); | ||
return typeof state[key] === 'function' && iterKeysInFunction; | ||
@@ -410,13 +410,13 @@ }); | ||
node.props.type = type === VNodeTypes.NEEDS_PATCH ? VNodeTypes.STATIC : type; | ||
const directivesToRender = compileRequest | ||
const directivesToRender = firstRender | ||
? Object.keys(directives) | ||
: affectedDirectives; | ||
directivesToRender.map((name) => { | ||
const value = directives[name]; | ||
const data = directives[name]; | ||
const el = (attributes.id ? document.getElementById(attributes.id) : ref); | ||
renderDirective({ el, name, value, state }, Object.assign({}, directiveKV)); | ||
renderDirective({ el, name, data, app }, Object.assign({}, app.directives)); | ||
}); | ||
} | ||
if (node.children.length > 0) | ||
patch(node, state, directiveKV, keys); | ||
patch(node, state, keys); | ||
} | ||
@@ -426,29 +426,33 @@ }; | ||
class App { | ||
constructor(state = {}) { | ||
this.vdom = null; | ||
constructor(state = {}, mountHook) { | ||
this.state = state; | ||
this.directives = {}; | ||
this.components = {}; | ||
this.mounted = false; | ||
this.mountHook = mountHook; | ||
} | ||
mount(el, shallow = false) { | ||
this.vdom = this.compile((typeof el === 'string' ? document.querySelector(el) : el)); | ||
const rootEl = typeof el === 'string' ? document.querySelector(el) : el; | ||
this.vdom = this.compile(rootEl); | ||
if (!shallow) { | ||
this.state = reactive(this.state, this.patch.bind(this)); | ||
this.directives = directives; | ||
this.directives = Object.assign(Object.assign({}, this.directives), directives); | ||
} | ||
this.mounted = true; | ||
this.patch([LUCIA_COMPILE_REQUEST]); | ||
this.patch([LUCIA_FIRST_RENDER]); | ||
if (this.mountHook) | ||
this.mountHook(this.state); | ||
return this.state; | ||
} | ||
component(name, fn) { | ||
this.components[name.toUpperCase()] = fn; | ||
component(name, templateCallback) { | ||
this.components[name.toUpperCase()] = templateCallback; | ||
} | ||
directive(name, fn) { | ||
this.directives[name.toUpperCase()] = fn; | ||
directive(name, evaluationCallback) { | ||
this.directives[name.toUpperCase()] = evaluationCallback; | ||
} | ||
patch(keys) { | ||
if (!this.mounted) | ||
throw new Error('App is not mounted.'); | ||
patch(this.vdom, this.state, this.directives, keys); | ||
const app = { | ||
state: this.state, | ||
directives: this.directives, | ||
components: this.components, | ||
}; | ||
patch(this.vdom, app, keys); | ||
} | ||
@@ -459,22 +463,44 @@ compile(el) { | ||
} | ||
const createApp = (state) => { | ||
return new App(state); | ||
const createApp = (state, mountHook) => { | ||
return new App(state, mountHook); | ||
}; | ||
const init = (element = document, directive = 'use') => { | ||
const elements = [...element.querySelectorAll(`[${DIRECTIVE_PREFIX + directive}]`)]; | ||
const apps = []; | ||
elements.map((el) => { | ||
const state = el.getAttribute(DIRECTIVE_PREFIX + directive); | ||
if (state === null) | ||
return; | ||
const stateDirective = `${DIRECTIVE_PREFIX}state`; | ||
const init = (element = document) => { | ||
const elements = [...element.querySelectorAll(`[${stateDirective}]`)]; | ||
elements | ||
.filter((el) => el.__l === undefined) | ||
.map((el) => { | ||
const expression = el.getAttribute(stateDirective); | ||
try { | ||
const app = createApp(safeEval(state)); | ||
const state = new Function(`return ${expression}`)(); | ||
const app = createApp(state); | ||
app.mount(el); | ||
apps.push(app); | ||
el.__l = app; | ||
} | ||
catch (err) { } | ||
catch (err) { | ||
console.warn(`Lucia Error: "${err}"\n\nExpression: "${expression}"\nElement:`, el); | ||
} | ||
}); | ||
return apps; | ||
}; | ||
const listen = (callback, element = document, config) => { | ||
const observer = new MutationObserver((mutations) => { | ||
mutations.map((mut) => { | ||
if (mut.addedNodes.length > 0) { | ||
mut.addedNodes.forEach((node) => { | ||
if (node.nodeType !== 1) | ||
return; | ||
if (node.parentElement && node.parentElement.closest(`[${stateDirective}]`)) | ||
return; | ||
callback(node.parentElement); | ||
}); | ||
} | ||
}); | ||
observer.observe(element, config || { | ||
childList: true, | ||
attributes: true, | ||
subtree: true, | ||
}); | ||
}); | ||
}; | ||
@@ -486,4 +512,5 @@ exports.compile = compile; | ||
exports.init = init; | ||
exports.listen = listen; | ||
exports.patch = patch; | ||
exports.reactive = reactive; | ||
exports.renderDirective = renderDirective; |
@@ -1,1 +0,1 @@ | ||
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e,t;!function(e){e["@"]="ON",e[":"]="BIND"}(e||(e={})),function(e){e[e.STATIC=0]="STATIC",e[e.NEEDS_PATCH=1]="NEEDS_PATCH",e[e.DYNAMIC=2]="DYNAMIC"}(t||(t={}));const s=/:|\./,n=/(?=\.)|(?=#)|(?=\[)/,i=(e,t=!0)=>new RegExp(`${t?"this\\.":""}${e}\\b`),r=(e,t,s)=>{const i=e.split(n),r=i[0],l=Object.assign({},null==s?void 0:s.attributes),o=Object.assign({},null==s?void 0:s.directives);if(i.length>1){i.shift();for(const e of i)switch(e[0]){case"#":l.id=e.slice(1);break;case".":l.className||(l.className=""),l.className+=`${e.slice(1)} `;break;case"[":const[t,s]=e.slice(1,-1).split("=");t.startsWith("l-")?o[t.slice("l-".length)]=s:l[t]=s}}return l.className&&(l.className=l.className.trim()),{tag:r,children:"string"==typeof t?[t]:t||[],props:{attributes:l,directives:o,ref:(null==s?void 0:s.ref)||void 0,type:(null==s?void 0:s.type)||0}}},l=t=>{const s={},n={};if(t.attributes)for(const{name:i,value:r}of[...t.attributes])i.startsWith("l-")?n[i.slice("l-".length)]=r:Object.keys(e).includes(i[0])?n[`${e[i[0]]}:${i.slice(1)}`]=r:s[i]=r;return{attributes:s,directives:n}},o=(e,s,n)=>{const{attributes:o,directives:a}=l(e);let c=t.STATIC;const u=Object.keys(a).length>0,p=Object.values(a).some((e=>Object.keys(s).some((t=>i(t,!1).test(e)))));return u&&(c=t.NEEDS_PATCH),p&&(c=t.DYNAMIC),r(e.tagName.toLowerCase(),n,{attributes:o,directives:a,ref:c===t.STATIC||o.id?void 0:e,type:c})},a=(e,t={},s={},n=!1,i=!1)=>{var r;if(!e)throw new Error("Please provide a Element");const u=[],p=Array.prototype.slice.call(e.childNodes);for(const i of p)switch(i.nodeType){case Node.TEXT_NODE:!n&&i.nodeValue&&u.push(i.nodeValue);break;case Node.ELEMENT_NODE:if(Object.keys(s).includes(i.tagName)){const o=document.createElement("div"),c=s[i.tagName]({children:i.innerHTML,state:t});o.innerHTML=c;for(const[e,t]of Object.entries(l(i).directives))null===(r=o.firstElementChild)||void 0===r||r.setAttribute(`l-${e}`,t);if(!n||o.outerHTML.includes(" l-")){const e=a(o,t,s,n,!0);for(const t of e)u.push(t)}e.replaceChild(o.firstElementChild,i)}else if(!n||i.outerHTML.includes(" l-")){const e=a(i,t,s,n,!0),r=o(i,t,e);u.push(r)}}if(i)return u;{let s=o(e,t,u);return n?c(s):s}},c=e=>{const t=Object.assign({},e);t.children.filter((e=>"object"==typeof e&&e.props.type>0));for(const s of e.children)if("string"!=typeof s&&s.children.length>0)for(const e of c(s).children)"string"!=typeof e&&0!==e.props.type&&t.children.push(e);return t},u=(e,t={},s={},n=!0)=>new Function(...Object.keys(t),n?`return ${e}`:e).bind(s)(...Object.values(t)),p=(e,t,s=!0)=>u(e,{$el:t.$el},t.$state,s),d={BIND:({el:e,name:t,value:s,state:n})=>{switch(t.split(":")[1]){case"class":const i=p(s,{$state:n,$el:e});if("string"==typeof i)return e.setAttribute("class",`${e.className} ${i}`.trim());if(i instanceof Array)return e.setAttribute("class",`${e.className} ${i.join(" ")}`.trim());{const t=[];for(const e in i)i[e]&&t.push(e);return t.length>0?e.setAttribute("class",`${e.className} ${t.join(" ").trim()}`.trim()):e.className.trim().length>0?e.setAttribute("class",e.className):e.removeAttribute("class")}case"style":const r=p(s,{$state:n,$el:e});e.removeAttribute("style");for(const t in r)e.style[t]=r[t];break;default:const l=p(s,{$state:n,$el:e});l?e.setAttribute(t.split(":")[1],l):e.removeAttribute(t.split(":")[1])}},JOIN:({el:e,value:t,state:s})=>{const[n,i,r]=t.split(/ as | by /),l=p(n,{$state:s,$el:e});e["text"===i?"innerText":"innerHTML"]=l.join(r||"");b(Object.assign({},s)).mount(e,!0)},HTML:({el:e,value:t,state:s})=>{b(Object.assign({},s)).mount(e,!0);try{e.innerHTML=p(t,{$state:s,$el:e})}catch(s){e.innerHTML=t}},IF:({el:e,value:t,state:s})=>{p(t,{$state:s,$el:e})?e.style.removeProperty("display"):e.style.display="none"},MODEL:({el:e,value:t,state:s})=>{const n=e,i=p(t,{$state:s,$el:n});n.value!==i&&(n.value=i),n.oninput=()=>{const e="number"==typeof i&&!isNaN(n.value),r="boolean"==typeof i&&("true"===n.value||"false"===n.value),l=null==i&&("null"===n.value||"undefined"===n.value);let o;o=e?`Number('${n.value}').toPrecision()`:r?`Boolean('${n.value}')`:l?"null"===n.value?null:void 0:`'${n.value}'`,p(`${t} = ${o}`,{$state:s,$el:n},!1)}},ON:({el:e,name:t,value:s,state:n})=>{const[i,r]=t.split("."),l=i.split(":")[1],o=r||null;e[`on${l}`]=t=>{"prevent"===o&&t.preventDefault(),"stop"===o&&t.stopPropagation(),p(s,{$state:n,$el:e},!1)}},TEXT:({el:e,value:t,state:s})=>{try{e.innerHTML=p(t,{$state:s,$el:e})}catch(s){e.innerHTML=t}}},h=({el:e,name:t,value:n,state:i},r)=>{r[t.split(s)[0].toUpperCase()]({el:e,name:t,value:n,state:i})},f=(e,t,s,n)=>{if("length"===t){const t=Object.keys(s).filter((t=>{return s[t]instanceof Array&&(n=e,i=s[t],n instanceof Array&&i instanceof Array&&n.length===i.length&&n.every(((e,t)=>e===i[t])));var n,i}));return 0!==t.length&&n(t),!0}return n([t]),!1},m=(e,t)=>{const s={get:(e,t)=>"object"==typeof e[t]&&null!==e[t]?new Proxy(e[t],s):e[t],set:(s,n,i)=>(s[n]=i,f(s,n,e,t),!0),deleteProperty:(s,n)=>(delete s[n],f(s,n,e,t),!0)};return new Proxy(e,s)},v=(e,s={},n={},r)=>{let l=!1;if(e){r||(r=Object.keys(s)),"%LUCIA_COMPILE_REQUEST%"===r[0]&&(l=!0);for(let o of e.children)if("string"!=typeof o){if(o.props.type>t.STATIC){const{attributes:e,directives:a,ref:c,type:u}=o.props;let p=[];if(!l)for(const e in a){const t=a[e],n=1===u,l=r.some((e=>i(e).test(t.toString()))),o=Object.keys(s).some((e=>{const t=r.some((t=>i(t).test(s[e].toString())));return"function"==typeof s[e]&&t}));(n||l||o)&&p.push(e)}o.props.type=u===t.NEEDS_PATCH?t.STATIC:u;(l?Object.keys(a):p).map((t=>{const i=a[t],r=e.id?document.getElementById(e.id):c;h({el:r,name:t,value:i,state:s},Object.assign({},n))}))}o.children.length>0&&v(o,s,n,r)}}};class y{constructor(e={}){this.vdom=null,this.state=e,this.directives={},this.components={},this.mounted=!1}mount(e,t=!1){return this.vdom=this.compile("string"==typeof e?document.querySelector(e):e),t||(this.state=m(this.state,this.patch.bind(this)),this.directives=d),this.mounted=!0,this.patch(["%LUCIA_COMPILE_REQUEST%"]),this.state}component(e,t){this.components[e.toUpperCase()]=t}directive(e,t){this.directives[e.toUpperCase()]=t}patch(e){if(!this.mounted)throw new Error("App is not mounted.");v(this.vdom,this.state,this.directives,e)}compile(e){return a(e,this.state,this.components,!0)}}const b=e=>new y(e);exports.compile=a,exports.createApp=b,exports.directives=d,exports.h=r,exports.init=(e=document,t="use")=>{const s=[...e.querySelectorAll(`[${"l-"+t}]`)],n=[];return s.map((e=>{const s=e.getAttribute("l-"+t);if(null!==s)try{const t=b(u(s));t.mount(e),n.push(t)}catch(e){}})),n},exports.patch=v,exports.reactive=m,exports.renderDirective=h; | ||
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e;!function(e){e["@"]="on",e[":"]="bind"}(e||(e={}));const t=/:|\./,s=(e,t=!0)=>new RegExp(`${t?"this\\.":""}${e}\\b`);function n(e){try{const t=this.returnable?`return ${this.expression}`:this.expression;return new Function(...Object.keys(this.argsKV),t).bind(e)(...Object.values(this.argsKV))}catch(e){console.warn(`Lucia Error: "${e}"\n\nExpression: "${this.expression}"\nElement:`,this.argsKV.$el)}}const r=(e,t,s=!0)=>n.bind({expression:e,argsKV:{$el:t.$el},returnable:s}),o={BIND:({el:e,name:t,data:s,app:n})=>{switch(t.split(":")[1]){case"class":const r=s.compute(n.state);if("string"==typeof r)return e.setAttribute("class",`${e.className} ${r}`.trim());if(r instanceof Array)return e.setAttribute("class",`${e.className} ${r.join(" ")}`.trim());{const t=[];for(const e in r)r[e]&&t.push(e);return t.length>0?e.setAttribute("class",`${e.className} ${t.join(" ").trim()}`.trim()):e.className.trim().length>0?e.setAttribute("class",e.className):e.removeAttribute("class")}case"style":const o=s.compute(n.state);e.removeAttribute("style");for(const t in o)e.style[t]=o[t];break;default:const i=s.compute(n.state);if("object"==typeof i&&null!==i)for(const t in i)i[t]?e.setAttribute(t,i[t]):e.removeAttribute(t);else i?e.setAttribute(t.split(":")[1],i):e.removeAttribute(t.split(":")[1])}},JOIN:({el:e,data:t,app:s})=>{const[n,o,i]=t.value.split(/ as | by /),a=r(n,{$el:e})(s.state);e["text"===o?"innerText":"innerHTML"]=a.join(i||"");const c=b(Object.assign({},s.state));Object.entries(s.directives||{}).map((([e,t])=>{c.directive(e,t)})),Object.entries(s.components||{}).map((([e,t])=>{c.component(e,t)})),c.mount(e)},HTML:({el:e,data:t,app:s})=>{var n;e.innerHTML=null!==(n=t.compute(s.state))&&void 0!==n?n:t.value;const r=b(Object.assign({},s.state));Object.entries(s.directives||{}).map((([e,t])=>{r.directive(e,t)})),Object.entries(s.components||{}).map((([e,t])=>{r.component(e,t)})),r.mount(e)},IF:({el:e,data:t,app:s})=>{t.compute(s.state)?e.style.removeProperty("display"):e.style.display="none"},MODEL:({el:e,data:t,app:s})=>{const n=e,o=r(t.compute(),{$el:n})(s.state);n.value!==o&&(n.value=o),n.oninput=()=>{const e="number"==typeof o&&!isNaN(n.value),i="boolean"==typeof o&&("true"===n.value||"false"===n.value),a=null==o&&("null"===n.value||"undefined"===n.value);let c;c=e?`Number('${n.value}').toPrecision()`:i?`Boolean('${n.value}')`:a?"null"===n.value?null:void 0:`'${n.value}'`,r(`${t.value} = ${c}`,{$el:n},!1)(s.state)}},ON:({el:e,name:t,data:s,app:n})=>{const[r,o]=t.split("."),i=r.split(":")[1],a=o||null;e[`on${i}`]=e=>{"prevent"===a&&e.preventDefault(),"stop"===a&&e.stopPropagation(),s.compute(n.state)}},TEXT:({el:e,data:t,app:s})=>{var n;e.textContent=null!==(n=t.compute(s.state))&&void 0!==n?n:t.value}},i=(e,s)=>{s[e.name.split(t)[0].toUpperCase()](e)};var a;!function(e){e[e.STATIC=0]="STATIC",e[e.NEEDS_PATCH=1]="NEEDS_PATCH",e[e.DYNAMIC=2]="DYNAMIC"}(a||(a={}));const c=(e,t=[],s)=>{const n=Object.assign({},null==s?void 0:s.attributes),r=Object.assign({},null==s?void 0:s.directives);return t=t instanceof Array?t:[t],n.className&&(n.className=n.className.trim()),{tag:e,children:t,props:{attributes:n,directives:r,ref:(null==s?void 0:s.ref)||void 0,type:(null==s?void 0:s.type)||0}}},l=t=>{const s={},n={};if(t.attributes)for(const{name:o,value:i}of[...t.attributes]){const a={compute:r(i,{$el:t}),value:i};o.startsWith("l-")?n[o.slice("l-".length)]=a:Object.keys(e).includes(o[0])?n[`${e[o[0]]}:${o.slice(1)}`]=a:s[o]=i}return{attributes:s,directives:n}},p=(e,t,n)=>{const{attributes:r,directives:o}=l(e);let i=a.STATIC;const p=Object.keys(o).length>0,u=Object.values(o).some((({value:e})=>Object.keys(t).some((t=>s(t,!1).test(e)))));return p&&(i=a.NEEDS_PATCH),u&&(i=a.DYNAMIC),c(e.tagName.toLowerCase(),n,{attributes:r,directives:o,ref:i===a.STATIC||r.id?void 0:e,type:i})},u=(e,t={},s={},n=!1,r=!1)=>{var o;if(!e)throw new Error("Please provide a Element");const i=[],a=Array.prototype.slice.call(e.childNodes);for(const r of a)switch(r.nodeType){case Node.TEXT_NODE:!n&&r.nodeValue&&i.push(r.nodeValue);break;case Node.ELEMENT_NODE:if(Object.keys(s).includes(r.tagName)){const a=document.createElement("div"),c=s[r.tagName]({children:r.innerHTML,state:t});a.innerHTML=c;for(const[e,t]of Object.entries(l(r).directives))null===(o=a.firstElementChild)||void 0===o||o.setAttribute(`l-${e}`,t.value);if(!n||a.outerHTML.includes(" l-")){const e=u(a,t,s,n,!0);for(const t of e)i.push(t)}e.replaceChild(a.firstElementChild,r)}else if(!n||r.outerHTML.includes(" l-")){const e=u(r,t,s,n,!0),o=p(r,t,e);i.push(o)}}if(r)return i;{let s=p(e,t,i);return n?d(s):s}},d=e=>{const t=Object.assign({},e);t.children.filter((e=>"object"==typeof e&&e.props.type>0));for(const s of e.children)if("string"!=typeof s&&s.children.length>0)for(const e of d(s).children)"string"!=typeof e&&0!==e.props.type&&t.children.push(e);return t},m=(e,t,s,n,r=!1)=>{if("length"===t){const t=Object.keys(s).filter((t=>{return s[t]instanceof Array&&(n=e,r=s[t],n instanceof Array&&r instanceof Array&&n.length===r.length&&n.every(((e,t)=>e===r[t])));var n,r}));return 0!==t.length&&n(t),!0}return r&&n([t]),!1},h=(e,t)=>{const s={get:(e,t)=>"object"==typeof e[t]&&null!==e[t]?new Proxy(e[t],s):e[t],set(s,n,r){const o=s[n]!==r;return o&&(s[n]=r),m(s,n,e,t,o),!0},deleteProperty:(s,n)=>(delete s[n],m(s,n,e,t),!0)};return new Proxy(e,s)},v=(e,t={},n)=>{let r=!1;const o=t.state||{};if(e){n||(n=Object.keys(o)),"%LUCIA_FIRST_RENDER%"===n[0]&&(r=!0);for(let c of e.children)if("string"!=typeof c){if(c.props.type>a.STATIC){const{attributes:e,directives:l,ref:p,type:u}=c.props;let d=[];if(!r)for(const e in l){const t=1===u,r=n.some((t=>s(t).test(String(l[e].value)))),i=Object.keys(o).some((e=>{const t=n.some((t=>s(t).test(String(o[e]))));return"function"==typeof o[e]&&t}));(t||r||i)&&d.push(e)}c.props.type=u===a.NEEDS_PATCH?a.STATIC:u;(r?Object.keys(l):d).map((s=>{const n=l[s],r=e.id?document.getElementById(e.id):p;i({el:r,name:s,data:n,app:t},Object.assign({},t.directives))}))}c.children.length>0&&v(c,o,n)}}};class f{constructor(e={},t){this.state=e,this.directives={},this.components={},this.mountHook=t}mount(e,t=!1){const s="string"==typeof e?document.querySelector(e):e;return this.vdom=this.compile(s),t||(this.state=h(this.state,this.patch.bind(this)),this.directives=Object.assign(Object.assign({},this.directives),o)),this.patch(["%LUCIA_FIRST_RENDER%"]),this.mountHook&&this.mountHook(this.state),this.state}component(e,t){this.components[e.toUpperCase()]=t}directive(e,t){this.directives[e.toUpperCase()]=t}patch(e){const t={state:this.state,directives:this.directives,components:this.components};v(this.vdom,t,e)}compile(e){return u(e,this.state,this.components,!0)}}const b=(e,t)=>new f(e,t);exports.compile=u,exports.createApp=b,exports.directives=o,exports.h=c,exports.init=(e=document)=>{[...e.querySelectorAll("[l-state]")].filter((e=>void 0===e.__l)).map((e=>{const t=e.getAttribute("l-state");try{const s=new Function(`return ${t}`)(),n=b(s);n.mount(e),e.__l=n}catch(s){console.warn(`Lucia Error: "${s}"\n\nExpression: "${t}"\nElement:`,e)}}))},exports.listen=(e,t=document,s)=>{const n=new MutationObserver((r=>{r.map((t=>{t.addedNodes.length>0&&t.addedNodes.forEach((t=>{1===t.nodeType&&(t.parentElement&&t.parentElement.closest("[l-state]")||e(t.parentElement))}))})),n.observe(t,s||{childList:!0,attributes:!0,subtree:!0})}))},exports.patch=v,exports.reactive=h,exports.renderDirective=i; |
const DIRECTIVE_PREFIX = 'l-'; | ||
const LUCIA_COMPILE_REQUEST = '%LUCIA_COMPILE_REQUEST%'; | ||
const LUCIA_FIRST_RENDER = '%LUCIA_FIRST_RENDER%'; | ||
var DIRECTIVE_SHORTHANDS; | ||
(function (DIRECTIVE_SHORTHANDS) { | ||
DIRECTIVE_SHORTHANDS["@"] = "ON"; | ||
DIRECTIVE_SHORTHANDS[":"] = "BIND"; | ||
DIRECTIVE_SHORTHANDS["@"] = "on"; | ||
DIRECTIVE_SHORTHANDS[":"] = "bind"; | ||
})(DIRECTIVE_SHORTHANDS || (DIRECTIVE_SHORTHANDS = {})); | ||
var VNodeTypes; | ||
(function (VNodeTypes) { | ||
VNodeTypes[VNodeTypes["STATIC"] = 0] = "STATIC"; | ||
VNodeTypes[VNodeTypes["NEEDS_PATCH"] = 1] = "NEEDS_PATCH"; | ||
VNodeTypes[VNodeTypes["DYNAMIC"] = 2] = "DYNAMIC"; | ||
})(VNodeTypes || (VNodeTypes = {})); | ||
const rawDirectiveSplitPattern = /:|\./; | ||
const selectorSplitPattern = /(?=\.)|(?=#)|(?=\[)/; | ||
const keyPattern = (key, hasThis = true) => { | ||
@@ -22,31 +14,182 @@ return new RegExp(`${hasThis ? 'this\\.' : ''}${key}\\b`); | ||
const h = (selector, children, props) => { | ||
const tokens = selector.split(selectorSplitPattern); | ||
const tag = tokens[0]; | ||
const attributes = Object.assign({}, props === null || props === void 0 ? void 0 : props.attributes); | ||
const directives = Object.assign({}, props === null || props === void 0 ? void 0 : props.directives); | ||
if (tokens.length > 1) { | ||
tokens.shift(); | ||
for (const token of tokens) { | ||
switch (token[0]) { | ||
case '#': | ||
attributes.id = token.slice(1); | ||
break; | ||
case '.': | ||
if (!attributes.className) | ||
attributes.className = ''; | ||
attributes.className += `${token.slice(1)} `; | ||
break; | ||
case '[': | ||
const [key, value] = token.slice(1, -1).split('='); | ||
if (key.startsWith(DIRECTIVE_PREFIX)) { | ||
directives[key.slice(DIRECTIVE_PREFIX.length)] = value; | ||
const bindDirective = ({ el, name, data, app }) => { | ||
switch (name.split(':')[1]) { | ||
case 'class': | ||
const hydratedClasses = data.compute(app.state); | ||
if (typeof hydratedClasses === 'string') { | ||
return el.setAttribute('class', `${el.className} ${hydratedClasses}`.trim()); | ||
} | ||
else if (hydratedClasses instanceof Array) { | ||
return el.setAttribute('class', `${el.className} ${hydratedClasses.join(' ')}`.trim()); | ||
} | ||
else { | ||
const classes = []; | ||
for (const key in hydratedClasses) { | ||
if (hydratedClasses[key]) | ||
classes.push(key); | ||
} | ||
if (classes.length > 0) { | ||
return el.setAttribute('class', `${el.className} ${classes.join(' ').trim()}`.trim()); | ||
} | ||
else if (el.className.trim().length > 0) { | ||
return el.setAttribute('class', el.className); | ||
} | ||
else { | ||
return el.removeAttribute('class'); | ||
} | ||
} | ||
case 'style': | ||
const hydratedStyles = data.compute(app.state); | ||
el.removeAttribute('style'); | ||
for (const key in hydratedStyles) { | ||
el.style[key] = hydratedStyles[key]; | ||
} | ||
break; | ||
default: | ||
const hydratedAttributes = data.compute(app.state); | ||
if (typeof hydratedAttributes === 'object' && hydratedAttributes !== null) { | ||
for (const key in hydratedAttributes) { | ||
if (hydratedAttributes[key]) { | ||
el.setAttribute(key, hydratedAttributes[key]); | ||
} | ||
else { | ||
attributes[key] = value; | ||
el.removeAttribute(key); | ||
} | ||
break; | ||
} | ||
} | ||
else if (hydratedAttributes) { | ||
el.setAttribute(name.split(':')[1], hydratedAttributes); | ||
} | ||
else { | ||
el.removeAttribute(name.split(':')[1]); | ||
} | ||
break; | ||
} | ||
}; | ||
const htmlDirective = ({ el, data, app }) => { | ||
var _a; | ||
el.innerHTML = (_a = data.compute(app.state)) !== null && _a !== void 0 ? _a : data.value; | ||
const scope = createApp(Object.assign({}, app.state)); | ||
Object.entries(app.directives || {}).map(([name, evaluationCallback]) => { | ||
scope.directive(name, evaluationCallback); | ||
}); | ||
Object.entries(app.components || {}).map(([name, templateCallback]) => { | ||
scope.component(name, templateCallback); | ||
}); | ||
scope.mount(el); | ||
}; | ||
const ifDirective = ({ el, data, app }) => { | ||
const hydratedConditional = data.compute(app.state); | ||
if (hydratedConditional) { | ||
el.style.removeProperty('display'); | ||
} | ||
else { | ||
el.style.display = 'none'; | ||
} | ||
}; | ||
function createComputeFunction(state) { | ||
try { | ||
const expression = this.returnable ? `return ${this.expression}` : this.expression; | ||
return new Function(...Object.keys(this.argsKV), expression).bind(state)(...Object.values(this.argsKV)); | ||
} | ||
catch (err) { | ||
console.warn(`Lucia Error: "${err}"\n\nExpression: "${this.expression}"\nElement:`, this.argsKV.$el); | ||
} | ||
} | ||
const compute = (expression, data, returnable = true) => { | ||
return createComputeFunction.bind({ expression, argsKV: { $el: data.$el }, returnable }); | ||
}; | ||
const joinDirective = ({ el, data, app }) => { | ||
const [array, contentType, delimiter] = data.value.split(/ as | by /); | ||
const hydratedArray = compute(array, { $el: el })(app.state); | ||
const accessProp = contentType === 'text' ? 'innerText' : 'innerHTML'; | ||
el[accessProp] = hydratedArray.join(delimiter || ''); | ||
const scope = createApp(Object.assign({}, app.state)); | ||
Object.entries(app.directives || {}).map(([name, evaluationCallback]) => { | ||
scope.directive(name, evaluationCallback); | ||
}); | ||
Object.entries(app.components || {}).map(([name, templateCallback]) => { | ||
scope.component(name, templateCallback); | ||
}); | ||
scope.mount(el); | ||
}; | ||
const modelDirective = ({ el: awaitingTypecastEl, data, app }) => { | ||
const el = awaitingTypecastEl; | ||
const hydratedValue = compute(data.compute(), { $el: el })(app.state); | ||
if (el.value !== hydratedValue) { | ||
el.value = hydratedValue; | ||
} | ||
el.oninput = () => { | ||
const isNumber = typeof hydratedValue === 'number' && !isNaN(el.value); | ||
const isBoolean = typeof hydratedValue === 'boolean' && (el.value === 'true' || el.value === 'false'); | ||
const isNullish = (hydratedValue === null || hydratedValue === undefined) && | ||
(el.value === 'null' || el.value === 'undefined'); | ||
let payload; | ||
if (isNumber) { | ||
payload = `Number('${el.value}').toPrecision()`; | ||
} | ||
} | ||
else if (isBoolean) { | ||
payload = `Boolean('${el.value}')`; | ||
} | ||
else if (isNullish) { | ||
if (el.value === 'null') | ||
payload = null; | ||
else | ||
payload = undefined; | ||
} | ||
else { | ||
payload = `'${el.value}'`; | ||
} | ||
compute(`${data.value} = ${payload}`, { $el: el }, false)(app.state); | ||
}; | ||
}; | ||
const onDirective = ({ el, name, data, app }) => { | ||
const [directiveAndEventName, prop] = name.split('.'); | ||
const eventName = directiveAndEventName.split(':')[1]; | ||
const eventProp = prop || null; | ||
el[`on${eventName}`] = ($event) => { | ||
if (eventProp === 'prevent') | ||
$event.preventDefault(); | ||
if (eventProp === 'stop') | ||
$event.stopPropagation(); | ||
data.compute(app.state); | ||
}; | ||
}; | ||
const textDirective = ({ el, data, app }) => { | ||
var _a; | ||
el.textContent = (_a = data.compute(app.state)) !== null && _a !== void 0 ? _a : data.value; | ||
}; | ||
const directives = { | ||
BIND: bindDirective, | ||
JOIN: joinDirective, | ||
HTML: htmlDirective, | ||
IF: ifDirective, | ||
MODEL: modelDirective, | ||
ON: onDirective, | ||
TEXT: textDirective, | ||
}; | ||
const renderDirective = (props, directives) => { | ||
const name = props.name.split(rawDirectiveSplitPattern)[0]; | ||
directives[name.toUpperCase()](props); | ||
}; | ||
var VNodeTypes; | ||
(function (VNodeTypes) { | ||
VNodeTypes[VNodeTypes["STATIC"] = 0] = "STATIC"; | ||
VNodeTypes[VNodeTypes["NEEDS_PATCH"] = 1] = "NEEDS_PATCH"; | ||
VNodeTypes[VNodeTypes["DYNAMIC"] = 2] = "DYNAMIC"; | ||
})(VNodeTypes || (VNodeTypes = {})); | ||
const h = (tag, children = [], props) => { | ||
const attributes = Object.assign({}, props === null || props === void 0 ? void 0 : props.attributes); | ||
const directives = Object.assign({}, props === null || props === void 0 ? void 0 : props.directives); | ||
children = children instanceof Array ? children : [children]; | ||
if (attributes.className) | ||
@@ -56,3 +199,3 @@ attributes.className = attributes.className.trim(); | ||
tag, | ||
children: typeof children === 'string' ? [children] : children ? children : [], | ||
children, | ||
props: { | ||
@@ -72,7 +215,8 @@ attributes, | ||
for (const { name, value } of [...el.attributes]) { | ||
const directiveData = { compute: compute(value, { $el: el }), value }; | ||
if (name.startsWith(DIRECTIVE_PREFIX)) { | ||
directives[name.slice(DIRECTIVE_PREFIX.length)] = value; | ||
directives[name.slice(DIRECTIVE_PREFIX.length)] = directiveData; | ||
} | ||
else if (Object.keys(DIRECTIVE_SHORTHANDS).includes(name[0])) { | ||
directives[`${DIRECTIVE_SHORTHANDS[name[0]]}:${name.slice(1)}`] = value; | ||
directives[`${DIRECTIVE_SHORTHANDS[name[0]]}:${name.slice(1)}`] = directiveData; | ||
} | ||
@@ -91,3 +235,3 @@ else { | ||
const hasDirectives = Object.keys(directives).length > 0; | ||
const hasKeyInDirectives = Object.values(directives).some((value) => Object.keys(state).some((key) => keyPattern(key, false).test(value))); | ||
const hasKeyInDirectives = Object.values(directives).some(({ value }) => Object.keys(state).some((key) => keyPattern(key, false).test(value))); | ||
if (hasDirectives) | ||
@@ -98,4 +242,4 @@ type = VNodeTypes.NEEDS_PATCH; | ||
return h(el.tagName.toLowerCase(), children, { | ||
attributes, | ||
directives, | ||
attributes: attributes, | ||
directives: directives, | ||
ref: type === VNodeTypes.STATIC || attributes.id ? undefined : el, | ||
@@ -126,4 +270,4 @@ type, | ||
container.innerHTML = template; | ||
for (const [key, value] of Object.entries(props(child).directives)) { | ||
(_a = container.firstElementChild) === null || _a === void 0 ? void 0 : _a.setAttribute(`${DIRECTIVE_PREFIX}${key}`, value); | ||
for (const [key, data] of Object.entries(props(child).directives)) { | ||
(_a = container.firstElementChild) === null || _a === void 0 ? void 0 : _a.setAttribute(`${DIRECTIVE_PREFIX}${key}`, data.value); | ||
} | ||
@@ -175,150 +319,2 @@ if (!strip || container.outerHTML.includes(` ${DIRECTIVE_PREFIX}`)) { | ||
const safeEval = (expression, argsKV = {}, bindKV = {}, returnable = true) => { | ||
return new Function(...Object.keys(argsKV), returnable ? `return ${expression}` : expression).bind(bindKV)(...Object.values(argsKV)); | ||
}; | ||
const computeProperties = (expression, data, returnable = true) => { | ||
return safeEval(expression, { $el: data.$el }, data.$state, returnable); | ||
}; | ||
const bindDirective = ({ el, name, value, state }) => { | ||
switch (name.split(':')[1]) { | ||
case 'class': | ||
const classState = computeProperties(value, { $state: state, $el: el }); | ||
if (typeof classState === 'string') { | ||
return el.setAttribute('class', `${el.className} ${classState}`.trim()); | ||
} | ||
if (classState instanceof Array) { | ||
return el.setAttribute('class', `${el.className} ${classState.join(' ')}`.trim()); | ||
} | ||
else { | ||
const classes = []; | ||
for (const key in classState) { | ||
if (classState[key]) | ||
classes.push(key); | ||
} | ||
if (classes.length > 0) { | ||
return el.setAttribute('class', `${el.className} ${classes.join(' ').trim()}`.trim()); | ||
} | ||
else if (el.className.trim().length > 0) { | ||
return el.setAttribute('class', el.className); | ||
} | ||
else { | ||
return el.removeAttribute('class'); | ||
} | ||
} | ||
case 'style': | ||
const styleState = computeProperties(value, { $state: state, $el: el }); | ||
el.removeAttribute('style'); | ||
for (const key in styleState) { | ||
el.style[key] = styleState[key]; | ||
} | ||
break; | ||
default: | ||
const out = computeProperties(value, { $state: state, $el: el }); | ||
if (out) { | ||
el.setAttribute(name.split(':')[1], out); | ||
} | ||
else { | ||
el.removeAttribute(name.split(':')[1]); | ||
} | ||
break; | ||
} | ||
}; | ||
const htmlDirective = ({ el, value, state }) => { | ||
const app = createApp(Object.assign({}, state)); | ||
app.mount(el, true); | ||
try { | ||
el.innerHTML = computeProperties(value, { $state: state, $el: el }); | ||
} | ||
catch (_a) { | ||
el.innerHTML = value; | ||
} | ||
}; | ||
const ifDirective = ({ el, value, state }) => { | ||
const out = computeProperties(value, { $state: state, $el: el }); | ||
if (out) { | ||
el.style.removeProperty('display'); | ||
} | ||
else { | ||
el.style.display = 'none'; | ||
} | ||
}; | ||
const joinDirective = ({ el, value, state }) => { | ||
const [array, contentType, delimiter] = value.split(/ as | by /); | ||
const out = computeProperties(array, { $state: state, $el: el }); | ||
const accessProp = contentType === 'text' ? 'innerText' : 'innerHTML'; | ||
el[accessProp] = out.join(delimiter || ''); | ||
const app = createApp(Object.assign({}, state)); | ||
app.mount(el, true); | ||
}; | ||
const modelDirective = ({ el: awaitingTypecastEl, value, state }) => { | ||
const el = awaitingTypecastEl; | ||
const out = computeProperties(value, { $state: state, $el: el }); | ||
if (el.value !== out) { | ||
el.value = out; | ||
} | ||
el.oninput = () => { | ||
const isNumber = typeof out === 'number' && !isNaN(el.value); | ||
const isBoolean = typeof out === 'boolean' && (el.value === 'true' || el.value === 'false'); | ||
const isNullish = (out === null || out === undefined) && (el.value === 'null' || el.value === 'undefined'); | ||
let payload; | ||
if (isNumber) { | ||
payload = `Number('${el.value}').toPrecision()`; | ||
} | ||
else if (isBoolean) { | ||
payload = `Boolean('${el.value}')`; | ||
} | ||
else if (isNullish) { | ||
if (el.value === 'null') | ||
payload = null; | ||
else | ||
payload = undefined; | ||
} | ||
else { | ||
payload = `'${el.value}'`; | ||
} | ||
computeProperties(`${value} = ${payload}`, { $state: state, $el: el }, false); | ||
}; | ||
}; | ||
const onDirective = ({ el, name, value, state }) => { | ||
const [directiveAndEventName, prop] = name.split('.'); | ||
const eventName = directiveAndEventName.split(':')[1]; | ||
const eventProp = prop || null; | ||
el[`on${eventName}`] = ($event) => { | ||
if (eventProp === 'prevent') | ||
$event.preventDefault(); | ||
if (eventProp === 'stop') | ||
$event.stopPropagation(); | ||
computeProperties(value, { $state: state, $el: el }, false); | ||
}; | ||
}; | ||
const textDirective = ({ el, value, state }) => { | ||
try { | ||
el.innerHTML = computeProperties(value, { $state: state, $el: el }); | ||
} | ||
catch (_a) { | ||
el.innerHTML = value; | ||
} | ||
}; | ||
const directives = { | ||
BIND: bindDirective, | ||
JOIN: joinDirective, | ||
HTML: htmlDirective, | ||
IF: ifDirective, | ||
MODEL: modelDirective, | ||
ON: onDirective, | ||
TEXT: textDirective, | ||
}; | ||
const renderDirective = ({ el, name, value, state }, directives) => { | ||
const rootName = name.split(rawDirectiveSplitPattern)[0]; | ||
directives[rootName.toUpperCase()]({ el, name, value, state }); | ||
}; | ||
const arrayEquals = (firstArray, secondArray) => { | ||
@@ -331,3 +327,3 @@ return (firstArray instanceof Array && | ||
const handleArray = (target, key, state, patch) => { | ||
const handlePatch = (target, key, state, patch, needsUpdate = false) => { | ||
if (key === 'length') { | ||
@@ -342,3 +338,4 @@ const affectedKeys = Object.keys(state).filter((k) => { | ||
else { | ||
patch([key]); | ||
if (needsUpdate) | ||
patch([key]); | ||
return false; | ||
@@ -358,4 +355,7 @@ } | ||
set(target, key, value) { | ||
target[key] = value; | ||
handleArray(target, key, state, patch); | ||
const needsUpdate = target[key] !== value; | ||
if (needsUpdate) { | ||
target[key] = value; | ||
} | ||
handlePatch(target, key, state, patch, needsUpdate); | ||
return true; | ||
@@ -365,3 +365,3 @@ }, | ||
delete target[key]; | ||
handleArray(target, key, state, patch); | ||
handlePatch(target, key, state, patch); | ||
return true; | ||
@@ -373,4 +373,5 @@ }, | ||
const patch = (rootVNode, state = {}, directiveKV = {}, keys) => { | ||
let compileRequest = false; | ||
const patch = (rootVNode, app = {}, keys) => { | ||
let firstRender = false; | ||
const state = app.state || {}; | ||
if (!rootVNode) | ||
@@ -380,4 +381,4 @@ return; | ||
keys = Object.keys(state); | ||
if (keys[0] === LUCIA_COMPILE_REQUEST) | ||
compileRequest = true; | ||
if (keys[0] === LUCIA_FIRST_RENDER) | ||
firstRender = true; | ||
for (let node of rootVNode.children) { | ||
@@ -389,9 +390,8 @@ if (typeof node === 'string') | ||
let affectedDirectives = []; | ||
if (!compileRequest) { | ||
if (!firstRender) { | ||
for (const name in directives) { | ||
const value = directives[name]; | ||
const needsInit = type === 1; | ||
const hasKey = keys.some((key) => keyPattern(key).test(value.toString())); | ||
const hasKey = keys.some((key) => keyPattern(key).test(String(directives[name].value))); | ||
const hasKeyInFunction = Object.keys(state).some((key) => { | ||
const iterKeysInFunction = keys.some((k) => keyPattern(k).test(state[key].toString())); | ||
const iterKeysInFunction = keys.some((k) => keyPattern(k).test(String(state[key]))); | ||
return typeof state[key] === 'function' && iterKeysInFunction; | ||
@@ -405,13 +405,13 @@ }); | ||
node.props.type = type === VNodeTypes.NEEDS_PATCH ? VNodeTypes.STATIC : type; | ||
const directivesToRender = compileRequest | ||
const directivesToRender = firstRender | ||
? Object.keys(directives) | ||
: affectedDirectives; | ||
directivesToRender.map((name) => { | ||
const value = directives[name]; | ||
const data = directives[name]; | ||
const el = (attributes.id ? document.getElementById(attributes.id) : ref); | ||
renderDirective({ el, name, value, state }, Object.assign({}, directiveKV)); | ||
renderDirective({ el, name, data, app }, Object.assign({}, app.directives)); | ||
}); | ||
} | ||
if (node.children.length > 0) | ||
patch(node, state, directiveKV, keys); | ||
patch(node, state, keys); | ||
} | ||
@@ -421,29 +421,33 @@ }; | ||
class App { | ||
constructor(state = {}) { | ||
this.vdom = null; | ||
constructor(state = {}, mountHook) { | ||
this.state = state; | ||
this.directives = {}; | ||
this.components = {}; | ||
this.mounted = false; | ||
this.mountHook = mountHook; | ||
} | ||
mount(el, shallow = false) { | ||
this.vdom = this.compile((typeof el === 'string' ? document.querySelector(el) : el)); | ||
const rootEl = typeof el === 'string' ? document.querySelector(el) : el; | ||
this.vdom = this.compile(rootEl); | ||
if (!shallow) { | ||
this.state = reactive(this.state, this.patch.bind(this)); | ||
this.directives = directives; | ||
this.directives = Object.assign(Object.assign({}, this.directives), directives); | ||
} | ||
this.mounted = true; | ||
this.patch([LUCIA_COMPILE_REQUEST]); | ||
this.patch([LUCIA_FIRST_RENDER]); | ||
if (this.mountHook) | ||
this.mountHook(this.state); | ||
return this.state; | ||
} | ||
component(name, fn) { | ||
this.components[name.toUpperCase()] = fn; | ||
component(name, templateCallback) { | ||
this.components[name.toUpperCase()] = templateCallback; | ||
} | ||
directive(name, fn) { | ||
this.directives[name.toUpperCase()] = fn; | ||
directive(name, evaluationCallback) { | ||
this.directives[name.toUpperCase()] = evaluationCallback; | ||
} | ||
patch(keys) { | ||
if (!this.mounted) | ||
throw new Error('App is not mounted.'); | ||
patch(this.vdom, this.state, this.directives, keys); | ||
const app = { | ||
state: this.state, | ||
directives: this.directives, | ||
components: this.components, | ||
}; | ||
patch(this.vdom, app, keys); | ||
} | ||
@@ -454,23 +458,45 @@ compile(el) { | ||
} | ||
const createApp = (state) => { | ||
return new App(state); | ||
const createApp = (state, mountHook) => { | ||
return new App(state, mountHook); | ||
}; | ||
const init = (element = document, directive = 'use') => { | ||
const elements = [...element.querySelectorAll(`[${DIRECTIVE_PREFIX + directive}]`)]; | ||
const apps = []; | ||
elements.map((el) => { | ||
const state = el.getAttribute(DIRECTIVE_PREFIX + directive); | ||
if (state === null) | ||
return; | ||
const stateDirective = `${DIRECTIVE_PREFIX}state`; | ||
const init = (element = document) => { | ||
const elements = [...element.querySelectorAll(`[${stateDirective}]`)]; | ||
elements | ||
.filter((el) => el.__l === undefined) | ||
.map((el) => { | ||
const expression = el.getAttribute(stateDirective); | ||
try { | ||
const app = createApp(safeEval(state)); | ||
const state = new Function(`return ${expression}`)(); | ||
const app = createApp(state); | ||
app.mount(el); | ||
apps.push(app); | ||
el.__l = app; | ||
} | ||
catch (err) { } | ||
catch (err) { | ||
console.warn(`Lucia Error: "${err}"\n\nExpression: "${expression}"\nElement:`, el); | ||
} | ||
}); | ||
return apps; | ||
}; | ||
const listen = (callback, element = document, config) => { | ||
const observer = new MutationObserver((mutations) => { | ||
mutations.map((mut) => { | ||
if (mut.addedNodes.length > 0) { | ||
mut.addedNodes.forEach((node) => { | ||
if (node.nodeType !== 1) | ||
return; | ||
if (node.parentElement && node.parentElement.closest(`[${stateDirective}]`)) | ||
return; | ||
callback(node.parentElement); | ||
}); | ||
} | ||
}); | ||
observer.observe(element, config || { | ||
childList: true, | ||
attributes: true, | ||
subtree: true, | ||
}); | ||
}); | ||
}; | ||
export { compile, createApp, directives, h, init, patch, reactive, renderDirective }; | ||
export { compile, createApp, directives, h, init, listen, patch, reactive, renderDirective }; |
@@ -1,1 +0,1 @@ | ||
var e,t;!function(e){e["@"]="ON",e[":"]="BIND"}(e||(e={})),function(e){e[e.STATIC=0]="STATIC",e[e.NEEDS_PATCH=1]="NEEDS_PATCH",e[e.DYNAMIC=2]="DYNAMIC"}(t||(t={}));const s=/:|\./,n=/(?=\.)|(?=#)|(?=\[)/,i=(e,t=!0)=>new RegExp(`${t?"this\\.":""}${e}\\b`),r=(e,t,s)=>{const i=e.split(n),r=i[0],l=Object.assign({},null==s?void 0:s.attributes),o=Object.assign({},null==s?void 0:s.directives);if(i.length>1){i.shift();for(const e of i)switch(e[0]){case"#":l.id=e.slice(1);break;case".":l.className||(l.className=""),l.className+=`${e.slice(1)} `;break;case"[":const[t,s]=e.slice(1,-1).split("=");t.startsWith("l-")?o[t.slice("l-".length)]=s:l[t]=s}}return l.className&&(l.className=l.className.trim()),{tag:r,children:"string"==typeof t?[t]:t||[],props:{attributes:l,directives:o,ref:(null==s?void 0:s.ref)||void 0,type:(null==s?void 0:s.type)||0}}},l=t=>{const s={},n={};if(t.attributes)for(const{name:i,value:r}of[...t.attributes])i.startsWith("l-")?n[i.slice("l-".length)]=r:Object.keys(e).includes(i[0])?n[`${e[i[0]]}:${i.slice(1)}`]=r:s[i]=r;return{attributes:s,directives:n}},o=(e,s,n)=>{const{attributes:o,directives:a}=l(e);let c=t.STATIC;const u=Object.keys(a).length>0,p=Object.values(a).some((e=>Object.keys(s).some((t=>i(t,!1).test(e)))));return u&&(c=t.NEEDS_PATCH),p&&(c=t.DYNAMIC),r(e.tagName.toLowerCase(),n,{attributes:o,directives:a,ref:c===t.STATIC||o.id?void 0:e,type:c})},a=(e,t={},s={},n=!1,i=!1)=>{var r;if(!e)throw new Error("Please provide a Element");const u=[],p=Array.prototype.slice.call(e.childNodes);for(const i of p)switch(i.nodeType){case Node.TEXT_NODE:!n&&i.nodeValue&&u.push(i.nodeValue);break;case Node.ELEMENT_NODE:if(Object.keys(s).includes(i.tagName)){const o=document.createElement("div"),c=s[i.tagName]({children:i.innerHTML,state:t});o.innerHTML=c;for(const[e,t]of Object.entries(l(i).directives))null===(r=o.firstElementChild)||void 0===r||r.setAttribute(`l-${e}`,t);if(!n||o.outerHTML.includes(" l-")){const e=a(o,t,s,n,!0);for(const t of e)u.push(t)}e.replaceChild(o.firstElementChild,i)}else if(!n||i.outerHTML.includes(" l-")){const e=a(i,t,s,n,!0),r=o(i,t,e);u.push(r)}}if(i)return u;{let s=o(e,t,u);return n?c(s):s}},c=e=>{const t=Object.assign({},e);t.children.filter((e=>"object"==typeof e&&e.props.type>0));for(const s of e.children)if("string"!=typeof s&&s.children.length>0)for(const e of c(s).children)"string"!=typeof e&&0!==e.props.type&&t.children.push(e);return t},u=(e,t={},s={},n=!0)=>new Function(...Object.keys(t),n?`return ${e}`:e).bind(s)(...Object.values(t)),p=(e,t,s=!0)=>u(e,{$el:t.$el},t.$state,s),d={BIND:({el:e,name:t,value:s,state:n})=>{switch(t.split(":")[1]){case"class":const i=p(s,{$state:n,$el:e});if("string"==typeof i)return e.setAttribute("class",`${e.className} ${i}`.trim());if(i instanceof Array)return e.setAttribute("class",`${e.className} ${i.join(" ")}`.trim());{const t=[];for(const e in i)i[e]&&t.push(e);return t.length>0?e.setAttribute("class",`${e.className} ${t.join(" ").trim()}`.trim()):e.className.trim().length>0?e.setAttribute("class",e.className):e.removeAttribute("class")}case"style":const r=p(s,{$state:n,$el:e});e.removeAttribute("style");for(const t in r)e.style[t]=r[t];break;default:const l=p(s,{$state:n,$el:e});l?e.setAttribute(t.split(":")[1],l):e.removeAttribute(t.split(":")[1])}},JOIN:({el:e,value:t,state:s})=>{const[n,i,r]=t.split(/ as | by /),l=p(n,{$state:s,$el:e});e["text"===i?"innerText":"innerHTML"]=l.join(r||"");b(Object.assign({},s)).mount(e,!0)},HTML:({el:e,value:t,state:s})=>{b(Object.assign({},s)).mount(e,!0);try{e.innerHTML=p(t,{$state:s,$el:e})}catch(s){e.innerHTML=t}},IF:({el:e,value:t,state:s})=>{p(t,{$state:s,$el:e})?e.style.removeProperty("display"):e.style.display="none"},MODEL:({el:e,value:t,state:s})=>{const n=e,i=p(t,{$state:s,$el:n});n.value!==i&&(n.value=i),n.oninput=()=>{const e="number"==typeof i&&!isNaN(n.value),r="boolean"==typeof i&&("true"===n.value||"false"===n.value),l=null==i&&("null"===n.value||"undefined"===n.value);let o;o=e?`Number('${n.value}').toPrecision()`:r?`Boolean('${n.value}')`:l?"null"===n.value?null:void 0:`'${n.value}'`,p(`${t} = ${o}`,{$state:s,$el:n},!1)}},ON:({el:e,name:t,value:s,state:n})=>{const[i,r]=t.split("."),l=i.split(":")[1],o=r||null;e[`on${l}`]=t=>{"prevent"===o&&t.preventDefault(),"stop"===o&&t.stopPropagation(),p(s,{$state:n,$el:e},!1)}},TEXT:({el:e,value:t,state:s})=>{try{e.innerHTML=p(t,{$state:s,$el:e})}catch(s){e.innerHTML=t}}},h=({el:e,name:t,value:n,state:i},r)=>{r[t.split(s)[0].toUpperCase()]({el:e,name:t,value:n,state:i})},f=(e,t,s,n)=>{if("length"===t){const t=Object.keys(s).filter((t=>{return s[t]instanceof Array&&(n=e,i=s[t],n instanceof Array&&i instanceof Array&&n.length===i.length&&n.every(((e,t)=>e===i[t])));var n,i}));return 0!==t.length&&n(t),!0}return n([t]),!1},m=(e,t)=>{const s={get:(e,t)=>"object"==typeof e[t]&&null!==e[t]?new Proxy(e[t],s):e[t],set:(s,n,i)=>(s[n]=i,f(s,n,e,t),!0),deleteProperty:(s,n)=>(delete s[n],f(s,n,e,t),!0)};return new Proxy(e,s)},v=(e,s={},n={},r)=>{let l=!1;if(e){r||(r=Object.keys(s)),"%LUCIA_COMPILE_REQUEST%"===r[0]&&(l=!0);for(let o of e.children)if("string"!=typeof o){if(o.props.type>t.STATIC){const{attributes:e,directives:a,ref:c,type:u}=o.props;let p=[];if(!l)for(const e in a){const t=a[e],n=1===u,l=r.some((e=>i(e).test(t.toString()))),o=Object.keys(s).some((e=>{const t=r.some((t=>i(t).test(s[e].toString())));return"function"==typeof s[e]&&t}));(n||l||o)&&p.push(e)}o.props.type=u===t.NEEDS_PATCH?t.STATIC:u;(l?Object.keys(a):p).map((t=>{const i=a[t],r=e.id?document.getElementById(e.id):c;h({el:r,name:t,value:i,state:s},Object.assign({},n))}))}o.children.length>0&&v(o,s,n,r)}}};class y{constructor(e={}){this.vdom=null,this.state=e,this.directives={},this.components={},this.mounted=!1}mount(e,t=!1){return this.vdom=this.compile("string"==typeof e?document.querySelector(e):e),t||(this.state=m(this.state,this.patch.bind(this)),this.directives=d),this.mounted=!0,this.patch(["%LUCIA_COMPILE_REQUEST%"]),this.state}component(e,t){this.components[e.toUpperCase()]=t}directive(e,t){this.directives[e.toUpperCase()]=t}patch(e){if(!this.mounted)throw new Error("App is not mounted.");v(this.vdom,this.state,this.directives,e)}compile(e){return a(e,this.state,this.components,!0)}}const b=e=>new y(e),$=(e=document,t="use")=>{const s=[...e.querySelectorAll(`[${"l-"+t}]`)],n=[];return s.map((e=>{const s=e.getAttribute("l-"+t);if(null!==s)try{const t=b(u(s));t.mount(e),n.push(t)}catch(e){}})),n};export{a as compile,b as createApp,d as directives,r as h,$ as init,v as patch,m as reactive,h as renderDirective}; | ||
var t;!function(t){t["@"]="on",t[":"]="bind"}(t||(t={}));const e=/:|\./,s=(t,e=!0)=>new RegExp(`${e?"this\\.":""}${t}\\b`);function n(t){try{const e=this.returnable?`return ${this.expression}`:this.expression;return new Function(...Object.keys(this.argsKV),e).bind(t)(...Object.values(this.argsKV))}catch(t){console.warn(`Lucia Error: "${t}"\n\nExpression: "${this.expression}"\nElement:`,this.argsKV.$el)}}const o=(t,e,s=!0)=>n.bind({expression:t,argsKV:{$el:e.$el},returnable:s}),i={BIND:({el:t,name:e,data:s,app:n})=>{switch(e.split(":")[1]){case"class":const o=s.compute(n.state);if("string"==typeof o)return t.setAttribute("class",`${t.className} ${o}`.trim());if(o instanceof Array)return t.setAttribute("class",`${t.className} ${o.join(" ")}`.trim());{const e=[];for(const t in o)o[t]&&e.push(t);return e.length>0?t.setAttribute("class",`${t.className} ${e.join(" ").trim()}`.trim()):t.className.trim().length>0?t.setAttribute("class",t.className):t.removeAttribute("class")}case"style":const i=s.compute(n.state);t.removeAttribute("style");for(const e in i)t.style[e]=i[e];break;default:const r=s.compute(n.state);if("object"==typeof r&&null!==r)for(const e in r)r[e]?t.setAttribute(e,r[e]):t.removeAttribute(e);else r?t.setAttribute(e.split(":")[1],r):t.removeAttribute(e.split(":")[1])}},JOIN:({el:t,data:e,app:s})=>{const[n,i,r]=e.value.split(/ as | by /),a=o(n,{$el:t})(s.state);t["text"===i?"innerText":"innerHTML"]=a.join(r||"");const c=b(Object.assign({},s.state));Object.entries(s.directives||{}).map((([t,e])=>{c.directive(t,e)})),Object.entries(s.components||{}).map((([t,e])=>{c.component(t,e)})),c.mount(t)},HTML:({el:t,data:e,app:s})=>{var n;t.innerHTML=null!==(n=e.compute(s.state))&&void 0!==n?n:e.value;const o=b(Object.assign({},s.state));Object.entries(s.directives||{}).map((([t,e])=>{o.directive(t,e)})),Object.entries(s.components||{}).map((([t,e])=>{o.component(t,e)})),o.mount(t)},IF:({el:t,data:e,app:s})=>{e.compute(s.state)?t.style.removeProperty("display"):t.style.display="none"},MODEL:({el:t,data:e,app:s})=>{const n=t,i=o(e.compute(),{$el:n})(s.state);n.value!==i&&(n.value=i),n.oninput=()=>{const t="number"==typeof i&&!isNaN(n.value),r="boolean"==typeof i&&("true"===n.value||"false"===n.value),a=null==i&&("null"===n.value||"undefined"===n.value);let c;c=t?`Number('${n.value}').toPrecision()`:r?`Boolean('${n.value}')`:a?"null"===n.value?null:void 0:`'${n.value}'`,o(`${e.value} = ${c}`,{$el:n},!1)(s.state)}},ON:({el:t,name:e,data:s,app:n})=>{const[o,i]=e.split("."),r=o.split(":")[1],a=i||null;t[`on${r}`]=t=>{"prevent"===a&&t.preventDefault(),"stop"===a&&t.stopPropagation(),s.compute(n.state)}},TEXT:({el:t,data:e,app:s})=>{var n;t.textContent=null!==(n=e.compute(s.state))&&void 0!==n?n:e.value}},r=(t,s)=>{s[t.name.split(e)[0].toUpperCase()](t)};var a;!function(t){t[t.STATIC=0]="STATIC",t[t.NEEDS_PATCH=1]="NEEDS_PATCH",t[t.DYNAMIC=2]="DYNAMIC"}(a||(a={}));const c=(t,e=[],s)=>{const n=Object.assign({},null==s?void 0:s.attributes),o=Object.assign({},null==s?void 0:s.directives);return e=e instanceof Array?e:[e],n.className&&(n.className=n.className.trim()),{tag:t,children:e,props:{attributes:n,directives:o,ref:(null==s?void 0:s.ref)||void 0,type:(null==s?void 0:s.type)||0}}},l=e=>{const s={},n={};if(e.attributes)for(const{name:i,value:r}of[...e.attributes]){const a={compute:o(r,{$el:e}),value:r};i.startsWith("l-")?n[i.slice("l-".length)]=a:Object.keys(t).includes(i[0])?n[`${t[i[0]]}:${i.slice(1)}`]=a:s[i]=r}return{attributes:s,directives:n}},u=(t,e,n)=>{const{attributes:o,directives:i}=l(t);let r=a.STATIC;const u=Object.keys(i).length>0,p=Object.values(i).some((({value:t})=>Object.keys(e).some((e=>s(e,!1).test(t)))));return u&&(r=a.NEEDS_PATCH),p&&(r=a.DYNAMIC),c(t.tagName.toLowerCase(),n,{attributes:o,directives:i,ref:r===a.STATIC||o.id?void 0:t,type:r})},p=(t,e={},s={},n=!1,o=!1)=>{var i;if(!t)throw new Error("Please provide a Element");const r=[],a=Array.prototype.slice.call(t.childNodes);for(const o of a)switch(o.nodeType){case Node.TEXT_NODE:!n&&o.nodeValue&&r.push(o.nodeValue);break;case Node.ELEMENT_NODE:if(Object.keys(s).includes(o.tagName)){const a=document.createElement("div"),c=s[o.tagName]({children:o.innerHTML,state:e});a.innerHTML=c;for(const[t,e]of Object.entries(l(o).directives))null===(i=a.firstElementChild)||void 0===i||i.setAttribute(`l-${t}`,e.value);if(!n||a.outerHTML.includes(" l-")){const t=p(a,e,s,n,!0);for(const e of t)r.push(e)}t.replaceChild(a.firstElementChild,o)}else if(!n||o.outerHTML.includes(" l-")){const t=p(o,e,s,n,!0),i=u(o,e,t);r.push(i)}}if(o)return r;{let s=u(t,e,r);return n?d(s):s}},d=t=>{const e=Object.assign({},t);e.children.filter((t=>"object"==typeof t&&t.props.type>0));for(const s of t.children)if("string"!=typeof s&&s.children.length>0)for(const t of d(s).children)"string"!=typeof t&&0!==t.props.type&&e.children.push(t);return e},m=(t,e,s,n,o=!1)=>{if("length"===e){const e=Object.keys(s).filter((e=>{return s[e]instanceof Array&&(n=t,o=s[e],n instanceof Array&&o instanceof Array&&n.length===o.length&&n.every(((t,e)=>t===o[e])));var n,o}));return 0!==e.length&&n(e),!0}return o&&n([e]),!1},h=(t,e)=>{const s={get:(t,e)=>"object"==typeof t[e]&&null!==t[e]?new Proxy(t[e],s):t[e],set(s,n,o){const i=s[n]!==o;return i&&(s[n]=o),m(s,n,t,e,i),!0},deleteProperty:(s,n)=>(delete s[n],m(s,n,t,e),!0)};return new Proxy(t,s)},v=(t,e={},n)=>{let o=!1;const i=e.state||{};if(t){n||(n=Object.keys(i)),"%LUCIA_FIRST_RENDER%"===n[0]&&(o=!0);for(let c of t.children)if("string"!=typeof c){if(c.props.type>a.STATIC){const{attributes:t,directives:l,ref:u,type:p}=c.props;let d=[];if(!o)for(const t in l){const e=1===p,o=n.some((e=>s(e).test(String(l[t].value)))),r=Object.keys(i).some((t=>{const e=n.some((e=>s(e).test(String(i[t]))));return"function"==typeof i[t]&&e}));(e||o||r)&&d.push(t)}c.props.type=p===a.NEEDS_PATCH?a.STATIC:p;(o?Object.keys(l):d).map((s=>{const n=l[s],o=t.id?document.getElementById(t.id):u;r({el:o,name:s,data:n,app:e},Object.assign({},e.directives))}))}c.children.length>0&&v(c,i,n)}}};class f{constructor(t={},e){this.state=t,this.directives={},this.components={},this.mountHook=e}mount(t,e=!1){const s="string"==typeof t?document.querySelector(t):t;return this.vdom=this.compile(s),e||(this.state=h(this.state,this.patch.bind(this)),this.directives=Object.assign(Object.assign({},this.directives),i)),this.patch(["%LUCIA_FIRST_RENDER%"]),this.mountHook&&this.mountHook(this.state),this.state}component(t,e){this.components[t.toUpperCase()]=e}directive(t,e){this.directives[t.toUpperCase()]=e}patch(t){const e={state:this.state,directives:this.directives,components:this.components};v(this.vdom,e,t)}compile(t){return p(t,this.state,this.components,!0)}}const b=(t,e)=>new f(t,e),y=(t=document)=>{[...t.querySelectorAll("[l-state]")].filter((t=>void 0===t.__l)).map((t=>{const e=t.getAttribute("l-state");try{const s=new Function(`return ${e}`)(),n=b(s);n.mount(t),t.__l=n}catch(s){console.warn(`Lucia Error: "${s}"\n\nExpression: "${e}"\nElement:`,t)}}))},g=(t,e=document,s)=>{const n=new MutationObserver((o=>{o.map((e=>{e.addedNodes.length>0&&e.addedNodes.forEach((e=>{1===e.nodeType&&(e.parentElement&&e.parentElement.closest("[l-state]")||t(e.parentElement))}))})),n.observe(e,s||{childList:!0,attributes:!0,subtree:!0})}))};export{p as compile,b as createApp,i as directives,c as h,y as init,g as listen,v as patch,h as reactive,r as renderDirective}; |
@@ -8,18 +8,10 @@ (function (global, factory) { | ||
const DIRECTIVE_PREFIX = 'l-'; | ||
const LUCIA_COMPILE_REQUEST = '%LUCIA_COMPILE_REQUEST%'; | ||
const LUCIA_FIRST_RENDER = '%LUCIA_FIRST_RENDER%'; | ||
var DIRECTIVE_SHORTHANDS; | ||
(function (DIRECTIVE_SHORTHANDS) { | ||
DIRECTIVE_SHORTHANDS["@"] = "ON"; | ||
DIRECTIVE_SHORTHANDS[":"] = "BIND"; | ||
DIRECTIVE_SHORTHANDS["@"] = "on"; | ||
DIRECTIVE_SHORTHANDS[":"] = "bind"; | ||
})(DIRECTIVE_SHORTHANDS || (DIRECTIVE_SHORTHANDS = {})); | ||
var VNodeTypes; | ||
(function (VNodeTypes) { | ||
VNodeTypes[VNodeTypes["STATIC"] = 0] = "STATIC"; | ||
VNodeTypes[VNodeTypes["NEEDS_PATCH"] = 1] = "NEEDS_PATCH"; | ||
VNodeTypes[VNodeTypes["DYNAMIC"] = 2] = "DYNAMIC"; | ||
})(VNodeTypes || (VNodeTypes = {})); | ||
const rawDirectiveSplitPattern = /:|\./; | ||
const selectorSplitPattern = /(?=\.)|(?=#)|(?=\[)/; | ||
const keyPattern = (key, hasThis = true) => { | ||
@@ -29,31 +21,182 @@ return new RegExp(`${hasThis ? 'this\\.' : ''}${key}\\b`); | ||
const h = (selector, children, props) => { | ||
const tokens = selector.split(selectorSplitPattern); | ||
const tag = tokens[0]; | ||
const attributes = Object.assign({}, props === null || props === void 0 ? void 0 : props.attributes); | ||
const directives = Object.assign({}, props === null || props === void 0 ? void 0 : props.directives); | ||
if (tokens.length > 1) { | ||
tokens.shift(); | ||
for (const token of tokens) { | ||
switch (token[0]) { | ||
case '#': | ||
attributes.id = token.slice(1); | ||
break; | ||
case '.': | ||
if (!attributes.className) | ||
attributes.className = ''; | ||
attributes.className += `${token.slice(1)} `; | ||
break; | ||
case '[': | ||
const [key, value] = token.slice(1, -1).split('='); | ||
if (key.startsWith(DIRECTIVE_PREFIX)) { | ||
directives[key.slice(DIRECTIVE_PREFIX.length)] = value; | ||
const bindDirective = ({ el, name, data, app }) => { | ||
switch (name.split(':')[1]) { | ||
case 'class': | ||
const hydratedClasses = data.compute(app.state); | ||
if (typeof hydratedClasses === 'string') { | ||
return el.setAttribute('class', `${el.className} ${hydratedClasses}`.trim()); | ||
} | ||
else if (hydratedClasses instanceof Array) { | ||
return el.setAttribute('class', `${el.className} ${hydratedClasses.join(' ')}`.trim()); | ||
} | ||
else { | ||
const classes = []; | ||
for (const key in hydratedClasses) { | ||
if (hydratedClasses[key]) | ||
classes.push(key); | ||
} | ||
if (classes.length > 0) { | ||
return el.setAttribute('class', `${el.className} ${classes.join(' ').trim()}`.trim()); | ||
} | ||
else if (el.className.trim().length > 0) { | ||
return el.setAttribute('class', el.className); | ||
} | ||
else { | ||
return el.removeAttribute('class'); | ||
} | ||
} | ||
case 'style': | ||
const hydratedStyles = data.compute(app.state); | ||
el.removeAttribute('style'); | ||
for (const key in hydratedStyles) { | ||
el.style[key] = hydratedStyles[key]; | ||
} | ||
break; | ||
default: | ||
const hydratedAttributes = data.compute(app.state); | ||
if (typeof hydratedAttributes === 'object' && hydratedAttributes !== null) { | ||
for (const key in hydratedAttributes) { | ||
if (hydratedAttributes[key]) { | ||
el.setAttribute(key, hydratedAttributes[key]); | ||
} | ||
else { | ||
attributes[key] = value; | ||
el.removeAttribute(key); | ||
} | ||
break; | ||
} | ||
} | ||
else if (hydratedAttributes) { | ||
el.setAttribute(name.split(':')[1], hydratedAttributes); | ||
} | ||
else { | ||
el.removeAttribute(name.split(':')[1]); | ||
} | ||
break; | ||
} | ||
}; | ||
const htmlDirective = ({ el, data, app }) => { | ||
var _a; | ||
el.innerHTML = (_a = data.compute(app.state)) !== null && _a !== void 0 ? _a : data.value; | ||
const scope = createApp(Object.assign({}, app.state)); | ||
Object.entries(app.directives || {}).map(([name, evaluationCallback]) => { | ||
scope.directive(name, evaluationCallback); | ||
}); | ||
Object.entries(app.components || {}).map(([name, templateCallback]) => { | ||
scope.component(name, templateCallback); | ||
}); | ||
scope.mount(el); | ||
}; | ||
const ifDirective = ({ el, data, app }) => { | ||
const hydratedConditional = data.compute(app.state); | ||
if (hydratedConditional) { | ||
el.style.removeProperty('display'); | ||
} | ||
else { | ||
el.style.display = 'none'; | ||
} | ||
}; | ||
function createComputeFunction(state) { | ||
try { | ||
const expression = this.returnable ? `return ${this.expression}` : this.expression; | ||
return new Function(...Object.keys(this.argsKV), expression).bind(state)(...Object.values(this.argsKV)); | ||
} | ||
catch (err) { | ||
console.warn(`Lucia Error: "${err}"\n\nExpression: "${this.expression}"\nElement:`, this.argsKV.$el); | ||
} | ||
} | ||
const compute = (expression, data, returnable = true) => { | ||
return createComputeFunction.bind({ expression, argsKV: { $el: data.$el }, returnable }); | ||
}; | ||
const joinDirective = ({ el, data, app }) => { | ||
const [array, contentType, delimiter] = data.value.split(/ as | by /); | ||
const hydratedArray = compute(array, { $el: el })(app.state); | ||
const accessProp = contentType === 'text' ? 'innerText' : 'innerHTML'; | ||
el[accessProp] = hydratedArray.join(delimiter || ''); | ||
const scope = createApp(Object.assign({}, app.state)); | ||
Object.entries(app.directives || {}).map(([name, evaluationCallback]) => { | ||
scope.directive(name, evaluationCallback); | ||
}); | ||
Object.entries(app.components || {}).map(([name, templateCallback]) => { | ||
scope.component(name, templateCallback); | ||
}); | ||
scope.mount(el); | ||
}; | ||
const modelDirective = ({ el: awaitingTypecastEl, data, app }) => { | ||
const el = awaitingTypecastEl; | ||
const hydratedValue = compute(data.compute(), { $el: el })(app.state); | ||
if (el.value !== hydratedValue) { | ||
el.value = hydratedValue; | ||
} | ||
el.oninput = () => { | ||
const isNumber = typeof hydratedValue === 'number' && !isNaN(el.value); | ||
const isBoolean = typeof hydratedValue === 'boolean' && (el.value === 'true' || el.value === 'false'); | ||
const isNullish = (hydratedValue === null || hydratedValue === undefined) && | ||
(el.value === 'null' || el.value === 'undefined'); | ||
let payload; | ||
if (isNumber) { | ||
payload = `Number('${el.value}').toPrecision()`; | ||
} | ||
} | ||
else if (isBoolean) { | ||
payload = `Boolean('${el.value}')`; | ||
} | ||
else if (isNullish) { | ||
if (el.value === 'null') | ||
payload = null; | ||
else | ||
payload = undefined; | ||
} | ||
else { | ||
payload = `'${el.value}'`; | ||
} | ||
compute(`${data.value} = ${payload}`, { $el: el }, false)(app.state); | ||
}; | ||
}; | ||
const onDirective = ({ el, name, data, app }) => { | ||
const [directiveAndEventName, prop] = name.split('.'); | ||
const eventName = directiveAndEventName.split(':')[1]; | ||
const eventProp = prop || null; | ||
el[`on${eventName}`] = ($event) => { | ||
if (eventProp === 'prevent') | ||
$event.preventDefault(); | ||
if (eventProp === 'stop') | ||
$event.stopPropagation(); | ||
data.compute(app.state); | ||
}; | ||
}; | ||
const textDirective = ({ el, data, app }) => { | ||
var _a; | ||
el.textContent = (_a = data.compute(app.state)) !== null && _a !== void 0 ? _a : data.value; | ||
}; | ||
const directives = { | ||
BIND: bindDirective, | ||
JOIN: joinDirective, | ||
HTML: htmlDirective, | ||
IF: ifDirective, | ||
MODEL: modelDirective, | ||
ON: onDirective, | ||
TEXT: textDirective, | ||
}; | ||
const renderDirective = (props, directives) => { | ||
const name = props.name.split(rawDirectiveSplitPattern)[0]; | ||
directives[name.toUpperCase()](props); | ||
}; | ||
var VNodeTypes; | ||
(function (VNodeTypes) { | ||
VNodeTypes[VNodeTypes["STATIC"] = 0] = "STATIC"; | ||
VNodeTypes[VNodeTypes["NEEDS_PATCH"] = 1] = "NEEDS_PATCH"; | ||
VNodeTypes[VNodeTypes["DYNAMIC"] = 2] = "DYNAMIC"; | ||
})(VNodeTypes || (VNodeTypes = {})); | ||
const h = (tag, children = [], props) => { | ||
const attributes = Object.assign({}, props === null || props === void 0 ? void 0 : props.attributes); | ||
const directives = Object.assign({}, props === null || props === void 0 ? void 0 : props.directives); | ||
children = children instanceof Array ? children : [children]; | ||
if (attributes.className) | ||
@@ -63,3 +206,3 @@ attributes.className = attributes.className.trim(); | ||
tag, | ||
children: typeof children === 'string' ? [children] : children ? children : [], | ||
children, | ||
props: { | ||
@@ -79,7 +222,8 @@ attributes, | ||
for (const { name, value } of [...el.attributes]) { | ||
const directiveData = { compute: compute(value, { $el: el }), value }; | ||
if (name.startsWith(DIRECTIVE_PREFIX)) { | ||
directives[name.slice(DIRECTIVE_PREFIX.length)] = value; | ||
directives[name.slice(DIRECTIVE_PREFIX.length)] = directiveData; | ||
} | ||
else if (Object.keys(DIRECTIVE_SHORTHANDS).includes(name[0])) { | ||
directives[`${DIRECTIVE_SHORTHANDS[name[0]]}:${name.slice(1)}`] = value; | ||
directives[`${DIRECTIVE_SHORTHANDS[name[0]]}:${name.slice(1)}`] = directiveData; | ||
} | ||
@@ -98,3 +242,3 @@ else { | ||
const hasDirectives = Object.keys(directives).length > 0; | ||
const hasKeyInDirectives = Object.values(directives).some((value) => Object.keys(state).some((key) => keyPattern(key, false).test(value))); | ||
const hasKeyInDirectives = Object.values(directives).some(({ value }) => Object.keys(state).some((key) => keyPattern(key, false).test(value))); | ||
if (hasDirectives) | ||
@@ -105,4 +249,4 @@ type = VNodeTypes.NEEDS_PATCH; | ||
return h(el.tagName.toLowerCase(), children, { | ||
attributes, | ||
directives, | ||
attributes: attributes, | ||
directives: directives, | ||
ref: type === VNodeTypes.STATIC || attributes.id ? undefined : el, | ||
@@ -133,4 +277,4 @@ type, | ||
container.innerHTML = template; | ||
for (const [key, value] of Object.entries(props(child).directives)) { | ||
(_a = container.firstElementChild) === null || _a === void 0 ? void 0 : _a.setAttribute(`${DIRECTIVE_PREFIX}${key}`, value); | ||
for (const [key, data] of Object.entries(props(child).directives)) { | ||
(_a = container.firstElementChild) === null || _a === void 0 ? void 0 : _a.setAttribute(`${DIRECTIVE_PREFIX}${key}`, data.value); | ||
} | ||
@@ -182,150 +326,2 @@ if (!strip || container.outerHTML.includes(` ${DIRECTIVE_PREFIX}`)) { | ||
const safeEval = (expression, argsKV = {}, bindKV = {}, returnable = true) => { | ||
return new Function(...Object.keys(argsKV), returnable ? `return ${expression}` : expression).bind(bindKV)(...Object.values(argsKV)); | ||
}; | ||
const computeProperties = (expression, data, returnable = true) => { | ||
return safeEval(expression, { $el: data.$el }, data.$state, returnable); | ||
}; | ||
const bindDirective = ({ el, name, value, state }) => { | ||
switch (name.split(':')[1]) { | ||
case 'class': | ||
const classState = computeProperties(value, { $state: state, $el: el }); | ||
if (typeof classState === 'string') { | ||
return el.setAttribute('class', `${el.className} ${classState}`.trim()); | ||
} | ||
if (classState instanceof Array) { | ||
return el.setAttribute('class', `${el.className} ${classState.join(' ')}`.trim()); | ||
} | ||
else { | ||
const classes = []; | ||
for (const key in classState) { | ||
if (classState[key]) | ||
classes.push(key); | ||
} | ||
if (classes.length > 0) { | ||
return el.setAttribute('class', `${el.className} ${classes.join(' ').trim()}`.trim()); | ||
} | ||
else if (el.className.trim().length > 0) { | ||
return el.setAttribute('class', el.className); | ||
} | ||
else { | ||
return el.removeAttribute('class'); | ||
} | ||
} | ||
case 'style': | ||
const styleState = computeProperties(value, { $state: state, $el: el }); | ||
el.removeAttribute('style'); | ||
for (const key in styleState) { | ||
el.style[key] = styleState[key]; | ||
} | ||
break; | ||
default: | ||
const out = computeProperties(value, { $state: state, $el: el }); | ||
if (out) { | ||
el.setAttribute(name.split(':')[1], out); | ||
} | ||
else { | ||
el.removeAttribute(name.split(':')[1]); | ||
} | ||
break; | ||
} | ||
}; | ||
const htmlDirective = ({ el, value, state }) => { | ||
const app = createApp(Object.assign({}, state)); | ||
app.mount(el, true); | ||
try { | ||
el.innerHTML = computeProperties(value, { $state: state, $el: el }); | ||
} | ||
catch (_a) { | ||
el.innerHTML = value; | ||
} | ||
}; | ||
const ifDirective = ({ el, value, state }) => { | ||
const out = computeProperties(value, { $state: state, $el: el }); | ||
if (out) { | ||
el.style.removeProperty('display'); | ||
} | ||
else { | ||
el.style.display = 'none'; | ||
} | ||
}; | ||
const joinDirective = ({ el, value, state }) => { | ||
const [array, contentType, delimiter] = value.split(/ as | by /); | ||
const out = computeProperties(array, { $state: state, $el: el }); | ||
const accessProp = contentType === 'text' ? 'innerText' : 'innerHTML'; | ||
el[accessProp] = out.join(delimiter || ''); | ||
const app = createApp(Object.assign({}, state)); | ||
app.mount(el, true); | ||
}; | ||
const modelDirective = ({ el: awaitingTypecastEl, value, state }) => { | ||
const el = awaitingTypecastEl; | ||
const out = computeProperties(value, { $state: state, $el: el }); | ||
if (el.value !== out) { | ||
el.value = out; | ||
} | ||
el.oninput = () => { | ||
const isNumber = typeof out === 'number' && !isNaN(el.value); | ||
const isBoolean = typeof out === 'boolean' && (el.value === 'true' || el.value === 'false'); | ||
const isNullish = (out === null || out === undefined) && (el.value === 'null' || el.value === 'undefined'); | ||
let payload; | ||
if (isNumber) { | ||
payload = `Number('${el.value}').toPrecision()`; | ||
} | ||
else if (isBoolean) { | ||
payload = `Boolean('${el.value}')`; | ||
} | ||
else if (isNullish) { | ||
if (el.value === 'null') | ||
payload = null; | ||
else | ||
payload = undefined; | ||
} | ||
else { | ||
payload = `'${el.value}'`; | ||
} | ||
computeProperties(`${value} = ${payload}`, { $state: state, $el: el }, false); | ||
}; | ||
}; | ||
const onDirective = ({ el, name, value, state }) => { | ||
const [directiveAndEventName, prop] = name.split('.'); | ||
const eventName = directiveAndEventName.split(':')[1]; | ||
const eventProp = prop || null; | ||
el[`on${eventName}`] = ($event) => { | ||
if (eventProp === 'prevent') | ||
$event.preventDefault(); | ||
if (eventProp === 'stop') | ||
$event.stopPropagation(); | ||
computeProperties(value, { $state: state, $el: el }, false); | ||
}; | ||
}; | ||
const textDirective = ({ el, value, state }) => { | ||
try { | ||
el.innerHTML = computeProperties(value, { $state: state, $el: el }); | ||
} | ||
catch (_a) { | ||
el.innerHTML = value; | ||
} | ||
}; | ||
const directives = { | ||
BIND: bindDirective, | ||
JOIN: joinDirective, | ||
HTML: htmlDirective, | ||
IF: ifDirective, | ||
MODEL: modelDirective, | ||
ON: onDirective, | ||
TEXT: textDirective, | ||
}; | ||
const renderDirective = ({ el, name, value, state }, directives) => { | ||
const rootName = name.split(rawDirectiveSplitPattern)[0]; | ||
directives[rootName.toUpperCase()]({ el, name, value, state }); | ||
}; | ||
const arrayEquals = (firstArray, secondArray) => { | ||
@@ -338,3 +334,3 @@ return (firstArray instanceof Array && | ||
const handleArray = (target, key, state, patch) => { | ||
const handlePatch = (target, key, state, patch, needsUpdate = false) => { | ||
if (key === 'length') { | ||
@@ -349,3 +345,4 @@ const affectedKeys = Object.keys(state).filter((k) => { | ||
else { | ||
patch([key]); | ||
if (needsUpdate) | ||
patch([key]); | ||
return false; | ||
@@ -365,4 +362,7 @@ } | ||
set(target, key, value) { | ||
target[key] = value; | ||
handleArray(target, key, state, patch); | ||
const needsUpdate = target[key] !== value; | ||
if (needsUpdate) { | ||
target[key] = value; | ||
} | ||
handlePatch(target, key, state, patch, needsUpdate); | ||
return true; | ||
@@ -372,3 +372,3 @@ }, | ||
delete target[key]; | ||
handleArray(target, key, state, patch); | ||
handlePatch(target, key, state, patch); | ||
return true; | ||
@@ -380,4 +380,5 @@ }, | ||
const patch = (rootVNode, state = {}, directiveKV = {}, keys) => { | ||
let compileRequest = false; | ||
const patch = (rootVNode, app = {}, keys) => { | ||
let firstRender = false; | ||
const state = app.state || {}; | ||
if (!rootVNode) | ||
@@ -387,4 +388,4 @@ return; | ||
keys = Object.keys(state); | ||
if (keys[0] === LUCIA_COMPILE_REQUEST) | ||
compileRequest = true; | ||
if (keys[0] === LUCIA_FIRST_RENDER) | ||
firstRender = true; | ||
for (let node of rootVNode.children) { | ||
@@ -396,9 +397,8 @@ if (typeof node === 'string') | ||
let affectedDirectives = []; | ||
if (!compileRequest) { | ||
if (!firstRender) { | ||
for (const name in directives) { | ||
const value = directives[name]; | ||
const needsInit = type === 1; | ||
const hasKey = keys.some((key) => keyPattern(key).test(value.toString())); | ||
const hasKey = keys.some((key) => keyPattern(key).test(String(directives[name].value))); | ||
const hasKeyInFunction = Object.keys(state).some((key) => { | ||
const iterKeysInFunction = keys.some((k) => keyPattern(k).test(state[key].toString())); | ||
const iterKeysInFunction = keys.some((k) => keyPattern(k).test(String(state[key]))); | ||
return typeof state[key] === 'function' && iterKeysInFunction; | ||
@@ -412,13 +412,13 @@ }); | ||
node.props.type = type === VNodeTypes.NEEDS_PATCH ? VNodeTypes.STATIC : type; | ||
const directivesToRender = compileRequest | ||
const directivesToRender = firstRender | ||
? Object.keys(directives) | ||
: affectedDirectives; | ||
directivesToRender.map((name) => { | ||
const value = directives[name]; | ||
const data = directives[name]; | ||
const el = (attributes.id ? document.getElementById(attributes.id) : ref); | ||
renderDirective({ el, name, value, state }, Object.assign({}, directiveKV)); | ||
renderDirective({ el, name, data, app }, Object.assign({}, app.directives)); | ||
}); | ||
} | ||
if (node.children.length > 0) | ||
patch(node, state, directiveKV, keys); | ||
patch(node, state, keys); | ||
} | ||
@@ -428,29 +428,33 @@ }; | ||
class App { | ||
constructor(state = {}) { | ||
this.vdom = null; | ||
constructor(state = {}, mountHook) { | ||
this.state = state; | ||
this.directives = {}; | ||
this.components = {}; | ||
this.mounted = false; | ||
this.mountHook = mountHook; | ||
} | ||
mount(el, shallow = false) { | ||
this.vdom = this.compile((typeof el === 'string' ? document.querySelector(el) : el)); | ||
const rootEl = typeof el === 'string' ? document.querySelector(el) : el; | ||
this.vdom = this.compile(rootEl); | ||
if (!shallow) { | ||
this.state = reactive(this.state, this.patch.bind(this)); | ||
this.directives = directives; | ||
this.directives = Object.assign(Object.assign({}, this.directives), directives); | ||
} | ||
this.mounted = true; | ||
this.patch([LUCIA_COMPILE_REQUEST]); | ||
this.patch([LUCIA_FIRST_RENDER]); | ||
if (this.mountHook) | ||
this.mountHook(this.state); | ||
return this.state; | ||
} | ||
component(name, fn) { | ||
this.components[name.toUpperCase()] = fn; | ||
component(name, templateCallback) { | ||
this.components[name.toUpperCase()] = templateCallback; | ||
} | ||
directive(name, fn) { | ||
this.directives[name.toUpperCase()] = fn; | ||
directive(name, evaluationCallback) { | ||
this.directives[name.toUpperCase()] = evaluationCallback; | ||
} | ||
patch(keys) { | ||
if (!this.mounted) | ||
throw new Error('App is not mounted.'); | ||
patch(this.vdom, this.state, this.directives, keys); | ||
const app = { | ||
state: this.state, | ||
directives: this.directives, | ||
components: this.components, | ||
}; | ||
patch(this.vdom, app, keys); | ||
} | ||
@@ -461,22 +465,44 @@ compile(el) { | ||
} | ||
const createApp = (state) => { | ||
return new App(state); | ||
const createApp = (state, mountHook) => { | ||
return new App(state, mountHook); | ||
}; | ||
const init = (element = document, directive = 'use') => { | ||
const elements = [...element.querySelectorAll(`[${DIRECTIVE_PREFIX + directive}]`)]; | ||
const apps = []; | ||
elements.map((el) => { | ||
const state = el.getAttribute(DIRECTIVE_PREFIX + directive); | ||
if (state === null) | ||
return; | ||
const stateDirective = `${DIRECTIVE_PREFIX}state`; | ||
const init = (element = document) => { | ||
const elements = [...element.querySelectorAll(`[${stateDirective}]`)]; | ||
elements | ||
.filter((el) => el.__l === undefined) | ||
.map((el) => { | ||
const expression = el.getAttribute(stateDirective); | ||
try { | ||
const app = createApp(safeEval(state)); | ||
const state = new Function(`return ${expression}`)(); | ||
const app = createApp(state); | ||
app.mount(el); | ||
apps.push(app); | ||
el.__l = app; | ||
} | ||
catch (err) { } | ||
catch (err) { | ||
console.warn(`Lucia Error: "${err}"\n\nExpression: "${expression}"\nElement:`, el); | ||
} | ||
}); | ||
return apps; | ||
}; | ||
const listen = (callback, element = document, config) => { | ||
const observer = new MutationObserver((mutations) => { | ||
mutations.map((mut) => { | ||
if (mut.addedNodes.length > 0) { | ||
mut.addedNodes.forEach((node) => { | ||
if (node.nodeType !== 1) | ||
return; | ||
if (node.parentElement && node.parentElement.closest(`[${stateDirective}]`)) | ||
return; | ||
callback(node.parentElement); | ||
}); | ||
} | ||
}); | ||
observer.observe(element, config || { | ||
childList: true, | ||
attributes: true, | ||
subtree: true, | ||
}); | ||
}); | ||
}; | ||
@@ -492,6 +518,9 @@ var Lucia = /*#__PURE__*/Object.freeze({ | ||
renderDirective: renderDirective, | ||
init: init | ||
init: init, | ||
listen: listen | ||
}); | ||
document.addEventListener('DOMContentLoaded', () => init(document, 'init')); | ||
document.addEventListener('DOMContentLoaded', () => init()); | ||
document.addEventListener('turbolinks:load', () => init()); | ||
listen((el) => init(el)); | ||
@@ -498,0 +527,0 @@ return Lucia; |
@@ -1,1 +0,1 @@ | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).Lucia=t()}(this,(function(){"use strict";const e="l-",t="%LUCIA_COMPILE_REQUEST%";var s,n;!function(e){e["@"]="ON",e[":"]="BIND"}(s||(s={})),function(e){e[e.STATIC=0]="STATIC",e[e.NEEDS_PATCH=1]="NEEDS_PATCH",e[e.DYNAMIC=2]="DYNAMIC"}(n||(n={}));const i=/:|\./,r=/(?=\.)|(?=#)|(?=\[)/,o=(e,t=!0)=>new RegExp(`${t?"this\\.":""}${e}\\b`),l=(t,s,n)=>{const i=t.split(r),o=i[0],l=Object.assign({},null==n?void 0:n.attributes),a=Object.assign({},null==n?void 0:n.directives);if(i.length>1){i.shift();for(const t of i)switch(t[0]){case"#":l.id=t.slice(1);break;case".":l.className||(l.className=""),l.className+=`${t.slice(1)} `;break;case"[":const[s,n]=t.slice(1,-1).split("=");s.startsWith(e)?a[s.slice(e.length)]=n:l[s]=n}}return l.className&&(l.className=l.className.trim()),{tag:o,children:"string"==typeof s?[s]:s||[],props:{attributes:l,directives:a,ref:(null==n?void 0:n.ref)||void 0,type:(null==n?void 0:n.type)||0}}},a=t=>{const n={},i={};if(t.attributes)for(const{name:r,value:o}of[...t.attributes])r.startsWith(e)?i[r.slice(e.length)]=o:Object.keys(s).includes(r[0])?i[`${s[r[0]]}:${r.slice(1)}`]=o:n[r]=o;return{attributes:n,directives:i}},c=(e,t,s)=>{const{attributes:i,directives:r}=a(e);let c=n.STATIC;const u=Object.keys(r).length>0,p=Object.values(r).some((e=>Object.keys(t).some((t=>o(t,!1).test(e)))));return u&&(c=n.NEEDS_PATCH),p&&(c=n.DYNAMIC),l(e.tagName.toLowerCase(),s,{attributes:i,directives:r,ref:c===n.STATIC||i.id?void 0:e,type:c})},u=(e,t={},s={},n=!1,i=!1)=>{var r;if(!e)throw new Error("Please provide a Element");const o=[],l=Array.prototype.slice.call(e.childNodes);for(const i of l)switch(i.nodeType){case Node.TEXT_NODE:!n&&i.nodeValue&&o.push(i.nodeValue);break;case Node.ELEMENT_NODE:if(Object.keys(s).includes(i.tagName)){const l=document.createElement("div"),c=s[i.tagName]({children:i.innerHTML,state:t});l.innerHTML=c;for(const[e,t]of Object.entries(a(i).directives))null===(r=l.firstElementChild)||void 0===r||r.setAttribute(`l-${e}`,t);if(!n||l.outerHTML.includes(" l-")){const e=u(l,t,s,n,!0);for(const t of e)o.push(t)}e.replaceChild(l.firstElementChild,i)}else if(!n||i.outerHTML.includes(" l-")){const e=u(i,t,s,n,!0),r=c(i,t,e);o.push(r)}}if(i)return o;{let s=c(e,t,o);return n?p(s):s}},p=e=>{const t=Object.assign({},e);t.children.filter((e=>"object"==typeof e&&e.props.type>0));for(const s of e.children)if("string"!=typeof s&&s.children.length>0)for(const e of p(s).children)"string"!=typeof e&&0!==e.props.type&&t.children.push(e);return t},d=(e,t={},s={},n=!0)=>new Function(...Object.keys(t),n?`return ${e}`:e).bind(s)(...Object.values(t)),f=(e,t,s=!0)=>d(e,{$el:t.$el},t.$state,s),h={BIND:({el:e,name:t,value:s,state:n})=>{switch(t.split(":")[1]){case"class":const i=f(s,{$state:n,$el:e});if("string"==typeof i)return e.setAttribute("class",`${e.className} ${i}`.trim());if(i instanceof Array)return e.setAttribute("class",`${e.className} ${i.join(" ")}`.trim());{const t=[];for(const e in i)i[e]&&t.push(e);return t.length>0?e.setAttribute("class",`${e.className} ${t.join(" ").trim()}`.trim()):e.className.trim().length>0?e.setAttribute("class",e.className):e.removeAttribute("class")}case"style":const r=f(s,{$state:n,$el:e});e.removeAttribute("style");for(const t in r)e.style[t]=r[t];break;default:const o=f(s,{$state:n,$el:e});o?e.setAttribute(t.split(":")[1],o):e.removeAttribute(t.split(":")[1])}},JOIN:({el:e,value:t,state:s})=>{const[n,i,r]=t.split(/ as | by /),o=f(n,{$state:s,$el:e});e["text"===i?"innerText":"innerHTML"]=o.join(r||"");g(Object.assign({},s)).mount(e,!0)},HTML:({el:e,value:t,state:s})=>{g(Object.assign({},s)).mount(e,!0);try{e.innerHTML=f(t,{$state:s,$el:e})}catch(s){e.innerHTML=t}},IF:({el:e,value:t,state:s})=>{f(t,{$state:s,$el:e})?e.style.removeProperty("display"):e.style.display="none"},MODEL:({el:e,value:t,state:s})=>{const n=e,i=f(t,{$state:s,$el:n});n.value!==i&&(n.value=i),n.oninput=()=>{const e="number"==typeof i&&!isNaN(n.value),r="boolean"==typeof i&&("true"===n.value||"false"===n.value),o=null==i&&("null"===n.value||"undefined"===n.value);let l;l=e?`Number('${n.value}').toPrecision()`:r?`Boolean('${n.value}')`:o?"null"===n.value?null:void 0:`'${n.value}'`,f(`${t} = ${l}`,{$state:s,$el:n},!1)}},ON:({el:e,name:t,value:s,state:n})=>{const[i,r]=t.split("."),o=i.split(":")[1],l=r||null;e[`on${o}`]=t=>{"prevent"===l&&t.preventDefault(),"stop"===l&&t.stopPropagation(),f(s,{$state:n,$el:e},!1)}},TEXT:({el:e,value:t,state:s})=>{try{e.innerHTML=f(t,{$state:s,$el:e})}catch(s){e.innerHTML=t}}},m=({el:e,name:t,value:s,state:n},r)=>{r[t.split(i)[0].toUpperCase()]({el:e,name:t,value:s,state:n})},v=(e,t,s,n)=>{if("length"===t){const t=Object.keys(s).filter((t=>{return s[t]instanceof Array&&(n=e,i=s[t],n instanceof Array&&i instanceof Array&&n.length===i.length&&n.every(((e,t)=>e===i[t])));var n,i}));return 0!==t.length&&n(t),!0}return n([t]),!1},y=(e,t)=>{const s={get:(e,t)=>"object"==typeof e[t]&&null!==e[t]?new Proxy(e[t],s):e[t],set:(s,n,i)=>(s[n]=i,v(s,n,e,t),!0),deleteProperty:(s,n)=>(delete s[n],v(s,n,e,t),!0)};return new Proxy(e,s)},b=(e,s={},i={},r)=>{let l=!1;if(e){r||(r=Object.keys(s)),r[0]===t&&(l=!0);for(let t of e.children)if("string"!=typeof t){if(t.props.type>n.STATIC){const{attributes:e,directives:a,ref:c,type:u}=t.props;let p=[];if(!l)for(const e in a){const t=a[e],n=1===u,i=r.some((e=>o(e).test(t.toString()))),l=Object.keys(s).some((e=>{const t=r.some((t=>o(t).test(s[e].toString())));return"function"==typeof s[e]&&t}));(n||i||l)&&p.push(e)}t.props.type=u===n.NEEDS_PATCH?n.STATIC:u;(l?Object.keys(a):p).map((t=>{const n=a[t],r=e.id?document.getElementById(e.id):c;m({el:r,name:t,value:n,state:s},Object.assign({},i))}))}t.children.length>0&&b(t,s,i,r)}}};class ${constructor(e={}){this.vdom=null,this.state=e,this.directives={},this.components={},this.mounted=!1}mount(e,s=!1){return this.vdom=this.compile("string"==typeof e?document.querySelector(e):e),s||(this.state=y(this.state,this.patch.bind(this)),this.directives=h),this.mounted=!0,this.patch([t]),this.state}component(e,t){this.components[e.toUpperCase()]=t}directive(e,t){this.directives[e.toUpperCase()]=t}patch(e){if(!this.mounted)throw new Error("App is not mounted.");b(this.vdom,this.state,this.directives,e)}compile(e){return u(e,this.state,this.components,!0)}}const g=e=>new $(e),T=(t=document,s="use")=>{const n=[...t.querySelectorAll(`[${e+s}]`)],i=[];return n.map((t=>{const n=t.getAttribute(e+s);if(null!==n)try{const e=g(d(n));e.mount(t),i.push(e)}catch(e){}})),i};var N=Object.freeze({__proto__:null,createApp:g,h:l,compile:u,patch:b,reactive:y,directives:h,renderDirective:m,init:T});return document.addEventListener("DOMContentLoaded",(()=>T(document,"init"))),N})); | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).Lucia=t()}(this,(function(){"use strict";const e="l-",t="%LUCIA_FIRST_RENDER%";var s;!function(e){e["@"]="on",e[":"]="bind"}(s||(s={}));const n=/:|\./,i=(e,t=!0)=>new RegExp(`${t?"this\\.":""}${e}\\b`);function o(e){try{const t=this.returnable?`return ${this.expression}`:this.expression;return new Function(...Object.keys(this.argsKV),t).bind(e)(...Object.values(this.argsKV))}catch(e){console.warn(`Lucia Error: "${e}"\n\nExpression: "${this.expression}"\nElement:`,this.argsKV.$el)}}const r=(e,t,s=!0)=>o.bind({expression:e,argsKV:{$el:t.$el},returnable:s}),a={BIND:({el:e,name:t,data:s,app:n})=>{switch(t.split(":")[1]){case"class":const i=s.compute(n.state);if("string"==typeof i)return e.setAttribute("class",`${e.className} ${i}`.trim());if(i instanceof Array)return e.setAttribute("class",`${e.className} ${i.join(" ")}`.trim());{const t=[];for(const e in i)i[e]&&t.push(e);return t.length>0?e.setAttribute("class",`${e.className} ${t.join(" ").trim()}`.trim()):e.className.trim().length>0?e.setAttribute("class",e.className):e.removeAttribute("class")}case"style":const o=s.compute(n.state);e.removeAttribute("style");for(const t in o)e.style[t]=o[t];break;default:const r=s.compute(n.state);if("object"==typeof r&&null!==r)for(const t in r)r[t]?e.setAttribute(t,r[t]):e.removeAttribute(t);else r?e.setAttribute(t.split(":")[1],r):e.removeAttribute(t.split(":")[1])}},JOIN:({el:e,data:t,app:s})=>{const[n,i,o]=t.value.split(/ as | by /),a=r(n,{$el:e})(s.state);e["text"===i?"innerText":"innerHTML"]=a.join(o||"");const c=g(Object.assign({},s.state));Object.entries(s.directives||{}).map((([e,t])=>{c.directive(e,t)})),Object.entries(s.components||{}).map((([e,t])=>{c.component(e,t)})),c.mount(e)},HTML:({el:e,data:t,app:s})=>{var n;e.innerHTML=null!==(n=t.compute(s.state))&&void 0!==n?n:t.value;const i=g(Object.assign({},s.state));Object.entries(s.directives||{}).map((([e,t])=>{i.directive(e,t)})),Object.entries(s.components||{}).map((([e,t])=>{i.component(e,t)})),i.mount(e)},IF:({el:e,data:t,app:s})=>{t.compute(s.state)?e.style.removeProperty("display"):e.style.display="none"},MODEL:({el:e,data:t,app:s})=>{const n=e,i=r(t.compute(),{$el:n})(s.state);n.value!==i&&(n.value=i),n.oninput=()=>{const e="number"==typeof i&&!isNaN(n.value),o="boolean"==typeof i&&("true"===n.value||"false"===n.value),a=null==i&&("null"===n.value||"undefined"===n.value);let c;c=e?`Number('${n.value}').toPrecision()`:o?`Boolean('${n.value}')`:a?"null"===n.value?null:void 0:`'${n.value}'`,r(`${t.value} = ${c}`,{$el:n},!1)(s.state)}},ON:({el:e,name:t,data:s,app:n})=>{const[i,o]=t.split("."),r=i.split(":")[1],a=o||null;e[`on${r}`]=e=>{"prevent"===a&&e.preventDefault(),"stop"===a&&e.stopPropagation(),s.compute(n.state)}},TEXT:({el:e,data:t,app:s})=>{var n;e.textContent=null!==(n=t.compute(s.state))&&void 0!==n?n:t.value}},c=(e,t)=>{t[e.name.split(n)[0].toUpperCase()](e)};var l;!function(e){e[e.STATIC=0]="STATIC",e[e.NEEDS_PATCH=1]="NEEDS_PATCH",e[e.DYNAMIC=2]="DYNAMIC"}(l||(l={}));const u=(e,t=[],s)=>{const n=Object.assign({},null==s?void 0:s.attributes),i=Object.assign({},null==s?void 0:s.directives);return t=t instanceof Array?t:[t],n.className&&(n.className=n.className.trim()),{tag:e,children:t,props:{attributes:n,directives:i,ref:(null==s?void 0:s.ref)||void 0,type:(null==s?void 0:s.type)||0}}},p=t=>{const n={},i={};if(t.attributes)for(const{name:o,value:a}of[...t.attributes]){const c={compute:r(a,{$el:t}),value:a};o.startsWith(e)?i[o.slice(e.length)]=c:Object.keys(s).includes(o[0])?i[`${s[o[0]]}:${o.slice(1)}`]=c:n[o]=a}return{attributes:n,directives:i}},d=(e,t,s)=>{const{attributes:n,directives:o}=p(e);let r=l.STATIC;const a=Object.keys(o).length>0,c=Object.values(o).some((({value:e})=>Object.keys(t).some((t=>i(t,!1).test(e)))));return a&&(r=l.NEEDS_PATCH),c&&(r=l.DYNAMIC),u(e.tagName.toLowerCase(),s,{attributes:n,directives:o,ref:r===l.STATIC||n.id?void 0:e,type:r})},m=(e,t={},s={},n=!1,i=!1)=>{var o;if(!e)throw new Error("Please provide a Element");const r=[],a=Array.prototype.slice.call(e.childNodes);for(const i of a)switch(i.nodeType){case Node.TEXT_NODE:!n&&i.nodeValue&&r.push(i.nodeValue);break;case Node.ELEMENT_NODE:if(Object.keys(s).includes(i.tagName)){const a=document.createElement("div"),c=s[i.tagName]({children:i.innerHTML,state:t});a.innerHTML=c;for(const[e,t]of Object.entries(p(i).directives))null===(o=a.firstElementChild)||void 0===o||o.setAttribute(`l-${e}`,t.value);if(!n||a.outerHTML.includes(" l-")){const e=m(a,t,s,n,!0);for(const t of e)r.push(t)}e.replaceChild(a.firstElementChild,i)}else if(!n||i.outerHTML.includes(" l-")){const e=m(i,t,s,n,!0),o=d(i,t,e);r.push(o)}}if(i)return r;{let s=d(e,t,r);return n?f(s):s}},f=e=>{const t=Object.assign({},e);t.children.filter((e=>"object"==typeof e&&e.props.type>0));for(const s of e.children)if("string"!=typeof s&&s.children.length>0)for(const e of f(s).children)"string"!=typeof e&&0!==e.props.type&&t.children.push(e);return t},h=(e,t,s,n,i=!1)=>{if("length"===t){const t=Object.keys(s).filter((t=>{return s[t]instanceof Array&&(n=e,i=s[t],n instanceof Array&&i instanceof Array&&n.length===i.length&&n.every(((e,t)=>e===i[t])));var n,i}));return 0!==t.length&&n(t),!0}return i&&n([t]),!1},v=(e,t)=>{const s={get:(e,t)=>"object"==typeof e[t]&&null!==e[t]?new Proxy(e[t],s):e[t],set(s,n,i){const o=s[n]!==i;return o&&(s[n]=i),h(s,n,e,t,o),!0},deleteProperty:(s,n)=>(delete s[n],h(s,n,e,t),!0)};return new Proxy(e,s)},b=(e,s={},n)=>{let o=!1;const r=s.state||{};if(e){n||(n=Object.keys(r)),n[0]===t&&(o=!0);for(let t of e.children)if("string"!=typeof t){if(t.props.type>l.STATIC){const{attributes:e,directives:a,ref:u,type:p}=t.props;let d=[];if(!o)for(const e in a){const t=1===p,s=n.some((t=>i(t).test(String(a[e].value)))),o=Object.keys(r).some((e=>{const t=n.some((t=>i(t).test(String(r[e]))));return"function"==typeof r[e]&&t}));(t||s||o)&&d.push(e)}t.props.type=p===l.NEEDS_PATCH?l.STATIC:p;(o?Object.keys(a):d).map((t=>{const n=a[t],i=e.id?document.getElementById(e.id):u;c({el:i,name:t,data:n,app:s},Object.assign({},s.directives))}))}t.children.length>0&&b(t,r,n)}}};class y{constructor(e={},t){this.state=e,this.directives={},this.components={},this.mountHook=t}mount(e,s=!1){const n="string"==typeof e?document.querySelector(e):e;return this.vdom=this.compile(n),s||(this.state=v(this.state,this.patch.bind(this)),this.directives=Object.assign(Object.assign({},this.directives),a)),this.patch([t]),this.mountHook&&this.mountHook(this.state),this.state}component(e,t){this.components[e.toUpperCase()]=t}directive(e,t){this.directives[e.toUpperCase()]=t}patch(e){const t={state:this.state,directives:this.directives,components:this.components};b(this.vdom,t,e)}compile(e){return m(e,this.state,this.components,!0)}}const g=(e,t)=>new y(e,t),E="l-state",A=(e=document)=>{[...e.querySelectorAll("[l-state]")].filter((e=>void 0===e.__l)).map((e=>{const t=e.getAttribute(E);try{const s=new Function(`return ${t}`)(),n=g(s);n.mount(e),e.__l=n}catch(s){console.warn(`Lucia Error: "${s}"\n\nExpression: "${t}"\nElement:`,e)}}))},T=(e,t=document,s)=>{const n=new MutationObserver((i=>{i.map((t=>{t.addedNodes.length>0&&t.addedNodes.forEach((t=>{1===t.nodeType&&(t.parentElement&&t.parentElement.closest("[l-state]")||e(t.parentElement))}))})),n.observe(t,s||{childList:!0,attributes:!0,subtree:!0})}))};var N=Object.freeze({__proto__:null,createApp:g,h:u,compile:m,patch:b,reactive:v,directives:a,renderDirective:c,init:A,listen:T});return document.addEventListener("DOMContentLoaded",(()=>A())),document.addEventListener("turbolinks:load",(()=>A())),T((e=>A(e))),N})); |
import { Directives, Components, State } from './models/structs'; | ||
import { VNode } from './models/vnode'; | ||
export declare class App { | ||
vdom: VNode | null; | ||
state: State; | ||
directives: Directives; | ||
components: Components; | ||
mounted: boolean; | ||
constructor(state?: State); | ||
vdom?: VNode; | ||
mountHook?: Function; | ||
constructor(state?: State, mountHook?: Function); | ||
mount(el: HTMLElement | string, shallow?: boolean): State; | ||
component(name: string, fn: Function): void; | ||
directive(name: string, fn: Function): void; | ||
component(name: string, templateCallback: Function): void; | ||
directive(name: string, evaluationCallback: Function): void; | ||
private patch; | ||
private compile; | ||
} | ||
export declare const createApp: (state: State) => App; | ||
export declare const createApp: (state: State, mountHook?: Function | undefined) => App; | ||
export default createApp; |
@@ -1,2 +0,2 @@ | ||
import { App, createApp } from './App'; | ||
import { createApp } from './App'; | ||
import h from './vdom/h'; | ||
@@ -8,2 +8,3 @@ import patch from './vdom/patch'; | ||
export { createApp, h, compile, patch, reactive, directives, renderDirective }; | ||
export declare const init: (element?: HTMLElement | Document, directive?: string) => App[]; | ||
export declare const init: (element?: HTMLElement | Document) => void; | ||
export declare const listen: (callback: Function, element?: HTMLElement | Document, config?: Record<string, boolean> | undefined) => void; |
export declare const DIRECTIVE_PREFIX = "l-"; | ||
export declare const LUCIA_COMPILE_REQUEST = "%LUCIA_COMPILE_REQUEST%"; | ||
export declare const LUCIA_FIRST_RENDER = "%LUCIA_FIRST_RENDER%"; | ||
export declare enum DIRECTIVE_SHORTHANDS { | ||
'@' = "ON", | ||
':' = "BIND" | ||
'@' = "on", | ||
':' = "bind" | ||
} | ||
export declare type UnknownKV = Record<string, unknown>; | ||
export declare type StringKV = Record<string, string>; |
@@ -5,11 +5,20 @@ import { UnknownKV } from './generics'; | ||
export declare type State = UnknownKV; | ||
export declare type DirectiveKV = Record<string, DirectiveData>; | ||
export interface DirectiveData { | ||
compute: Function; | ||
value: string; | ||
} | ||
export interface DirectiveApp { | ||
state?: State; | ||
directives?: Directives; | ||
components?: Components; | ||
} | ||
export interface DirectiveProps { | ||
el: HTMLElement; | ||
name: string; | ||
value: string; | ||
state: State; | ||
data: DirectiveData; | ||
app: DirectiveApp; | ||
} | ||
export interface Data { | ||
$el?: HTMLElement; | ||
$state: UnknownKV; | ||
} |
import { StringKV } from './generics'; | ||
import { DirectiveKV } from './structs'; | ||
export interface VNode { | ||
@@ -11,3 +12,3 @@ tag: string; | ||
attributes: StringKV; | ||
directives: StringKV; | ||
directives: DirectiveKV; | ||
} | ||
@@ -14,0 +15,0 @@ export declare type VNodeChild = VNode | string; |
import { Directives, DirectiveProps } from '../models/structs'; | ||
export declare const directives: Directives; | ||
export declare const renderDirective: ({ el, name, value, state }: DirectiveProps, directives: Directives) => void; | ||
export declare const renderDirective: (props: DirectiveProps, directives: Directives) => void; | ||
export default renderDirective; |
import { DirectiveProps } from '../../models/structs'; | ||
export declare const bindDirective: ({ el, name, value, state }: DirectiveProps) => void; | ||
export declare const bindDirective: ({ el, name, data, app }: DirectiveProps) => void; |
import { DirectiveProps } from '../../models/structs'; | ||
export declare const htmlDirective: ({ el, value, state }: DirectiveProps) => void; | ||
export declare const htmlDirective: ({ el, data, app }: DirectiveProps) => void; |
import { DirectiveProps } from '../../models/structs'; | ||
export declare const ifDirective: ({ el, value, state }: DirectiveProps) => void; | ||
export declare const ifDirective: ({ el, data, app }: DirectiveProps) => void; |
import { DirectiveProps } from '../../models/structs'; | ||
export declare const joinDirective: ({ el, value, state }: DirectiveProps) => void; | ||
export declare const joinDirective: ({ el, data, app }: DirectiveProps) => void; |
import { DirectiveProps } from '../../models/structs'; | ||
export declare const modelDirective: ({ el: awaitingTypecastEl, value, state }: DirectiveProps) => void; | ||
export declare const modelDirective: ({ el: awaitingTypecastEl, data, app }: DirectiveProps) => void; |
import { DirectiveProps } from '../../models/structs'; | ||
export declare const onDirective: ({ el, name, value, state }: DirectiveProps) => void; | ||
export declare const onDirective: ({ el, name, data, app }: DirectiveProps) => void; |
import { DirectiveProps } from '../../models/structs'; | ||
export declare const textDirective: ({ el, value, state }: DirectiveProps) => void; | ||
export declare const textDirective: ({ el, data, app }: DirectiveProps) => void; |
import { VNode, VNodeProps, VNodeChildren } from '../models/vnode'; | ||
export declare const h: (selector: string, children?: string | VNodeChildren | undefined, props?: VNodeProps | undefined) => VNode; | ||
export declare const h: (tag: string, children?: VNodeChildren | string, props?: VNodeProps | undefined) => VNode; | ||
export default h; |
@@ -1,4 +0,4 @@ | ||
import { Directives, State } from '../models/structs'; | ||
import { DirectiveApp } from '../models/structs'; | ||
import { VNode } from '../models/vnode'; | ||
declare const patch: (rootVNode: VNode, state?: State, directiveKV?: Directives, keys?: string[] | undefined) => void; | ||
declare const patch: (rootVNode: VNode, app?: DirectiveApp, keys?: string[] | undefined) => void; | ||
export default patch; |
import { UnknownKV } from '../models/generics'; | ||
import { State } from '../models/structs'; | ||
export declare const handleArray: (target: UnknownKV | unknown[], key: string, state: State, patch: Function) => boolean; | ||
export declare const handlePatch: (target: UnknownKV | unknown[], key: string, state: State, patch: Function, needsUpdate?: boolean) => boolean; | ||
export declare const reactive: (state: State, patch: Function) => UnknownKV; | ||
export default reactive; |
@@ -1,5 +0,3 @@ | ||
import { UnknownKV } from '../../models/generics'; | ||
import { Data } from '../../models/structs'; | ||
export declare const safeEval: (expression: string, argsKV?: UnknownKV, bindKV?: UnknownKV, returnable?: boolean) => any; | ||
export declare const computeProperties: (expression: string, data: Data, returnable?: boolean) => any; | ||
export default computeProperties; | ||
export declare const compute: (expression: string, data: Data, returnable?: boolean) => any; | ||
export default compute; |
export declare const rawDirectiveSplitPattern: RegExp; | ||
export declare const selectorSplitPattern: RegExp; | ||
export declare const keyPattern: (key: string, hasThis?: boolean) => RegExp; |
import { StringKV } from '../../models/generics'; | ||
export declare const props: (el: HTMLElement) => Record<string, StringKV>; | ||
import { DirectiveKV } from '../../models/structs'; | ||
export declare const props: (el: HTMLElement) => Record<string, StringKV | DirectiveKV>; | ||
export default props; |
{ | ||
"name": "lucia", | ||
"version": "0.3.5", | ||
"version": "0.3.6", | ||
"description": "A tiny 3kb JavaScript library for prototyping web applications.", | ||
@@ -5,0 +5,0 @@ "main": "dist/lucia.cjs.js", |
@@ -44,3 +44,3 @@ # <a href="http://lucia.js.org"><img src="https://raw.githubusercontent.com/aidenybai/lucia/master/.github/img/logo.svg" height="60" alt="Lucia Logo" aria-label="http://lucia.js.org" /></a> | ||
```html | ||
<div l-init="{ count: 0 }"> | ||
<div l-state="{ count: 0 }"> | ||
<button l-text="this.count" l-on:click="++this.count">0</button> | ||
@@ -47,0 +47,0 @@ </div> |
205532
3678