@elcrm/components 0.1.2 → 0.2.0

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.
Files changed (89) hide show
  1. package/README.md +66 -2
  2. package/dist/ActionGroup.css +1 -1
  3. package/dist/Avatar.d.ts +2 -1
  4. package/dist/AvatarGroup.d.ts +2 -1
  5. package/dist/AvatarName-0BzyfpMq.js +68 -0
  6. package/dist/AvatarName.css +1 -1
  7. package/dist/AvatarName.d.ts +4 -1
  8. package/dist/AvatarName.js +1 -1
  9. package/dist/Badge.d.ts +2 -1
  10. package/dist/Card.css +1 -1
  11. package/dist/ChatFrame-BW2TmCkZ.js +37 -0
  12. package/dist/ChatFrame.css +1 -0
  13. package/dist/ChatList.d.ts +9 -0
  14. package/dist/ChatList.js +7 -0
  15. package/dist/ChatMessages-B8rdXiK-.js +19 -0
  16. package/dist/ChatMessages.d.ts +9 -0
  17. package/dist/ChatMessages.js +4 -0
  18. package/dist/ChatSplit-DNnu3TNq.js +21 -0
  19. package/dist/CheckIcon-FdB8fMEF.js +17 -0
  20. package/dist/CheckIcon.d.ts +8 -0
  21. package/dist/Dropdown-4yUB2tk1.js +142 -0
  22. package/dist/Dropdown.css +1 -1
  23. package/dist/Dropdown.js +1 -1
  24. package/dist/Footer.css +1 -1
  25. package/dist/Item.css +1 -1
  26. package/dist/ItemColumn.css +1 -1
  27. package/dist/ItemColumn.d.ts +2 -1
  28. package/dist/Layout-mi6Ghayv.js +31 -0
  29. package/dist/Layout.css +1 -1
  30. package/dist/Layout.d.ts +19 -2
  31. package/dist/Layout.js +1 -1
  32. package/dist/Loading-DkkG7RcE.js +16 -0
  33. package/dist/Loading.css +1 -1
  34. package/dist/Loading.d.ts +1 -1
  35. package/dist/Loading.js +1 -1
  36. package/dist/Menu-DuXQv-zT.js +66 -0
  37. package/dist/Menu.css +1 -1
  38. package/dist/Menu.js +1 -1
  39. package/dist/NavSections-BpyZPimZ.js +79 -0
  40. package/dist/NavSections.css +1 -1
  41. package/dist/NavSections.js +1 -1
  42. package/dist/PageHead.css +1 -1
  43. package/dist/Popover-D0m5JWIt.js +142 -0
  44. package/dist/Popover.css +1 -1
  45. package/dist/Popover.js +1 -1
  46. package/dist/PricingGroup-Czuhe81Z.js +120 -0
  47. package/dist/PricingGroup.css +1 -1
  48. package/dist/PricingGroup.js +1 -1
  49. package/dist/{PricingTable-DALddSwM.js → PricingTable-BuLC0opK.js} +69 -75
  50. package/dist/PricingTable.css +1 -1
  51. package/dist/PricingTable.js +1 -1
  52. package/dist/RadioGroup-fcXzhvMu.js +129 -0
  53. package/dist/RadioGroup.css +1 -1
  54. package/dist/RadioGroup.js +1 -1
  55. package/dist/Sidebar-CBYq1ad6.js +107 -0
  56. package/dist/Sidebar.css +1 -1
  57. package/dist/Sidebar.d.ts +17 -1
  58. package/dist/Sidebar.js +1 -1
  59. package/dist/Stat.css +1 -1
  60. package/dist/TabSections-DN7yVJoF.js +69 -0
  61. package/dist/TabSections.css +1 -1
  62. package/dist/TabSections.js +1 -1
  63. package/dist/TextGroup.d.ts +2 -1
  64. package/dist/badgeText-CRzlIzi3.js +8 -0
  65. package/dist/badgeText.d.ts +4 -0
  66. package/dist/dark.css +4 -1
  67. package/dist/index.css +21 -19
  68. package/dist/index.d.ts +10 -1
  69. package/dist/index.es.d.ts +10 -1
  70. package/dist/index.es.js +51 -44
  71. package/dist/light.css +4 -1
  72. package/dist/rovingKeys-CGlfTtNQ.js +15 -0
  73. package/dist/rovingKeys.d.ts +13 -0
  74. package/dist/tokens.css +35 -14
  75. package/dist/types.d.ts +2 -0
  76. package/dist/useControllableValue-CWqH1kpM.js +10 -0
  77. package/dist/useControllableValue.d.ts +4 -0
  78. package/package.json +5 -1
  79. package/dist/AvatarName-C1sIDPH-.js +0 -66
  80. package/dist/Dropdown-CQBMF9aR.js +0 -151
  81. package/dist/Layout-BQwEaeO0.js +0 -22
  82. package/dist/Loading-ChGq9peU.js +0 -15
  83. package/dist/Menu-DpUvOl8Y.js +0 -58
  84. package/dist/NavSections-NDcIDD6H.js +0 -59
  85. package/dist/Popover-g2xTGubK.js +0 -123
  86. package/dist/PricingGroup-DgcdVSq8.js +0 -126
  87. package/dist/RadioGroup-D2UUOTkY.js +0 -138
  88. package/dist/Sidebar-DeqxYgxn.js +0 -69
  89. package/dist/TabSections-Bf_sZo7b.js +0 -50
package/README.md CHANGED
@@ -4,6 +4,17 @@ Shell UI для elCRM: `Layout`, `Header`, `Section`, `Stack`, `NavSections`, `T
4
4
 
5
5
  Стили — CSS Modules с короткими уникальными классами; значения токенов задаёт приложение (`theme-dark.css` / `theme-light.css`). Fallback в пакете нет.
6
6
 
7
+ ## Визуальный стенд
8
+
9
+ Как у `@elcrm/form` — страница с галереей компонентов (`@elcrm/storybook`):
10
+
11
+ ```bash
12
+ bun i
13
+ bun run dev
14
+ ```
15
+
16
+ Откроется `http://localhost:3001`. В сайдбаре стенда: `section` (компонент / `all`), `size`, тон Badge, вариант Menu.
17
+
7
18
  ## Установка
