elcrm 1.1.21 → 1.1.23
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/dist/index.js +16 -9
- package/package.json +1 -1
- package/templates/elcrm-docs/COMPONENTS.elCRM.md +7 -4
- package/templates/elcrm-docs/FORM.elCRM.md +2 -1
- package/templates/elcrm-docs/MODAL.elCRM.md +24 -4
- package/templates/orbit/web/src/style/theme.css +2 -0
- package/templates/panel/web/src/style/theme.css +2 -0
package/dist/index.js
CHANGED
|
@@ -3899,16 +3899,23 @@ function isMainComponentDoc(doc) {
|
|
|
3899
3899
|
return false;
|
|
3900
3900
|
return doc.length > 72;
|
|
3901
3901
|
}
|
|
3902
|
-
function
|
|
3902
|
+
function componentDocs(content, slug) {
|
|
3903
3903
|
const fnAnchor = "export declare function " + slug;
|
|
3904
3904
|
const propsAnchor = "export type " + slug + "Props";
|
|
3905
3905
|
const fnDoc = leadingDoc(content, fnAnchor);
|
|
3906
3906
|
const propsDoc = leadingDoc(content, propsAnchor);
|
|
3907
|
-
|
|
3908
|
-
|
|
3909
|
-
if (
|
|
3910
|
-
|
|
3911
|
-
|
|
3907
|
+
const examplesDoc = fnDoc.includes("@example") ? fnDoc : propsDoc.includes("@example") ? propsDoc : fnDoc || propsDoc;
|
|
3908
|
+
let descriptionDoc = fnDoc || propsDoc;
|
|
3909
|
+
if (propsDoc.includes("@example")) {
|
|
3910
|
+
descriptionDoc = propsDoc;
|
|
3911
|
+
} else if (isMainComponentDoc(propsDoc) && propsDoc.length > fnDoc.length) {
|
|
3912
|
+
descriptionDoc = propsDoc;
|
|
3913
|
+
} else if (isMainComponentDoc(fnDoc)) {
|
|
3914
|
+
descriptionDoc = fnDoc;
|
|
3915
|
+
} else if (isMainComponentDoc(propsDoc)) {
|
|
3916
|
+
descriptionDoc = propsDoc;
|
|
3917
|
+
}
|
|
3918
|
+
return { descriptionDoc, examplesDoc };
|
|
3912
3919
|
}
|
|
3913
3920
|
function leadingDoc(content, anchor) {
|
|
3914
3921
|
const idx = content.indexOf(anchor);
|
|
@@ -3976,15 +3983,15 @@ function parseComponentDts(content, slug) {
|
|
|
3976
3983
|
if (!new RegExp("export declare function " + slug + "\\b").test(content)) {
|
|
3977
3984
|
return null;
|
|
3978
3985
|
}
|
|
3979
|
-
const
|
|
3986
|
+
const { descriptionDoc, examplesDoc } = componentDocs(content, slug);
|
|
3980
3987
|
const propsMatch = content.match(new RegExp("export type " + slug + "Props\\s*=\\s*([\\s\\S]*?);\\s*(?:export|$)"));
|
|
3981
3988
|
const propsBlock = propsMatch?.[1] ?? "";
|
|
3982
3989
|
return {
|
|
3983
3990
|
slug,
|
|
3984
3991
|
title: slug,
|
|
3985
|
-
description: descriptionFromDoc(
|
|
3992
|
+
description: descriptionFromDoc(descriptionDoc) || slug,
|
|
3986
3993
|
importFrom: "@elcrm/components",
|
|
3987
|
-
examples: examplesFromDoc(
|
|
3994
|
+
examples: examplesFromDoc(examplesDoc),
|
|
3988
3995
|
props: propsFromPropsBlock(propsBlock)
|
|
3989
3996
|
};
|
|
3990
3997
|
}
|
package/package.json
CHANGED
|
@@ -14,7 +14,7 @@ Shell UI: оболочка, шапка, секции, списки, Dropdown / R
|
|
|
14
14
|
import {
|
|
15
15
|
Layout, Header, Footer, Brand, Avatar, AvatarName, AvatarGroup, Badge,
|
|
16
16
|
Menu, Dropdown, Section, NavSections, TabSections, Breadcrumb, Stack,
|
|
17
|
-
Card, Stat, ActionGroup, TextGroup, ItemColumn, List, Item, PageHead, PageShell, ChatList, ChatMessages, ChatSplit, Sidebar, Popover,
|
|
17
|
+
Card, Stat, ActionGroup, Toolbar, TextGroup, ItemColumn, List, Item, PageHead, PageShell, ChatList, ChatMessages, ChatSplit, Sidebar, Popover,
|
|
18
18
|
Healthmap, PanelInfo,
|
|
19
19
|
Loading, EmptyState, RadioGroup, PricingGroup, PricingTable,
|
|
20
20
|
createLazyResolver,
|
|
@@ -31,13 +31,15 @@ import type { PricingPlan, HealthmapData } from "@elcrm/components";
|
|
|
31
31
|
- **PageHead** — title + actions. `sup` — текст или Badge сразу после title (надстрочно; `0` скрыт). `sticky` — шапка прилипает к верху скролла (фон `--shell-bg`). `children` — фильтры/поиск под заголовком, отступ `--shell-gap`.
|
|
32
32
|
- **Section** — блок контента / auth.
|
|
33
33
|
- **Layout / Header** — оболочка приложения. `Layout sidebar={<Sidebar />}` — ряд: меню слева + контент. `fixed={["header", "footer", "sidebar"]}` (по умолчанию) — эти слоты не скроллятся, крутится только `children`. `fixed={[]}` — поток страницы. Высота каркаса: `--layout-height` (`100dvh`).
|
|
34
|
-
- **Sidebar** — левое меню. `variant="cards"` (карточки) или `"plain"` (плоский backoffice). `groups` + `value`.
|
|
34
|
+
- **Sidebar** — левое меню. `variant="cards"` (карточки) или `"plain"` (плоский backoffice). `groups` + `value`. Подменю: у пункта `items` + `defaultOpen` (открыто/скрыто при старте). Контроль: `open` / `onOpenChange` (массив `value` родителей). Клик по родителю только раскрывает; `onSelect` — у листьев. Если выбран потомок — ветка открывается. Слоты: `brand`, `extra`, `footer`. Меню аккаунта: `footerItems` + `onFooterSelect`. Отступ вложенных: `--sidebar-indent`.
|
|
35
|
+
- **NavSections** — сайдбар страницы + lazy-панель. Подменю как у Sidebar: `items` + `defaultOpen`, `open` / `onOpenChange`. Панель грузится по `value` листа (`resolveSection`). Клик по родителю только раскрывает.
|
|
35
36
|
- **Stack** — ряд/колонка/сетка (`direction="row"|"column"|"grid"`). Не `Block` / `Row` / `Column`. Сетка: `auto-fit` + `--stack-grid-min`, либо `columns={4}` / `columns={["1fr", "100px", "auto"]}`. С `columns` ряды `stretch` (карточки не наезжают); в одну линию — `style={{ alignItems: "center" }}`. Не `height: 100%` у детей сетки.
|
|
36
37
|
- **Card** — курсор: `--card-pointer` (`auto` / `pointer`). Сетка Stack: `--stack-grid-min`.
|
|
37
38
|
- **Stat** — метрика: `label` + `value`, `tone` как у Badge, `labelMuted`. Не собирать из `span` в приложении.
|
|
38
39
|
- **Healthmap** — теплокарта дней (`data.days`). Данные грузит приложение; слоты `brandName` / `brandSub` / `unit` / `hint`. Токены `--healthmap-cell`, `--healthmap-gap`, `--healthmap-l0`…`l4`.
|
|
39
40
|
- **PanelInfo** — выезд справа (шапка / body / footer). На узком экране — оверлей. Слоты: `children`, `footer`, `headerExtra`, `close`. Токены `--panel-info-width`, `--panel-info-width-min`, `--panel-info-overlay-max`, `--panel-info-backdrop`.
|
|
40
|
-
- **ActionGroup** —
|
|
41
|
+
- **ActionGroup** — ряд иконок в карточке / строке: `label` + `items` и/или `children`. Кнопки — `@elcrm/button`.
|
|
42
|
+
- **Toolbar** — фильтры над списком. `size` (`s`/`m`/`l`, по умолчанию `s`) наследуют вложенные `*Field`, `Search`, `Button`, `Dropdown` (свой `size` важнее). `align`: `start` / `center` / `end` / `between`. `width`: `l` (100%, по умолчанию) или `s` (по контенту, не растягивать). Токены `--toolbar-gap`. Не `ActionGroup`.
|
|
41
43
|
- **TextGroup** — две строки: `title` + `description` (без аватара; с аватаром — AvatarName).
|
|
42
44
|
- **Item** — строка списка. `as` button/a/li, `active`. `variant="card"` — рамка и muted-фон (идеи / тикеты / inbox). Не дублировать `.desk-row` в приложении.
|
|
43
45
|
- **ItemColumn** — внутри Item: `icon` слева, столбик `title` / `description` / `footer` или `meta`, `extra` — бейджи справа сверху, `aside` — колонка справа. `unread` — жирный title. Title: `--item-column-title-size` / `--item-column-title-line` (в console = `--button-size-s` / `--button-line-height`).
|
|
@@ -45,7 +47,7 @@ import type { PricingPlan, HealthmapData } from "@elcrm/components";
|
|
|
45
47
|
## Меню
|
|
46
48
|
|
|
47
49
|
- **Menu** — inline-навигация в шапке. `items`: `value` + `label` + `badge` (`0` не показываем, иначе `Badge` size s). `variant="line"` — вкладки с чертой снизу (не ломать pill селекторами страницы).
|
|
48
|
-
- **Dropdown** — выпадающее меню по `items`/`groups` (portal). `placement="auto"|"top"|"bottom"` — куда открывать панель (футер Sidebar — `top`).
|
|
50
|
+
- **Dropdown** — выпадающее меню по `items`/`groups` (portal). `placement="auto"|"top"|"bottom"` — куда открывать панель (футер Sidebar — `top`). `size` — высота триггера; в `Toolbar` берётся сам.
|
|
49
51
|
- **Popover** — свой попап в portal (якорь + `children`). z-index: `acquireOverlayZIndex` (тот же стек, что у form). Не `@elcrm/overlay` `Menu`. `placement` как у Dropdown: позиция по **реальной** высоте панели, не по `maxHeight` 420.
|
|
50
52
|
|
|
51
53
|
## Avatar
|
|
@@ -65,6 +67,7 @@ import type { PricingPlan, HealthmapData } from "@elcrm/components";
|
|
|
65
67
|
- `--layout-padding` / `--layout-margin` / `--layout-max-width` — отступы и макс. ширина корня Layout (`0` / `none` = на весь вьюпорт).
|
|
66
68
|
- `--header-border` — рамка Header (shorthand: все стороны и толщина). Только снизу: `none` + линия через `--header-shadow`.
|
|
67
69
|
- `--header-nav-justify` — выравнивание `nav` в шапке (`flex-start` / `center` / `flex-end`).
|
|
70
|
+
- `<Toolbar size="s" width="l" align="start">` — один размер для Search / `*Field` / Button / Dropdown. `width="s"` — ряд по контенту. Свой `size` у ребёнка важнее.
|
|
68
71
|
- Узкие токены (`--chat-*`, `--sidebar-*`, `--item-column-*`) по умолчанию = `--shell-*`. Переопределяй только отличие.
|
|
69
72
|
- Задать `--shell-color` / `--shell-padding` / `--shell-radius` один раз — большинство компонентов подхватят.
|
|
70
73
|
- `--popup-shadow` общий с `@elcrm/form`.
|
|
@@ -23,7 +23,8 @@ const form = useForm({ login: "", password: "" });
|
|
|
23
23
|
|
|
24
24
|
Канонические поля: `StringField`, `PasswordField`, `TextareaField`, `NumberField`, `PercentField`, `MoneyField`, `MaskField`, `PhoneField`, `EmailField`, `UrlField`, `DateField`, `TimeField`, `SelectField`, `OptionsField`, `ModalField`, `RangeField`, `CheckField`, `RadioField`, `TagsField`, `RatingField`, `CodeField`, `FileField`, `DragDropField`, `RichTextField`, `ColorField`, `HiddenField`, `DisplayField`, `SearchField`, `TabsField`.
|
|
25
25
|
|
|
26
|
-
`disabled`, `size` (`"s"` | `"m"` | `"l"`) — у всех видимых `*Field` (кроме `HiddenField`).
|
|
26
|
+
`disabled`, `size` (`"s"` | `"m"` | `"l"`) — у всех видимых `*Field` (кроме `HiddenField`).
|
|
27
|
+
В ряду фильтров — `<Toolbar size="s">` из `@elcrm/components`: вложенные поля/Search/Button берут этот `size`.
|
|
27
28
|
|
|
28
29
|
`PasswordField`: `generate` — кнопка случайного пароля. `true` → `Az09#` (A–Z, a–z, 0–9, символы). `generate="A"` только заглавные, `"59"` цифры 5–9, `"#"` только символы. Длина — `maxLength` или 12.
|
|
29
30
|
|
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
function EditModal({ id, onClose }: { id: number; onClose?: () => void }) {
|
|
11
11
|
return (
|
|
12
12
|
<Modal.Main title="Редактирование" onClose={onClose} size="m">
|
|
13
|
-
|
|
13
|
+
{/* scroll + padding по умолчанию — без Modal.Scroll */}
|
|
14
|
+
<p>…</p>
|
|
14
15
|
</Modal.Main>
|
|
15
16
|
);
|
|
16
17
|
}
|
|
@@ -25,12 +26,30 @@ Open({ id: 123 });
|
|
|
25
26
|
|
|
26
27
|
| API | Зачем |
|
|
27
28
|
| --- | --- |
|
|
28
|
-
| `Modal.Main` | окно + оверлей: `title`, `size`, `button`, `tabs`, `menu`, `shake`, `escape
|
|
29
|
-
| `Modal.Panel` | без оверлея |
|
|
30
|
-
| `Modal.Scroll`
|
|
29
|
+
| `Modal.Main` | окно + оверлей: `title`, `size`, `button`, `tabs`, `menu`, `shake`, `escape`, **`scroll`**, **`padding`** |
|
|
30
|
+
| `Modal.Panel` | без оверлея (те же props) |
|
|
31
|
+
| `Modal.Scroll` | редко: сырой layout или `padding={false}` внутри |
|
|
32
|
+
| `Center` / `Form` / `Column` / `List` | раскладка |
|
|
31
33
|
| `Modal.Close(name?)` | одно или все |
|
|
32
34
|
| `Modal.Shake` | тряска |
|
|
33
35
|
|
|
36
|
+
### Отступы (по умолчанию уже есть)
|
|
37
|
+
|
|
38
|
+
Один токен **`--modal-padding`** (default `30px`) — шапка, тело, футер, Form, List.
|
|
39
|
+
|
|
40
|
+
| Как | Пример |
|
|
41
|
+
| --- | --- |
|
|
42
|
+
| Тема на всё приложение | `--modal-padding: 24px` в `theme-*.css` |
|
|
43
|
+
| Одно окно | `<Modal.Main padding="20px">` |
|
|
44
|
+
| Без отступов тела | `padding={false}` |
|
|
45
|
+
| Выключить авто-Scroll | `scroll={false}` |
|
|
46
|
+
|
|
47
|
+
`Modal.Main` / `Panel` сами оборачивают children в `Modal.Scroll` с отступами.
|
|
48
|
+
|
|
49
|
+
- Обычный контент — **не** пишите `Modal.Scroll`.
|
|
50
|
+
- Единственный `Modal.List` или `Modal.Form` — без внешнего Scroll (свои отступы через тот же токен).
|
|
51
|
+
- Если единственный ребёнок уже `Modal.Scroll` — второй раз не оборачиваем.
|
|
52
|
+
|
|
34
53
|
`size`: `a` auto · `s` 400 · `m` 500 · `l` 800 · `x` 1000 · `f` full · `p` page (весь экран поверх страницы).
|
|
35
54
|
`escape` закрывает верхнее; клик по оверлею при `shake` (default true) трясёт, не закрывает; крестик закрывает всегда. Для `size="p"` обычно `shake={false}`.
|
|
36
55
|
|
|
@@ -58,3 +77,4 @@ Card.Open({ id: 1 }, { origin: event.currentTarget });
|
|
|
58
77
|
- `key={Date.now()}` на модалке.
|
|
59
78
|
- Без `Modal.Init`.
|
|
60
79
|
- Нативные input внутри модалки — `@elcrm/form`.
|
|
80
|
+
- Ручные `padding: 0` / пустой layout «в край» без нужды — дефолт уже с отступами.
|
|
@@ -134,6 +134,7 @@
|
|
|
134
134
|
--item-column-title-line: 1.3;
|
|
135
135
|
--stat-value-size: 1.75rem;
|
|
136
136
|
--action-group-gap: var(--shell-gap-sm);
|
|
137
|
+
--toolbar-gap: var(--shell-gap-sm);
|
|
137
138
|
--sidebar-width: 260px;
|
|
138
139
|
--sidebar-pad-x: var(--shell-gap);
|
|
139
140
|
--sidebar-pad-y: var(--shell-gap-lg);
|
|
@@ -142,6 +143,7 @@
|
|
|
142
143
|
--sidebar-item-padding: 6px 10px;
|
|
143
144
|
--sidebar-icon-size: 16px;
|
|
144
145
|
--sidebar-group-font-size: 11px;
|
|
146
|
+
--sidebar-indent: 14px;
|
|
145
147
|
--pricing-card-min-width: 16rem;
|
|
146
148
|
--pricing-table-label-width: 10rem;
|
|
147
149
|
--chat-list-width: 340px;
|
|
@@ -145,6 +145,7 @@
|
|
|
145
145
|
--item-column-title-line: 1.3;
|
|
146
146
|
--stat-value-size: 1.75rem;
|
|
147
147
|
--action-group-gap: var(--shell-gap-sm);
|
|
148
|
+
--toolbar-gap: var(--shell-gap-sm);
|
|
148
149
|
--sidebar-width: 248px;
|
|
149
150
|
--sidebar-pad-x: var(--shell-gap);
|
|
150
151
|
--sidebar-pad-y: var(--shell-gap-lg);
|
|
@@ -153,6 +154,7 @@
|
|
|
153
154
|
--sidebar-item-padding: 6px 10px;
|
|
154
155
|
--sidebar-icon-size: 16px;
|
|
155
156
|
--sidebar-group-font-size: 11px;
|
|
157
|
+
--sidebar-indent: 14px;
|
|
156
158
|
--pricing-card-min-width: 16rem;
|
|
157
159
|
--pricing-table-label-width: 10rem;
|
|
158
160
|
--chat-list-width: 340px;
|