@blinkk/selective-edit
Version:
Selective structured text editor.
152 lines • 6.19 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.OptionMixin = exports.ColorsOrientation = void 0;
const lit_html_1 = require("lit-html");
const class_map_js_1 = require("lit-html/directives/class-map.js");
const if_defined_js_1 = require("lit-html/directives/if-defined.js");
const repeat_js_1 = require("lit-html/directives/repeat.js");
const style_map_js_1 = require("lit-html/directives/style-map.js");
/**
* Orientation for colors gradient.
*/
var ColorsOrientation;
(function (ColorsOrientation) {
ColorsOrientation["Vertical"] = "vertical";
ColorsOrientation["Horizontal"] = "horizontal";
ColorsOrientation["Slope"] = "slope";
})(ColorsOrientation = exports.ColorsOrientation || (exports.ColorsOrientation = {}));
function OptionMixin(Base) {
return class OptionClass extends Base {
ariaLabelForOptionDot(config, option) {
if (option.color) {
return option.color;
}
if (!option.gradient || !option.gradient.colors.length) {
return option.label;
}
return option.gradient.colors.join(', ');
}
classesForOptions(config, options) {
return {
selective__options: true,
'selective__options--color-hint': this.hasColorHints(options),
'selective__options--few': options.length > 4,
'selective__options--many': options.length > 11,
'selective__options--multi': config.isMulti || false,
};
}
classesForOption(config, option) {
return {
selective__options__option: true,
'selective__options__option--selected': config.isOptionSelected(option),
'selective__options__option--color-hint': Boolean(option.color),
'selective__options__option--color-hint-gradient': Boolean(option.gradient),
};
}
/**
* Are there color hints?
*/
hasColorHints(options) {
for (const option of options) {
if (option.color || option.gradient) {
return true;
}
}
return false;
}
stylesForOptionDot(config, option) {
if (option.color) {
return {
backgroundColor: option.color,
};
}
if (!option.gradient || !option.gradient.colors.length) {
return {};
}
const gradient = option.gradient;
let orientationAngle = '0deg';
if (gradient.orientation === ColorsOrientation.Horizontal) {
orientationAngle = '90deg';
}
else if (gradient.orientation === ColorsOrientation.Slope) {
orientationAngle = '45deg';
}
const isSmooth = gradient.isSmooth || false;
const breakpoints = [`${gradient.colors[0]} 0%`];
const numBreakpoints = isSmooth
? gradient.colors.length - 1
: gradient.colors.length;
let breakpoint = Math.floor(100 / numBreakpoints);
let lastColor = null;
for (const color of gradient.colors) {
if (!lastColor) {
lastColor = color;
continue;
}
if (!isSmooth) {
breakpoints.push(`${lastColor} ${breakpoint}%`);
}
breakpoints.push(`${color} ${breakpoint}%`);
breakpoint += breakpoint;
lastColor = color;
}
if (!isSmooth) {
breakpoints.push(`${gradient.colors[gradient.colors.length - 1]} 100%`);
}
return {
backgroundImage: `linear-gradient(${orientationAngle}, ${breakpoints.join(', ')})`,
};
}
templateColorSwatch(editor, data, config, option) {
if (!option.color && !option.gradient) {
return (0, lit_html_1.html) ``;
}
return (0, lit_html_1.html) `<div
class="selective__swatch"
aria-label=${this.ariaLabelForOptionDot(config, option)}
style=${(0, style_map_js_1.styleMap)(this.stylesForOptionDot(config, option))}
></div>`;
}
templateOption(editor, data, config, option) {
let icon = '';
if (config.isOptionSelected(option)) {
icon = config.isMulti ? 'check_box' : 'radio_button_checked';
}
else {
icon = config.isMulti
? 'check_box_outline_blank'
: 'radio_button_unchecked';
}
return (0, lit_html_1.html) `<div
class=${(0, class_map_js_1.classMap)(this.classesForOption(config, option))}
aria-checked=${config.isOptionSelected(option)}
data-value=${option.value}
tabindex="0"
role=${config.isMulti ? 'checkbox' : 'radio'}
@blur=${config.handleBlur}
@click=${config.handleInput}
@keypress=${(evt) => {
if (evt.code === 'Space') {
evt.preventDefault();
config.handleInput(evt);
}
}}
>
<span class="material-icons">${icon}</span>
${this.templateColorSwatch(editor, data, config, option)}
<label>${option.label || option.value || '(Empty)'}</label>
</div>`;
}
templateOptions(editor, data, config, options) {
// TODO: Convert to a different UI when there are a lot of options.
return (0, lit_html_1.html) `<div
class=${(0, class_map_js_1.classMap)(this.classesForOptions(config, options))}
role=${(0, if_defined_js_1.ifDefined)(config.isMulti ? undefined : 'radiogroup')}
>
${(0, repeat_js_1.repeat)(options, option => option.value, option => this.templateOption(editor, data, config, option))}
</div>`;
}
};
}
exports.OptionMixin = OptionMixin;
//# sourceMappingURL=option.js.map