@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.
Files changed (94) hide show
  1. package/README.md +66 -16
  2. package/dist/ActionGroup-ChKFW0mt.js +27 -0
  3. package/dist/ActionGroup.css +1 -0
  4. package/dist/ActionGroup.d.ts +42 -0
  5. package/dist/ActionGroup.js +4 -0
  6. package/dist/Avatar-loGgFt72.js +113 -0
  7. package/dist/Avatar.d.ts +9 -1
  8. package/dist/Avatar.js +3 -2
  9. package/dist/{AvatarGroup-BAWas4pU.js → AvatarGroup-D1gnT3Od.js} +1 -1
  10. package/dist/AvatarGroup.js +1 -1
  11. package/dist/AvatarName-C1sIDPH-.js +66 -0
  12. package/dist/AvatarName.css +1 -1
  13. package/dist/AvatarName.d.ts +4 -1
  14. package/dist/AvatarName.js +1 -1
  15. package/dist/Badge-jp-9iNNL.js +28 -0
  16. package/dist/Badge.css +1 -1
  17. package/dist/Badge.d.ts +32 -17
  18. package/dist/Badge.js +1 -1
  19. package/dist/{Block-BAXh0PPp.js → Block-Bu7NEA0g.js} +1 -1
  20. package/dist/Block.js +1 -1
  21. package/dist/Card.css +1 -1
  22. package/dist/Card.d.ts +8 -1
  23. package/dist/{Column-DDaqX-A7.js → Column-BiogBDf8.js} +1 -1
  24. package/dist/Column.js +1 -1
  25. package/dist/Dropdown-CQBMF9aR.js +151 -0
  26. package/dist/Dropdown.css +1 -1
  27. package/dist/Dropdown.d.ts +3 -3
  28. package/dist/Dropdown.js +1 -1
  29. package/dist/Item-D4okhsfW.js +46 -0
  30. package/dist/Item.css +1 -1
  31. package/dist/Item.d.ts +8 -1
  32. package/dist/Item.js +1 -1
  33. package/dist/ItemColumn-M7a9L8CI.js +41 -0
  34. package/dist/ItemColumn.css +1 -0
  35. package/dist/ItemColumn.d.ts +61 -0
  36. package/dist/ItemColumn.js +4 -0
  37. package/dist/Layout-BQwEaeO0.js +22 -0
  38. package/dist/Layout.css +1 -1
  39. package/dist/Layout.d.ts +10 -5
  40. package/dist/Layout.js +1 -1
  41. package/dist/Menu-DpUvOl8Y.js +58 -0
  42. package/dist/Menu.css +1 -1
  43. package/dist/Menu.d.ts +15 -3
  44. package/dist/Menu.js +1 -1
  45. package/dist/PageHead-DgaJ1mXY.js +31 -0
  46. package/dist/PageHead.css +1 -1
  47. package/dist/PageHead.d.ts +28 -6
  48. package/dist/PageHead.js +1 -1
  49. package/dist/{PageShell-CghThHS3.js → PageShell-D9EZiO8o.js} +13 -11
  50. package/dist/PageShell.css +1 -1
  51. package/dist/PageShell.d.ts +11 -6
  52. package/dist/PageShell.js +1 -1
  53. package/dist/Popover-g2xTGubK.js +123 -0
  54. package/dist/Popover.css +1 -0
  55. package/dist/Popover.d.ts +54 -0
  56. package/dist/Popover.js +4 -0
  57. package/dist/{Row--HIe6vb9.js → Row-DsQOVn18.js} +1 -1
  58. package/dist/Row.js +1 -1
  59. package/dist/Sidebar-DeqxYgxn.js +69 -0
  60. package/dist/Sidebar.css +1 -0
  61. package/dist/Sidebar.d.ts +83 -0
  62. package/dist/Sidebar.js +4 -0
  63. package/dist/Stack-XkmPSswj.js +53 -0
  64. package/dist/Stack.css +1 -1
  65. package/dist/Stack.d.ts +16 -4
  66. package/dist/Stack.js +3 -2
  67. package/dist/Stat-C5iZyEoo.js +27 -0
  68. package/dist/Stat.css +1 -0
  69. package/dist/Stat.d.ts +39 -0
  70. package/dist/Stat.js +4 -0
  71. package/dist/{TabSections-DL7DufKU.js → TabSections-Bf_sZo7b.js} +1 -1
  72. package/dist/TabSections.js +1 -1
  73. package/dist/TextGroup-DmhuyMR1.js +23 -0
  74. package/dist/TextGroup.css +1 -0
  75. package/dist/TextGroup.d.ts +35 -0
  76. package/dist/TextGroup.js +4 -0
  77. package/dist/dark.css +10 -0
  78. package/dist/index.css +22 -10
  79. package/dist/index.d.ts +17 -3
  80. package/dist/index.es.d.ts +73 -0
  81. package/dist/index.es.js +76 -59
  82. package/dist/light.css +10 -0
  83. package/dist/overlayZ.d.ts +9 -0
  84. package/dist/tokens.css +19 -0
  85. package/package.json +2 -2
  86. package/dist/Avatar-CyNXYvsa.js +0 -101
  87. package/dist/AvatarName-DhD3TytF.js +0 -56
  88. package/dist/Badge-l6nUkl-H.js +0 -22
  89. package/dist/Dropdown-DQlDiWCR.js +0 -168
  90. package/dist/Item-CaU4RW2G.js +0 -38
  91. package/dist/Layout-Xb3-xsmA.js +0 -18
  92. package/dist/Menu-DRBHvSdJ.js +0 -40
  93. package/dist/PageHead-Baz9BLuA.js +0 -22
  94. package/dist/Stack-b0-XWwQ1.js +0 -31
