element-book
Version:
An [`element-vir`](https://npmjs.com/package/element-vir) drop-in element for building, testing, and demonstrating a collection of elements (or, in other words, a design system).
188 lines (183 loc) • 6.78 kB
JavaScript
import { check } from '@augment-vir/assert';
import { VirColorPicker } from '@electrovir/color';
import { css, defineElementEvent, html, listen, renderIf } from 'element-vir';
import { Options24Icon, ViraCheckbox, ViraError, ViraIcon, ViraInput, ViraSelect, viraTheme, } from 'vira';
import { BookPageControlType, isControlInitType, } from '../../../../data/book-entry/book-page/book-page-controls.js';
import { defineBookElement } from '../../define-book-element.js';
export const BookPageControls = defineBookElement()({
tagName: 'book-page-controls',
events: {
controlValueChange: defineElementEvent(),
},
hostClasses: {
'book-page-controls-has-controls': ({ inputs }) => !!Object.keys(inputs.config).length,
},
styles: ({ hostClasses }) => css `
:host {
display: flex;
flex-wrap: wrap;
align-items: flex-end;
padding-left: 36px;
align-content: flex-start;
gap: 16px;
row-gap: 10px;
color: ${viraTheme.colors['vira-grey-foreground-placeholder'].foreground.value};
}
${hostClasses['book-page-controls-has-controls'].selector} {
margin-top: 8px;
}
.control-wrapper {
position: relative;
display: flex;
gap: 4px;
flex-direction: column;
}
${ViraInput}, ${ViraSelect} {
height: 24px;
max-width: 128px;
}
${ViraIcon}.options-icon {
position: absolute;
left: 0;
bottom: 0;
margin-left: -32px;
}
`,
render({ inputs, dispatch, events }) {
if (!Object.entries(inputs.config).length) {
return '';
}
return Object.entries(inputs.config).map(([controlName, controlInit,], index) => {
if (controlInit.controlType === BookPageControlType.Hidden) {
return '';
}
const controlInputTemplate = createControlInput(inputs.currentValues[controlName], controlInit, (newValue) => {
const fullUrlBreadcrumbs = check.isArray(inputs.fullUrlBreadcrumbs)
? inputs.fullUrlBreadcrumbs
: inputs.fullUrlBreadcrumbs[controlName];
if (!fullUrlBreadcrumbs) {
throw new Error(`Failed to find breadcrumbs from given control name: '${controlName}'`);
}
dispatch(new events.controlValueChange({
fullUrlBreadcrumbs,
newValues: {
/**
* Only include values for controls defined in the current
* config, not inherited parent values. This prevents
* overwriting parent controls with their inherited values.
*/
...Object.fromEntries(Object.keys(inputs.config).map((key) => [
key,
inputs.currentValues[key],
])),
[controlName]: newValue,
},
}));
});
return html `
<div class="control-wrapper">
${renderIf(index === 0, html `
<${ViraIcon.assign({
icon: Options24Icon,
})}
class="options-icon"
></${ViraIcon}>
`)}
<label class="control-wrapper">
<span>
${controlInit.controlType === BookPageControlType.Custom
? html `
`
: controlName}
</span>
${controlInputTemplate}
</label>
</div>
`;
});
},
});
function createControlInput(value, controlInit, valueChange) {
if (isControlInitType(controlInit, BookPageControlType.Hidden)) {
return '';
}
else if (isControlInitType(controlInit, BookPageControlType.Checkbox)) {
return html `
<${ViraCheckbox.assign({
value: !!value,
})}
${listen(ViraCheckbox.events.valueChange, (event) => {
valueChange(event.detail);
})}
></${ViraCheckbox}>
`;
}
else if (isControlInitType(controlInit, BookPageControlType.Color)) {
return html `
<${VirColorPicker.assign({
color: value,
})}
style=${css `
${VirColorPicker.cssVars['vir-color-picker-swatch-height'].name}: 24px;
${VirColorPicker.cssVars['vir-color-picker-swatch-width'].name}: 24px;
`}
${listen(VirColorPicker.events.colorChange, (event) => {
valueChange(event.detail);
})}
></${VirColorPicker}>
`;
}
else if (isControlInitType(controlInit, BookPageControlType.Text)) {
return html `
<${ViraInput.assign({
value,
showClearButton: true,
disableBrowserHelps: true,
})}
${listen(ViraInput.events.valueChange, (event) => {
valueChange(event.detail);
})}
></${ViraInput}>
`;
}
else if (isControlInitType(controlInit, BookPageControlType.Number)) {
return html `
<${ViraInput.assign({
value,
allowedInputs: /[\d.]/,
})}
${listen(ViraInput.events.valueChange, (event) => {
valueChange(event.detail);
})}
></${ViraInput}>
`;
}
else if (isControlInitType(controlInit, BookPageControlType.Dropdown)) {
return html `
<${ViraSelect.assign({
value,
options: controlInit.options.map((option) => {
return {
label: option,
value: option,
};
}),
})}
${listen(ViraSelect.events.valueChange, (event) => {
valueChange(event.detail);
})}
></${ViraSelect}>
`;
}
else if (isControlInitType(controlInit, BookPageControlType.Custom)) {
return controlInit.content;
}
else {
return html `
<${ViraError}>
${controlInit.controlType} controls are not implemented yet.
</${ViraError}>
`;
}
}