diff --git a/.eslintrc.yml b/.eslintrc.yml index c55d3fdb..f2a33eaa 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -7,6 +7,7 @@ extends: - plugin:import/recommended - plugin:sonarjs/recommended - plugin:unicorn/recommended + - plugin:perfectionist/recommended-natural plugins: - simple-import-sort @@ -92,6 +93,9 @@ rules: - error simple-import-sort/exports: - error + perfectionist/sort-named-imports: + - error + - type: alphabetical import/exports-last: - error import/group-exports: diff --git a/commitlint.config.js b/commitlint.config.js index 28e2f90c..d213e68e 100644 --- a/commitlint.config.js +++ b/commitlint.config.js @@ -2,12 +2,12 @@ import { ProjectPrefix } from './project.config.js' /** @type {import('@commitlint/types').UserConfig} */ let configuration = { + extends: [`@commitlint/config-conventional`], parserPreset: { parserOpts: { issuePrefixes: ProjectPrefix.APPS.map((it) => `${it}-`), }, }, - extends: [`@commitlint/config-conventional`], rules: { 'references-empty': [2, `never`], }, diff --git a/eleventy.config.cjs b/eleventy.config.cjs index a377fe7b..7e291caa 100644 --- a/eleventy.config.cjs +++ b/eleventy.config.cjs @@ -2,7 +2,7 @@ let esbuild = require(`esbuild`) let lightningcss = require(`lightningcss`) let htmlMin = require(`html-minifier-terser`) let { existsSync } = require(`fs`) -let { readFile, writeFile, mkdir } = require(`fs/promises`) +let { mkdir, readFile, writeFile } = require(`fs/promises`) let browserslist = require(`browserslist`) let packageJson = require(`./package.json`) let Image = require(`@11ty/eleventy-img`) @@ -13,12 +13,6 @@ let fs = require(`node:fs/promises`) let isDevelopment = process.env.NODE_ENV === `development` let Path = { - CSS: `./source/styles/index.css`, - JS: { - MAIN: `./source/scripts/index.js`, - FORM: `./source/scripts/form.js`, - }, - DB: `./source/database.json`, COPY: [ `./source/fonts`, `./source/files`, @@ -26,6 +20,12 @@ let Path = { `./source/manifest.webmanifest`, `./source/favicon.ico`, ], + CSS: `./source/styles/index.css`, + DB: `./source/database.json`, + JS: { + FORM: `./source/scripts/form.js`, + MAIN: `./source/scripts/index.js`, + }, } /** @param {import("@11ty/eleventy").UserConfig} config */ @@ -44,7 +44,6 @@ let init = (config) => { config.addTemplateFormats(`json`) config.addExtension(`json`, { - outputFileExtension: `json`, compile: async (_content, url) => { if (url !== Path.DB) { return @@ -65,6 +64,7 @@ let init = (config) => { }), ) }, + outputFileExtension: `json`, }) // html @@ -84,7 +84,6 @@ let init = (config) => { config.addTemplateFormats(`css`) config.addExtension(`css`, { - outputFileExtension: `css`, compile: async (_content, url) => { if (url !== Path.CSS) { return @@ -108,13 +107,13 @@ let init = (config) => { : code } }, + outputFileExtension: `css`, }) // js config.addTemplateFormats(`js`) config.addExtension(`js`, { - outputFileExtension: `js`, compile: async (_content, url) => { if (url !== Path.JS.MAIN) { return @@ -124,12 +123,12 @@ let init = (config) => { let { outputFiles: [formOutputFile], } = await esbuild.build({ + bundle: true, entryPoints: [Path.JS.FORM], - target: `es2020`, minify: true, - bundle: true, - write: false, sourcemap: isDevelopment, + target: `es2020`, + write: false, }) let isFolderExists = existsSync(`build/scripts`) @@ -145,24 +144,24 @@ let init = (config) => { let { outputFiles: [mainOutputFile], } = await esbuild.build({ + bundle: true, entryPoints: [url], - target: `es2020`, minify: true, - bundle: true, - write: false, sourcemap: isDevelopment, + target: `es2020`, + write: false, }) return mainOutputFile.text } }, + outputFileExtension: `js`, }) // png config.addTemplateFormats(`png`) config.addExtension(`png`, { - outputFileExtension: `png`, compile: async (_content, url) => { return async () => { let { @@ -174,27 +173,27 @@ let init = (config) => { if (url.includes(`.photo.`)) { await Image(url, { - formats: [`webp`, `avif`], - outputDir: `build/images`, filenameFormat: (_id, source, _width, format) => { let extension = path.extname(source) let name = path.basename(source, extension) return `${name}.${format}` }, + formats: [`webp`, `avif`], + outputDir: `build/images`, }) } return originalImg.buffer } }, + outputFileExtension: `png`, }) // svg config.addTemplateFormats(`svg`) config.addExtension(`svg`, { - outputFileExtension: `svg`, compile: (content, url) => { return () => { if (url === `./source/images/icons/icon.svg`) { @@ -204,16 +203,17 @@ let init = (config) => { return svgo.optimize(content).data } }, + outputFileExtension: `svg`, }) return { + dataTemplateEngine: `njk`, dir: { input: `source`, output: `build`, }, - dataTemplateEngine: `njk`, - markdownTemplateEngine: `njk`, htmlTemplateEngine: `njk`, + markdownTemplateEngine: `njk`, passthroughFileCopy: true, templateFormats: [`md`, `njk`], } diff --git a/package-lock.json b/package-lock.json index fd393e5a..2ba37d42 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,6 +20,7 @@ "eslint": "8.53.0", "eslint-import-resolver-alias": "1.1.2", "eslint-plugin-import": "2.29.0", + "eslint-plugin-perfectionist": "2.3.0", "eslint-plugin-simple-import-sort": "10.0.0", "eslint-plugin-sonarjs": "0.23.0", "eslint-plugin-unicorn": "49.0.0", @@ -1608,6 +1609,12 @@ "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", "dev": true }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true + }, "node_modules/@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", @@ -1638,6 +1645,111 @@ "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", "dev": true }, + "node_modules/@types/semver": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.5.tgz", + "integrity": "sha512-+d+WYC1BxJ6yVOgUgzK8gWvp5qF8ssV5r4nsDcZWKRWcDQLQ619tvWAxJQYGgBrO1MnLJC7a5GtiYsAoQ47dJg==", + "dev": true + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.11.0.tgz", + "integrity": "sha512-0A8KoVvIURG4uhxAdjSaxy8RdRE//HztaZdG8KiHLP8WOXSk0vlF7Pvogv+vlJA5Rnjj/wDcFENvDaHb+gKd1A==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.11.0", + "@typescript-eslint/visitor-keys": "6.11.0" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.11.0.tgz", + "integrity": "sha512-ZbEzuD4DwEJxwPqhv3QULlRj8KYTAnNsXxmfuUXFCxZmO6CF2gM/y+ugBSAQhrqaJL3M+oe4owdWunaHM6beqA==", + "dev": true, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.11.0.tgz", + "integrity": "sha512-Aezzv1o2tWJwvZhedzvD5Yv7+Lpu1by/U1LZ5gLc4tCx8jUmuSCMioPFRjliN/6SJIvY6HpTtJIWubKuYYYesQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.11.0", + "@typescript-eslint/visitor-keys": "6.11.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.11.0.tgz", + "integrity": "sha512-p23ibf68fxoZy605dc0dQAEoUsoiNoP3MD9WQGiHLDuTSOuqoTsa4oAy+h3KDkTcxbbfOtUjb9h3Ta0gT4ug2g==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.11.0", + "@typescript-eslint/types": "6.11.0", + "@typescript-eslint/typescript-estree": "6.11.0", + "semver": "^7.5.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.11.0.tgz", + "integrity": "sha512-+SUN/W7WjBr05uRxPggJPSzyB8zUpaYo2hByKasWbqr3PM8AXfZt8UHdNpBS1v9SA62qnSSMF3380SwDqqprgQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.11.0", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, "node_modules/@ungap/structured-clone": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", @@ -4065,6 +4177,62 @@ "semver": "bin/semver.js" } }, + "node_modules/eslint-plugin-perfectionist": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-perfectionist/-/eslint-plugin-perfectionist-2.3.0.tgz", + "integrity": "sha512-T/1HOysrsyExPr/N5apy3XFhejYqIturtejlSbTGy0WCw5dt72FDT92NOvRRKJvx8lftZDJ8AEIs5nHk9Pfa9Q==", + "dev": true, + "dependencies": { + "@typescript-eslint/utils": "^6.10.0", + "minimatch": "^9.0.3", + "natural-compare-lite": "^1.4.0" + }, + "peerDependencies": { + "astro-eslint-parser": "^0.16.0", + "eslint": ">=8.0.0", + "svelte": ">=3.0.0", + "svelte-eslint-parser": "^0.33.0", + "vue-eslint-parser": ">=9.0.0" + }, + "peerDependenciesMeta": { + "astro-eslint-parser": { + "optional": true + }, + "svelte": { + "optional": true + }, + "svelte-eslint-parser": { + "optional": true + }, + "vue-eslint-parser": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-perfectionist/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==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/eslint-plugin-perfectionist/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/eslint-plugin-simple-import-sort": { "version": "10.0.0", "resolved": "https://registry.npmjs.org/eslint-plugin-simple-import-sort/-/eslint-plugin-simple-import-sort-10.0.0.tgz", @@ -7826,6 +7994,12 @@ "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "dev": true }, + "node_modules/natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "dev": true + }, "node_modules/negotiator": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", @@ -10587,6 +10761,18 @@ "node": ">=8" } }, + "node_modules/ts-api-utils": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz", + "integrity": "sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==", + "dev": true, + "engines": { + "node": ">=16.13.0" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, "node_modules/ts-node": { "version": "10.9.1", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", diff --git a/package.json b/package.json index 01aba60d..6df33fb7 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "eslint": "8.53.0", "eslint-import-resolver-alias": "1.1.2", "eslint-plugin-import": "2.29.0", + "eslint-plugin-perfectionist": "2.3.0", "eslint-plugin-simple-import-sort": "10.0.0", "eslint-plugin-sonarjs": "0.23.0", "eslint-plugin-unicorn": "49.0.0", diff --git a/source/scripts/common/enums/app/app-config.enum.js b/source/scripts/common/enums/app/app-config.enum.js index 6581e5c5..a9717c0b 100644 --- a/source/scripts/common/enums/app/app-config.enum.js +++ b/source/scripts/common/enums/app/app-config.enum.js @@ -1,7 +1,7 @@ let AppConfig = { + FILES_API_PATH: `/api`, SERVER_HOST: `http://localhost:`, SERVER_PORT: 3001, - FILES_API_PATH: `/api`, } export { AppConfig } diff --git a/source/scripts/common/enums/event/keyboard-key.enum.js b/source/scripts/common/enums/event/keyboard-key.enum.js index 772b4e12..8a35685b 100644 --- a/source/scripts/common/enums/event/keyboard-key.enum.js +++ b/source/scripts/common/enums/event/keyboard-key.enum.js @@ -1,6 +1,6 @@ let KeyboardKey = { - TAB: `Tab`, ESCAPE: `Escape`, + TAB: `Tab`, } export { KeyboardKey } diff --git a/source/scripts/common/enums/setting/setting-name.enum.js b/source/scripts/common/enums/setting/setting-name.enum.js index 3d5804d9..daf76cdd 100644 --- a/source/scripts/common/enums/setting/setting-name.enum.js +++ b/source/scripts/common/enums/setting/setting-name.enum.js @@ -1,6 +1,6 @@ let SettingName = { - THEME: `theme`, MOTION: `motion`, + THEME: `theme`, WHATISLOVE: `whatislove`, } diff --git a/source/scripts/common/enums/timeline/timeline-type.enum.js b/source/scripts/common/enums/timeline/timeline-type.enum.js index 52d119f4..98370043 100644 --- a/source/scripts/common/enums/timeline/timeline-type.enum.js +++ b/source/scripts/common/enums/timeline/timeline-type.enum.js @@ -1,8 +1,8 @@ let TimelineType = { - POSITION: `position`, - COURSE: `course`, BOOK: `book`, + COURSE: `course`, MEETUP: `meetup`, + POSITION: `position`, } export { TimelineType } diff --git a/source/scripts/components/common/toast/toast.js b/source/scripts/components/common/toast/toast.js index 040e32ed..949f6322 100644 --- a/source/scripts/components/common/toast/toast.js +++ b/source/scripts/components/common/toast/toast.js @@ -13,16 +13,21 @@ class Toast { this._isShowingMessage = false } - init() { - this._toastNode = document.querySelector(`.toast`) - } + async _displayToastMessage(messagePayload) { + let { cb, duration = TOAST_DEFAULT_DURATION, message } = messagePayload - pushMessage(message) { - this._messages.push(message) + this._toastNode.classList.add(TOAST_SHOW_CLASS_NAME) + this._toastNode.textContent = message - if (!this._isShowingMessage) { - this._initShowingMessages() - } + await setAsyncTimeout(() => { + this._toastNode.classList.remove(TOAST_SHOW_CLASS_NAME) + }, duration) + + await setAsyncTimeout(() => { + this._toastNode.textContent = `` + }, CLEAN_MESSAGE_DELAY) + + cb?.() } async _initShowingMessages() { @@ -43,21 +48,16 @@ class Toast { this._isShowingMessage = false } - async _displayToastMessage(messagePayload) { - let { duration = TOAST_DEFAULT_DURATION, message, cb } = messagePayload - - this._toastNode.classList.add(TOAST_SHOW_CLASS_NAME) - this._toastNode.textContent = message - - await setAsyncTimeout(() => { - this._toastNode.classList.remove(TOAST_SHOW_CLASS_NAME) - }, duration) + init() { + this._toastNode = document.querySelector(`.toast`) + } - await setAsyncTimeout(() => { - this._toastNode.textContent = `` - }, CLEAN_MESSAGE_DELAY) + pushMessage(message) { + this._messages.push(message) - cb?.() + if (!this._isShowingMessage) { + this._initShowingMessages() + } } } diff --git a/source/scripts/components/form/form.js b/source/scripts/components/form/form.js index 5d0df84a..845a6387 100644 --- a/source/scripts/components/form/form.js +++ b/source/scripts/components/form/form.js @@ -15,12 +15,18 @@ class Form { this._handleSubmit = this._handleSubmit.bind(this) } - init() { - this._formNode = document.querySelector(`form[name="timeline"]`) + async _handleSubmit(event_) { + event_.preventDefault() - this._initSelects() + let formValues = getFormValues(this._formNode) - this._initListeners() + await this._timelineApi.saveTimeline(getTransformedTimeline(formValues)) + + this._formNode.reset() + } + + _initListeners() { + this._formNode.addEventListener(`submit`, this._handleSubmit) } _initSelects() { @@ -34,18 +40,12 @@ class Form { ) } - _initListeners() { - this._formNode.addEventListener(`submit`, this._handleSubmit) - } - - async _handleSubmit(event_) { - event_.preventDefault() - - let formValues = getFormValues(this._formNode) + init() { + this._formNode = document.querySelector(`form[name="timeline"]`) - await this._timelineApi.saveTimeline(getTransformedTimeline(formValues)) + this._initSelects() - this._formNode.reset() + this._initListeners() } } diff --git a/source/scripts/components/home/components/easter-egg/easter-egg.js b/source/scripts/components/home/components/easter-egg/easter-egg.js index a6d66425..1e0002f7 100644 --- a/source/scripts/components/home/components/easter-egg/easter-egg.js +++ b/source/scripts/components/home/components/easter-egg/easter-egg.js @@ -13,7 +13,7 @@ import { import { getNodeRandomCoords, getPlayerElement } from './helpers/helpers.js' class EasterEgg { - constructor({ onSettingBtnAppend, onNotificationAdd }) { + constructor({ onNotificationAdd, onSettingBtnAppend }) { this._onSettingBtnAppend = onSettingBtnAppend this._onNotificationAdd = onNotificationAdd @@ -29,13 +29,35 @@ class EasterEgg { ) } - init() { - this._easterEggContainer = document.querySelector(`.not-easter-egg`) - this._easterEggBtn = document.querySelector(`.not-easter-egg__button`) + _handleEasterEggClick() { + this._onNotificationAdd({ + cb: () => { + let buttonNode = this._onSettingBtnAppend({ + isDefaultChecked: true, + label: SettingButtonLabel.SWITCH_LOVE, + name: SettingName.WHATISLOVE, + onClick: this._handleSettingBtnClick, + }) - this._setRandomPosition() + buttonNode.focus() + }, + duration: NOTIFICATION_DELAY, + message: NotificationMessage.LOVE, + }) - this._initListeners() + this._renderPlayer() + + this._removeListeners() + + this._easterEggContainer.remove() + } + + _handleSettingBtnClick({ isChecked }) { + isChecked ? this._audio.play() : this._audio.pause() + } + + _handleWindowResize() { + this._setRandomPosition() } _initListeners() { @@ -61,35 +83,13 @@ class EasterEgg { this._easterEggContainer.style.left = `${x}px` } - _handleEasterEggClick() { - this._onNotificationAdd({ - message: NotificationMessage.LOVE, - duration: NOTIFICATION_DELAY, - cb: () => { - let buttonNode = this._onSettingBtnAppend({ - name: SettingName.WHATISLOVE, - label: SettingButtonLabel.SWITCH_LOVE, - isDefaultChecked: true, - onClick: this._handleSettingBtnClick, - }) - - buttonNode.focus() - }, - }) - - this._renderPlayer() - - this._removeListeners() - - this._easterEggContainer.remove() - } - - _handleSettingBtnClick({ isChecked }) { - isChecked ? this._audio.play() : this._audio.pause() - } + init() { + this._easterEggContainer = document.querySelector(`.not-easter-egg`) + this._easterEggBtn = document.querySelector(`.not-easter-egg__button`) - _handleWindowResize() { this._setRandomPosition() + + this._initListeners() } } diff --git a/source/scripts/components/home/components/navigation/navigation.js b/source/scripts/components/home/components/navigation/navigation.js index c37de179..39595992 100644 --- a/source/scripts/components/home/components/navigation/navigation.js +++ b/source/scripts/components/home/components/navigation/navigation.js @@ -15,38 +15,26 @@ class Navigation { this._handleNavBtnClick = this._handleNavBtnClick.bind(this) } - get headerLinkNodes() { - return this._headerNode.querySelectorAll(`.navigation__item a[href]`) + _handleEscapePress({ key }) { + if (checkIsOneOf(key, KeyboardKey.ESCAPE)) { + this._handleOverlayClick() + } } - init() { - this._headerNode = document.querySelector(`.header`) - this._headerOverlayNode = this._headerNode.querySelector( - `.header__navigation-wrapper`, - ) - this._headerBtnNode = this._headerNode.querySelector( - `.header__toggle-button`, - ) + _handleNavBtnClick(event_) { + event_.stopPropagation() - this._initListeners() - } + let hasClass = this._headerNode.classList.contains(HEADER_ACTIVE_CLASS) - _initListeners() { - this._headerBtnNode.addEventListener(`click`, this._handleNavBtnClick) + this._toggleOverlay(!hasClass) } - _toggleOverlay(isActive) { - document.body.style.overflowY = isActive ? `hidden` : `` - - this._headerNode.classList.toggle(HEADER_ACTIVE_CLASS) - - this._headerBtnNode.setAttribute(`aria-expanded`, isActive) - - isActive ? this._initOverlayListeners() : this._removeOverlayListeners() + _handleOverlayClick() { + this._toggleOverlay(false) + } - this._cleanFocusTrap = isActive - ? subscribeFocusTrap(this._headerBtnNode, ...this.headerLinkNodes) - : this._cleanFocusTrap() + _initListeners() { + this._headerBtnNode.addEventListener(`click`, this._handleNavBtnClick) } _initOverlayListeners() { @@ -62,22 +50,34 @@ class Navigation { window.removeEventListener(`keydown`, this._handleEscapePress) } - _handleNavBtnClick(event_) { - event_.stopPropagation() + _toggleOverlay(isActive) { + document.body.style.overflowY = isActive ? `hidden` : `` - let hasClass = this._headerNode.classList.contains(HEADER_ACTIVE_CLASS) + this._headerNode.classList.toggle(HEADER_ACTIVE_CLASS) - this._toggleOverlay(!hasClass) + this._headerBtnNode.setAttribute(`aria-expanded`, isActive) + + isActive ? this._initOverlayListeners() : this._removeOverlayListeners() + + this._cleanFocusTrap = isActive + ? subscribeFocusTrap(this._headerBtnNode, ...this.headerLinkNodes) + : this._cleanFocusTrap() } - _handleEscapePress({ key }) { - if (checkIsOneOf(key, KeyboardKey.ESCAPE)) { - this._handleOverlayClick() - } + init() { + this._headerNode = document.querySelector(`.header`) + this._headerOverlayNode = this._headerNode.querySelector( + `.header__navigation-wrapper`, + ) + this._headerBtnNode = this._headerNode.querySelector( + `.header__toggle-button`, + ) + + this._initListeners() } - _handleOverlayClick() { - this._toggleOverlay(false) + get headerLinkNodes() { + return this._headerNode.querySelectorAll(`.navigation__item a[href]`) } } diff --git a/source/scripts/components/home/components/settings/components/control/control.js b/source/scripts/components/home/components/settings/components/control/control.js index ed1503e3..a9ca3d06 100644 --- a/source/scripts/components/home/components/settings/components/control/control.js +++ b/source/scripts/components/home/components/settings/components/control/control.js @@ -1,5 +1,5 @@ class Control { - constructor({ name, defaultValue, onChange }) { + constructor({ defaultValue, name, onChange }) { this._name = name this._onChange = onChange this._defaultValue = defaultValue @@ -9,12 +9,15 @@ class Control { this._handleSwitchChange = this._handleSwitchChange.bind(this) } - init(selector) { - this._controlNode = document.querySelector(selector) - - this._setInitialValue() + _handleSwitchChange({ target }) { + this._onChange({ + name: this._name, + value: target.value, + }) + } - this._initListeners() + _initListeners() { + this._controlNode.addEventListener(`change`, this._handleSwitchChange) } _setInitialValue() { @@ -31,15 +34,12 @@ class Control { } } - _initListeners() { - this._controlNode.addEventListener(`change`, this._handleSwitchChange) - } + init(selector) { + this._controlNode = document.querySelector(selector) - _handleSwitchChange({ target }) { - this._onChange({ - name: this._name, - value: target.value, - }) + this._setInitialValue() + + this._initListeners() } } diff --git a/source/scripts/components/home/components/settings/components/switch/switch.js b/source/scripts/components/home/components/settings/components/switch/switch.js index 007f0f9b..ebaf8e84 100644 --- a/source/scripts/components/home/components/settings/components/switch/switch.js +++ b/source/scripts/components/home/components/settings/components/switch/switch.js @@ -2,7 +2,7 @@ import { CHECKED_ATTR } from './common/constants.js' import { checkIsChecked } from './helpers/helpers.js' class Switch { - constructor({ name, isDefaultChecked, onClick }) { + constructor({ isDefaultChecked, name, onClick }) { this._name = name this._isDefaultChecked = isDefaultChecked this._onClick = onClick @@ -12,38 +12,38 @@ class Switch { this._handleSwitchClick = this._handleSwitchClick.bind(this) } - set _isChecked(isChecked) { - this._switchNode.setAttribute(CHECKED_ATTR, isChecked) - } - - init(selector) { - this._switchNode = document.querySelector(selector) - - this._isChecked = this._isDefaultChecked + _handleSwitchClick({ target }) { + let isChecked = !checkIsChecked(target) - this._initListeners() + this._isChecked = isChecked this._onClick({ + isChecked, name: this._name, - isChecked: this._isDefaultChecked, }) - - return this._switchNode } _initListeners() { this._switchNode.addEventListener(`click`, this._handleSwitchClick) } - _handleSwitchClick({ target }) { - let isChecked = !checkIsChecked(target) + set _isChecked(isChecked) { + this._switchNode.setAttribute(CHECKED_ATTR, isChecked) + } - this._isChecked = isChecked + init(selector) { + this._switchNode = document.querySelector(selector) + + this._isChecked = this._isDefaultChecked + + this._initListeners() this._onClick({ + isChecked: this._isDefaultChecked, name: this._name, - isChecked, }) + + return this._switchNode } } diff --git a/source/scripts/components/home/components/settings/helpers/get-setting-item-element/get-setting-item-element.helper.js b/source/scripts/components/home/components/settings/helpers/get-setting-item-element/get-setting-item-element.helper.js index 0662fa3d..ff54bc79 100644 --- a/source/scripts/components/home/components/settings/helpers/get-setting-item-element/get-setting-item-element.helper.js +++ b/source/scripts/components/home/components/settings/helpers/get-setting-item-element/get-setting-item-element.helper.js @@ -1,6 +1,6 @@ import { createElement } from '~/helpers/helpers.js' -let getSettingItemElement = ({ name, label }) => { +let getSettingItemElement = ({ label, name }) => { return createElement(`