@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
JavaScript
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
};