solid-tweakpane
Version:
Solid components for Tweakpane library
204 lines (197 loc) • 6.02 kB
JavaScript
;
var solidJs = require('solid-js');
var tweakpane = require('tweakpane');
const TWPRootContext = solidJs.createContext();
const useTWPRoot = () => solidJs.useContext(TWPRootContext);
function TWPGroup(props) {
return solidJs.createComponent(TWPRootContext.Provider, {
get value() {
return props.root;
},
get children() {
return props.children;
}
});
}
function Tweakpane(props) {
const [compProps, paneProps] = solidJs.splitProps(props, ["children"]);
const pane = new tweakpane.Pane(paneProps);
solidJs.onCleanup(() => pane.dispose());
return solidJs.createComponent(TWPGroup, {
root: pane,
get children() {
return compProps.children;
}
});
}
const TWPBindGroupContext = solidJs.createContext();
const useTWPBingGroup = () => solidJs.useContext(TWPBindGroupContext);
function TWPBindGroup(props) {
return solidJs.createComponent(TWPBindGroupContext.Provider, {
get value() {
return props.target;
},
get children() {
return props.children;
}
});
}
function createTWPUI(initFn) {
return function (props) {
const root = useTWPRoot();
if (!root) throw new Error(`Use tweakpane controls within <${"Tweakpane"}>`);
const [comp, element] = initFn(root, props);
solidJs.onCleanup(() => {
if (!comp) return;
comp.dispose();
root.remove(comp);
});
props.ref?.(comp);
if (element) return element;
};
}
const TWPFolder = createTWPUI((root, props) => {
const [compProps, folderProps] = solidJs.splitProps(props, ["children"]);
const folder = root.addFolder(folderProps);
return [folder, solidJs.createComponent(TWPGroup, {
root: folder,
get children() {
return compProps.children;
}
})];
});
const TWPButton = createTWPUI((root, props) => {
const button = root.addButton(props);
props.onClick && button.on("click", props.onClick);
solidJs.createEffect(() => {
button.title = props.title;
});
return [button];
});
const TWPSeparator = createTWPUI((root, props) => {
const separator = root.addSeparator(props);
return [separator];
});
const TabContext = solidJs.createContext();
const useTab = () => solidJs.useContext(TabContext);
const TWPTab = createTWPUI((root, props) => {
const [compProps, tabProps] = solidJs.splitProps(props, ["children"]);
const tab = root.addTab({
...tabProps,
pages: [{
title: "mock"
}]
});
solidJs.onMount(() => tab.removePage(0));
return [tab, solidJs.createComponent(TabContext.Provider, {
value: tab,
get children() {
return compProps.children;
}
})];
});
function TWPTabPage(props) {
const root = useTab();
if (!root) throw new Error(`Parent for <${"TWPTabPage"}> should be <${"TWPTab"}>`);
const [compProps, pageProps] = solidJs.splitProps(props, ["children"]);
const page = root.addPage(pageProps);
solidJs.createEffect(() => page.title = props.title);
solidJs.onCleanup(() => {
root.removePage(root.pages.indexOf(page));
});
return solidJs.createComponent(TWPGroup, {
root: page,
get children() {
return compProps.children;
}
});
}
function createTWPControl(initFn) {
return function (props) {
const root = useTWPRoot();
if (!root) throw new Error(`Use tweakpane controls within <${"Tweakpane"}>`);
let binding = props.target ?? useTWPBingGroup();
if (!binding && props.key) {
throw new Error(`In case of usage <TWPControl> with key, place it within <${"TWPBindGroup"}> and provide taget`);
}
if (binding && !Object.hasOwn(binding, props.key)) {
throw new Error(`There is no key ${props.key} in binding ${binding}`);
}
if (!binding && !props.key) {
if (!props.initialValue) {
throw new Error(`In case of usage <TWPControl> without target and key, provide ${"initialValue"} prop`);
}
binding = {
value: props.initialValue
};
props.key = "value";
}
const [comp, element] = initFn(root, binding, props);
solidJs.createEffect(solidJs.on(() => binding[props.key], () => comp.refresh(), {
defer: true
}));
solidJs.onCleanup(() => {
if (!comp) return;
root.remove(comp);
comp.dispose();
});
props.ref?.(comp);
if (element) return element;
};
}
const TWPInput = createTWPControl((root, binding, props) => {
const input = root.addInput(binding, props.key, props.params);
props.onChange && input.on("change", props.onChange);
return [input];
});
const TWPMonitor = createTWPControl((root, binding, props) => {
const monitor = root.addMonitor(binding, props.key, props.params);
props.onUpdate && monitor.on("update", props.onUpdate);
return [monitor];
});
function TWPAutoMutable(props) {
return solidJs.createComponent(solidJs.For, {
get each() {
return Object.keys(props.target);
},
children: key => solidJs.createComponent(solidJs.Switch, {
get fallback() {
return solidJs.createComponent(TWPInput, {
key: key,
get target() {
return props.target;
}
});
},
get children() {
return solidJs.createComponent(solidJs.Match, {
get when() {
return props.target[key].constructor === Object;
},
get children() {
return solidJs.createComponent(TWPFolder, {
title: key,
get children() {
return solidJs.createComponent(TWPAutoMutable, {
get target() {
return props.target[key];
}
});
}
});
}
});
}
})
});
}
exports.TWPAutoMutable = TWPAutoMutable;
exports.TWPBindGroup = TWPBindGroup;
exports.TWPButton = TWPButton;
exports.TWPFolder = TWPFolder;
exports.TWPInput = TWPInput;
exports.TWPMonitor = TWPMonitor;
exports.TWPSeparator = TWPSeparator;
exports.TWPTab = TWPTab;
exports.TWPTabPage = TWPTabPage;
exports.Tweakpane = Tweakpane;