@@ -1,5 +1,5 @@
1
1
  import o from "react";
2
- import { S as r } from "./Stack-b0-XWwQ1.js";
2
+ import { S as r } from "./Stack-XkmPSswj.js";
3
3
  function n(t) {
4
4
  return /* @__PURE__ */ o.createElement(r, { direction: "column", ...t });
5
5
  }
package/dist/Column.js CHANGED
@@ -1,4 +1,4 @@
1
- import { C as r } from "./Column-DDaqX-A7.js";
1
+ import { C as r } from "./Column-BiogBDf8.js";
2
2
  export {
3
3
  r as Column
4
4
  };
@@ -0,0 +1,151 @@
1
+ import e from "react";
2
+ import { c as s } from "./cx-CcykAxZN.js";
3
+ import { P as I } from "./Popover-g2xTGubK.js";
4
+ import './Dropdown.css';const R = "crr", z = "crt", F = "crc", G = "crp", P = "crh", T = "crg", U = "crd", q = "cri", A = "crn", H = "crk", J = "crl", K = "cru", O = "crm", Q = "crb", V = "cro", X = "crf", Y = "crx", Z = "cry", _ = "crv", n = {
5
+ r: R,
6
+ t: z,
7
+ c: F,
8
+ p: G,
9
+ h: P,
10
+ g: T,
11
+ d: U,
12
+ i: q,
13
+ n: A,
14
+ k: H,
15
+ l: J,
16
+ u: K,
17
+ m: O,
18
+ b: Q,
19
+ o: V,
20
+ f: X,
21
+ x: Y,
22
+ y: Z,
23
+ v: _
24
+ };
25
+ function $() {
26
+ return /* @__PURE__ */ e.createElement("svg", { className: n.c, viewBox: "0 0 12 12", "aria-hidden": !0 }, /* @__PURE__ */ e.createElement(
27
+ "path",
28
+ {
29
+ d: "M2.5 4.5 6 8l3.5-3.5",
30
+ fill: "none",
31
+ stroke: "currentColor",
32
+ strokeWidth: "1.5",
33
+ strokeLinecap: "round",
34
+ strokeLinejoin: "round"
35
+ }
36
+ ));
37
+ }
38
+ function S() {
39
+ return /* @__PURE__ */ e.createElement("svg", { className: n.m, viewBox: "0 0 12 12", "aria-hidden": !0 }, /* @__PURE__ */ e.createElement(
40
+ "path",
41
+ {
42
+ d: "M4.5 2.5 8 6l-3.5 3.5",
43
+ fill: "none",
44
+ stroke: "currentColor",
45
+ strokeWidth: "1.5",
46
+ strokeLinecap: "round",
47
+ strokeLinejoin: "round"
48
+ }
49
+ ));
50
+ }
51
+ function b({ className: t }) {
52
+ return /* @__PURE__ */ e.createElement("svg", { className: s(n.v, t), viewBox: "0 0 12 12", "aria-hidden": !0 }, /* @__PURE__ */ e.createElement(
53
+ "path",
54
+ {
55
+ d: "M2.5 6.2 4.8 8.5 9.5 3.5",
56
+ fill: "none",
57
+ stroke: "currentColor",
58
+ strokeWidth: "1.8",
59
+ strokeLinecap: "round",
60
+ strokeLinejoin: "round"
61
+ }
62
+ ));
63
+ }
64
+ function ee({ item: t }) {
65
+ return t.checkbox ? /* @__PURE__ */ e.createElement("span", { className: s(n.x, t.checked && n.y), "aria-hidden": !0 }, t.checked ? /* @__PURE__ */ e.createElement(b, null) : null) : t.checked ? /* @__PURE__ */ e.createElement("span", { className: n.k, "aria-hidden": !0 }, /* @__PURE__ */ e.createElement(b, null)) : t.status != null ? /* @__PURE__ */ e.createElement(
66
+ "span",
67
+ {
68
+ className: s(n.b, t.status === "online" ? n.o : n.f),
69
+ "aria-hidden": !0
70
+ }
71
+ ) : t.icon != null ? /* @__PURE__ */ e.createElement("span", { className: n.n }, t.icon) : null;
72
+ }
73
+ function ne(t, l, a) {
74
+ return l != null && l.length > 0 ? a != null && l[0] && l[0].title == null ? [{ ...l[0], title: a }, ...l.slice(1)] : l : t != null && t.length > 0 ? [{ title: a, items: t }] : a != null ? [{ title: a, items: [] }] : [];
75
+ }
76
+ function le({
77
+ items: t,
78
+ groups: l,
79
+ trigger: a,
80
+ label: u,
81
+ hideChevron: N = !1,
82
+ title: x,
83
+ align: f = "end",
84
+ open: p,
85
+ defaultOpen: y = !1,
86
+ onOpenChange: d,
87
+ closeOnSelect: L = !0,
88
+ disabled: i = !1,
89
+ onSelect: h,
90
+ className: C
91
+ }) {
92
+ const [g, w] = e.useState(y), E = p !== void 0, k = E ? p : g, v = (r) => {
93
+ E || w(r), d == null || d(r);
94
+ }, B = ne(t, l, x), j = (r) => {
95
+ var c;
96
+ if (r.disabled) return;
97
+ (c = r.onClick) == null || c.call(r), h == null || h(r.value, r), r.checkbox || r.submenu || !L || v(!1);
98
+ }, D = a ?? /* @__PURE__ */ e.createElement(
99
+ "button",
100
+ {
101
+ type: "button",
102
+ className: n.t,
103
+ "data-open": k ? "true" : void 0,
104
+ disabled: i,
105
+ "aria-haspopup": "menu",
106
+ "aria-expanded": k
107
+ },
108
+ u,
109
+ N ? null : /* @__PURE__ */ e.createElement($, null)
110
+ );
111
+ return /* @__PURE__ */ e.createElement(
112
+ I,
113
+ {
114
+ className: s(n.r, C),
115
+ open: k,
116
+ onOpenChange: (r) => {
117
+ i || v(r);
118
+ },
119
+ align: f,
120
+ trigger: D,
121
+ label: typeof u == "string" ? u : void 0,
122
+ disabled: i
123
+ },
124
+ /* @__PURE__ */ e.createElement("div", { className: n.p, "data-align": f }, B.map((r, m) => /* @__PURE__ */ e.createElement(e.Fragment, { key: m }, m > 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) => {
125
+ const M = r.items.some(
126
+ (o) => o.checked || o.checkbox || o.status != null || o.icon != null
127
+ ), W = /* @__PURE__ */ e.createElement(ee, { item: c });
128
+ return /* @__PURE__ */ e.createElement(
129
+ "button",
130
+ {
131
+ key: c.value,
132
+ type: "button",
133
+ role: "menuitem",
134
+ className: n.i,
135
+ "data-checked": (c.checked || c.checkbox) && c.checked ? "true" : void 0,
136
+ "data-danger": c.danger ? "true" : void 0,
137
+ disabled: c.disabled,
138
+ "aria-checked": c.checked != null || c.checkbox ? !!c.checked : void 0,
139
+ onClick: () => j(c)
140
+ },
141
+ M ? W ?? /* @__PURE__ */ e.createElement("span", { className: n.n, "aria-hidden": !0 }) : null,
142
+ c.label != null ? /* @__PURE__ */ e.createElement("span", { className: n.l }, c.label) : null,
143
+ c.shortcut != null ? /* @__PURE__ */ e.createElement("span", { className: n.u }, c.shortcut) : null,
144
+ c.submenu ? /* @__PURE__ */ e.createElement(S, null) : null
145
+ );
146
+ })))))
147
+ );
148
+ }
149
+ export {
150
+ le as D
151
+ };
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{position:absolute;top:calc(100% + var(--shell-gap-sm));z-index:var(--shell-z);min-width:var(--dropdown-min-width);max-width:var(--dropdown-max-width);max-height:var(--dropdown-max-height);overflow:auto;padding:var(--shell-gap-sm);box-sizing:border-box;background:var(--shell-background);border:1px solid var(--shell-border);border-radius:var(--shell-radius);box-shadow:var(--popup-shadow)}.crp[data-align=start]{left:0}.crp[data-align=end]{right: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: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}}
@@ -80,14 +80,14 @@ export type DropdownProps = Omit<React.HTMLAttributes<HTMLDivElement>, "onChange
80
80
  onSelect?: (value: string, item: DropdownItem) => void;
