urfu-ui-kit-react 2.0.6-next.1 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. package/README.md +155 -144
  2. package/dist/components/Accordion/Accordion.d.ts +1 -1
  3. package/dist/components/Accordion/Accordion.d.ts.map +1 -1
  4. package/dist/components/BreadCrumbs/BreadCrumbs.d.ts +1 -1
  5. package/dist/components/Button/Button.d.ts +1 -1
  6. package/dist/components/Calendar/Calendar.d.ts.map +1 -1
  7. package/dist/components/Calendar/Calendar.types.d.ts +2 -1
  8. package/dist/components/Calendar/Calendar.types.d.ts.map +1 -1
  9. package/dist/components/Card/Card.d.ts +1 -1
  10. package/dist/components/Checkbox/Checkbox.d.ts +1 -1
  11. package/dist/components/ColumnSettings/ColumnSettings.d.ts +1 -1
  12. package/dist/components/ErrorScreen/ErrorScreen.d.ts +16 -3
  13. package/dist/components/ErrorScreen/ErrorScreen.d.ts.map +1 -1
  14. package/dist/components/ErrorScreen/ErrorScreenIllustration.d.ts +17 -0
  15. package/dist/components/ErrorScreen/ErrorScreenIllustration.d.ts.map +1 -0
  16. package/dist/components/FormField/FormField.d.ts +1 -1
  17. package/dist/components/Icon/Icon.d.ts +2 -2
  18. package/dist/components/Icon/Icon.d.ts.map +1 -1
  19. package/dist/components/Icon/Icon.types.d.ts +5 -0
  20. package/dist/components/Icon/Icon.types.d.ts.map +1 -1
  21. package/dist/components/InputExpandTextarea/InputExpandTextarea.d.ts +1 -1
  22. package/dist/components/InputExpandTextarea/InputExpandTextarea.d.ts.map +1 -1
  23. package/dist/components/InputExpandTextarea/InputExpandTextarea.types.d.ts +2 -1
  24. package/dist/components/InputExpandTextarea/InputExpandTextarea.types.d.ts.map +1 -1
  25. package/dist/components/InputFile/InputFile.d.ts +1 -1
  26. package/dist/components/InputNumber/InputNumber.d.ts +2 -2
  27. package/dist/components/InputNumber/InputNumber.d.ts.map +1 -1
  28. package/dist/components/InputNumber/InputNumber.types.d.ts +6 -0
  29. package/dist/components/InputNumber/InputNumber.types.d.ts.map +1 -1
  30. package/dist/components/InputText/InputAffix.d.ts +47 -0
  31. package/dist/components/InputText/InputAffix.d.ts.map +1 -0
  32. package/dist/components/InputText/InputText.d.ts +3 -2
  33. package/dist/components/InputText/InputText.d.ts.map +1 -1
  34. package/dist/components/InputText/InputText.types.d.ts +40 -1
  35. package/dist/components/InputText/InputText.types.d.ts.map +1 -1
  36. package/dist/components/InputTime/InputTime.d.ts +2 -2
  37. package/dist/components/InputTime/InputTime.d.ts.map +1 -1
  38. package/dist/components/InputTime/InputTime.types.d.ts +8 -1
  39. package/dist/components/InputTime/InputTime.types.d.ts.map +1 -1
  40. package/dist/components/Menu/Menu.d.ts +1 -1
  41. package/dist/components/Message/Message.d.ts +1 -1
  42. package/dist/components/Modal/Modal.d.ts +1 -1
  43. package/dist/components/Modal/Modal.d.ts.map +1 -1
  44. package/dist/components/Multiselect/Multiselect.d.ts +2 -2
  45. package/dist/components/Multiselect/Multiselect.d.ts.map +1 -1
  46. package/dist/components/Multiselect/Multiselect.types.d.ts +8 -1
  47. package/dist/components/Multiselect/Multiselect.types.d.ts.map +1 -1
  48. package/dist/components/Notification/Notification.d.ts +24 -3
  49. package/dist/components/Notification/Notification.d.ts.map +1 -1
  50. package/dist/components/Preloader/Preloader.d.ts +1 -1
  51. package/dist/components/Radio/Radio.d.ts +1 -1
  52. package/dist/components/Search/Search.d.ts +2 -2
  53. package/dist/components/Search/Search.d.ts.map +1 -1
  54. package/dist/components/Search/Search.types.d.ts +6 -0
  55. package/dist/components/Search/Search.types.d.ts.map +1 -1
  56. package/dist/components/SearchSelect/SearchSelect.d.ts +1 -1
  57. package/dist/components/SearchSelect/SearchSelect.d.ts.map +1 -1
  58. package/dist/components/SearchSelect/SearchSelect.types.d.ts +2 -1
  59. package/dist/components/SearchSelect/SearchSelect.types.d.ts.map +1 -1
  60. package/dist/components/Select/Select.d.ts +1 -1
  61. package/dist/components/Select/Select.d.ts.map +1 -1
  62. package/dist/components/Select/Select.types.d.ts +2 -1
  63. package/dist/components/Select/Select.types.d.ts.map +1 -1
  64. package/dist/components/Status/Status.d.ts +1 -1
  65. package/dist/components/StickyActionBar/StickyActionBar.d.ts +1 -1
  66. package/dist/components/Switch/Switch.d.ts +2 -2
  67. package/dist/components/Table/Filter/Filter.d.ts +1 -1
  68. package/dist/components/Table/Filter/Filter.d.ts.map +1 -1
  69. package/dist/components/Table/Filter/FilterBoxShell.d.ts.map +1 -1
  70. package/dist/components/Table/Filter/FilterSortIndicator.d.ts.map +1 -1
  71. package/dist/components/Table/Table.d.ts +2 -2
  72. package/dist/components/Table/Table.d.ts.map +1 -1
  73. package/dist/components/Table/Table.types.d.ts +8 -0
  74. package/dist/components/Table/Table.types.d.ts.map +1 -1
  75. package/dist/components/Table/TableHead.d.ts.map +1 -1
  76. package/dist/components/Table/useDelayedSkeleton.d.ts +23 -0
  77. package/dist/components/Table/useDelayedSkeleton.d.ts.map +1 -0
  78. package/dist/components/Table/useTableColumnPinning.d.ts.map +1 -1
  79. package/dist/components/Table/useTableSortState.d.ts.map +1 -1
  80. package/dist/components/Table/useTableVirtualization.d.ts.map +1 -1
  81. package/dist/components/Tabs/Tabs.d.ts +1 -1
  82. package/dist/components/Tabs/Tabs.d.ts.map +1 -1
  83. package/dist/components/Tabs/Tabs.types.d.ts +20 -2
  84. package/dist/components/Tabs/Tabs.types.d.ts.map +1 -1
  85. package/dist/components/Tabs/distributeTabs.d.ts +14 -2
  86. package/dist/components/Tabs/distributeTabs.d.ts.map +1 -1
  87. package/dist/components/Tabs/useTabsOverflow.d.ts +4 -0
  88. package/dist/components/Tabs/useTabsOverflow.d.ts.map +1 -1
  89. package/dist/components/Textarea/Textarea.d.ts +2 -2
  90. package/dist/components/Textarea/Textarea.d.ts.map +1 -1
  91. package/dist/components/Textarea/Textarea.types.d.ts +8 -1
  92. package/dist/components/Textarea/Textarea.types.d.ts.map +1 -1
  93. package/dist/components/Tooltip/Tooltip.d.ts +1 -1
  94. package/dist/components/Tooltip/Tooltip.d.ts.map +1 -1
  95. package/dist/components/TreeView/TreeView.d.ts +1 -1
  96. package/dist/components/TreeView/TreeView.d.ts.map +1 -1
  97. package/dist/components/TreeView/TreeView.types.d.ts +2 -1
  98. package/dist/components/TreeView/TreeView.types.d.ts.map +1 -1
  99. package/dist/dev/index.js +838 -0
  100. package/dist/dev/types/react/src/dev/index.d.ts +15 -0
  101. package/dist/dev/types/vanilla/src/dev/index.d.ts +17 -0
  102. package/dist/dev/types/vanilla/src/dev/intercept.d.ts +32 -0
  103. package/dist/dev/types/vanilla/src/dev/journal.d.ts +29 -0
  104. package/dist/dev/types/vanilla/src/dev/panel.d.ts +8 -0
  105. package/dist/dev/types/vanilla/src/dev/shown.d.ts +24 -0
  106. package/dist/dev/types/vanilla/src/dev/store.d.ts +44 -0
  107. package/dist/dev/types/vanilla/src/dev/types.d.ts +83 -0
  108. package/dist/index.d.ts +7 -6
  109. package/dist/index.d.ts.map +1 -1
  110. package/dist/responsive/uiKitResponsive.d.ts +7 -0
  111. package/dist/responsive/uiKitResponsive.d.ts.map +1 -1
  112. package/dist/shared/popupTransition.d.ts +1 -1
  113. package/dist/shared/size.d.ts +15 -1
  114. package/dist/shared/size.d.ts.map +1 -1
  115. package/dist/shared/uiKitDefaults.d.ts +12 -0
  116. package/dist/shared/uiKitDefaults.d.ts.map +1 -1
  117. package/dist/style-no-fonts.css +1 -1
  118. package/dist/style.css +1 -1
  119. package/dist/style.layer.css +145 -0
  120. package/dist/style.shell.css +173 -0
  121. package/dist/urfu-ui-kit-react.js +7688 -7208
  122. package/dist/utils/describeError.d.ts +27 -0
  123. package/dist/utils/describeError.d.ts.map +1 -1
  124. package/package.json +113 -79