8
19
 
9
20
  ```bash
@@ -41,6 +52,9 @@ import {
41
52
  Breadcrumb,
42
53
  PageHead,
43
54
  PageShell,
55
+ ChatList,
56
+ ChatMessages,
57
+ ChatSplit,
44
58
  Sidebar,
45
59
  Popover,
46
60
  createLazyResolver,
@@ -62,7 +76,7 @@ import { RadioGroup } from "@elcrm/components/RadioGroup";
62
76
 
63
77
  | | Назначение | Ключевые props |
64
78
  | -------------------------------- | -------------------------------- | ---------------------------------------------------- |
65
- | **Layout** | Оболочка страницы | `sidebar`, `header`, `footer`, `children` |
79
+ | **Layout** | Оболочка страницы | `sidebar`, `header`, `footer`, `fixed`, `children` |
66
80
  | **Header** | Шапка со слотами | `brand`, `nav`, `search`, `actions` |
67
81
  | **Footer** | Подвал | `children` |
68
82
  | **Brand** | Название / логотип | `as`, `children`, `onClick` |
@@ -77,8 +91,11 @@ import { RadioGroup } from "@elcrm/components/RadioGroup";
77
91
  | **Dropdown** | Выпадающее меню (items, portal) | `label`/`trigger`, `items`/`groups`, `onSelect` |
78
92
  | **Popover** | Свой попап в portal | `trigger`, `children`, `align`, `open` |
79
93
  | **Breadcrumb** | Хлебные крошки | `items`, `separator`, `collapseAfter` |
80
- | **Sidebar** | Левое меню приложения | `groups`, `value`, `variant` (`cards`/`plain`) |
94
+ | **Sidebar** | Левое меню приложения | `groups`, `value`, `footer` + `footerItems`, `variant` |
81
95
  | **PageShell** | Каркас модуля (скролл + footer) | `wide`, `scroll`, `footer`, `children` |
96
+ | **ChatList** | Колонка диалогов | `header`, `footer`, `children` (`List`/`Item`), `bodyRef` |
97
+ | **ChatMessages** | Колонка переписки | `header`, `footer`, `children`, `bodyRef`, `onBodyScroll` |
98
+ | **ChatSplit** | Список + лента | `list`, `messages` |
82
99
  | **PageHead** | Заголовок страницы + actions | `title`, `sup` (текст/Badge), `subtitle`, `actions`, `sticky`, `children` |
83
100
  | **Section** | Блок контента / auth / подраздел | `title`, `description`, `icon`, `actions`, `variant` |
84
101
  | **NavSections** | Сайдбар + lazy-панель | `groups` (`value`), `resolveSection`, `defaultValue` |
@@ -114,6 +131,12 @@ import { RadioGroup } from "@elcrm/components/RadioGroup";
114
131
  { value: "admin", title: "Админ", items: [{ value: "ops", label: "Операции" }] },
115
132
  ]}
116
133
  footer={<AvatarName title="Паша" description="mail@…" />}
134
+ footerItems={[
135
+ { value: "docs", label: "Документация", icon: <Icon /> },
136
+ { value: "theme", label: "Тема", submenu: true },
137
+ { value: "logout", label: "Выйти", danger: true },
138
+ ]}
139
+ onFooterSelect={(value) => console.log(value)}
117
140
  version="v 0.2.26"
118
141
  />
119
142
  ```
