@elcrm/components 0.1.1 → 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.
- package/README.md +130 -16
- package/dist/ActionGroup-ChKFW0mt.js +27 -0
- package/dist/ActionGroup.css +1 -0
- package/dist/ActionGroup.d.ts +42 -0
- package/dist/ActionGroup.js +4 -0
- package/dist/Avatar-loGgFt72.js +113 -0
- package/dist/Avatar.d.ts +11 -2
- package/dist/Avatar.js +3 -2
- package/dist/{AvatarGroup-BAWas4pU.js → AvatarGroup-D1gnT3Od.js} +1 -1
- package/dist/AvatarGroup.d.ts +2 -1
- package/dist/AvatarGroup.js +1 -1
- package/dist/AvatarName-0BzyfpMq.js +68 -0
- package/dist/AvatarName.css +1 -1
- package/dist/AvatarName.d.ts +8 -2
- package/dist/AvatarName.js +1 -1
- package/dist/Badge-jp-9iNNL.js +28 -0
- package/dist/Badge.css +1 -1
- package/dist/Badge.d.ts +33 -17
- package/dist/Badge.js +1 -1
- package/dist/{Block-BAXh0PPp.js → Block-Bu7NEA0g.js} +1 -1
- package/dist/Block.js +1 -1
- package/dist/Card.css +1 -1
- package/dist/Card.d.ts +8 -1
- package/dist/ChatFrame-BW2TmCkZ.js +37 -0
- package/dist/ChatFrame.css +1 -0
- package/dist/ChatList.d.ts +9 -0
- package/dist/ChatList.js +7 -0
- package/dist/ChatMessages-B8rdXiK-.js +19 -0
- package/dist/ChatMessages.d.ts +9 -0
- package/dist/ChatMessages.js +4 -0
- package/dist/ChatSplit-DNnu3TNq.js +21 -0
- package/dist/CheckIcon-FdB8fMEF.js +17 -0
- package/dist/CheckIcon.d.ts +8 -0
- package/dist/{Column-DDaqX-A7.js → Column-BiogBDf8.js} +1 -1
- package/dist/Column.js +1 -1
- package/dist/Dropdown-4yUB2tk1.js +142 -0
- package/dist/Dropdown.css +1 -1
- package/dist/Dropdown.d.ts +3 -3
- package/dist/Dropdown.js +1 -1
- package/dist/Footer.css +1 -1
- package/dist/Item-D4okhsfW.js +46 -0
- package/dist/Item.css +1 -1
- package/dist/Item.d.ts +8 -1
- package/dist/Item.js +1 -1
- package/dist/ItemColumn-M7a9L8CI.js +41 -0
- package/dist/ItemColumn.css +1 -0
- package/dist/ItemColumn.d.ts +62 -0
- package/dist/ItemColumn.js +4 -0
- package/dist/Layout-mi6Ghayv.js +31 -0
- package/dist/Layout.css +1 -1
- package/dist/Layout.d.ts +28 -6
- package/dist/Layout.js +1 -1
- package/dist/Loading-DkkG7RcE.js +16 -0
- package/dist/Loading.css +1 -1
- package/dist/Loading.d.ts +1 -1
- package/dist/Loading.js +1 -1
- package/dist/Menu-DuXQv-zT.js +66 -0
- package/dist/Menu.css +1 -1
- package/dist/Menu.d.ts +15 -3
- package/dist/Menu.js +1 -1
- package/dist/NavSections-BpyZPimZ.js +79 -0
- package/dist/NavSections.css +1 -1
- package/dist/NavSections.js +1 -1
- package/dist/PageHead-DgaJ1mXY.js +31 -0
- package/dist/PageHead.css +1 -1
- package/dist/PageHead.d.ts +28 -6
- package/dist/PageHead.js +1 -1
- package/dist/{PageShell-CghThHS3.js → PageShell-D9EZiO8o.js} +13 -11
- package/dist/PageShell.css +1 -1
- package/dist/PageShell.d.ts +11 -6
- package/dist/PageShell.js +1 -1
- package/dist/Popover-D0m5JWIt.js +142 -0
- package/dist/Popover.css +1 -0
- package/dist/Popover.d.ts +54 -0
- package/dist/Popover.js +4 -0
- package/dist/PricingGroup-Czuhe81Z.js +120 -0
- package/dist/PricingGroup.css +1 -1
- package/dist/PricingGroup.js +1 -1
- package/dist/{PricingTable-DALddSwM.js → PricingTable-BuLC0opK.js} +69 -75
- package/dist/PricingTable.css +1 -1
- package/dist/PricingTable.js +1 -1
- package/dist/RadioGroup-fcXzhvMu.js +129 -0
- package/dist/RadioGroup.css +1 -1
- package/dist/RadioGroup.js +1 -1
- package/dist/{Row--HIe6vb9.js → Row-DsQOVn18.js} +1 -1
- package/dist/Row.js +1 -1
- package/dist/Sidebar-CBYq1ad6.js +107 -0
- package/dist/Sidebar.css +1 -0
- package/dist/Sidebar.d.ts +99 -0
- package/dist/Sidebar.js +4 -0
- package/dist/Stack-XkmPSswj.js +53 -0
- package/dist/Stack.css +1 -1
- package/dist/Stack.d.ts +16 -4
- package/dist/Stack.js +3 -2
- package/dist/Stat-C5iZyEoo.js +27 -0
- package/dist/Stat.css +1 -0
- package/dist/Stat.d.ts +39 -0
- package/dist/Stat.js +4 -0
- package/dist/TabSections-DN7yVJoF.js +69 -0
- package/dist/TabSections.css +1 -1
- package/dist/TabSections.js +1 -1
- package/dist/TextGroup-DmhuyMR1.js +23 -0
- package/dist/TextGroup.css +1 -0
- package/dist/TextGroup.d.ts +36 -0
- package/dist/TextGroup.js +4 -0
- package/dist/badgeText-CRzlIzi3.js +8 -0
- package/dist/badgeText.d.ts +4 -0
- package/dist/dark.css +13 -0
- package/dist/index.css +31 -17
- package/dist/index.d.ts +27 -4
- package/dist/index.es.d.ts +82 -0
- package/dist/index.es.js +83 -59
- package/dist/light.css +13 -0
- package/dist/overlayZ.d.ts +9 -0
- package/dist/rovingKeys-CGlfTtNQ.js +15 -0
- package/dist/rovingKeys.d.ts +13 -0
- package/dist/tokens.css +44 -4
- package/dist/types.d.ts +2 -0
- package/dist/useControllableValue-CWqH1kpM.js +10 -0
- package/dist/useControllableValue.d.ts +4 -0
- package/package.json +6 -2
- package/dist/Avatar-CyNXYvsa.js +0 -101
- package/dist/AvatarName-DhD3TytF.js +0 -56
- package/dist/Badge-l6nUkl-H.js +0 -22
- package/dist/Dropdown-DQlDiWCR.js +0 -168
- package/dist/Item-CaU4RW2G.js +0 -38
- package/dist/Layout-Xb3-xsmA.js +0 -18
- package/dist/Loading-ChGq9peU.js +0 -15
- package/dist/Menu-DRBHvSdJ.js +0 -40
- package/dist/NavSections-NDcIDD6H.js +0 -59
- package/dist/PageHead-Baz9BLuA.js +0 -22
- package/dist/PricingGroup-DgcdVSq8.js +0 -126
- package/dist/RadioGroup-D2UUOTkY.js +0 -138
- package/dist/Stack-b0-XWwQ1.js +0 -31
- package/dist/TabSections-DL7DufKU.js +0 -50
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
import { UiSize } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* Колонка содержимого строки списка: иконка слева, текст столбиком, слоты справа.
|
|
5
|
+
*
|
|
6
|
+
* Роли: внутри {@link Item} / {@link Card} (идеи, тикеты, inbox).
|
|
7
|
+
* Не заменяет Item (клик / active) и не AvatarName (там фото).
|
|
8
|
+
*
|
|
9
|
+
* @param icon кружок слева (иконка приложения)
|
|
10
|
+
* @param title первая строка
|
|
11
|
+
* @param extra бейджи в правом верхнем углу строки title
|
|
12
|
+
* @param aside колонка справа на всю высоту (дата, действия)
|
|
13
|
+
* @param description превью / вторая строка
|
|
14
|
+
* @param footer третья строка (мета)
|
|
15
|
+
* @param meta куски футера через «·» (если нет footer)
|
|
16
|
+
* @param size `s` | `m` | `l`
|
|
17
|
+
* @param unread жирный title (непрочитанное)
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```tsx
|
|
21
|
+
* <Item as="button" onClick={open}>
|
|
22
|
+
* <ItemColumn
|
|
23
|
+
* icon={<Icon />}
|
|
24
|
+
* title="Тема"
|
|
25
|
+
* extra={<Badge size="s" tone="accent">Новые</Badge>}
|
|
26
|
+
* description="Превью текста…"
|
|
27
|
+
* meta={["★ 2", "3 комм.", "Иван"]}
|
|
28
|
+
* />
|
|
29
|
+
* </Item>
|
|
30
|
+
* ```
|
|
31
|
+
*
|
|
32
|
+
* Токены: `--item-column-gap`, `--item-column-icon-size`, `--item-column-icon-radius`,
|
|
33
|
+
* `--item-column-title-size`, `--item-column-title-line`.
|
|
34
|
+
*/
|
|
35
|
+
export type ItemColumnProps = Omit<React.HTMLAttributes<HTMLDivElement>, "title"> & {
|
|
36
|
+
/** Иконка слева */
|
|
37
|
+
icon?: React.ReactNode;
|
|
38
|
+
/** Заголовок */
|
|
39
|
+
title?: React.ReactNode;
|
|
40
|
+
/** Справа сверху у title (Badge, счётчик) */
|
|
41
|
+
extra?: React.ReactNode;
|
|
42
|
+
/** Правая колонка (верхний край) */
|
|
43
|
+
aside?: React.ReactNode;
|
|
44
|
+
/** Описание / превью */
|
|
45
|
+
description?: React.ReactNode;
|
|
46
|
+
/** Подвал целиком */
|
|
47
|
+
footer?: React.ReactNode;
|
|
48
|
+
/** Куски подвала через точку — если нет `footer` */
|
|
49
|
+
meta?: React.ReactNode[];
|
|
50
|
+
/** Размер текста */
|
|
51
|
+
size?: UiSize;
|
|
52
|
+
/** Жирный title (непрочитанное) */
|
|
53
|
+
unread?: boolean;
|
|
54
|
+
/** Доп. строки под footer */
|
|
55
|
+
children?: React.ReactNode;
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* Иконка + колонка title / description / footer (+ extra / aside).
|
|
59
|
+
*
|
|
60
|
+
* @see Item, TextGroup, AvatarName, Badge
|
|
61
|
+
*/
|
|
62
|
+
export declare function ItemColumn({ icon, title, extra, aside, description, footer, meta, size, unread, children, className, ...rest }: ItemColumnProps): React.JSX.Element;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import l from "react";
|
|
2
|
+
import { c as a } from "./cx-CcykAxZN.js";
|
|
3
|
+
import './Layout.css';const f = "clr", h = "clx", k = "clm", x = "cls", F = "clb", L = "cla", g = "clk", y = "clh", D = "clf", n = {
|
|
4
|
+
r: f,
|
|
5
|
+
x: h,
|
|
6
|
+
m: k,
|
|
7
|
+
s: x,
|
|
8
|
+
b: F,
|
|
9
|
+
a: L,
|
|
10
|
+
k: g,
|
|
11
|
+
h: y,
|
|
12
|
+
f: D
|
|
13
|
+
}, p = ["header", "footer", "sidebar"];
|
|
14
|
+
function o(e, c) {
|
|
15
|
+
return (e ?? p).includes(c);
|
|
16
|
+
}
|
|
17
|
+
function I({
|
|
18
|
+
sidebar: e,
|
|
19
|
+
header: c,
|
|
20
|
+
footer: t,
|
|
21
|
+
fixed: s,
|
|
22
|
+
children: b,
|
|
23
|
+
className: m,
|
|
24
|
+
...r
|
|
25
|
+
}) {
|
|
26
|
+
const u = c != null && o(s, "header"), i = t != null && o(s, "footer"), v = e != null && o(s, "sidebar"), E = (s ?? p).length > 0, N = /* @__PURE__ */ l.createElement("main", { className: n.m }, c != null && !u ? c : null, b, t != null && !i ? t : null), d = /* @__PURE__ */ l.createElement(l.Fragment, null, u ? /* @__PURE__ */ l.createElement("div", { className: n.h }, c) : null, N, i ? /* @__PURE__ */ l.createElement("div", { className: n.f }, t) : null);
|
|
27
|
+
return e != null ? /* @__PURE__ */ l.createElement("div", { className: a(n.r, n.s, E && n.x, m), ...r }, /* @__PURE__ */ l.createElement("div", { className: a(n.a, v && n.k) }, e), /* @__PURE__ */ l.createElement("div", { className: n.b }, d)) : /* @__PURE__ */ l.createElement("div", { className: a(n.r, E && n.x, m), ...r }, d);
|
|
28
|
+
}
|
|
29
|
+
export {
|
|
30
|
+
I as L
|
|
31
|
+
};
|
package/dist/Layout.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
@layer elcrm-components{.clr{display:flex;flex-direction:column;flex:1 1 auto;
|
|
1
|
+
@layer elcrm-components{.clr{display:flex;flex-direction:column;flex:1 1 auto;min-height:0;box-sizing:border-box;background:var(--shell-background-muted);gap:0}.clx{height:var(--layout-height);max-height:var(--layout-height);overflow:hidden}.clm{display:flex;flex-direction:column;flex:1 1 auto;min-width:0;min-height:0;overflow:auto;overscroll-behavior:contain}.clr:not(.clx){height:auto;max-height:none;overflow:visible}.clr:not(.clx) .clm{overflow:visible;flex:0 1 auto;min-height:auto}.cls{flex-direction:row;align-items:stretch}.clb{display:flex;flex-direction:column;flex:1 1 auto;min-width:0;min-height:0;overflow:hidden}.clr:not(.clx) .clb{overflow:visible}.cla{display:flex;flex-direction:column;flex:0 0 auto;min-height:0;align-self:stretch}.clk{overflow:hidden}.cla:not(.clk){overflow:auto}.cla>*{flex:1 1 auto;min-height:0;height:auto;max-height:100%}.clh,.clf{flex:0 0 auto;min-width:0}}
|
package/dist/Layout.d.ts
CHANGED
|
@@ -1,30 +1,52 @@
|
|
|
1
1
|
import { default as React } from 'react';
|
|
2
|
+
/** Слот каркаса, который можно закрепить вне скролла `children`. */
|
|
3
|
+
export type LayoutFixedSlot = "header" | "footer" | "sidebar";
|
|
2
4
|
/**
|
|
3
5
|
* Оболочка приложения: шапка, основной контент, подвал.
|
|
4
6
|
*
|
|
5
7
|
* Роли: Layout = каркас страницы; внутри — Header / Section / PageShell / Footer.
|
|
6
8
|
* Используйте как корневой каркас маршрута или приложения.
|
|
7
9
|
*
|
|
10
|
+
* `fixed` — какие слоты не крутятся вместе со страницей.
|
|
11
|
+
* По умолчанию `["header", "footer", "sidebar"]`: скроллится только `children` в `<main>`.
|
|
12
|
+
* Пустой массив — обычный поток, скролл у предка.
|
|
13
|
+
*
|
|
14
|
+
* Высота каркаса: `--layout-height` (по умолчанию `100dvh`).
|
|
15
|
+
* Вложенный стенд: `--layout-height: 100%` у родителя с явной высотой.
|
|
16
|
+
*
|
|
8
17
|
* @example
|
|
9
18
|
* ```tsx
|
|
10
|
-
* <Layout
|
|
11
|
-
*
|
|
19
|
+
* <Layout
|
|
20
|
+
* fixed={["header", "footer", "sidebar"]}
|
|
21
|
+
* sidebar={<Sidebar groups={groups} value={page} onSelect={setPage} />}
|
|
22
|
+
* header={<Header brand="App" />}
|
|
23
|
+
* footer={<Footer>© elCRM</Footer>}
|
|
24
|
+
* >
|
|
25
|
+
* <PageShell>…</PageShell>
|
|
12
26
|
* </Layout>
|
|
13
27
|
* ```
|
|
14
28
|
*
|
|
15
|
-
* Токены: `--shell-background-muted
|
|
29
|
+
* Токены: `--layout-height`, `--shell-background-muted`, прочие `--shell-*`.
|
|
16
30
|
*/
|
|
17
31
|
export type LayoutProps = React.HTMLAttributes<HTMLDivElement> & {
|
|
32
|
+
/** Левая колонка (обычно `<Sidebar />`) — ряд: сайдбар + контент */
|
|
33
|
+
sidebar?: React.ReactNode;
|
|
18
34
|
/** Слот шапки (обычно `<Header />`) */
|
|
19
35
|
header?: React.ReactNode;
|
|
20
36
|
/** Слот подвала (обычно `<Footer />`) */
|
|
21
37
|
footer?: React.ReactNode;
|
|
38
|
+
/**
|
|
39
|
+
* Какие слоты зафиксированы (не прокручиваются).
|
|
40
|
+
* По умолчанию все: `header`, `footer`, `sidebar`.
|
|
41
|
+
* `[]` — ничего не фиксировать.
|
|
42
|
+
*/
|
|
43
|
+
fixed?: LayoutFixedSlot[];
|
|
22
44
|
/** Основной контент страницы (рендерится в `<main>`) */
|
|
23
45
|
children?: React.ReactNode;
|
|
24
46
|
};
|
|
25
47
|
/**
|
|
26
|
-
*
|
|
48
|
+
* Оболочка: опционально `sidebar` слева, затем header + main + footer.
|
|
27
49
|
*
|
|
28
|
-
* @see Header, Footer, Section, PageShell
|
|
50
|
+
* @see Sidebar, Header, Footer, Section, PageShell
|
|
29
51
|
*/
|
|
30
|
-
export declare function Layout({ header, footer, children, className, ...rest }: LayoutProps): React.JSX.Element;
|
|
52
|
+
export declare function Layout({ sidebar, header, footer, fixed, children, className, ...rest }: LayoutProps): React.JSX.Element;
|
package/dist/Layout.js
CHANGED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import e from "react";
|
|
2
|
+
import { c as s } from "./cx-CcykAxZN.js";
|
|
3
|
+
import './Loading.css';const i = "cgr", n = "cgi", r = {
|
|
4
|
+
r: i,
|
|
5
|
+
i: n
|
|
6
|
+
};
|
|
7
|
+
function l({
|
|
8
|
+
children: t = "Загрузка…",
|
|
9
|
+
className: a,
|
|
10
|
+
...c
|
|
11
|
+
}) {
|
|
12
|
+
return /* @__PURE__ */ e.createElement("div", { className: s(r.r, a), role: "status", ...c }, /* @__PURE__ */ e.createElement("span", { className: r.i, "aria-hidden": !0 }), t);
|
|
13
|
+
}
|
|
14
|
+
export {
|
|
15
|
+
l as L
|
|
16
|
+
};
|
package/dist/Loading.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
@layer elcrm-components{.cgr{display:flex;align-items:center;justify-content:center;padding:var(--shell-gap-lg);color:var(--shell-color-muted)}}
|
|
1
|
+
@layer elcrm-components{.cgr{display:flex;align-items:center;justify-content:center;gap:var(--shell-gap-sm);padding:var(--shell-gap-lg);color:var(--shell-color-muted)}.cgi{box-sizing:border-box;width:var(--shell-icon-size);height:var(--shell-icon-size);border:2px solid var(--shell-border);border-top-color:var(--shell-color-accent);border-radius:var(--avatar-radius);animation:cgspin .7s linear infinite}}@keyframes cgspin{to{transform:rotate(360deg)}}
|
package/dist/Loading.d.ts
CHANGED
package/dist/Loading.js
CHANGED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import d from "react";
|
|
2
|
+
import { B as g } from "./Badge-jp-9iNNL.js";
|
|
3
|
+
import { b as x } from "./badgeText-CRzlIzi3.js";
|
|
4
|
+
import { c as i } from "./cx-CcykAxZN.js";
|
|
5
|
+
import { h as y } from "./rovingKeys-CGlfTtNQ.js";
|
|
6
|
+
import './Menu.css';const h = "cmr", k = "cmv", E = "cmi", N = "cmd", w = "cma", B = "cmu", n = {
|
|
7
|
+
r: h,
|
|
8
|
+
v: k,
|
|
9
|
+
i: E,
|
|
10
|
+
d: N,
|
|
11
|
+
a: w,
|
|
12
|
+
u: B
|
|
13
|
+
};
|
|
14
|
+
function D({
|
|
15
|
+
items: s,
|
|
16
|
+
vertical: l,
|
|
17
|
+
variant: u = "plain",
|
|
18
|
+
value: e,
|
|
19
|
+
onSelect: c,
|
|
20
|
+
children: b,
|
|
21
|
+
className: p,
|
|
22
|
+
...m
|
|
23
|
+
}) {
|
|
24
|
+
const f = (s ?? []).filter((a) => !a.disabled).map((a) => a.value), o = u === "line";
|
|
25
|
+
return /* @__PURE__ */ d.createElement(
|
|
26
|
+
"nav",
|
|
27
|
+
{
|
|
28
|
+
className: i(n.r, l && n.v, o && n.u, p),
|
|
29
|
+
role: o ? "tablist" : void 0,
|
|
30
|
+
onKeyDown: c ? (a) => y(a, {
|
|
31
|
+
values: f,
|
|
32
|
+
value: e,
|
|
33
|
+
onSelect: c,
|
|
34
|
+
vertical: l
|
|
35
|
+
}) : void 0,
|
|
36
|
+
...m
|
|
37
|
+
},
|
|
38
|
+
s == null ? void 0 : s.map((a) => {
|
|
39
|
+
const r = a.active ?? (e != null && a.value === e), t = x(a.badge);
|
|
40
|
+
return /* @__PURE__ */ d.createElement(
|
|
41
|
+
"button",
|
|
42
|
+
{
|
|
43
|
+
key: a.value,
|
|
44
|
+
type: "button",
|
|
45
|
+
role: o ? "tab" : void 0,
|
|
46
|
+
className: i(n.i, r && n.a),
|
|
47
|
+
"data-active": r ? "true" : void 0,
|
|
48
|
+
"aria-current": o ? void 0 : r ? "page" : void 0,
|
|
49
|
+
"aria-selected": o ? r : void 0,
|
|
50
|
+
tabIndex: o ? r ? 0 : -1 : void 0,
|
|
51
|
+
disabled: a.disabled,
|
|
52
|
+
onClick: () => {
|
|
53
|
+
var v;
|
|
54
|
+
(v = a.onClick) == null || v.call(a), c == null || c(a.value);
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
a.label,
|
|
58
|
+
t != null ? /* @__PURE__ */ d.createElement(g, { className: n.d, tone: "accent", size: "s" }, t) : null
|
|
59
|
+
);
|
|
60
|
+
}),
|
|
61
|
+
b
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
export {
|
|
65
|
+
D as M
|
|
66
|
+
};
|
package/dist/Menu.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
@layer elcrm-components{.cmr{display:flex;align-items:center;gap:var(--shell-gap-sm);margin:0;padding:0;list-style:none}.cmv{flex-direction:column;align-items:stretch}.cmi{-webkit-appearance:none;-moz-appearance:none;appearance:none;display:inline-flex;align-items:center;justify-content:center;border:0;background:transparent;color:var(--shell-color-muted);padding:var(--shell-padding);border-radius:var(--shell-radius);font:inherit;line-height:1;cursor:pointer;text-align:left}.cmi>svg{display:block;flex-shrink:0}.cmi:hover{background:var(--shell-background-hover);color:var(--shell-color)}.cma,.cmi[aria-current=page],.cmi[data-active=true]{background:var(--shell-background-selected);color:var(--shell-color)}}
|
|
1
|
+
@layer elcrm-components{.cmr{display:flex;align-items:center;gap:var(--shell-gap-sm);margin:0;padding:0;list-style:none}.cmv{flex-direction:column;align-items:stretch}.cmi{-webkit-appearance:none;-moz-appearance:none;appearance:none;display:inline-flex;align-items:center;justify-content:center;border:0;background:transparent;color:var(--shell-color-muted);padding:var(--shell-padding);border-radius:var(--shell-radius);font:inherit;line-height:1;cursor:pointer;text-align:left;gap:var(--shell-gap-sm)}.cmd{flex-shrink:0;min-width:16px;height:16px;padding:0 4px;font-size:10px}.cmi>svg{display:block;flex-shrink:0}.cmi:hover{background:var(--shell-background-hover);color:var(--shell-color)}.cma,.cmi[aria-current=page],.cmi[data-active=true]{background:var(--shell-background-selected);color:var(--shell-color)}.cmu{width:100%;align-items:stretch;gap:1.25rem;padding:0;border-bottom:1px solid var(--shell-border)}.cmu .cmi{border-radius:0;background:transparent;padding:.45rem .1rem .55rem;border-bottom:2px solid transparent;margin-bottom:-1px}.cmu .cmi:hover{background:transparent;color:var(--shell-color)}.cmu .cma,.cmu .cmi[aria-current=page],.cmu .cmi[data-active=true]{background:transparent;color:var(--shell-color);border-bottom-color:var(--shell-color-accent)}}
|
package/dist/Menu.d.ts
CHANGED
|
@@ -19,6 +19,11 @@ export type MenuItem = {
|
|
|
19
19
|
onClick?: () => void;
|
|
20
20
|
/** Недоступный пункт. */
|
|
21
21
|
disabled?: boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Счётчик справа (`Badge`).
|
|
24
|
+
* `0`, `null`, `""` — не рендерим.
|
|
25
|
+
*/
|
|
26
|
+
badge?: number | string | null;
|
|
22
27
|
};
|
|
23
28
|
/**
|
|
24
29
|
* Props компонента {@link Menu}.
|
|
@@ -34,6 +39,11 @@ export type MenuProps = Omit<React.HTMLAttributes<HTMLElement>, "onSelect"> & {
|
|
|
34
39
|
items?: MenuItem[];
|
|
35
40
|
/** Вертикальный ряд пунктов. */
|
|
36
41
|
vertical?: boolean;
|
|
42
|
+
/**
|
|
43
|
+
* `plain` — пилюли.
|
|
44
|
+
* `line` — вкладки с нижней чертой (фильтры страницы).
|
|
45
|
+
*/
|
|
46
|
+
variant?: "plain" | "line";
|
|
37
47
|
/**
|
|
38
48
|
* Активный `value` пункта (если у item не задан `active`).
|
|
39
49
|
* Идентификатор — `value`, не `key`.
|
|
@@ -53,18 +63,20 @@ export type MenuProps = Omit<React.HTMLAttributes<HTMLElement>, "onSelect"> & {
|
|
|
53
63
|
*
|
|
54
64
|
* Связанные компоненты:
|
|
55
65
|
* - {@link Dropdown} — выпадающая панель рядом с триггером;
|
|
56
|
-
* -
|
|
66
|
+
* - {@link Popover} / {@link Dropdown} — панель в portal;
|
|
57
67
|
* - {@link NavSections} / {@link TabSections} — разделы с lazy-контентом.
|
|
58
68
|
*
|
|
59
69
|
* API: декларативные `items` (идентификатор — `value`). Compound-слоты не используются.
|
|
60
70
|
*
|
|
71
|
+
* @param variant `plain` (пилюли) или `line` (черта снизу)
|
|
72
|
+
*
|
|
61
73
|
* CSS-токены: `--shell-*` (цвета/отступы shell-навигации).
|
|
62
74
|
*
|
|
63
75
|
* @example
|
|
64
76
|
* ```tsx
|
|
65
77
|
* const items = [
|
|
66
78
|
* { value: "home", label: "Главная" },
|
|
67
|
-
* { value: "team", label: "Команда",
|
|
79
|
+
* { value: "team", label: "Команда", badge: 3 },
|
|
68
80
|
* ];
|
|
69
81
|
*
|
|
70
82
|
* <Menu
|
|
@@ -75,4 +87,4 @@ export type MenuProps = Omit<React.HTMLAttributes<HTMLElement>, "onSelect"> & {
|
|
|
75
87
|
* />
|
|
76
88
|
* ```
|
|
77
89
|
*/
|
|
78
|
-
export declare function Menu({ items, vertical, value, onSelect, children, className, ...rest }: MenuProps): React.JSX.Element;
|
|
90
|
+
export declare function Menu({ items, vertical, variant, value, onSelect, children, className, ...rest }: MenuProps): React.JSX.Element;
|
package/dist/Menu.js
CHANGED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import a, { useMemo as h, Suspense as S } from "react";
|
|
2
|
+
import { c as d } from "./cx-CcykAxZN.js";
|
|
3
|
+
import { I as g } from "./Item-D4okhsfW.js";
|
|
4
|
+
import { h as x } from "./rovingKeys-CGlfTtNQ.js";
|
|
5
|
+
import { u as C } from "./useControllableValue-CWqH1kpM.js";
|
|
6
|
+
import './NavSections.css';const I = "cvr", K = "cvn", M = "cvg", R = "cvl", V = "cvi", w = "cva", D = "cvc", P = "cvt", j = "cvf", q = "cvm", l = {
|
|
7
|
+
r: I,
|
|
8
|
+
n: K,
|
|
9
|
+
g: M,
|
|
10
|
+
l: R,
|
|
11
|
+
i: V,
|
|
12
|
+
a: w,
|
|
13
|
+
c: D,
|
|
14
|
+
t: P,
|
|
15
|
+
f: j,
|
|
16
|
+
m: q
|
|
17
|
+
};
|
|
18
|
+
function z(n) {
|
|
19
|
+
for (const m of n) {
|
|
20
|
+
const c = m.items.find((s) => !s.disabled);
|
|
21
|
+
if (c) return c.value;
|
|
22
|
+
}
|
|
23
|
+
return "";
|
|
24
|
+
}
|
|
25
|
+
function J({
|
|
26
|
+
groups: n,
|
|
27
|
+
resolveSection: m,
|
|
28
|
+
value: c,
|
|
29
|
+
defaultValue: s,
|
|
30
|
+
onValueChange: f,
|
|
31
|
+
loading: b = null,
|
|
32
|
+
footer: i,
|
|
33
|
+
className: E,
|
|
34
|
+
navLabel: N = "Разделы"
|
|
35
|
+
}) {
|
|
36
|
+
const p = h(
|
|
37
|
+
() => s || z(n),
|
|
38
|
+
[s, n]
|
|
39
|
+
), [r, v] = C(
|
|
40
|
+
c,
|
|
41
|
+
p,
|
|
42
|
+
f
|
|
43
|
+
), k = n.flatMap((e) => e.items).filter((e) => !e.disabled).map((e) => e.value), u = r ? m(r) : null;
|
|
44
|
+
return /* @__PURE__ */ a.createElement("div", { className: d(l.r, E) }, /* @__PURE__ */ a.createElement(
|
|
45
|
+
"nav",
|
|
46
|
+
{
|
|
47
|
+
className: l.n,
|
|
48
|
+
"aria-label": N,
|
|
49
|
+
onKeyDown: (e) => x(e, {
|
|
50
|
+
values: k,
|
|
51
|
+
value: r,
|
|
52
|
+
onSelect: v,
|
|
53
|
+
vertical: !0
|
|
54
|
+
})
|
|
55
|
+
},
|
|
56
|
+
n.map((e, y) => /* @__PURE__ */ a.createElement("div", { key: y, className: l.g }, e.label != null ? /* @__PURE__ */ a.createElement("div", { className: l.l }, e.label) : null, e.items.map((t) => {
|
|
57
|
+
const o = t.value === r;
|
|
58
|
+
return /* @__PURE__ */ a.createElement(
|
|
59
|
+
g,
|
|
60
|
+
{
|
|
61
|
+
key: t.value,
|
|
62
|
+
as: "button",
|
|
63
|
+
active: o,
|
|
64
|
+
className: d(l.i, o && l.a),
|
|
65
|
+
"data-active": o ? "true" : void 0,
|
|
66
|
+
"aria-current": o ? "page" : void 0,
|
|
67
|
+
disabled: t.disabled,
|
|
68
|
+
onClick: () => v(t.value)
|
|
69
|
+
},
|
|
70
|
+
t.icon != null ? /* @__PURE__ */ a.createElement("span", { className: l.c, "aria-hidden": !0 }, t.icon) : null,
|
|
71
|
+
/* @__PURE__ */ a.createElement("span", { className: l.t }, t.label)
|
|
72
|
+
);
|
|
73
|
+
}))),
|
|
74
|
+
i != null ? /* @__PURE__ */ a.createElement("div", { className: l.f }, i) : null
|
|
75
|
+
), /* @__PURE__ */ a.createElement("div", { className: l.m }, u ? /* @__PURE__ */ a.createElement(S, { fallback: b }, a.createElement(u)) : null));
|
|
76
|
+
}
|
|
77
|
+
export {
|
|
78
|
+
J as N
|
|
79
|
+
};
|
package/dist/NavSections.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
@layer elcrm-components{.cvr{display:flex;align-items:stretch;gap:var(--shell-gap-lg);width:100%;flex:1 1 auto;min-height:0;box-sizing:border-box;padding:var(--nav-sections-padding)}.cvn{display:flex;flex-direction:column;gap:var(--shell-gap);flex:0 0 var(--nav-sections-nav-width);width:var(--nav-sections-nav-width);min-width:var(--nav-sections-nav-width);box-sizing:border-box}.cvg{display:flex;flex-direction:column;gap:2px;padding-bottom:var(--shell-gap);border-bottom:1px solid var(--shell-border)}.cvg:last-of-type{border-bottom:none;padding-bottom:0}.cvl{font-size:
|
|
1
|
+
@layer elcrm-components{.cvr{display:flex;align-items:stretch;gap:var(--shell-gap-lg);width:100%;flex:1 1 auto;min-height:0;box-sizing:border-box;padding:var(--nav-sections-padding)}.cvn{display:flex;flex-direction:column;gap:var(--shell-gap);flex:0 0 var(--nav-sections-nav-width);width:var(--nav-sections-nav-width);min-width:var(--nav-sections-nav-width);box-sizing:border-box}.cvg{display:flex;flex-direction:column;gap:2px;padding-bottom:var(--shell-gap);border-bottom:1px solid var(--shell-border)}.cvg:last-of-type{border-bottom:none;padding-bottom:0}.cvl{font-size:var(--sidebar-group-font-size);font-weight:var(--shell-font-weight);letter-spacing:.04em;text-transform:uppercase;color:var(--shell-color-muted);padding:0 var(--shell-padding-inline) var(--shell-gap-sm)}.cvi:is(button){position:relative;font-size:var(--shell-font-size-sm)}.cva:before{content:"";position:absolute;left:0;top:6px;bottom:6px;width:3px;border-radius:0 2px 2px 0;background:var(--shell-color-accent)}.cvi:disabled{opacity:var(--shell-disabled-opacity);cursor:not-allowed}.cvc{display:inline-flex;flex:0 0 auto;color:var(--shell-color-muted);line-height:0}.cva .cvc{color:var(--shell-color)}.cvt{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.cvf{margin-top:auto;padding-top:var(--shell-gap);border-top:1px solid var(--shell-border)}.cvm{flex:1 1 auto;min-width:0;max-width:var(--nav-sections-main-max-width);width:100%;min-height:0;overflow:auto}@media (max-width: 720px){.cvr{flex-direction:column}.cvn{flex:none;width:100%;min-width:0;max-width:none}}}
|
package/dist/NavSections.js
CHANGED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import c from "react";
|
|
2
|
+
import { c as o } from "./cx-CcykAxZN.js";
|
|
3
|
+
import './PageHead.css';const u = "ccr", f = "cck", i = "ccw", E = "cct", N = "cch", d = "ccn", h = "ccu", v = "ccs", w = "cca", k = "ccc", e = {
|
|
4
|
+
r: u,
|
|
5
|
+
k: f,
|
|
6
|
+
w: i,
|
|
7
|
+
t: E,
|
|
8
|
+
h: N,
|
|
9
|
+
n: d,
|
|
10
|
+
u: h,
|
|
11
|
+
s: v,
|
|
12
|
+
a: w,
|
|
13
|
+
c: k
|
|
14
|
+
};
|
|
15
|
+
function p(t) {
|
|
16
|
+
return !(t == null || t === !1 || t === "" || typeof t == "number" && t === 0 || t === "0");
|
|
17
|
+
}
|
|
18
|
+
function g({
|
|
19
|
+
title: t,
|
|
20
|
+
sup: n,
|
|
21
|
+
subtitle: a,
|
|
22
|
+
actions: l,
|
|
23
|
+
sticky: r,
|
|
24
|
+
className: m,
|
|
25
|
+
children: s
|
|
26
|
+
}) {
|
|
27
|
+
return /* @__PURE__ */ c.createElement("div", { className: o(e.r, r && e.k, m) }, /* @__PURE__ */ c.createElement("div", { className: e.w }, /* @__PURE__ */ c.createElement("div", { className: e.t }, /* @__PURE__ */ c.createElement("h1", { className: e.h }, /* @__PURE__ */ c.createElement("span", { className: e.n }, t), p(n) ? /* @__PURE__ */ c.createElement("span", { className: e.u }, n) : null), a != null ? /* @__PURE__ */ c.createElement("p", { className: e.s }, a) : null), l != null ? /* @__PURE__ */ c.createElement("div", { className: e.a }, l) : null), s != null ? /* @__PURE__ */ c.createElement("div", { className: e.c }, s) : null);
|
|
28
|
+
}
|
|
29
|
+
export {
|
|
30
|
+
g as P
|
|
31
|
+
};
|
package/dist/PageHead.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
@layer elcrm-components{.ccr{margin:0 0 var(--shell-gap-
|
|
1
|
+
@layer elcrm-components{.ccr{display:flex;flex-direction:column;gap:var(--shell-gap);margin:0 0 var(--shell-gap)}.cck{position:sticky;top:0;z-index:var(--shell-z);background:var(--shell-bg)}.ccw{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:var(--shell-gap-sm)}.cct{min-width:0;max-width:36rem}.cch{margin:0;display:flex;align-items:flex-start;gap:.4em;font-size:var(--section-title-size);font-weight:var(--shell-font-weight);color:var(--shell-color);line-height:1.15}.ccn{min-width:0}.ccu{display:inline-flex;align-items:center;margin-top:.12em;font-size:.7rem;font-weight:600;line-height:1;color:var(--shell-color-muted)}.ccs{margin:var(--shell-gap-sm) 0 0;font-size:var(--shell-font-size);color:var(--shell-color-muted);line-height:1.45}.cca{display:flex;flex-wrap:wrap;align-items:center;gap:var(--shell-gap-sm)}.ccc{display:flex;flex-direction:column;gap:var(--shell-gap);min-width:0}}
|
package/dist/PageHead.d.ts
CHANGED
|
@@ -8,8 +8,10 @@ import { default as React } from 'react';
|
|
|
8
8
|
*
|
|
9
9
|
* @example
|
|
10
10
|
* ```tsx
|
|
11
|
-
* <PageShell>
|
|
12
|
-
* <PageHead title="
|
|
11
|
+
* <PageShell scroll>
|
|
12
|
+
* <PageHead title="Идеи" sup={<Badge size="s" tone="accent">4</Badge>} sticky>
|
|
13
|
+
* <Menu items={tabs} value={tab} onSelect={setTab} />
|
|
14
|
+
* </PageHead>
|
|
13
15
|
* …
|
|
14
16
|
* </PageShell>
|
|
15
17
|
* ```
|
|
@@ -19,18 +21,38 @@ import { default as React } from 'react';
|
|
|
19
21
|
export type PageHeadProps = {
|
|
20
22
|
/** Заголовок страницы */
|
|
21
23
|
title: React.ReactNode;
|
|
24
|
+
/**
|
|
25
|
+
* Надстрочный слот сразу после title: текст или {@link Badge}.
|
|
26
|
+
* Пусто / `0` / `false` — не рендерим.
|
|
27
|
+
*/
|
|
28
|
+
sup?: React.ReactNode;
|
|
22
29
|
/** Подзаголовок */
|
|
23
30
|
subtitle?: React.ReactNode;
|
|
24
31
|
/** Кнопки / поиск справа в одной строке с заголовком */
|
|
25
32
|
actions?: React.ReactNode;
|
|
33
|
+
/**
|
|
34
|
+
* Прилипает к верху скролла предка (`PageShell` с `scroll`).
|
|
35
|
+
* По умолчанию `false`.
|
|
36
|
+
*/
|
|
37
|
+
sticky?: boolean;
|
|
26
38
|
/** Доп. CSS-класс */
|
|
27
39
|
className?: string;
|
|
28
|
-
/**
|
|
40
|
+
/**
|
|
41
|
+
* Контент под строкой заголовка (фильтры, поиск, вкладки).
|
|
42
|
+
* Между title и children — `--shell-gap`.
|
|
43
|
+
*/
|
|
29
44
|
children?: React.ReactNode;
|
|
30
45
|
};
|
|
31
46
|
/**
|
|
32
|
-
* Заголовок: title
|
|
47
|
+
* Заголовок: title слева (+ `sup` сверху), actions справа.
|
|
33
48
|
*
|
|
34
|
-
* @
|
|
49
|
+
* @param props.title — заголовок
|
|
50
|
+
* @param props.sup — текст или Badge после title (надстрочно)
|
|
51
|
+
* @param props.subtitle — строка под заголовком
|
|
52
|
+
* @param props.actions — кнопки справа
|
|
53
|
+
* @param props.sticky — прилипает к скроллу
|
|
54
|
+
* @param props.children — фильтры / вкладки под шапкой
|
|
55
|
+
*
|
|
56
|
+
* @see PageShell, Section, Header, Badge
|
|
35
57
|
*/
|
|
36
|
-
export declare function PageHead({ title, subtitle, actions, className, children, }: PageHeadProps): React.JSX.Element;
|
|
58
|
+
export declare function PageHead({ title, sup, subtitle, actions, sticky, className, children, }: PageHeadProps): React.JSX.Element;
|
package/dist/PageHead.js
CHANGED
|
@@ -1,28 +1,30 @@
|
|
|
1
1
|
import e from "react";
|
|
2
2
|
import { c as l } from "./cx-CcykAxZN.js";
|
|
3
|
-
import './PageShell.css';const m = "ckr",
|
|
3
|
+
import './PageShell.css';const m = "ckr", f = "ckw", i = "ckb", k = "ckf", u = "cko", c = {
|
|
4
4
|
r: m,
|
|
5
|
-
w:
|
|
6
|
-
b:
|
|
7
|
-
f:
|
|
5
|
+
w: f,
|
|
6
|
+
b: i,
|
|
7
|
+
f: k,
|
|
8
|
+
o: u
|
|
8
9
|
};
|
|
9
|
-
function
|
|
10
|
+
function d({
|
|
10
11
|
children: s,
|
|
11
|
-
className:
|
|
12
|
-
wide:
|
|
12
|
+
className: n,
|
|
13
|
+
wide: o,
|
|
14
|
+
scroll: r = !0,
|
|
13
15
|
footer: t,
|
|
14
|
-
...
|
|
16
|
+
...a
|
|
15
17
|
}) {
|
|
16
18
|
return /* @__PURE__ */ e.createElement(
|
|
17
19
|
"div",
|
|
18
20
|
{
|
|
19
|
-
...
|
|
20
|
-
className: l(c.r,
|
|
21
|
+
...a,
|
|
22
|
+
className: l(c.r, o && c.w, !r && c.o, n)
|
|
21
23
|
},
|
|
22
24
|
/* @__PURE__ */ e.createElement("div", { className: c.b }, s),
|
|
23
25
|
t != null ? /* @__PURE__ */ e.createElement("div", { className: c.f }, t) : null
|
|
24
26
|
);
|
|
25
27
|
}
|
|
26
28
|
export {
|
|
27
|
-
|
|
29
|
+
d as P
|
|
28
30
|
};
|
package/dist/PageShell.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
@layer elcrm-components{.ckr{flex:1 1 auto;min-height:0;height:100%;width:100%;display:flex;flex-direction:column;box-sizing:border-box;padding:var(--shell-padding);overflow:hidden}.ckw{max-width:none}.ckb{flex:1 1 auto;min-height:0;overflow:auto;display:flex;flex-direction:column;gap:var(--shell-gap)}.ckf{flex:0 0 auto;padding-top:var(--shell-gap-sm)}}
|
|
1
|
+
@layer elcrm-components{.ckr{flex:1 1 auto;min-height:0;height:100%;width:100%;display:flex;flex-direction:column;box-sizing:border-box;padding:var(--shell-padding);overflow:hidden}.ckw{max-width:none}.ckb{flex:1 1 auto;min-height:0;overflow:auto;display:flex;flex-direction:column;gap:var(--shell-gap)}.ckf{flex:0 0 auto;padding-top:var(--shell-gap-sm)}.cko{overflow:visible;height:auto}.cko .ckb{overflow:visible;flex:0 1 auto;min-height:auto}}
|
package/dist/PageShell.d.ts
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { default as React } from 'react';
|
|
2
2
|
/**
|
|
3
|
-
* Каркас модуля: скролл в body,
|
|
3
|
+
* Каркас модуля: опциональный скролл в body, footer прибит к низу.
|
|
4
4
|
*
|
|
5
5
|
* Роли: PageShell = внутренний каркас контента в Layout;
|
|
6
6
|
* сверху часто PageHead / Section, снизу — панель действий.
|
|
7
7
|
*
|
|
8
8
|
* @example
|
|
9
9
|
* ```tsx
|
|
10
|
-
* <PageShell wide footer={<Footer><Button>Сохранить</Button></Footer>}>
|
|
11
|
-
* <PageHead title="Редактор" />
|
|
10
|
+
* <PageShell wide scroll footer={<Footer><Button>Сохранить</Button></Footer>}>
|
|
11
|
+
* <PageHead title="Редактор" sticky />
|
|
12
12
|
* …
|
|
13
13
|
* </PageShell>
|
|
14
14
|
* ```
|
|
@@ -16,18 +16,23 @@ import { default as React } from 'react';
|
|
|
16
16
|
* Токены: `--shell-*`.
|
|
17
17
|
*/
|
|
18
18
|
export type PageShellProps = {
|
|
19
|
-
/** Контент модуля
|
|
19
|
+
/** Контент модуля */
|
|
20
20
|
children: React.ReactNode;
|
|
21
21
|
/** Доп. CSS-класс */
|
|
22
22
|
className?: string;
|
|
23
23
|
/** Шире контент (редакторы, таблицы) */
|
|
24
24
|
wide?: boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Скролл внутри body. По умолчанию `true`.
|
|
27
|
+
* `false` — шелл растёт с контентом, крутит предок.
|
|
28
|
+
*/
|
|
29
|
+
scroll?: boolean;
|
|
25
30
|
/** Нижняя панель вне скролла */
|
|
26
31
|
footer?: React.ReactNode;
|
|
27
32
|
} & Omit<React.HTMLAttributes<HTMLDivElement>, "children" | "className">;
|
|
28
33
|
/**
|
|
29
|
-
* Каркас модуля: скролл в body, footer прибит к низу.
|
|
34
|
+
* Каркас модуля: скролл в body (если `scroll`), footer прибит к низу.
|
|
30
35
|
*
|
|
31
36
|
* @see PageHead, Layout, Section, Footer
|
|
32
37
|
*/
|
|
33
|
-
export declare function PageShell({ children, className, wide, footer, ...rootProps }: PageShellProps): React.JSX.Element;
|
|
38
|
+
export declare function PageShell({ children, className, wide, scroll, footer, ...rootProps }: PageShellProps): React.JSX.Element;
|
package/dist/PageShell.js
CHANGED