UNPKG

@taiga-ui/cdk

Version:

Base library for creating Angular components and applications using Taiga UI principles regarding of actual visual appearance

247 lines • 13.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.migrateComboBox = migrateComboBox; const insert_todo_1 = require("../../../../utils/insert-todo"); const elements_1 = require("../../../../utils/templates/elements"); const template_resource_1 = require("../../../../utils/templates/template-resource"); const control_state_attrs_1 = require("../../../utils/templates/control-state-attrs"); const replace_tag_1 = require("../../../utils/templates/replace-tag"); const DOCS_LINK = 'https://taiga-ui.dev/components/combo-box'; const CONTROL_ATTR_NAMES = [ 'formControlName', '[formControl]', 'formControl', '[(ngModel)]', '[ngModel]', 'ngModel', ]; const CONTROL_ATTRS = new Set(CONTROL_ATTR_NAMES.map((name) => name.toLowerCase())); const INPUT_ATTRS = new Set(['[strictMatcher]'.toLowerCase(), '[strict]']); const REMOVE_ATTRS = new Set([ '[tuiTextfieldLabelOutside]'.toLowerCase(), 'tuiTextfieldLabelOutside'.toLowerCase(), ]); function migrateComboBox({ resource, recorder, fileSystem, }) { const template = (0, template_resource_1.getTemplateFromTemplateResource)(resource, fileSystem); const templateOffset = (0, template_resource_1.getTemplateOffset)(resource); const elements = (0, elements_1.findElementsByTagName)(template, 'tui-combo-box'); elements.forEach((element) => { var _a, _b; const sourceCodeLocation = element.sourceCodeLocation; const controlAttrs = element.attrs.filter((attr) => CONTROL_ATTRS.has(attr.name.toLowerCase())); const inputAttrs = element.attrs.filter((attr) => INPUT_ATTRS.has(attr.name.toLowerCase())); const removeAttrs = element.attrs.filter((attr) => REMOVE_ATTRS.has(attr.name.toLowerCase())); const controlStateAttrs = (0, control_state_attrs_1.getControlStateAttrs)(element); const labelOutsideAttr = removeAttrs.find((attr) => REMOVE_ATTRS.has(attr.name.toLowerCase())); const searchAttr = element.attrs.find((attr) => attr.name.toLowerCase() === '[search]'); const searchChangeAttr = element.attrs.find((attr) => attr.name.toLowerCase() === '(searchChange)'.toLowerCase()); const valueContentAttr = element.attrs.find((attr) => attr.name.toLowerCase() === '[valueContent]'.toLowerCase()); for (const attr of [...controlAttrs, ...inputAttrs, ...removeAttrs]) { removeAttr(recorder, templateOffset, element, attr.name, template); } (0, control_state_attrs_1.removeControlStateAttrs)(recorder, templateOffset, element, template, controlStateAttrs); if (searchAttr) { removeAttr(recorder, templateOffset, element, searchAttr.name, template); } if (searchChangeAttr) { removeAttr(recorder, templateOffset, element, searchChangeAttr.name, template); } const addAttributes = []; if (valueContentAttr) { removeAttr(recorder, templateOffset, element, '[valueContent]', template); addAttributes.push('#textfieldRef', `[content]="textfieldRef.focused() ? '' : ${valueContentAttr.value}"`); } (0, replace_tag_1.replaceTag)(recorder, sourceCodeLocation, 'tui-combo-box', 'tui-textfield', template, templateOffset, addAttributes); if (searchAttr || searchChangeAttr) { const searchTodo = [ `<!-- ${insert_todo_1.TODO_MARK} tui-combo-box migration (see ${DOCS_LINK}):`, ' - [search] / (searchChange): use native (input) event on <input tuiComboBox>', '-->\n', ].join('\n'); const insertAt = ((_a = sourceCodeLocation === null || sourceCodeLocation === void 0 ? void 0 : sourceCodeLocation.startOffset) !== null && _a !== void 0 ? _a : 0) + templateOffset; recorder.insertLeft(insertAt, searchTodo); } const searchHandler = searchChangeAttr ? ` (input)="${searchChangeAttr.value.replaceAll('$event', '$event.target.value')}"` : ''; const inputs = element.childNodes.filter((node) => node.nodeName === 'input'); const isBinding = (_b = labelOutsideAttr === null || labelOutsideAttr === void 0 ? void 0 : labelOutsideAttr.name.startsWith('[')) !== null && _b !== void 0 ? _b : false; const isLabelOutsideTrue = (labelOutsideAttr === null || labelOutsideAttr === void 0 ? void 0 : labelOutsideAttr.value) === 'true' || (!!labelOutsideAttr && !isBinding && labelOutsideAttr.value === ''); const isLabelOutsideDynamic = !!labelOutsideAttr && !isLabelOutsideTrue && labelOutsideAttr.value !== 'false'; if (inputs.length) { handleExistingInput({ inputs, recorder, templateOffset, template, controlAttrs, inputAttrs, controlStateAttrs, searchHandler, placeholder: isLabelOutsideTrue ? getPlaceholderText(element) : '', }); if (!labelOutsideAttr || labelOutsideAttr.value === 'false') { wrapTextInLabel(recorder, templateOffset, element); } else if (isLabelOutsideTrue) { removeTextNode(recorder, templateOffset, element); } else if (isLabelOutsideDynamic) { addLabelOutsideTodo(recorder, templateOffset, element, template); } } else { if (!labelOutsideAttr || labelOutsideAttr.value === 'false') { wrapTextInLabel(recorder, templateOffset, element); } else if (isLabelOutsideDynamic) { addLabelOutsideTodo(recorder, templateOffset, element, template); } handleGeneratedInput({ element, recorder, templateOffset, controlAttrs, inputAttrs, controlStateAttrs, searchHandler, sourceCodeLocation, isLabelOutsideTrue, }); } }); } function handleExistingInput({ inputs, recorder, templateOffset, template, controlAttrs, inputAttrs, controlStateAttrs, searchHandler, placeholder, }) { inputs.forEach((input) => { var _a, _b, _c, _d, _e, _f; const legacyAttr = input.attrs.find((attr) => /^tuitextfieldlegacy$/i.test(attr.name)); if (legacyAttr) { const { startOffset = 0, endOffset = 0 } = (_c = (_b = (_a = input.sourceCodeLocation) === null || _a === void 0 ? void 0 : _a.attrs) === null || _b === void 0 ? void 0 : _b[legacyAttr.name]) !== null && _c !== void 0 ? _c : {}; const lineStart = template.lastIndexOf('\n', startOffset) + 1; const lineEnd = template.indexOf('\n', endOffset); const lineText = lineEnd === -1 ? '' : template.slice(lineStart, lineEnd); const attrText = template.slice(startOffset, endOffset); if (lineText.trim() === attrText.trim() && lineEnd !== -1) { recorder.remove(templateOffset + lineStart, lineEnd - lineStart + 1); } else { recorder.remove(templateOffset + startOffset, endOffset - startOffset); } } const insertOffset = ((_f = (_e = (_d = input.sourceCodeLocation) === null || _d === void 0 ? void 0 : _d.startTag) === null || _e === void 0 ? void 0 : _e.startOffset) !== null && _f !== void 0 ? _f : 0) + '<input'.length; const formAttrs = formatControlAttrs(controlAttrs); const inputAttrStr = formatInputAttrs(inputAttrs); const placeholderAttr = placeholder ? ` placeholder="${placeholder}"` : ''; const controlStateStr = (0, control_state_attrs_1.stringifyControlStateAttrs)(controlStateAttrs); recorder.insertRight(templateOffset + insertOffset, ` tuiComboBox${formAttrs}${inputAttrStr}${searchHandler}${placeholderAttr}${controlStateStr}`); }); } function handleGeneratedInput({ element, recorder, templateOffset, controlAttrs, inputAttrs, controlStateAttrs, searchHandler, sourceCodeLocation, isLabelOutsideTrue, }) { var _a, _b, _c, _d, _e, _f, _g, _h; const formAttrs = formatControlAttrs(controlAttrs); const inputAttrStr = formatInputAttrs(inputAttrs); const controlStateStr = (0, control_state_attrs_1.stringifyControlStateAttrs)(controlStateAttrs); const labelNode = findTextNode(element); if (isLabelOutsideTrue && labelNode) { const labelText = labelNode.value.trim(); const textStart = (_b = (_a = labelNode.sourceCodeLocation) === null || _a === void 0 ? void 0 : _a.startOffset) !== null && _b !== void 0 ? _b : 0; const textEnd = (_d = (_c = labelNode.sourceCodeLocation) === null || _c === void 0 ? void 0 : _c.endOffset) !== null && _d !== void 0 ? _d : 0; recorder.remove(templateOffset + textStart, textEnd - textStart); recorder.insertRight(templateOffset + textStart, `\n<input tuiComboBox${formAttrs}${inputAttrStr}${searchHandler} placeholder="${labelText}"${controlStateStr} />\n`); return; } const insertOffset = labelNode ? ((_f = (_e = labelNode.sourceCodeLocation) === null || _e === void 0 ? void 0 : _e.endOffset) !== null && _f !== void 0 ? _f : 0) : ((_h = (_g = sourceCodeLocation === null || sourceCodeLocation === void 0 ? void 0 : sourceCodeLocation.endTag) === null || _g === void 0 ? void 0 : _g.startOffset) !== null && _h !== void 0 ? _h : 0); recorder.insertRight(templateOffset + insertOffset, `\n<input tuiComboBox${formAttrs}${inputAttrStr}${searchHandler}${controlStateStr} />\n`); } function findTextNode(element) { return element.childNodes.find((node) => node.nodeName === '#text' && !!node.value.trim()); } function getPlaceholderText(element) { var _a, _b; return (_b = (_a = findTextNode(element)) === null || _a === void 0 ? void 0 : _a.value.trim()) !== null && _b !== void 0 ? _b : ''; } function removeTextNode(recorder, templateOffset, element) { var _a, _b, _c, _d; const labelNode = findTextNode(element); if (!labelNode) { return; } const textStart = (_b = (_a = labelNode.sourceCodeLocation) === null || _a === void 0 ? void 0 : _a.startOffset) !== null && _b !== void 0 ? _b : 0; const textEnd = (_d = (_c = labelNode.sourceCodeLocation) === null || _c === void 0 ? void 0 : _c.endOffset) !== null && _d !== void 0 ? _d : 0; recorder.remove(templateOffset + textStart, textEnd - textStart); } function addLabelOutsideTodo(recorder, templateOffset, element, template) { var _a, _b; const elementStart = (_b = (_a = element.sourceCodeLocation) === null || _a === void 0 ? void 0 : _a.startOffset) !== null && _b !== void 0 ? _b : 0; const lineStart = template.lastIndexOf('\n', elementStart - 1) + 1; const indent = template.slice(lineStart, elementStart); recorder.insertRight(templateOffset + elementStart, `<!-- ${insert_todo_1.TODO_MARK} [tuiTextfieldLabelOutside] is dynamic and cannot be migrated automatically. Use <label tuiLabel> inside <tui-textfield> for floating label or input[placeholder] for outside label -->\n${indent}`); } function wrapTextInLabel(recorder, templateOffset, element) { var _a, _b, _c, _d; const labelNode = findTextNode(element); if (!labelNode) { return; } const labelTextStart = ((_b = (_a = labelNode.sourceCodeLocation) === null || _a === void 0 ? void 0 : _a.startOffset) !== null && _b !== void 0 ? _b : 0) + templateOffset; const labelTextEnd = ((_d = (_c = labelNode.sourceCodeLocation) === null || _c === void 0 ? void 0 : _c.endOffset) !== null && _d !== void 0 ? _d : 0) + templateOffset; recorder.insertRight(labelTextStart, '\n<label tuiLabel>'); recorder.insertRight(labelTextEnd, '</label>\n'); } function removeAttr(recorder, templateOffset, element, name, template) { var _a, _b; const attrLocation = (_b = (_a = element.sourceCodeLocation) === null || _a === void 0 ? void 0 : _a.attrs) === null || _b === void 0 ? void 0 : _b[name.toLowerCase()]; if (!attrLocation) { return; } const lineStart = template.lastIndexOf('\n', attrLocation.startOffset) + 1; const lineEnd = template.indexOf('\n', attrLocation.endOffset); const attrText = template.slice(attrLocation.startOffset, attrLocation.endOffset); const lineText = lineEnd === -1 ? '' : template.slice(lineStart, lineEnd); if (lineText.trim() === attrText.trim() && lineEnd !== -1) { recorder.remove(templateOffset + lineStart, lineEnd - lineStart + 1); return; } recorder.remove(templateOffset + attrLocation.startOffset - 1, attrLocation.endOffset - attrLocation.startOffset + 1); } function formatControlAttrs(attrs) { return attrs .map(({ name, value }) => ` ${normalizeAttrName(name)}="${value}"`) .join(''); } function formatInputAttrs(attrs) { return attrs .map(({ name, value }) => { const attrName = name.toLowerCase() === '[strictMatcher]'.toLowerCase() ? '[matcher]' : normalizeAttrName(name); return ` ${attrName}="${value}"`; }) .join(''); } function normalizeAttrName(name) { switch (name.toLowerCase()) { case '[(ngModel)]'.toLowerCase(): return '[(ngModel)]'; case '[formControl]'.toLowerCase(): return '[formControl]'; case '[ngModel]'.toLowerCase(): return '[ngModel]'; case 'formControl'.toLowerCase(): return 'formControl'; case 'formControlName'.toLowerCase(): return 'formControlName'; case 'ngModel'.toLowerCase(): return 'ngModel'; case '[strict]': return '[strict]'; default: return name; } } //# sourceMappingURL=migrate-combo-box.js.map