81
81
  };
82
82
  /**
83
- * Выпадающее меню: триггер + панель с `groups` / `items` рядом с якорем (не portal).
83
+ * Выпадающее меню: триггер + панель с `groups` / `items` (portal, {@link Popover}).
84
84
  *
85
85
  * Когда использовать:
86
86
  * - действия строки списка, переключатели колонок, контекстные пункты у кнопки.
87
87
  *
88
88
  * Отличия:
89
89
  * - {@link Menu} — инлайн-навигация в потоке (шапка), без панели;
90
- * - `@elcrm/overlay`портальное меню/popover поверх layout (фокус-ловушка, слои).
90
+ * - {@link Popover} свой контент в portal, без `items`.
91
91
  *
92
92
  * API: декларативные `items` / `groups`. Идентификатор пункта — `value` (не `key`).
93
93
  * Compound-слоты (`Dropdown.Item`) не используются.
@@ -121,4 +121,4 @@ export type DropdownProps = Omit<React.HTMLAttributes<HTMLDivElement>, "onChange
121
121
  * />
122
122
  * ```
123
123
  */
124
- export declare function Dropdown({ items, groups, trigger, label, hideChevron, title, align, open: openProp, defaultOpen, onOpenChange, closeOnSelect, disabled, onSelect, className, ...rest }: DropdownProps): React.JSX.Element;
124
+ export declare function Dropdown({ items, groups, trigger, label, hideChevron, title, align, open: openProp, defaultOpen, onOpenChange, closeOnSelect, disabled, onSelect, className, }: DropdownProps): React.JSX.Element;
package/dist/Dropdown.js CHANGED
@@ -1,4 +1,4 @@
1
- import { D as p } from "./Dropdown-DQlDiWCR.js";
1
+ import { D as p } from "./Dropdown-CQBMF9aR.js";
2
2
  export {
3
3
  p as Dropdown
4
4
  };
