@elcrm/components 0.2.3 → 0.2.5

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 CHANGED
@@ -682,7 +682,7 @@ const resolve = createLazyResolver((value) => import(`./sections/${value}.tsx`))
682
682
  **Узкие (только если нужно иначе)**
683
683
 
684
684
  ```
685
- --header-height / --header-z / --header-margin / --header-shadow / --header-radius
685
+ --header-height / --header-z / --header-margin / --header-shadow / --header-radius / --header-border
686
686
  --section-padding / --section-title-size / --section-title-size-md / --section-auth-card-max-width
687
687
  --nav-sections-padding / --nav-sections-nav-width / --nav-sections-main-max-width
688
688
  --avatar-size-s|m|l / --avatar-group-overlap
@@ -1,30 +1,30 @@
1
1
  import e from "react";
2
2
  import { C as f } from "./CheckIcon-FdB8fMEF.js";
3
3
  import { c as m } from "./cx-CcykAxZN.js";
4
- import { P as D } from "./Popover-5dFP4TXx.js";
5
- import { u as j } from "./useControllableValue-CWqH1kpM.js";
6
- import './Dropdown.css';const I = "crr", M = "crt", P = "crc", R = "crp", W = "crh", z = "crg", F = "crd", G = "cri", T = "crn", V = "crm", q = "crk", A = "crl", H = "cru", J = "crb", K = "cro", Q = "crf", U = "crx", X = "cry", Y = "crv", n = {
7
- r: I,
8
- t: M,
9
- c: P,
10
- p: R,
11
- h: W,
12
- g: z,
13
- d: F,
14
- i: G,
15
- n: T,
16
- m: V,
17
- k: q,
18
- l: A,
19
- u: H,
20
- b: J,
21
- o: K,
22
- f: Q,
23
- x: U,
24
- y: X,
25
- v: Y
4
+ import { P as j } from "./Popover-D5RymtcJ.js";
5
+ import { u as I } from "./useControllableValue-CWqH1kpM.js";
6
+ import './Dropdown.css';const M = "crr", P = "crt", R = "crc", W = "crp", z = "crh", F = "crg", G = "crd", T = "cri", V = "crn", q = "crm", A = "crk", H = "crl", J = "cru", K = "crb", Q = "cro", U = "crf", X = "crx", Y = "cry", Z = "crv", n = {
7
+ r: M,
8
+ t: P,
9
+ c: R,
10
+ p: W,
11
+ h: z,
12
+ g: F,
13
+ d: G,
14
+ i: T,
15
+ n: V,
16
+ m: q,
17
+ k: A,
18
+ l: H,
19
+ u: J,
20
+ b: K,
21
+ o: Q,
22
+ f: U,
23
+ x: X,
24
+ y: Y,
25
+ v: Z
26
26
  };
27
- function Z() {
27
+ function _() {
28
28
  return /* @__PURE__ */ e.createElement("svg", { className: n.c, viewBox: "0 0 12 12", "aria-hidden": !0 }, /* @__PURE__ */ e.createElement(
29
29
  "path",
30
30
  {
@@ -37,7 +37,7 @@ function Z() {
37
37
  }
38
38
  ));
39
39
  }
40
- function _() {
40
+ function $() {
41
41
  return /* @__PURE__ */ e.createElement("svg", { className: n.m, viewBox: "0 0 12 12", "aria-hidden": !0 }, /* @__PURE__ */ e.createElement(
42
42
  "path",
43
43
  {
@@ -50,7 +50,7 @@ function _() {
50
50
  }
51
51
  ));
52
52
  }
53
- function $({ item: a }) {
53
+ function S({ item: a }) {
54
54
  return a.checkbox ? /* @__PURE__ */ e.createElement("span", { className: m(n.x, a.checked && n.y), "aria-hidden": !0 }, a.checked ? /* @__PURE__ */ e.createElement(f, { className: n.v }) : null) : a.checked ? /* @__PURE__ */ e.createElement("span", { className: n.k, "aria-hidden": !0 }, /* @__PURE__ */ e.createElement(f, { className: n.v })) : a.status != null ? /* @__PURE__ */ e.createElement(
55
55
  "span",
56
56
  {
@@ -59,34 +59,35 @@ function $({ item: a }) {
59
59
  }
60
60
  ) : a.icon != null ? /* @__PURE__ */ e.createElement("span", { className: n.n }, a.icon) : null;
61
61
  }
62
- function S(a, l, t) {
63
- return l != null && l.length > 0 ? t != null && l[0] && l[0].title == null ? [{ ...l[0], title: t }, ...l.slice(1)] : l : a != null && a.length > 0 ? [{ title: t, items: a }] : t != null ? [{ title: t, items: [] }] : [];
62
+ function ee(a, t, l) {
63
+ return t != null && t.length > 0 ? l != null && t[0] && t[0].title == null ? [{ ...t[0], title: l }, ...t.slice(1)] : t : a != null && a.length > 0 ? [{ title: l, items: a }] : l != null ? [{ title: l, items: [] }] : [];
64
64
  }
65
65
  function le({
66
66
  items: a,
67
- groups: l,
68
- trigger: t,
67
+ groups: t,
68
+ trigger: l,
69
69
  label: o,
70
70
  hideChevron: E = !1,
71
71
  title: v,
72
72
  align: k = "end",
73
- open: b,
74
- defaultOpen: N = !1,
75
- onOpenChange: x,
76
- closeOnSelect: C = !0,
73
+ placement: b = "auto",
74
+ open: N,
75
+ defaultOpen: x = !1,
76
+ onOpenChange: C,
77
+ closeOnSelect: y = !0,
77
78
  disabled: u = !1,
78
79
  onSelect: d,
79
- className: y
80
+ className: g
80
81
  }) {
81
- const [i = !1, p] = j(
82
- b,
82
+ const [i = !1, p] = I(
83
83
  N,
84
- x
85
- ), g = S(a, l, v), L = (r) => {
84
+ x,
85
+ C
86
+ ), L = ee(a, t, v), w = (r) => {
86
87
  var c;
87
88
  if (r.disabled) return;
88
- (c = r.onClick) == null || c.call(r), d == null || d(r.value, r), r.checkbox || r.submenu || !C || p(!1);
89
- }, w = t ?? /* @__PURE__ */ e.createElement(
89
+ (c = r.onClick) == null || c.call(r), d == null || d(r.value, r), r.checkbox || r.submenu || !y || p(!1);
90
+ }, O = l ?? /* @__PURE__ */ e.createElement(
90
91
  "button",
91
92
  {
92
93
  type: "button",
@@ -97,25 +98,26 @@ function le({
97
98
  "aria-expanded": i
98
99
  },
99
100
  o,
100
- E ? null : /* @__PURE__ */ e.createElement(Z, null)
101
+ E ? null : /* @__PURE__ */ e.createElement(_, null)
101
102
  );
102
103
  return /* @__PURE__ */ e.createElement(
103
- D,
104
+ j,
104
105
  {
105
- className: m(n.r, y),
106
+ className: m(n.r, g),
106
107
  open: i,
107
108
  onOpenChange: (r) => {
108
109
  u || p(r);
109
110
  },
110
111
  align: k,
111
- trigger: w,
112
+ placement: b,
113
+ trigger: O,
112
114
  label: typeof o == "string" ? o : void 0,
113
115
  disabled: u
114
116
  },
115
- /* @__PURE__ */ e.createElement("div", { className: n.p, "data-align": k }, g.map((r, h) => /* @__PURE__ */ e.createElement(e.Fragment, { key: h }, h > 0 ? /* @__PURE__ */ e.createElement("hr", { className: n.d }) : null, /* @__PURE__ */ e.createElement("div", { className: n.g, role: "group" }, r.title != null ? /* @__PURE__ */ e.createElement("p", { className: n.h }, r.title) : null, r.items.map((c) => {
116
- const O = r.items.some(
117
+ /* @__PURE__ */ e.createElement("div", { className: n.p, "data-align": k }, L.map((r, h) => /* @__PURE__ */ e.createElement(e.Fragment, { key: h }, h > 0 ? /* @__PURE__ */ e.createElement("hr", { className: n.d }) : null, /* @__PURE__ */ e.createElement("div", { className: n.g, role: "group" }, r.title != null ? /* @__PURE__ */ e.createElement("p", { className: n.h }, r.title) : null, r.items.map((c) => {
118
+ const B = r.items.some(
117
119
  (s) => s.checked || s.checkbox || s.status != null || s.icon != null
118
- ), B = /* @__PURE__ */ e.createElement($, { item: c });
120
+ ), D = /* @__PURE__ */ e.createElement(S, { item: c });
119
121
  return /* @__PURE__ */ e.createElement(
120
122
  "button",
121
123
  {
@@ -127,12 +129,12 @@ function le({
127
129
  "data-danger": c.danger ? "true" : void 0,
128
130
  disabled: c.disabled,
129
131
  "aria-checked": c.checked != null || c.checkbox ? !!c.checked : void 0,
130
- onClick: () => L(c)
132
+ onClick: () => w(c)
131
133
  },
132
- O ? B ?? /* @__PURE__ */ e.createElement("span", { className: n.n, "aria-hidden": !0 }) : null,
134
+ B ? D ?? /* @__PURE__ */ e.createElement("span", { className: n.n, "aria-hidden": !0 }) : null,
133
135
  c.label != null ? /* @__PURE__ */ e.createElement("span", { className: n.l }, c.label) : null,
134
136
  c.shortcut != null ? /* @__PURE__ */ e.createElement("span", { className: n.u }, c.shortcut) : null,
135
- c.submenu ? /* @__PURE__ */ e.createElement(_, null) : null
137
+ c.submenu ? /* @__PURE__ */ e.createElement($, null) : null
136
138
  );
137
139
  })))))
138
140
  );
@@ -63,6 +63,12 @@ export type DropdownProps = Omit<React.HTMLAttributes<HTMLDivElement>, "onChange
63
63
  title?: React.ReactNode;
64
64
  /** Выравнивание панели относительно триггера. */
65
65
  align?: "start" | "end";
66
+ /**
67
+ * Куда открывать панель.
68
+ * Футер Sidebar передаёт `top`.
69
+ * @default "auto"
70
+ */
71
+ placement?: "auto" | "top" | "bottom";
66
72
  /** Контролируемое открытие. */
67
73
  open?: boolean;
68
74
  /** Начальное открытие (неконтролируемый режим). */
@@ -121,4 +127,4 @@ export type DropdownProps = Omit<React.HTMLAttributes<HTMLDivElement>, "onChange
121
127
  * />
122
128
  * ```
