@freshworks/crayons
Version:
Crayons Web Components library
389 lines (388 loc) • 15.7 kB
JavaScript
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
/* eslint-disable @typescript-eslint/no-explicit-any */
import { Component, Prop, h, Element, State, Method } from '@stencil/core';
import { hasSlot } from '../../utils';
import { TranslationController } from '../../global/Translation';
const NATIVE_CONTROLS = ['input', 'select', 'textarea'];
export class FormControl {
constructor() {
this.type = 'TEXT';
this.required = false;
this.hint = '';
this.placeholder = '';
this.choices = [];
/**
* Additional props can be passed here for crayons components. Useful when rendering crayons components implicitly via form-control.
*/
this.fieldProps = {};
this.touched = false;
this.error = '';
this.hasSlot = false;
}
renderControl() {
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v;
if (this.hasSlot)
return null;
if (!this.name)
return null;
let cmp;
switch (this.type) {
case 'TEXT':
case 'NUMBER':
case 'DECIMAL':
case 'EMAIL':
case 'TEL':
case 'URL': {
const type = this.type === 'DECIMAL' ? 'number' : (_a = this.type) === null || _a === void 0 ? void 0 : _a.toLowerCase();
const componentProps = Object.assign(Object.assign(Object.assign(Object.assign({}, this.fieldProps), { name: this.name, placeholder: this.placeholder, label: this.label, required: this.required, type: type }), (_b = this.controlProps) === null || _b === void 0 ? void 0 : _b.inputProps(this.name, type)), { state: (this.touched && this.error && 'error') || 'normal', ['hint-text']: this.hint, ['error-text']: TranslationController.t(this.error, {
field: this.label || this.name,
}) });
cmp = (h("fw-input", Object.assign({}, componentProps, { ref: (el) => (this.crayonsControlRef = el) })));
break;
}
case 'PARAGRAPH':
{
const componentProps = Object.assign(Object.assign(Object.assign(Object.assign({}, this.fieldProps), { name: this.name, placeholder: this.placeholder, label: this.label, required: this.required }), (_c = this.controlProps) === null || _c === void 0 ? void 0 : _c.inputProps(this.name, (_d = this.type) === null || _d === void 0 ? void 0 : _d.toLowerCase())), { state: (this.touched && this.error && 'error') || 'normal', ['hint-text']: this.hint, ['error-text']: TranslationController.t(this.error, {
field: this.label || this.name,
}) });
cmp = (h("fw-textarea", Object.assign({}, componentProps, { ref: (el) => (this.crayonsControlRef = el) })));
}
break;
case 'DATE':
{
const componentProps = Object.assign(Object.assign(Object.assign(Object.assign({}, this.fieldProps), { name: this.name, placeholder: this.placeholder, label: this.label, required: this.required }), (_e = this.controlProps) === null || _e === void 0 ? void 0 : _e.inputProps(this.name, (_f = this.type) === null || _f === void 0 ? void 0 : _f.toLowerCase())), { state: (this.touched && this.error && 'error') || 'normal', ['hint-text']: this.hint, ['error-text']: TranslationController.t(this.error, {
field: this.label || this.name,
}) });
cmp = (h("fw-datepicker", Object.assign({}, componentProps, { ref: (el) => (this.crayonsControlRef = el) })));
}
break;
case 'CHECKBOX':
{
const componentProps = Object.assign(Object.assign(Object.assign(Object.assign({}, this.fieldProps), { name: this.name, placeholder: this.placeholder, label: '', required: this.required }), (_g = this.controlProps) === null || _g === void 0 ? void 0 : _g.checkboxProps(this.name, (_h = this.type) === null || _h === void 0 ? void 0 : _h.toLowerCase())), { state: (this.touched && this.error && 'error') || 'normal', ['hint-text']: this.hint, ['error-text']: TranslationController.t(this.error, {
field: this.label || this.name,
}) });
cmp = (h("fw-checkbox", Object.assign({}, componentProps, { ref: (el) => (this.crayonsControlRef = el) }), this.label));
}
break;
case 'RADIO':
{
const controlProps = (_j = this.controlProps) === null || _j === void 0 ? void 0 : _j.radioProps(this.name, (_k = this.type) === null || _k === void 0 ? void 0 : _k.toLowerCase());
const componentProps = Object.assign(Object.assign(Object.assign({}, this.fieldProps), { 'name': this.name, 'placeholder': this.placeholder, 'label': this.label, 'required': this.required, 'allow-empty': true, 'state': (this.touched && this.error && 'error') || 'normal', ['hint-text']: this.hint, ['error-text']: TranslationController.t(this.error, {
field: this.label || this.name,
}) }), controlProps);
cmp = (h("fw-radio-group", Object.assign({}, componentProps, { ref: (el) => (this.crayonsControlRef = el) }), (_l = this.choices) === null || _l === void 0 ? void 0 : _l.map((ch) => {
const val = ch[componentProps.optionValuePath] || ch.value;
const label = ch[componentProps.optionLabelPath] || ch.value;
return (h("fw-radio", { name: this.name, value: val, state: this.touched && this.error ? 'error' : 'normal' }, label));
})));
}
break;
case 'DROPDOWN':
case 'MULTI_SELECT':
{
const controlProps = (_m = this.controlProps) === null || _m === void 0 ? void 0 : _m.selectProps(this.name, (_o = this.type) === null || _o === void 0 ? void 0 : _o.toLowerCase());
let componentProps = Object.assign(Object.assign({}, this.fieldProps), { name: this.name, placeholder: this.placeholder, label: this.label, required: this.required, multiple: this.type === 'MULTI_SELECT', state: (this.touched && this.error && 'error') || 'normal', ['hint-text']: this.hint, ['error-text']: TranslationController.t(this.error, {
field: this.label || this.name,
}) });
componentProps = Object.assign(Object.assign(Object.assign({}, componentProps), controlProps), { options: this.choices });
cmp = (h("fw-select", Object.assign({}, componentProps, { ref: (el) => (this.crayonsControlRef = el) })));
}
break;
case 'RELATIONSHIP':
{
const controlProps = (_p = this.controlProps) === null || _p === void 0 ? void 0 : _p.selectProps(this.name, (_q = this.type) === null || _q === void 0 ? void 0 : _q.toLowerCase());
const componentProps = Object.assign(Object.assign({}, this.fieldProps), { name: this.name, placeholder: this.placeholder, label: this.label, required: this.required, state: (this.touched && this.error && 'error') || 'normal', ['hint-text']: this.hint, ['error-text']: TranslationController.t(this.error, {
field: this.label || this.name,
}) });
if (Array.isArray(controlProps.value) &&
typeof controlProps.value[0] === 'object'
// handle multi_select, select [{}] initialValues
) {
componentProps.selectedOptions = controlProps.value;
}
if (((_r = componentProps.selectedOptions) === null || _r === void 0 ? void 0 : _r.length) > 0) {
(_s = this.crayonsControlRef) === null || _s === void 0 ? void 0 : _s.setSelectedOptions(componentProps.selectedOptions);
}
else if (!controlProps.value) {
(_t = this.crayonsControlRef) === null || _t === void 0 ? void 0 : _t.setSelectedOptions([]);
}
componentProps.noDataText =
TranslationController.t('search.startTyping');
cmp = (h("fw-select", Object.assign({}, componentProps, { ref: (el) => (this.crayonsControlRef = el) })));
}
break;
case 'TIME':
{
const componentProps = Object.assign(Object.assign(Object.assign(Object.assign({}, this.fieldProps), { name: this.name, placeholder: this.placeholder, label: this.label, required: this.required }), (_u = this.controlProps) === null || _u === void 0 ? void 0 : _u.inputProps(this.name, (_v = this.type) === null || _v === void 0 ? void 0 : _v.toLowerCase())), { state: (this.touched && this.error && 'error') || 'normal', ['hint-text']: this.hint, ['error-text']: TranslationController.t(this.error, {
field: this.label || this.name,
}) });
cmp = (h("fw-timepicker", Object.assign({}, componentProps, { ref: (el) => (this.crayonsControlRef = el) })));
}
break;
}
return cmp;
}
componentWillLoad() {
this.handleSlotChange();
}
/**
* Set Focus on the child
*/
async setFocus() {
var _a, _b, _c, _d;
if (!this.hasSlot) {
await ((_b = (_a = this.crayonsControlRef) === null || _a === void 0 ? void 0 : _a.setFocus) === null || _b === void 0 ? void 0 : _b.call(_a));
}
else {
(_d = (_c = this.slotElement) === null || _c === void 0 ? void 0 : _c.focus) === null || _d === void 0 ? void 0 : _d.call(_c);
}
}
handleSlotChange() {
var _a;
this.hasSlot = hasSlot(this.el);
this.slotElement = (_a = [...this.el.querySelectorAll('*')].filter((el) => {
var _a;
return NATIVE_CONTROLS.includes((_a = el === null || el === void 0 ? void 0 : el.tagName) === null || _a === void 0 ? void 0 : _a.toLowerCase());
})) === null || _a === void 0 ? void 0 : _a[0];
}
render() {
return (h("div", { class: 'form-control-container' },
this.renderControl(),
this.hasSlot && (h("label", { htmlFor: this.name, class: {
label: true,
required: this.required,
} }, this.label)),
h("slot", { onSlotchange: () => this.handleSlotChange() }),
this.hasSlot && !(this.touched && this.error) && (h("div", { class: 'hint', id: `hint-${this.name}` }, this.hint)),
this.hasSlot && this.touched && this.error && (h("div", { class: 'error', id: `error-${this.name}` }, TranslationController.t(this.error, {
field: this.label || this.name,
})))));
}
static get is() { return "fw-form-control"; }
static get encapsulation() { return "shadow"; }
static get originalStyleUrls() { return {
"$": ["form-control.scss"]
}; }
static get styleUrls() { return {
"$": ["form-control.css"]
}; }
static get properties() { return {
"type": {
"type": "string",
"mutable": false,
"complexType": {
"original": "| 'TEXT'\n | 'NUMBER'\n | 'DECIMAL'\n | 'DROPDOWN'\n | 'MULTI_SELECT'\n | 'RADIO'\n | 'CHECKBOX'\n | 'DATE'\n | 'PARAGRAPH'\n | 'EMAIL'\n | 'URL'\n | 'TEL'\n | 'TIME'\n | 'RELATIONSHIP'",
"resolved": "\"CHECKBOX\" | \"DATE\" | \"DECIMAL\" | \"DROPDOWN\" | \"EMAIL\" | \"MULTI_SELECT\" | \"NUMBER\" | \"PARAGRAPH\" | \"RADIO\" | \"RELATIONSHIP\" | \"TEL\" | \"TEXT\" | \"TIME\" | \"URL\"",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": ""
},
"attribute": "type",
"reflect": false,
"defaultValue": "'TEXT'"
},
"name": {
"type": "any",
"mutable": false,
"complexType": {
"original": "any",
"resolved": "any",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": ""
},
"attribute": "name",
"reflect": true
},
"label": {
"type": "any",
"mutable": false,
"complexType": {
"original": "any",
"resolved": "any",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": ""
},
"attribute": "label",
"reflect": false
},
"required": {
"type": "boolean",
"mutable": false,
"complexType": {
"original": "boolean",
"resolved": "boolean",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": ""
},
"attribute": "required",
"reflect": false,
"defaultValue": "false"
},
"hint": {
"type": "string",
"mutable": false,
"complexType": {
"original": "string",
"resolved": "string",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": ""
},
"attribute": "hint",
"reflect": false,
"defaultValue": "''"
},
"placeholder": {
"type": "string",
"mutable": false,
"complexType": {
"original": "string",
"resolved": "string",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": ""
},
"attribute": "placeholder",
"reflect": false,
"defaultValue": "''"
},
"choices": {
"type": "any",
"mutable": false,
"complexType": {
"original": "any",
"resolved": "any",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": ""
},
"attribute": "choices",
"reflect": false,
"defaultValue": "[]"
},
"fieldProps": {
"type": "any",
"mutable": true,
"complexType": {
"original": "any",
"resolved": "any",
"references": {}
},
"required": false,
"optional": true,
"docs": {
"tags": [],
"text": "Additional props can be passed here for crayons components. Useful when rendering crayons components implicitly via form-control."
},
"attribute": "field-props",
"reflect": false,
"defaultValue": "{}"
},
"controlProps": {
"type": "any",
"mutable": false,
"complexType": {
"original": "any",
"resolved": "any",
"references": {}
},
"required": false,
"optional": true,
"docs": {
"tags": [],
"text": "Contains values for crayons components. Useful when rendering crayons components implicitly via form-control.\nNot required when using controls via slots."
},
"attribute": "control-props",
"reflect": false
},
"touched": {
"type": "boolean",
"mutable": false,
"complexType": {
"original": "boolean",
"resolved": "boolean",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": ""
},
"attribute": "touched",
"reflect": false,
"defaultValue": "false"
},
"error": {
"type": "string",
"mutable": false,
"complexType": {
"original": "string",
"resolved": "string",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": ""
},
"attribute": "error",
"reflect": false,
"defaultValue": "''"
}
}; }
static get states() { return {
"hasSlot": {}
}; }
static get methods() { return {
"setFocus": {
"complexType": {
"signature": "() => Promise<void>",
"parameters": [],
"references": {
"Promise": {
"location": "global"
}
},
"return": "Promise<void>"
},
"docs": {
"text": "Set Focus on the child",
"tags": []
}
}
}; }
static get elementRef() { return "el"; }
}