itube-specs 0.0.858 → 0.0.861
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
# itube-specs
|
|
2
2
|
|
|
3
3
|
Общий **Nuxt Layer** для сайтов itube. Держит единую базу: компоненты, composables, сервисы, утилиты,
|
|
4
|
-
runtime-хелперы, типы, lib-данные,
|
|
4
|
+
runtime-хелперы, типы, lib-данные, middleware, SSR-плагины, BFF-хендлеры (`server/api`) и **весь SCSS —
|
|
5
|
+
палитру, темы, миксины и глобальные стили**.
|
|
5
6
|
Приложения расширяют слой (`extends: ['itube-specs']`) и форкаются под разные сайты одной ниши —
|
|
6
7
|
поэтому слой должен оставаться **самодостаточным и site-agnostic**.
|
|
7
8
|
|
|
8
9
|
> Bitbucket: https://bitbucket.org/luckytube/specs/src/master/
|
|
10
|
+
>
|
|
11
|
+
> Заводишь новый сайт поверх слоя — [**NEW_SITE_CHECKLIST.md**](./NEW_SITE_CHECKLIST.md).
|
|
9
12
|
|
|
10
13
|
---
|
|
11
14
|
|
|
@@ -63,6 +66,9 @@ npm run patch # npm version patch — бамп версии перед п
|
|
|
63
66
|
```
|
|
64
67
|
|
|
65
68
|
Pre-commit (husky + lint-staged): на закоммиченных файлах прогоняются `eslint --fix` и `stylelint --fix`.
|
|
69
|
+
⚠️ **Шаблоны `.vue` не типизируются вообще.** Обычный `tsc` их не читает, а `vue-tsc` не подключён (накопился
|
|
70
|
+
бэклог ошибок в шаблонах, подключение — отдельная задача). Значит чистый `tsc` ничего не говорит про выражения
|
|
71
|
+
в шаблоне: арифметика над строковым union, неверный тип пропа, переименованное поле пройдут молча.
|
|
66
72
|
|
|
67
73
|
---
|
|
68
74
|
|
|
@@ -81,10 +87,52 @@ lib/ # статические scheme/config-данные (barrel index
|
|
|
81
87
|
middleware/ # глобальные: auth.global, normalize.global, age.global
|
|
82
88
|
plugins/ # SSR/клиент: country/countries/mobile (SSR), services.client, sentry.client, adv
|
|
83
89
|
server/ # BFF: api/** (тонкие прокси к внешнему API), utils/metrics, plugins/*, tasks
|
|
90
|
+
assets/
|
|
91
|
+
icons/ # спрайты/svg для <UiIcon>
|
|
92
|
+
scss/
|
|
93
|
+
vars/ # _palette (сырые $color-*), _vars (скаляры), _tokens (CSS custom props), _z-index, _index
|
|
94
|
+
themes/ # по папке на тему: light/_theme.scss, dark/_theme.scss — токены по компонентам
|
|
95
|
+
mixins/ # font-sizes, breakpoints, accessibility, page, video-card, surface, button
|
|
96
|
+
base/ # document, global, hacks, animations, loading
|
|
97
|
+
layout/ # layout, page
|
|
98
|
+
main.scss # точка входа: vars/tokens + base + layout
|
|
84
99
|
```
|
|
85
100
|
|
|
86
|
-
> `middleware`/`plugins`/`server` обязаны быть в `files` (whitelist) —
|
|
87
|
-
> (см. раздел `files`/`exports`).
|
|
101
|
+
> `middleware`/`plugins`/`server` и каждая подпапка `assets/scss/*` обязаны быть в `files` (whitelist) —
|
|
102
|
+
> иначе не попадут в паблиш (см. раздел `files`/`exports`).
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## Темы
|
|
107
|
+
|
|
108
|
+
Темы живут здесь, по папке на тему, и раздаются всем сайтам:
|
|
109
|
+
|
|
110
|
+
```
|
|
111
|
+
assets/scss/themes/light/_theme.scss
|
|
112
|
+
assets/scss/themes/dark/_theme.scss
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Приложение только **выбирает** одну — `theme:` в его `config/site.config.ts`. Оттуда значение читают
|
|
116
|
+
и `app.config.ts` (в рантайм), и `nuxt.config.ts`, который добавляет `themes/<theme>/` в Sass
|
|
117
|
+
`loadPaths`. `@forward 'theme'` в `vars/_index.scss` резолвится туда, потому что рядом с ним
|
|
118
|
+
`_theme.scss` нет.
|
|
119
|
+
|
|
120
|
+
**Папка-на-тему обязательна:** Sass требует литеральный путь в `@use`/`@forward`, значит имя файла
|
|
121
|
+
всегда `_theme.scss`, а варьироваться может только папка. Плоские `themes/light.scss` потребовали бы
|
|
122
|
+
`@forward 'themes/light'` — литерал, который нельзя подставить на билде.
|
|
123
|
+
|
|
124
|
+
Приоритет `loadPaths` — приложение первым, поэтому сайт может перекрыть любой партиал по имени:
|
|
125
|
+
свой `assets/scss/vars/_theme.scss` в проекте выиграет у темы слоя (относительный резолв Sass старше
|
|
126
|
+
`loadPaths`). Это точка пер-сайтовой темизации.
|
|
127
|
+
|
|
128
|
+
**Все токены обязаны быть во всех темах.** Отсутствующий токен — жёсткая ошибка Sass в момент, когда
|
|
129
|
+
тема выбрана, то есть падает вся сборка сайта, а не «поехал цвет». Сверять набор имён после любой
|
|
130
|
+
правки темы.
|
|
131
|
+
|
|
132
|
+
Контекстные различия (контрол внутри попапа, вариант кнопки, зависящий от темы) решают миксины
|
|
133
|
+
`surface()` и `button-variant()` из `mixins/`: место объявляет себя, а значения даёт тема через карты
|
|
134
|
+
`$surfaces` / `$button-variant-overrides`. Компоненты про темы не знают. `appConfig.theme` — только
|
|
135
|
+
для структурных различий (`v-if`, другой элемент), никогда для цвета.
|
|
88
136
|
|
|
89
137
|
---
|
|
90
138
|
|
|
@@ -117,8 +165,9 @@ ad-конфиг), теперь читается из `runtimeConfig.public` (з
|
|
|
117
165
|
`lib/` (scheme, css-breakpoints), middleware (`auth`/`normalize`/`age`), SSR-плагины
|
|
118
166
|
(`country`/`mobile`/`services`/`sentry`/`adv`), BFF-хендлеры `server/api/**` — всё site-agnostic.
|
|
119
167
|
- **Приложение:** только per-site — **значения** config (флаги/реклама/локали) через `runtimeConfig.public`
|
|
120
|
-
(слой держит пустые контейнеры-заглушки), `
|
|
121
|
-
`
|
|
168
|
+
(слой держит пустые контейнеры-заглушки), i18n-локали, `public/` и **выбор темы** (`theme:` в
|
|
169
|
+
`config/site.config.ts`). Своего SCSS у приложения нет: `assets/scss/` — пустой слот-оверрайд.
|
|
170
|
+
`server/` целиком в слое, включая locale-кластер.
|
|
122
171
|
|
|
123
172
|
---
|
|
124
173
|
|
|
@@ -128,10 +177,14 @@ ad-конфиг), теперь читается из `runtimeConfig.public` (з
|
|
|
128
177
|
|
|
129
178
|
- **Компоненты** — `pathPrefix: true`: имя = папка + файл (`ui/icon.vue` → `<UiIcon>`), BEM-класс = kebab
|
|
130
179
|
тега. Корень папки — `index.vue` (или `main.vue`, если иначе имя было бы односложным).
|
|
131
|
-
- **`as const`** вместо `enum` — доменные наборы в `runtime/constants
|
|
180
|
+
- **`as const`** вместо `enum` — доменные наборы в `runtime/constants/`, тип через
|
|
181
|
+
`typeof X[keyof typeof X]`. В enum не положить строку из API, он остаётся в бандле, и в
|
|
182
|
+
опубликованном пакете `import type` на нём ломается в рантайме. Фреймворковые union'ы не
|
|
183
|
+
оборачивать. Подробнее — в [CLAUDE.md](./CLAUDE.md).
|
|
132
184
|
- **Стили** — co-location в `<style lang="scss">` без `scoped`, flat-BEM, только дизайн-токены.
|
|
133
|
-
|
|
134
|
-
|
|
185
|
+
`vars` и `mixins` **авто-инжектятся** через `additionalData` приложения, поэтому в блоке компонента
|
|
186
|
+
`@use` писать не надо. Сам `sass` в слое не установлен — SCSS компилируется внутри приложения, но
|
|
187
|
+
все исходники (палитра, темы, миксины) лежат здесь.
|
|
135
188
|
- **Разметка** — семантические теги, `<div>` только когда ничего не подходит.
|
|
136
189
|
- **TS/JS** — всегда точка с запятой, без лишних комментариев.
|
|
137
190
|
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
transparent-backdrop
|
|
11
11
|
:back="isBackShow"
|
|
12
12
|
class="auth-popup"
|
|
13
|
-
@back="
|
|
13
|
+
@back="goBack"
|
|
14
14
|
>
|
|
15
15
|
<template #title>{{ $t('auth.create_new') }}</template>
|
|
16
16
|
<AuthRegister
|
|
@@ -27,12 +27,12 @@
|
|
|
27
27
|
transparent-backdrop
|
|
28
28
|
:back="isBackShow"
|
|
29
29
|
class="auth-popup"
|
|
30
|
-
@back="
|
|
30
|
+
@back="goBack"
|
|
31
31
|
>
|
|
32
32
|
<template #title>{{ $t('auth.welcome_back') }}</template>
|
|
33
33
|
<AuthLogin
|
|
34
34
|
@forgot="onRecoveryClick"
|
|
35
|
-
@create="currentStep
|
|
35
|
+
@create="currentStep = AuthSteps.Registration"
|
|
36
36
|
/>
|
|
37
37
|
</UiPopup>
|
|
38
38
|
</transition>
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
transparent-backdrop
|
|
45
45
|
:back="isBackShow"
|
|
46
46
|
class="auth-popup"
|
|
47
|
-
@back="
|
|
47
|
+
@back="goBack"
|
|
48
48
|
>
|
|
49
49
|
<template #title>{{ $t('auth.recovery_title')}}</template>
|
|
50
50
|
<AuthRecovery @login="onLoginClick"/>
|
|
@@ -59,6 +59,20 @@ const { isAuthPopupOpen, currentStep, additionalText } = useAuthPopup();
|
|
|
59
59
|
|
|
60
60
|
const backShow = ref(false);
|
|
61
61
|
|
|
62
|
+
// Куда ведёт «назад» с каждого шага. Registration — начальный, назад с него нет.
|
|
63
|
+
const previousStep: Partial<Record<AuthSteps, AuthSteps>> = {
|
|
64
|
+
[AuthSteps.Login]: AuthSteps.Registration,
|
|
65
|
+
[AuthSteps.Recovery]: AuthSteps.Login,
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
function goBack(): void {
|
|
69
|
+
const previous = previousStep[currentStep.value];
|
|
70
|
+
|
|
71
|
+
if (previous) {
|
|
72
|
+
currentStep.value = previous;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
62
76
|
function onLoginClick(): void {
|
|
63
77
|
currentStep.value = AuthSteps.Login;
|
|
64
78
|
backShow.value = true;
|
package/package.json
CHANGED