diff --git a/example/indexTs.ts b/example/indexTs.ts index ce8f715..dfa4a3a 100644 --- a/example/indexTs.ts +++ b/example/indexTs.ts @@ -4,29 +4,15 @@ const dropdn = new CGSelect({ selector: '.cg-dropdown_one', placeholder: 'Выберите авто', items: [ + 'BMW', { - category: 'Russia', - categoryItems: [ - { - id: '28qwds', - title: 'Москва', - value: 0, - }, - , - 'Ростов-на-дону', - 'Саратов', - 'Волгоград', - 'Донецк', - ], - }, - { - category: 'USA', - categoryItems: ['Alabama', 'Texas', 'Colorado', 'Klirens', 'Los-Angeles'], - }, - { - category: 'France', - categoryItems: ['Paris'], + id: '213sade', + title: 'Opel', + value: 1, }, + 'Mersedes', + 'MAN', + 'max', ], styles: { head: { diff --git a/index.ts b/index.ts new file mode 100644 index 0000000..37a4489 --- /dev/null +++ b/index.ts @@ -0,0 +1,3 @@ +import { CGSelect } from './src/cg-selectTS'; + +export default CGSelect; diff --git a/package-lock.json b/package-lock.json index 724119e..e532c4b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "@parcel/optimizer-css": "^2.8.0", "@types/prettier": "^2.7.2", "gh-pages": "^4.0.0", + "typedoc": "^0.23.24", "typescript": "^4.9.4" }, "devDependencies": { @@ -3016,6 +3017,11 @@ "node": ">=6" } }, + "node_modules/jsonc-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", + "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==" + }, "node_modules/jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", @@ -3267,6 +3273,11 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, + "node_modules/lunr": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", + "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==" + }, "node_modules/make-dir": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", @@ -3328,7 +3339,6 @@ "version": "4.2.5", "resolved": "https://registry.npmjs.org/marked/-/marked-4.2.5.tgz", "integrity": "sha512-jPueVhumq7idETHkb203WDD4fMA3yV9emQ5vLwop58lu8bTclMghBWcYAavlDqIEMaisADinV1TooIFCfqOsYQ==", - "dev": true, "bin": { "marked": "bin/marked.js" }, @@ -3817,6 +3827,16 @@ "semver": "bin/semver" } }, + "node_modules/shiki": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.12.1.tgz", + "integrity": "sha512-aieaV1m349rZINEBkjxh2QbBvFFQOlgqYTNtCal82hHj4dDZ76oMlQIX+C7ryerBTDiga3e5NfH6smjdJ02BbQ==", + "dependencies": { + "jsonc-parser": "^3.2.0", + "vscode-oniguruma": "^1.7.0", + "vscode-textmate": "^8.0.0" + } + }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -3990,6 +4010,45 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/typedoc": { + "version": "0.23.24", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.23.24.tgz", + "integrity": "sha512-bfmy8lNQh+WrPYcJbtjQ6JEEsVl/ce1ZIXyXhyW+a1vFrjO39t6J8sL/d6FfAGrJTc7McCXgk9AanYBSNvLdIA==", + "dependencies": { + "lunr": "^2.3.9", + "marked": "^4.2.5", + "minimatch": "^5.1.2", + "shiki": "^0.12.1" + }, + "bin": { + "typedoc": "bin/typedoc" + }, + "engines": { + "node": ">= 14.14" + }, + "peerDependencies": { + "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x" + } + }, + "node_modules/typedoc/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/typedoc/node_modules/minimatch": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.2.tgz", + "integrity": "sha512-bNH9mmM9qsJ2X4r2Nat1B//1dJVcn3+iBLa3IgqJ7EbGaDNepL9QSHOxN4ng33s52VMMhhIfgCYDk3C4ZmlDAg==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/typescript": { "version": "4.9.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz", @@ -4061,6 +4120,16 @@ "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", "dev": true }, + "node_modules/vscode-oniguruma": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", + "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==" + }, + "node_modules/vscode-textmate": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-8.0.0.tgz", + "integrity": "sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==" + }, "node_modules/weak-lru-cache": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/weak-lru-cache/-/weak-lru-cache-1.2.2.tgz", @@ -6064,6 +6133,11 @@ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==" }, + "jsonc-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", + "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==" + }, "jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", @@ -6198,6 +6272,11 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, + "lunr": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", + "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==" + }, "make-dir": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", @@ -6244,8 +6323,7 @@ "marked": { "version": "4.2.5", "resolved": "https://registry.npmjs.org/marked/-/marked-4.2.5.tgz", - "integrity": "sha512-jPueVhumq7idETHkb203WDD4fMA3yV9emQ5vLwop58lu8bTclMghBWcYAavlDqIEMaisADinV1TooIFCfqOsYQ==", - "dev": true + "integrity": "sha512-jPueVhumq7idETHkb203WDD4fMA3yV9emQ5vLwop58lu8bTclMghBWcYAavlDqIEMaisADinV1TooIFCfqOsYQ==" }, "mdn-data": { "version": "2.0.14", @@ -6585,6 +6663,16 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" }, + "shiki": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.12.1.tgz", + "integrity": "sha512-aieaV1m349rZINEBkjxh2QbBvFFQOlgqYTNtCal82hHj4dDZ76oMlQIX+C7ryerBTDiga3e5NfH6smjdJ02BbQ==", + "requires": { + "jsonc-parser": "^3.2.0", + "vscode-oniguruma": "^1.7.0", + "vscode-textmate": "^8.0.0" + } + }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -6711,6 +6799,35 @@ "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true }, + "typedoc": { + "version": "0.23.24", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.23.24.tgz", + "integrity": "sha512-bfmy8lNQh+WrPYcJbtjQ6JEEsVl/ce1ZIXyXhyW+a1vFrjO39t6J8sL/d6FfAGrJTc7McCXgk9AanYBSNvLdIA==", + "requires": { + "lunr": "^2.3.9", + "marked": "^4.2.5", + "minimatch": "^5.1.2", + "shiki": "^0.12.1" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.2.tgz", + "integrity": "sha512-bNH9mmM9qsJ2X4r2Nat1B//1dJVcn3+iBLa3IgqJ7EbGaDNepL9QSHOxN4ng33s52VMMhhIfgCYDk3C4ZmlDAg==", + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, "typescript": { "version": "4.9.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz", @@ -6753,6 +6870,16 @@ "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", "dev": true }, + "vscode-oniguruma": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", + "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==" + }, + "vscode-textmate": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-8.0.0.tgz", + "integrity": "sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==" + }, "weak-lru-cache": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/weak-lru-cache/-/weak-lru-cache-1.2.2.tgz", diff --git a/package.json b/package.json index cec7f93..9b9c8b7 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "homepage": "https://cg-select.itguild.info", "scripts": { "start": "parcel example/index.html -p 4500 --open ", - "build": "parcel build index.js", + "build": "parcel build index.ts", "deploy": "gh-pages -d dist", "predeploy": "npm run build" }, @@ -31,6 +31,7 @@ "@parcel/optimizer-css": "^2.8.0", "@types/prettier": "^2.7.2", "gh-pages": "^4.0.0", + "typedoc": "^0.23.24", "typescript": "^4.9.4" }, "keywords": [ diff --git a/src/cg-selectTS.js b/src/cg-selectTS.js new file mode 100644 index 0000000..d98807b --- /dev/null +++ b/src/cg-selectTS.js @@ -0,0 +1,839 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (g && (g = 0, op[0] && (_ = 0)), _) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +exports.__esModule = true; +exports.CGSelect = void 0; +var create_elementTs_1 = require("./components/create-element/create-elementTs"); +var utilsTs_1 = require("./components/utils/utilsTs"); +var languageTS_1 = require("./language/languageTS"); +require("./main.scss"); +/** + * @class Описание класса ICgSelect + * @description Этот класс реализовывает функционал кастомного селекта, с возможностями кастомизации. + * @author Овсяников Максим + */ +var CGSelect = /** @class */ (function () { + /** + * @param {ICgSelect} setting Объект принимающий настройки селекта + * @constructor Конструктор класса DropDown + * @description Конструктор принимает объект и рендерит селект. + * @example + * options = { + * selector: 'Уникальный селектор', + selected: 'Выбранный элемент', + placeholder: '...', + lable: '...' + items: [string|number|object], + darkTheme: true/false, + searchMode: true/false, + closeOnSelect: true/false, + nativeSelectMode: true/false, + listDisplayMode: true/false, + language: 'ru/en', + styles: { + head: { + background: '...', + }, + list: {...}, + chips: {...}, + caret: {...}, + placeholder: {...}, + lable: {..}, + }, + event: '...', + url: 'http/...', + multiselect: true/false, + multiselectTag: true/false, + * } + */ + function CGSelect(setting) { + /** + * Массив индексов выбранных элементов + * @type {number[]} + */ + this.indexes = []; + this.init(setting); + this.render(); + this.closeSelectClick(); + this.initEvent(); + } + Object.defineProperty(CGSelect.prototype, "value", { + //Getters + /** + * Метод экземпляра класса DropDown + * @returns {string[] | string} Возвращает выбранные элемент(ы) в виде массива/элемента/null + * @description Геттер возвращающий выбранные элемент(ы) селекта + */ + get: function () { + var _a; + return (_a = this.selectedItems) !== null && _a !== void 0 ? _a : null; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(CGSelect.prototype, "indexesOf", { + /** + * Метод экземпляра класса DropDown + * @returns {number | number[]}Возвращает индексы выбранных элемента(ов) в виде массива/пустой массив + * @description Геттер возвращающий индексы выбранных элемента(ов) селекта + */ + get: function () { + var _a; + return (_a = this.indexes) !== null && _a !== void 0 ? _a : []; + }, + enumerable: false, + configurable: true + }); + /** + * Приватный метод инициализации экземпляра класса DropDown + * @method init + * @member + * @protected + * @param {ISgSelect} setting передаваемые настройки селекта + * @description Приватный метод. Общая инициализация селекта. Получение настоек и преобразвание элементов селекта. + * @example + * { + selector: '.cg-dropdown_one', + placeholder: 'Выберите авто', + items: [ + 'BMW', + { + id: '213sade', + title: 'Opel', + value: 1, + }, + 'Mersedes', + 'MAN', + 'max', + ], + darkTheme: true, + multiselect: true, + multiselectTag: true, + } + */ + CGSelect.prototype.init = function (setting) { + var _this = this; + var _a; + var items = setting.items, multiselect = setting.multiselect, multiselectTag = setting.multiselectTag, url = setting.url, selector = setting.selector, listDisplayMode = setting.listDisplayMode, nativeSelectMode = setting.nativeSelectMode, searchMode = setting.searchMode, darkTheme = setting.darkTheme, language = setting.language, styles = setting.styles, lable = setting.lable, event = setting.event, selected = setting.selected, placeholder = setting.placeholder; + this.options = setting; + this.multiselect = multiselect; + this.multiselectTag = multiselectTag; + this.url = url; + this.selector = selector; + this.items = items; + this.searchMode = searchMode; + this.darkTheme = darkTheme; + this.language = language; + this.nativeSelectMode = nativeSelectMode; + this.listDisplayMode = listDisplayMode; + this.styles = styles; + this.lable = lable; + this.event = event; + this.selected = selected; + this.placeholder = placeholder; + var elem = document.querySelector(this.selector); + this.element = elem; + (_a = this.element) === null || _a === void 0 ? void 0 : _a.addEventListener('click', function (e) { + e.preventDefault(); + _this.open(); + }); + this.items = []; + if (!this.items && this.url) { + this.renderUrl(); + return; + } + utilsTs_1.createSelected; + items.forEach(function (dataItem, index) { + var itemInputs = { + ItemValue: dataItem, + category: dataItem.category, + categoryItems: dataItem.categoryItems + }; + if (itemInputs.category && itemInputs.categoryItems) { + _this.category = itemInputs.category; + _this.items.push(_this.category); + itemInputs.categoryItems.forEach(function (categoryItem, indexCategory) { + _this.items.push((0, utilsTs_1.getFormatItem)(categoryItem, indexCategory)); + }); + } + else { + _this.items.push((0, utilsTs_1.getFormatItem)(itemInputs.ItemValue, index)); + } + }); + }; + /** + * Приватный метод рендера экземпляра класса DropDown + * @protected + * @method render + * @param {string} select необязательный елемент. Передаеться в метод initSelected + * @description Рендер елементов в селекте. + */ + CGSelect.prototype.render = function (select) { + var _this = this; + var _a, _b; + var random = Math.random().toString(36).substring(2, 10); + if (select || (select && this.styles)) { + this.initSelected(select); + (0, utilsTs_1.customStyles)(this.element, this.styles); + } + else { + this.initSelected(); + } + var ulList = document.createElement('ul'); + var nativeSelect = (0, create_elementTs_1.createNativeSelect)(); + var inputSearch; + var textNode; + this.randomId = random; + ulList.classList.add('list'); + if (this.styles) { + (0, utilsTs_1.customStylesFormat)(this.styles.list, ulList); + } + if (this.searchMode) { + if (this.language === 'ru') { + inputSearch = (0, create_elementTs_1.createInputSearch)(random, languageTS_1.ru.placeholder); + } + else { + inputSearch = (0, create_elementTs_1.createInputSearch)(random, languageTS_1.en.placeholder); + } + (0, utilsTs_1.customStylesFormat)((_a = this.styles) === null || _a === void 0 ? void 0 : _a.search, inputSearch); + ulList.appendChild(inputSearch); + } + (_b = this.element) === null || _b === void 0 ? void 0 : _b.appendChild(ulList); + this.items.forEach(function (dataItem) { + var _a; + (_a = _this.element) === null || _a === void 0 ? void 0 : _a.appendChild(nativeSelect); + var liItem = document.createElement('li'); + var nativeOption = (0, create_elementTs_1.createNativeSelectOption)(); + var strongItem = document.createElement('strong'); + liItem.classList.add('list__item'); + strongItem.classList.add('category'); + if (_this.multiselect) { + var checkBox = document.createElement('input'); + checkBox.type = 'checkbox'; + checkBox.setAttribute('id', "chbox-".concat(dataItem.id)); + liItem.appendChild(checkBox); + if (_this.multiselectTag) { + checkBox.classList.add('displayHide'); + } + nativeSelect.setAttribute('multiple', 'multiple'); + } + if (dataItem.title) { + nativeOption.text = dataItem.title; + nativeOption.value = dataItem.title; + textNode = document.createTextNode(dataItem.title); + nativeSelect.appendChild(nativeOption); + liItem.appendChild(textNode); + ulList.appendChild(liItem); + } + else { + // Для отрисовки категорий + textNode = document.createTextNode(dataItem); + strongItem.appendChild(textNode); + ulList.appendChild(strongItem); + } + }); + this.items.filter(function (item, index) { + if (typeof item !== 'object') { + _this.items.splice(index, 1); + } + return item; + }); + this.list = this.element.querySelector('.list'); + this.caret = this.element.querySelector('.caret'); + if (this.darkTheme == false) { + this.checkTheme(); + } + if (this.nativeSelectMode === true) { + this.selectMode(this.nativeSelectMode); + } + if (this.listDisplayMode) { + this.displayMode(this.listDisplayMode); + } + this.addOptionsBehaviour(); + }; + /** + * Приватный метод рендера экземпляра класса DropDown + * @protected + * @method renderUrl + * @description Рендер елементов в селекте переданных с URL и их настойка + */ + CGSelect.prototype.renderUrl = function () { + return __awaiter(this, void 0, void 0, function () { + var response, dataUrl, nativeSelect; + var _this = this; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + if (this.items || !this.url) { + return [2 /*return*/]; + } + return [4 /*yield*/, fetch(this.url)]; + case 1: + response = _a.sent(); + return [4 /*yield*/, response.json()]; + case 2: + dataUrl = _a.sent(); + nativeSelect = (0, create_elementTs_1.createNativeSelect)(); + dataUrl.forEach(function (dataItem, index) { + var item = { + id: dataItem.id, + title: dataItem.title, + value: index + }; + var ulUrl = _this.element.querySelector('.list'); + var nativeOption = (0, create_elementTs_1.createNativeSelectOption)(); + var liUrl = document.createElement('li'); + var textUrl = document.createTextNode(item.title); + if (_this.multiselect) { + var checkBox = document.createElement('input'); + checkBox.type = 'checkbox'; + if (_this.multiselectTag) { + checkBox.classList.add('displayHide'); + } + checkBox.setAttribute('id', "chbox-".concat(item.id)); + nativeSelect.setAttribute('multiple', 'multiple'); + liUrl.appendChild(checkBox); + } + liUrl.classList.add('list__item'); + nativeOption.value = item.title; + nativeOption.text = item.title; + nativeSelect.appendChild(nativeOption); + liUrl.appendChild(textUrl); + ulUrl.appendChild(liUrl); + _this.items.push(item); + }); + this.element.appendChild(nativeSelect); + this.items.filter(function (item, index) { + if (typeof item !== 'object') { + _this.items.splice(index, 1); + } + return item; + }); + this.addOptionsBehaviour(); + return [2 /*return*/]; + } + }); + }); + }; + /** + * Привaтный метод экземпляра класса DropDown + * @method initSelected + * @param {string} select необязательный елемент. Используется в методе selectIndex + * @description Отрисовывает и стилизует селект + * @protected + */ + CGSelect.prototype.initSelected = function (select) { + if (this.selected) { + (0, utilsTs_1.createSelected)(this.element, this.selected); + } + else if (this.placeholder) { + (0, utilsTs_1.createSelected)(this.element, this.placeholder); + } + else { + if (this.language && this.language === 'ru') { + (0, utilsTs_1.createSelected)(this.element, languageTS_1.ru.selectPlaceholder); + } + else { + (0, utilsTs_1.createSelected)(this.element, languageTS_1.en.selectPlaceholder); + } + } + if (select) { + (0, utilsTs_1.createSelected)(this.element, select, this.styles); + } + if (this.lable) { + var lableItem = document.createElement('h1'); + var textLable = document.createTextNode(this.lable); + lableItem.appendChild(textLable); + lableItem.classList.add('label'); + this.element.insertAdjacentElement('beforebegin', lableItem); + } + if (this.styles) { + (0, utilsTs_1.customStyles)(this.element, this.styles); + } + }; + /** + * Приватный метод экземпляра класса DropDown + * @protected + * @description Открывает и закрывает список по переданному эвенту + * @method initEvent + */ + CGSelect.prototype.initEvent = function () { + var _this = this; + if (!this.event) { + return; + } + if (this.event) { + if (this.event === 'mouseenter') { + this.element.addEventListener(this.event, function () { + _this.open(); + }); + this.element.addEventListener('mouseleave', function () { + _this.close(); + }); + } + } + }; + /** + * Приватный метод экземпляра класса DropDown + * @protected + * @param {boolean} oneClick необязательный параметр передаваемый из функции buttonControl + * @description Открывает список для выбора элемента + * @method open + */ + CGSelect.prototype.open = function (oneClick) { + if (oneClick === true) { + this.list.classList.add('open'); + this.caret.classList.add('caret_rotate'); + } + else { + this.list.classList.toggle('open'); + this.caret.classList.toggle('caret_rotate'); + } + }; + /** + * Приватный метод экземпляра класса DropDown + * @protected + * @description Закрывает список + * @method close + */ + CGSelect.prototype.close = function () { + var _a, _b; + (_a = this.list) === null || _a === void 0 ? void 0 : _a.classList.remove('open'); + (_b = this.caret) === null || _b === void 0 ? void 0 : _b.classList.remove('caret_rotate'); + }; + /** + * Приватный метод экземпляра класса DropDown + * @protected + * @description Закрывает список по клику вне элемента + * @method closeSelectClick + */ + CGSelect.prototype.closeSelectClick = function () { + var _this = this; + var dropdown = document.querySelector("".concat(this.options.selector)); + document.addEventListener('click', function (e) { + var withinBoundaries = e.composedPath().includes(dropdown); + if (!withinBoundaries) { + if (_this.btnCntr) { + return; + } + else { + _this.close(); + } + } + }); + }; + /** + * Приватный метод экземпляра класса DropDown + * @protected + * @description Метод реализовывающий выбор элементов в разных режимах. Обычный/Мультиселект/Мультиселект + Мультиселект Таг. + * @method addOptionsBehaviour + */ + CGSelect.prototype.addOptionsBehaviour = function () { + var _this = this; + var _a, _b; + var options = (_a = this.element) === null || _a === void 0 ? void 0 : _a.querySelectorAll('.list__item'); + var select = (_b = this.element) === null || _b === void 0 ? void 0 : _b.querySelector('.selected'); + var nativeOption = this.element.querySelectorAll('.nativeSelect__nativeOption'); + var selectedItemsClear; + var ulMultipul = document.createElement('ul'); + if (this.multiselect) { + this.selectedItems = []; + ulMultipul.classList.add('multiselect-tag'); + select === null || select === void 0 ? void 0 : select.classList.add('overflow-hidden'); + } + if (this.searchMode) { + this.searchModeSelect(this.randomId); + } + options === null || options === void 0 ? void 0 : options.forEach(function (option, index) { + option.addEventListener('click', function (event) { + if (Array.isArray(_this.selectedItems)) { + selectedItemsClear = { + placeholder: _this.placeholder, + selected: _this.selected, + selectedItems: _this.selectedItems, + indexes: _this.indexes, + darkTheme: _this.darkTheme, + multiselectTag: _this.multiselectTag + }; + } + var item = _this.items[index]; + var checkIndex = _this.indexes.indexOf(index); + if (_this.closeOnSelect == false || _this.multiselect) { + event.stopPropagation(); + event.preventDefault(); + } + if (_this.multiselect) { + option.classList.toggle('active'); + var checkBox = option.querySelector('input[type="checkbox"]'); + if (checkBox) { + if (!(event.target instanceof HTMLInputElement)) { + checkBox.checked = !checkBox.checked; + } + if (checkIndex == -1) { + _this.indexes.push(index); + (0, utilsTs_1.nativeOptionMultiple)(nativeOption, item.title, true); + select.textContent = ''; + if (_this.multiselectTag) { + if (Array.isArray(_this.selectedItems)) { + var dataBreadCrumb = { + option: _this.options, + element: _this.element, + indexes: _this.indexes, + selectedItems: _this.selectedItems + }; + _this.selectedItems.push(item.title); + select.appendChild(ulMultipul); + ulMultipul.appendChild((0, create_elementTs_1.createBreadCrumb)(dataBreadCrumb, item.title, index, item.id)); + } + } + else { + if (Array.isArray(_this.selectedItems)) { + _this.selectedItems.push(item.title); + select.innerText = _this.selectedItems.join(','); + } + } + } + else { + if (_this.multiselectTag) { + var tagItem = document.getElementById("tag-".concat(index, "-").concat(item.id)); + ulMultipul.removeChild(tagItem); + } + if (Array.isArray(_this.selectedItems)) { + _this.selectedItems.splice(checkIndex, 1); + _this.indexes.splice(checkIndex, 1); + (0, utilsTs_1.nativeOptionMultiple)(nativeOption, item.title, false); + } + } + if (!_this.selectedItems.length) { + (0, utilsTs_1.getSelectText)(selectedItemsClear, select); + } + else { + if (_this.multiselectTag) { + select.appendChild(ulMultipul); + } + else { + if (Array.isArray(_this.selectedItems)) { + select.innerText = _this.selectedItems.join(','); + } + } + } + } + } + else { + select.textContent = item.title; + _this.selectedItems = item.title; + (0, utilsTs_1.nativeOptionOrdinary)(nativeOption, item.title); + options.forEach(function (option) { + option.classList.remove('active'); + }); + option.classList.add('active'); + } + (0, utilsTs_1.clearSelect)(select, _this.element, selectedItemsClear); + }); + }); + }; + /** + * Приватный метод рендера экземпляра класса DropDown + * @protected + * @method #checkTheme + * @description Изменяет цветовую схему с темной на светлую. + */ + CGSelect.prototype.checkTheme = function () { + var select = this.element.querySelector('.cg-select'); + var caret = this.element.querySelector('.caret'); + var list = this.element.querySelector('ul.list'); + var search = this.element.querySelector('.inputSearch'); + if (this.darkTheme == false) { + select.classList.add('selectWhite'); + caret.classList.add('caretWhite'); + list.classList.add('listWhite'); + if (this.searchMode == true) { + search.classList.add('inputWhite'); + } + } + else if (this.darkTheme == true) { + return; + } + else { + throw new Error('Styles error or invalid value entered!'); + } + }; + /** + * Приватный метод экземпляра класса DropDown + * @protected + * @param {boolean} nativeSelectMode параметр отвечающий за добавления нативного селекта. + * @description Изменяет отображение селекта на мобильных устройствах + * @method selectMode + */ + CGSelect.prototype.selectMode = function (nativeSelectMode) { + var win = window.outerWidth; + if (nativeSelectMode === true) { + var select = this.element.querySelector('.cg-select'); + var list = this.element.querySelector('.list'); + var nativeSelect = this.element.querySelector('.nativeSelect'); + if (win < 576) { + select.classList.add('displayHide'); + list.classList.add('displayHide'); + nativeSelect.classList.add('nativeSelectActive'); + } + else if (win > 576) { + select.classList.remove('displayHide'); + list.classList.remove('displayHide'); + nativeSelect.classList.remove('nativeSelectActive'); + nativeSelect.classList.add('displayHide'); + } + } + else { + return; + } + }; + /** + * Метод который реализует поиск элементов в селекте + * @protected + * @param {string} random уникальное значение для input элемента. + * @method searchMode + */ + CGSelect.prototype.searchModeSelect = function (random) { + var input = this.element.querySelector("#searchSelect-".concat(random)); + var searchSelect = this.element.querySelectorAll('.list__item'); + var result = document.createElement('p'); + var textNode; + if (this.language && this.language === 'ru') { + textNode = document.createTextNode("".concat(languageTS_1.ru.textInListSearch)); + } + else { + textNode = document.createTextNode("".concat(languageTS_1.en.textInListSearch)); + } + result.appendChild(textNode); + result.classList.add('displayHide'); + result.classList.add('noRezult'); + input.parentElement.appendChild(result); + input.addEventListener('click', function (e) { + e.stopPropagation(); + }); + if (input instanceof HTMLInputElement) { + input.oninput = function () { + var valueSearch = input.value.trim().toLowerCase(); + var anyMatch = false; + if (valueSearch != '') { + searchSelect.forEach(function (elem) { + var isMatching = new RegExp(valueSearch, 'gi').test(elem.textContent); + anyMatch = anyMatch || isMatching; + if (elem.textContent.toLowerCase().search(valueSearch) == -1) { + elem.classList.add('displayHide'); + } + else { + elem.classList.remove('displayHide'); + } + }); + result.classList.toggle('displayHide', anyMatch); + } + else { + searchSelect.forEach(function (elem) { + elem.classList.remove('displayHide'); + result.classList.add('displayHide'); + }); + } + }; + } + }; + /** + * Приватный метод экземпляра класса DropDown + * @protected + * @param {boolean} listDisplayMode параметр отвечающий за отображение выбора в виде модального окна. + * @description Изменяет отображение листа с выбором в виде модального окна. + * @method displayMode + */ + CGSelect.prototype.displayMode = function (listDisplayMode) { + if (listDisplayMode) { + var modal_1 = document.createElement('div'); + var body_1 = document.querySelector('body'); + var list_1 = this.list; + modal_1.appendChild(list_1); + this.element.appendChild(modal_1); + this.element.addEventListener('click', function () { + modal_1.classList.toggle('modal'); + list_1.classList.toggle('listModal'); + body_1.classList.toggle('overflowHide'); + }); + } + else { + return; + } + }; + // Public methods + /** + * Метод экземпляра класса DropDown + * @param {number} numberItem номер возвращаемого элемента + * @returns {HTMLElement} возвращает ссылку на выбранный HTML элемент + * @method getElement + */ + CGSelect.prototype.getElement = function (numberItem) { + if (numberItem > this.items.length) { + return; + } + return this.items[numberItem]; + }; + /** + * Метод экземпляра класса DropDown + * @param {object} language объект в котором находятся поля для подключения языка имеет два обязательных поля placeholder, textInListSearch + * @description метод позволяющий заменить плейсхолдер в поиске и текст который выводится если нет результата + * @method addLanguage + */ + CGSelect.prototype.addLanguage = function (language) { + var placeholder = language.placeholder, textInListSearch = language.textInListSearch, selectPlaceholder = language.selectPlaceholder; + var select = this.element.querySelector('.selected'); + var textNodeSelect = document.createTextNode(selectPlaceholder); + select.appendChild(textNodeSelect); + if (this.searchMode) { + var search = this.element.querySelector('.inputSearch'); + var textNoRezult = this.element.querySelector('.noRezult'); + var textNode = document.createTextNode(textInListSearch); + search.setAttribute('placeholder', placeholder); + search.setAttribute('placeholder', placeholder); + textNoRezult.textContent = ''; + textNoRezult.appendChild(textNode); + } + }; + /** + * Метод экземпляра класса DropDown + * @param {HTMLInputElement} button - HTML кнопка + * @param {string} method - метод открытия open/close + * @description Метод позволяющий открывать/закрывать селект с помощью кнопок + * @method buttonControl + */ + CGSelect.prototype.buttonControl = function (button, method) { + var _this = this; + if (this.listDisplayMode) { + return; + } + this.btnCntr = button; + button.addEventListener('click', function () { + if (method.toLowerCase() === 'open') { + _this.open(true); + } + else if (method.toLowerCase() === 'close') { + _this.close(); + } + else { + return; + } + }); + }; + /** + * Метод экземпляра класса DropDown + * @param {boolean} value - Передаваемый параметр для добавления атрибута disabled; + * @description Метод позволяющий переключать состояние селекта disabled, + * @method disabled + */ + CGSelect.prototype.disabled = function (value) { + var select = this.element.querySelector('.cg-select'); + var nativeSelect = this.element.querySelector('.nativeSelect'); + if (value === true) { + this.element.setAttribute('disabled', 'true'); + nativeSelect.setAttribute('disabled', 'true'); + select.classList.add('disabled'); + } + else { + this.element.removeAttribute('disabled'); + nativeSelect.removeAttribute('disabled'); + select.classList.remove('disabled'); + } + }; + /** + * Метод экземпляра класса DropDown + * @param {string | object} item добавляемый елемент + * @description добавляет переданный элемент в конец списка и перерисовывает список. Не может использоваться при передачи элементов с категорями + * @method addItem + */ + CGSelect.prototype.addItem = function (item) { + if (this.category) { + console.log('can`t add item to category'); + return; + } + if (!item) { + return false; + } + var index = this.items.length; + this.items.push((0, utilsTs_1.getFormatItem)(item, index)); + this.render(); + }; + /** + * Метод экземпляра класса DropDown + * @param {number} index индекс удаляемого элемента + * @description удаляет елемент по индексу из списка и перерисовывает его. Не может использоваться при передачи элементов с категорями. + * @method deleteItem + */ + CGSelect.prototype.deleteItem = function (index) { + if (this.category) { + console.log('can`t add item to category'); + return; + } + var item = this.items[index]; + this.items.splice(index, 1); + this.render(); + }; + /** + * Метод экземпляра класса DropDown + * @description удаляет все елементы из списка и перерисовывает его. + * @method deleteItemAll + */ + CGSelect.prototype.deleteItemAll = function () { + this.items.splice(0, this.items.length); + this.render(); + }; + /** + * Метод экземпляра класса DropDown + * @param {number} index индекс выбранного элемента + * @description выбирает элемент который будет изначально отрисовываться в селекте + * @method selectIndex + */ + CGSelect.prototype.selectIndex = function (index) { + if (this.category) { + console.log('can`t add item to category'); + return; + } + var options = this.element.querySelectorAll('.list__item'); + if (index > options.length) { + return; + } + var select = options[index].innerText; + this.render(select); + }; + return CGSelect; +}()); +exports.CGSelect = CGSelect; diff --git a/src/cg-selectTS.ts b/src/cg-selectTS.ts index a29265f..faa5e46 100644 --- a/src/cg-selectTS.ts +++ b/src/cg-selectTS.ts @@ -25,8 +25,14 @@ import { ILanguage } from './interfaces/language.interface'; import './main.scss'; +/** + * @class Описание класса ICgSelect + * @description Этот класс реализовывает функционал кастомного селекта, с возможностями кастомизации. + * @author Овсяников Максим + */ export class CGSelect implements ICgSelect { // Настройки селекта + selector: string; selected?: string; placeholder?: string; @@ -45,16 +51,86 @@ export class CGSelect implements ICgSelect { multiselectTag?: boolean; // Переменные и комплектующие селекта + + /** + * Созданный HTML елемент + * @type {Element | null} + */ private element: Element | null; + /** + * Созданный список(ul), с классом list + * @type {Element | null | undefined} + */ private list: Element | null | undefined; + /** + * Настройки селекта передаваемые при создании экземпляра класса + * @type {ICgSelect} + */ private options: ICgSelect; + /** + * Уникальный Id для елементов + * @type {string} + */ private randomId: string; + /** + * Переменная для управления каретки + * @type {Element | null | undefined} + */ private caret: Element | null | undefined; + /** + * Переданные категории + * @type {string} + */ private category: string; + /** + * Выбранный или массив выбранных элементов из списка + * @type {string[] | string} + */ private selectedItems: string[] | string; + /** + * Массив индексов выбранных элементов + * @type {number[]} + */ private indexes: number[] = []; + /** + * Кнопка, для управления селектом + * @type {Element | null} + */ private btnCntr: Element | null; + /** + * @param {ICgSelect} setting Объект принимающий настройки селекта + * @constructor Конструктор класса DropDown + * @description Конструктор принимает объект и рендерит селект. + * @example + * options = { + * selector: 'Уникальный селектор', + selected: 'Выбранный элемент', + placeholder: '...', + lable: '...' + items: [string|number|object], + darkTheme: true/false, + searchMode: true/false, + closeOnSelect: true/false, + nativeSelectMode: true/false, + listDisplayMode: true/false, + language: 'ru/en', + styles: { + head: { + background: '...', + }, + list: {...}, + chips: {...}, + caret: {...}, + placeholder: {...}, + lable: {..}, + }, + event: '...', + url: 'http/...', + multiselect: true/false, + multiselectTag: true/false, + * } + */ constructor(setting: ICgSelect) { this.init(setting); this.render(); @@ -62,6 +138,25 @@ export class CGSelect implements ICgSelect { this.initEvent(); } + //Getters + /** + * Метод экземпляра класса DropDown + * @returns {string[] | string} Возвращает выбранные элемент(ы) в виде массива/элемента/null + * @description Геттер возвращающий выбранные элемент(ы) селекта + */ + get value(): string | string[] { + return this.selectedItems ?? null; + } + + /** + * Метод экземпляра класса DropDown + * @returns {number | number[]}Возвращает индексы выбранных элемента(ов) в виде массива/пустой массив + * @description Геттер возвращающий индексы выбранных элемента(ов) селекта + */ + get indexesOf(): number | number[] { + return this.indexes ?? []; + } + /** * Приватный метод инициализации экземпляра класса DropDown * @method init @@ -140,18 +235,19 @@ export class CGSelect implements ICgSelect { this.renderUrl(); return; } + createSelected; items.forEach((dataItem: any, index: number) => { let itemInputs: IDataItem = { ItemValue: dataItem, - // category: dataItem.category, - // categoryItems: dataItem.categoryItems, + category: dataItem.category, + categoryItems: dataItem.categoryItems, }; - if (dataItem.category && dataItem.categoryItems) { - this.category = dataItem.category!; + if (itemInputs.category && itemInputs.categoryItems) { + this.category = itemInputs.category!; this.items.push(this.category); - dataItem.categoryItems.forEach((categoryItem, indexCategory: number) => { + itemInputs.categoryItems.forEach((categoryItem, indexCategory: number) => { this.items.push(getFormatItem(categoryItem, indexCategory)); }); } else { @@ -168,13 +264,11 @@ export class CGSelect implements ICgSelect { * @description Рендер елементов в селекте. */ private render(select?: string): void { - const { styles } = this.options; - const random = Math.random().toString(36).substring(2, 10); - if (select || (select && styles)) { + if (select || (select && this.styles)) { this.initSelected(select); - customStyles(this.element!, styles); + customStyles(this.element!, this.styles!); } else { this.initSelected(); } @@ -189,9 +283,8 @@ export class CGSelect implements ICgSelect { ulList.classList.add('list'); - if (styles) { - const { list } = styles; - customStylesFormat(list!, ulList); + if (this.styles) { + customStylesFormat(this.styles.list!, ulList); } if (this.searchMode) { @@ -201,8 +294,7 @@ export class CGSelect implements ICgSelect { inputSearch = createInputSearch(random, en.placeholder); } - const { search } = styles!; - customStylesFormat(search!, inputSearch); + customStylesFormat(this.styles?.search!, inputSearch); ulList.appendChild(inputSearch); } @@ -247,10 +339,11 @@ export class CGSelect implements ICgSelect { } }); - this.items.filter((item, index) => { + this.items.filter((item: IItems | any, index: number) => { if (typeof item !== 'object') { this.items.splice(index, 1); } + return item; }); @@ -340,29 +433,26 @@ export class CGSelect implements ICgSelect { /** * Привaтный метод экземпляра класса DropDown - * * @method initSelected * @param {string} select необязательный елемент. Используется в методе selectIndex * @description Отрисовывает и стилизует селект * @protected */ private initSelected(select?: string): void { - const { styles } = this.options; - if (this.selected) { - createSelected(this.element, this.selected); + createSelected(this.element!, this.selected); } else if (this.placeholder) { - createSelected(this.element, this.placeholder); + createSelected(this.element!, this.placeholder); } else { if (this.language && this.language === 'ru') { - createSelected(this.element, ru.selectPlaceholder); + createSelected(this.element!, ru.selectPlaceholder); } else { - createSelected(this.element, en.selectPlaceholder); + createSelected(this.element!, en.selectPlaceholder); } } if (select) { - createSelected(this.element, select, styles); + createSelected(this.element!, select, this.styles); } if (this.lable) { @@ -375,8 +465,8 @@ export class CGSelect implements ICgSelect { this.element!.insertAdjacentElement('beforebegin', lableItem); } - if (styles) { - customStyles(this.element!, styles); + if (this.styles) { + customStyles(this.element!, this.styles); } } @@ -722,7 +812,7 @@ export class CGSelect implements ICgSelect { * @returns {HTMLElement} возвращает ссылку на выбранный HTML элемент * @method getElement */ - public getElement(numberItem: number) { + public getElement(numberItem: number): IItems[] | string[] | any { if (numberItem > this.items.length) { return; } diff --git a/src/components/create-element/create-element.interface.js b/src/components/create-element/create-element.interface.js new file mode 100644 index 0000000..0e34578 --- /dev/null +++ b/src/components/create-element/create-element.interface.js @@ -0,0 +1,2 @@ +"use strict"; +exports.__esModule = true; diff --git a/src/components/create-element/create-element.interface.ts b/src/components/create-element/create-element.interface.ts index 31c3ada..b0acac0 100644 --- a/src/components/create-element/create-element.interface.ts +++ b/src/components/create-element/create-element.interface.ts @@ -1,8 +1,24 @@ import { ICgSelect } from '../../interfaces/cg-select.interface'; export interface ICreateBreadCrumb { + /** + * Определенный экземпляр класса. + * @type {Element | null} + */ element: Element | null; + /** + * Настройки селекта. + * @type {ICgSelect} + */ option: ICgSelect; + /** + * Массив индексов выбранных элементов. + * @type {number[]} + */ indexes: number[]; + /** + * Массив с выбранными элементами. + * @type {string[]} + */ selectedItems: string[]; } diff --git a/src/components/create-element/create-elementTs.js b/src/components/create-element/create-elementTs.js new file mode 100644 index 0000000..bd8f9b0 --- /dev/null +++ b/src/components/create-element/create-elementTs.js @@ -0,0 +1,103 @@ +"use strict"; +exports.__esModule = true; +exports.createInputSearch = exports.createBreadCrumb = exports.createNativeSelectOption = exports.createNativeSelect = void 0; +var utilsTs_1 = require("../utils/utilsTs"); +/** + * Метод который создает нативный селект + * @returns {HTMLSelectElement} Возвращает созданный нативный селект + */ +function createNativeSelect() { + var nativeSelect = document.createElement('select'); + nativeSelect.setAttribute('name', 'dataSelect'); + nativeSelect.classList.add('nativeSelect'); + return nativeSelect; +} +exports.createNativeSelect = createNativeSelect; +/** + * Метод который создает Options для нативного селекта + * @returns {HTMLOptionElement} Возвращает созданные Options нативного селекта + */ +function createNativeSelectOption() { + var nativeOption = document.createElement('option'); + nativeOption.classList.add('nativeSelect__nativeOption'); + return nativeOption; +} +exports.createNativeSelectOption = createNativeSelectOption; +/** + * Метод который создает и отвечает за поведение chips + * @param {ICreateBreadCrumb} data объект в котором содержатся настройки и элементы селекта + * @param {string} title имя выбранного элемента для отрисовки chips + * @param {number} index индекс выбранного элемента для отрисовки chips + * @param {string} id уникальное id выбранного элемента + * @returns {HTMLElement} возвращает сформированный HTMLElement chips item + */ +function createBreadCrumb(data, title, index, id) { + var element = data.element, option = data.option, indexes = data.indexes, selectedItems = data.selectedItems; + var placeholder = option.placeholder, styles = option.styles; + var selected = element === null || element === void 0 ? void 0 : element.querySelector('.selected'); + var nativeOption = element.querySelectorAll('.nativeSelect__nativeOption'); + var liChip = document.createElement('li'); + var textNode = document.createTextNode(title); + var svgIcon = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); + var path1 = document.createElementNS('http://www.w3.org/2000/svg', 'path'); + var path2 = document.createElementNS('http://www.w3.org/2000/svg', 'path'); + svgIcon.setAttribute('viewBox', '0 0 10 10'); + path1.setAttribute('d', 'M3,7 L7,3'); + path2.setAttribute('d', 'M3,3 L7,7'); + liChip.setAttribute('id', "tag-".concat(index, "-").concat(id)); + svgIcon.classList.add('svg-icon'); + svgIcon.appendChild(path1); + svgIcon.appendChild(path2); + liChip.appendChild(textNode); + liChip.appendChild(svgIcon); + if (styles) { + // const { chips } = styles; + // customStylesFormat(chips, liChip); + } + svgIcon.addEventListener('click', function (event) { + event.preventDefault(); + event.stopPropagation(); + (0, utilsTs_1.nativeOptionMultiple)(nativeOption, title, false); + var deleteIcon = indexes.indexOf(index); + var checkBox; + indexes.splice(deleteIcon, 1); + selectedItems.splice(deleteIcon, 1); + if (id) { + checkBox = document.getElementById("chbox-".concat(id)); + } + else { + checkBox = document.getElementById("chbox-".concat(index)); + } + checkBox.checked = false; + checkBox.parentElement.classList.remove('active'); + if (!selectedItems.length) { + selected.innerText = placeholder; + } + liChip.parentElement.removeChild(liChip); + }); + return liChip; +} +exports.createBreadCrumb = createBreadCrumb; +/** + * Метод который создает поиск элементов в селекте + * @param {string} random уникальное значение для input элемента. + * @param {string} lenguage текст на определенном языке переданный из файла language.js + * @returns {HTMLInputElement} Возвращает сформированный input елемент. + */ +function createInputSearch(random, lenguage) { + var inputSearch = document.createElement('input'); + inputSearch.type = 'text'; + inputSearch.classList.add('inputSearch'); + inputSearch.setAttribute('id', "searchSelect-".concat(random)); + if (lenguage) { + inputSearch.setAttribute('placeholder', "".concat(lenguage)); + } + else { + inputSearch.setAttribute('placeholder', 'Search...'); + } + inputSearch.addEventListener('click', function (e) { + e.preventDefault(); + }); + return inputSearch; +} +exports.createInputSearch = createInputSearch; diff --git a/src/components/utils/urils.interface.js b/src/components/utils/urils.interface.js new file mode 100644 index 0000000..0e34578 --- /dev/null +++ b/src/components/utils/urils.interface.js @@ -0,0 +1,2 @@ +"use strict"; +exports.__esModule = true; diff --git a/src/components/utils/urils.interface.ts b/src/components/utils/urils.interface.ts index 62ea811..a949fd0 100644 --- a/src/components/utils/urils.interface.ts +++ b/src/components/utils/urils.interface.ts @@ -1,16 +1,53 @@ import { IItems } from '../../interfaces/items.interface'; export interface IDataItem { + /** + * Необязательный параметр. Категория группы элементов. + * @type {string} + */ category?: string; - categoryItems?: string; + /** + * Необязательный параметр. Массив с элементами. + * @type {IItems[] | string[] | any} + */ + categoryItems?: IItems[] | string[] | any; + /** + * Значение переданного элемента. + * @type {string | IItems | number} + */ ItemValue: string | IItems | number; } export interface ISelectedItems { + /** + * Placeholder необязательный параметр, в который передается текст плейсхолдера селекта. + * @type {string} + */ placeholder?: string; + /** + * Необязательный параметр, в который передается элемент который будет выбран изначально в селекте. + * @type {string} + */ selected?: string; + /** + * Массив выбранных элементов из списка + * @type {string[]} + */ selectedItems?: string[]; + /** + * Массив индексов выбранных элементов + * @type {number[]} + */ indexes?: number[]; + /** + * Необязательный параметр, который отвечает за поведения селекта, + * для него, ***работает только в месте с подключением multiselect. + * @type {boolean} + */ multiselectTag?: boolean; + /** + * Необязательный параметр, который отвечает за включение светлой/темной темы по умолчанию, стоит темная тема. + * @type {boolean} + */ darkTheme?: boolean; } diff --git a/src/components/utils/utilsTs.js b/src/components/utils/utilsTs.js new file mode 100644 index 0000000..3181b8d --- /dev/null +++ b/src/components/utils/utilsTs.js @@ -0,0 +1,210 @@ +"use strict"; +/** + * Utils module + * @module Utils + */ +exports.__esModule = true; +exports.customStylesFormat = exports.customStyles = exports.nativeOptionMultiple = exports.nativeOptionOrdinary = exports.clearSelect = exports.createSelected = exports.checkItemStruct = exports.getSelectText = exports.getFormatItem = void 0; +/** + * Преобразование каждого елемента полученного из поля Items; + * @param {any} dataItem полученный елемент переданный при создании селекта может быть как object / string + * @param {number} index индекс этого элемента + * @returns {IItems} возвращает сформированный объект + */ +function getFormatItem(dataItem, index) { + var random = Math.random().toString(36).substring(2, 10); + var item; + if (checkItemStruct(dataItem)) { + return dataItem; + } + else { + item = { + id: random, + title: dataItem, + value: index + }; + return item; + } +} +exports.getFormatItem = getFormatItem; +/** + * Вставка изначального текста селекта(до выбора) + * @param {ITextSelect} data объект в котором находяться title селекта + * @param {HTMLElement | null | undefined} select елемент селекта, куда будет вставляться title + * @returns {HTMLElement} возвращает сформированный елемент селекта + */ +function getSelectText(data, select) { + var placeholder = data.placeholder, selected = data.selected; + if (placeholder) { + select.innerText = placeholder; + } + else if (selected) { + select.innerText = selected; + } + else { + select.innerText = 'Select...'; + } + return select; +} +exports.getSelectText = getSelectText; +/** + * Проверка содержит ли item указанные свойства, + * @param {object} item проверяемый на определенную структуру элемент + * @returns {boolean} возвращает true/false если item содержит указанные свойства + */ +function checkItemStruct(item) { + if (item && typeof item !== 'object') { + return false; + } + return item.hasOwnProperty('id') && item.hasOwnProperty('title') && item.hasOwnProperty('value'); +} +exports.checkItemStruct = checkItemStruct; +/** + * Создание кнопки выбора элементов + * @param {HTMLElement} element созданный экземпляр класса DropDown + * @param {string} content placeholer передаваемый из настроек селекта + * @param {object} styles не обязательный параметр. Объект в котором находяться настройки кастомизации частей селекта + */ +function createSelected(element, content, styles) { + var select = document.createElement('div'); + var selected = document.createElement('p'); + var caret = document.createElement('div'); + select.classList.add('cg-select'); + selected.classList.add('selected'); + caret.classList.add('caret'); + select.appendChild(selected); + select.appendChild(caret); + if (content) { + var text = document.createTextNode(content); + selected.appendChild(text); + element === null || element === void 0 ? void 0 : element.appendChild(select); + } + else if (styles) { + customStyles(element, styles); + select.setAttribute('style', "".concat(styles)); + selected.setAttribute('style', "".concat(styles)); + caret.setAttribute('style', "".concat(styles)); + } +} +exports.createSelected = createSelected; +/** + * Создание кнопки отчиски селекта, при единичном выборе. + * @param {HTMLElement} select место в селекте которое будет переназначено на ''. + * @param {Element} element экземпляр класса DropDown. + * @param {ISelectedItems} dataSelectText текст который отрисовывается в селекте. + */ +function clearSelect(select, element, dataSelectText) { + var selectedItems = dataSelectText.selectedItems, indexes = dataSelectText.indexes, darkTheme = dataSelectText.darkTheme, multiselectTag = dataSelectText.multiselectTag; + var options = element.querySelectorAll('.list__item'); + var ulMultiSelect = element.querySelector('.multiselect-tag'); + var svgIcon = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); + var path1 = document.createElementNS('http://www.w3.org/2000/svg', 'path'); + var path2 = document.createElementNS('http://www.w3.org/2000/svg', 'path'); + var checkBox = element.querySelectorAll('li input'); + svgIcon.setAttribute('viewBox', '0 0 10 10'); + path1.setAttribute('d', 'M2,8 L8,2'); + path2.setAttribute('d', 'M2,2 L8,8'); + svgIcon.appendChild(path1); + svgIcon.appendChild(path2); + if (multiselectTag) { + return; + } + if (darkTheme === true || !darkTheme) { + path1.classList.add('pathWhite'); + path2.classList.add('pathWhite'); + } + if (darkTheme === false) { + path1.classList.add('pathBlack'); + path2.classList.add('pathBlack'); + } + svgIcon.classList.add('svg-icon'); + svgIcon.classList.add('svg-clear'); + select.appendChild(svgIcon); + svgIcon.addEventListener('click', function () { + select.innerText = ''; + if (Array.isArray(selectedItems)) { + selectedItems.splice(0); + indexes.splice(0); + } + checkBox.forEach(function (item) { + if (item instanceof HTMLInputElement) { + item.checked = false; + } + }); + getSelectText(dataSelectText, select); + options.forEach(function (option) { + option.classList.remove('active'); + }); + }); +} +exports.clearSelect = clearSelect; +/** + * Поведение нативного(одинарного) селекта при выборе кастомного + * @param {NodeList} element NodeList нативного селекта + * @param {any} item выбранный элемент в кастомном селекте + */ +function nativeOptionOrdinary(element, item) { + element.forEach(function (option) { + option.removeAttribute('selected'); + if (option.textContent === item) { + option.setAttribute('selected', 'selected'); + } + }); +} +exports.nativeOptionOrdinary = nativeOptionOrdinary; +/** + * Поведение нативного(Multiple) селекта при выборе в кастомном + * @param {NodeListOf | undefined} element NodeList нативного селекта + * @param {string} item выбранный элемент в кастомном селекте + * @param {boolean} condition специальный флаг при котором добавляются/убераются атрибуты у нативного селекта + */ +function nativeOptionMultiple(element, item, condition) { + element.forEach(function (option) { + if (condition == true) { + if (option.textContent === item) { + option.setAttribute('selected', 'selected'); + } + } + else if (condition == false) { + if (option.textContent === item) { + option.removeAttribute('selected'); + } + } + else { + return; + } + }); +} +exports.nativeOptionMultiple = nativeOptionMultiple; +/** + * Поиск и стилизация елементов полученных из styles экземпляра DropDown + * @param {Element} element созданный экземпляр класса DropDown + * @param {object} styles объект в котором находяться настройки кастомизации частей селекта + */ +function customStyles(element, styles) { + var cgSelect = element.querySelector('.cg-select'); + var caretSelect = element.querySelector('.caret'); + var placeholderSelect = element.querySelector('.selected'); + var lableItem = element.parentElement.querySelector('h1.label'); + customStylesFormat(styles.head, cgSelect); + customStylesFormat(styles.caret, caretSelect); + customStylesFormat(styles.lable, lableItem); + if (placeholderSelect) { + customStylesFormat(styles.placeholder, placeholderSelect); + } +} +exports.customStyles = customStyles; +/** + * Универсальный метод для стилизации селекта + * @param {object} elemOption объект полученное из объекта styles у которого мы получаем ключ-значение стилей + * @param {HTMLElement} selector HTMLElement подвергающиеся кастомизации + */ +function customStylesFormat(elemOption, selector) { + if (elemOption) { + Object.entries(elemOption).forEach(function (_a) { + var key = _a[0], value = _a[1]; + selector.style[key] = value; + }); + } +} +exports.customStylesFormat = customStylesFormat; diff --git a/src/components/utils/utilsTs.ts b/src/components/utils/utilsTs.ts index 720ae3b..c6cf502 100644 --- a/src/components/utils/utilsTs.ts +++ b/src/components/utils/utilsTs.ts @@ -1,14 +1,18 @@ -import { ICgSelect } from '../../interfaces/cg-select.interface'; +/** + * Utils module + * @module Utils + */ + +import { IStyle } from '../../interfaces/cg-select.interface'; import { IItems } from '../../interfaces/items.interface'; import { IDataItem, ISelectedItems } from './urils.interface'; /** * Преобразование каждого елемента полученного из поля Items; - * @param {IDataItem} dataItem полученный елемент переданный при создании селекта может быть как object / string + * @param {any} dataItem полученный елемент переданный при создании селекта может быть как object / string * @param {number} index индекс этого элемента - * @returns {IDataItem | IItems} возвращает сформированный объект + * @returns {IItems} возвращает сформированный объект */ - export function getFormatItem(dataItem: any, index: number): IItems { const random = Math.random().toString(36).substring(2, 10); let item: IItems; @@ -67,7 +71,7 @@ export function checkItemStruct(item: object): boolean { * @param {string} content placeholer передаваемый из настроек селекта * @param {object} styles не обязательный параметр. Объект в котором находяться настройки кастомизации частей селекта */ -export function createSelected(element: Element | null, content?: string, styles?: object) { +export function createSelected(element: Element, content?: string, styles?: IStyle) { const select = document.createElement('div'); const selected = document.createElement('p'); const caret = document.createElement('div'); @@ -89,17 +93,6 @@ export function createSelected(element: Element | null, content?: string, styles selected.setAttribute('style', `${styles}`); caret.setAttribute('style', `${styles}`); } - - // if (styles) { - // customStyles(element, styles); - - // element.innerHTML = ` - //
- //

${content}

- //
- //
- // `; - // } } /** @@ -210,24 +203,18 @@ export function nativeOptionMultiple( * @param {Element} element созданный экземпляр класса DropDown * @param {object} styles объект в котором находяться настройки кастомизации частей селекта */ -export function customStyles(element: Element, styles: any) { - if (!styles) { - return; - } - - const { head, caret, placeholder, lable } = styles; - +export function customStyles(element: Element, styles: IStyle) { const cgSelect = element.querySelector('.cg-select'); const caretSelect = element.querySelector('.caret'); const placeholderSelect = element.querySelector('.selected'); const lableItem = element.parentElement!.querySelector('h1.label'); - customStylesFormat(head, cgSelect!); - customStylesFormat(caret, caretSelect!); - customStylesFormat(lable, lableItem!); + customStylesFormat(styles.head!, cgSelect!); + customStylesFormat(styles.caret!, caretSelect!); + customStylesFormat(styles.lable!, lableItem!); if (placeholderSelect) { - customStylesFormat(placeholder, placeholderSelect); + customStylesFormat(styles.placeholder!, placeholderSelect); } } diff --git a/src/interfaces/cg-select.interface.js b/src/interfaces/cg-select.interface.js new file mode 100644 index 0000000..0e34578 --- /dev/null +++ b/src/interfaces/cg-select.interface.js @@ -0,0 +1,2 @@ +"use strict"; +exports.__esModule = true; diff --git a/src/interfaces/cg-select.interface.ts b/src/interfaces/cg-select.interface.ts index b2cb7f6..8da039c 100644 --- a/src/interfaces/cg-select.interface.ts +++ b/src/interfaces/cg-select.interface.ts @@ -1,29 +1,125 @@ import { IItems } from './items.interface'; export interface ICgSelect { + /** + * Уникальный селектор - *обязательный параметр(индефикатор), который задаеться при создании селекта. + * @type {string} + */ selector: string; + /** + * Необязательный параметр, в который передается элемент который будет выбран изначально в селекте. + * @type {string} + */ selected?: string; + /** + * Placeholder необязательный параметр, в который передается текст плейсхолдера селекта. + * @type {string} + */ placeholder?: string; + /** + * *Обязательный параметр(эсли не указан другой способ получения данных (url)), это массив элементов, + * которые будут отображаться в селекте при выборе. + * @type {IItems[] | string[] | any} + */ items?: IItems[] | string[] | any; + /** + * Необязательный параметр, который отвечает за включение светлой/темной темы по умолчанию, стоит темная тема(darkTheme == true) + * @type {boolean} + */ darkTheme?: boolean; + /** + * Необязательный параметр, который добавляет живой поиск по элеметам селекта. + * @type {boolean} + */ searchMode?: boolean; + /** + * Необязательный параметр, который отвечает за поведения селекта при открытии, если closeOnSelect: false, + * тогда при выборе елемента в селекте закрытия не происходит, + * и можно выбрать другой элемент по умолчанию, closeOnSelect:true. + * @type {boolean} + */ closeOnSelect?: boolean; + /** + * Необязательный параметр, который отвечает за поведения селекта при открытии на мобильных усторйствах. + * @type {boolean} + */ nativeSelectMode?: boolean; + /** + * Необязательный параметр, который отвечает за поведения селекта при открытии. + * @type {boolean} + */ listDisplayMode?: boolean; + /** + * Необязательный параметр, отвечающий за локализацию некоторых текстовых элементов. + * @type {string} + */ language?: string; + /** + * Необязательный параметр,который добавляет lable перед селектом. + * @type {string} + */ lable?: string; + /** + * Необязательный параметр, который отвечает за кастомизацию элементов селекта, + * в него передаются обьекты с CSS свойствами для кастомизируемых элементов. + * @type {IStyle} + */ styles?: IStyle; + /** + * Необязательный параметр, который отвечает за поведения селекта, передавая в этот параметр, евент по типу 'mouseenter', + * селект будет открываться при наведении. + * @type {string} + */ event?: string; + /** + * Обязательный параметр(эсли не указан другой способ получения данных (items)), + * данные которые приходят с бекэнда в формате {id:"", title: "", value: ""}. + * @type {string} + */ url?: string; + /** + * Необязательный параметр, который отвечает за поведения селекта, добавляет возможность выбирать несколько элементов. + * Выбранные элементы отрисовываются как обычный текст, через запятую. + * @type {boolean} + */ multiselect?: boolean; + /** + * Необязательный параметр, который отвечает за поведения селекта, + * для него, ***работает только в месте с подключением multiselect. + * @type {boolean} + */ multiselectTag?: boolean; } export interface IStyle { + /** + * Кастомизация кнопки селекта. + * @type {object} + */ head?: object; + /** + * Кастомизация каретки. + * @type {object} + */ caret?: object; + /** + * Кастомизация placeholder. + * @type {object} + */ placeholder?: object; + /** + * Кастомизация lable селекта. + * @type {object} + */ lable?: object; + /** + * Кастомизация листа с выбором элементов. + * @type {object} + */ list?: object; + /** + * Кастомизация поиска. + * @type {object} + */ search?: object; } diff --git a/src/interfaces/items.interface.js b/src/interfaces/items.interface.js new file mode 100644 index 0000000..0e34578 --- /dev/null +++ b/src/interfaces/items.interface.js @@ -0,0 +1,2 @@ +"use strict"; +exports.__esModule = true; diff --git a/src/interfaces/items.interface.ts b/src/interfaces/items.interface.ts index c7bfa0d..b827cfd 100644 --- a/src/interfaces/items.interface.ts +++ b/src/interfaces/items.interface.ts @@ -1,5 +1,17 @@ -export interface IItems{ - id: string; - title: string; - value: number | string -} \ No newline at end of file +export interface IItems { + /** + * Уникальное ID элемента + * @type {string} + */ + id: string; + /** + * Текстовое значение элемента + * @type {string} + */ + title: string; + /** + * Порядковый номер, или другая информация + * @type {number | string} + */ + value: number | string; +} diff --git a/src/interfaces/language.interface.js b/src/interfaces/language.interface.js new file mode 100644 index 0000000..0e34578 --- /dev/null +++ b/src/interfaces/language.interface.js @@ -0,0 +1,2 @@ +"use strict"; +exports.__esModule = true; diff --git a/src/interfaces/language.interface.ts b/src/interfaces/language.interface.ts index ffaaf2a..c2665f7 100644 --- a/src/interfaces/language.interface.ts +++ b/src/interfaces/language.interface.ts @@ -1,5 +1,17 @@ export interface ILanguage { + /** + * Текст в поиске. + * @type {string} + */ placeholder: string; + /** + * Дефолтный Текст Селекта если не указан placeholder или выбранный элемент + * @type {string} + */ selectPlaceholder: string; + /** + * Текст если совпадений нет. + * @type {string} + */ textInListSearch: string; } diff --git a/src/language/languageTS.js b/src/language/languageTS.js new file mode 100644 index 0000000..1e4e0ca --- /dev/null +++ b/src/language/languageTS.js @@ -0,0 +1,13 @@ +"use strict"; +exports.__esModule = true; +exports.en = exports.ru = void 0; +exports.ru = { + selectPlaceholder: 'Выберите элемент...', + placeholder: 'Поиск...', + textInListSearch: 'Совпадений нет...' +}; +exports.en = { + selectPlaceholder: 'Select element...', + placeholder: 'Search...', + textInListSearch: 'No matches...' +}; diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..2e03881 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,102 @@ +{ + "compilerOptions": { + + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + + /* Language and Environment */ + "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ + // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + + /* Modules */ + "module": "commonjs", /* Specify what module code is generated. */ + // "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + // "outDir": "./", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + // "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ + // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ + + /* Type Checking */ + "strict": true, /* Enable all strict type-checking options. */ + // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true /* Skip type checking all .d.ts files. */ + } +}