elcrm 1.1.36 → 1.1.39

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.
@@ -16,14 +16,14 @@ function checkThemeTokens(options) {
16
16
  const used = new Set;
17
17
  for (const file of listModuleCss(options.libDir)) {
18
18
  const css = readFileSync(file, "utf8");
19
- for (const m of css.matchAll(/var\(\s*(--[a-z0-9-]+)\s*\)/gi)) {
19
+ for (const m of css.matchAll(/var\(\s*(--[a-zA-Z0-9-]+)/g)) {
20
20
  used.add(m[1]);
21
21
  }
22
22
  }
23
23
  const defined = new Set;
24
24
  for (const file of options.themeFiles) {
25
25
  const css = readFileSync(file, "utf8");
26
- for (const m of css.matchAll(/(--[a-z0-9-]+)\s*:/gi)) {
26
+ for (const m of css.matchAll(/(--[a-zA-Z0-9-]+)\s*:/g)) {
27
27
  defined.add(m[1]);
28
28
  }
29
29
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "elcrm",
3
- "version": "1.1.36",
3
+ "version": "1.1.39",
4
4
  "description": "CLI @elcrm/*: doctor --fix (порядок проекта), update, css, docs, cursor, kit, migrate, publish",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -55,6 +55,15 @@ alwaysApply: true
55
55
 
56
56
  После правок CLI достаточно, чтобы в приложениях снова вызвали `elcrm docs` и `elcrm cursor` — они перезапишут `docs/` и `.cursor/`.
57
57
 
58
+ **Токены и elUI** — не руками в elUI и не отдельный сервер:
59
+
60
+ ```bash
61
+ # из elCRM.cli (или bun run docs:hub в пакете)
62
+ elcrm hub # collect → check → push в elUI
63
+ ```
64
+
65
+ Автотаблица в шпаргалке (`<!-- elcrm-hub-tokens -->`) и `generated/tokens.json`. API/можно/нельзя по-прежнему писать руками в `templates/elcrm-docs/`.
66
+
58
67
  ## Чеклист по типу правки в `src/`
59
68
 
60
69
  ### 1. Публичный API (компонент, хук, функция, тип, props)
@@ -10,6 +10,7 @@ alwaysApply: true
10
10
  - в проекте: `docs/*.elCRM.md`
11
11
  - копия для агента: `.cursor/docs/*.elCRM.md`
12
12
  - обновить оба: `elcrm docs && elcrm cursor`
13
+ - источник шпаргалок: **elCRM.cli** (`elcrm hub` после смены токенов в пакетах)
13
14
 
14
15
  | Файл | Пакет | Делать так |
15
16
  | ------------------------ | ---------------------- | ------------------------------------------------------- |
@@ -26,6 +27,7 @@ alwaysApply: true
26
27
  | `TOOLTIP.elCRM.md` | `@elcrm/tooltip` | `<Tooltip content>`, не `title` |
27
28
  | `ICONS.elCRM.md` | `@elcrm/icons` | `Icons.Line`, vite `icons()`, `icons update` |
28
29
  | `FORM.elCRM.md` | `@elcrm/form` | поля + useForm, не native input |
30
+ | `SEARCH.elCRM.md` | `@elcrm/search` | поиск; токены `--search-*` |
29
31
  | `COMPONENTS.elCRM.md` | `@elcrm/components` | Layout/Header/Sidebar/Popover/Dropdown; migrate components |
30
32
  | `SERVER.elCRM.md` | `@elcrm/server` | createServer + createRouter, не REST, не node:fs |
31
33
 
@@ -24,3 +24,29 @@ const ok = await Alert.Confirm({ title: "Удалить?", icon: "warning" });
24
24
  - `window.alert` / `window.confirm`.
25
25
  - Несколько `Alert.Init`.
26
26
  - Нативные `<button>` в UI приложения, если это действие формы — `@elcrm/button`.
27
+
28
+ <!-- elcrm-hub-tokens:start -->
29
+ Автотаблица: `elcrm hub collect` · **@elcrm/alert@0.1.1**. Не править руками.
30
+
31
+ | Токен | Слой | Значение |
32
+ | --- | --- | --- |
33
+ | `--alert-background` | dark | `rgba(28, 28, 30, 0.95)` |
34
+ | `--alert-button-bg` | dark | `transparent` |
35
+ | `--alert-button-bg-hover` | dark | `rgba(255, 255, 255, 0.1)` |
36
+ | `--alert-button-color` | dark | `#5ac8fa` |
37
+ | `--alert-color` | dark | `#ffffff` |
38
+ | `--alert-overlay` | dark | `rgba(0, 0, 0, 0.6)` |
39
+ | `--alert-overlay-filter` | dark | `blur(4px)` |
40
+ | `--alert-separator-color` | dark | `rgba(255, 255, 255, 0.1)` |
41
+ | `--alert-shadow` | dark | `0 8px 32px rgba(0, 0, 0, 0.5)` |
42
+ | `--alert-background` | light | `rgba(255, 255, 255, 0.95)` |
43
+ | `--alert-button-bg` | light | `transparent` |
44
+ | `--alert-button-bg-hover` | light | `rgba(0, 0, 0, 0.05)` |
45
+ | `--alert-button-color` | light | `#1b6ac0` |
46
+ | `--alert-color` | light | `#1a1a1a` |
47
+ | `--alert-overlay` | light | `rgba(0, 0, 0, 0.4)` |
48
+ | `--alert-overlay-filter` | light | `blur(4px)` |
49
+ | `--alert-separator-color` | light | `rgba(0, 0, 0, 0.1)` |
50
+ | `--alert-shadow` | light | `0 8px 32px rgba(0, 0, 0, 0.2)` |
51
+
52
+ <!-- elcrm-hub-tokens:end -->
@@ -36,3 +36,10 @@ Side-fields рядом с `status`/`data`: `ssid` → storageKey, `url` → urlK
36
36
  - Путать URL: base уже с prefix (`/v1/` или `/api/`), путь RPC без лишнего `/api`.
37
37
  - Игнорировать logout/refresh — сессия сломается.
38
38
  - `createPasskey` из `@elcrm/passkey` — это другой пакет; HTTP passkey тоже через клиент/сервер passkey.
39
+
40
+ <!-- elcrm-hub-tokens:start -->
41
+ Автотаблица: `elcrm hub collect` · **@elcrm/api@0.1.56**. Не править руками.
42
+
43
+ _В пакете нет CSS-токенов (или только runtime var)._
44
+
45
+ <!-- elcrm-hub-tokens:end -->
@@ -35,3 +35,10 @@ import { Button } from "@elcrm/button";
35
35
  - `size="sm"|"md"`.
36
36
  - `import "@elcrm/button/themes.css"` — нет такого файла; токены в theme приложения.
37
37
  - Хардкод цветов вместо `--button-*`.
38
+
39
+ <!-- elcrm-hub-tokens:start -->
40
+ Автотаблица: `elcrm hub collect` · **@elcrm/button@1.2.0**. Не править руками.
41
+
42
+ _В пакете нет CSS-токенов (или только runtime var)._
43
+
44
+ <!-- elcrm-hub-tokens:end -->
@@ -18,7 +18,7 @@ elcrm cursor
18
18
  | # | Команда | Что делает |
19
19
  | --- | --- | --- |
20
20
  | 1 | `elcrm update --fix --test` | Обновляет глобальный `elcrm` + все `@elcrm/*` в `package.json` → install → **migrate front** (API/токены/css-sanitize) → внутри `--fix` ещё раз **sync CSS** → `elcrm test` |
21
- | 2 | `elcrm css` | Недостающие **цвета** → `theme-light` / `theme-dark`. Геометрию из пакетов с `tokens.css` **не** дублирует в `theme.css` (дефолты через `@import …/tokens.css`). **Не дописывает** `--button-*-shadow: none` и снимает такие строки. В `elcrm.css`: **добавляет** рабочие `@import`, **удаляет битые**. Затем css-sanitize |
21
+ | 2 | `elcrm css` | Недостающие **цвета** → `theme-light` / `theme-dark`. Геометрию из пакетов с `tokens.css` **не** дублирует в `theme.css` (дефолты через `@import …/tokens.css`). `--button-*-shadow` **синкается** как геометрия (`@elcrm/button@1.2+` без fallback). В `elcrm.css`: **добавляет** рабочие `@import`, **удаляет битые**. Затем css-sanitize. `--check` — покрытие `var(--*)` без записи |
22
22
  | 3 | `elcrm docs` | Перезаписывает `docs/*.elCRM.md` (шпаргалки пакетов) |
23
23
  | 4 | `elcrm cursor` | `.cursor/rules` + `.cursor/docs` + `AGENTS.md` для агента |
24
24
 
@@ -44,10 +44,31 @@ elcrm update --test # + elcrm test (обычно вместе: --fix --
44
44
  ```bash
45
45
  elcrm css # токены + починка elcrm.css
46
46
  elcrm css --dry
47
+ elcrm css --check # пробелы var(--*) → exit 1
47
48
  elcrm css --dir=./web # panel: web/
48
49
  ```
49
50
 
50
- Почему Vite ругался на `@elcrm/search/light.css`: в `elcrm.css` остался `@import`, а в **установленном** `@elcrm/search@0.1.4` нет export `./light.css`. Раньше `css` только добавлял imports — теперь **снимает** такие строки. Лечение: `elcrm css` (или `update --fix`).
51
+ ### Автообновление токенов
52
+
53
+ После `bun update` / смены `@elcrm/*` в **приложении**:
54
+
55
+ ```bash
56
+ elcrm css # дописать токены + @import
57
+ elcrm css --check # CI: пробелы → exit 1
58
+ elcrm doctor # migrate + css
59
+ elcrm update --fix # обновить пакеты + doctor
60
+ ```
61
+
62
+ После правки **самого пакета** `@elcrm/*` (не отдельный docs-сервер):
63
+
64
+ ```bash
65
+ cd ../elCRM.cli
66
+ elcrm hub # токены → шпаргалки CLI → elUI.web/docs/elcrm
67
+ elcrm docs && elcrm cursor # в приложении
68
+ ```
69
+
70
+ В panel-шаблоне: `bun run css` / `bun run css:check`.
71
+
51
72
 
52
73
  ### `docs` / `cursor` — шпаргалки
53
74
 
@@ -84,7 +84,7 @@ import type { PricingPlan, HealthmapData, NavTreeItem } from "@elcrm/components"
84
84
 
85
85
  ## Меню
86
86
 
87
- - **Menu** — inline-навигация в шапке. `items` + `value` / `defaultValue` + `onValueChange`. `badge` (`0` скрыт). `variant="line"` — вкладки с чертой снизу.
87
+ - **Menu** — inline-навигация в шапке. `items` + `value` / `defaultValue` + `onValueChange`. `badge` (`0` скрыт). `ariaLabel` — подпись для скринридера, если `label` — иконка. `variant="line"` — вкладки с чертой снизу.
88
88
  - **Dropdown** — выпадающее меню по `items`/`groups` (portal) + `onValueChange`. `placement="auto"|"top"|"bottom"`. `size` — высота триггера; в `Toolbar` берётся сам. `item.submenu` — только шеврон (намёк); вложенное меню — снаружи.
89
89
  - **Popover** — свой попап в portal (якорь + `children`). По умолчанию **без** `role="menu"`; меню пунктов — `Dropdown` (`role="menu"`). ARIA на триггере. z-index: `acquireOverlayZIndex`. Канон `trigger={(api) => …}`.
90
90
  - **Breadcrumb** — `items` + `separator` / `collapseAfter`. `item.dropdown` — только ↕-намёк; меню — обернуть в `Dropdown`.
@@ -107,6 +107,7 @@ import type { PricingPlan, HealthmapData, NavTreeItem } from "@elcrm/components"
107
107
 
108
108
  - `--layout-height` — высота каркаса `Layout` при `fixed` (по умолчанию `100dvh`).
109
109
  - `--layout-padding` / `--layout-margin` / `--layout-max-width` — отступы и макс. ширина корня Layout (`0` / `none` = на весь вьюпорт).
110
+ - `--layout-main-padding` — padding у `<main>` (`.slm`): сверху/снизу между шапкой и контентом (`0` по умолчанию; например `16px 0`).
110
111
  - `--header-border` — рамка Header (shorthand: все стороны и толщина). Только снизу: `none` + линия через `--header-shadow`.
111
112
  - `--header-nav-justify` — выравнивание `nav` в шапке (`flex-start` / `center` / `flex-end`).
112
113
  - `<Toolbar size="s" width="l" align="start">` — один размер для Search / `*Field` / Button / Dropdown. `width="s"` — ряд по контенту. Свой `size` у ребёнка важнее.
@@ -141,3 +142,217 @@ elcrm cursor
141
142
  ```
142
143
 
143
144
  Пилюля: `elcrm migrate components` (также внутри `migrate front` / `update --fix`).
145
+
146
+ <!-- elcrm-hub-tokens:start -->
147
+ Автотаблица: `elcrm hub collect` · **@elcrm/components@0.5.3**. Не править руками.
148
+
149
+ | Токен | Слой | Значение |
150
+ | --- | --- | --- |
151
+ | `--avatar-background` | dark | `var(--shell-color-accent)` |
152
+ | `--avatar-border` | dark | `1px solid var(--shell-border)` |
153
+ | `--avatar-color` | dark | `var(--button-primary-fg)` |
154
+ | `--avatar-name-description-color` | dark | `var(--shell-color-muted)` |
155
+ | `--avatar-name-title-color` | dark | `var(--shell-color)` |
156
+ | `--avatar-outline-active` | dark | `2px solid color-mix(in srgb, var(--accent) 70%, white)` |
157
+ | `--banner-bg` | dark | `color-mix(in srgb, var(--shell-color-accent) 8%, var(--shell-bg))` |
158
+ | `--banner-border` | dark | `color-mix(in srgb, var(--shell-color-accent) 35%, var(--shell-border))` |
159
+ | `--chat-background` | dark | `var(--shell-background)` |
160
+ | `--chat-border` | dark | `1px solid var(--shell-border)` |
161
+ | `--code-block-bg` | dark | `var(--shell-background)` |
162
+ | `--header-border` | dark | `1px solid var(--shell-border)` |
163
+ | `--header-shadow` | dark | `none` |
164
+ | `--healthmap-l1` | dark | `color-mix(in srgb, var(--shell-color-success) 25%, var(--shell-background-muted))` |
165
+ | `--healthmap-l2` | dark | `color-mix(in srgb, var(--shell-color-success) 45%, transparent)` |
166
+ | `--healthmap-l3` | dark | `color-mix(in srgb, var(--shell-color-success) 70%, transparent)` |
167
+ | `--layout-main-background` | dark | `transparent` |
168
+ | `--layout-main-border` | dark | `none` |
169
+ | `--layout-main-shadow` | dark | `none` |
170
+ | `--panel-info-backdrop` | dark | `color-mix(in srgb, var(--shell-color) 35%, transparent)` |
171
+ | `--shell-background` | dark | `var(--panel)` |
172
+ | `--shell-background-hover` | dark | `color-mix(in srgb, var(--text) 8%, transparent)` |
173
+ | `--shell-background-muted` | dark | `var(--bg)` |
174
+ | `--shell-background-selected` | dark | `color-mix(in srgb, var(--accent) 14%, transparent)` |
175
+ | `--shell-bg` | dark | `var(--shell-background-muted)` |
176
+ | `--shell-border` | dark | `var(--line)` |
177
+ | `--shell-color` | dark | `var(--text)` |
178
+ | `--shell-color-accent` | dark | `var(--accent)` |
179
+ | `--shell-color-danger` | dark | `var(--danger)` |
180
+ | `--shell-color-muted` | dark | `var(--muted)` |
181
+ | `--shell-color-success` | dark | `var(--success)` |
182
+ | `--shell-color-warning` | dark | `var(--warning)` |
183
+ | `--shell-shadow` | dark | `var(--shadow)` |
184
+ | `--sidebar-account-danger-hover` | dark | `color-mix( in srgb, var(--shell-color-danger) 14%, transparent )` |
185
+ | `--sidebar-account-menu-bg` | dark | `var(--shell-background)` |
186
+ | `--sidebar-account-menu-border` | dark | `var(--shell-border)` |
187
+ | `--sidebar-account-menu-color` | dark | `var(--shell-color)` |
188
+ | `--sidebar-account-menu-shadow` | dark | `var(--popup-shadow, var(--shell-shadow))` |
189
+ | `--sidebar-block-bg` | dark | `var(--shell-background)` |
190
+ | `--sidebar-block-border` | dark | `var(--shell-border)` |
191
+ | `--sidebar-block-shadow` | dark | `none` |
192
+ | `--sidebar-item-active-bg` | dark | `var(--shell-background-selected)` |
193
+ | `--split-handle-bg` | dark | `var(--shell-border)` |
194
+ | `--split-handle-bg-hover` | dark | `color-mix( in srgb, var(--shell-color-accent) 25%, var(--shell-border) )` |
195
+ | `--table-head-background` | dark | `var(--shell-background)` |
196
+ | `--action-group-gap` | geometry | `var(--shell-gap-sm)` |
197
+ | `--avatar-font-size-l` | geometry | `0.95rem` |
198
+ | `--avatar-font-size-m` | geometry | `0.7rem` |
199
+ | `--avatar-font-size-s` | geometry | `0.6rem` |
200
+ | `--avatar-font-weight` | geometry | `700` |
201
+ | `--avatar-group-overlap` | geometry | `-0.4rem` |
202
+ | `--avatar-group-ring` | geometry | `2px` |
203
+ | `--avatar-outline-offset` | geometry | `0` |
204
+ | `--avatar-radius` | geometry | `999px` |
205
+ | `--avatar-size-l` | geometry | `2.75rem` |
206
+ | `--avatar-size-m` | geometry | `2rem` |
207
+ | `--avatar-size-s` | geometry | `1.5rem` |
208
+ | `--banner-padding` | geometry | `0.55rem 0.85rem` |
209
+ | `--card-pointer` | geometry | `auto` |
210
+ | `--chat-body-padding` | geometry | `0` |
211
+ | `--chat-footer-padding` | geometry | `var(--shell-gap)` |
212
+ | `--chat-header-padding` | geometry | `var(--shell-gap)` |
213
+ | `--chat-list-width` | geometry | `340px` |
214
+ | `--chat-messages-body-padding` | geometry | `16px 16px 20px` |
215
+ | `--chat-messages-footer-padding` | geometry | `10px 12px 12px` |
216
+ | `--chat-messages-header-padding` | geometry | `14px 16px` |
217
+ | `--chat-radius` | geometry | `var(--shell-radius)` |
218
+ | `--chat-split-gap` | geometry | `var(--shell-gap-lg)` |
219
+ | `--code-block-bar-padding` | geometry | `0.4rem 0.75rem` |
220
+ | `--code-block-font-family` | geometry | `ui-monospace, SFMono-Regular, Menlo, monospace` |
221
+ | `--code-block-font-size` | geometry | `0.8rem` |
222
+ | `--code-block-line-height` | geometry | `1.55` |
223
+ | `--code-block-padding` | geometry | `0.85rem 1rem` |
224
+ | `--control-font-size-s` | geometry | `0.8125rem` |
225
+ | `--dropdown-max-height` | geometry | `20rem` |
226
+ | `--dropdown-max-width` | geometry | `20rem` |
227
+ | `--dropdown-min-width` | geometry | `12rem` |
228
+ | `--empty-max-width` | geometry | `36rem` |
229
+ | `--empty-padding` | geometry | `2rem` |
230
+ | `--header-height` | geometry | `52px` |
231
+ | `--header-margin` | geometry | `0` |
232
+ | `--header-nav-justify` | geometry | `flex-start` |
233
+ | `--header-radius` | geometry | `var(--shell-radius)` |
234
+ | `--header-z` | geometry | `30` |
235
+ | `--healthmap-cell` | geometry | `12px` |
236
+ | `--healthmap-gap` | geometry | `3px` |
237
+ | `--healthmap-l0` | geometry | `var(--shell-background-muted)` |
238
+ | `--healthmap-l4` | geometry | `var(--shell-color-success)` |
239
+ | `--item-column-gap` | geometry | `var(--shell-gap)` |
240
+ | `--item-column-icon-radius` | geometry | `var(--avatar-radius)` |
241
+ | `--item-column-icon-size` | geometry | `40px` |
242
+ | `--item-column-meta-size` | geometry | `var(--shell-font-size-sm)` |
243
+ | `--item-column-title-line` | geometry | `1.3` |
244
+ | `--item-column-title-size` | geometry | `var(--shell-font-size)` |
245
+ | `--layout-gap` | geometry | `0` |
246
+ | `--layout-height` | geometry | `100dvh` |
247
+ | `--layout-main-padding` | geometry | `0` |
248
+ | `--layout-main-radius` | geometry | `0` |
249
+ | `--layout-margin` | geometry | `0` |
250
+ | `--layout-max-width` | geometry | `none` |
251
+ | `--layout-padding` | geometry | `0` |
252
+ | `--loading-min-height` | geometry | `min(50vh, 24rem)` |
253
+ | `--nav-sections-main-max-width` | geometry | `720px` |
254
+ | `--nav-sections-nav-width` | geometry | `220px` |
255
+ | `--nav-sections-padding` | geometry | `var(--section-padding)` |
256
+ | `--panel-info-overlay-max` | geometry | `24rem` |
257
+ | `--panel-info-width` | geometry | `min(22rem, 42vw)` |
258
+ | `--panel-info-width-min` | geometry | `16rem` |
259
+ | `--pricing-card-min-width` | geometry | `16rem` |
260
+ | `--pricing-table-label-width` | geometry | `10rem` |
261
+ | `--section-auth-card-max-width` | geometry | `22rem` |
262
+ | `--section-padding` | geometry | `1.5rem 1.75rem 2.5rem` |
263
+ | `--section-title-size` | geometry | `1.5rem` |
264
+ | `--section-title-size-md` | geometry | `1.25rem` |
265
+ | `--shell-check-size` | geometry | `18px` |
266
+ | `--shell-disabled-opacity` | geometry | `0.55` |
267
+ | `--shell-font-size` | geometry | `var(--control-font-size)` |
268
+ | `--shell-font-size-lg` | geometry | `18px` |
269
+ | `--shell-font-size-sm` | geometry | `13px` |
270
+ | `--shell-font-weight` | geometry | `600` |
271
+ | `--shell-gap` | geometry | `12px` |
272
+ | `--shell-gap-lg` | geometry | `16px` |
273
+ | `--shell-gap-sm` | geometry | `8px` |
274
+ | `--shell-icon-size` | geometry | `20px` |
275
+ | `--shell-padding` | geometry | `var(--shell-padding-block) var(--shell-padding-inline)` |
276
+ | `--shell-padding-block` | geometry | `10px` |
277
+ | `--shell-padding-inline` | geometry | `14px` |
278
+ | `--shell-radius` | geometry | `var(--control-radius)` |
279
+ | `--shell-status-size` | geometry | `10px` |
280
+ | `--shell-z` | geometry | `var(--elcrm-z-popover, 1000)` |
281
+ | `--sidebar-account-chip-gap` | geometry | `10px` |
282
+ | `--sidebar-account-chip-padding` | geometry | `8px` |
283
+ | `--sidebar-account-chip-radius` | geometry | `14px` |
284
+ | `--sidebar-account-item-gap` | geometry | `12px` |
285
+ | `--sidebar-account-item-hover` | geometry | `var(--shell-background-hover)` |
286
+ | `--sidebar-account-item-icon` | geometry | `var(--shell-color-muted)` |
287
+ | `--sidebar-account-item-padding` | geometry | `10px 12px` |
288
+ | `--sidebar-account-item-radius` | geometry | `12px` |
289
+ | `--sidebar-account-menu-padding` | geometry | `6px` |
290
+ | `--sidebar-account-menu-radius` | geometry | `18px` |
291
+ | `--sidebar-block-radius` | geometry | `14px` |
292
+ | `--sidebar-group-font-size` | geometry | `11px` |
293
+ | `--sidebar-icon-active` | geometry | `var(--shell-color-accent)` |
294
+ | `--sidebar-icon-size` | geometry | `16px` |
295
+ | `--sidebar-indent` | geometry | `14px` |
296
+ | `--sidebar-item-active` | geometry | `var(--shell-color)` |
297
+ | `--sidebar-item-font-size` | geometry | `var(--shell-font-size-sm)` |
298
+ | `--sidebar-item-padding` | geometry | `6px 10px` |
299
+ | `--sidebar-pad-x` | geometry | `var(--shell-gap)` |
300
+ | `--sidebar-pad-y` | geometry | `var(--shell-gap-lg)` |
301
+ | `--sidebar-width` | geometry | `248px` |
302
+ | `--split-handle-size` | geometry | `6px` |
303
+ | `--stack-columns-template` | geometry | `minmax(0, 1fr)` |
304
+ | `--stack-grid-min` | geometry | `180px` |
305
+ | `--stat-value-size` | geometry | `1.75rem` |
306
+ | `--table-cell-padding` | geometry | `0.55rem 0.7rem` |
307
+ | `--table-code-font-size` | geometry | `0.8rem` |
308
+ | `--table-font-size` | geometry | `0.9rem` |
309
+ | `--table-head-font-size` | geometry | `0.75rem` |
310
+ | `--table-max-height` | geometry | `none` |
311
+ | `--toolbar-gap` | geometry | `var(--shell-gap-sm)` |
312
+ | `--avatar-background` | light | `var(--shell-color-accent)` |
313
+ | `--avatar-border` | light | `1px solid var(--shell-border)` |
314
+ | `--avatar-color` | light | `var(--button-primary-fg)` |
315
+ | `--avatar-name-description-color` | light | `var(--shell-color-muted)` |
316
+ | `--avatar-name-title-color` | light | `var(--shell-color)` |
317
+ | `--avatar-outline-active` | light | `2px solid color-mix(in srgb, var(--accent) 70%, white)` |
318
+ | `--banner-bg` | light | `color-mix(in srgb, var(--shell-color-accent) 8%, var(--shell-bg))` |
319
+ | `--banner-border` | light | `color-mix(in srgb, var(--shell-color-accent) 35%, var(--shell-border))` |
320
+ | `--chat-background` | light | `var(--shell-background)` |
321
+ | `--chat-border` | light | `1px solid var(--shell-border)` |
322
+ | `--code-block-bg` | light | `var(--shell-background)` |
323
+ | `--header-border` | light | `1px solid var(--shell-border)` |
324
+ | `--header-shadow` | light | `none` |
325
+ | `--healthmap-l1` | light | `color-mix(in srgb, var(--shell-color-success) 25%, var(--shell-background-muted))` |
326
+ | `--healthmap-l2` | light | `color-mix(in srgb, var(--shell-color-success) 45%, transparent)` |
327
+ | `--healthmap-l3` | light | `color-mix(in srgb, var(--shell-color-success) 70%, transparent)` |
328
+ | `--layout-main-background` | light | `transparent` |
329
+ | `--layout-main-border` | light | `none` |
330
+ | `--layout-main-shadow` | light | `none` |
331
+ | `--panel-info-backdrop` | light | `color-mix(in srgb, var(--shell-color) 35%, transparent)` |
332
+ | `--shell-background` | light | `var(--panel)` |
333
+ | `--shell-background-hover` | light | `color-mix(in srgb, var(--text) 6%, transparent)` |
334
+ | `--shell-background-muted` | light | `var(--bg)` |
335
+ | `--shell-background-selected` | light | `color-mix(in srgb, var(--accent) 10%, transparent)` |
336
+ | `--shell-bg` | light | `var(--shell-background-muted)` |
337
+ | `--shell-border` | light | `var(--line)` |
338
+ | `--shell-color` | light | `var(--text)` |
339
+ | `--shell-color-accent` | light | `var(--accent)` |
340
+ | `--shell-color-danger` | light | `var(--danger)` |
341
+ | `--shell-color-muted` | light | `var(--muted)` |
342
+ | `--shell-color-success` | light | `var(--success)` |
343
+ | `--shell-color-warning` | light | `var(--warning)` |
344
+ | `--shell-shadow` | light | `var(--shadow)` |
345
+ | `--sidebar-account-danger-hover` | light | `color-mix( in srgb, var(--shell-color-danger) 12%, transparent )` |
346
+ | `--sidebar-account-menu-bg` | light | `var(--shell-background)` |
347
+ | `--sidebar-account-menu-border` | light | `var(--shell-border)` |
348
+ | `--sidebar-account-menu-color` | light | `var(--shell-color)` |
349
+ | `--sidebar-account-menu-shadow` | light | `var(--popup-shadow, var(--shell-shadow))` |
350
+ | `--sidebar-block-bg` | light | `var(--shell-background)` |
351
+ | `--sidebar-block-border` | light | `var(--shell-border)` |
352
+ | `--sidebar-block-shadow` | light | `none` |
353
+ | `--sidebar-item-active-bg` | light | `var(--shell-background-selected)` |
354
+ | `--split-handle-bg` | light | `var(--shell-border)` |
355
+ | `--split-handle-bg-hover` | light | `color-mix( in srgb, var(--shell-color-accent) 25%, var(--shell-border) )` |
356
+ | `--table-head-background` | light | `var(--shell-background)` |
357
+
358
+ <!-- elcrm-hub-tokens:end -->
@@ -54,3 +54,143 @@ const form = useForm({ login: "", password: "" });
54
54
  - Серверные пакеты `@elcrm/db|jwt|cron|tb` на фронте.
55
55
 
56
56
  Подпути (tree-shake): `@elcrm/form/fields/Date`, `@elcrm/form/hooks/use`.
57
+
58
+ <!-- elcrm-hub-tokens:start -->
59
+ Автотаблица: `elcrm hub collect` · **@elcrm/form@0.1.20**. Не править руками.
60
+
61
+ | Токен | Слой | Значение |
62
+ | --- | --- | --- |
63
+ | `--field-background` | dark | `#1c1c1e` |
64
+ | `--field-background-active` | dark | `#8e8e93` |
65
+ | `--field-background-disabled` | dark | `#2c2c2e` |
66
+ | `--field-background-focus` | dark | `rgba(255, 255, 255, 0.06)` |
67
+ | `--field-border` | dark | `0px solid #38383a` |
68
+ | `--field-border-disabled` | dark | `#48484a` |
69
+ | `--field-border-focus` | dark | `#636366` |
70
+ | `--field-border-hover` | dark | `#48484a` |
71
+ | `--field-check-box-border` | dark | `2px solid #8e8e93` |
72
+ | `--field-color` | dark | `#ffffff` |
73
+ | `--field-color-disabled` | dark | `#636366` |
74
+ | `--field-drag-border` | dark | `2px dashed #48484a` |
75
+ | `--field-drag-border-hover` | dark | `#8e8e93` |
76
+ | `--field-error-background` | dark | `rgba(255, 69, 58, 0.15)` |
77
+ | `--field-error-border` | dark | `#ff453a` |
78
+ | `--field-error-color` | dark | `#ff6961` |
79
+ | `--field-focus-ring` | dark | `rgba(235, 235, 245, 0.22)` |
80
+ | `--field-focus-shadow` | dark | `0 0 0 3px var(--field-focus-ring)` |
81
+ | `--field-icon-color` | dark | `#8e8e93` |
82
+ | `--field-label-color` | dark | `#aeaeb2` |
83
+ | `--field-placeholder` | dark | `#8e8e93` |
84
+ | `--field-range-fill` | dark | `#30d158` |
85
+ | `--field-range-thumb` | dark | `#e4e4e7` |
86
+ | `--field-range-track` | dark | `#39393d` |
87
+ | `--field-selection-bg` | dark | `rgba(235, 235, 245, 0.18)` |
88
+ | `--field-selection-color` | dark | `#ffffff` |
89
+ | `--field-tabs-active-bg` | dark | `rgba(255, 255, 255, 0.12)` |
90
+ | `--field-tabs-color` | dark | `#8e8e93` |
91
+ | `--field-tabs-color-active` | dark | `#ffffff` |
92
+ | `--field-tabs-divider` | dark | `1px solid #48484a` |
93
+ | `--popup-shadow` | dark | `0 6px 24px 0 #00000040` |
94
+ | `--select-background` | dark | `#2c2c2e` |
95
+ | `--select-color` | dark | `#ffffff` |
96
+ | `--select-li-focus-bg` | dark | `#48484a` |
97
+ | `--select-li-hover-bg` | dark | `#3a3a3c` |
98
+ | `--select-li-selected-bg` | dark | `#48484a` |
99
+ | `--select-overlay` | dark | `transparent` |
100
+ | `--select-separator` | dark | `1px solid #48484a` |
101
+ | `--color-picker-handle` | geometry | `14px` |
102
+ | `--color-picker-input-radius` | geometry | `5px` |
103
+ | `--color-picker-pad` | geometry | `10px` |
104
+ | `--color-picker-radius` | geometry | `16px` |
105
+ | `--color-picker-swatch` | geometry | `20px` |
106
+ | `--color-picker-width` | geometry | `260px` |
107
+ | `--control-font-size` | geometry | `17px` |
108
+ | `--control-height` | geometry | `44px` |
109
+ | `--control-height-l` | geometry | `48px` |
110
+ | `--control-height-m` | geometry | `var(--control-height)` |
111
+ | `--control-height-s` | geometry | `32px` |
112
+ | `--control-radius` | geometry | `12px` |
113
+ | `--date-popup-cell-radius` | geometry | `5px` |
114
+ | `--date-popup-min-width` | geometry | `259px` |
115
+ | `--date-popup-padding` | geometry | `10px 12px 12px` |
116
+ | `--date-popup-radius` | geometry | `10px` |
117
+ | `--date-popup-row-height` | geometry | `34px` |
118
+ | `--elcrm-z-popover` | geometry | `1000` |
119
+ | `--elcrm-z-popover-front` | geometry | `1001` |
120
+ | `--field-block-gap` | geometry | `0` |
121
+ | `--field-check-size` | geometry | `22px` |
122
+ | `--field-code-gap` | geometry | `8px` |
123
+ | `--field-code-size` | geometry | `var(--field-height)` |
124
+ | `--field-drag-min-height` | geometry | `88px` |
125
+ | `--field-error-gap` | geometry | `6px` |
126
+ | `--field-error-size` | geometry | `12px` |
127
+ | `--field-group-gap` | geometry | `12px` |
128
+ | `--field-height` | geometry | `var(--control-height)` |
129
+ | `--field-icon-gap` | geometry | `10px` |
130
+ | `--field-icon-size` | geometry | `20px` |
131
+ | `--field-label-gap` | geometry | `10px` |
132
+ | `--field-label-size` | geometry | `14px` |
133
+ | `--field-note-height` | geometry | `100px` |
134
+ | `--field-note-line-height` | geometry | `1.5` |
135
+ | `--field-padding` | geometry | `var(--field-padding-block) var(--field-padding-inline)` |
136
+ | `--field-padding-block` | geometry | `calc(var(--field-height) * 0.18)` |
137
+ | `--field-padding-inline` | geometry | `calc(var(--field-height) * 0.32)` |
138
+ | `--field-radio-size` | geometry | `20px` |
139
+ | `--field-radius` | geometry | `var(--control-radius)` |
140
+ | `--field-range-bar-height` | geometry | `14px` |
141
+ | `--field-range-line-height` | geometry | `2px` |
142
+ | `--field-range-thumb-size` | geometry | `12px` |
143
+ | `--field-rating-size` | geometry | `22px` |
144
+ | `--field-search-expand-min` | geometry | `180px` |
145
+ | `--field-search-list-max-height` | geometry | `240px` |
146
+ | `--field-search-min-width` | geometry | `200px` |
147
+ | `--field-tabs-gap` | geometry | `4px` |
148
+ | `--field-tabs-item-padding` | geometry | `4px 12px` |
149
+ | `--field-tabs-item-radius` | geometry | `var(--field-radius)` |
150
+ | `--field-tabs-padding` | geometry | `4px` |
151
+ | `--field-tabs-radius` | geometry | `var(--field-radius)` |
152
+ | `--field-width` | geometry | `100%` |
153
+ | `--select-font-size` | geometry | `var(--control-font-size)` |
154
+ | `--select-height` | geometry | `var(--field-height)` |
155
+ | `--select-max-height` | geometry | `300px` |
156
+ | `--select-radius` | geometry | `20px` |
157
+ | `--field-background` | light | `#ffffff` |
158
+ | `--field-background-active` | light | `#636366` |
159
+ | `--field-background-disabled` | light | `#f2f2f7` |
160
+ | `--field-background-focus` | light | `rgba(0, 0, 0, 0.04)` |
161
+ | `--field-border` | light | `0px solid #c6c6c8` |
162
+ | `--field-border-disabled` | light | `#d1d1d6` |
163
+ | `--field-border-focus` | light | `#8e8e93` |
164
+ | `--field-border-hover` | light | `#aeaeb2` |
165
+ | `--field-check-box-border` | light | `2px solid #636366` |
166
+ | `--field-color` | light | `#000000` |
167
+ | `--field-color-disabled` | light | `#c7c7cc` |
168
+ | `--field-drag-border` | light | `2px dashed #c7c7cc` |
169
+ | `--field-drag-border-hover` | light | `#8e8e93` |
170
+ | `--field-error-background` | light | `rgba(255, 59, 48, 0.12)` |
171
+ | `--field-error-border` | light | `#ff3b30` |
172
+ | `--field-error-color` | light | `#d70015` |
173
+ | `--field-focus-ring` | light | `rgba(0, 0, 0, 0.12)` |
174
+ | `--field-focus-shadow` | light | `0 0 0 3px var(--field-focus-ring)` |
175
+ | `--field-icon-color` | light | `#8e8e93` |
176
+ | `--field-label-color` | light | `#636366` |
177
+ | `--field-placeholder` | light | `#8e8e93` |
178
+ | `--field-range-fill` | light | `#34c759` |
179
+ | `--field-range-thumb` | light | `#000000` |
180
+ | `--field-range-track` | light | `#e9e9eb` |
181
+ | `--field-selection-bg` | light | `rgba(0, 0, 0, 0.12)` |
182
+ | `--field-selection-color` | light | `inherit` |
183
+ | `--field-tabs-active-bg` | light | `rgba(0, 0, 0, 0.08)` |
184
+ | `--field-tabs-color` | light | `#8e8e93` |
185
+ | `--field-tabs-color-active` | light | `#000000` |
186
+ | `--field-tabs-divider` | light | `1px solid #c6c6c8` |
187
+ | `--popup-shadow` | light | `0 6px 24px 0 #00000040` |
188
+ | `--select-background` | light | `#ffffff` |
189
+ | `--select-color` | light | `#000000` |
190
+ | `--select-li-focus-bg` | light | `#e5e5ea` |
191
+ | `--select-li-hover-bg` | light | `#f2f2f7` |
192
+ | `--select-li-selected-bg` | light | `#e5e5ea` |
193
+ | `--select-overlay` | light | `transparent` |
194
+ | `--select-separator` | light | `1px solid #c6c6c8` |
195
+
196
+ <!-- elcrm-hub-tokens:end -->
@@ -40,3 +40,10 @@ import { Icons } from "@elcrm/icons";
40
40
  - Импортировать локальный `./Icons`, если уже `@elcrm/icons` (см. `icons migrate`).
41
41
 
42
42
  Формат `file`: `import { Icons } from "./icons.generated"` — standalone, без vite-плагина.
43
+
44
+ <!-- elcrm-hub-tokens:start -->
45
+ Автотаблица: `elcrm hub collect` · **@elcrm/icons@0.1.5**. Не править руками.
46
+
47
+ _В пакете нет CSS-токенов (или только runtime var)._
48
+
49
+ <!-- elcrm-hub-tokens:end -->
@@ -78,3 +78,10 @@ Card.Open({ id: 1 }, { origin: event.currentTarget });
78
78
  - Без `Modal.Init`.
79
79
  - Нативные input внутри модалки — `@elcrm/form`.
80
80
  - Ручные `padding: 0` / пустой layout «в край» без нужды — дефолт уже с отступами.
81
+
82
+ <!-- elcrm-hub-tokens:start -->
83
+ Автотаблица: `elcrm hub collect` · **@elcrm/modal@0.0.42**. Не править руками.
84
+
85
+ _В пакете нет CSS-токенов (или только runtime var)._
86
+
87
+ <!-- elcrm-hub-tokens:end -->
@@ -16,6 +16,48 @@ Notice.Close(id);
16
16
  Notice.CloseAll();
17
17
  ```
18
18
 
19
+ ## CSS (обязательно)
20
+
21
+ В `elcrm.css` (или вручную):
22
+
23
+ ```css
24
+ @import "@elcrm/notice/style.css";
25
+ @import "@elcrm/notice/tokens.css"; /* геометрия + --elcrm-z-notice */
26
+ @import "@elcrm/notice/light.css";
27
+ @import "@elcrm/notice/dark.css";
28
+ ```
29
+
30
+ `elcrm css` допишет недостающие `@import` и цвета в `theme-light` / `theme-dark`. Геометрию из `tokens.css` **не** дублирует в `theme.css`.
31
+
32
+ Тема: `data-theme="light"|"dark"` на **`html` или `body`** (пакет слушает оба).
33
+
34
+ ### Геометрия (`tokens.css` / `:root`)
35
+
36
+ | Токен | Назначение |
37
+ | --- | --- |
38
+ | `--notice-inset` | `inset` контейнера (`20px 20px auto auto` = top-right) |
39
+ | `--notice-width` | ширина карточки (`clamp(280px, 92vw, 360px)`) |
40
+ | `--notice-height` | высота (`auto`) |
41
+ | `--notice-radius` | радиус |
42
+ | `--notice-family` | шрифт |
43
+ | `--notice-filter` | backdrop-filter blur |
44
+ | `--elcrm-z-notice` | z-index слоя тостов (дефолт `1000`) |
45
+
46
+ `Notice.Init position="…"` переопределяет только `--notice-inset`.
47
+
48
+ ### Цвета (`light.css` / `dark.css`)
49
+
50
+ | Токен | Назначение |
51
+ | --- | --- |
52
+ | `--notice-background` | фон карточки |
53
+ | `--notice-border` | рамка |
54
+ | `--notice-color` | текст |
55
+ | `--notice-error` / `--success` / `--remark` / `--copy` / `--undo` | акцент типа |
56
+
57
+ Стили в `@layer elcrm-notice`. Не импортировать устаревший `themes.css`.
58
+
59
+ Проверка покрытия: `elcrm css --check`.
60
+
19
61
  ## Можно
20
62
 
21
63
  - `Init`: `durationMs` (≥100), `maxVisible`, `pauseOnHover`, `undoLabel`, `icon` (false = палочка), `position`, `titles`.
@@ -29,3 +71,34 @@ Notice.CloseAll();
29
71
  - Несколько Init.
30
72
  - `alert()` вместо тоста для немодальных сообщений (модальный вопрос — `@elcrm/alert`).
31
73
  - `import "@elcrm/notice/themes.css"`.
74
+
75
+ <!-- elcrm-hub-tokens:start -->
76
+ Автотаблица: `elcrm hub collect` · **@elcrm/notice@0.1.8**. Не править руками.
77
+
78
+ | Токен | Слой | Значение |
79
+ | --- | --- | --- |
80
+ | `--notice-background` | dark | `rgba(45, 45, 45, 0.95)` |
81
+ | `--notice-border` | dark | `transparent` |
82
+ | `--notice-color` | dark | `#e0e0e0` |
83
+ | `--notice-copy` | dark | `#5c6bc0` |
84
+ | `--notice-error` | dark | `#ff6b6b` |
85
+ | `--notice-remark` | dark | `#ff9800` |
86
+ | `--notice-success` | dark | `#4caf50` |
87
+ | `--notice-undo` | dark | `#7986cb` |
88
+ | `--elcrm-z-notice` | geometry | `1000` |
89
+ | `--notice-family` | geometry | `-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, sans-serif` |
90
+ | `--notice-filter` | geometry | `blur(5px)` |
91
+ | `--notice-height` | geometry | `auto` |
92
+ | `--notice-inset` | geometry | `20px 20px auto auto` |
93
+ | `--notice-radius` | geometry | `20px` |
94
+ | `--notice-width` | geometry | `clamp(280px, 92vw, 360px)` |
95
+ | `--notice-background` | light | `rgba(255, 255, 255, 0.95)` |
96
+ | `--notice-border` | light | `transparent` |
97
+ | `--notice-color` | light | `#333333` |
98
+ | `--notice-copy` | light | `#3f51b5` |
99
+ | `--notice-error` | light | `#bb2014` |
100
+ | `--notice-remark` | light | `#b77513` |
101
+ | `--notice-success` | light | `#367738` |
102
+ | `--notice-undo` | light | `#5c6bc0` |
103
+
104
+ <!-- elcrm-hub-tokens:end -->