@@ -0,0 +1,46 @@
1
+ import r from "react";
2
+ import { c as m } from "./cx-CcykAxZN.js";
3
+ import './Item.css';const u = "cir", d = "cia", v = "cic", i = {
4
+ r: u,
5
+ a: d,
6
+ c: v
7
+ };
8
+ function N(s) {
9
+ const {
10
+ active: t,
11
+ variant: o = "plain",
12
+ children: a,
13
+ className: l,
14
+ as: n = "button",
15
+ ...e
16
+ } = s, c = m(i.r, o === "card" && i.c, t && i.a, l);
17
+ return n === "a" ? /* @__PURE__ */ r.createElement(
18
+ "a",
19
+ {
20
+ className: c,
21
+ "data-active": t ? "true" : void 0,
22
+ ...e
23
+ },
24
+ a
25
+ ) : n === "li" ? /* @__PURE__ */ r.createElement(
26
+ "li",
27
+ {
28
+ className: c,
29
+ "data-active": t ? "true" : void 0,
30
+ ...e
31
+ },
32
+ a
33
+ ) : /* @__PURE__ */ r.createElement(
34
+ "button",
35
+ {
36
+ type: "button",
37
+ className: c,
38
+ "data-active": t ? "true" : void 0,
39
+ ...e
40
+ },
41
+ a
42
+ );
43
+ }
44
+ export {
45
+ N as I
46
+ };
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)}}
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)}}
package/dist/Item.d.ts CHANGED
@@ -2,6 +2,11 @@ import { default as React } from 'react';
2
2
  type Common = {
3
3
  /** Активное / выбранное состояние */
4
4
  active?: boolean;
5
+ /**
6
+ * `plain` — строка списка.
7
+ * `card` — карточка (идеи / тикеты): рамка, muted-фон, hover.
8
+ */
9
+ variant?: "plain" | "card";
5
10
  /** Содержимое элемента */
6
11
  children?: React.ReactNode;
7
12
  /** Доп. CSS-класс */
@@ -13,11 +18,13 @@ type Common = {
13
18
  * Роли: Item внутри List / Menu; для групповых списков выбора —
14
19
  * RadioGroup / Dropdown с `items` (не собирайте Item вручную).
15
20
  *
21
+ * @param variant `plain` (строка) или `card` (рамка, muted-фон)
22
+ *
16
23
  * @example
17
24
  * ```tsx
18
25
  * <List>
19
26
  * <Item as="li" active>Текущий</Item>
20
- * <Item as="a" href="/docs">Документация</Item>
27
+ * <Item as="button" variant="card" active>Карточка</Item>
21
28
  * </List>
22
29
  * ```
23
30
  *
package/dist/Item.js CHANGED
@@ -1,4 +1,4 @@
1
- import { I as o } from "./Item-CaU4RW2G.js";
1
+ import { I as o } from "./Item-D4okhsfW.js";
2
2
  export {
3
3
  o as Item
4
4
  };
@@ -0,0 +1,41 @@
1
+ import e from "react";
2
+ import { c as N } from "./cx-CcykAxZN.js";
3
+ import './ItemColumn.css';const h = "c7r", v = "c7i", k = "c7b", b = "c7h", x = "c7t", g = "c7x", C = "c7d", F = "c7f", I = "c7p", y = "c7a", L = "c7s", M = "c7l", R = "c7k", l = {
4
+ r: h,
5
+ i: v,
6
+ b: k,
7
+ h: b,
8
+ t: x,
9
+ x: g,
10
+ d: C,
11
+ f: F,
12
+ p: I,
13
+ a: y,
14
+ s: L,
15
+ l: M,
16
+ k: R
17
+ };
18
+ function $({ items: a }) {
19
+ const t = a.filter((n) => n != null && n !== !1 && n !== "");
20
+ return t.length === 0 ? null : /* @__PURE__ */ e.createElement(e.Fragment, null, t.map((n, c) => /* @__PURE__ */ e.createElement(e.Fragment, { key: c }, c > 0 ? /* @__PURE__ */ e.createElement("span", { className: l.p, "aria-hidden": !0 }, "·") : null, /* @__PURE__ */ e.createElement("span", null, n))));
21
+ }
22
+ function w({
23
+ icon: a,
24
+ title: t,
25
+ extra: n,
26
+ aside: c,
27
+ description: s,
28
+ footer: o,
29
+ meta: m,
30
+ size: r = "m",
31
+ unread: i,
32
+ children: E,
33
+ className: d,
34
+ ...p
35
+ }) {
36
+ const f = r === "s" ? l.s : r === "l" ? l.l : void 0, u = o ?? (m != null ? /* @__PURE__ */ e.createElement($, { items: m }) : null);
37
+ return /* @__PURE__ */ e.createElement("div", { className: N(l.r, f, i && l.k, d), ...p }, a != null ? /* @__PURE__ */ e.createElement("span", { className: l.i, "aria-hidden": !0 }, a) : null, /* @__PURE__ */ e.createElement("div", { className: l.b }, t != null || n != null ? /* @__PURE__ */ e.createElement("div", { className: l.h }, t != null ? /* @__PURE__ */ e.createElement("span", { className: l.t }, t) : null, n != null ? /* @__PURE__ */ e.createElement("span", { className: l.x }, n) : null) : null, s != null ? /* @__PURE__ */ e.createElement("div", { className: l.d }, s) : null, u != null ? /* @__PURE__ */ e.createElement("div", { className: l.f }, u) : null, E), c != null ? /* @__PURE__ */ e.createElement("div", { className: l.a }, c) : null);
38
+ }
39
+ export {
40
+ w as I
41
+ };
@@ -0,0 +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}}
@@ -0,0 +1,61 @@
1
+ import { default as React } from 'react';
2
+ /**
3
+ * Колонка содержимого строки списка: иконка слева, текст столбиком, слоты справа.
4
+ *
5
+ * Роли: внутри {@link Item} / {@link Card} (идеи, тикеты, inbox).
6
+ * Не заменяет Item (клик / active) и не AvatarName (там фото).
7
+ *
8
+ * @param icon кружок слева (иконка приложения)
9
+ * @param title первая строка
10
+ * @param extra бейджи в правом верхнем углу строки title
11
+ * @param aside колонка справа на всю высоту (дата, действия)
12
+ * @param description превью / вторая строка
13
+ * @param footer третья строка (мета)
14
+ * @param meta куски футера через «·» (если нет footer)
15
+ * @param size `s` | `m` | `l`
16
+ * @param unread жирный title (непрочитанное)
17
+ *
18
+ * @example
19
+ * ```tsx
20
+ * <Item as="button" onClick={open}>
21
+ * <ItemColumn
22
+ * icon={<Icon />}
23
+ * title="Тема"
24
+ * extra={<Badge size="s" tone="accent">Новые</Badge>}
25
+ * description="Превью текста…"
26
+ * meta={["★ 2", "3 комм.", "Иван"]}
27
+ * />
28
+ * </Item>
29
+ * ```
30
+ *
31
+ * Токены: `--item-column-gap`, `--item-column-icon-size`, `--item-column-icon-radius`,
32
+ * `--item-column-title-size`, `--item-column-title-line`.
33
+ */
34
+ export type ItemColumnProps = Omit<React.HTMLAttributes<HTMLDivElement>, "title"> & {
35
+ /** Иконка слева */
36
+ icon?: React.ReactNode;
37
+ /** Заголовок */
38
+ title?: React.ReactNode;
39
+ /** Справа сверху у title (Badge, счётчик) */
40
+ extra?: React.ReactNode;
41
+ /** Правая колонка (верхний край) */
42
+ aside?: React.ReactNode;
43
+ /** Описание / превью */
44
+ description?: React.ReactNode;
45
+ /** Подвал целиком */
46
+ footer?: React.ReactNode;
47
+ /** Куски подвала через точку — если нет `footer` */
48
+ meta?: React.ReactNode[];
49
+ /** Размер текста */
50
+ size?: "s" | "m" | "l";
51
+ /** Жирный title (непрочитанное) */
52
+ unread?: boolean;
53
+ /** Доп. строки под footer */
54
+ children?: React.ReactNode;
55
+ };
56
+ /**
57
+ * Иконка + колонка title / description / footer (+ extra / aside).
58
+ *
59
+ * @see Item, TextGroup, AvatarName, Badge
60
+ */
61
+ export declare function ItemColumn({ icon, title, extra, aside, description, footer, meta, size, unread, children, className, ...rest }: ItemColumnProps): React.JSX.Element;
@@ -0,0 +1,4 @@
1
+ import { I as e } from "./ItemColumn-M7a9L8CI.js";
2
+ export {
3
+ e as ItemColumn
4
+ };
@@ -0,0 +1,22 @@
1
+ import e from "react";
2
+ import { c as s } from "./cx-CcykAxZN.js";
3
+ import './Layout.css';const i = "clr", u = "clm", E = "cls", b = "clb", t = {
4
+ r: i,
5
+ m: u,
6
+ s: E,
7
+ b
8
+ };
9
+ function p({
10
+ sidebar: c,
11
+ header: a,
12
+ footer: l,
13
+ children: o,
14
+ className: n,
15
+ ...m
16
+ }) {
17
+ const r = /* @__PURE__ */ e.createElement(e.Fragment, null, a, /* @__PURE__ */ e.createElement("main", { className: t.m }, o), l);
18
+ return c != null ? /* @__PURE__ */ e.createElement("div", { className: s(t.r, t.s, n), ...m }, c, /* @__PURE__ */ e.createElement("div", { className: t.b }, r)) : /* @__PURE__ */ e.createElement("div", { className: s(t.r, n), ...m }, r);
19
+ }
20
+ export {
21
+ p as L
22
+ };
package/dist/Layout.css CHANGED
@@ -1 +1 @@
1
- @layer elcrm-components{.clr{display:flex;flex-direction:column;flex:1 1 auto;height:100%;min-height:0;max-height:100%;overflow:hidden;background:var(--shell-background-muted);gap:0}.clm{display:flex;flex-direction:column;flex:1 1 auto;min-width:0;min-height:0;overflow:hidden}}
1
+ @layer elcrm-components{.clr{display:flex;flex-direction:column;flex:1 1 auto;height:100%;min-height:0;max-height:100%;overflow:hidden;background:var(--shell-background-muted);gap:0}.clm{display:flex;flex-direction:column;flex:1 1 auto;min-width:0;min-height:0;overflow:hidden}.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}}
package/dist/Layout.d.ts CHANGED
@@ -7,14 +7,19 @@ import { default as React } from 'react';
7
7
  *