@@ -312,6 +335,42 @@ const sections = [
312
335
  </PageShell>
313
336
  ```
314
337
 
338
+ ### ChatList / ChatMessages / ChatSplit
339
+
340
+ Каркас мессенджера, не пузыри и не композер. Строки диалогов — `List` + `Item` (+ `ItemColumn` / `Avatar`). Поиск и ввод — слоты `header` / `footer` приложения.
341
+
342
+ | | Роль |
343
+ | --- | --- |
344
+ | **ChatList** | Колонка диалогов: `header` (поиск), `children` (список), `footer` |
345
+ | **ChatMessages** | Колонка переписки: `header` (собеседник), `children` (лента), `footer` (ввод) |
346
+ | **ChatSplit** | Ряд `list` + `messages` (`--chat-split-gap`) |
347
+
348
+ Токены: `--chat-list-width`, `--chat-split-gap`, `--chat-radius`, `--chat-background`, `--chat-border` (рамка и разделители header/footer), `--chat-header-padding` / `--chat-body-padding` / `--chat-footer-padding`, узкие `--chat-messages-*-padding`. Узкие `--chat-*` по умолчанию = `--shell-*`.
349
+
350
+ ```tsx
351
+ <ChatSplit
352
+ list={
353
+ <ChatList header={<SearchField name="q" placeholder="Найти" />}>
354
+ <List>
355
+ <li>
356
+ <Item as="button" active>
357
+ <ItemColumn icon={<Avatar name="Иван" />} title="Иван" description="Привет" />
358
+ </Item>
359
+ </li>
360
+ </List>
361
+ </ChatList>
362
+ }
363
+ messages={
364
+ <ChatMessages
365
+ header={<AvatarName title="Иван" description="в сети" />}
366
+ footer={<TextareaField name="body" placeholder="Сообщение" />}
367
+ >
368
+ {bubbles}
369
+ </ChatMessages>
370
+ }
371
+ />
372
+ ```
373
+
315
374
  ### AvatarGroup
316
375
 
317
376
  Стопка аватаров через `items`:
@@ -495,6 +554,7 @@ const people = [
495
554
 
496
555
  ```tsx
497
556
  <Layout
557
+ fixed={["header", "footer", "sidebar"]}
498
558
  sidebar={<Sidebar groups={groups} value={page} onSelect={setPage} />}
499
559
  header={
500
560
  <Header
@@ -520,6 +580,10 @@ const people = [
520
580
  </Section>
521
581
  </Layout>;
522
582
 
583
+ {/* `fixed` по умолчанию = header + footer + sidebar. Скролл только у children.
584
+ Высота каркаса: `--layout-height` (100dvh). Вложенно: 100% + явная высота родителя.
585
+ `fixed={[]}` — обычный поток страницы. */}
586
+
523
587
  {
524
588
  /* Экран входа */
525
589
  }
@@ -1 +1 @@
1
- @layer elcrm-components{.c5r{display:flex;flex-wrap:nowrap;align-items:center;gap:var(--action-group-gap, var(--shell-gap-sm));flex:0 0 auto}}
1
+ @layer elcrm-components{.c5r{display:flex;flex-wrap:nowrap;align-items:center;gap:var(--action-group-gap);flex:0 0 auto}}
package/dist/Avatar.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { default as React } from 'react';
2
+ import { UiSize } from './types';
2
3
  /**
3
4
  * Инициалы из имени: «Иван Петров» → «ИП», «admin» → «AD».
4
5
  *
@@ -25,7 +26,7 @@ type Common = {
25
26
  */
26
27
  name?: string;
27
28
  /** Размер: `s` | `m` | `l`. */
28
- size?: "s" | "m" | "l";
29
+ size?: UiSize;
29
30
  /** Точка статуса (online / offline). */
30
31
  status?: AvatarStatus;
31
32
  /** Подсветка (например активный пункт шапки). */
@@ -1,4 +1,5 @@
1
1
  import { default as React } from 'react';
2
+ import { UiSize } from './types';
2
3
  /**
3
4
  * Элемент стопки {@link AvatarGroup}.
4
5
  *
@@ -30,7 +31,7 @@ export type AvatarGroupProps = React.HTMLAttributes<HTMLDivElement> & {
30
31
  /** Сколько аватаров показать до «+N». По умолчанию все. */
31
32
  max?: number;
32
33
  /** Размер аватаров: `s` | `m` | `l`. */
33
- size?: "s" | "m" | "l";
34
+ size?: UiSize;
34
35
  /** Кнопка «+» справа. */
35
36
  add?: boolean;
36
37
  /** Подпись для кнопки добавления (`aria-label`). */
@@ -0,0 +1,68 @@
1
+ import t from "react";
2
+ import { A as b } from "./Avatar-loGgFt72.js";
3
+ import { c as g } from "./cx-CcykAxZN.js";
4
+ import './AvatarName.css';const y = "czr", A = "czc", h = "czx", C = "czt", F = "czd", I = "czs", R = "czm", S = "czl", e = {
5
+ r: y,
6
+ c: A,
7
+ x: h,
8
+ t: C,
9
+ d: F,
10
+ s: I,
11
+ m: R,
12
+ l: S
13
+ };
14
+ function $(s, n) {
15
+ if (s != null && s !== "") return s;
16
+ if (typeof n == "string") return n;
17
+ }
18
+ function w(s) {
19
+ const {
20
+ src: n,
21
+ name: c,
22
+ title: m,
23
+ description: i,
24
+ size: a = "m",
25
+ radius: p,
26
+ status: z,
27
+ className: E,
28
+ children: N,
29
+ extra: u,
30
+ as: d = "div",
31
+ ...r
32
+ } = s, x = a === "s" ? e.s : a === "l" ? e.l : e.m, l = g(e.r, x, E), f = m ?? (typeof c == "string" ? c : void 0), v = $(c, m), o = /* @__PURE__ */ t.createElement(t.Fragment, null, /* @__PURE__ */ t.createElement(
33
+ b,
34
+ {
35
+ src: n,
36
+ name: v,
37
+ size: a,
38
+ radius: p,
39
+ status: z
40
+ }
41
+ ), /* @__PURE__ */ t.createElement("span", { className: e.c }, f != null ? /* @__PURE__ */ t.createElement("span", { className: e.t }, f) : null, i != null ? /* @__PURE__ */ t.createElement("span", { className: e.d }, i) : null, N), u != null ? /* @__PURE__ */ t.createElement("span", { className: e.x }, u) : null);
42
+ return d === "button" ? /* @__PURE__ */ t.createElement(
43
+ "button",
44
+ {
45
+ type: "button",
46
+ className: l,
47
+ ...r
48
+ },
49
+ o
50
+ ) : d === "a" ? /* @__PURE__ */ t.createElement(
51
+ "a",
52
+ {
53
+ className: l,
54
+ ...r
55
+ },
56
+ o
57
+ ) : /* @__PURE__ */ t.createElement(
58
+ "div",
59
+ {
60
+ className: l,
61
+ ...r
62
+ },
63
+ o
64
+ );
65
+ }
66
+ export {
67
+ w as A
68
+ };
@@ -1 +1 @@
1
- @layer elcrm-components{.czr{display:inline-flex;align-items:center;gap:var(--shell-gap);max-width:100%;text-align:left;vertical-align:middle}.czr:is(button,a){-webkit-appearance:none;-moz-appearance:none;appearance:none;margin:0;padding:0;border:none;background:transparent;font:inherit;color:inherit;cursor:pointer;text-decoration:none}.czc{display:flex;flex-direction:column;gap:2px;min-width:0}.czt{margin:0;font-size:var(--shell-font-size);font-weight:var(--shell-font-weight);color:var(--avatar-name-title-color, var(--shell-color));line-height:1.3;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.czd{margin:0;font-size:var(--shell-font-size-sm);font-weight:400;color:var(--avatar-name-description-color, var(--shell-color-muted));line-height:1.35;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.czs{gap:var(--shell-gap-sm)}.czs .czt{font-size:var(--shell-font-size-sm)}.czm{gap:var(--shell-gap)}.czl{gap:var(--shell-gap-lg)}.czl .czt{font-size:var(--shell-font-size-lg)}.czl .czd{font-size:var(--shell-font-size)}}
1
+ @layer elcrm-components{.czr{display:inline-flex;align-items:center;gap:var(--shell-gap);max-width:100%;text-align:left;vertical-align:middle}.czr:is(button,a){-webkit-appearance:none;-moz-appearance:none;appearance:none;margin:0;padding:0;border:none;background:transparent;font:inherit;color:inherit;cursor:pointer;text-decoration:none}.czc{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1 1 auto}.czx{display:inline-flex;flex-shrink:0;align-items:center;margin-left:auto;color:var(--shell-color-muted);line-height:0}.czt{margin:0;font-size:var(--shell-font-size);font-weight:var(--shell-font-weight);color:var(--avatar-name-title-color);line-height:1.3;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.czd{margin:0;font-size:var(--shell-font-size-sm);font-weight:400;color:var(--avatar-name-description-color);line-height:1.35;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.czs{gap:var(--shell-gap-sm)}.czs .czt{font-size:var(--shell-font-size-sm)}.czm{gap:var(--shell-gap)}.czl{gap:var(--shell-gap-lg)}.czl .czt{font-size:var(--shell-font-size-lg)}.czl .czd{font-size:var(--shell-font-size)}}
@@ -1,5 +1,6 @@
1
1
  import { default as React } from 'react';
2
2
  import { AvatarStatus } from './Avatar';
3
+ import { UiSize } from './types';
3
4
  /**
4
5
  * Общие поля блока «аватар + текст».
5
6
  *
@@ -19,7 +20,7 @@ type Common = {
19
20
  /** Подпись: email, роль… */
20
21
  description?: React.ReactNode;
21
22
  /** Размер: `s` | `m` | `l`. */
22
- size?: "s" | "m" | "l";
23
+ size?: UiSize;
23
24
  /** Скругление аватара (`10` → `10px`). Токен `--avatar-radius`. */
24
25
  radius?: number | string;
25
26
  /** Статус у аватара. */
@@ -28,6 +29,8 @@ type Common = {
28
29
  className?: string;
29
30
  /** Доп. контент в текстовой колонке. */
30
31
  children?: React.ReactNode;
32
+ /** Справа: ⋮, шеврон, бейдж. Нет — не рисуем. */
33
+ extra?: React.ReactNode;
31
34
  };
32
35
  /**
33
36
  * Props {@link AvatarName}: корень как `button` | `a` | `div`.
@@ -1,4 +1,4 @@
1
- import { A as e } from "./AvatarName-C1sIDPH-.js";
1
+ import { A as e } from "./AvatarName-0BzyfpMq.js";
2
2
  export {
3
3
  e as AvatarName
4
4
  };
package/dist/Badge.d.ts CHANGED
@@ -1,8 +1,9 @@
1
1
  import { default as React } from 'react';
2
+ import { UiSize } from './types';
2
3
  /** Тон метки — те же смыслы, что у Stat */
3
4
  export type BadgeTone = "neutral" | "accent" | "success" | "warning" | "danger";
4
5
  /** Размер метки */
5
- export type BadgeSize = "s" | "m" | "l";
6
+ export type BadgeSize = UiSize;
6
7
  export type BadgeProps = React.HTMLAttributes<HTMLSpanElement> & {
7
8
  /**
8
9
  * Цвет по смыслу.
package/dist/Card.css CHANGED
@@ -1 +1 @@
1
- @layer elcrm-components{.cdr{background:var(--shell-background);border:1px solid var(--shell-border);border-radius:var(--shell-radius);padding:var(--shell-padding);box-shadow:var(--shell-shadow);cursor:var(--card-pointer, auto)}.cdt{margin:0 0 var(--shell-gap-sm);font-size:var(--shell-font-size-lg);font-weight:var(--shell-font-weight);color:var(--shell-color)}}
1
+ @layer elcrm-components{.cdr{background:var(--shell-background);border:1px solid var(--shell-border);border-radius:var(--shell-radius);padding:var(--shell-padding);box-shadow:var(--shell-shadow);cursor:var(--card-pointer)}.cdt{margin:0 0 var(--shell-gap-sm);font-size:var(--shell-font-size-lg);font-weight:var(--shell-font-weight);color:var(--shell-color)}}
@@ -0,0 +1,37 @@
1
+ import e from "react";
2
+ import { c as f } from "./cx-CcykAxZN.js";
3
+ import './ChatFrame.css';const p = "c8r", u = "c8l", g = "c8g", b = "c8h", h = "c8b", E = "c8f", N = "c8p", c = {
4
+ r: p,
5
+ l: u,
6
+ g,
7
+ h: b,
8
+ b: h,
9
+ f: E,
10
+ p: N
11
+ };
12
+ function x({
13
+ variant: l = "messages",
14
+ as: n = "section",
15
+ header: s,
16
+ footer: t,
17
+ children: a,
18
+ className: r,
19
+ bodyRef: o,
20
+ onBodyScroll: m,
21
+ ...i
22
+ }) {
23
+ return /* @__PURE__ */ e.createElement(
24
+ n,
25
+ {
26
+ className: f(c.r, l === "list" ? c.l : c.g, r),
27
+ ...i
28
+ },
29
+ s != null ? /* @__PURE__ */ e.createElement("div", { className: c.h }, s) : null,
30
+ /* @__PURE__ */ e.createElement("div", { className: c.b, ref: o, onScroll: m }, a),
31
+ t != null ? /* @__PURE__ */ e.createElement("div", { className: c.f }, t) : null
32
+ );
33
+ }
34
+ export {
35
+ x as C,
36
+ c as s
37
+ };
@@ -0,0 +1 @@
1
+ @layer elcrm-components{.c8r{display:flex;flex-direction:column;box-sizing:border-box;min-width:0;min-height:0;height:100%;overflow:hidden;background:var(--chat-background);border:var(--chat-border);border-radius:var(--chat-radius)}.c8l{width:var(--chat-list-width);max-width:100%}.c8g{width:100%}.c8h{flex:0 0 auto;padding:var(--chat-header-padding);border-bottom:var(--chat-border)}.c8b{flex:1 1 auto;min-height:0;overflow:auto;padding:var(--chat-body-padding)}.c8g .c8h{padding:var(--chat-messages-header-padding)}.c8g .c8b{display:flex;flex-direction:column;padding:var(--chat-messages-body-padding)}.c8f{flex:0 0 auto;padding:var(--chat-footer-padding);border-top:var(--chat-border)}.c8g .c8f{padding:var(--chat-messages-footer-padding)}.c8p{display:flex;align-items:stretch;gap:var(--chat-split-gap);min-height:0;height:100%}.c8p>*{min-height:0}}
@@ -0,0 +1,9 @@
1
+ import { default as React } from 'react';
2
+ import { ChatFrameProps } from './ChatFrame';
3
+ export type ChatListProps = Omit<ChatFrameProps, "variant" | "as" | "onBodyScroll">;
4
+ /**
5
+ * Колонка списка диалогов (`aside`).
6
+ *
7
+ * @see ChatMessages, ChatSplit, List, Item
8
+ */
9
+ export declare function ChatList({ "aria-label": ariaLabel, ...rest }: ChatListProps): React.JSX.Element;
@@ -0,0 +1,7 @@
1
+ import { C as r, a as C } from "./ChatSplit-DNnu3TNq.js";
2
+ import { C as s } from "./ChatFrame-BW2TmCkZ.js";
3
+ export {
4
+ s as ChatFrame,
5
+ r as ChatList,
6
+ C as ChatSplit
7
+ };
@@ -0,0 +1,19 @@
1
+ import r from "react";
2
+ import { C as t } from "./ChatFrame-BW2TmCkZ.js";
3
+ function m({
4
+ "aria-label": a = "Переписка",
5
+ ...e
6
+ }) {
7
+ return /* @__PURE__ */ r.createElement(
8
+ t,
9
+ {
10
+ variant: "messages",
11
+ as: "section",
12
+ "aria-label": a,
13
+ ...e
14
+ }
15
+ );
16
+ }
17
+ export {
18
+ m as C
19
+ };
@@ -0,0 +1,9 @@
1
+ import { default as React } from 'react';
2
+ import { ChatFrameProps } from './ChatList/ChatFrame';
3
+ export type ChatMessagesProps = Omit<ChatFrameProps, "variant" | "as">;
4
+ /**
5
+ * Колонка переписки (`section`).
6
+ *
7
+ * @see ChatList, ChatSplit, AvatarName
8
+ */
9
+ export declare function ChatMessages({ "aria-label": ariaLabel, ...rest }: ChatMessagesProps): React.JSX.Element;
@@ -0,0 +1,4 @@
1
+ import { C as e } from "./ChatMessages-B8rdXiK-.js";
2
+ export {
3
+ e as ChatMessages
4
+ };
@@ -0,0 +1,21 @@
1
+ import e from "react";
2
+ import { C as s, s as m } from "./ChatFrame-BW2TmCkZ.js";
3
+ import { c as l } from "./cx-CcykAxZN.js";
4
+ function p({
5
+ "aria-label": a = "Диалоги",
6
+ ...t
7
+ }) {
8
+ return /* @__PURE__ */ e.createElement(s, { variant: "list", as: "aside", "aria-label": a, ...t });
9
+ }
10
+ function f({
11
+ list: a,
12
+ messages: t,
13
+ className: r,
14
+ ...i
15
+ }) {
16
+ return /* @__PURE__ */ e.createElement("div", { className: l(m.p, r), ...i }, a, t);
17
+ }
18
+ export {
19
+ p as C,
20
+ f as a
21
+ };
@@ -0,0 +1,17 @@
1
+ import e from "react";
2
+ function o({ className: r }) {
3
+ return /* @__PURE__ */ e.createElement("svg", { className: r, viewBox: "0 0 12 12", "aria-hidden": !0 }, /* @__PURE__ */ e.createElement(
4
+ "path",
5
+ {
6
+ d: "M2.5 6.2 4.8 8.5 9.5 3.5",
7
+ fill: "none",
8
+ stroke: "currentColor",
9
+ strokeWidth: "1.8",
10
+ strokeLinecap: "round",
11
+ strokeLinejoin: "round"
12
+ }
13
+ ));
14
+ }
15
+ export {
16
+ o as C
17
+ };
@@ -0,0 +1,8 @@
1
+ import { default as React } from 'react';
2
+ /**
3
+ * Галочка shell (RadioGroup / Pricing / Dropdown).
4
+ * Размер и цвет — `currentColor` + `--shell-check-size` у родителя.
5
+ */
6
+ export declare function CheckIcon({ className }: {
7
+ className?: string;
8
+ }): React.JSX.Element;
@@ -0,0 +1,142 @@
1
+ import e from "react";
2
+ import { C as f } from "./CheckIcon-FdB8fMEF.js";
3
+ import { c as m } from "./cx-CcykAxZN.js";
4
+ import { P as D } from "./Popover-D0m5JWIt.js";
5
+ import { u as j } from "./useControllableValue-CWqH1kpM.js";
6
+ import './Dropdown.css';const I = "crr", M = "crt", P = "crc", R = "crp", W = "crh", z = "crg", F = "crd", G = "cri", T = "crn", V = "crm", q = "crk", A = "crl", H = "cru", J = "crb", K = "cro", Q = "crf", U = "crx", X = "cry", Y = "crv", n = {
7
+ r: I,
8
+ t: M,
9
+ c: P,
10
+ p: R,
11
+ h: W,
12
+ g: z,
13
+ d: F,
14
+ i: G,
15
+ n: T,
16
+ m: V,
17
+ k: q,
18
+ l: A,
19
+ u: H,
20
+ b: J,
21
+ o: K,
22
+ f: Q,
23
+ x: U,
24
+ y: X,
25
+ v: Y
26
+ };
27
+ function Z() {
28
+ return /* @__PURE__ */ e.createElement("svg", { className: n.c, viewBox: "0 0 12 12", "aria-hidden": !0 }, /* @__PURE__ */ e.createElement(
29
+ "path",
30
+ {
31
+ d: "M2.5 4.5 6 8l3.5-3.5",
32
+ fill: "none",
33
+ stroke: "currentColor",
34
+ strokeWidth: "1.5",
35
+ strokeLinecap: "round",
36
+ strokeLinejoin: "round"
37
+ }
38
+ ));
39
+ }
40
+ function _() {
41
+ return /* @__PURE__ */ e.createElement("svg", { className: n.m, viewBox: "0 0 12 12", "aria-hidden": !0 }, /* @__PURE__ */ e.createElement(
42
+ "path",
43
+ {
44
+ d: "M4.5 2.5 8 6l-3.5 3.5",
45
+ fill: "none",
46
+ stroke: "currentColor",
47
+ strokeWidth: "1.5",
48
+ strokeLinecap: "round",
49
+ strokeLinejoin: "round"
50
+ }
51
+ ));
52
+ }
53
+ function $({ item: a }) {
54
+ return a.checkbox ? /* @__PURE__ */ e.createElement("span", { className: m(n.x, a.checked && n.y), "aria-hidden": !0 }, a.checked ? /* @__PURE__ */ e.createElement(f, { className: n.v }) : null) : a.checked ? /* @__PURE__ */ e.createElement("span", { className: n.k, "aria-hidden": !0 }, /* @__PURE__ */ e.createElement(f, { className: n.v })) : a.status != null ? /* @__PURE__ */ e.createElement(
55
+ "span",
56
+ {
57
+ className: m(n.b, a.status === "online" ? n.o : n.f),
58
+ "aria-hidden": !0
59
+ }
60
+ ) : a.icon != null ? /* @__PURE__ */ e.createElement("span", { className: n.n }, a.icon) : null;
61
+ }
62
+ function S(a, l, t) {
63
+ return l != null && l.length > 0 ? t != null && l[0] && l[0].title == null ? [{ ...l[0], title: t }, ...l.slice(1)] : l : a != null && a.length > 0 ? [{ title: t, items: a }] : t != null ? [{ title: t, items: [] }] : [];
64
+ }
65
+ function le({
66
+ items: a,
67
+ groups: l,
68
+ trigger: t,
69
+ label: o,
70
+ hideChevron: E = !1,
71
+ title: v,
72
+ align: k = "end",
73
+ open: b,
74
+ defaultOpen: N = !1,
75
+ onOpenChange: x,
76
+ closeOnSelect: C = !0,
77
+ disabled: u = !1,
78
+ onSelect: d,
79
+ className: y
80
+ }) {
81
+ const [i = !1, p] = j(
82
+ b,
83
+ N,
84
+ x
85
+ ), g = S(a, l, v), L = (r) => {
86
+ var c;
87
+ if (r.disabled) return;
88
+ (c = r.onClick) == null || c.call(r), d == null || d(r.value, r), r.checkbox || r.submenu || !C || p(!1);
89
+ }, w = t ?? /* @__PURE__ */ e.createElement(
90
+ "button",
91
+ {
92
+ type: "button",
93
+ className: n.t,
94
+ "data-open": i ? "true" : void 0,
95
+ disabled: u,
96
+ "aria-haspopup": "menu",
97
+ "aria-expanded": i
98
+ },
99
+ o,
100
+ E ? null : /* @__PURE__ */ e.createElement(Z, null)
101
+ );
102
+ return /* @__PURE__ */ e.createElement(
103
+ D,
104
+ {
105
+ className: m(n.r, y),
106
+ open: i,
107
+ onOpenChange: (r) => {
108
+ u || p(r);
109
+ },
110
+ align: k,
111
+ trigger: w,
112
+ label: typeof o == "string" ? o : void 0,
113
+ disabled: u
114
+ },
115
+ /* @__PURE__ */ e.createElement("div", { className: n.p, "data-align": k }, g.map((r, h) => /* @__PURE__ */ e.createElement(e.Fragment, { key: h }, h > 0 ? /* @__PURE__ */ e.createElement("hr", { className: n.d }) : null, /* @__PURE__ */ e.createElement("div", { className: n.g, role: "group" }, r.title != null ? /* @__PURE__ */ e.createElement("p", { className: n.h }, r.title) : null, r.items.map((c) => {
116
+ const O = r.items.some(
117
+ (s) => s.checked || s.checkbox || s.status != null || s.icon != null
118
+ ), B = /* @__PURE__ */ e.createElement($, { item: c });
119
+ return /* @__PURE__ */ e.createElement(
120
+ "button",
121
+ {
122
+ key: c.value,
123
+ type: "button",
124
+ role: "menuitem",
125
+ className: n.i,
126
+ "data-checked": (c.checked || c.checkbox) && c.checked ? "true" : void 0,
127
+ "data-danger": c.danger ? "true" : void 0,
128
+ disabled: c.disabled,
129
+ "aria-checked": c.checked != null || c.checkbox ? !!c.checked : void 0,
130
+ onClick: () => L(c)
131
+ },
132
+ O ? B ?? /* @__PURE__ */ e.createElement("span", { className: n.n, "aria-hidden": !0 }) : null,
133
+ c.label != null ? /* @__PURE__ */ e.createElement("span", { className: n.l }, c.label) : null,
134
+ c.shortcut != null ? /* @__PURE__ */ e.createElement("span", { className: n.u }, c.shortcut) : null,
135
+ c.submenu ? /* @__PURE__ */ e.createElement(_, null) : null
136
+ );
137
+ })))))
138
+ );
139
+ }
140
+ export {
141
+ le as D
142
+ };
package/dist/Dropdown.css CHANGED
@@ -1 +1 @@
1
- @layer elcrm-components{.crr{position:relative;display:inline-flex;vertical-align:middle}.crt{display:inline-flex;align-items:center;gap:var(--shell-gap-sm);margin:0;padding:var(--shell-padding);box-sizing:border-box;font:inherit;font-size:var(--shell-font-size);font-weight:var(--shell-font-weight);color:var(--shell-color);background:var(--shell-background);border:1px solid var(--shell-border);border-radius:var(--shell-radius);cursor:pointer;-webkit-appearance:none;-moz-appearance:none;appearance:none;line-height:1.2}.crt:hover{background:var(--shell-background-hover)}.crt[data-open=true]{border-color:var(--shell-color-accent);color:var(--shell-color-accent)}.crc{display:inline-flex;width:var(--shell-icon-size);height:var(--shell-icon-size);flex-shrink:0;color:var(--shell-color-muted)}.crt[data-open=true] .crc{color:var(--shell-color-accent)}.crp{min-width:0}.crh{margin:0;padding:var(--shell-padding);font-size:var(--shell-font-size-sm);font-weight:var(--shell-font-weight);color:var(--shell-color-muted);line-height:1.3}.crg{display:flex;flex-direction:column;gap:2px}.crd{height:0;margin:var(--shell-gap-sm) 0;border:0;border-top:1px solid var(--shell-border)}.cri{display:flex;align-items:center;gap:var(--shell-gap-sm);width:100%;margin:0;padding:var(--shell-padding);box-sizing:border-box;text-align:left;font:inherit;font-size:var(--shell-font-size);font-weight:500;color:var(--shell-color);background:transparent;border:none;border-radius:calc(var(--shell-radius) * .7);cursor:pointer;-webkit-appearance:none;-moz-appearance:none;appearance:none;line-height:1.35}.cri:hover:not(:disabled),.cri:focus-visible:not(:disabled){background:var(--shell-background-hover);outline:none}.cri[data-checked=true]{background:var(--shell-background-selected)}.cri[data-danger=true]{color:var(--shell-color-danger)}.cri:disabled,.cri[aria-disabled=true]{opacity:var(--shell-disabled-opacity);cursor:not-allowed}.crn,.crk{display:inline-flex;flex-shrink:0;align-items:center;justify-content:center;width:var(--shell-icon-size);height:var(--shell-icon-size);color:var(--shell-color-muted)}.crk{color:var(--shell-color-accent)}.crl{flex:1;min-width:0}.cru{flex-shrink:0;margin-left:auto;font-size:var(--shell-font-size-sm);color:var(--shell-color-muted)}.crm{display:inline-flex;flex-shrink:0;margin-left:auto;width:var(--shell-icon-size);height:var(--shell-icon-size);color:var(--shell-color-muted)}.crb{display:inline-flex;flex-shrink:0;width:var(--shell-status-size);height:var(--shell-status-size);border-radius:50%}.cro{background:var(--shell-color-success)}.crf{background:var(--shell-color-muted)}.crx{display:inline-flex;flex-shrink:0;align-items:center;justify-content:center;box-sizing:border-box;width:var(--shell-check-size);height:var(--shell-check-size);border:1px solid var(--shell-border);border-radius:calc(var(--shell-radius) * .4);background:var(--shell-background);color:#fff}.cry{border-color:var(--shell-color-accent);background:var(--shell-color-accent)}.crv{width:70%;height:70%;display:block}}
1
+ @layer elcrm-components{.crr{position:relative;display:inline-flex;vertical-align:middle}.crt{display:inline-flex;align-items:center;gap:var(--shell-gap-sm);margin:0;padding:var(--shell-padding);box-sizing:border-box;font:inherit;font-size:var(--shell-font-size);font-weight:var(--shell-font-weight);color:var(--shell-color);background:var(--shell-background);border:1px solid var(--shell-border);border-radius:var(--shell-radius);cursor:pointer;-webkit-appearance:none;-moz-appearance:none;appearance:none;line-height:1.2}.crt:hover{background:var(--shell-background-hover)}.crt[data-open=true]{border-color:var(--shell-color-accent);color:var(--shell-color-accent)}.crc{display:inline-flex;width:var(--shell-icon-size);height:var(--shell-icon-size);flex-shrink:0;color:var(--shell-color-muted)}.crt[data-open=true] .crc{color:var(--shell-color-accent)}.crp{min-width:0}.crh{margin:0;padding:var(--shell-padding);font-size:var(--shell-font-size-sm);font-weight:var(--shell-font-weight);color:var(--shell-color-muted);line-height:1.3}.crg{display:flex;flex-direction:column;gap:2px}.crd{height:0;margin:var(--shell-gap-sm) 0;border:0;border-top:1px solid var(--shell-border)}.cri{display:flex;align-items:center;gap:var(--shell-gap-sm);width:100%;margin:0;padding:var(--shell-padding);box-sizing:border-box;text-align:left;font:inherit;font-size:var(--shell-font-size);font-weight:500;color:var(--shell-color);background:transparent;border:none;border-radius:calc(var(--shell-radius) * .7);cursor:pointer;-webkit-appearance:none;-moz-appearance:none;appearance:none;line-height:1.35}.cri:hover:not(:disabled),.cri:focus-visible:not(:disabled){background:var(--shell-background-hover);outline:none}.cri[data-checked=true]{background:var(--shell-background-selected)}.cri[data-danger=true]{color:var(--shell-color-danger)}.cri[data-danger=true] .crn,.cri[data-danger=true] .crm{color:inherit}.cri:disabled,.cri[aria-disabled=true]{opacity:var(--shell-disabled-opacity);cursor:not-allowed}.crn,.crk{display:inline-flex;flex-shrink:0;align-items:center;justify-content:center;width:var(--shell-icon-size);height:var(--shell-icon-size);color:var(--shell-color-muted)}.crk{color:var(--shell-color-accent)}.crl{flex:1;min-width:0}.cru{flex-shrink:0;margin-left:auto;font-size:var(--shell-font-size-sm);color:var(--shell-color-muted)}.crm{display:inline-flex;flex-shrink:0;margin-left:auto;width:var(--shell-icon-size);height:var(--shell-icon-size);color:var(--shell-color-muted)}.crb{display:inline-flex;flex-shrink:0;width:var(--shell-status-size);height:var(--shell-status-size);border-radius:50%}.cro{background:var(--shell-color-success)}.crf{background:var(--shell-color-muted)}.crx{display:inline-flex;flex-shrink:0;align-items:center;justify-content:center;box-sizing:border-box;width:var(--shell-check-size);height:var(--shell-check-size);border:1px solid var(--shell-border);border-radius:calc(var(--shell-radius) * .4);background:var(--shell-background);color:var(--avatar-color)}.cry{border-color:var(--shell-color-accent);background:var(--shell-color-accent)}.crv{width:70%;height:70%;display:block}}
package/dist/Dropdown.js CHANGED
@@ -1,4 +1,4 @@
1
- import { D as p } from "./Dropdown-CQBMF9aR.js";
1
+ import { D as p } from "./Dropdown-4yUB2tk1.js";
2
2
  export {
3
3
  p as Dropdown
4
4
  };
package/dist/Footer.css CHANGED
@@ -1 +1 @@
1
- @layer elcrm-components{.cfr{padding:var(--shell-padding);color:var(--shell-color-muted);background:transparent;border-top:1px solid var(--shell-border);font-size:var(--shell-font-size-sm)}}
1
+ @layer elcrm-components{.cfr{flex-shrink:0;padding:var(--shell-padding);color:var(--shell-color-muted);background:transparent;border-top:1px solid var(--shell-border);font-size:var(--shell-font-size-sm)}}
package/dist/Item.css CHANGED
@@ -1 +1 @@
1
- @layer elcrm-components{.cir{display:flex;align-items:center;gap:var(--shell-gap-sm);padding:var(--shell-padding);color:var(--shell-color);background:transparent;border:1px solid transparent;border-radius:var(--shell-radius);cursor:default}.cir:is(button,a){-webkit-appearance:none;-moz-appearance:none;appearance:none;font:inherit;text-align:left;width:100%;cursor:pointer}.cir:hover{background:var(--shell-background-hover)}.cia,.cir[aria-current=true],.cir[data-active=true]{background:var(--shell-background-selected)}.cic{align-items:flex-start;gap:12px;padding:12px 14px;border:1px solid var(--shell-border);border-radius:14px;background:var(--shell-background-muted);flex-shrink:0}.cic:hover,.cic.cia,.cic[data-active=true]{background:color-mix(in srgb,var(--shell-color-accent) 12%,var(--shell-background-muted));border-color:color-mix(in srgb,var(--shell-color-accent) 35%,transparent)}}
1
+ @layer elcrm-components{.cir{display:flex;align-items:center;gap:var(--shell-gap-sm);padding:var(--shell-padding);color:var(--shell-color);background:transparent;border:1px solid transparent;border-radius:var(--shell-radius);cursor:default}.cir:is(button,a){-webkit-appearance:none;-moz-appearance:none;appearance:none;font:inherit;text-align:left;width:100%;cursor:pointer}.cir:hover{background:var(--shell-background-hover)}.cia,.cir[aria-current=true],.cir[data-active=true]{background:var(--shell-background-selected)}.cic{align-items:flex-start;gap:var(--shell-gap);padding:var(--shell-padding);border:1px solid var(--shell-border);border-radius:var(--shell-radius);background:var(--shell-background-muted);flex-shrink:0}.cic:hover,.cic.cia,.cic[data-active=true]{background:color-mix(in srgb,var(--shell-color-accent) 12%,var(--shell-background-muted));border-color:color-mix(in srgb,var(--shell-color-accent) 35%,transparent)}}
@@ -1 +1 @@
1
- @layer elcrm-components{.c7r{display:flex;align-items:flex-start;gap:var(--item-column-gap, 12px);min-width:0;width:100%;text-align:left}.c7i{flex-shrink:0;box-sizing:border-box;width:var(--item-column-icon-size, 40px);height:var(--item-column-icon-size, 40px);border-radius:var(--item-column-icon-radius, 999px);display:inline-flex;align-items:center;justify-content:center;background:color-mix(in srgb,var(--shell-color-accent) 14%,transparent);color:var(--shell-color-accent)}.c7b{flex:1;min-width:0;display:flex;flex-direction:column;gap:4px}.c7h{display:flex;align-items:center;gap:8px;min-width:0}.c7t{flex:1;min-width:0;margin:0;font-size:var(--item-column-title-size, var(--shell-font-size));font-weight:var(--shell-font-weight);color:var(--shell-color);line-height:var(--item-column-title-line, 1.3);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.c7x{flex-shrink:0;display:inline-flex;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:6px}.c7d{margin:0;font-size:var(--shell-font-size-sm);font-weight:400;color:var(--shell-color);line-height:1.4;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.c7f{display:flex;flex-wrap:wrap;align-items:baseline;gap:4px 6px;font-size:12px;color:var(--shell-color-muted);line-height:1.35}.c7p{opacity:.5;-webkit-user-select:none;user-select:none}.c7a{flex-shrink:0;display:inline-flex;align-items:flex-start}.c7s .c7t{font-size:var(--shell-font-size-sm)}.c7s .c7d{font-size:12px}.c7l .c7t{font-size:var(--shell-font-size-lg)}.c7l .c7d{font-size:var(--shell-font-size)}.c7k .c7t{font-weight:700}}
1
+ @layer elcrm-components{.c7r{display:flex;align-items:flex-start;gap:var(--item-column-gap);min-width:0;width:100%;text-align:left}.c7i{flex-shrink:0;box-sizing:border-box;width:var(--item-column-icon-size);height:var(--item-column-icon-size);border-radius:var(--item-column-icon-radius);display:inline-flex;align-items:center;justify-content:center;background:color-mix(in srgb,var(--shell-color-accent) 14%,transparent);color:var(--shell-color-accent)}.c7b{flex:1;min-width:0;display:flex;flex-direction:column;gap:4px}.c7h{display:flex;align-items:center;gap:8px;min-width:0}.c7t{flex:1;min-width:0;margin:0;font-size:var(--item-column-title-size);font-weight:var(--shell-font-weight);color:var(--shell-color);line-height:var(--item-column-title-line);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.c7x{flex-shrink:0;display:inline-flex;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:6px}.c7d{margin:0;font-size:var(--shell-font-size-sm);font-weight:400;color:var(--shell-color);line-height:1.4;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.c7f{display:flex;flex-wrap:wrap;align-items:baseline;gap:4px 6px;font-size:12px;color:var(--shell-color-muted);line-height:1.35}.c7p{opacity:.5;-webkit-user-select:none;user-select:none}.c7a{flex-shrink:0;display:inline-flex;align-items:flex-start}.c7s .c7t{font-size:var(--shell-font-size-sm)}.c7s .c7d{font-size:12px}.c7l .c7t{font-size:var(--shell-font-size-lg)}.c7l .c7d{font-size:var(--shell-font-size)}.c7k .c7t{font-weight:700}}
@@ -1,4 +1,5 @@
1
1
  import { default as React } from 'react';
2
+ import { UiSize } from './types';
2
3
  /**
3
4
  * Колонка содержимого строки списка: иконка слева, текст столбиком, слоты справа.
4
5
  *
@@ -47,7 +48,7 @@ export type ItemColumnProps = Omit<React.HTMLAttributes<HTMLDivElement>, "title"
47
48
  /** Куски подвала через точку — если нет `footer` */
48
49
  meta?: React.ReactNode[];
49
50
  /** Размер текста */
50
- size?: "s" | "m" | "l";
51
+ size?: UiSize;
51
52
  /** Жирный title (непрочитанное) */
52
53
  unread?: boolean;
53
54
  /** Доп. строки под footer */