mirror of
https://github.com/nvms/soma3.git
synced 2025-12-13 06:40:52 +00:00
pass el to most directives
This commit is contained in:
parent
0d2a1b6e82
commit
4067cc710a
@ -3,7 +3,7 @@
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"serve": "esr --serve src/demo.ts",
|
||||
"build": "esr --build src/index.ts",
|
||||
"build": "esr --build src/index.ts && brotli -f -q 11 public/index.js && brotli -f -q 11 public/index.css",
|
||||
"build:watch": "esr --build --watch src/index.ts",
|
||||
"run": "esr --run src/index.ts",
|
||||
"run:watch": "esr --run --watch src/index.ts",
|
||||
|
||||
@ -203,7 +203,7 @@ var AttributeDirective = class {
|
||||
}
|
||||
}
|
||||
update() {
|
||||
let value = evalGet(this.context.scope, this.expression);
|
||||
let value = evalGet(this.context.scope, this.expression, this.element);
|
||||
if (this.is.spread && typeof value === "object") {
|
||||
for (const [key, val] of Object.entries(value)) {
|
||||
this.element.setAttribute(key, String(val));
|
||||
@ -259,7 +259,7 @@ var EventDirective = class {
|
||||
if (parts.includes("stop")) event.stopPropagation();
|
||||
if (parts.includes("once") && this.eventCount > 0) return;
|
||||
this.eventCount++;
|
||||
const handler = evalGet(context.scope, attr.value);
|
||||
const handler = evalGet(context.scope, attr.value, element);
|
||||
if (typeof handler === "function") {
|
||||
handler(event);
|
||||
}
|
||||
@ -345,7 +345,7 @@ var _for = (el, exp, ctx, component, componentProps, allProps) => {
|
||||
indexExp && (data[indexExp] = index);
|
||||
}
|
||||
const childCtx = createScopedContext(ctx, data);
|
||||
const key = keyExp ? evalGet(childCtx.scope, keyExp) : index;
|
||||
const key = keyExp ? evalGet(childCtx.scope, keyExp, el) : index;
|
||||
map.set(key, index);
|
||||
childCtx.key = key;
|
||||
return childCtx;
|
||||
@ -357,7 +357,7 @@ var _for = (el, exp, ctx, component, componentProps, allProps) => {
|
||||
return block;
|
||||
};
|
||||
ctx.effect(() => {
|
||||
const source = evalGet(ctx.scope, sourceExp);
|
||||
const source = evalGet(ctx.scope, sourceExp, el);
|
||||
const prevKeyToIndexMap = keyToIndexMap;
|
||||
[childCtxs, keyToIndexMap] = createChildContexts(source);
|
||||
if (!mounted) {
|
||||
@ -429,7 +429,7 @@ function _if(el, exp, ctx, component, componentProps, allProps) {
|
||||
ctx.effect(() => {
|
||||
for (let i = 0; i < branches.length; i++) {
|
||||
const { exp: exp2, el: el2 } = branches[i];
|
||||
if (!exp2 || evalGet(ctx.scope, exp2)) {
|
||||
if (!exp2 || evalGet(ctx.scope, exp2, el2)) {
|
||||
if (i !== activeBranchIndex) {
|
||||
removeActiveBlock();
|
||||
block = new Block({ element: el2, parentContext: ctx, replacementType: "replace", component, componentProps, allProps });
|
||||
@ -459,7 +459,7 @@ var InterpolationDirective = class {
|
||||
this.textNodes.forEach((nodes, expression) => {
|
||||
const trimmedExpression = expression.slice(2, -2).trim();
|
||||
nodes.forEach((node) => {
|
||||
const getter = (exp = trimmedExpression) => evalGet(this.context.scope, exp, node);
|
||||
const getter = (exp = trimmedExpression) => evalGet(this.context.scope, exp, element);
|
||||
context.effect(() => {
|
||||
node.textContent = toDisplayString(getter());
|
||||
});
|
||||
@ -518,7 +518,7 @@ var ShowDirective = class {
|
||||
context.effect(this.update.bind(this));
|
||||
}
|
||||
update() {
|
||||
const shouldShow = Boolean(evalGet(this.context.scope, this.expression));
|
||||
const shouldShow = Boolean(evalGet(this.context.scope, this.expression, this.element));
|
||||
this.element.style.display = shouldShow ? this.originalDisplay : "none";
|
||||
}
|
||||
};
|
||||
@ -815,11 +815,7 @@ function unwrap(value) {
|
||||
// src/plugins/router/plugin.ts
|
||||
var activeRouters = /* @__PURE__ */ new Set();
|
||||
var link = {
|
||||
template: html`
|
||||
<a {href:bind} @click="go" .class:bind="classes">
|
||||
<slot>LINK</slot>
|
||||
</a>
|
||||
`,
|
||||
template: html`<a {href:bind} @click="go" .class:bind="classes"><slot /></a>`,
|
||||
props: { href: { default: "#" } },
|
||||
main({ href }) {
|
||||
const go = (e) => {
|
||||
@ -835,7 +831,7 @@ var link = {
|
||||
|
||||
// src/index.ts
|
||||
var App2 = class {
|
||||
rootBlock;
|
||||
root;
|
||||
registry = /* @__PURE__ */ new Map();
|
||||
plugins = /* @__PURE__ */ new Set();
|
||||
register(name, component) {
|
||||
@ -852,11 +848,11 @@ var App2 = class {
|
||||
const root = typeof target === "string" ? document.querySelector(target) : target;
|
||||
const display = root.style.display;
|
||||
root.style.display = "none";
|
||||
this.rootBlock = this._mount(component, root, props, true);
|
||||
this.root = this._mount(component, root, props);
|
||||
root.style.display = display;
|
||||
return this.rootBlock;
|
||||
return this.root;
|
||||
}
|
||||
_mount(component, target, props, isRoot = false) {
|
||||
_mount(component, target, props) {
|
||||
const parentContext = createContext({ app: this });
|
||||
if (props) {
|
||||
parentContext.scope = reactive(props);
|
||||
@ -868,14 +864,14 @@ var App2 = class {
|
||||
element: target,
|
||||
parentContext,
|
||||
component,
|
||||
isRoot,
|
||||
isRoot: true,
|
||||
componentProps: props,
|
||||
replacementType: "replaceChildren"
|
||||
});
|
||||
return block;
|
||||
}
|
||||
unmount() {
|
||||
this.rootBlock.teardown();
|
||||
this.root.teardown();
|
||||
}
|
||||
};
|
||||
function createContext({ parentContext, app: app2 }) {
|
||||
@ -1108,7 +1104,7 @@ function walk(node, context) {
|
||||
if (warnInvalidDirectives(node2, [":if", ":teleport"])) return;
|
||||
if (warnInvalidDirectives(node2, [":for", ":teleport"])) return;
|
||||
if (exp = checkAndRemoveAttribute(node2, ":scope")) {
|
||||
const scope = evalGet(context2.scope, exp);
|
||||
const scope = evalGet(context2.scope, exp, node2);
|
||||
if (typeof scope === "object") {
|
||||
Object.assign(context2.scope, scope);
|
||||
}
|
||||
@ -1133,7 +1129,7 @@ function walk(node, context) {
|
||||
}
|
||||
if (exp = checkAndRemoveAttribute(node2, ":html")) {
|
||||
context2.effect(() => {
|
||||
const result = evalGet(context2.scope, exp);
|
||||
const result = evalGet(context2.scope, exp, node2);
|
||||
if (result instanceof Element) {
|
||||
node2.replaceChildren();
|
||||
node2.append(result);
|
||||
@ -1144,7 +1140,7 @@ function walk(node, context) {
|
||||
}
|
||||
if (exp = checkAndRemoveAttribute(node2, ":text")) {
|
||||
context2.effect(() => {
|
||||
node2.textContent = toDisplayString(evalGet(context2.scope, exp));
|
||||
node2.textContent = toDisplayString(evalGet(context2.scope, exp, node2));
|
||||
});
|
||||
}
|
||||
};
|
||||
@ -1156,7 +1152,7 @@ function walk(node, context) {
|
||||
originalName: attr.name,
|
||||
extractedName: extractPropName(attr.name),
|
||||
exp: attr.value,
|
||||
value: isMirrorProp(attr.name) ? evalGet(context.scope, extractPropName(attr.name)) : attr.value ? evalGet(context.scope, attr.value) : void 0
|
||||
value: isMirrorProp(attr.name) ? evalGet(context.scope, extractPropName(attr.name), node2) : attr.value ? evalGet(context.scope, attr.value, node2) : void 0
|
||||
}));
|
||||
};
|
||||
if (isComponent(node, context)) {
|
||||
@ -1164,10 +1160,10 @@ function walk(node, context) {
|
||||
const allProps = processAttributes(node, component);
|
||||
const componentProps = allProps.reduce((acc, { isSpread, isMirror, extractedName, value }) => {
|
||||
if (isSpread) {
|
||||
const spread = evalGet(context.scope, extractedName);
|
||||
const spread = evalGet(context.scope, extractedName, node);
|
||||
if (isObject(spread)) Object.assign(acc, spread);
|
||||
} else if (isMirror) {
|
||||
acc[extractedName] = evalGet(context.scope, extractedName);
|
||||
acc[extractedName] = evalGet(context.scope, extractedName, node);
|
||||
} else {
|
||||
acc[extractedName] = value;
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
BIN
public/index.css.br
Normal file
BIN
public/index.css.br
Normal file
Binary file not shown.
File diff suppressed because one or more lines are too long
BIN
public/index.js.br
Executable file
BIN
public/index.js.br
Executable file
Binary file not shown.
@ -63,7 +63,7 @@ export class AttributeDirective {
|
||||
}
|
||||
|
||||
update() {
|
||||
let value = evalGet(this.context.scope, this.expression);
|
||||
let value = evalGet(this.context.scope, this.expression, this.element);
|
||||
|
||||
if (this.is.spread && typeof value === "object") {
|
||||
for (const [key, val] of Object.entries(value)) {
|
||||
|
||||
@ -29,7 +29,7 @@ export class EventDirective {
|
||||
|
||||
this.eventCount++;
|
||||
|
||||
const handler = evalGet(context.scope, attr.value);
|
||||
const handler = evalGet(context.scope, attr.value, element);
|
||||
if (typeof handler === "function") {
|
||||
handler(event);
|
||||
}
|
||||
|
||||
@ -92,7 +92,7 @@ export const _for = (el: Element, exp: string, ctx: Context, component?: Compone
|
||||
}
|
||||
|
||||
const childCtx = createScopedContext(ctx, data);
|
||||
const key = keyExp ? evalGet(childCtx.scope, keyExp) : index;
|
||||
const key = keyExp ? evalGet(childCtx.scope, keyExp, el) : index;
|
||||
map.set(key, index);
|
||||
childCtx.key = key;
|
||||
return childCtx;
|
||||
@ -106,7 +106,7 @@ export const _for = (el: Element, exp: string, ctx: Context, component?: Compone
|
||||
};
|
||||
|
||||
ctx.effect(() => {
|
||||
const source = evalGet(ctx.scope, sourceExp);
|
||||
const source = evalGet(ctx.scope, sourceExp, el);
|
||||
const prevKeyToIndexMap = keyToIndexMap;
|
||||
[childCtxs, keyToIndexMap] = createChildContexts(source);
|
||||
if (!mounted) {
|
||||
|
||||
@ -46,7 +46,7 @@ export function _if(el: Element, exp: string, ctx: Context, component?: Componen
|
||||
for (let i = 0; i < branches.length; i++) {
|
||||
const { exp, el } = branches[i];
|
||||
|
||||
if (!exp || evalGet(ctx.scope, exp)) {
|
||||
if (!exp || evalGet(ctx.scope, exp, el)) {
|
||||
if (i !== activeBranchIndex) {
|
||||
removeActiveBlock();
|
||||
block = new Block({ element: el, parentContext: ctx, replacementType: "replace", component, componentProps, allProps });
|
||||
|
||||
@ -23,7 +23,7 @@ export class InterpolationDirective {
|
||||
const trimmedExpression = expression.slice(2, -2).trim();
|
||||
|
||||
nodes.forEach((node) => {
|
||||
const getter = (exp = trimmedExpression) => evalGet(this.context.scope, exp, node);
|
||||
const getter = (exp = trimmedExpression) => evalGet(this.context.scope, exp, element);
|
||||
|
||||
context.effect(() => {
|
||||
node.textContent = toDisplayString(getter());
|
||||
|
||||
@ -22,7 +22,7 @@ export class ShowDirective {
|
||||
}
|
||||
|
||||
update() {
|
||||
const shouldShow = Boolean(evalGet(this.context.scope, this.expression));
|
||||
const shouldShow = Boolean(evalGet(this.context.scope, this.expression, this.element));
|
||||
// @ts-ignore
|
||||
this.element.style.display = shouldShow ? this.originalDisplay : "none";
|
||||
}
|
||||
|
||||
26
src/index.ts
26
src/index.ts
@ -43,7 +43,7 @@ export function inject(key: string) {
|
||||
}
|
||||
|
||||
export class App {
|
||||
rootBlock: Block;
|
||||
root: Block;
|
||||
registry = new Map<string, Component>();
|
||||
plugins = new Set<Plugin>();
|
||||
|
||||
@ -64,12 +64,12 @@ export class App {
|
||||
const root = typeof target === "string" ? (document.querySelector(target) as HTMLElement) : target;
|
||||
const display = root.style.display;
|
||||
root.style.display = "none";
|
||||
this.rootBlock = this._mount(component, root, props, true);
|
||||
this.root = this._mount(component, root, props);
|
||||
root.style.display = display;
|
||||
return this.rootBlock;
|
||||
return this.root;
|
||||
}
|
||||
|
||||
private _mount(component: Component, target: HTMLElement, props: Record<string, any>, isRoot = false) {
|
||||
private _mount(component: Component, target: HTMLElement, props: Record<string, any>) {
|
||||
const parentContext = createContext({ app: this });
|
||||
|
||||
if (props) {
|
||||
@ -84,7 +84,7 @@ export class App {
|
||||
element: target,
|
||||
parentContext,
|
||||
component,
|
||||
isRoot,
|
||||
isRoot: true,
|
||||
componentProps: props,
|
||||
replacementType: "replaceChildren",
|
||||
});
|
||||
@ -93,7 +93,7 @@ export class App {
|
||||
}
|
||||
|
||||
unmount() {
|
||||
this.rootBlock.teardown();
|
||||
this.root.teardown();
|
||||
}
|
||||
}
|
||||
|
||||
@ -258,7 +258,7 @@ export class Block {
|
||||
}
|
||||
}
|
||||
|
||||
opts.allProps?.forEach((prop) => {
|
||||
opts.allProps?.forEach((prop: any) => {
|
||||
if (prop.isBind) {
|
||||
this.context.effect(() => {
|
||||
let newValue: unknown;
|
||||
@ -422,7 +422,7 @@ function walk(node: Node, context: Context) {
|
||||
// In this case, the scope is merged into context.scope and will overwrite
|
||||
// anything returned from `main`.
|
||||
if ((exp = checkAndRemoveAttribute(node, ":scope"))) {
|
||||
const scope = evalGet(context.scope, exp);
|
||||
const scope = evalGet(context.scope, exp, node);
|
||||
if (typeof scope === "object") {
|
||||
Object.assign(context.scope, scope);
|
||||
// context = createScopedContext(context, scope);
|
||||
@ -449,7 +449,7 @@ function walk(node: Node, context: Context) {
|
||||
}
|
||||
if ((exp = checkAndRemoveAttribute(node, ":html"))) {
|
||||
context.effect(() => {
|
||||
const result = evalGet(context.scope, exp);
|
||||
const result = evalGet(context.scope, exp, node);
|
||||
if (result instanceof Element) {
|
||||
node.replaceChildren();
|
||||
node.append(result);
|
||||
@ -460,7 +460,7 @@ function walk(node: Node, context: Context) {
|
||||
}
|
||||
if ((exp = checkAndRemoveAttribute(node, ":text"))) {
|
||||
context.effect(() => {
|
||||
node.textContent = toDisplayString(evalGet(context.scope, exp));
|
||||
node.textContent = toDisplayString(evalGet(context.scope, exp, node));
|
||||
});
|
||||
}
|
||||
};
|
||||
@ -475,7 +475,7 @@ function walk(node: Node, context: Context) {
|
||||
originalName: attr.name,
|
||||
extractedName: extractPropName(attr.name),
|
||||
exp: attr.value,
|
||||
value: isMirrorProp(attr.name) ? evalGet(context.scope, extractPropName(attr.name)) : attr.value ? evalGet(context.scope, attr.value) : undefined,
|
||||
value: isMirrorProp(attr.name) ? evalGet(context.scope, extractPropName(attr.name), node) : attr.value ? evalGet(context.scope, attr.value, node) : undefined,
|
||||
}));
|
||||
};
|
||||
|
||||
@ -485,10 +485,10 @@ function walk(node: Node, context: Context) {
|
||||
|
||||
const componentProps = allProps.reduce((acc, { isSpread, isMirror, extractedName, value }) => {
|
||||
if (isSpread) {
|
||||
const spread = evalGet(context.scope, extractedName);
|
||||
const spread = evalGet(context.scope, extractedName, node);
|
||||
if (isObject(spread)) Object.assign(acc, spread);
|
||||
} else if (isMirror) {
|
||||
acc[extractedName] = evalGet(context.scope, extractedName);
|
||||
acc[extractedName] = evalGet(context.scope, extractedName, node);
|
||||
} else {
|
||||
acc[extractedName] = value;
|
||||
}
|
||||
|
||||
@ -6,14 +6,14 @@ import { reactive } from "../../reactivity/reactive";
|
||||
import { unwrap } from "../../reactivity/unwrap";
|
||||
import { html } from "../../util";
|
||||
|
||||
const activeRouters = new Set<RouterPlugin>();
|
||||
export const activeRouters = new Set<RouterPlugin>();
|
||||
|
||||
export function getRouter(): RouterPlugin | undefined {
|
||||
return current.componentBlock ? [...activeRouters].find((router) => router.app === current.componentBlock.context.app) : undefined;
|
||||
}
|
||||
|
||||
const link = {
|
||||
template: html`
|
||||
<a {href:bind} @click="go" .class:bind="classes">
|
||||
<slot>LINK</slot>
|
||||
</a>
|
||||
`,
|
||||
template: html`<a {href:bind} @click="go" .class:bind="classes"><slot /></a>`,
|
||||
props: { href: { default: "#" } },
|
||||
main({ href }: { href: string }) {
|
||||
const go = (e: Event) => {
|
||||
@ -60,7 +60,7 @@ export class RouterPlugin implements Plugin {
|
||||
this.routes = routes;
|
||||
}
|
||||
|
||||
use(app: App, ...config: any[]) {
|
||||
use(app: App, ..._: any[]) {
|
||||
this.app = app;
|
||||
this.app.register("router-link", link);
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user