@@ -0,0 +1,838 @@
1
+ import { useSyncExternalStore as It } from "react";
2
+ let O = [], Mt = 1;
3
+ const H = /* @__PURE__ */ new Set();
4
+ let R = !1;
5
+ function _() {
6
+ R || (R = !0, setTimeout(() => {
7
+ R = !1, H.forEach((t) => t());
8
+ }, 16));
9
+ }
10
+ function zt(t, e, n) {
11
+ const a = Date.now(), s = { id: Mt++, service: t, method: e.toUpperCase(), path: n, status: "pending", duration: null, endedAt: null, faked: !1 };
12
+ O = [...O.slice(-49), s], _();
13
+ let o = !1;
14
+ return (i, r) => {
15
+ o || (o = !0, s.status = i, s.faked = r, s.endedAt = Date.now(), s.duration = s.endedAt - a, _());
16
+ };
17
+ }
18
+ function Q() {
19
+ return [...O].reverse();
20
+ }
21
+ function ct() {
22
+ O = [], R = !1, _();
23
+ }
24
+ function qt(t) {
25
+ return H.add(t), () => {
26
+ H.delete(t);
27
+ };
28
+ }
29
+ const ut = "urfu-ui-kit:dev:", v = /* @__PURE__ */ new Map(), W = /* @__PURE__ */ new Set();
30
+ let dt;
31
+ const ft = (t) => `${ut}${t}`, jt = ["offline", "network", "slow"];
32
+ let E = null;
33
+ const C = /* @__PURE__ */ new Set();
34
+ function Ut() {
35
+ let t;
36
+ try {
37
+ t = new URLSearchParams(window.location.search).get("dev");
38
+ } catch {
39
+ return;
40
+ }
41
+ if (t !== null) {
42
+ if (t === "off") {
43
+ E = null;
44
+ try {
45
+ Object.keys(localStorage).filter((e) => e.startsWith(ut)).forEach((e) => localStorage.removeItem(e));
46
+ } catch {
47
+ }
48
+ } else
49
+ E = t.split(",").map((e) => e.trim()).filter(Boolean), C.clear();
50
+ try {
51
+ const e = new URL(window.location.href);
52
+ e.searchParams.delete("dev"), window.history.replaceState(window.history.state, "", e.href);
53
+ } catch {
54
+ }
55
+ }
56
+ }
57
+ function Ft(t) {
58
+ return [...jt, ...t.builtins ?? [], ...(t.groups ?? []).flatMap((e) => e.items.map((n) => n.id))];
59
+ }
60
+ function Nt(t) {
61
+ if (!E || C.has(t.config.service)) return;
62
+ const e = new Set(Ft(t.config)), n = E.filter((a) => e.has(a));
63
+ n.length && (C.add(t.config.service), t.state = { ...t.state, faults: n }, F(t.config.service, t.state));
64
+ }
65
+ function Ht(t) {
66
+ try {
67
+ const e = JSON.parse(localStorage.getItem(ft(t)) ?? "null");
68
+ return {
69
+ faults: Array.isArray(e == null ? void 0 : e.faults) ? e.faults.filter((n) => typeof n == "string") : [],
70
+ rules: Array.isArray(e == null ? void 0 : e.rules) ? e.rules : [],
71
+ ...(e == null ? void 0 : e.launcher) === "visible" || (e == null ? void 0 : e.launcher) === "hidden" ? { launcher: e.launcher } : {}
72
+ };
73
+ } catch {
74
+ return { faults: [], rules: [] };
75
+ }
76
+ }
77
+ function F(t, e) {
78
+ try {
79
+ localStorage.setItem(ft(t), JSON.stringify(e));
80
+ } catch {
81
+ }
82
+ }
83
+ function _t(t) {
84
+ t && (dt = t);
85
+ }
86
+ function Wt() {
87
+ return dt;
88
+ }
89
+ function Bt(t) {
90
+ const e = { config: t, state: Ht(t.service) };
91
+ return Nt(e), v.set(t.service, e), P(), e;
92
+ }
93
+ function Kt(t) {
94
+ v.delete(t), v.size || (E = null, C.clear()), P();
95
+ }
96
+ function m() {
97
+ return [...v.values()];
98
+ }
99
+ function Jt(t) {
100
+ return t ? v.get(t) : v.values().next().value;
101
+ }
102
+ function pt(t) {
103
+ return W.add(t), () => {
104
+ W.delete(t);
105
+ };
106
+ }
107
+ function P() {
108
+ W.forEach((t) => t());
109
+ }
110
+ function N(t, e) {
111
+ t.state = e, F(t.config.service, e), P();
112
+ }
113
+ function Xt(t, e, n) {
114
+ const a = t.state.faults.filter((s) => s !== e);
115
+ N(t, { ...t.state, faults: n ? [...a, e] : a });
116
+ }
117
+ function Gt(t, e) {
118
+ const n = `rule-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 6)}`;
119
+ N(t, { ...t.state, rules: [...t.state.rules, { ...e, id: n, enabled: !0 }] });
120
+ }
121
+ function Yt(t, e, n) {
122
+ N(t, { ...t.state, rules: t.state.rules.map((a) => a.id === e ? { ...a, enabled: n } : a) });
123
+ }
124
+ function Vt(t, e) {
125
+ N(t, { ...t.state, rules: t.state.rules.filter((n) => n.id !== e) });
126
+ }
127
+ function Qt() {
128
+ v.forEach((t) => {
129
+ t.state = { faults: [], rules: [], ...t.state.launcher ? { launcher: t.state.launcher } : {} }, F(t.config.service, t.state);
130
+ }), P();
131
+ }
132
+ function I(t) {
133
+ return t.state.faults.length + t.state.rules.filter((e) => e.enabled).length;
134
+ }
135
+ function Zt(t) {
136
+ return t.state.launcher ?? t.config.launcher ?? "visible";
137
+ }
138
+ function tt(t) {
139
+ v.forEach((e) => {
140
+ e.state = { ...e.state, launcher: t }, F(e.config.service, e.state);
141
+ }), P();
142
+ }
143
+ const te = 1e4, et = 200, T = ".u-error-screen, .u-notification-fail, .u-notification-warning, .u-offline-banner-offline";
144
+ let M = [], ee = 1;
145
+ const B = /* @__PURE__ */ new WeakMap(), z = /* @__PURE__ */ new Set();
146
+ let w = null;
147
+ const x = (t) => {
148
+ const e = (t ?? "").replace(/\s+/g, " ").trim();
149
+ return e.length > et ? `${e.slice(0, et - 1)}…` : e;
150
+ }, ne = (t) => t.status === "network" || typeof t.status == "number" && t.status >= 400;
151
+ function ae(t, e) {
152
+ var r;
153
+ const n = m().map((l) => l.config.service), a = (r = e.closest("[data-name]")) == null ? void 0 : r.getAttribute("data-name"), s = a && n.includes(a) ? a : null, o = Q().find((l) => ne(l) && l.endedAt !== null && t - l.endedAt <= te && (!s || l.service === s));
154
+ if (!o) return;
155
+ const i = `${o.method} ${o.path} → ${o.status === "network" ? "сеть" : o.status}`;
156
+ return n.length > 1 ? `${o.service}: ${i}` : i;
157
+ }
158
+ function oe(t) {
159
+ var a, s, o;
160
+ if (t.classList.contains("u-error-screen"))
161
+ return {
162
+ kind: "screen",
163
+ // Код — в data-error-code на корне заглушки: крупный код рисуется не у всех вариантов (forbidden, serverError).
164
+ // .u-error-screen-code — для разметки кита до появления атрибута.
165
+ code: x(t.dataset.errorCode || ((a = t.querySelector(".u-error-screen-code")) == null ? void 0 : a.textContent)) || void 0,
166
+ title: x((s = t.querySelector(".u-error-screen-title")) == null ? void 0 : s.textContent) || x(t.getAttribute("aria-label")) || "Заглушка",
167
+ text: x((o = t.querySelector(".u-error-screen-description")) == null ? void 0 : o.textContent) || void 0
168
+ };
169
+ if (t.classList.contains("u-offline-banner-offline"))
170
+ return { kind: "offline", title: x(t.textContent) || "Нет связи" };
171
+ const e = t.classList.contains("u-notification-fail") ? "fail" : "warning", n = t.querySelector(".u-notification-content") ?? t;
172
+ return { kind: "notification", variant: e, title: x(n.textContent) || "Уведомление" };
173
+ }
174
+ function nt(t) {
175
+ if (!t.isConnected || !t.matches(T)) return;
176
+ const e = oe(t);
177
+ if (!e) return;
178
+ const n = JSON.stringify(e);
179
+ if (B.get(t) === n) return;
180
+ B.set(t, n);
181
+ const a = Date.now();
182
+ M = [...M.slice(-29), { id: ee++, at: a, ...e, cause: ae(a, t) }], z.forEach((s) => s());
183
+ }
184
+ function se(t, e) {
185
+ t instanceof Element && (t.matches(T) && e.push(t), t.querySelectorAll(T).forEach((n) => e.push(n)));
186
+ }
187
+ function re() {
188
+ w || typeof MutationObserver > "u" || (w = new MutationObserver((t) => {
189
+ const e = [];
190
+ t.forEach((n) => {
191
+ if (n.type === "childList") {
192
+ n.addedNodes.forEach((s) => se(s, e));
193
+ return;
194
+ }
195
+ const a = n.target;
196
+ a.matches(T) ? e.push(a) : B.delete(a);
197
+ }), e.length && setTimeout(() => e.forEach(nt), 0);
198
+ }), w.observe(document.documentElement, { childList: !0, subtree: !0, attributes: !0, attributeFilter: ["data-error-code", "class"] }), document.querySelectorAll(T).forEach(nt));
199
+ }
200
+ function ie() {
201
+ w == null || w.disconnect(), w = null;
202
+ }
203
+ function K() {
204
+ return [...M].reverse();
205
+ }
206
+ function ht() {
207
+ M = [], z.forEach((t) => t());
208
+ }
209
+ function le(t) {
210
+ return z.add(t), () => {
211
+ z.delete(t);
212
+ };
213
+ }
214
+ const bt = 4e3, ce = /* @__PURE__ */ new Set(["GET", "HEAD"]);
215
+ function ue(t, e) {
216
+ let n;
217
+ try {
218
+ n = new URL(t, window.location.href).pathname;
219
+ } catch {
220
+ return null;
221
+ }
222
+ if (!e) return n;
223
+ const a = e.replace(/\/+$/, ""), s = n.indexOf(a);
224
+ if (s < 0) return null;
225
+ const o = n.slice(s + a.length);
226
+ return o.startsWith("/") || o === "" ? o || "/" : null;
227
+ }
228
+ function de(t, e) {
229
+ const n = (i) => i.split("/").filter(Boolean), a = n(t.trim()), s = n(e), o = (i, r) => i === a.length ? r === s.length : a[i] === "**" ? o(i + 1, r) || r < s.length && o(i, r + 1) : r === s.length ? !1 : (a[i] === "*" || a[i] === s[r]) && o(i + 1, r + 1);
230
+ return o(0, 0);
231
+ }
232
+ function fe(t, e) {
233
+ var a;
234
+ const n = (a = t.method) == null ? void 0 : a.trim().toUpperCase();
235
+ return !n || n === "*" ? !0 : n === "WRITE" ? !ce.has(e) : n === e;
236
+ }
237
+ function pe(t, e) {
238
+ return t.html ? {
239
+ kind: "response",
240
+ delay: e,
241
+ status: t.status,
242
+ contentType: "text/html",
243
+ body: `<html><body><h1>${t.status} ${t.message ?? "Bad Gateway"}</h1></body></html>`
244
+ } : {
245
+ kind: "response",
246
+ delay: e,
247
+ status: t.status,
248
+ contentType: "application/json",
249
+ body: JSON.stringify({ statusCode: t.status, message: t.message ?? `Сбой из dev-панели: ${t.status}` })
250
+ };
251
+ }
252
+ function he(t) {
253
+ const e = new Set(t.state.faults);
254
+ return [...(t.config.groups ?? []).flatMap((a) => a.items).filter((a) => e.has(a.id)).flatMap((a) => [].concat(a.request ?? [])), ...t.state.rules.filter((a) => a.enabled)];
255
+ }
256
+ function gt(t) {
257
+ for (const e of m()) {
258
+ const n = ue(t, e.config.apiBase);
259
+ if (n !== null) return { entry: e, path: n };
260
+ }
261
+ return null;
262
+ }
263
+ function mt({ entry: t, path: e }, n) {
264
+ const a = n.toUpperCase(), s = new Set(t.state.faults), o = s.has("slow") ? bt : 0;
265
+ if (s.has("offline") || s.has("network")) return { kind: "network", delay: o };
266
+ const i = he(t).find((r) => fe(r, a) && de(r.path, e));
267
+ return i ? pe(i, o) : o ? { kind: "pass", delay: o } : null;
268
+ }
269
+ const vt = (t, e) => zt(t.entry.config.service, e, t.path), J = (t) => t.reason ?? new DOMException("The operation was aborted.", "AbortError");
270
+ function be(t, e) {
271
+ return new Promise((n, a) => {
272
+ if (e != null && e.aborted) {
273
+ a(J(e));
274
+ return;
275
+ }
276
+ const s = setTimeout(n, t);
277
+ e == null || e.addEventListener("abort", () => {
278
+ clearTimeout(s), a(J(e));
279
+ }, { once: !0 });
280
+ });
281
+ }
282
+ const wt = /* @__PURE__ */ new Set([204, 205, 304]);
283
+ let at = !1;
284
+ function ge() {
285
+ at || typeof window > "u" || (at = !0, me(), we());
286
+ }
287
+ function me() {
288
+ var e;
289
+ const t = (e = window.fetch) == null ? void 0 : e.bind(window);
290
+ t && (window.fetch = async (n, a) => {
291
+ const s = typeof n == "object" && "url" in n ? n : null, o = gt(s ? s.url : String(n));
292
+ if (!o) return t(n, a);
293
+ const i = (a == null ? void 0 : a.method) ?? (s == null ? void 0 : s.method) ?? "GET", r = vt(o, i), l = mt(o, i), f = (a == null ? void 0 : a.signal) ?? (s == null ? void 0 : s.signal);
294
+ try {
295
+ if (l != null && l.delay && await be(l.delay, f), f != null && f.aborted) throw J(f);
296
+ if ((l == null ? void 0 : l.kind) === "network")
297
+ throw r("network", !0), new TypeError("Failed to fetch");
298
+ if ((l == null ? void 0 : l.kind) === "response")
299
+ return r(l.status, !0), new Response(wt.has(l.status) ? null : l.body, {
300
+ status: l.status,
301
+ headers: { "Content-Type": l.contentType }
302
+ });
303
+ const p = await t(n, a);
304
+ return r(p.status, !1), p;
305
+ } catch (p) {
306
+ throw r(f != null && f.aborted ? "abort" : "network", !1), p;
307
+ }
308
+ });
309
+ }
310
+ const ot = /* @__PURE__ */ new WeakMap(), st = /* @__PURE__ */ new WeakMap(), q = /* @__PURE__ */ new WeakMap(), ve = ["readyState", "responseURL", "status", "statusText", "responseText", "response", "getAllResponseHeaders", "getResponseHeader"];
311
+ function we() {
312
+ if (typeof XMLHttpRequest > "u") return;
313
+ const t = XMLHttpRequest.prototype, e = t.open, n = t.send, a = t.abort;
314
+ t.open = function(o, i, ...r) {
315
+ rt(this), ve.forEach((l) => {
316
+ Reflect.deleteProperty(this, l);
317
+ }), ot.set(this, { method: o, url: String(i) }), e.call(this, o, i, ...r);
318
+ }, t.send = function(o) {
319
+ const i = ot.get(this), r = i ? gt(i.url) : null;
320
+ if (!i || !r) {
321
+ n.call(this, o);
322
+ return;
323
+ }
324
+ const l = vt(r, i.method);
325
+ st.set(this, l);
326
+ const f = mt(r, i.method), p = () => {
327
+ this.addEventListener("abort", () => l("abort", !1), { once: !0 }), this.addEventListener("loadend", () => l(this.status || "network", !1), { once: !0 }), n.call(this, o);
328
+ };
329
+ if (!f) {
330
+ p();
331
+ return;
332
+ }
333
+ q.set(this, setTimeout(() => {
334
+ if (q.delete(this), f.kind === "pass") {
335
+ p();
336
+ return;
337
+ }
338
+ l(f.kind === "network" ? "network" : f.status, !0), xe(this, f, i.url);
339
+ }, f.delay));
340
+ }, t.abort = function() {
341
+ var i;
342
+ if (!rt(this)) {
343
+ a.call(this);
344
+ return;
345
+ }
346
+ (i = st.get(this)) == null || i("abort", !1);
347
+ const o = xt(this);
348
+ o("readyState", 4), o("status", 0), X(this, ["readystatechange", "abort", "loadend"]), o("readyState", 0);
349
+ };
350
+ }
351
+ function rt(t) {
352
+ const e = q.get(t);
353
+ return e === void 0 ? !1 : (clearTimeout(e), q.delete(t), !0);
354
+ }
355
+ const xt = (t) => (e, n) => {
356
+ Object.defineProperty(t, e, { configurable: !0, get: () => n });
357
+ }, X = (t, e) => {
358
+ e.forEach((n) => t.dispatchEvent(new ProgressEvent(n)));
359
+ };
360
+ function xe(t, e, n) {
361
+ const a = xt(t);
362
+ if (a("readyState", 4), a("responseURL", n), e.kind === "network") {
363
+ a("status", 0), a("statusText", ""), X(t, ["readystatechange", "error", "loadend"]);
364
+ return;
365
+ }
366
+ const s = wt.has(e.status) ? "" : e.body;
367
+ let o = s;
368
+ if (t.responseType === "json")
369
+ try {
370
+ o = e.contentType === "application/json" && s ? JSON.parse(s) : null;
371
+ } catch {
372
+ o = null;
373
+ }
374
+ a("status", e.status), a("statusText", String(e.status)), a("responseText", s), a("response", o);
375
+ const i = `content-type: ${e.contentType}\r
376
+ `;
377
+ Object.defineProperty(t, "getAllResponseHeaders", { configurable: !0, value: () => i }), Object.defineProperty(t, "getResponseHeader", {
378
+ configurable: !0,
379
+ value: (r) => r.toLowerCase() === "content-type" ? e.contentType : null
380
+ }), X(t, ["readystatechange", "load", "loadend"]);
381
+ }
382
+ function Z(t) {
383
+ try {
384
+ t ? Reflect.deleteProperty(navigator, "onLine") : Object.defineProperty(navigator, "onLine", { configurable: !0, get: () => !1 }), window.dispatchEvent(new Event(t ? "online" : "offline"));
385
+ } catch {
386
+ }
387
+ }
388
+ function yt() {
389
+ const t = m().some((e) => e.state.faults.includes("offline"));
390
+ Qt(), ct(), ht(), t && Z(!0);
391
+ }
392
+ const ye = {
393
+ title: "Сеть",
394
+ items: [
395
+ { id: "offline", label: "Офлайн браузера", hint: "Полоса «Нет связи», запросы к API падают" },
396
+ { id: "network", label: "Обрыв соединения", hint: "Сеть есть, а сервер не отвечает" },
397
+ { id: "slow", label: "Медленные ответы", hint: `Задержка ${bt / 1e3} с на запросы к API` }
398
+ ]
399
+ }, $e = {
400
+ authFail: { label: "Сбой входа", hint: "После перезагрузки сервис рисует заглушку входа" },
401
+ crashApp: { label: "Падение приложения", hint: "Ошибка рендера над каркасом сервиса" },
402
+ crashPage: { label: "Падение страницы", hint: "Каждая открытая страница падает, пока флаг включён" }
403
+ }, G = [["", "Любой"], ["GET", "GET"], ["write", "Запись"], ["POST", "POST"], ["PUT", "PUT"], ["PATCH", "PATCH"], ["DELETE", "DELETE"]], Se = [400, 401, 403, 404, 409, 422, 429, 500, 502, 503, 504], d = (t) => String(t ?? "").replace(/[&<>"']/g, (e) => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" })[e]), ke = `
404
+ :host { all: initial; }
405
+ * { box-sizing: border-box; }
406
+ .root { --p: #1e4391; --p-soft: #e8eef9; --fg: #222; --muted: #6b7280; --line: #d9dee8; --bg: #fff; --soft: #f5f7fb;
407
+ --danger: #d6342c; --danger-soft: #fdeceb;
408
+ font-family: Montserrat, "Segoe UI", Arial, sans-serif; font-size: 13px; line-height: 1.4; color: var(--fg); }
409
+ button, input, select { font: inherit; color: inherit; }
410
+ .pill { position: fixed; left: 12px; bottom: calc(12px + env(safe-area-inset-bottom, 0px)); z-index: 2147483000;
411
+ display: inline-flex; align-items: center; gap: 6px; height: 28px; padding: 0 10px; border: 0; border-radius: 14px;
412
+ background: #222; color: #fff; font-size: 12px; font-weight: 600; cursor: pointer; box-shadow: 0 4px 14px rgba(0,0,0,.2); opacity: .85; }
413
+ .pill:hover, .pill:focus-visible { opacity: 1; }
414
+ .pill.on { background: var(--danger); opacity: 1; }
415
+ .pill .dot { width: 7px; height: 7px; border-radius: 50%; background: #4ade80; }
416
+ .pill.on .dot { background: #fff; }
417
+ .panel { position: fixed; left: 12px; bottom: calc(48px + env(safe-area-inset-bottom, 0px)); z-index: 2147483001;
418
+ width: 360px; max-width: calc(100vw - 24px); max-height: min(70vh, 640px); display: flex; flex-direction: column;
419
+ background: var(--bg); border: 1px solid var(--line); border-radius: 12px; box-shadow: 0 12px 32px rgba(16,24,40,.25); }
420
+ .panel.alone { bottom: calc(12px + env(safe-area-inset-bottom, 0px)); }
421
+ .hint { position: fixed; left: 12px; bottom: calc(12px + env(safe-area-inset-bottom, 0px)); z-index: 2147483000;
422
+ max-width: calc(100vw - 24px); padding: 8px 12px; border-radius: 10px; background: #222; color: #fff; font-size: 12px;
423
+ box-shadow: 0 4px 14px rgba(0,0,0,.2); }
424
+ .note { margin: 0 12px 8px; padding: 6px 10px; border-radius: 8px; background: var(--p-soft); color: var(--fg); font-size: 12px; overflow-wrap: anywhere; }
425
+ .pill ~ .hint { bottom: calc(48px + env(safe-area-inset-bottom, 0px)); }
426
+ .head { display: flex; align-items: center; gap: 8px; padding: 10px 12px 8px; }
427
+ .title { flex: 1; min-width: 0; font-weight: 700; font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
428
+ .title select { font-weight: 700; border: 1px solid var(--line); border-radius: 6px; padding: 2px 4px; background: var(--bg); max-width: 100%; }
429
+ .reset { border: 0; border-radius: 6px; padding: 5px 10px; background: var(--danger-soft); color: var(--danger); font-weight: 600; font-size: 12px; cursor: pointer; }
430
+ .close { width: 26px; height: 26px; border: 0; border-radius: 6px; background: none; color: var(--muted); font-size: 18px; line-height: 1; cursor: pointer; }
431
+ .escape { padding: 0 12px 6px; color: var(--muted); font-size: 11px; }
432
+ .tabs { display: flex; gap: 4px; padding: 0 12px; border-bottom: 1px solid var(--line); }
433
+ .tab { border: 0; background: none; padding: 6px 8px; font-weight: 600; font-size: 12px; color: var(--muted); border-bottom: 2px solid transparent; cursor: pointer; }
434
+ .tab[aria-selected="true"] { color: var(--p); border-color: var(--p); }
435
+ .body { overflow: auto; padding: 8px 12px 10px; display: flex; flex-direction: column; gap: 10px; }
436
+ .search { width: 100%; padding: 6px 10px; border: 1px solid var(--line); border-radius: 8px; background: var(--soft); }
437
+ .group-title { margin: 2px 0 2px; font-size: 11px; font-weight: 600; letter-spacing: .05em; text-transform: uppercase; color: var(--muted); }
438
+ .row { display: flex; align-items: center; gap: 10px; padding: 4px 0; cursor: pointer; }
439
+ .row .text { flex: 1; min-width: 0; }
440
+ .row small { display: block; color: var(--muted); font-size: 11px; }
441
+ .switch { appearance: none; flex: none; width: 30px; height: 18px; border-radius: 9px; background: var(--line); position: relative; margin: 0; cursor: pointer; }
442
+ .switch::after { content: ''; position: absolute; top: 2px; left: 2px; width: 14px; height: 14px; border-radius: 50%; background: #fff; box-shadow: 0 1px 2px rgba(0,0,0,.3); transition: left .12s; }
443
+ .switch:checked { background: var(--danger); }
444
+ .switch:checked::after { left: 14px; }
445
+ .switch:focus-visible, button:focus-visible, select:focus-visible, input:focus-visible { outline: 2px solid var(--p); outline-offset: 2px; }
446
+ .rule { display: flex; align-items: center; gap: 8px; padding: 5px 8px; border-radius: 8px; background: var(--soft); font-family: Consolas, monospace; font-size: 12px; }
447
+ .rule .text { flex: 1; min-width: 0; overflow-wrap: anywhere; }
448
+ .remove { border: 0; background: none; color: var(--muted); font-size: 16px; line-height: 1; cursor: pointer; padding: 0 2px; }
449
+ .add { display: grid; grid-template-columns: auto 1fr auto auto; gap: 6px; }
450
+ .add select, .add input { min-width: 0; padding: 5px 6px; border: 1px solid var(--line); border-radius: 6px; background: var(--bg); font-size: 12px; }
451
+ .btn { border: 1px solid var(--line); border-radius: 6px; background: var(--bg); padding: 5px 10px; font-size: 12px; font-weight: 600; cursor: pointer; }
452
+ .btn.primary { background: var(--p); border-color: var(--p); color: #fff; }
453
+ .foot { display: flex; gap: 6px; flex-wrap: wrap; padding: 8px 12px; border-top: 1px solid var(--line); }
454
+ .empty { color: var(--muted); font-size: 12px; }
455
+ .requests { display: flex; flex-direction: column; gap: 2px; }
456
+ .req { display: grid; grid-template-columns: 52px 1fr auto auto; gap: 8px; align-items: center; padding: 4px 0;
457
+ border-bottom: 1px solid var(--soft); font-family: Consolas, monospace; font-size: 12px; }
458
+ .req .path { min-width: 0; overflow-wrap: anywhere; }
459
+ .req .status { font-weight: 700; }
460
+ .req .status.bad { color: var(--danger); }
461
+ .req small { display: block; color: var(--muted); font-family: Montserrat, "Segoe UI", Arial, sans-serif; font-size: 11px; }
462
+ .req .btn { padding: 3px 8px; font-family: Montserrat, "Segoe UI", Arial, sans-serif; }
463
+ .shown { padding: 6px 0; border-bottom: 1px solid var(--soft); }
464
+ .shown-head { display: flex; justify-content: space-between; gap: 8px; color: var(--muted); font-size: 11px; }
465
+ .shown-head .kind { font-weight: 600; color: var(--danger); }
466
+ .shown-head .kind.warning { color: #b45309; }
467
+ .shown-title { font-weight: 600; }
468
+ .shown small { display: block; color: var(--muted); font-size: 11px; }
469
+ .shown .cause { margin-top: 2px; font-family: Consolas, monospace; font-size: 12px; }
470
+ .requests-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; color: var(--muted); font-size: 11px; }
471
+ dl { display: grid; grid-template-columns: auto 1fr; gap: 6px 12px; margin: 0; }
472
+ dt { color: var(--muted); }
473
+ dd { margin: 0; font-family: Consolas, monospace; font-size: 12px; overflow-wrap: anywhere; }
474
+ @media (max-width: 576px) {
475
+ .panel { left: 0; right: 0; bottom: 0; width: auto; max-width: none; max-height: 70vh; border-radius: 14px 14px 0 0;
476
+ padding-bottom: env(safe-area-inset-bottom, 0px); }
477
+ .panel ~ .pill { display: none; }
478
+ }
479
+ @media (prefers-reduced-motion: reduce) { .switch::after { transition: none; } }
480
+ `, Ee = 6e3;
481
+ let Y, h = null, u = null, S = null, y = null, L = !1, k = !1;
482
+ const $t = { open: !1, tab: "faults", search: "", service: void 0, hint: "" }, c = { ...$t };
483
+ function D() {
484
+ const t = m();
485
+ return t.find((e) => e.config.service === c.service) ?? t[0];
486
+ }
487
+ function St(t) {
488
+ const e = (t.config.builtins ?? []).map((n) => ({ id: n, ...$e[n] }));
489
+ return [
490
+ ...e.length ? [{ title: "Весь сервис", items: e }] : [],
491
+ ye,
492
+ ...t.config.groups ?? []
493
+ ];
494
+ }
495
+ function Te(t, e) {
496
+ var n;
497
+ return ((n = St(t).flatMap((a) => a.items).find((a) => a.id === e)) == null ? void 0 : n.label) ?? e;
498
+ }
499
+ function kt(t) {
500
+ return [
501
+ ...t.state.faults.map((e) => Te(t, e)),
502
+ ...t.state.rules.filter((e) => e.enabled).map((e) => `${e.path} → ${e.status}`)
503
+ ];
504
+ }
505
+ function Le(t, e, n, a) {
506
+ const s = t % 100, o = t % 10;
507
+ return s >= 11 && s <= 14 ? a : o === 1 ? e : o >= 2 && o <= 4 ? n : a;
508
+ }
509
+ const it = (t) => !c.search || t.toLowerCase().includes(c.search.toLowerCase());
510
+ function Ae(t) {
511
+ const e = new Set(t.state.faults), n = St(t).map((o) => {
512
+ const i = o.items.filter((r) => it(`${r.label} ${r.hint ?? ""} ${r.id}`));
513
+ return i.length ? `<div><div class="group-title">${d(o.title)}</div>${i.map((r) => `
514
+ <label class="row"><span class="text">${d(r.label)}${r.hint ? `<small>${d(r.hint)}</small>` : ""}</span>
515
+ <input class="switch" type="checkbox" role="switch" data-fault="${d(r.id)}" ${e.has(r.id) ? "checked" : ""}
516
+ aria-label="${d(r.label)}"></label>`).join("")}</div>` : "";
517
+ }).join(""), a = t.state.rules.filter((o) => it(`${o.method ?? ""} ${o.path} ${o.status}`)), s = (o) => {
518
+ var i;
519
+ return ((i = G.find(([r]) => r === (o ?? ""))) == null ? void 0 : i[1]) ?? o;
520
+ };
521
+ return `
522
+ <input class="search" type="search" data-search placeholder="Поиск: 503, офлайн, роли…" aria-label="Поиск по сценариям" value="${d(c.search)}">
523
+ ${n || (a.length ? "" : '<div class="empty">Ничего не найдено.</div>')}
524
+ <div><div class="group-title">Ответы сервера</div>
525
+ ${a.map((o) => `<div class="rule"><span class="text">${d(s(o.method))} ${d(o.path)} → ${o.status}</span>
526
+ <input class="switch" type="checkbox" role="switch" data-rule="${d(o.id)}" ${o.enabled ? "checked" : ""}
527
+ aria-label="${d(`${o.path} → ${o.status}`)}">
528
+ <button class="remove" type="button" data-remove="${d(o.id)}" aria-label="Удалить правило">×</button></div>`).join("")}
529
+ <form class="add" data-add>
530
+ <select name="method" aria-label="Метод">${G.map(([o, i]) => `<option value="${o}">${i}</option>`).join("")}</select>
531
+ <input name="path" required placeholder="/assets/*" aria-label="Путь после ${d(t.config.apiBase ?? "адреса сайта")}">
532
+ <select name="status" aria-label="Код ответа">${Se.map((o) => `<option${o === 503 ? " selected" : ""}>${o}</option>`).join("")}</select>
533
+ <button class="btn primary" type="submit">Добавить</button>
534
+ </form>
535
+ </div>`;
536
+ }
537
+ function Pe() {
538
+ const t = document.documentElement.getAttribute("data-u-viewport");
539
+ return t || (window.matchMedia("(max-width: 576px)").matches ? "mobile" : window.matchMedia("(max-width: 900px)").matches ? "tablet" : "desktop");
540
+ }
541
+ function De(t) {
542
+ var r, l, f;
543
+ const e = document.documentElement, n = getComputedStyle(e).getPropertyValue("--u-unit").trim(), a = Wt();
544
+ let s = "—";
545
+ try {
546
+ const p = (l = (r = t.config).user) == null ? void 0 : l.call(r);
547
+ p && (s = [p.name, (f = p.roles) != null && f.length ? p.roles.join(", ") : "без ролей"].filter(Boolean).join(" · "));
548
+ } catch {
549
+ s = "не удалось прочитать";
550
+ }
551
+ const o = kt(t);
552
+ return `<dl>${[
553
+ ["Ширина", `${window.innerWidth} px · ${Pe()}`],
554
+ ["Шкала", `${e.getAttribute("data-u-responsive") ?? "legacy"}${n ? ` · --u-unit ${n}` : ""}`],
555
+ ["Кит", a ? `${a.name} ${a.version}` : "—"],
556
+ ["Сервис", [t.config.service, t.config.version].filter(Boolean).join(" ")],
557
+ ["API", t.config.apiBase ?? "все запросы"],
558
+ ["Оболочка ЛК", window.__POWERED_BY_QIANKUN__ ? "да (Qiankun)" : "нет"],
559
+ ["Ввод", e.getAttribute("data-input-mode") ?? "—"],
560
+ ["Сеть", navigator.onLine ? "онлайн" : "офлайн"],
561
+ ["Пользователь", s],
562
+ ["Включено", o.length ? o.join("; ") : "ничего"]
563
+ ].map(([p, $]) => `<dt>${d(p)}</dt><dd>${d($)}</dd>`).join("")}</dl>`;
564
+ }
565
+ function g() {
566
+ if (!u) return;
567
+ const t = D();
568
+ if (!t) {
569
+ u.innerHTML = "";
570
+ return;
571
+ }
572
+ const e = m().flatMap(kt), n = e.length, a = n ? `Dev · ${n === 1 ? e[0] : `${n} ${Le(n, "сбой", "сбоя", "сбоев")}`}` : "Dev", s = m(), o = s.every((b) => Zt(b) === "hidden"), i = !o || n > 0, r = s.length > 1 ? `<select data-service aria-label="Сервис">${s.map((b) => `<option value="${d(b.config.service)}"${b === t ? " selected" : ""}>Dev · ${d(b.config.service)}</option>`).join("")}</select>` : `Dev · ${d(t.config.service)}`, l = c.open ? `
573
+ <section class="panel${i ? "" : " alone"}" role="region" aria-label="Панель разработки">
574
+ <div class="head"><span class="title">${r}</span>
575
+ <button class="reset" type="button" data-reset>Сбросить всё</button>
576
+ <button class="close" type="button" data-close aria-label="Свернуть панель">×</button></div>
577
+ <div class="escape">Без панели: адрес с ?dev=off · открыть и закрыть: Ctrl+Alt+D</div>
578
+ <div class="tabs" role="tablist">
579
+ <button class="tab" type="button" role="tab" data-tab="faults" aria-selected="${c.tab === "faults"}">Сбои${I(t) ? ` · ${I(t)}` : ""}</button>
580
+ <button class="tab" type="button" role="tab" data-tab="requests" aria-selected="${c.tab === "requests"}">Запросы</button>
581
+ <button class="tab" type="button" role="tab" data-tab="errors" aria-selected="${c.tab === "errors"}">Ошибки${K().length ? ` · ${K().length}` : ""}</button>
582
+ <button class="tab" type="button" role="tab" data-tab="view" aria-selected="${c.tab === "view"}">Смотреть</button>
583
+ </div>
584
+ <div class="body">${c.tab === "faults" ? Ae(t) : c.tab === "requests" ? Lt(t) : c.tab === "errors" ? Me() : De(t)}</div>
585
+ ${c.hint ? `<div class="note" role="status">${d(c.hint)}</div>` : ""}
586
+ <div class="foot">
587
+ ${t.config.onRefetch ? '<button class="btn" type="button" data-refetch>Перезапросить данные</button>' : ""}
588
+ <button class="btn" type="button" data-reload>Перезагрузить</button>
589
+ ${s.some((b) => b.state.faults.length) ? '<button class="btn" type="button" data-share>Ссылка на сбои</button>' : ""}
590
+ <button class="btn" type="button" data-launcher="${o ? "visible" : "hidden"}">${o ? "Показывать кнопку" : "Скрыть кнопку"}</button>
591
+ </div>
592
+ </section>` : "", f = u.activeElement, p = Et(f), $ = (f == null ? void 0 : f.dataset.search) !== void 0 ? f.selectionStart : null, Dt = V ?? je();
593
+ V = null;
594
+ const Rt = [
595
+ e.length ? `Включено: ${e.join(", ")}` : "Панель разработки (Ctrl+Alt+D)",
596
+ o ? "Кнопка скрыта и видна, пока включены сбои" : ""
597
+ ].filter(Boolean).join(". "), Ot = i ? `
598
+ <button class="pill${n ? " on" : ""}" type="button" data-toggle aria-expanded="${c.open}"
599
+ title="${d(Rt)}"><span class="dot"></span>${d(a)}</button>` : "", Ct = c.hint && !c.open ? `<div class="hint" role="status">${d(c.hint)}</div>` : "";
600
+ if (u.innerHTML = `<style>${ke}</style><div class="root">${l}${Ot}${Ct}</div>`, Ue(Dt), p) {
601
+ const b = u.querySelector(p);
602
+ b == null || b.focus(), b instanceof HTMLInputElement && $ !== null && b.setSelectionRange($, $);
603
+ }
604
+ }
605
+ const Re = ["search", "fault", "rule", "tab", "service", "reset", "close", "toggle", "ruleFrom", "clearJournal"];
606
+ function Et(t) {
607
+ if (!t) return null;
608
+ const e = t.getAttribute("name");
609
+ if (e && t.closest("[data-add]")) return `[data-add] [name="${e}"]`;
610
+ const n = Re.find((o) => t.dataset[o] !== void 0);
611
+ if (!n) return null;
612
+ const a = t.dataset[n], s = `data-${n.replace(/[A-Z]/g, (o) => `-${o.toLowerCase()}`)}`;
613
+ return a ? `[${s}="${a.replace(/["\\]/g, "\\$&")}"]` : `[${s}]`;
614
+ }
615
+ const Tt = ["method", "path", "status"];
616
+ let V = null;
617
+ const Oe = { network: "сеть", abort: "отмена", pending: "…" };
618
+ function Lt(t) {
619
+ const e = Q().filter((n) => n.service === t.config.service);
620
+ return e.length ? `<div class="requests-head"><span>Последние ${e.length}, новые сверху</span>
621
+ <button class="btn" type="button" data-clear-journal>Очистить</button></div>
622
+ <div class="requests">${e.map((n) => {
623
+ const a = typeof n.status == "number" ? String(n.status) : Oe[n.status], s = n.status === "network" || typeof n.status == "number" && n.status >= 400, o = [n.duration === null ? "" : `${n.duration} мс`, n.faked ? "подменён панелью" : ""].filter(Boolean).join(" · ");
624
+ return `<div class="req"><span>${d(n.method)}</span>
625
+ <span class="path">${d(n.path)}${o ? `<small>${d(o)}</small>` : ""}</span>
626
+ <span class="status${s ? " bad" : ""}">${d(a)}</span>
627
+ <button class="btn" type="button" data-rule-from="${n.id}" title="Ответ на этот адрес — в «Ответах сервера»">Правило</button></div>`;
628
+ }).join("")}</div>` : '<div class="empty">Запросов к API пока не было. Журнал помнит последние 50 и очищается при перезагрузке.</div>';
629
+ }
630
+ const Ce = {
631
+ screen: "Заглушка",
632
+ fail: "Уведомление об ошибке",
633
+ warning: "Предупреждение",
634
+ offline: "Нет связи"
635
+ }, Ie = (t) => Ce[t.kind === "notification" ? t.variant ?? "fail" : t.kind];
636
+ function Me() {
637
+ const t = K();
638
+ return t.length ? `<div class="requests-head"><span>Последние ${t.length}, новые сверху</span>
639
+ <button class="btn" type="button" data-clear-shown>Очистить</button></div>
640
+ <div>${t.map((e) => `<div class="shown">
641
+ <div class="shown-head"><span class="kind${e.variant === "warning" ? " warning" : ""}">${d(Ie(e))}${e.code ? ` · ${d(e.code)}` : ""}</span>
642
+ <time>${d(new Date(e.at).toLocaleTimeString("ru-RU"))}</time></div>
643
+ <div class="shown-title">${d(e.title)}</div>
644
+ ${e.text ? `<small>${d(e.text)}</small>` : ""}
645
+ <div class="cause">${e.cause ? `← ${d(e.cause)}` : "<small>Неудачных запросов к API перед показом не было</small>"}</div>
646
+ </div>`).join("")}</div>` : '<div class="empty">Ошибок пользователю пока не показывали. Здесь появятся заглушки, уведомления об ошибке и полоса «Нет связи» — с причиной из запросов к API.</div>';
647
+ }
648
+ function ze(t) {
649
+ var a;
650
+ const e = Q().find((s) => String(s.id) === String(t));
651
+ if (!e) return;
652
+ V = { method: G.some(([s]) => s === e.method) ? e.method : "", path: e.path, status: "503" }, c.tab = "faults", c.search = "", g(), (a = u == null ? void 0 : u.querySelector('[data-add] [name="status"]')) == null || a.focus();
653
+ }
654
+ function qe() {
655
+ const t = [...new Set(m().flatMap((r) => r.state.faults))], e = new URL(window.location.href);
656
+ e.searchParams.set("dev", t.join(","));
657
+ const n = e.href.replace(/%2C/gi, ","), s = m().some((r) => r.state.rules.some((l) => l.enabled)) ? " Свои правила «адрес → код» в неё не входят." : "", o = () => {
658
+ A(`Ссылка скопирована.${s}`), g();
659
+ }, i = () => {
660
+ A(`Ссылка: ${n}${s}`), g();
661
+ };
662
+ try {
663
+ navigator.clipboard.writeText(n).then(o, i);
664
+ } catch {
665
+ i();
666
+ }
667
+ }
668
+ function je() {
669
+ const t = u == null ? void 0 : u.querySelector("[data-add]");
670
+ return t ? Object.fromEntries(Tt.map((e) => {
671
+ var n;
672
+ return [e, ((n = t.elements.namedItem(e)) == null ? void 0 : n.value) ?? ""];
673
+ })) : null;
674
+ }
675
+ function Ue(t) {
676
+ const e = u == null ? void 0 : u.querySelector("[data-add]");
677
+ !e || !t || Tt.forEach((n) => {
678
+ const a = e.elements.namedItem(n);
679
+ a && (a.value = t[n]);
680
+ });
681
+ }
682
+ function Fe(t) {
683
+ if (!t) {
684
+ A(""), tt("visible");
685
+ return;
686
+ }
687
+ c.open = !1;
688
+ const e = m().some((n) => I(n) > 0);
689
+ A(`Кнопка Dev скрыта${e ? " и видна, пока включены сбои" : ""}. Панель: Ctrl+Alt+D`), tt("hidden");
690
+ }
691
+ function A(t) {
692
+ clearTimeout(Y), c.hint = t, t && (Y = setTimeout(() => {
693
+ c.hint = "", g();
694
+ }, Ee));
695
+ }
696
+ function j(t = !c.open) {
697
+ var e, n;
698
+ t && A(""), c.open = t, g(), t ? (e = u == null ? void 0 : u.querySelector("[data-search], [data-tab]")) == null || e.focus() : (n = u == null ? void 0 : u.querySelector("[data-toggle]")) == null || n.focus();
699
+ }
700
+ function Ne(t) {
701
+ var a, s, o, i;
702
+ const e = t.target, n = D();
703
+ if (n)
704
+ if (e.closest("[data-toggle]")) j();
705
+ else if (e.closest("[data-close]")) j(!1);
706
+ else if (e.closest("[data-reset]"))
707
+ yt(), (s = (a = n.config).onRefetch) == null || s.call(a);
708
+ else if (e.closest("[data-reload]")) window.location.reload();
709
+ else if (e.closest("[data-rule-from]")) ze(Number(e.closest("[data-rule-from]").dataset.ruleFrom));
710
+ else if (e.closest("[data-clear-journal]"))
711
+ ct(), g();
712
+ else if (e.closest("[data-clear-shown]")) ht();
713
+ else if (e.closest("[data-share]")) qe();
714
+ else if (e.closest("[data-launcher]")) Fe(e.closest("[data-launcher]").dataset.launcher === "hidden");
715
+ else if (e.closest("[data-refetch]")) (i = (o = n.config).onRefetch) == null || i.call(o);
716
+ else if (e.closest("[data-tab]")) {
717
+ const r = e.closest("[data-tab]").dataset.tab;
718
+ c.tab = r === "view" || r === "requests" || r === "errors" ? r : "faults", g();
719
+ } else e.closest("[data-remove]") && Vt(n, e.closest("[data-remove]").dataset.remove);
720
+ }
721
+ function He(t) {
722
+ const e = t.target, n = D();
723
+ if (n)
724
+ if (e.dataset.fault) {
725
+ const a = e.checked;
726
+ Xt(n, e.dataset.fault, a), e.dataset.fault === "offline" && Z(!a);
727
+ } else e.dataset.rule ? Yt(n, e.dataset.rule, e.checked) : e.dataset.service !== void 0 && (c.service = e.value, g());
728
+ }
729
+ function _e(t) {
730
+ const e = t.target;
731
+ e.dataset.search !== void 0 && (c.search = e.value, g());
732
+ }
733
+ function We(t) {
734
+ const e = t.target;
735
+ if (e.dataset.add === void 0) return;
736
+ t.preventDefault();
737
+ const n = D(), a = new FormData(e), s = String(a.get("path") ?? "").trim();
738
+ !n || !s || (e.reset(), Gt(n, {
739
+ method: String(a.get("method") ?? "") || void 0,
740
+ path: s.startsWith("/") ? s : `/${s}`,
741
+ status: Number(a.get("status")) || 500,
742
+ html: Number(a.get("status")) === 502 || void 0
743
+ }));
744
+ }
745
+ function At(t) {
746
+ t.ctrlKey && t.altKey && t.code === "KeyD" ? (t.preventDefault(), j()) : t.key === "Escape" && c.open && h && t.composedPath().includes(h) && (t.preventDefault(), t.stopPropagation(), j(!1));
747
+ }
748
+ function Be() {
749
+ if (h || typeof document > "u") return;
750
+ h = document.createElement("div"), h.id = "urfu-ui-kit-dev", h.setAttribute("data-urfu-ui-kit-dev", ""), u = h.attachShadow({ mode: "open" }), u.addEventListener("click", Ne), u.addEventListener("change", He), u.addEventListener("input", _e), u.addEventListener("submit", We), window.addEventListener("keydown", At, !0), lt(), y = new MutationObserver((a) => {
751
+ (!(h != null && h.isConnected) || a.some((s) => s.type === "attributes")) && lt();
752
+ }), y.observe(document.documentElement, { childList: !0, subtree: !0, attributes: !0, attributeFilter: ["open"] }), c.open = m().some((a) => I(a) > 0);
753
+ const t = pt(g), e = qt(Pt);
754
+ u.addEventListener("pointerdown", Je), window.addEventListener("pointerup", U, !0), window.addEventListener("pointercancel", U, !0);
755
+ const n = le(() => {
756
+ c.open && g();
757
+ });
758
+ re(), S = () => {
759
+ t(), e(), n(), ie();
760
+ }, g();
761
+ }
762
+ function Ke() {
763
+ try {
764
+ const t = document.querySelectorAll("dialog:modal");
765
+ return t[t.length - 1] ?? null;
766
+ } catch {
767
+ return null;
768
+ }
769
+ }
770
+ function lt() {
771
+ if (!h) return;
772
+ const t = Ke() ?? document.documentElement;
773
+ h.parentNode !== t && t.appendChild(h);
774
+ }
775
+ function Pt() {
776
+ var s;
777
+ if (!c.open || c.tab !== "requests") {
778
+ k = !1;
779
+ return;
780
+ }
781
+ if (L) {
782
+ k = !0;
783
+ return;
784
+ }
785
+ k = !1;
786
+ const t = u == null ? void 0 : u.querySelector(".body"), e = D();
787
+ if (!u || !t || !e) {
788
+ g();
789
+ return;
790
+ }
791
+ const n = u.activeElement, a = n && t.contains(n) ? Et(n) : null;
792
+ t.innerHTML = Lt(e), a && ((s = t.querySelector(a)) == null || s.focus());
793
+ }
794
+ function Je() {
795
+ L = !0;
796
+ }
797
+ function U() {
798
+ L && (L = !1, k && setTimeout(Pt, 0));
799
+ }
800
+ function Xe() {
801
+ S == null || S(), S = null, y == null || y.disconnect(), y = null, window.removeEventListener("keydown", At, !0), window.removeEventListener("pointerup", U, !0), window.removeEventListener("pointercancel", U, !0), L = !1, k = !1, clearTimeout(Y), h == null || h.remove(), h = null, u = null, Object.assign(c, $t);
802
+ }
803
+ function Ge(t, e) {
804
+ return typeof window > "u" ? () => {
805
+ } : (Ut(), _t(e), Bt(t).state.faults.includes("offline") && Z(!1), ge(), Be(), () => {
806
+ Kt(t.service), m().length || Xe();
807
+ });
808
+ }
809
+ function Ye(t, e) {
810
+ var n;
811
+ return ((n = Jt(e)) == null ? void 0 : n.state.faults.includes(t)) ?? !1;
812
+ }
813
+ function Ve(t) {
814
+ return pt(t);
815
+ }
816
+ function en() {
817
+ yt();
818
+ }
819
+ const Qe = () => "2.1.0";
820
+ function nn(t) {
821
+ return Ge(t, { name: "urfu-ui-kit-react", version: Qe() });
822
+ }
823
+ function Ze(t, e) {
824
+ return It(Ve, () => Ye(t, e), () => !1);
825
+ }
826
+ function an({ scope: t, service: e }) {
827
+ if (Ze(t === "app" ? "crashApp" : "crashPage", e)) throw new Error(`Сбой из dev-панели: падение ${t === "app" ? "приложения" : "страницы"}`);
828
+ return null;
829
+ }
830
+ export {
831
+ an as DevCrashProbe,
832
+ Ye as isDevFault,
833
+ de as matchPath,
834
+ nn as mountDevPanel,
835
+ en as resetDevFaults,
836
+ Ve as subscribeDevFaults,
837
+ Ze as useDevFault
838
+ };