@elcrm/components 0.1.1 → 0.1.2
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 +66 -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 +9 -1
- package/dist/Avatar.js +3 -2
- package/dist/{AvatarGroup-BAWas4pU.js → AvatarGroup-D1gnT3Od.js} +1 -1
- package/dist/AvatarGroup.js +1 -1
- package/dist/AvatarName-C1sIDPH-.js +66 -0
- package/dist/AvatarName.css +1 -1
- package/dist/AvatarName.d.ts +4 -1
- 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 +32 -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/{Column-DDaqX-A7.js → Column-BiogBDf8.js} +1 -1
- package/dist/Column.js +1 -1
- package/dist/Dropdown-CQBMF9aR.js +151 -0
- package/dist/Dropdown.css +1 -1
- package/dist/Dropdown.d.ts +3 -3
- package/dist/Dropdown.js +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 +61 -0
- package/dist/ItemColumn.js +4 -0
- package/dist/Layout-BQwEaeO0.js +22 -0
- package/dist/Layout.css +1 -1
- package/dist/Layout.d.ts +10 -5
- package/dist/Layout.js +1 -1
- package/dist/Menu-DpUvOl8Y.js +58 -0
- package/dist/Menu.css +1 -1
- package/dist/Menu.d.ts +15 -3
- package/dist/Menu.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-g2xTGubK.js +123 -0
- package/dist/Popover.css +1 -0
- package/dist/Popover.d.ts +54 -0
- package/dist/Popover.js +4 -0
- package/dist/{Row--HIe6vb9.js → Row-DsQOVn18.js} +1 -1
- package/dist/Row.js +1 -1
- package/dist/Sidebar-DeqxYgxn.js +69 -0
- package/dist/Sidebar.css +1 -0
- package/dist/Sidebar.d.ts +83 -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-DL7DufKU.js → TabSections-Bf_sZo7b.js} +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 +35 -0
- package/dist/TextGroup.js +4 -0
- package/dist/dark.css +10 -0
- package/dist/index.css +22 -10
- package/dist/index.d.ts +17 -3
- package/dist/index.es.d.ts +73 -0
- package/dist/index.es.js +76 -59
- package/dist/light.css +10 -0
- package/dist/overlayZ.d.ts +9 -0
- package/dist/tokens.css +19 -0
- package/package.json +2 -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/Menu-DRBHvSdJ.js +0 -40
- package/dist/PageHead-Baz9BLuA.js +0 -22
- package/dist/Stack-b0-XWwQ1.js +0 -31
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
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import w, { useRef as h, useId as Q, useState as x, useLayoutEffect as S, useEffect as W } from "react";
|
|
2
|
+
import { createPortal as V } from "react-dom";
|
|
3
|
+
import { c as H } from "./cx-CcykAxZN.js";
|
|
4
|
+
import './Popover.css';const N = 1e3, X = 10;
|
|
5
|
+
function E() {
|
|
6
|
+
const e = globalThis;
|
|
7
|
+
return e.elcrm || (e.elcrm = {}), e.elcrm.overlayZ || (e.elcrm.overlayZ = { seq: 0, active: /* @__PURE__ */ new Set() }), e.elcrm.overlayZ;
|
|
8
|
+
}
|
|
9
|
+
function Y() {
|
|
10
|
+
const e = E();
|
|
11
|
+
e.seq += 1;
|
|
12
|
+
const r = N + e.seq * X;
|
|
13
|
+
return e.active.add(r), r;
|
|
14
|
+
}
|
|
15
|
+
function B(e) {
|
|
16
|
+
const r = E();
|
|
17
|
+
r.active.delete(e), r.active.size === 0 && (r.seq = 0);
|
|
18
|
+
}
|
|
19
|
+
function oe() {
|
|
20
|
+
const e = E();
|
|
21
|
+
return e.active.size === 0 ? N : Math.max(...e.active);
|
|
22
|
+
}
|
|
23
|
+
const _ = "c3r", $ = "c3t", C = "c3p", y = {
|
|
24
|
+
r: _,
|
|
25
|
+
t: $,
|
|
26
|
+
p: C
|
|
27
|
+
};
|
|
28
|
+
function re({
|
|
29
|
+
trigger: e,
|
|
30
|
+
children: r,
|
|
31
|
+
open: L,
|
|
32
|
+
defaultOpen: D = !1,
|
|
33
|
+
onOpenChange: m,
|
|
34
|
+
align: M = "end",
|
|
35
|
+
disabled: g = !1,
|
|
36
|
+
label: O,
|
|
37
|
+
role: T = "menu",
|
|
38
|
+
className: A,
|
|
39
|
+
panelClassName: F
|
|
40
|
+
}) {
|
|
41
|
+
const f = h(null), z = h(null), R = Q(), [K, U] = x(D), Z = L !== void 0, n = Z ? L : K, [c, I] = x(null), [i, P] = x(null), p = h(null);
|
|
42
|
+
p.current = i;
|
|
43
|
+
const v = (t) => {
|
|
44
|
+
g && t || (Z || U(t), m == null || m(t));
|
|
45
|
+
};
|
|
46
|
+
S(() => {
|
|
47
|
+
if (n) {
|
|
48
|
+
i == null && P(Y());
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
i != null && (B(i), P(null));
|
|
52
|
+
}, [n, i]), W(() => () => {
|
|
53
|
+
p.current != null && B(p.current);
|
|
54
|
+
}, []);
|
|
55
|
+
const b = () => {
|
|
56
|
+
const t = f.current;
|
|
57
|
+
if (!t) return;
|
|
58
|
+
const o = t.getBoundingClientRect(), s = 8, a = window.innerHeight - o.bottom - s - 8, l = o.top - s - 8, u = a >= 160 || a >= l, q = Math.min(420, Math.max(120, u ? a : l)), d = Math.max(200, o.width), G = u ? o.bottom + s : Math.max(8, o.top - s - q), J = M === "end" ? Math.max(8, Math.min(o.right - d, window.innerWidth - d - 8)) : Math.max(8, Math.min(o.left, window.innerWidth - d - 8));
|
|
59
|
+
I({ top: G, left: J, minWidth: d, maxHeight: q });
|
|
60
|
+
};
|
|
61
|
+
S(() => {
|
|
62
|
+
if (!n) {
|
|
63
|
+
I(null);
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
b();
|
|
67
|
+
const t = () => b();
|
|
68
|
+
return window.addEventListener("resize", t), window.addEventListener("scroll", t, !0), () => {
|
|
69
|
+
window.removeEventListener("resize", t), window.removeEventListener("scroll", t, !0);
|
|
70
|
+
};
|
|
71
|
+
}, [n, M]), W(() => {
|
|
72
|
+
if (!n) return;
|
|
73
|
+
const t = (s) => {
|
|
74
|
+
var l, u;
|
|
75
|
+
const a = s.target;
|
|
76
|
+
(l = f.current) != null && l.contains(a) || (u = z.current) != null && u.contains(a) || v(!1);
|
|
77
|
+
}, o = (s) => {
|
|
78
|
+
s.key === "Escape" && v(!1);
|
|
79
|
+
};
|
|
80
|
+
return document.addEventListener("mousedown", t), document.addEventListener("keydown", o), () => {
|
|
81
|
+
document.removeEventListener("mousedown", t), document.removeEventListener("keydown", o);
|
|
82
|
+
};
|
|
83
|
+
}, [n]);
|
|
84
|
+
const j = c ? {
|
|
85
|
+
position: "fixed",
|
|
86
|
+
top: c.top,
|
|
87
|
+
left: c.left,
|
|
88
|
+
minWidth: c.minWidth,
|
|
89
|
+
maxHeight: c.maxHeight,
|
|
90
|
+
zIndex: i ?? 1e3
|
|
91
|
+
} : void 0, k = n && c ? /* @__PURE__ */ w.createElement(
|
|
92
|
+
"div",
|
|
93
|
+
{
|
|
94
|
+
ref: z,
|
|
95
|
+
id: R,
|
|
96
|
+
role: T,
|
|
97
|
+
"aria-label": O,
|
|
98
|
+
className: H(y.p, F),
|
|
99
|
+
style: j,
|
|
100
|
+
onMouseDown: (t) => t.stopPropagation()
|
|
101
|
+
},
|
|
102
|
+
r
|
|
103
|
+
) : null;
|
|
104
|
+
return /* @__PURE__ */ w.createElement("div", { ref: f, className: H(y.r, A) }, /* @__PURE__ */ w.createElement(
|
|
105
|
+
"div",
|
|
106
|
+
{
|
|
107
|
+
className: y.t,
|
|
108
|
+
"aria-haspopup": "menu",
|
|
109
|
+
"aria-expanded": n,
|
|
110
|
+
"aria-controls": n ? R : void 0,
|
|
111
|
+
onClick: () => {
|
|
112
|
+
g || v(!n);
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
e
|
|
116
|
+
), k && typeof document < "u" ? V(k, document.body) : null);
|
|
117
|
+
}
|
|
118
|
+
export {
|
|
119
|
+
re as P,
|
|
120
|
+
Y as a,
|
|
121
|
+
oe as p,
|
|
122
|
+
B as r
|
|
123
|
+
};
|
package/dist/Popover.css
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@layer elcrm-components{.c3r{position:relative;display:inline-flex;vertical-align:middle}.c3t{display:inline-flex;align-items:center;min-width:0}.c3p{box-sizing:border-box;overflow:auto;padding:var(--shell-gap-sm);background:var(--shell-background);border:1px solid var(--shell-border);border-radius:var(--shell-radius);box-shadow:var(--popup-shadow);color:var(--shell-color);min-width:var(--dropdown-min-width, 200px);max-width:var(--dropdown-max-width, min(360px, calc(100vw - 16px) ));max-height:var(--dropdown-max-height, 420px)}}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Портал у якоря: Escape, клик снаружи, z-index (`globalThis.elcrm.overlayZ`).
|
|
4
|
+
*
|
|
5
|
+
* Роли: Popover = свой попап (слот `children`).
|
|
6
|
+
* Типовое меню пунктов — {@link Dropdown}.
|
|
7
|
+
* Инлайн-навигация — {@link Menu} (не путать).
|
|
8
|
+
*
|
|
9
|
+
* Бывший `@elcrm/overlay` `Menu` — этот компонент (`Popover`).
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```tsx
|
|
13
|
+
* <Popover
|
|
14
|
+
* trigger={<Button>Ещё</Button>}
|
|
15
|
+
* label="Действия"
|
|
16
|
+
* align="end"
|
|
17
|
+
* >
|
|
18
|
+
* <List>
|
|
19
|
+
* <Item as="button">Скачать</Item>
|
|
20
|
+
* </List>
|
|
21
|
+
* </Popover>
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* Токены: `--shell-*`, `--popup-shadow`, `--dropdown-min-width`.
|
|
25
|
+
*/
|
|
26
|
+
export type PopoverProps = {
|
|
27
|
+
/** Якорь (кнопка / иконка) */
|
|
28
|
+
trigger: React.ReactNode;
|
|
29
|
+
/** Содержимое панели */
|
|
30
|
+
children?: React.ReactNode;
|
|
31
|
+
/** Контролируемое открытие */
|
|
32
|
+
open?: boolean;
|
|
33
|
+
/** Начальное открытие */
|
|
34
|
+
defaultOpen?: boolean;
|
|
35
|
+
/** Смена open */
|
|
36
|
+
onOpenChange?: (open: boolean) => void;
|
|
37
|
+
/** Выравнивание панели */
|
|
38
|
+
align?: "start" | "end";
|
|
39
|
+
/** Не открывать по клику на якорь */
|
|
40
|
+
disabled?: boolean;
|
|
41
|
+
/** aria-label панели */
|
|
42
|
+
label?: string;
|
|
43
|
+
/** role панели */
|
|
44
|
+
role?: React.AriaRole;
|
|
45
|
+
className?: string;
|
|
46
|
+
/** Класс панели (portal) */
|
|
47
|
+
panelClassName?: string;
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* Панель в portal рядом с триггером.
|
|
51
|
+
*
|
|
52
|
+
* @see Dropdown, Menu
|
|
53
|
+
*/
|
|
54
|
+
export declare function Popover({ trigger, children, open: openProp, defaultOpen, onOpenChange, align, disabled, label, role, className, panelClassName, }: PopoverProps): React.JSX.Element;
|
package/dist/Popover.js
ADDED
package/dist/Row.js
CHANGED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import l from "react";
|
|
2
|
+
import { B as h } from "./Badge-jp-9iNNL.js";
|
|
3
|
+
import { I as x } from "./Item-D4okhsfW.js";
|
|
4
|
+
import { c as u } from "./cx-CcykAxZN.js";
|
|
5
|
+
import './Sidebar.css';const k = "c2r", g = "c2b", y = "c2x", B = "c2g", I = "c2s", w = "c2p", z = "c2h", C = "c2n", R = "c2i", T = "c2a", $ = "c2o", j = "c2l", q = "c2d", A = "c2f", D = "c2v", e = {
|
|
6
|
+
r: k,
|
|
7
|
+
b: g,
|
|
8
|
+
x: y,
|
|
9
|
+
g: B,
|
|
10
|
+
s: I,
|
|
11
|
+
p: w,
|
|
12
|
+
h: z,
|
|
13
|
+
n: C,
|
|
14
|
+
i: R,
|
|
15
|
+
a: T,
|
|
16
|
+
o: $,
|
|
17
|
+
l: j,
|
|
18
|
+
d: q,
|
|
19
|
+
f: A,
|
|
20
|
+
v: D
|
|
21
|
+
};
|
|
22
|
+
function F(n) {
|
|
23
|
+
if (n == null || n === "") return null;
|
|
24
|
+
const c = Number(n);
|
|
25
|
+
return !Number.isNaN(c) && c === 0 ? null : !Number.isNaN(c) && c > 99 ? "99+" : String(n);
|
|
26
|
+
}
|
|
27
|
+
function L({
|
|
28
|
+
groups: n,
|
|
29
|
+
items: c,
|
|
30
|
+
value: v,
|
|
31
|
+
onSelect: s,
|
|
32
|
+
variant: E = "cards",
|
|
33
|
+
brand: o,
|
|
34
|
+
extra: r,
|
|
35
|
+
footer: N,
|
|
36
|
+
version: m,
|
|
37
|
+
className: f,
|
|
38
|
+
"aria-label": b = "Основное меню"
|
|
39
|
+
}) {
|
|
40
|
+
const p = n ?? c ?? [];
|
|
41
|
+
return /* @__PURE__ */ l.createElement(
|
|
42
|
+
"aside",
|
|
43
|
+
{
|
|
44
|
+
className: u(e.r, E === "plain" && e.p, f),
|
|
45
|
+
"aria-label": b
|
|
46
|
+
},
|
|
47
|
+
o != null || r != null ? /* @__PURE__ */ l.createElement("div", { className: e.b }, o, r != null ? /* @__PURE__ */ l.createElement("div", { className: e.x }, r) : null) : null,
|
|
48
|
+
/* @__PURE__ */ l.createElement("div", { className: e.g }, p.map((t) => /* @__PURE__ */ l.createElement("nav", { key: t.value, className: e.s, "aria-label": t.title ?? "Навигация" }, t.title ? /* @__PURE__ */ l.createElement("div", { className: e.h }, t.title) : null, /* @__PURE__ */ l.createElement("ul", { className: e.n }, (t.items ?? []).map((a) => {
|
|
49
|
+
const d = F(a.badge), i = v === a.value;
|
|
50
|
+
return /* @__PURE__ */ l.createElement("li", { key: a.value }, /* @__PURE__ */ l.createElement(
|
|
51
|
+
x,
|
|
52
|
+
{
|
|
53
|
+
as: "button",
|
|
54
|
+
active: i,
|
|
55
|
+
className: u(e.i, i && e.a),
|
|
56
|
+
"aria-current": i ? "page" : void 0,
|
|
57
|
+
onClick: () => s == null ? void 0 : s(a.value)
|
|
58
|
+
},
|
|
59
|
+
a.icon != null ? /* @__PURE__ */ l.createElement("span", { className: e.o, "aria-hidden": !0 }, a.icon) : null,
|
|
60
|
+
/* @__PURE__ */ l.createElement("span", { className: e.l }, a.label),
|
|
61
|
+
d != null ? /* @__PURE__ */ l.createElement(h, { className: e.d, tone: "accent", size: "s" }, d) : null
|
|
62
|
+
));
|
|
63
|
+
}))))),
|
|
64
|
+
N != null || m != null ? /* @__PURE__ */ l.createElement("div", { className: u(e.s, e.f) }, N, m != null ? /* @__PURE__ */ l.createElement("div", { className: e.v }, m) : null) : null
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
export {
|
|
68
|
+
L as S
|
|
69
|
+
};
|
package/dist/Sidebar.css
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@layer elcrm-components{.c2r{box-sizing:border-box;display:flex;flex-direction:column;flex:0 0 var(--sidebar-width);width:var(--sidebar-width);min-height:100svh;max-height:100svh;padding:var(--sidebar-pad-y) var(--sidebar-pad-x);gap:var(--shell-gap-sm);color:var(--shell-color);position:sticky;top:0;align-self:flex-start}.c2b{display:flex;flex-direction:row;align-items:center;gap:var(--shell-gap);padding:4px 8px;min-width:0}.c2x{flex-shrink:0;margin-left:auto}.c2g{flex:1;min-height:0;display:flex;flex-direction:column;gap:var(--shell-gap-sm);overflow-y:auto;overflow-x:hidden;scrollbar-width:thin}.c2s{box-sizing:border-box;flex-shrink:0;padding:8px}.c2p{--sidebar-plain: 1}.c2r:not(.c2p) .c2s{background:var(--sidebar-block-bg, var(--shell-background));border:1px solid var(--sidebar-block-border, var(--shell-border));border-radius:var(--sidebar-block-radius, var(--shell-radius));box-shadow:var(--sidebar-block-shadow, none)}.c2h{margin:2px 10px 6px;font-size:var(--sidebar-group-font-size, 11px);font-weight:600;letter-spacing:.08em;text-transform:uppercase;color:var(--shell-color-muted)}.c2n{margin:0;padding:0;list-style:none}.c2n>li{list-style:none}.c2n .c2i:is(button){position:relative;display:flex;width:100%;box-sizing:border-box;flex-direction:row;align-items:center;gap:8px;margin:0 0 1px;padding:var(--sidebar-item-padding, 6px 10px);border:0;border-radius:8px;background:transparent;color:var(--shell-color-muted);font-family:inherit;font-size:var(--sidebar-item-font-size, 13px);font-weight:500;line-height:1.25;letter-spacing:0;text-align:left;cursor:pointer}.c2n .c2i:is(button):hover{color:var(--shell-color);background:var(--shell-background-hover)}.c2n .c2i:is(button).c2a,.c2n .c2i:is(button)[aria-current=page],.c2n .c2i:is(button)[data-active=true],.c2n .c2i:is(button).c2a:hover{color:var(--sidebar-item-active, var(--shell-color));background:var(--sidebar-item-active-bg, var(--shell-background-selected))}.c2o{display:inline-flex;flex-shrink:0;align-items:center;justify-content:center;width:var(--sidebar-icon-size, 16px);height:var(--sidebar-icon-size, 16px);color:inherit}.c2o :is(svg){display:block;width:var(--sidebar-icon-size, 16px);height:var(--sidebar-icon-size, 16px)}.c2a .c2o{color:var(--sidebar-icon-active, var(--shell-color-accent))}.c2l{flex:1;min-width:0}.c2d{flex-shrink:0;min-width:16px;height:16px;padding:0 4px;font-size:10px}.c2f{margin-top:auto}.c2v{margin-top:var(--shell-gap-sm);font-size:11px;color:var(--shell-color-muted);text-align:center}@media (max-width: 900px){.c2r{flex:0 0 72px;width:72px;padding:12px 8px}.c2l,.c2h,.c2v{display:none}.c2b{flex-direction:column;justify-content:center;align-items:center;gap:8px;padding:4px 0}.c2x{margin-left:0}.c2s{padding:6px}.c2n .c2i{justify-content:center;align-items:center;gap:0;width:100%;min-height:40px;padding:10px 0}.c2n .c2d{position:absolute;top:4px;right:4px;min-width:14px;height:14px;padding:0 4px;font-size:.625rem;line-height:14px;pointer-events:none}}}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
/** Вид колонки: карточки (консоль) или плоский список (backoffice) */
|
|
3
|
+
export type SidebarVariant = "cards" | "plain";
|
|
4
|
+
/** Пункт бокового меню. Идентификатор — `value`. */
|
|
5
|
+
export type SidebarItem = {
|
|
6
|
+
value: string;
|
|
7
|
+
/** Подпись */
|
|
8
|
+
label: string;
|
|
9
|
+
/** Иконка (слот приложения) */
|
|
10
|
+
icon?: React.ReactNode;
|
|
11
|
+
/** Счётчик справа */
|
|
12
|
+
badge?: number | string | null;
|
|
13
|
+
};
|
|
14
|
+
/** Группа пунктов. `title` — «Аккаунт» / «Админ». */
|
|
15
|
+
export type SidebarGroup = {
|
|
16
|
+
value: string;
|
|
17
|
+
title?: string;
|
|
18
|
+
items: SidebarItem[];
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Левая колонка приложения: бренд, группы меню, футер.
|
|
22
|
+
*
|
|
23
|
+
* Роли: Sidebar = навигация приложения; не путать с NavSections
|
|
24
|
+
* (сайдбар внутри страницы + lazy-панель).
|
|
25
|
+
*
|
|
26
|
+
* `variant="cards"` — секции-карточки (elWMS Console).
|
|
27
|
+
* `variant="plain"` — плоский список и заголовок группы (backoffice).
|
|
28
|
+
*
|
|
29
|
+
* Иконки, колокольчик, тема, выход — слоты приложения
|
|
30
|
+
* (`brand`, `extra`, `footer`). Роутер не подключаем.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```tsx
|
|
34
|
+
* <Sidebar
|
|
35
|
+
* variant="cards"
|
|
36
|
+
* value={page}
|
|
37
|
+
* onSelect={setPage}
|
|
38
|
+
* brand={<Brand as="strong">App</Brand>}
|
|
39
|
+
* extra={<Notifications.Bell />}
|
|
40
|
+
* groups={[
|
|
41
|
+
* { value: "main", items: [{ value: "home", label: "Обзор", icon: <Icon /> }] },
|
|
42
|
+
* { value: "admin", title: "Админ", items: [{ value: "users", label: "Люди" }] },
|
|
43
|
+
* ]}
|
|
44
|
+
* footer={<AvatarName title="Паша" description="mail@…" />}
|
|
45
|
+
* version="v 0.2.26"
|
|
46
|
+
* />
|
|
47
|
+
* ```
|
|
48
|
+
*
|
|
49
|
+
* Токены: `--sidebar-*`, цвета — `--shell-*`.
|
|
50
|
+
*/
|
|
51
|
+
export type SidebarProps = {
|
|
52
|
+
/** Группы пунктов (`value` + `items`) */
|
|
53
|
+
groups?: SidebarGroup[];
|
|
54
|
+
/** То же, что `groups` (совместимость) */
|
|
55
|
+
items?: SidebarGroup[];
|
|
56
|
+
/** Текущий пункт */
|
|
57
|
+
value?: string;
|
|
58
|
+
/** Выбор пункта */
|
|
59
|
+
onSelect?: (value: string) => void;
|
|
60
|
+
/**
|
|
61
|
+
* `cards` — блоки-карточки.
|
|
62
|
+
* `plain` — плоский список.
|
|
63
|
+
* @default "cards"
|
|
64
|
+
*/
|
|
65
|
+
variant?: SidebarVariant;
|
|
66
|
+
/** Логотип / название */
|
|
67
|
+
brand?: React.ReactNode;
|
|
68
|
+
/** Справа от бренда (колокольчик) */
|
|
69
|
+
extra?: React.ReactNode;
|
|
70
|
+
/** Низ: тема, выход или карточка пользователя */
|
|
71
|
+
footer?: React.ReactNode;
|
|
72
|
+
/** Версия под футером */
|
|
73
|
+
version?: React.ReactNode;
|
|
74
|
+
/** Подпись колонки */
|
|
75
|
+
"aria-label"?: string;
|
|
76
|
+
className?: string;
|
|
77
|
+
};
|
|
78
|
+
/**
|
|
79
|
+
* Левая навигация приложения.
|
|
80
|
+
*
|
|
81
|
+
* @see Layout, Brand, Item, Badge, NavSections
|
|
82
|
+
*/
|
|
83
|
+
export declare function Sidebar({ groups, items, value, onSelect, variant, brand, extra, footer, version, className, "aria-label": ariaLabel, }: SidebarProps): React.JSX.Element;
|
package/dist/Sidebar.js
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import m from "react";
|
|
2
|
+
import { c as f } from "./cx-CcykAxZN.js";
|
|
3
|
+
import './Stack.css';function l(t) {
|
|
4
|
+
if (t != null)
|
|
5
|
+
return { gap: typeof t == "number" ? `${t}px` : t };
|
|
6
|
+
}
|
|
7
|
+
const i = "c1r", p = "c1c", g = "c1g", h = "c1h", v = "c1n", r = {
|
|
8
|
+
r: i,
|
|
9
|
+
c: p,
|
|
10
|
+
g,
|
|
11
|
+
h,
|
|
12
|
+
n: v
|
|
13
|
+
};
|
|
14
|
+
function x(t) {
|
|
15
|
+
if (typeof t == "number")
|
|
16
|
+
return t <= 0 ? void 0 : `repeat(${t}, minmax(0, 1fr))`;
|
|
17
|
+
if (t.length !== 0)
|
|
18
|
+
return t.map((n) => typeof n == "number" ? `${n}px` : n).join(" ");
|
|
19
|
+
}
|
|
20
|
+
function k({
|
|
21
|
+
direction: t = "column",
|
|
22
|
+
columns: n,
|
|
23
|
+
gap: c,
|
|
24
|
+
children: o,
|
|
25
|
+
className: a,
|
|
26
|
+
style: s,
|
|
27
|
+
...u
|
|
28
|
+
}) {
|
|
29
|
+
const e = t === "grid" && n != null ? x(n) : void 0;
|
|
30
|
+
return /* @__PURE__ */ m.createElement(
|
|
31
|
+
"div",
|
|
32
|
+
{
|
|
33
|
+
className: f(
|
|
34
|
+
r.r,
|
|
35
|
+
t === "column" && r.c,
|
|
36
|
+
t === "row" && r.h,
|
|
37
|
+
t === "grid" && (e ? r.n : r.g),
|
|
38
|
+
a
|
|
39
|
+
),
|
|
40
|
+
style: {
|
|
41
|
+
...l(c),
|
|
42
|
+
...e ? { "--stack-columns-template": e } : null,
|
|
43
|
+
...s
|
|
44
|
+
},
|
|
45
|
+
...u
|
|
46
|
+
},
|
|
47
|
+
o
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
export {
|
|
51
|
+
k as S,
|
|
52
|
+
x as s
|
|
53
|
+
};
|
package/dist/Stack.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
@layer elcrm-components{.c1r{
|
|
1
|
+
@layer elcrm-components{.c1r{box-sizing:border-box;min-width:0;gap:var(--shell-gap)}.c1c,.c1g{width:100%}.c1c{display:flex;flex-direction:column}.c1h{display:flex;flex-direction:row;flex-wrap:wrap;align-items:center;width:auto;max-width:100%}.c1g{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,var(--stack-grid-min)),1fr))}.c1n{display:grid;width:100%;align-items:stretch;grid-template-columns:var(--stack-columns-template)}}
|
package/dist/Stack.d.ts
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { default as React } from 'react';
|
|
2
2
|
/** Направление раскладки стека */
|
|
3
|
-
export type StackDirection = "row" | "column";
|
|
3
|
+
export type StackDirection = "row" | "column" | "grid";
|
|
4
|
+
/** Сетка: число равных колонок или треки (`1fr`, `100px`, …). Число в массиве — px. */
|
|
5
|
+
export type StackColumns = number | Array<number | string>;
|
|
6
|
+
/** CSS `grid-template-columns` из пропа `columns`. */
|
|
7
|
+
export declare function stackColumnsTemplate(columns: StackColumns): string | undefined;
|
|
4
8
|
/**
|
|
5
9
|
* Универсальный стек (ряд / колонка) с отступами между детьми.
|
|
6
10
|
*
|
|
@@ -13,13 +17,21 @@ export type StackDirection = "row" | "column";
|
|
|
13
17
|
* <Button>Отмена</Button>
|
|
14
18
|
* <Button>Сохранить</Button>
|
|
15
19
|
* </Stack>
|
|
20
|
+
* <Stack direction="grid" columns={["1fr", "100px", "100px"]} gap={12} />
|
|
16
21
|
* ```
|
|
17
22
|
*
|
|
18
|
-
* Токены: `--shell-gap` (если `gap` не задан);
|
|
23
|
+
* Токены: `--shell-gap` (если `gap` не задан); сетка — `--stack-grid-min`.
|
|
24
|
+
* `columns` — число равных колонок или массив треков (`--stack-columns-template`).
|
|
25
|
+
* Явные колонки: `align-items: stretch` (несколько рядов). Центр в одном ряду — `style={{ alignItems: "center" }}`.
|
|
19
26
|
*/
|
|
20
27
|
export type StackProps = React.HTMLAttributes<HTMLDivElement> & {
|
|
21
|
-
/** Направление: по умолчанию `column` */
|
|
28
|
+
/** Направление: по умолчанию `column`. `grid` — сетка */
|
|
22
29
|
direction?: StackDirection;
|
|
30
|
+
/**
|
|
31
|
+
* Сетка: `4` — четыре равные колонки;
|
|
32
|
+
* `["1fr", "100px", "auto"]` — свои треки (число в массиве = px).
|
|
33
|
+
*/
|
|
34
|
+
columns?: StackColumns;
|
|
23
35
|
/** Отступ между детьми: число (px) или CSS-строка */
|
|
24
36
|
gap?: number | string;
|
|
25
37
|
/** Дочерние элементы стека */
|
|
@@ -31,4 +43,4 @@ export type StackProps = React.HTMLAttributes<HTMLDivElement> & {
|
|
|
31
43
|
*
|
|
32
44
|
* @see Block, Row, Column
|
|
33
45
|
*/
|
|
34
|
-
export declare function Stack({ direction, gap, children, className, style, ...rest }: StackProps): React.JSX.Element;
|
|
46
|
+
export declare function Stack({ direction, columns, gap, children, className, style, ...rest }: StackProps): React.JSX.Element;
|
package/dist/Stack.js
CHANGED