UNPKG

@solid-primitives/controlled-props

Version:

The primitives in this package allow you to create controlls for component props.

132 lines (131 loc) 5.28 kB
import { template as _$template } from "solid-js/web"; import { delegateEvents as _$delegateEvents } from "solid-js/web"; import { createComponent as _$createComponent } from "solid-js/web"; import { setAttribute as _$setAttribute } from "solid-js/web"; import { insert as _$insert } from "solid-js/web"; import { effect as _$effect } from "solid-js/web"; var _tmpl$ = /* @__PURE__ */ _$template(`<label><input type=checkbox> <span></span> `), _tmpl$2 = /* @__PURE__ */ _$template(`<label><span></span> <input type=number> `), _tmpl$3 = /* @__PURE__ */ _$template(`<label><span></span> <input type=text> `), _tmpl$4 = /* @__PURE__ */ _$template(`<label><span></span> <select></select> `), _tmpl$5 = /* @__PURE__ */ _$template(`<option>"options missing"`), _tmpl$6 = /* @__PURE__ */ _$template(`<option>`); import { createMemo, createSignal, For } from "solid-js"; const BoolProp = (props) => (() => { var _el$ = _tmpl$(), _el$2 = _el$.firstChild, _el$3 = _el$2.nextSibling, _el$4 = _el$3.nextSibling; _el$2.addEventListener("change", (ev) => props.setValue(ev.currentTarget.checked)); _$insert(_el$4, () => props.name); _$effect(() => _$setAttribute(_el$2, "name", props.name)); _$effect(() => _el$2.checked = props.value()); return _el$; })(); const NumberProp = (props) => (() => { var _el$5 = _tmpl$2(), _el$6 = _el$5.firstChild, _el$7 = _el$6.nextSibling, _el$8 = _el$7.nextSibling; _$insert(_el$6, () => props.name); _el$8.addEventListener("change", (ev) => props.setValue(ev.currentTarget.valueAsNumber)); _$effect((_p$) => { var _v$ = props.name, _v$2 = props.min, _v$3 = props.max; _v$ !== _p$.e && _$setAttribute(_el$8, "name", _p$.e = _v$); _v$2 !== _p$.t && _$setAttribute(_el$8, "min", _p$.t = _v$2); _v$3 !== _p$.a && _$setAttribute(_el$8, "max", _p$.a = _v$3); return _p$; }, { e: void 0, t: void 0, a: void 0 }); _$effect(() => _el$8.value = props.value()); return _el$5; })(); const StringProp = (props) => (() => { var _el$9 = _tmpl$3(), _el$10 = _el$9.firstChild, _el$11 = _el$10.nextSibling, _el$12 = _el$11.nextSibling; _$insert(_el$10, () => props.name); _el$12.addEventListener("change", (ev) => props.setValue(ev.currentTarget.value)); _el$12.$$input = (ev) => props.setValue(ev.currentTarget.value); _$effect(() => _$setAttribute(_el$12, "name", props.name)); _$effect(() => _el$12.value = props.value()); return _el$9; })(); const filterEnum = (options) => { const entries = Object.entries(options); if (Object.keys(options).every((key) => key === options[options[key]].toString())) { return entries.reduce((items, [key, value]) => { if (!items.includes(key)) { items.push(value); } return items; }, []).map((item) => [item, options[item]]); } return entries; }; const SelectProp = (props) => { const options = createMemo(() => Array.isArray(props.options) ? props.options.map((option) => [option, option]) : filterEnum(props.options)); const initialValue = options().findIndex(([, value]) => value === props.value()); return (() => { var _el$13 = _tmpl$4(), _el$14 = _el$13.firstChild, _el$15 = _el$14.nextSibling, _el$16 = _el$15.nextSibling; _$insert(_el$14, () => props.name); _el$16.addEventListener("change", (ev) => props.setValue(options()[ev.currentTarget.selectedIndex][1])); _$insert(_el$16, _$createComponent(For, { get each() { return options(); }, get fallback() { return _tmpl$5(); }, children: ([key], index) => (() => { var _el$18 = _tmpl$6(); _$insert(_el$18, key); _$effect(() => _el$18.value = index()); return _el$18; })() })); _$effect(() => _$setAttribute(_el$16, "name", props.name)); _$effect(() => _el$16.value = initialValue.toString()); return _el$13; })(); }; const defaultInitialValues = { boolean: false, number: 0, string: "", object: void 0 }; function createControlledProp(name, options) { const initialValue = options == null ? void 0 : typeof options !== "object" ? options : options.initialValue ?? defaultInitialValues[options.type ?? "object"]; if (initialValue == null) { throw new Error(`cannot get type for Prop ${name}`); } const propType = options.options ? "object" : options.type ?? typeof initialValue; const [value, setValue] = createSignal(initialValue, { name }); return [value, setValue, propType === "boolean" ? () => BoolProp({ name, value, setValue }) : propType === "number" ? () => NumberProp({ name, value, setValue }) : propType === "string" ? () => StringProp({ name, value, setValue }) : () => SelectProp({ name, value, setValue, options: options.options ?? [initialValue] })]; } const createControlledProps = (props) => Object.entries(props).reduce((result, [name, options]) => { const [value, setValue, field] = createControlledProp(name, options); result[0][name] = value; result[0][`set${name.slice(0, 1).toUpperCase()}${name.slice(1)}`] = setValue; result[1].push(field({})); return result; }, [{}, []]); _$delegateEvents(["input"]); export { BoolProp, NumberProp, SelectProp, StringProp, createControlledProp, createControlledProps };