8
8
  * @example
9
9
  * ```tsx
10
- * <Layout header={<Header brand="App" />} footer={<Footer>© 2026</Footer>}>
11
- * <Section title="Главная">…</Section>
10
+ * <Layout
11
+ * sidebar={<Sidebar groups={groups} value={page} onSelect={setPage} />}
12
+ * header={<Header brand="App" />}
13
+ * >
14
+ * <PageShell>…</PageShell>
12
15
  * </Layout>
13
16
  * ```
14
17
  *
15
18
  * Токены: `--shell-background-muted` (фон main), прочие `--shell-*`.
16
19
  */
17
20
  export type LayoutProps = React.HTMLAttributes<HTMLDivElement> & {
21
+ /** Левая колонка (обычно `<Sidebar />`) — ряд: сайдбар + контент */
22
+ sidebar?: React.ReactNode;
18
23
  /** Слот шапки (обычно `<Header />`) */
19
24
  header?: React.ReactNode;
20
25
  /** Слот подвала (обычно `<Footer />`) */
@@ -23,8 +28,8 @@ export type LayoutProps = React.HTMLAttributes<HTMLDivElement> & {
23
28
  children?: React.ReactNode;
24
29
  };
25
30
  /**
26
- * Оболочка страницы: header + main + footer.
31
+ * Оболочка: опционально `sidebar` слева, затем header + main + footer.
27
32
  *
28
- * @see Header, Footer, Section, PageShell
33
+ * @see Sidebar, Header, Footer, Section, PageShell
29
34
  */
30
- export declare function Layout({ header, footer, children, className, ...rest }: LayoutProps): React.JSX.Element;
35
+ export declare function Layout({ sidebar, header, footer, children, className, ...rest }: LayoutProps): React.JSX.Element;
package/dist/Layout.js CHANGED
@@ -1,4 +1,4 @@
1
- import { L as r } from "./Layout-Xb3-xsmA.js";
1
+ import { L as r } from "./Layout-BQwEaeO0.js";
2
2
  export {
3
3
  r as Layout
4
4
  };
@@ -0,0 +1,58 @@
1
+ import l from "react";
2
+ import { B as p } from "./Badge-jp-9iNNL.js";
3
+ import { c as i } from "./cx-CcykAxZN.js";
4
+ import './Menu.css';const b = "cmr", m = "cmv", k = "cmi", x = "cmd", E = "cma", g = "cmu", c = {
5
+ r: b,
6
+ v: m,
7
+ i: k,
8
+ d: x,
9
+ a: E,
10
+ u: g
11
+ };
12
+ function y(a) {
13
+ if (a == null || a === "") return null;
14
+ const r = Number(a);
15
+ return !Number.isNaN(r) && r === 0 ? null : !Number.isNaN(r) && r > 99 ? "99+" : String(a);
16
+ }
17
+ function h({
18
+ items: a,
19
+ vertical: r,
20
+ variant: v = "plain",
21
+ value: o,
22
+ onSelect: u,
23
+ children: d,
24
+ className: N,
25
+ ...f
26
+ }) {
27
+ return /* @__PURE__ */ l.createElement(
28
+ "nav",
29
+ {
30
+ className: i(c.r, r && c.v, v === "line" && c.u, N),
31
+ ...f
32
+ },
33
+ a == null ? void 0 : a.map((n) => {
34
+ const t = n.active ?? (o != null && n.value === o), s = y(n.badge);
35
+ return /* @__PURE__ */ l.createElement(
36
+ "button",
37
+ {
38
+ key: n.value,
39
+ type: "button",
40
+ className: i(c.i, t && c.a),
41
+ "data-active": t ? "true" : void 0,
42
+ "aria-current": t ? "page" : void 0,
43
+ disabled: n.disabled,
44
+ onClick: () => {
45
+ var e;
46
+ (e = n.onClick) == null || e.call(n), u == null || u(n.value);
47
+ }
48
+ },
49
+ n.label,
50
+ s != null ? /* @__PURE__ */ l.createElement(p, { className: c.d, tone: "accent", size: "s" }, s) : null
51
+ );
52
+ }),
53
+ d
54
+ );
55
+ }
56
+ export {
57
+ h as M
58
+ };
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:6px}.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
- * - `@elcrm/overlay`портальный popover/меню поверх страницы;
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: "Команда", disabled: true },
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
@@ -1,4 +1,4 @@
1
- import { M as r } from "./Menu-DRBHvSdJ.js";
1
+ import { M as r } from "./Menu-DpUvOl8Y.js";
2
2
  export {
3
3
  r as Menu
4
4
  };
@@ -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-lg)}.ccw{display:flex;flex-wrap:wrap;align-items:flex-start;justify-content:space-between;gap:var(--shell-gap)}.cct{min-width:0;max-width:36rem}.cch{margin:0;font-size:var(--section-title-size);font-weight:var(--shell-font-weight);color:var(--shell-color);line-height:1.25}.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)}}
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, var(--shell-background-muted))}.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}}