mirror of
https://github.com/eliasstepanik/strudel.git
synced 2026-01-11 05:38:35 +00:00
simplify widget creation + fix bugs
This commit is contained in:
parent
6dce9d5deb
commit
8742d50bad
@ -53,6 +53,12 @@ const widgetField = StateField.define(
|
||||
},
|
||||
);
|
||||
|
||||
const widgetElements = {};
|
||||
export function setWidget(id, el) {
|
||||
widgetElements[id] = el;
|
||||
el.id = id;
|
||||
}
|
||||
|
||||
export class BlockWidget extends WidgetType {
|
||||
constructor(col, type) {
|
||||
super();
|
||||
@ -64,11 +70,7 @@ export class BlockWidget extends WidgetType {
|
||||
}
|
||||
toDOM() {
|
||||
const id = getWidgetID(this.col); // matches id generated in transpiler
|
||||
let el = document.getElementById(id);
|
||||
if (!el) {
|
||||
el = document.createElement(this.type);
|
||||
el.id = id;
|
||||
}
|
||||
const el = widgetElements[id];
|
||||
return el;
|
||||
}
|
||||
ignoreEvent(e) {
|
||||
|
||||
@ -3,16 +3,9 @@ import { parse } from 'acorn';
|
||||
import escodegen from 'escodegen';
|
||||
import { walk } from 'estree-walker';
|
||||
|
||||
let widgetComponents = {};
|
||||
// this function allows registering a pattern method name and component name
|
||||
// e.g. register('claviature', 'strudel-claviature')
|
||||
// .. will map the Pattern method 'claviature' to the web component 'strudel-claviature'
|
||||
// the transpiler will turn .claviature(...args) into .claviature(id, ...args)
|
||||
// the widgetPlugin of @strudel/codemirror will automatically create an instance of 'strudel-claviature'
|
||||
// .. so you only have to implement the actual .claviature method (or what you've called it..)
|
||||
|
||||
export function registerWidget(name, tagName) {
|
||||
widgetComponents[name] = tagName;
|
||||
let widgetMethods = [];
|
||||
export function registerWidgetType(type) {
|
||||
widgetMethods.push(type);
|
||||
}
|
||||
|
||||
export function transpiler(input, options = {}) {
|
||||
@ -63,7 +56,7 @@ export function transpiler(input, options = {}) {
|
||||
emitWidgets &&
|
||||
widgets.push({
|
||||
to: node.end,
|
||||
type: widgetComponents[node.callee.property.name],
|
||||
type: node.callee.property.name,
|
||||
});
|
||||
return this.replace(widgetWithLocation(node));
|
||||
}
|
||||
@ -131,7 +124,7 @@ function isSliderFunction(node) {
|
||||
}
|
||||
|
||||
function isWidgetMethod(node) {
|
||||
return node.type === 'CallExpression' && Object.keys(widgetComponents).includes(node.callee.property?.name);
|
||||
return node.type === 'CallExpression' && widgetMethods.includes(node.callee.property?.name);
|
||||
}
|
||||
|
||||
function sliderWithLocation(node) {
|
||||
|
||||
@ -1,21 +0,0 @@
|
||||
import { customElement } from 'solid-element';
|
||||
|
||||
customElement('strudel-canvas', {}, () => {
|
||||
return <canvas width={300} height={200} />;
|
||||
});
|
||||
|
||||
export function getWidgetDrawContext(id, options) {
|
||||
let el = document.getElementById(id);
|
||||
if (!el) {
|
||||
console.warn(`widget with id ${id} not found in the DOM`);
|
||||
return;
|
||||
}
|
||||
const { width = 300, height = 100, pixelRatio = window.devicePixelRatio } = options || {};
|
||||
const canvas = el?.shadowRoot.firstChild;
|
||||
canvas.width = width * pixelRatio;
|
||||
canvas.height = height * pixelRatio;
|
||||
canvas.style.width = width + 'px';
|
||||
canvas.style.height = height + 'px';
|
||||
const ctx = canvas.getContext('2d');
|
||||
return ctx;
|
||||
}
|
||||
@ -2,8 +2,7 @@ import { For } from 'solid-js';
|
||||
import { customElement } from 'solid-element';
|
||||
import { getClaviature } from 'claviature';
|
||||
import { Dynamic } from 'solid-js/web';
|
||||
import { Pattern } from '@strudel/core';
|
||||
import { registerWidget } from '@strudel/transpiler';
|
||||
import { registerWidget } from './registry.mjs';
|
||||
|
||||
let defaultOptions = {
|
||||
range: ['A1', 'C6'],
|
||||
@ -31,12 +30,11 @@ customElement('strudel-claviature', { options: JSON.stringify(defaultOptions) },
|
||||
);
|
||||
});
|
||||
|
||||
registerWidget('claviature', 'strudel-claviature');
|
||||
|
||||
Pattern.prototype.claviature = function (id, options = {}) {
|
||||
return this.onFrame((haps) => {
|
||||
registerWidget('claviature', (id, options = {}, pat) => {
|
||||
const el = document.getElementById(id) || document.createElement('strudel-claviature');
|
||||
setWidget(id, el);
|
||||
return pat.onFrame(id, (haps) => {
|
||||
const colorize = haps.map((h) => ({ keys: [h.value.note], color: h.context?.color || 'steelblue' }));
|
||||
let el = document.getElementById(id);
|
||||
el?.setAttribute(
|
||||
'options',
|
||||
JSON.stringify({
|
||||
@ -46,4 +44,4 @@ Pattern.prototype.claviature = function (id, options = {}) {
|
||||
}),
|
||||
);
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
@ -1,14 +0,0 @@
|
||||
import { Pattern } from '@strudel/core';
|
||||
import { registerWidget } from '@strudel/transpiler';
|
||||
import { getWidgetDrawContext } from './Canvas.jsx';
|
||||
|
||||
registerWidget('roll', 'strudel-canvas');
|
||||
|
||||
Pattern.prototype.roll = function (id, options = { fold: 1 }) {
|
||||
// TODO: remove setTimeout...
|
||||
setTimeout(() => {
|
||||
const ctx = getWidgetDrawContext(id, options);
|
||||
this.pianoroll({ ...options, ctx });
|
||||
});
|
||||
return this;
|
||||
};
|
||||
23
packages/widgets/canvas.mjs
Normal file
23
packages/widgets/canvas.mjs
Normal file
@ -0,0 +1,23 @@
|
||||
import { registerWidget } from './registry.mjs';
|
||||
import { setWidget } from '@strudel/codemirror';
|
||||
|
||||
function createCanvasWidget(id, options) {
|
||||
const { width = 300, height = 100, pixelRatio = window.devicePixelRatio } = options || {};
|
||||
let canvas = document.getElementById(id) || document.createElement('canvas');
|
||||
canvas.width = width * pixelRatio;
|
||||
canvas.height = height * pixelRatio;
|
||||
canvas.style.width = width + 'px';
|
||||
canvas.style.height = height + 'px';
|
||||
setWidget(id, canvas);
|
||||
return canvas;
|
||||
}
|
||||
|
||||
registerWidget('roll', (id, options = { fold: 1 }, pat) => {
|
||||
const ctx = createCanvasWidget(id, options).getContext('2d');
|
||||
return pat.pianoroll({ ...options, ctx, id });
|
||||
});
|
||||
|
||||
registerWidget('twist', (id, options = {}, pat) => {
|
||||
const ctx = createCanvasWidget(id, options).getContext('2d');
|
||||
return pat.spiral({ ...options, ctx, size: 50, id });
|
||||
});
|
||||
@ -1,3 +1,3 @@
|
||||
export * from './Claviature.jsx';
|
||||
export * from './Pianoroll.jsx';
|
||||
export * from './Canvas.jsx';
|
||||
export * from './canvas.mjs';
|
||||
export * from './registry.mjs';
|
||||
|
||||
@ -30,6 +30,7 @@
|
||||
"@strudel/core": "workspace:*",
|
||||
"@strudel/transpiler": "workspace:*",
|
||||
"@strudel/draw": "workspace:*",
|
||||
"@strudel/codemirror": "workspace:*",
|
||||
"claviature": "^0.1.0",
|
||||
"solid-element": "^1.8.0",
|
||||
"solid-js": "^1.8.15",
|
||||
|
||||
11
packages/widgets/registry.mjs
Normal file
11
packages/widgets/registry.mjs
Normal file
@ -0,0 +1,11 @@
|
||||
import { registerWidgetType } from '@strudel/transpiler';
|
||||
import { Pattern } from '@strudel/core';
|
||||
|
||||
export function registerWidget(type, fn) {
|
||||
registerWidgetType(type);
|
||||
if (fn) {
|
||||
Pattern.prototype[type] = function (id, options = { fold: 1 }) {
|
||||
return fn(id, options, this);
|
||||
};
|
||||
}
|
||||
}
|
||||
3
pnpm-lock.yaml
generated
3
pnpm-lock.yaml
generated
@ -490,6 +490,9 @@ importers:
|
||||
|
||||
packages/widgets:
|
||||
dependencies:
|
||||
'@strudel/codemirror':
|
||||
specifier: workspace:*
|
||||
version: link:../codemirror
|
||||
'@strudel/core':
|
||||
specifier: workspace:*
|
||||
version: link:../core
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user