@alphakits/ui 2.5.0 → 2.5.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.
@@ -1 +1 @@
1
- .container_WE0K{position:fixed;inset:0;display:flex;align-items:center;justify-content:center}.content_p1kc{background:var(--color-bg-primary);box-shadow:0 0 10px #0003}@media print{.content_p1kc{width:100%!important}}.button_js2W{position:absolute!important;top:34px;right:32px;z-index:999}.button_js2W.doubleModal_1ZTt{right:384px}.inner_Zsdb{height:100%;box-sizing:border-box;overflow:auto}.right_e065{position:fixed;top:0;right:0;bottom:0;transition:width .2s,opacity .2s,right .2s;transition-delay:width .1s;transition-timing-function:ease-in}.bg_8ZfP{transition:opacity .2s;background:#00000080;position:fixed;display:block;border:0;inset:0}@media screen and (max-width:823px){.right_e065,.center_nguy{max-width:100%!important;inset:0!important}.content_p1kc{width:100%!important;height:100%!important;max-height:100%!important;box-shadow:none!important;margin:0!important;border-radius:0!important}.button_js2W{top:24px!important;right:16px!important}}
1
+ .container_WE0K{position:fixed;inset:0;display:flex;align-items:center;justify-content:center}.content_p1kc{background:var(--color-bg-primary);box-shadow:0 0 10px #0003}@media print{.content_p1kc{width:100%!important}}.button_js2W{position:absolute!important;top:34px;right:32px;z-index:999}.button_js2W.doubleModal_1ZTt{right:384px}.inner_Zsdb{height:100%;box-sizing:border-box;overflow:auto}.right_e065{position:fixed;top:0;right:0;bottom:0;transition:width .2s,opacity .2s,right .2s;transition-delay:width .1s;transition-timing-function:ease-in}.bg_8ZfP{transition:opacity .2s;background:#00000080;position:fixed;display:block;border:0;inset:0}.bottomSheet_CI-8{inset:0!important;width:100%!important;max-width:100%!important;height:100dvh;max-height:100dvh;border-radius:0!important;overflow:hidden;transform:translateY(100%);transition:transform .25s cubic-bezier(.32,.72,0,1)}@supports not (height: 100dvh){.bottomSheet_CI-8{height:100vh;max-height:100vh}}.bottomSheet_CI-8.open_eGDW{transform:translateY(0)}@media screen and (max-width:823px){.right_e065,.center_nguy{max-width:100%!important;right:0!important;left:0!important}.content_p1kc{box-shadow:none!important;margin:0!important}.button_js2W{top:16px!important;right:16px!important}}
@@ -1,21 +1,25 @@
1
1
  import * as __css from './index.css';
2
2
  export const __cssModule = __css;
3
- const t = "container_WE0K", n = "content_p1kc", o = "button_js2W", e = "doubleModal_1ZTt", c = "inner_Zsdb", s = "right_e065", b = "bg_8ZfP", r = {
3
+ const t = "container_WE0K", o = "content_p1kc", n = "button_js2W", e = "doubleModal_1ZTt", c = "inner_Zsdb", s = "right_e065", b = "bg_8ZfP", r = "bottomSheet_CI-8", i = "open_eGDW", _ = {
4
4
  container: t,
5
- content: n,
6
- button: o,
5
+ content: o,
6
+ button: n,
7
7
  doubleModal: e,
8
8
  inner: c,
9
9
  right: s,
10
- bg: b
10
+ bg: b,
11
+ bottomSheet: r,
12
+ open: i
11
13
  };
12
14
  export {
13
15
  b as bg,
14
- o as button,
16
+ r as bottomSheet,
17
+ n as button,
15
18
  t as container,
16
- n as content,
17
- r as default,
19
+ o as content,
20
+ _ as default,
18
21
  e as doubleModal,
19
22
  c as inner,
23
+ i as open,
20
24
  s as right
21
25
  };
@@ -1,93 +1,159 @@
1
- import { jsxs as d, jsx as i } from "react/jsx-runtime";
2
- import y from "@alphakits/icons/dist/CloseM";
3
- import k from "classnames";
4
- import { useState as v, useLayoutEffect as x, useCallback as w, useEffect as E } from "react";
5
- import { Button as g } from "../../../button/component.js";
6
- import { showConfirm as F } from "../../../confirm-popup/component.js";
1
+ import { jsxs as E, jsx as l } from "react/jsx-runtime";
2
+ import O from "@alphakits/icons/dist/CloseM";
3
+ import C from "classnames";
4
+ import { useState as L, useRef as w, useLayoutEffect as N, useEffect as k, useCallback as S } from "react";
5
+ import { Button as z } from "../../../button/component.js";
6
+ import { showConfirm as j } from "../../../confirm-popup/component.js";
7
+ import { useMatchMedia as B } from "../../../mq/use-match-media.js";
7
8
  import s from "./index.module.css.js";
8
- const C = {
9
+ const R = {
9
10
  s: 488,
10
11
  m: 888,
11
12
  full: "96%"
12
- }, b = 102, N = (e) => e === "full" ? `calc(-96vw - ${b}px)` : -C[e] - b, j = ({ modal: e, t: r, index: m, dirtyModals: a, closeModal: l, currentModalId: c }) => {
13
- const f = N(e.props.size), [h, p] = v(f);
14
- x(() => {
15
- const o = requestAnimationFrame(() => p(0));
13
+ }, T = 102, D = "(max-width: 823px)", K = (e) => e === "full" ? `calc(-96vw - ${T}px)` : -R[e] - T, _ = [
14
+ 'a[href]:not([tabindex="-1"])',
15
+ 'area[href]:not([tabindex="-1"])',
16
+ 'button:not([disabled]):not([tabindex="-1"])',
17
+ 'input:not([disabled]):not([type="hidden"]):not([tabindex="-1"])',
18
+ 'select:not([disabled]):not([tabindex="-1"])',
19
+ 'textarea:not([disabled]):not([tabindex="-1"])',
20
+ '[contenteditable="true"]:not([tabindex="-1"])',
21
+ '[tabindex]:not([tabindex="-1"])',
22
+ 'iframe:not([tabindex="-1"])',
23
+ 'object:not([tabindex="-1"])',
24
+ 'embed:not([tabindex="-1"])',
25
+ 'audio[controls]:not([tabindex="-1"])',
26
+ 'video[controls]:not([tabindex="-1"])',
27
+ 'details > summary:first-of-type:not([tabindex="-1"])'
28
+ ].join(","), F = (e) => e ? Array.from(e.querySelectorAll(_)).filter((r) => {
29
+ if (r.hidden || r.getAttribute("aria-hidden") === "true") return !1;
30
+ const a = window.getComputedStyle(r);
31
+ return a.visibility === "hidden" || a.display === "none" ? !1 : r.offsetWidth > 0 || r.offsetHeight > 0 || r.getClientRects().length > 0;
32
+ }) : [], W = ({ modal: e, t: c, index: r, dirtyModals: a, closeModal: m, currentModalId: u }) => {
33
+ const A = K(e.props.size), [b] = B(D), [p, y] = L(!1), i = w(null), x = w(null);
34
+ N(() => {
35
+ const o = requestAnimationFrame(() => y(!0));
16
36
  return () => cancelAnimationFrame(o);
17
- }, [e.id]);
18
- const u = w(
19
- (o) => a[o] ? F({
20
- title: r("common:exitConfirm"),
21
- confirmText: r("common:Да"),
22
- cancelText: r("common:Нет"),
37
+ }, [e.id]), k(() => {
38
+ if (e.id !== u) return;
39
+ x.current = document.activeElement || null;
40
+ const o = setTimeout(() => {
41
+ const n = F(i.current)[0] || i.current;
42
+ n && typeof n.focus == "function" && n.focus({ preventScroll: !0 });
43
+ }, 50);
44
+ return () => {
45
+ clearTimeout(o);
46
+ const t = document.activeElement;
47
+ if (!t || !i.current?.contains(t)) return;
48
+ const n = x.current;
49
+ if (n && typeof n.focus == "function" && document.body.contains(n))
50
+ try {
51
+ n.focus({ preventScroll: !0 });
52
+ } catch {
53
+ document.body.focus();
54
+ }
55
+ };
56
+ }, [e.id, u]);
57
+ const h = S(
58
+ (o) => a[o] ? j({
59
+ title: c("common:exitConfirm"),
60
+ confirmText: c("common:Да"),
61
+ cancelText: c("common:Нет"),
23
62
  confirmView: "negative"
24
63
  }) : Promise.resolve(!0),
25
64
  // eslint-disable-next-line react-hooks/exhaustive-deps
26
- [a, r]
27
- ), t = w(
65
+ [a, c]
66
+ ), f = S(
28
67
  async (o) => {
29
- const { id: n } = e;
30
- await u(o || n) && (p(f), setTimeout(() => {
31
- e.props.closeCallback && e.props.closeCallback(), l(o || n);
68
+ const { id: t } = e;
69
+ await h(o || t) && (y(!1), setTimeout(() => {
70
+ e.props.closeCallback && e.props.closeCallback(), m(o || t);
32
71
  }, 250));
33
72
  },
34
- [l, u, e, f]
73
+ [m, h, e]
35
74
  );
36
- return E(() => {
37
- const o = (n) => {
38
- (n.key === "27" || n.key === "Escape") && t(c);
75
+ return k(() => {
76
+ const o = (t) => {
77
+ if (t.key === "27" || t.key === "Escape") {
78
+ f(u);
79
+ return;
80
+ }
81
+ if (t.key !== "Tab") return;
82
+ const n = F(i.current);
83
+ if (!n.length) {
84
+ t.preventDefault(), i.current && i.current.focus({ preventScroll: !0 });
85
+ return;
86
+ }
87
+ const v = n[0], g = n[n.length - 1], d = document.activeElement;
88
+ if (t.shiftKey && (d === v || !i.current?.contains(d))) {
89
+ t.preventDefault(), g.focus({ preventScroll: !0 });
90
+ return;
91
+ }
92
+ !t.shiftKey && (d === g || !i.current?.contains(d)) && (t.preventDefault(), v.focus({ preventScroll: !0 }));
39
93
  };
40
- return e.id === c && window?.addEventListener("keydown", o), () => {
94
+ return e.id === u && window?.addEventListener("keydown", o), () => {
41
95
  window?.removeEventListener("keydown", o);
42
96
  };
43
- }, [t, c, e.id]), /* @__PURE__ */ d(
97
+ }, [f, u, e.id]), /* @__PURE__ */ E(
44
98
  "div",
45
99
  {
46
100
  className: s.container,
47
101
  style: {
48
- zIndex: 9999998 + m
102
+ zIndex: 9999998 + r
49
103
  },
50
104
  children: [
51
- /* @__PURE__ */ i(
105
+ /* @__PURE__ */ l(
52
106
  "div",
53
107
  {
54
- className: k(s.right, s.content),
108
+ ref: i,
109
+ className: C(s.right, s.content, {
110
+ [s.open]: p,
111
+ [s.bottomSheet]: b
112
+ }),
55
113
  style: {
56
- zIndex: 9999999 + m,
57
- width: C[e.props.size],
58
- right: h
114
+ zIndex: 9999999 + r,
115
+ width: R[e.props.size],
116
+ // На десктопе right-slide управляется JS-ом (старая
117
+ // схема — анимация ширины и right'а синхронны). На
118
+ // мобиле right=0 всегда, а появление контролируется
119
+ // CSS-классом .open → transform: translateY(0).
120
+ right: b || p ? 0 : A
59
121
  },
60
- children: /* @__PURE__ */ d("div", { className: s.inner, children: [
61
- /* @__PURE__ */ i(
122
+ role: "dialog",
123
+ "aria-modal": "true",
124
+ "aria-labelledby": `modal-title-${e.id}`,
125
+ tabIndex: -1,
126
+ children: /* @__PURE__ */ E("div", { className: s.inner, children: [
127
+ /* @__PURE__ */ l(
62
128
  e.modal,
63
129
  {
64
130
  ...e.props,
65
131
  modalId: e.id,
66
- close: () => t()
132
+ close: () => f()
67
133
  }
68
134
  ),
69
- /* @__PURE__ */ i(
70
- g,
135
+ /* @__PURE__ */ l(
136
+ z,
71
137
  {
72
- className: k(s.button, {
138
+ className: C(s.button, {
73
139
  [s.doubleModal]: e.props.isDouble
74
140
  }),
75
141
  view: "secondary",
76
142
  size: "xs",
77
- leftAddons: /* @__PURE__ */ i(y, {}),
78
- onClick: () => t()
143
+ leftAddons: /* @__PURE__ */ l(O, {}),
144
+ onClick: () => f()
79
145
  }
80
146
  )
81
147
  ] })
82
148
  }
83
149
  ),
84
- /* @__PURE__ */ i(
150
+ /* @__PURE__ */ l(
85
151
  "button",
86
152
  {
87
153
  className: s.bg,
88
- "aria-label": "close_backdrop",
154
+ "aria-label": "Close dialog",
89
155
  type: "button",
90
- onClick: () => t()
156
+ onClick: () => f()
91
157
  }
92
158
  )
93
159
  ]
@@ -95,5 +161,5 @@ const C = {
95
161
  );
96
162
  };
97
163
  export {
98
- j as Modal
164
+ W as Modal
99
165
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alphakits/ui",
3
- "version": "2.5.0",
3
+ "version": "2.5.2",
4
4
  "files": [
5
5
  "dist"
6
6
  ],