123
129
  */
124
- export declare function Dropdown({ items, groups, trigger, label, hideChevron, title, align, open: openProp, defaultOpen, onOpenChange, closeOnSelect, disabled, onSelect, className, }: DropdownProps): React.JSX.Element;
130
+ export declare function Dropdown({ items, groups, trigger, label, hideChevron, title, align, placement, 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-C6qlqMLV.js";
1
+ import { D as p } from "./Dropdown-B9AodUFf.js";
2
2
  export {
3
3
  p as Dropdown
4
4
  };
@@ -0,0 +1,21 @@
1
+ import l from "react";
2
+ import { c as u } from "./cx-CcykAxZN.js";
3
+ import './Header.css';const o = "chr", i = "chn", d = "cha", e = {
4
+ r: o,
5
+ n: i,
6
+ a: d
7
+ };
8
+ function p({
9
+ brand: n,
10
+ nav: c,
11
+ search: t,
12
+ actions: a,
13
+ children: r,
14
+ className: s,
15
+ ...m
16
+ }) {
17
+ return /* @__PURE__ */ l.createElement("header", { className: u(e.r, s), ...m }, n ?? null, c != null ? /* @__PURE__ */ l.createElement("div", { className: e.n }, c) : null, t ?? null, a != null ? /* @__PURE__ */ l.createElement("div", { className: e.a }, a) : null, r);
18
+ }
19
+ export {
20
+ p as H
21
+ };
package/dist/Header.css CHANGED
@@ -1 +1 @@
1
- @layer elcrm-components{.chr{display:flex;align-items:center;gap:var(--shell-gap);flex-shrink:0;min-height:var(--header-height);padding:var(--shell-padding);color:var(--shell-color);background:var(--shell-background);border-bottom:1px solid var(--shell-border);border-radius:var(--header-radius);box-shadow:var(--header-shadow);margin:var(--header-margin);position:relative;z-index:var(--header-z)}.chb{flex-shrink:0}.chn{display:flex;align-items:center;min-width:0}.chs{flex:1;min-width:0;margin-left:auto;max-width:18rem}.cha{display:flex;align-items:center;gap:var(--shell-gap-sm);flex-shrink:0;margin-left:auto}.chs+.cha{margin-left:0}}
1
+ @layer elcrm-components{.chr{display:flex;align-items:center;gap:var(--shell-gap);flex-shrink:0;min-height:var(--header-height);padding:var(--shell-padding);color:var(--shell-color);background:var(--shell-background);border:var(--header-border);border-radius:var(--header-radius);box-shadow:var(--header-shadow);margin:var(--header-margin);position:relative;z-index:var(--header-z)}.chn{display:flex;flex:1;align-items:center;min-width:0}.cha{display:flex;align-items:center;gap:var(--shell-gap-sm);flex-shrink:0;margin:auto}}
package/dist/Header.d.ts CHANGED
@@ -14,7 +14,8 @@ import { default as React } from 'react';
14
14
  * />
15
15
  * ```
16
16
  *
17
- * Токены: `--shell-*`, узкие `--header-height`, `--header-z`, `--header-margin`, `--header-shadow`, `--header-radius`.
17
+ * Токены: `--shell-*`, узкие `--header-height`, `--header-z`, `--header-margin`,
18
+ * `--header-shadow`, `--header-radius`, `--header-border` (shorthand рамки).
18
19
  */
19
20
  export type HeaderProps = React.HTMLAttributes<HTMLElement> & {
20
21
  /** Логотип / название (часто `<Brand />`) */
package/dist/Header.js CHANGED
@@ -1,4 +1,4 @@
1
- import { H as a } from "./Header-Cf28eyjW.js";
1
+ import { H as a } from "./Header-DZQopVNy.js";
2
2
  export {
3
3
  a as Header
4
4
  };
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;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)}}
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(--button-color-muted);padding:var(--button-padding);border-radius:var(--button-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(--button-background-hover);color:var(--button-color)}.cma,.cmi[aria-current=page],.cmi[data-active=true]{background:var(--button-background-selected);color:var(--button-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)}}
@@ -0,0 +1,156 @@
1
+ import u, { useRef as E, useId as $, useState as T, useLayoutEffect as A, useEffect as B } from "react";
2
+ import { createPortal as ee } from "react-dom";
3
+ import { c as F } from "./cx-CcykAxZN.js";
4
+ import { u as te } from "./useControllableValue-CWqH1kpM.js";
5
+ import './Popover.css';const V = 1e3, ne = 10;
6
+ function b() {
7
+ const e = globalThis;
8
+ return e.elcrm || (e.elcrm = {}), e.elcrm.overlayZ || (e.elcrm.overlayZ = { seq: 0, active: /* @__PURE__ */ new Set() }), e.elcrm.overlayZ;
9
+ }
10
+ function oe() {
11
+ const e = b();
12
+ e.seq += 1;
13
+ const t = V + e.seq * ne;
14
+ return e.active.add(t), t;
15
+ }
16
+ function N(e) {
17
+ const t = b();
18
+ t.active.delete(e), t.active.size === 0 && (t.seq = 0);
19
+ }
20
+ function ve() {
21
+ const e = b();
22
+ return e.active.size === 0 ? V : Math.max(...e.active);
23
+ }
24
+ const se = "c3r", ie = "c3t", re = "c3p", H = {
25
+ r: se,
26
+ t: ie,
27
+ p: re
28
+ };
29
+ function ce(e, t) {
30
+ const c = (t == null ? void 0 : t.querySelector("button, a, [role='button']")) ?? (t == null ? void 0 : t.firstElementChild);
31
+ return (c instanceof HTMLElement ? c : t ?? e).getBoundingClientRect();
32
+ }
33
+ function ae(e, t) {
34
+ return e != null && e.top === t.top && e.left === t.left && e.minWidth === t.minWidth && e.maxHeight === t.maxHeight;
35
+ }
36
+ function le(e, t, c, p) {
37
+ if (!u.isValidElement(e)) return e;
38
+ const d = e.props.onClick;
39
+ return u.cloneElement(e, {
40
+ "aria-haspopup": "menu",
41
+ "aria-expanded": t,
42
+ "aria-controls": t ? c : void 0,
43
+ onClick: (v) => {
44
+ d == null || d(v), p();
45
+ }
46
+ });
47
+ }
48
+ function he({
49
+ trigger: e,
50
+ children: t,
51
+ open: c,
52
+ defaultOpen: p = !1,
53
+ onOpenChange: d,
54
+ align: v = "end",
55
+ placement: x = "auto",
56
+ disabled: z = !1,
57
+ label: D,
58
+ role: K = "menu",
59
+ className: j,
60
+ panelClassName: G
61
+ }) {
62
+ const w = E(null), P = E(null), y = E(null), g = $(), [s = !1, J] = te(
63
+ c,
64
+ p,
65
+ d
66
+ ), [m, W] = T(null), [a, q] = T(null), L = E(null);
67
+ L.current = a;
68
+ const M = (o) => {
69
+ z && o || J(o);
70
+ };
71
+ A(() => {
72
+ if (s) {
73
+ a == null && q(oe());
74
+ return;
75
+ }
76
+ a != null && (N(a), q(null));
77
+ }, [s, a]), B(() => () => {
78
+ L.current != null && N(L.current);
79
+ }, []);
80
+ const R = () => {
81
+ var S;
82
+ const o = w.current;
83
+ if (!o) return;
84
+ const n = ce(o, P.current), i = 8, l = 8, r = ((S = y.current) == null ? void 0 : S.offsetHeight) ?? 0, f = window.innerHeight - n.bottom - i - l, U = n.top - i - l, X = r > 0 ? r : 160, I = x === "bottom" || x !== "top" && f >= X, Y = Math.min(
85
+ 420,
86
+ Math.max(120, I ? f : U)
87
+ ), h = Math.max(200, n.width), _ = v === "end" ? Math.max(8, Math.min(n.right - h, window.innerWidth - h - 8)) : Math.max(8, Math.min(n.left, window.innerWidth - h - 8)), O = { top: I ? n.bottom + i : Math.max(l, n.top - i - (r > 0 ? r : 0)), left: _, minWidth: h, maxHeight: Y };
88
+ W((C) => ae(C, O) ? C : O);
89
+ };
90
+ A(() => {
91
+ if (!s) {
92
+ W(null);
93
+ return;
94
+ }
95
+ R();
96
+ const o = window.requestAnimationFrame(() => R()), n = () => R();
97
+ return window.addEventListener("resize", n), window.addEventListener("scroll", n, !0), () => {
98
+ window.cancelAnimationFrame(o), window.removeEventListener("resize", n), window.removeEventListener("scroll", n, !0);
99
+ };
100
+ }, [s, v, x, t]), B(() => {
101
+ if (!s) return;
102
+ const o = (i) => {
103
+ var r, f;
104
+ const l = i.target;
105
+ (r = w.current) != null && r.contains(l) || (f = y.current) != null && f.contains(l) || M(!1);
106
+ }, n = (i) => {
107
+ i.key === "Escape" && M(!1);
108
+ };
109
+ return document.addEventListener("mousedown", o), document.addEventListener("keydown", n), () => {
110
+ document.removeEventListener("mousedown", o), document.removeEventListener("keydown", n);
111
+ };
112
+ }, [s]);
113
+ const Q = {
114
+ position: "fixed",
115
+ zIndex: a ?? 1e3,
116
+ ...m ? {
117
+ top: m.top,
118
+ bottom: "auto",
119
+ left: m.left,
120
+ minWidth: m.minWidth,
121
+ maxHeight: m.maxHeight
122
+ } : { visibility: "hidden", pointerEvents: "none" }
123
+ }, Z = s ? /* @__PURE__ */ u.createElement(
124
+ "div",
125
+ {
126
+ ref: y,
127
+ id: g,
128
+ role: K,
129
+ "aria-label": D,
130
+ className: F(H.p, G),
131
+ style: Q,
132
+ onMouseDown: (o) => o.stopPropagation()
133
+ },
134
+ t
135
+ ) : null, k = () => {
136
+ z || M(!s);
137
+ };
138
+ return /* @__PURE__ */ u.createElement("div", { ref: w, className: F(H.r, j) }, /* @__PURE__ */ u.createElement(
139
+ "div",
140
+ {
141
+ ref: P,
142
+ className: H.t,
143
+ "aria-haspopup": "menu",
144
+ "aria-expanded": s,
145
+ "aria-controls": s ? g : void 0,
146
+ onClick: u.isValidElement(e) ? void 0 : k
147
+ },
148
+ le(e, s, g, k)
149
+ ), Z && typeof document < "u" ? ee(Z, document.body) : null);
150
+ }
151
+ export {
152
+ he as P,
153
+ oe as a,
154
+ ve as p,
155
+ N as r
156
+ };
package/dist/Popover.css CHANGED
@@ -1 +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);max-width:var(--dropdown-max-width);max-height:var(--dropdown-max-height)}}
1
+ @layer elcrm-components{.c3r{position:relative;display:inline-flex;vertical-align:middle}.c3t{display:inline-flex;align-items:center;min-width:0;height:auto}.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);max-width:var(--dropdown-max-width);max-height:var(--dropdown-max-height)}}
package/dist/Popover.d.ts CHANGED
@@ -1,4 +1,6 @@
1
1
  import { default as React } from 'react';
2
+ /** Куда открывать панель относительно якоря. */
3
+ export type PopoverPlacement = "auto" | "top" | "bottom";
2
4
  /**
3
5
  * Портал у якоря: Escape, клик снаружи, z-index (`globalThis.elcrm.overlayZ`).
4
6
  *
@@ -36,6 +38,12 @@ export type PopoverProps = {
36
38
  onOpenChange?: (open: boolean) => void;
37
39
  /** Выравнивание панели */
38
40
  align?: "start" | "end";
41
+ /**
42
+ * Куда открывать панель.
43
+ * `top` — всегда вверх (футер Sidebar).
44
+ * @default "auto"
45
+ */
46
+ placement?: PopoverPlacement;
39
47
  /** Не открывать по клику на якорь */
40
48
  disabled?: boolean;
41
49
  /** aria-label панели */
@@ -51,4 +59,4 @@ export type PopoverProps = {
51
59
  *
52
60
  * @see Dropdown, Menu
53
61
  */
54
- export declare function Popover({ trigger, children, open: openProp, defaultOpen, onOpenChange, align, disabled, label, role, className, panelClassName, }: PopoverProps): React.JSX.Element;
62
+ export declare function Popover({ trigger, children, open: openProp, defaultOpen, onOpenChange, align, placement, disabled, label, role, className, panelClassName, }: PopoverProps): React.JSX.Element;
package/dist/Popover.js CHANGED
@@ -1,4 +1,4 @@
1
- import { P as e } from "./Popover-5dFP4TXx.js";
1
+ import { P as e } from "./Popover-D5RymtcJ.js";
2
2
  export {
3
3
  e as Popover
4
4
  };
@@ -1,6 +1,6 @@
1
1
  import e from "react";
2
2
  import { B as h } from "./Badge-jp-9iNNL.js";
3
- import { D as w } from "./Dropdown-C6qlqMLV.js";
3
+ import { D as w } from "./Dropdown-B9AodUFf.js";
4
4
  import { I as y } from "./Item-D4okhsfW.js";
5
5
  import { b as C } from "./badgeText-CRzlIzi3.js";
6
6
  import { c as u } from "./cx-CcykAxZN.js";
@@ -94,6 +94,7 @@ function S({
94
94
  {
95
95
  className: l.q,
96
96
  align: "start",
97
+ placement: "top",
97
98
  label: g,
98
99
  trigger: /* @__PURE__ */ e.createElement(Q, { footer: t, className: l.w }),
99
100
  items: d,
package/dist/Sidebar.css CHANGED
@@ -1 +1 @@
1
- @layer elcrm-components{.c2r{box-sizing:border-box;display:flex;flex-direction:column;flex:1 1 auto;width:var(--sidebar-width, 248px);min-width:0;min-height:0;height:100%;max-height:100%;padding:var(--sidebar-pad-y, 16px) var(--sidebar-pad-x, 12px);gap:var(--shell-gap-sm, 8px);color:var(--shell-color);align-self:stretch}.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);border:1px solid var(--sidebar-block-border);border-radius:var(--sidebar-block-radius);box-shadow:var(--sidebar-block-shadow)}.c2h{margin:2px 10px 6px;font-size:var(--sidebar-group-font-size);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);border:0;border-radius:8px;background:transparent;color:var(--shell-color-muted);font-family:inherit;font-size:var(--sidebar-item-font-size);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);background:var(--sidebar-item-active-bg)}.c2o{display:inline-flex;flex-shrink:0;align-items:center;justify-content:center;width:var(--sidebar-icon-size);height:var(--sidebar-icon-size);color:inherit}.c2o :is(svg){display:block;width:var(--sidebar-icon-size);height:var(--sidebar-icon-size)}.c2a .c2o{color:var(--sidebar-icon-active)}.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}.c2q{display:flex;width:100%;min-width:0}.c2q>*{display:flex;width:100%;min-width:0}.c2w{display:flex;width:100%;min-width:0;align-items:center}.c2u{display:flex;align-items:center;width:100%;min-width:0;gap:var(--shell-gap-sm);margin:0;padding:0;border:none;background:transparent;font:inherit;color:inherit;cursor:pointer;text-align:left}.c2k{flex-shrink:0;width:var(--sidebar-icon-size);height:var(--sidebar-icon-size);color:var(--shell-color-muted)}.c2v{margin-top:var(--shell-gap-sm);font-size:11px;color:var(--shell-color-muted);text-align:center}@media (max-width: 900px){.c2r{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}}}
1
+ @layer elcrm-components{.c2r{box-sizing:border-box;display:flex;flex-direction:column;flex:1 1 auto;width:var(--sidebar-width, 248px);min-width:0;min-height:0;height:100%;max-height:100%;padding:var(--sidebar-pad-y, 16px) var(--sidebar-pad-x, 12px);gap:var(--shell-gap-sm, 8px);color:var(--shell-color);align-self:stretch}.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);border:1px solid var(--sidebar-block-border);border-radius:var(--sidebar-block-radius);box-shadow:var(--sidebar-block-shadow)}.c2h{margin:2px 10px 6px;font-size:var(--sidebar-group-font-size);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);border:0;border-radius:8px;background:transparent;color:var(--shell-color-muted);font-family:inherit;font-size:var(--sidebar-item-font-size);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);background:var(--sidebar-item-active-bg)}.c2o{display:inline-flex;flex-shrink:0;align-items:center;justify-content:center;width:var(--sidebar-icon-size);height:var(--sidebar-icon-size);color:inherit}.c2o :is(svg){display:block;width:var(--sidebar-icon-size);height:var(--sidebar-icon-size)}.c2a .c2o{color:var(--sidebar-icon-active)}.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}.c2q{display:flex;width:100%;min-width:0;flex:0 0 auto;height:auto;align-items:center}.c2q>*{display:flex;width:100%;min-width:0;height:auto;align-items:center}.c2w{display:flex;width:100%;min-width:0;align-items:center}.c2u{display:flex;align-items:center;width:100%;min-width:0;gap:var(--shell-gap-sm);margin:0;padding:0;border:none;background:transparent;font:inherit;color:inherit;cursor:pointer;text-align:left}.c2k{flex-shrink:0;width:var(--sidebar-icon-size);height:var(--sidebar-icon-size);color:var(--shell-color-muted)}.c2v{margin-top:var(--shell-gap-sm);font-size:11px;color:var(--shell-color-muted);text-align:center}@media (max-width: 900px){.c2r{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}}}
package/dist/Sidebar.d.ts CHANGED
@@ -77,7 +77,7 @@ export type SidebarProps = {
77
77
  /** Низ: тема, выход или карточка пользователя */
78
78
  footer?: React.ReactNode;
79
79
  /**
80
- * Меню по клику на `footer` (Dropdown).
80
+ * Меню по клику на `footer` (Dropdown, `placement="top"`).
81
81
  * Есть пункты → футер становится триггером, справа ⋮.
82
82
  */
83
83
  footerItems?: DropdownItem[];
package/dist/Sidebar.js CHANGED
@@ -1,4 +1,4 @@
1
- import { S as e } from "./Sidebar-D7CTdu37.js";
1
+ import { S as e } from "./Sidebar-BSOLtF8H.js";
2
2
  export {
3
3
  e as Sidebar
4
4
  };
package/dist/index.css CHANGED
@@ -22,7 +22,7 @@
22
22
 
23
23
  @layer elcrm-components{.cfr{flex-shrink:0;padding:var(--shell-padding);color:var(--shell-color-muted);background:transparent;border-top:1px solid var(--shell-border);font-size:var(--shell-font-size-sm)}}
24
24
 
25
- @layer elcrm-components{.chr{display:flex;align-items:center;gap:var(--shell-gap);flex-shrink:0;min-height:var(--header-height);padding:var(--shell-padding);color:var(--shell-color);background:var(--shell-background);border-bottom:1px solid var(--shell-border);border-radius:var(--header-radius);box-shadow:var(--header-shadow);margin:var(--header-margin);position:relative;z-index:var(--header-z)}.chb{flex-shrink:0}.chn{display:flex;align-items:center;min-width:0}.chs{flex:1;min-width:0;margin-left:auto;max-width:18rem}.cha{display:flex;align-items:center;gap:var(--shell-gap-sm);flex-shrink:0;margin-left:auto}.chs+.cha{margin-left:0}}
25
+ @layer elcrm-components{.chr{display:flex;align-items:center;gap:var(--shell-gap);flex-shrink:0;min-height:var(--header-height);padding:var(--shell-padding);color:var(--shell-color);background:var(--shell-background);border:var(--header-border);border-radius:var(--header-radius);box-shadow:var(--header-shadow);margin:var(--header-margin);position:relative;z-index:var(--header-z)}.chn{display:flex;flex:1;align-items:center;min-width:0}.cha{display:flex;align-items:center;gap:var(--shell-gap-sm);flex-shrink:0;margin:auto}}
26
26
 
27
27
  @layer elcrm-components{.cir{display:flex;align-items:center;gap:var(--shell-gap-sm);padding:var(--shell-padding);color:var(--shell-color);background:transparent;border:1px solid transparent;border-radius:var(--shell-radius);cursor:default}.cir:is(button,a){-webkit-appearance:none;-moz-appearance:none;appearance:none;font:inherit;text-align:left;width:100%;cursor:pointer}.cir:hover{background:var(--shell-background-hover)}.cia,.cir[aria-current=true],.cir[data-active=true]{background:var(--shell-background-selected)}.cic{align-items:flex-start;gap:var(--shell-gap);padding:var(--shell-padding);border:1px solid var(--shell-border);border-radius:var(--shell-radius);background:var(--shell-background-muted);flex-shrink:0}.cic:hover,.cic.cia,.cic[data-active=true]{background:color-mix(in srgb,var(--shell-color-accent) 12%,var(--shell-background-muted));border-color:color-mix(in srgb,var(--shell-color-accent) 35%,transparent)}}
28
28
 
@@ -34,7 +34,7 @@
34
34
 
35
35
  @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)}}
36
36
 
37
- @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)}}
37
+ @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(--button-color-muted);padding:var(--button-padding);border-radius:var(--button-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(--button-background-hover);color:var(--button-color)}.cma,.cmi[aria-current=page],.cmi[data-active=true]{background:var(--button-background-selected);color:var(--button-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)}}
38
38
 
39
39
  @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}}}
40
40
 
@@ -42,7 +42,7 @@
42
42
 
43
43
  @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}}
44
44
 
45
- @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);max-width:var(--dropdown-max-width);max-height:var(--dropdown-max-height)}}
45
+ @layer elcrm-components{.c3r{position:relative;display:inline-flex;vertical-align:middle}.c3t{display:inline-flex;align-items:center;min-width:0;height:auto}.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);max-width:var(--dropdown-max-width);max-height:var(--dropdown-max-height)}}
46
46
 
47
47
  @layer elcrm-components{.cur{display:grid;grid-template-columns:repeat(auto-fit,minmax(var(--pricing-card-min-width),1fr));gap:var(--shell-gap-lg);align-items:stretch}.cui{position:relative;display:flex;flex-direction:column;gap:var(--shell-gap);padding:var(--shell-padding);box-sizing:border-box;text-align:left;font:inherit;color:var(--shell-color);background:var(--shell-background);border:1px solid var(--shell-border);border-radius:var(--shell-radius);box-shadow:var(--shell-shadow)}.cui[data-selectable=true]{cursor:pointer}.cui:disabled,.cui[aria-disabled=true]{opacity:var(--shell-disabled-opacity);cursor:not-allowed}.cus,.cui[data-selected=true],.cui[data-highlighted=true]{border-color:var(--shell-color-accent);background:var(--shell-background-selected);box-shadow:var(--shell-shadow)}.cub{display:flex;align-items:center;justify-content:center;margin:calc(-1 * var(--shell-padding-block)) calc(-1 * var(--shell-padding-inline)) 0;padding:var(--shell-gap-sm) var(--shell-padding-inline);border-radius:var(--shell-radius) var(--shell-radius) 0 0;background:var(--shell-color-accent);color:var(--avatar-color);font-size:var(--shell-font-size-sm);font-weight:var(--shell-font-weight);text-align:center}.cug{display:inline-flex;align-items:center;width:fit-content;padding:.15rem .5rem;border-radius:999px;background:var(--shell-background-hover);color:var(--shell-color-accent);font-size:var(--shell-font-size-sm);font-weight:var(--shell-font-weight);line-height:1.2}.cua{position:absolute;top:0;left:50%;transform:translate(-50%,-50%)}.cum{display:flex;flex-shrink:0;align-items:center;justify-content:center;width:calc(var(--shell-icon-size) * 1.6);height:calc(var(--shell-icon-size) * 1.6);color:var(--shell-color-accent);background:var(--shell-background-hover);border-radius:50%;overflow:hidden}.cuh{display:flex;flex-wrap:wrap;align-items:center;gap:var(--shell-gap-sm)}.cut{margin:0;font-size:var(--shell-font-size);font-weight:var(--shell-font-weight);color:var(--shell-color);line-height:1.3}.cup{display:flex;flex-wrap:wrap;align-items:baseline;gap:var(--shell-gap-sm)}.cuz{font-size:calc(var(--shell-font-size-lg) * 1.35);font-weight:700;color:var(--shell-color);line-height:1.15}.cui[data-highlighted=true] .cuz,.cui[data-selected=true] .cuz{color:var(--shell-color-accent)}.cuo{font-size:var(--shell-font-size-sm);color:var(--shell-color-muted);text-decoration:line-through}.cue{font-size:var(--shell-font-size-sm);color:var(--shell-color-muted)}.cud{margin:0;font-size:var(--shell-font-size-sm);color:var(--shell-color-muted);line-height:1.45}.cux{display:flex;flex-direction:column;gap:var(--shell-gap-sm)}.cuf{display:flex;flex-direction:column;gap:var(--shell-gap-sm);margin:auto calc(-1 * var(--shell-padding-inline)) calc(-1 * var(--shell-padding-block));padding:var(--shell-padding);background:var(--shell-background-muted);border-top:1px solid var(--shell-border);border-radius:0 0 var(--shell-radius) var(--shell-radius)}.cuy{display:flex;flex-direction:column;gap:var(--shell-gap-sm);margin-top:auto}.cul{margin:0;font-size:var(--shell-font-size-sm);font-weight:var(--shell-font-weight);letter-spacing:.04em;text-transform:uppercase;color:var(--shell-color-muted)}.cuu{margin:0;font-size:var(--shell-font-size-sm);color:var(--shell-color-muted);line-height:1.4}.cun{display:flex;flex-direction:column;gap:var(--shell-gap-sm);margin:0;padding:0;list-style:none}.cuc{display:flex;align-items:flex-start;gap:var(--shell-gap-sm);font-size:var(--shell-font-size-sm);color:var(--shell-color);line-height:1.4}.cuk{display:inline-flex;flex-shrink:0;align-items:center;justify-content:center;width:var(--shell-check-size);height:var(--shell-check-size);margin-top:.1em;color:var(--avatar-color);background:var(--shell-color-success);border-radius:50%}.cuw{width:60%;height:60%;display:block}}
48
48
 
@@ -52,7 +52,7 @@
52
52
 
53
53
  @layer elcrm-components{.cep{display:flex;flex-direction:column;gap:var(--shell-gap);padding:var(--section-padding);flex:1;min-width:0}.ceu{box-sizing:border-box;min-height:100svh;display:flex;align-items:center;justify-content:center;padding:var(--section-padding)}.cek{box-sizing:border-box;width:100%;max-width:var(--section-auth-card-max-width);padding:var(--shell-gap-lg);background:var(--shell-background);border:1px solid var(--shell-border);border-radius:var(--shell-radius);box-shadow:var(--shell-shadow);display:flex;flex-direction:column;gap:var(--shell-gap)}.ceh{display:flex;flex-direction:column;gap:var(--shell-gap-sm)}.cec{text-align:center;align-items:center}.cei{display:flex;margin-bottom:var(--shell-gap-sm)}.cec .cei{justify-content:center}.cet{margin:0;font-size:var(--section-title-size);font-weight:var(--shell-font-weight);letter-spacing:-.02em;color:var(--shell-color);line-height:1.25}.ced{font-size:var(--section-title-size-md)}.cee{margin:0;font-size:var(--shell-font-size);color:var(--shell-color-muted);line-height:1.45}.ceb{display:flex;flex-direction:column;gap:var(--shell-gap);width:100%;text-align:left}.ces{display:flex;flex-direction:column;gap:var(--shell-gap-sm);width:100%}.cel{display:flex;flex-direction:column;gap:var(--shell-gap);margin-bottom:var(--shell-gap-lg);padding-bottom:var(--shell-gap-lg);border-bottom:1px solid var(--shell-border)}.cel:last-of-type{margin-bottom:0;padding-bottom:0;border-bottom:none}.cel .cet{font-size:var(--shell-font-size);font-weight:var(--shell-font-weight)}}
54
54
 
55
- @layer elcrm-components{.c2r{box-sizing:border-box;display:flex;flex-direction:column;flex:1 1 auto;width:var(--sidebar-width, 248px);min-width:0;min-height:0;height:100%;max-height:100%;padding:var(--sidebar-pad-y, 16px) var(--sidebar-pad-x, 12px);gap:var(--shell-gap-sm, 8px);color:var(--shell-color);align-self:stretch}.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);border:1px solid var(--sidebar-block-border);border-radius:var(--sidebar-block-radius);box-shadow:var(--sidebar-block-shadow)}.c2h{margin:2px 10px 6px;font-size:var(--sidebar-group-font-size);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);border:0;border-radius:8px;background:transparent;color:var(--shell-color-muted);font-family:inherit;font-size:var(--sidebar-item-font-size);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);background:var(--sidebar-item-active-bg)}.c2o{display:inline-flex;flex-shrink:0;align-items:center;justify-content:center;width:var(--sidebar-icon-size);height:var(--sidebar-icon-size);color:inherit}.c2o :is(svg){display:block;width:var(--sidebar-icon-size);height:var(--sidebar-icon-size)}.c2a .c2o{color:var(--sidebar-icon-active)}.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}.c2q{display:flex;width:100%;min-width:0}.c2q>*{display:flex;width:100%;min-width:0}.c2w{display:flex;width:100%;min-width:0;align-items:center}.c2u{display:flex;align-items:center;width:100%;min-width:0;gap:var(--shell-gap-sm);margin:0;padding:0;border:none;background:transparent;font:inherit;color:inherit;cursor:pointer;text-align:left}.c2k{flex-shrink:0;width:var(--sidebar-icon-size);height:var(--sidebar-icon-size);color:var(--shell-color-muted)}.c2v{margin-top:var(--shell-gap-sm);font-size:11px;color:var(--shell-color-muted);text-align:center}@media (max-width: 900px){.c2r{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}}}
55
+ @layer elcrm-components{.c2r{box-sizing:border-box;display:flex;flex-direction:column;flex:1 1 auto;width:var(--sidebar-width, 248px);min-width:0;min-height:0;height:100%;max-height:100%;padding:var(--sidebar-pad-y, 16px) var(--sidebar-pad-x, 12px);gap:var(--shell-gap-sm, 8px);color:var(--shell-color);align-self:stretch}.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);border:1px solid var(--sidebar-block-border);border-radius:var(--sidebar-block-radius);box-shadow:var(--sidebar-block-shadow)}.c2h{margin:2px 10px 6px;font-size:var(--sidebar-group-font-size);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);border:0;border-radius:8px;background:transparent;color:var(--shell-color-muted);font-family:inherit;font-size:var(--sidebar-item-font-size);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);background:var(--sidebar-item-active-bg)}.c2o{display:inline-flex;flex-shrink:0;align-items:center;justify-content:center;width:var(--sidebar-icon-size);height:var(--sidebar-icon-size);color:inherit}.c2o :is(svg){display:block;width:var(--sidebar-icon-size);height:var(--sidebar-icon-size)}.c2a .c2o{color:var(--sidebar-icon-active)}.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}.c2q{display:flex;width:100%;min-width:0;flex:0 0 auto;height:auto;align-items:center}.c2q>*{display:flex;width:100%;min-width:0;height:auto;align-items:center}.c2w{display:flex;width:100%;min-width:0;align-items:center}.c2u{display:flex;align-items:center;width:100%;min-width:0;gap:var(--shell-gap-sm);margin:0;padding:0;border:none;background:transparent;font:inherit;color:inherit;cursor:pointer;text-align:left}.c2k{flex-shrink:0;width:var(--sidebar-icon-size);height:var(--sidebar-icon-size);color:var(--shell-color-muted)}.c2v{margin-top:var(--shell-gap-sm);font-size:11px;color:var(--shell-color-muted);text-align:center}@media (max-width: 900px){.c2r{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}}}
56
56
 
57
57
  @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)}}
58
58
 
package/dist/index.d.ts CHANGED
@@ -74,7 +74,7 @@ export type { ChatFrameProps } from './ChatList';
74
74
  export { Sidebar } from './Sidebar';
75
75
  export type { SidebarProps, SidebarGroup, SidebarItem, SidebarVariant, } from './Sidebar';
76
76
  export { Popover } from './Popover';
77
- export type { PopoverProps } from './Popover';
77
+ export type { PopoverProps, PopoverPlacement } from './Popover';
78
78
  export { acquireOverlayZIndex, releaseOverlayZIndex, peekOverlayZIndex, } from './overlayZ';
79
79
  export { createLazyResolver } from './lazyRoute';
80
80
  export type { LazyRouteChunk } from './lazyRoute';
@@ -74,7 +74,7 @@ export type { ChatFrameProps } from './ChatList';
74
74
  export { Sidebar } from './Sidebar';
75
75
  export type { SidebarProps, SidebarGroup, SidebarItem, SidebarVariant, } from './Sidebar';
76
76
  export { Popover } from './Popover';
77
- export type { PopoverProps } from './Popover';
77
+ export type { PopoverProps, PopoverPlacement } from './Popover';
78
78
  export { acquireOverlayZIndex, releaseOverlayZIndex, peekOverlayZIndex, } from './overlayZ';
79
79
  export { createLazyResolver } from './lazyRoute';
80
80
  export type { LazyRouteChunk } from './lazyRoute';
package/dist/index.es.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { L as x } from "./Layout-mi6Ghayv.js";
2
- import { H as i } from "./Header-Cf28eyjW.js";
2
+ import { H as i } from "./Header-DZQopVNy.js";
3
3
  import { F as c } from "./Footer-qxUlnPR9.js";
4
4
  import { L as u } from "./List-BgKkYaGO.js";
5
5
  import { I as S } from "./Item-D4okhsfW.js";
@@ -13,7 +13,7 @@ import { R as g } from "./Row-DsQOVn18.js";
13
13
  import { C as F } from "./Column-BiogBDf8.js";
14
14
  import { S as H, s as M } from "./Stack-XkmPSswj.js";
15
15
  import { M as Z } from "./Menu-DuXQv-zT.js";
16
- import { D as z } from "./Dropdown-C6qlqMLV.js";
16
+ import { D as z } from "./Dropdown-B9AodUFf.js";
17
17
  import { B as E } from "./Breadcrumb-CAM_e9LN.js";
18
18
  import { L as j } from "./Loading-DkkG7RcE.js";
19
19
  import { S as K } from "./Section-Crxk2J-E.js";
@@ -33,8 +33,8 @@ import { P as Pr } from "./PageShell-D9EZiO8o.js";
33
33
  import { C as Ar, a as Br } from "./ChatSplit-DNnu3TNq.js";
34
34
  import { C as Ir } from "./ChatFrame-BW2TmCkZ.js";
35
35
  import { C as Rr } from "./ChatMessages-B8rdXiK-.js";
36
- import { S as Gr } from "./Sidebar-D7CTdu37.js";
37
- import { P as gr, a as kr, p as Fr, r as Nr } from "./Popover-5dFP4TXx.js";
36
+ import { S as Gr } from "./Sidebar-BSOLtF8H.js";
37
+ import { P as gr, a as kr, p as Fr, r as Nr } from "./Popover-D5RymtcJ.js";
38
38
  import { lazy as e } from "react";
39
39
  import { c as Mr } from "./cx-CcykAxZN.js";
40
40
  function s(a) {
package/dist/tokens.css CHANGED
@@ -32,6 +32,8 @@
32
32
  --header-shadow: none;
33
33
  --header-margin: 0;
34
34
  --header-z: 20;
35
+ /* shorthand: толщина + стиль + цвет, все стороны. Только снизу — `none` и линия через --header-shadow */
36
+ --header-border: 1px solid var(--shell-border);
35
37
 
36
38
  /* —— section / nav-sections —— */
37
39
  --section-padding: 1.5rem 1.75rem 2.5rem;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elcrm/components",
3
- "version": "0.2.3",
3
+ "version": "0.2.5",
4
4
  "description": "Shell UI elCRM: Layout, Header, Sidebar, Popover, PageHead, PageShell, Section, Stack, Stat, ActionGroup, TextGroup, ItemColumn и др.",
5
5
  "type": "module",
6
6
  "author": "MaSkal <dev@elcrm.online>",
@@ -1,23 +0,0 @@
1
- import e from "react";
2
- import { c as o } from "./cx-CcykAxZN.js";
3
- import './Header.css';const u = "chr", i = "chb", d = "chn", h = "chs", E = "cha", l = {
4
- r: u,
5
- b: i,
6
- n: d,
7
- s: h,
8
- a: E
9
- };
10
- function f({
11
- brand: c,
12
- nav: n,
13
- search: s,
14
- actions: t,
15
- children: a,
16
- className: r,
17
- ...m
18
- }) {
19
- return /* @__PURE__ */ e.createElement("header", { className: o(l.r, r), ...m }, c != null ? /* @__PURE__ */ e.createElement("div", { className: l.b }, c) : null, n != null ? /* @__PURE__ */ e.createElement("div", { className: l.n }, n) : null, s != null ? /* @__PURE__ */ e.createElement("div", { className: l.s }, s) : null, t != null ? /* @__PURE__ */ e.createElement("div", { className: l.a }, t) : null, a);
20
- }
21
- export {
22
- f as H
23
- };
@@ -1,149 +0,0 @@
1
- import l, { useRef as g, useId as j, useState as H, useLayoutEffect as S, useEffect as W } from "react";
2
- import { createPortal as G } from "react-dom";
3
- import { c as C } from "./cx-CcykAxZN.js";
4
- import { u as J } from "./useControllableValue-CWqH1kpM.js";
5
- import './Popover.css';const B = 1e3, Q = 10;
6
- function L() {
7
- const e = globalThis;
8
- return e.elcrm || (e.elcrm = {}), e.elcrm.overlayZ || (e.elcrm.overlayZ = { seq: 0, active: /* @__PURE__ */ new Set() }), e.elcrm.overlayZ;
9
- }
10
- function U() {
11
- const e = L();
12
- e.seq += 1;
13
- const n = B + e.seq * Q;
14
- return e.active.add(n), n;
15
- }
16
- function T(e) {
17
- const n = L();
18
- n.active.delete(e), n.active.size === 0 && (n.seq = 0);
19
- }
20
- function re() {
21
- const e = L();
22
- return e.active.size === 0 ? B : Math.max(...e.active);
23
- }
24
- const X = "c3r", Y = "c3t", _ = "c3p", b = {
25
- r: X,
26
- t: Y,
27
- p: _
28
- };
29
- function $(e, n, v, w) {
30
- if (!l.isValidElement(e)) return e;
31
- const u = e.props.onClick;
32
- return l.cloneElement(e, {
33
- "aria-haspopup": "menu",
34
- "aria-expanded": n,
35
- "aria-controls": n ? v : void 0,
36
- onClick: (p) => {
37
- u == null || u(p), w();
38
- }
39
- });
40
- }
41
- function se({
42
- trigger: e,
43
- children: n,
44
- open: v,
45
- defaultOpen: w = !1,
46
- onOpenChange: u,
47
- align: p = "end",
48
- disabled: M = !1,
49
- label: N,
50
- role: V = "menu",
51
- className: D,
52
- panelClassName: A
53
- }) {
54
- const h = g(null), R = g(null), E = j(), [o = !1, F] = J(
55
- v,
56
- w,
57
- u
58
- ), [i, z] = H(null), [a, P] = H(null), x = g(null);
59
- x.current = a;
60
- const y = (t) => {
61
- M && t || F(t);
62
- };
63
- S(() => {
64
- if (o) {
65
- a == null && P(U());
66
- return;
67
- }
68
- a != null && (T(a), P(null));
69
- }, [o, a]), W(() => () => {
70
- x.current != null && T(x.current);
71
- }, []);
72
- const Z = () => {
73
- const t = h.current;
74
- if (!t) return;
75
- const r = t.getBoundingClientRect(), s = 8, c = window.innerHeight - r.bottom - s - 8, d = r.top - s - 8, m = c >= 160 || c >= d, O = Math.min(420, Math.max(120, m ? c : d)), f = Math.max(200, r.width), q = p === "end" ? Math.max(8, Math.min(r.right - f, window.innerWidth - f - 8)) : Math.max(8, Math.min(r.left, window.innerWidth - f - 8));
76
- z(
77
- m ? { top: r.bottom + s, left: q, minWidth: f, maxHeight: O } : {
78
- bottom: window.innerHeight - r.top + s,
79
- left: q,
80
- minWidth: f,
81
- maxHeight: O
82
- }
83
- );
84
- };
85
- S(() => {
86
- if (!o) {
87
- z(null);
88
- return;
89
- }
90
- Z();
91
- const t = () => Z();
92
- return window.addEventListener("resize", t), window.addEventListener("scroll", t, !0), () => {
93
- window.removeEventListener("resize", t), window.removeEventListener("scroll", t, !0);
94
- };
95
- }, [o, p]), W(() => {
96
- if (!o) return;
97
- const t = (s) => {
98
- var d, m;
99
- const c = s.target;
100
- (d = h.current) != null && d.contains(c) || (m = R.current) != null && m.contains(c) || y(!1);
101
- }, r = (s) => {
102
- s.key === "Escape" && y(!1);
103
- };
104
- return document.addEventListener("mousedown", t), document.addEventListener("keydown", r), () => {
105
- document.removeEventListener("mousedown", t), document.removeEventListener("keydown", r);
106
- };
107
- }, [o]);
108
- const K = {
109
- position: "fixed",
110
- zIndex: a ?? 1e3,
111
- ...i ? {
112
- ...i.top != null ? { top: i.top } : { bottom: i.bottom },
113
- left: i.left,
114
- minWidth: i.minWidth,
115
- maxHeight: i.maxHeight
116
- } : { visibility: "hidden", pointerEvents: "none" }
117
- }, k = o ? /* @__PURE__ */ l.createElement(
118
- "div",
119
- {
120
- ref: R,
121
- id: E,
122
- role: V,
123
- "aria-label": N,
124
- className: C(b.p, A),
125
- style: K,
126
- onMouseDown: (t) => t.stopPropagation()
127
- },
128
- n
129
- ) : null, I = () => {
130
- M || y(!o);
131
- };
132
- return /* @__PURE__ */ l.createElement("div", { ref: h, className: C(b.r, D) }, /* @__PURE__ */ l.createElement(
133
- "div",
134
- {
135
- className: b.t,
136
- "aria-haspopup": "menu",
137
- "aria-expanded": o,
138
- "aria-controls": o ? E : void 0,
139
- onClick: l.isValidElement(e) ? void 0 : I
140
- },
141
- $(e, o, E, I)
142
- ), k && typeof document < "u" ? G(k, document.body) : null);
143
- }
144
- export {
145
- se as P,
146
- U as a,
147
- re as p,
148
- T as r
149
- };