new propagator syntax experiment
This commit is contained in:
parent
5e74882dff
commit
f1b2a67adb
|
|
@ -49,14 +49,14 @@
|
||||||
source="folk-metronome"
|
source="folk-metronome"
|
||||||
target="#kick"
|
target="#kick"
|
||||||
triggers="beat"
|
triggers="beat"
|
||||||
expression="if ($source.beat % 2 === 0) $target.play();"
|
expression="play(): from.beat === 1"
|
||||||
></folk-event-propagator>
|
></folk-event-propagator>
|
||||||
|
|
||||||
<folk-event-propagator
|
<folk-event-propagator
|
||||||
source="folk-metronome"
|
source="folk-metronome"
|
||||||
target="#hat"
|
target="#hat"
|
||||||
triggers="beat"
|
triggers="beat"
|
||||||
expression="if ($source.beat > 2) $target.play();"
|
expression="play(): from.beat % 3"
|
||||||
></folk-event-propagator>
|
></folk-event-propagator>
|
||||||
|
|
||||||
<script type="module">
|
<script type="module">
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@
|
||||||
source="#box1"
|
source="#box1"
|
||||||
target="#box2"
|
target="#box2"
|
||||||
triggers="click"
|
triggers="click"
|
||||||
expression="textContent: _ + '!'"
|
expression="textContent: to.textContent + '!'"
|
||||||
></folk-event-propagator>
|
></folk-event-propagator>
|
||||||
|
|
||||||
<folk-shape id="box3" x="350" y="200" width="30" height="30"></folk-shape>
|
<folk-shape id="box3" x="350" y="200" width="30" height="30"></folk-shape>
|
||||||
|
|
@ -48,7 +48,7 @@
|
||||||
target="#box4"
|
target="#box4"
|
||||||
triggers="move"
|
triggers="move"
|
||||||
expression="y: from.x,
|
expression="y: from.x,
|
||||||
rotate: from.x"
|
rotation: from.x"
|
||||||
></folk-event-propagator>
|
></folk-event-propagator>
|
||||||
|
|
||||||
<script type="module">
|
<script type="module">
|
||||||
|
|
|
||||||
|
|
@ -46,55 +46,50 @@ export class FolkEventPropagator extends FolkRope {
|
||||||
set expression(expression) {
|
set expression(expression) {
|
||||||
this.mend();
|
this.mend();
|
||||||
this.#expression = expression;
|
this.#expression = expression;
|
||||||
|
const processedExp = expression.trim();
|
||||||
|
|
||||||
|
const codeLines: string[] = [];
|
||||||
|
|
||||||
|
// Split the expression into lines, handling different line endings
|
||||||
|
const lines = processedExp.split(/\r?\n/);
|
||||||
|
|
||||||
|
for (const line of lines) {
|
||||||
|
let line_trimmed = line.trim();
|
||||||
|
if (!line_trimmed) continue;
|
||||||
|
|
||||||
|
// Remove trailing comma if it exists (only if it's at the very end of the line)
|
||||||
|
if (line_trimmed.endsWith(',')) {
|
||||||
|
line_trimmed = line_trimmed.slice(0, -1).trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the first colon index, which separates the key and value.
|
||||||
|
// Colons can still be used in ternary operators or other expressions,
|
||||||
|
const colonIndex = line_trimmed.indexOf(':');
|
||||||
|
if (colonIndex === -1) {
|
||||||
|
// Line without a colon, skip or handle error
|
||||||
|
console.warn(`Skipping line without colon: "${line_trimmed}"`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const key = line_trimmed.slice(0, colonIndex).trim();
|
||||||
|
const value = line_trimmed.slice(colonIndex + 1).trim();
|
||||||
|
|
||||||
|
if (key.endsWith('()')) {
|
||||||
|
// If the key is a function call, execute it if the condition is true
|
||||||
|
const methodName = key.slice(0, -2);
|
||||||
|
codeLines.push(`if (${value}) { to.${methodName}(); }`);
|
||||||
|
} else {
|
||||||
|
// For property assignments, assign the value directly
|
||||||
|
codeLines.push(`to.${key} = ${value};`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const functionBody = codeLines.join('\n');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const processedExp = expression.trim();
|
this.#function = new Function('from', 'to', 'event', functionBody);
|
||||||
|
|
||||||
// Process each line, looking for the first ':' to separate key from value
|
|
||||||
const processedProps = processedExp
|
|
||||||
.split('\n')
|
|
||||||
.map((line) => {
|
|
||||||
const line_trimmed = line.trim();
|
|
||||||
if (!line_trimmed || line_trimmed === '{' || line_trimmed === '}') return '';
|
|
||||||
|
|
||||||
// Remove trailing comma if it exists
|
|
||||||
const withoutComma = line_trimmed.replace(/,\s*$/, '');
|
|
||||||
|
|
||||||
const colonIndex = withoutComma.indexOf(':');
|
|
||||||
if (colonIndex === -1) return withoutComma;
|
|
||||||
|
|
||||||
const key = withoutComma.slice(0, colonIndex).trim();
|
|
||||||
const value = withoutComma.slice(colonIndex + 1).trim();
|
|
||||||
|
|
||||||
return `${key}: (function() { const _ = to[${JSON.stringify(key)}]; return ${value}; })()`;
|
|
||||||
})
|
|
||||||
.filter((line) => line)
|
|
||||||
.join(',\n');
|
|
||||||
|
|
||||||
this.#function = new Function(
|
|
||||||
'from',
|
|
||||||
'to',
|
|
||||||
'event',
|
|
||||||
`
|
|
||||||
return {
|
|
||||||
${processedProps}
|
|
||||||
};
|
|
||||||
`
|
|
||||||
);
|
|
||||||
|
|
||||||
console.log(processedProps);
|
|
||||||
|
|
||||||
this.#function = new Function(
|
|
||||||
'from',
|
|
||||||
'to',
|
|
||||||
'event',
|
|
||||||
`
|
|
||||||
return {
|
|
||||||
${processedProps}
|
|
||||||
};
|
|
||||||
`
|
|
||||||
);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.warn('Failed to parse expression:', error);
|
console.warn('Failed to parse expression:', error, functionBody);
|
||||||
this.cut();
|
this.cut();
|
||||||
this.#function = null;
|
this.#function = null;
|
||||||
}
|
}
|
||||||
|
|
@ -184,10 +179,26 @@ export class FolkEventPropagator extends FolkRope {
|
||||||
if (!this.#function) return;
|
if (!this.#function) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const assignments = this.#function(this.sourceElement, this.targetElement, event);
|
const toProxy = new Proxy(this.targetElement, {
|
||||||
Object.assign(this.targetElement, assignments);
|
set(target, prop, value, receiver) {
|
||||||
|
if (!(prop in target)) {
|
||||||
|
throw new Error(`Property '${String(prop)}' does not exist on target element.`);
|
||||||
|
}
|
||||||
|
return Reflect.set(target, prop, value, receiver);
|
||||||
|
},
|
||||||
|
get(target, prop, receiver) {
|
||||||
|
const value = Reflect.get(target, prop, receiver);
|
||||||
|
if (typeof value === 'function') {
|
||||||
|
return value.bind(target);
|
||||||
|
} else {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
this.#function(this.sourceElement, toProxy, event);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.warn('Failed to parse expression:', error);
|
console.warn('Failed to evaluate expression:', error);
|
||||||
this.stroke = 'red';
|
this.stroke = 'red';
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue