filestash/public/components/form.js
2023-08-02 19:39:34 +10:00

165 lines
4.8 KiB
JavaScript

import { createElement } from "../lib/skeleton/index.js";
import { safe } from "../lib/dom.js";
import { gid } from "../lib/random.js";
export function formTmpl(withAutocomplete) {
return {
renderNode: ({ label }) => {
return createElement(`
<fieldset>
<legend class="no-select">${format(label)}</legend>
</fieldset>
`);
},
renderLeaf: ({ label }) => {
return createElement(`
<label>
${format(label)}
</label>
`);
},
renderInput: $renderInput,
formatLabel: format,
};
};
export async function $renderInput(props) {
const {
id = null,
type,
value = null,
placeholder = "",
required = false,
readonly = false,
path = [],
autocomplete = false,
datalist = null,
options = null,
} = props
let attr = `name="${path.join(".")}" `;
if (value) attr += `value="${value}" `;
if (id) attr += `id=${id} `;
if (placeholder) attr += `placeholder=${placeholder} `;
if (!autocomplete) attr += `autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="off" `;
if (required) attr += "required ";
if (readonly) attr += "readonly ";
switch(type) {
case "text": // TODO
const dataListId = gid("list_");
const $input = createElement(`
<input ${safe(attr)}
type="text"
class="component_input"
/>
`);
if (!datalist) return $input;
const $wrapper = window.document.createElement("span");
const $datalist = window.document.createElement("datalist")
$wrapper.appendChild($input);
$datalist.setAttribute("id", dataListId);
// const filtered = function(multi, datalist, currentValue) {
// if (multi !== true || currentValue == null) return datalist;
// return autocomplete(
// currentValue
// .split(",")
// .map((t) => t.trim())
// .filter((t) => t),
// datalist,
// );
// };
// fitlered()
return $wrapper;
case "number":
return createElement(`
<input
${safe(attr)}
type="number"
class="component_input"
/>
`);
case "password":
// TODO: click eye
return createElement(`
<div class="formbuilder_password">
<input
${safe(attr)}
type="password"
class="component_input"
/>
</div>
`);
// case "long_password":
// // TODO
// case "long_text":
// return // TODO
// case "bcrypt": import("./bcrypt.js")
// // TODO
case "hidden":
return createElement(`
<input
type="hidden" value=${safe(value)}
name="${safe(path.join("."))}"
/>
`);
case "boolean":
return createElement(`
<div class="component_checkbox">
<input ${safe(attr)} type="checkbox" />
<span className="indicator"></span>
</div>
`);
case "select":
const renderOption = (name) => `<option name="${safe(name)}">${safe(name)}</option>`;
return createElement(`
<select class="component_select" ${safe(attr)}>
${(options || []).map(renderOption)}
</select>
`);
case "date":
return createElement(`
<input
${safe(attr)}
type="date"
class="component_input"
/>
`);
case "datetime":
return createElement(`
<input
${safe(attr)}
type="datetime-local"
class="component_input"
/>
`);
case "image":
return createElement(` <img id="${safe(id)}" src="${save(value)}" />`);
// case "file":
// return createElement() // TODO
default:
return createElement(`
<input
value="unknown element type ${type}"
type="text"
class="component_input"
path="${safe(path.join("."))}"
readonly
/>
`);
}
}
export function format(name) {
if (typeof name !== "string") {
return "N/A";
}
return name
.split("_")
.map((word) => {
if (word.length < 1) {
return word;
}
return word[0].toUpperCase() + word.substring(1);
})
.join(" ");
};