@dskripchenko/laravel-admin 1.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 (163) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +226 -0
  3. package/dist/.gitkeep +0 -0
  4. package/dist/api/bootstrap.d.ts +38 -0
  5. package/dist/api/bootstrap.test.d.ts +1 -0
  6. package/dist/api/client.d.ts +30 -0
  7. package/dist/api/client.test.d.ts +1 -0
  8. package/dist/api/envelope.d.ts +24 -0
  9. package/dist/api/envelope.test.d.ts +1 -0
  10. package/dist/api/errors.d.ts +40 -0
  11. package/dist/api/errors.test.d.ts +1 -0
  12. package/dist/components/AdminApp.vue.d.ts +2 -0
  13. package/dist/components/ForbiddenPage.vue.d.ts +2 -0
  14. package/dist/components/HomePage.vue.d.ts +2 -0
  15. package/dist/components/NotFoundPage.vue.d.ts +2 -0
  16. package/dist/components/SettingsPage.vue.d.ts +2 -0
  17. package/dist/components/UnknownScreenPage.vue.d.ts +2 -0
  18. package/dist/components/auth/LoginForm.test.d.ts +1 -0
  19. package/dist/components/auth/LoginForm.vue.d.ts +17 -0
  20. package/dist/components/auth/LoginPage.test.d.ts +1 -0
  21. package/dist/components/auth/LoginPage.vue.d.ts +26 -0
  22. package/dist/components/auth/TwoFactorForm.test.d.ts +1 -0
  23. package/dist/components/auth/TwoFactorForm.vue.d.ts +8 -0
  24. package/dist/components/auth/index.d.ts +6 -0
  25. package/dist/components/createComponentRegistry.d.ts +22 -0
  26. package/dist/components/dashboard/BarChartWidget.vue.d.ts +18 -0
  27. package/dist/components/dashboard/DashboardPage.test.d.ts +1 -0
  28. package/dist/components/dashboard/DashboardPage.vue.d.ts +28 -0
  29. package/dist/components/dashboard/DonutChartWidget.vue.d.ts +13 -0
  30. package/dist/components/dashboard/GaugeWidget.vue.d.ts +29 -0
  31. package/dist/components/dashboard/HeatmapWidget.vue.d.ts +18 -0
  32. package/dist/components/dashboard/MarkdownWidget.vue.d.ts +8 -0
  33. package/dist/components/dashboard/RecentTableWidget.vue.d.ts +12 -0
  34. package/dist/components/dashboard/StatWidget.vue.d.ts +22 -0
  35. package/dist/components/dashboard/UnknownWidget.vue.d.ts +5 -0
  36. package/dist/components/dashboard/WidgetRenderer.vue.d.ts +10 -0
  37. package/dist/components/dashboard/builtin.d.ts +4 -0
  38. package/dist/components/dashboard/index.d.ts +16 -0
  39. package/dist/components/dashboard/registry.d.ts +25 -0
  40. package/dist/components/dashboard/registry.test.d.ts +1 -0
  41. package/dist/components/fields/CheckboxField.vue.d.ts +16 -0
  42. package/dist/components/fields/DateField.vue.d.ts +25 -0
  43. package/dist/components/fields/NumberField.vue.d.ts +24 -0
  44. package/dist/components/fields/SelectField.vue.d.ts +28 -0
  45. package/dist/components/fields/TextAreaField.vue.d.ts +20 -0
  46. package/dist/components/fields/TextField.vue.d.ts +22 -0
  47. package/dist/components/fields/UnknownField.vue.d.ts +6 -0
  48. package/dist/components/fields/fields.test.d.ts +1 -0
  49. package/dist/components/fields/wysiwyg/quill/QuillField.vue.d.ts +26 -0
  50. package/dist/components/fields/wysiwyg/quill/index.d.ts +12 -0
  51. package/dist/components/fields/wysiwyg/tinymce/TinymceField.vue.d.ts +31 -0
  52. package/dist/components/fields/wysiwyg/tinymce/index.d.ts +12 -0
  53. package/dist/components/gallery/FieldGalleryPage.test.d.ts +1 -0
  54. package/dist/components/gallery/FieldGalleryPage.vue.d.ts +2 -0
  55. package/dist/components/gallery/index.d.ts +1 -0
  56. package/dist/components/import/ImportWizardPage.test.d.ts +1 -0
  57. package/dist/components/import/ImportWizardPage.vue.d.ts +59 -0
  58. package/dist/components/import/index.d.ts +1 -0
  59. package/dist/components/infolist/BadgeEntry.vue.d.ts +18 -0
  60. package/dist/components/infolist/IconEntry.vue.d.ts +22 -0
  61. package/dist/components/infolist/InfolistRenderer.test.d.ts +1 -0
  62. package/dist/components/infolist/InfolistRenderer.vue.d.ts +11 -0
  63. package/dist/components/infolist/KeyValueEntry.vue.d.ts +11 -0
  64. package/dist/components/infolist/TextEntry.vue.d.ts +17 -0
  65. package/dist/components/infolist/UnknownEntry.vue.d.ts +6 -0
  66. package/dist/components/infolist/builtin.d.ts +4 -0
  67. package/dist/components/infolist/index.d.ts +13 -0
  68. package/dist/components/infolist/recordContext.d.ts +9 -0
  69. package/dist/components/infolist/registry.d.ts +19 -0
  70. package/dist/components/infolist/registry.test.d.ts +1 -0
  71. package/dist/components/layouts/ColumnsLayout.vue.d.ts +13 -0
  72. package/dist/components/layouts/RowsLayout.vue.d.ts +10 -0
  73. package/dist/components/layouts/SectionLayout.vue.d.ts +11 -0
  74. package/dist/components/layouts/TabsLayout.vue.d.ts +22 -0
  75. package/dist/components/notifications/NotificationsDrawer.test.d.ts +1 -0
  76. package/dist/components/notifications/NotificationsDrawer.vue.d.ts +13 -0
  77. package/dist/components/notifications/index.d.ts +1 -0
  78. package/dist/components/profile/ProfilePage.test.d.ts +1 -0
  79. package/dist/components/profile/ProfilePage.vue.d.ts +50 -0
  80. package/dist/components/profile/index.d.ts +1 -0
  81. package/dist/components/render/FieldRenderer.test.d.ts +1 -0
  82. package/dist/components/render/FieldRenderer.vue.d.ts +9 -0
  83. package/dist/components/render/LayoutRenderer.test.d.ts +1 -0
  84. package/dist/components/render/LayoutRenderer.vue.d.ts +10 -0
  85. package/dist/components/render/builtin.d.ts +9 -0
  86. package/dist/components/render/formState.d.ts +36 -0
  87. package/dist/components/render/formState.test.d.ts +1 -0
  88. package/dist/components/render/index.d.ts +23 -0
  89. package/dist/components/render/registry.d.ts +35 -0
  90. package/dist/components/render/registry.test.d.ts +1 -0
  91. package/dist/components/resource/ResourceFormPage.test.d.ts +1 -0
  92. package/dist/components/resource/ResourceFormPage.vue.d.ts +13 -0
  93. package/dist/components/resource/ResourceIndexPage.test.d.ts +1 -0
  94. package/dist/components/resource/ResourceIndexPage.vue.d.ts +44 -0
  95. package/dist/components/resource/ResourceViewPage.test.d.ts +1 -0
  96. package/dist/components/resource/ResourceViewPage.vue.d.ts +13 -0
  97. package/dist/components/resource/index.d.ts +6 -0
  98. package/dist/components/shell/AdminShell.vue.d.ts +35 -0
  99. package/dist/components/shell/AdminSidebar.test.d.ts +1 -0
  100. package/dist/components/shell/AdminSidebar.vue.d.ts +27 -0
  101. package/dist/components/shell/AdminTopBar.test.d.ts +1 -0
  102. package/dist/components/shell/AdminTopBar.vue.d.ts +33 -0
  103. package/dist/components/shell/index.d.ts +18 -0
  104. package/dist/components/shell/widgets/LocaleSwitcher.test.d.ts +1 -0
  105. package/dist/components/shell/widgets/LocaleSwitcher.vue.d.ts +2 -0
  106. package/dist/components/shell/widgets/NotificationBell.vue.d.ts +2 -0
  107. package/dist/components/shell/widgets/ThemeToggle.test.d.ts +1 -0
  108. package/dist/components/shell/widgets/ThemeToggle.vue.d.ts +2 -0
  109. package/dist/components/shell/widgets/UserMenu.test.d.ts +1 -0
  110. package/dist/components/shell/widgets/UserMenu.vue.d.ts +2 -0
  111. package/dist/createAdminApp.d.ts +85 -0
  112. package/dist/createAdminApp.test.d.ts +1 -0
  113. package/dist/formState-DGNcH1XQ.js +40 -0
  114. package/dist/formState-DGNcH1XQ.js.map +1 -0
  115. package/dist/formState-GlJBphEn.cjs +2 -0
  116. package/dist/formState-GlJBphEn.cjs.map +1 -0
  117. package/dist/index.cjs +2 -0
  118. package/dist/index.cjs.map +1 -0
  119. package/dist/index.d.ts +62 -0
  120. package/dist/index.mjs +4345 -0
  121. package/dist/index.mjs.map +1 -0
  122. package/dist/quill.cjs +2 -0
  123. package/dist/quill.cjs.map +1 -0
  124. package/dist/quill.mjs +71 -0
  125. package/dist/quill.mjs.map +1 -0
  126. package/dist/router/builder.d.ts +52 -0
  127. package/dist/router/builder.test.d.ts +1 -0
  128. package/dist/router/guards.d.ts +56 -0
  129. package/dist/router/guards.test.d.ts +1 -0
  130. package/dist/router/index.d.ts +63 -0
  131. package/dist/router/index.test.d.ts +1 -0
  132. package/dist/stores/auth.d.ts +142 -0
  133. package/dist/stores/auth.test.d.ts +1 -0
  134. package/dist/stores/index.d.ts +21 -0
  135. package/dist/stores/locale.d.ts +29 -0
  136. package/dist/stores/locale.test.d.ts +1 -0
  137. package/dist/stores/manifest.d.ts +515 -0
  138. package/dist/stores/manifest.test.d.ts +1 -0
  139. package/dist/stores/menu.d.ts +215 -0
  140. package/dist/stores/menu.test.d.ts +1 -0
  141. package/dist/stores/notifications.d.ts +137 -0
  142. package/dist/stores/notifications.test.d.ts +1 -0
  143. package/dist/stores/registry.d.ts +16 -0
  144. package/dist/stores/registry.test.d.ts +1 -0
  145. package/dist/stores/resourceForm.d.ts +91 -0
  146. package/dist/stores/resourceForm.test.d.ts +1 -0
  147. package/dist/stores/resourceIndex.d.ts +149 -0
  148. package/dist/stores/resourceIndex.test.d.ts +1 -0
  149. package/dist/stores/theme.d.ts +29 -0
  150. package/dist/stores/theme.test.d.ts +1 -0
  151. package/dist/style.css +1 -0
  152. package/dist/tinymce.cjs +2 -0
  153. package/dist/tinymce.cjs.map +1 -0
  154. package/dist/tinymce.mjs +80 -0
  155. package/dist/tinymce.mjs.map +1 -0
  156. package/dist/types/bootstrap.d.ts +50 -0
  157. package/package.json +162 -0
  158. package/resources/fonts/InterDisplay-Bold.woff2 +0 -0
  159. package/resources/fonts/InterDisplay-ExtraBold.woff2 +0 -0
  160. package/resources/fonts/InterDisplay-SemiBold.woff2 +0 -0
  161. package/resources/fonts/InterVariable-Italic.woff2 +0 -0
  162. package/resources/fonts/InterVariable.woff2 +0 -0
  163. package/resources/fonts/fonts.css +69 -0
package/dist/index.mjs ADDED
@@ -0,0 +1,4345 @@
1
+ import { ref as E, computed as p, defineComponent as L, openBlock as s, createElementBlock as c, createElementVNode as d, createBlock as k, unref as r, withCtx as m, Fragment as T, renderList as I, createTextVNode as C, toDisplayString as h, createCommentVNode as F, createVNode as x, renderSlot as H, resolveDynamicComponent as oe, normalizeClass as X, createSlots as Me, h as ht, watch as te, onBeforeUnmount as _t, resolveComponent as Ze, withModifiers as Ie, nextTick as Le, onMounted as xe, withKeys as yt, normalizeProps as Ce, mergeProps as Se, normalizeStyle as Ae, inject as et, provide as bt, createApp as kt, reactive as wt } from "vue";
2
+ import { defineStore as Z, createPinia as $t } from "pinia";
3
+ import { RouterLink as xt, useRouter as ne, useRoute as pe, createWebHistory as tt, createRouter as Ct } from "vue-router";
4
+ import { UidMenu as nt, UidMenuItem as Ne, UidMenuSeparator as St, UidAvatar as at, UidSidebar as At, UidSidebarGroup as Rt, UidSidebarItem as Ut, UidSidebarLayout as Et, UidCard as q, UidButton as B, UidAlert as J, UidInput as ie, UidCheckbox as we, UidSkeleton as Be, UidErrorState as Ft, UidEmptyState as Lt, UidTable as Ve, UidPagination as Pt, UidBadge as ze, UidSelect as $e, UidStat as be, UidHeatmap as Tt, UidGauge as Mt, UidFormField as ge, UidTextarea as Nt, UidNumberInput as It, UidDatePicker as Bt, UidStack as Vt, UidGrid as zt, UidTabs as lt, UidTabPanel as st, UidTab as ke, UidDescriptionList as qt, UidDescriptionItem as Dt, UidDrawer as Ot, UidStepper as Wt, UidFileUpload as jt, UidProgress as Kt } from "@dskripchenko/ui";
5
+ import Gt from "axios";
6
+ import { p as it, u as re } from "./formState-DGNcH1XQ.js";
7
+ import { t as uo } from "./formState-DGNcH1XQ.js";
8
+ let ve = null;
9
+ function Ht(e) {
10
+ ve = e;
11
+ }
12
+ function W() {
13
+ if (ve === null)
14
+ throw new Error(
15
+ "[admin] AdminClient is not registered. Call setAdminClient(...) before using stores."
16
+ );
17
+ return ve;
18
+ }
19
+ function Ni() {
20
+ ve = null;
21
+ }
22
+ function Ii() {
23
+ return ve !== null;
24
+ }
25
+ const qe = Z("admin-theme", () => {
26
+ const e = E("light"), t = E(["light", "dark"]), n = p(() => e.value === "dark");
27
+ function o(u) {
28
+ e.value = u.theme, t.value = u.availableThemes, i(u.theme);
29
+ }
30
+ function a(u) {
31
+ if (!t.value.includes(u))
32
+ throw new Error(`Theme "${u}" is not available`);
33
+ e.value = u, i(u);
34
+ }
35
+ async function l(u) {
36
+ if (!t.value.includes(u))
37
+ throw new Error(`Theme "${u}" is not available`);
38
+ const f = e.value;
39
+ a(u);
40
+ try {
41
+ await W().post("/system/setTheme", { theme: u });
42
+ } catch (v) {
43
+ throw a(f), v;
44
+ }
45
+ }
46
+ function i(u) {
47
+ typeof document < "u" && document.documentElement && document.documentElement.setAttribute("data-theme", u);
48
+ }
49
+ return {
50
+ current: e,
51
+ available: t,
52
+ isDark: n,
53
+ hydrate: o,
54
+ applyLocal: a,
55
+ setTheme: l
56
+ };
57
+ }), Xt = ["aria-label", "aria-pressed"], Jt = ["data-icon"], ot = /* @__PURE__ */ L({
58
+ __name: "ThemeToggle",
59
+ setup(e) {
60
+ const t = qe(), n = p(() => t.current === "dark"), o = p(() => n.value ? "sun" : "moon"), a = p(
61
+ () => n.value ? "Переключить на светлую тему" : "Переключить на тёмную тему"
62
+ );
63
+ async function l() {
64
+ const i = n.value ? "light" : "dark";
65
+ await t.setTheme(i);
66
+ }
67
+ return (i, u) => (s(), c("button", {
68
+ type: "button",
69
+ class: "admin-topbar__icon-btn",
70
+ "aria-label": a.value,
71
+ "aria-pressed": n.value,
72
+ onClick: l
73
+ }, [
74
+ d("span", {
75
+ class: "admin-topbar__icon",
76
+ "data-icon": o.value
77
+ }, null, 8, Jt)
78
+ ], 8, Xt));
79
+ }
80
+ }), De = Z("admin-locale", () => {
81
+ const e = E("ru"), t = E(["ru", "en"]);
82
+ function n(i) {
83
+ e.value = i.locale, t.value = i.availableLocales, l(i.locale);
84
+ }
85
+ function o(i) {
86
+ if (!t.value.includes(i))
87
+ throw new Error(`Locale "${i}" is not available`);
88
+ e.value = i, l(i);
89
+ }
90
+ async function a(i) {
91
+ if (!t.value.includes(i))
92
+ throw new Error(`Locale "${i}" is not available`);
93
+ const u = e.value;
94
+ o(i);
95
+ try {
96
+ await W().post("/system/setLocale", { locale: i });
97
+ } catch (f) {
98
+ throw o(u), f;
99
+ }
100
+ }
101
+ function l(i) {
102
+ typeof document < "u" && document.documentElement && document.documentElement.setAttribute("lang", i);
103
+ try {
104
+ W().setLocale(i);
105
+ } catch {
106
+ }
107
+ }
108
+ return {
109
+ current: e,
110
+ available: t,
111
+ hydrate: n,
112
+ applyLocal: o,
113
+ setLocale: a
114
+ };
115
+ }), Yt = {
116
+ type: "button",
117
+ class: "admin-topbar__icon-btn",
118
+ style: { width: "auto", padding: "0 8px", gap: "4px", "font-size": "12px" },
119
+ "aria-label": "Сменить локаль"
120
+ }, rt = /* @__PURE__ */ L({
121
+ __name: "LocaleSwitcher",
122
+ setup(e) {
123
+ const t = De();
124
+ async function n(o) {
125
+ o !== t.current && await t.setLocale(o);
126
+ }
127
+ return (o, a) => (s(), k(r(nt), null, {
128
+ trigger: m(() => [
129
+ d("button", Yt, [
130
+ a[0] || (a[0] = d("span", {
131
+ class: "admin-topbar__icon",
132
+ "data-icon": "globe"
133
+ }, null, -1)),
134
+ d("span", null, h((r(t).current ?? "").toUpperCase()), 1)
135
+ ])
136
+ ]),
137
+ default: m(() => [
138
+ (s(!0), c(T, null, I(r(t).available, (l) => (s(), k(r(Ne), {
139
+ key: l,
140
+ onClick: (i) => n(l)
141
+ }, {
142
+ default: m(() => [
143
+ C(h(l.toUpperCase()), 1)
144
+ ]),
145
+ _: 2
146
+ }, 1032, ["onClick"]))), 128))
147
+ ]),
148
+ _: 1
149
+ }));
150
+ }
151
+ }), Oe = Z("admin-notifications", () => {
152
+ const e = E([]), t = E(0), n = E(!1), o = E("all"), a = E(null), l = p(() => t.value > 0);
153
+ function i(R) {
154
+ t.value = R.unread_notifications_count;
155
+ }
156
+ async function u(R = "all", A = 1) {
157
+ n.value = !0;
158
+ try {
159
+ const g = await W().get(`/notifications/list?type=${R}&page=${A}`);
160
+ e.value = g.data, t.value = g.meta.unread_count, a.value = {
161
+ page: g.meta.page,
162
+ per_page: g.meta.per_page,
163
+ total: g.meta.total,
164
+ last_page: g.meta.last_page
165
+ }, o.value = R;
166
+ } finally {
167
+ n.value = !1;
168
+ }
169
+ }
170
+ async function f() {
171
+ const A = await W().get(
172
+ "/notifications/unread"
173
+ );
174
+ t.value = A.count, o.value === "unread" && (e.value = A.data);
175
+ }
176
+ async function v(R) {
177
+ await W().post("/notifications/markAsRead", { id: R });
178
+ const _ = e.value.find((g) => g.id === R);
179
+ _ && _.read_at === null && (_.read_at = (/* @__PURE__ */ new Date()).toISOString(), t.value = Math.max(0, t.value - 1));
180
+ }
181
+ async function w() {
182
+ await W().post("/notifications/markAllAsRead");
183
+ const A = (/* @__PURE__ */ new Date()).toISOString();
184
+ for (const _ of e.value)
185
+ _.read_at === null && (_.read_at = A);
186
+ t.value = 0;
187
+ }
188
+ async function S(R) {
189
+ await W().post("/notifications/destroy", { id: R });
190
+ const _ = e.value.findIndex((g) => g.id === R);
191
+ if (_ !== -1) {
192
+ const g = e.value[_].read_at === null;
193
+ e.value.splice(_, 1), g && (t.value = Math.max(0, t.value - 1));
194
+ }
195
+ }
196
+ return {
197
+ items: e,
198
+ unreadCount: t,
199
+ loading: n,
200
+ meta: a,
201
+ lastFilter: o,
202
+ hasUnread: l,
203
+ hydrate: i,
204
+ load: u,
205
+ loadUnread: f,
206
+ markAsRead: v,
207
+ markAllAsRead: w,
208
+ destroy: S
209
+ };
210
+ }), Qt = ["title"], Zt = /* @__PURE__ */ L({
211
+ __name: "NotificationBell",
212
+ setup(e) {
213
+ const t = Oe(), n = p(() => {
214
+ const o = t.unreadCount;
215
+ return o <= 0 ? null : o > 99 ? "99+" : String(o);
216
+ });
217
+ return (o, a) => (s(), k(r(xt), {
218
+ to: "/notifications",
219
+ class: "admin-topbar__icon-btn",
220
+ "aria-label": "Уведомления"
221
+ }, {
222
+ default: m(() => [
223
+ a[0] || (a[0] = d("span", {
224
+ class: "admin-topbar__icon",
225
+ "data-icon": "bell"
226
+ }, null, -1)),
227
+ n.value !== null ? (s(), c("span", {
228
+ key: 0,
229
+ class: "admin-topbar__bell-badge",
230
+ title: `Непрочитанных: ${r(t).unreadCount}`
231
+ }, h(n.value), 9, Qt)) : F("", !0)
232
+ ]),
233
+ _: 1
234
+ }));
235
+ }
236
+ });
237
+ class Y extends Error {
238
+ status;
239
+ errorKey;
240
+ payload;
241
+ constructor(t, n) {
242
+ super(n.message ?? `API error ${t}`), this.name = "ApiError", this.status = t, this.errorKey = n.errorKey ?? "unknown", this.payload = n;
243
+ }
244
+ }
245
+ class ut extends Y {
246
+ constructor(t) {
247
+ super(401, t), this.name = "UnauthenticatedError";
248
+ }
249
+ }
250
+ class en extends Y {
251
+ constructor(t) {
252
+ super(403, t), this.name = "ForbiddenError";
253
+ }
254
+ }
255
+ class tn extends Y {
256
+ constructor(t) {
257
+ super(404, t), this.name = "NotFoundError";
258
+ }
259
+ }
260
+ class Re extends Y {
261
+ /** Field-keyed map of error messages. */
262
+ fields;
263
+ constructor(t) {
264
+ super(422, t), this.name = "ValidationError", this.fields = t.messages ?? {};
265
+ }
266
+ /** Первое сообщение из field'а — удобно для toast. */
267
+ firstFieldMessage() {
268
+ for (const t of Object.values(this.fields))
269
+ if (t.length > 0)
270
+ return t[0];
271
+ return null;
272
+ }
273
+ }
274
+ class Ue extends Error {
275
+ constructor(t = "Network error") {
276
+ super(t), this.name = "NetworkError";
277
+ }
278
+ }
279
+ function je(e, t) {
280
+ switch (e) {
281
+ case 401:
282
+ return new ut(t);
283
+ case 403:
284
+ return new en(t);
285
+ case 404:
286
+ return new tn(t);
287
+ case 422:
288
+ return new Re(t);
289
+ default:
290
+ return new Y(e, t);
291
+ }
292
+ }
293
+ const Q = Z("admin-auth", () => {
294
+ const e = E(null), t = E([]), n = E(null), o = p(() => e.value !== null), a = p(() => n.value !== null);
295
+ function l(_) {
296
+ e.value = _.user, t.value = _.permissions;
297
+ }
298
+ function i(_) {
299
+ return t.value.includes("*") || t.value.includes(_) ? !0 : t.value.some((g) => {
300
+ if (!g.endsWith(".*")) return !1;
301
+ const U = g.slice(0, -1);
302
+ return _.startsWith(U);
303
+ });
304
+ }
305
+ function u(_) {
306
+ return _.some(i);
307
+ }
308
+ function f(_) {
309
+ return _.every(i);
310
+ }
311
+ async function v(_) {
312
+ const g = W();
313
+ try {
314
+ const U = await g.post(
315
+ "/auth/login",
316
+ _
317
+ );
318
+ return U?.user && (e.value = U.user), Array.isArray(U?.permissions) && (t.value = U.permissions), n.value = null, "authenticated";
319
+ } catch (U) {
320
+ if (U instanceof Y && U.errorKey === "two_factor_required") {
321
+ const P = U.payload.challenge_token;
322
+ return n.value = {
323
+ challengeToken: typeof P == "string" ? P : "",
324
+ remember: _.remember ?? !1
325
+ }, "two_factor_required";
326
+ }
327
+ throw U;
328
+ }
329
+ }
330
+ async function w(_) {
331
+ if (n.value === null)
332
+ throw new Error("No pending 2FA challenge");
333
+ const U = await W().post("/auth/twoFactorChallenge", {
334
+ challenge_token: n.value.challengeToken,
335
+ code: _
336
+ });
337
+ e.value = U.user, n.value = null;
338
+ }
339
+ async function S(_) {
340
+ if (n.value === null)
341
+ throw new Error("No pending 2FA challenge");
342
+ const U = await W().post("/auth/twoFactorRecovery", {
343
+ challenge_token: n.value.challengeToken,
344
+ recovery_code: _
345
+ });
346
+ return e.value = U.user, n.value = null, { remaining: U.recovery_codes_remaining };
347
+ }
348
+ function R() {
349
+ n.value = null;
350
+ }
351
+ async function A() {
352
+ const _ = W();
353
+ try {
354
+ await _.post("/auth/logout");
355
+ } finally {
356
+ e.value = null, t.value = [], n.value = null;
357
+ }
358
+ }
359
+ return {
360
+ // state
361
+ user: e,
362
+ permissions: t,
363
+ pendingChallenge: n,
364
+ // getters
365
+ isAuthenticated: o,
366
+ isChallengePending: a,
367
+ // actions
368
+ hydrate: l,
369
+ hasPermission: i,
370
+ hasAnyPermission: u,
371
+ hasAllPermissions: f,
372
+ login: v,
373
+ twoFactorChallenge: w,
374
+ twoFactorRecovery: S,
375
+ cancelChallenge: R,
376
+ logout: A
377
+ };
378
+ }), nn = {
379
+ type: "button",
380
+ class: "admin-topbar__icon-btn admin-user-menu__trigger",
381
+ "aria-label": "Меню пользователя",
382
+ "aria-haspopup": "menu",
383
+ style: { width: "auto", padding: "0 4px", gap: "8px" }
384
+ }, an = /* @__PURE__ */ L({
385
+ __name: "UserMenu",
386
+ setup(e) {
387
+ const t = Q(), n = ne();
388
+ async function o() {
389
+ try {
390
+ await t.logout();
391
+ } finally {
392
+ await n.push({ name: "admin.login" });
393
+ }
394
+ }
395
+ function a() {
396
+ n.push({ name: "admin.profile" });
397
+ }
398
+ return (l, i) => (s(), k(r(nt), null, {
399
+ trigger: m(() => [
400
+ d("button", nn, [
401
+ x(r(at), {
402
+ src: r(t).user?.avatar ?? void 0,
403
+ name: r(t).user?.name ?? "?",
404
+ alt: r(t).user?.name ?? "User",
405
+ size: "sm"
406
+ }, null, 8, ["src", "name", "alt"])
407
+ ])
408
+ ]),
409
+ default: m(() => [
410
+ x(r(Ne), { onClick: a }, {
411
+ default: m(() => [...i[0] || (i[0] = [
412
+ C("Профиль", -1)
413
+ ])]),
414
+ _: 1
415
+ }),
416
+ x(r(St)),
417
+ x(r(Ne), {
418
+ variant: "danger",
419
+ onClick: o
420
+ }, {
421
+ default: m(() => [...i[1] || (i[1] = [
422
+ C("Выйти", -1)
423
+ ])]),
424
+ _: 1
425
+ })
426
+ ]),
427
+ _: 1
428
+ }));
429
+ }
430
+ }), ln = { class: "admin-topbar" }, sn = { class: "admin-topbar__breadcrumbs" }, on = {
431
+ key: 0,
432
+ class: "sep"
433
+ }, rn = /* @__PURE__ */ L({
434
+ __name: "AdminTopBar",
435
+ props: {
436
+ breadcrumbs: { default: () => [] },
437
+ showCollapseToggle: { type: Boolean, default: !0 }
438
+ },
439
+ emits: ["toggle-sidebar"],
440
+ setup(e, { emit: t }) {
441
+ const n = e, o = t, a = p(() => n.breadcrumbs.length - 1);
442
+ return (l, i) => (s(), c("header", ln, [
443
+ e.showCollapseToggle ? (s(), c("button", {
444
+ key: 0,
445
+ type: "button",
446
+ class: "admin-topbar__icon-btn",
447
+ "aria-label": "Свернуть меню",
448
+ onClick: i[0] || (i[0] = (u) => o("toggle-sidebar"))
449
+ }, [...i[1] || (i[1] = [
450
+ d("span", {
451
+ class: "admin-topbar__icon",
452
+ "data-icon": "panel-left"
453
+ }, null, -1)
454
+ ])])) : F("", !0),
455
+ d("div", sn, [
456
+ H(l.$slots, "breadcrumbs", {}, () => [
457
+ (s(!0), c(T, null, I(e.breadcrumbs, (u, f) => (s(), c(T, { key: f }, [
458
+ f > 0 ? (s(), c("span", on, "›")) : F("", !0),
459
+ (s(), k(oe(u.to ? "a" : "span"), {
460
+ href: typeof u.to == "string" ? u.to : void 0,
461
+ class: X(f === a.value ? "cur" : "")
462
+ }, {
463
+ default: m(() => [
464
+ C(h(u.label), 1)
465
+ ]),
466
+ _: 2
467
+ }, 1032, ["href", "class"]))
468
+ ], 64))), 128))
469
+ ])
470
+ ]),
471
+ i[3] || (i[3] = d("div", { class: "admin-topbar__spacer" }, null, -1)),
472
+ H(l.$slots, "search", {}, () => [
473
+ i[2] || (i[2] = d("div", {
474
+ class: "admin-topbar__search",
475
+ role: "button",
476
+ tabindex: "0"
477
+ }, [
478
+ d("span", {
479
+ class: "admin-topbar__icon",
480
+ "data-icon": "search"
481
+ }),
482
+ d("span", null, "Поиск везде…"),
483
+ d("kbd", null, "⌘K")
484
+ ], -1))
485
+ ]),
486
+ H(l.$slots, "actions"),
487
+ x(Zt),
488
+ x(ot),
489
+ x(rt),
490
+ x(an)
491
+ ]));
492
+ }
493
+ }), un = Z("admin-menu", () => {
494
+ const e = E([]), t = E(!1), n = E(null), o = E(!1), a = p(() => {
495
+ const v = Q(), w = (S) => {
496
+ if (Array.isArray(S.permissions) && S.permissions.length > 0 && !v.hasAnyPermission(S.permissions))
497
+ return null;
498
+ const R = (S.children ?? []).map(w).filter((A) => A !== null);
499
+ return { ...S, children: R };
500
+ };
501
+ return e.value.map(w).filter((S) => S !== null);
502
+ }), l = p(() => {
503
+ const v = /* @__PURE__ */ new Map();
504
+ for (const S of a.value) {
505
+ const R = S.group ?? null;
506
+ v.has(R) || v.set(R, []), v.get(R).push(S);
507
+ }
508
+ const w = [];
509
+ for (const [S, R] of v)
510
+ R.sort((A, _) => {
511
+ const g = (A.order ?? 0) - (_.order ?? 0);
512
+ return g !== 0 ? g : A.label.localeCompare(_.label);
513
+ }), w.push({ group: S, items: R });
514
+ return w;
515
+ });
516
+ async function i(v = !1) {
517
+ if (o.value && !v) return e.value;
518
+ t.value = !0, n.value = null;
519
+ try {
520
+ const S = await W().get("/system/menu");
521
+ return e.value = Array.isArray(S.items) ? S.items : [], o.value = !0, e.value;
522
+ } catch (w) {
523
+ throw n.value = w instanceof Error ? w : new Error(String(w)), w;
524
+ } finally {
525
+ t.value = !1;
526
+ }
527
+ }
528
+ function u(v) {
529
+ e.value = v, o.value = !0, n.value = null;
530
+ }
531
+ function f() {
532
+ e.value = [], o.value = !1, n.value = null, t.value = !1;
533
+ }
534
+ return {
535
+ items: e,
536
+ loading: t,
537
+ error: n,
538
+ isLoaded: o,
539
+ visibleItems: a,
540
+ groupedItems: l,
541
+ load: i,
542
+ setItems: u,
543
+ reset: f
544
+ };
545
+ }), dn = { class: "admin-sidebar-brand" }, cn = { class: "admin-sidebar-brand__mark" }, mn = {
546
+ key: 0,
547
+ class: "admin-sidebar-brand__name"
548
+ }, fn = {
549
+ key: 0,
550
+ class: "admin-sidebar-tenant"
551
+ }, vn = { class: "admin-sidebar-foot" }, pn = {
552
+ key: 0,
553
+ class: "admin-sidebar-foot__text"
554
+ }, gn = ["href"], hn = /* @__PURE__ */ L({
555
+ __name: "AdminSidebar",
556
+ props: {
557
+ collapsed: { type: Boolean, default: !1 },
558
+ brandName: { default: "Laravel Admin" },
559
+ brandMark: { default: "L" },
560
+ tenant: { default: null },
561
+ version: { default: null },
562
+ docsUrl: { default: null }
563
+ },
564
+ setup(e) {
565
+ const t = un(), n = pe(), o = p(() => t.groupedItems);
566
+ function a(u) {
567
+ return !!(u.routeName && n.name === u.routeName || u.url && n.path === u.url);
568
+ }
569
+ function l(u) {
570
+ if (u)
571
+ return () => ht("span", { class: "admin-sidebar__icon", "data-icon": u });
572
+ }
573
+ function i(u) {
574
+ if (u.routeName) return { name: u.routeName };
575
+ if (u.url) return u.url;
576
+ }
577
+ return (u, f) => (s(), k(r(At), { collapsed: e.collapsed }, Me({
578
+ header: m(() => [
579
+ d("div", dn, [
580
+ d("div", cn, h(e.brandMark), 1),
581
+ e.collapsed ? F("", !0) : (s(), c("div", mn, h(e.brandName), 1))
582
+ ]),
583
+ e.tenant && !e.collapsed ? (s(), c("div", fn, [
584
+ d("span", null, h(e.tenant.label), 1),
585
+ d("b", null, h(e.tenant.name), 1)
586
+ ])) : F("", !0)
587
+ ]),
588
+ nav: m(() => [
589
+ (s(!0), c(T, null, I(o.value, (v, w) => (s(), k(r(Rt), {
590
+ key: `grp-${w}`,
591
+ title: v.group ?? void 0
592
+ }, {
593
+ default: m(() => [
594
+ (s(!0), c(T, null, I(v.items, (S) => (s(), k(r(Ut), {
595
+ key: S.key,
596
+ to: i(S),
597
+ active: a(S),
598
+ badge: S.badge ?? void 0
599
+ }, Me({
600
+ default: m(() => [
601
+ C(" " + h(S.label), 1)
602
+ ]),
603
+ _: 2
604
+ }, [
605
+ S.icon ? {
606
+ name: "icon",
607
+ fn: m(() => [
608
+ (s(), k(oe(l(S.icon))))
609
+ ]),
610
+ key: "0"
611
+ } : void 0
612
+ ]), 1032, ["to", "active", "badge"]))), 128))
613
+ ]),
614
+ _: 2
615
+ }, 1032, ["title"]))), 128))
616
+ ]),
617
+ _: 2
618
+ }, [
619
+ e.version || e.docsUrl ? {
620
+ name: "footer",
621
+ fn: m(() => [
622
+ d("div", vn, [
623
+ e.version ? (s(), c("span", pn, h(e.version), 1)) : F("", !0),
624
+ e.docsUrl ? (s(), c("a", {
625
+ key: 1,
626
+ href: e.docsUrl,
627
+ class: "admin-sidebar-foot__text admin-sidebar-foot__link"
628
+ }, " Docs ", 8, gn)) : F("", !0)
629
+ ])
630
+ ]),
631
+ key: "0"
632
+ } : void 0
633
+ ]), 1032, ["collapsed"]));
634
+ }
635
+ }), _n = { class: "admin-shell-root" }, yn = {
636
+ key: 0,
637
+ class: "admin-impersonation-banner",
638
+ role: "status"
639
+ }, Pe = "data-admin-impersonating", bn = /* @__PURE__ */ L({
640
+ __name: "AdminShell",
641
+ props: {
642
+ collapsed: { type: Boolean, default: !1 },
643
+ impersonation: { default: null }
644
+ },
645
+ emits: ["update:collapsed", "exit-impersonation"],
646
+ setup(e, { emit: t }) {
647
+ const n = e, o = t;
648
+ function a(i) {
649
+ o("update:collapsed", i);
650
+ }
651
+ function l() {
652
+ o("exit-impersonation");
653
+ }
654
+ return te(
655
+ () => n.impersonation,
656
+ (i) => {
657
+ typeof document > "u" || (i !== null ? document.documentElement.setAttribute(Pe, "true") : document.documentElement.removeAttribute(Pe));
658
+ },
659
+ { immediate: !0 }
660
+ ), _t(() => {
661
+ typeof document < "u" && document.documentElement.removeAttribute(Pe);
662
+ }), (i, u) => (s(), c("div", _n, [
663
+ e.impersonation ? (s(), c("div", yn, [
664
+ d("span", null, [
665
+ u[1] || (u[1] = C(" Вы вошли как ", -1)),
666
+ d("b", null, h(e.impersonation.asName), 1),
667
+ u[2] || (u[2] = C(" · режим имперсонации ", -1))
668
+ ]),
669
+ d("button", {
670
+ type: "button",
671
+ class: "admin-impersonation-banner__exit",
672
+ onClick: l
673
+ }, " Выйти из режима ")
674
+ ])) : F("", !0),
675
+ x(r(Et), {
676
+ "model-value": e.collapsed,
677
+ "onUpdate:modelValue": a
678
+ }, {
679
+ sidebar: m(() => [
680
+ H(i.$slots, "sidebar", {}, () => [
681
+ x(hn, { collapsed: e.collapsed }, null, 8, ["collapsed"])
682
+ ])
683
+ ]),
684
+ header: m(() => [
685
+ H(i.$slots, "topbar", {}, () => [
686
+ x(rn, {
687
+ onToggleSidebar: u[0] || (u[0] = (f) => a(!e.collapsed))
688
+ })
689
+ ])
690
+ ]),
691
+ default: m(() => [
692
+ H(i.$slots, "default")
693
+ ]),
694
+ _: 3
695
+ }, 8, ["model-value"])
696
+ ]));
697
+ }
698
+ }), kn = /* @__PURE__ */ L({
699
+ __name: "AdminApp",
700
+ setup(e) {
701
+ const t = pe(), n = p(() => !(t.meta?.fullscreen === !0 || t.meta?.kind === "auth" || t.name === "admin.notFound"));
702
+ return (o, a) => {
703
+ const l = Ze("router-view");
704
+ return n.value ? (s(), k(bn, { key: 0 }, {
705
+ default: m(() => [
706
+ x(l)
707
+ ]),
708
+ _: 1
709
+ })) : (s(), k(l, { key: 1 }));
710
+ };
711
+ }
712
+ }), ae = Z("admin-manifest", () => {
713
+ const e = E(null), t = E(!1), n = E(null), o = p(() => e.value !== null), a = p(() => e.value?.version ?? null), l = p(() => e.value?.resources ?? []), i = p(() => e.value?.screens ?? []), u = p(() => e.value?.settings ?? []), f = p(() => e.value?.plugins ?? []);
714
+ function v(_) {
715
+ return l.value.find((g) => g.slug === _) ?? null;
716
+ }
717
+ function w(_) {
718
+ return i.value.find((g) => g.slug === _) ?? null;
719
+ }
720
+ function S(_) {
721
+ return u.value.find((g) => g.slug === _) ?? null;
722
+ }
723
+ async function R(_ = !1) {
724
+ if (e.value !== null && !_)
725
+ return e.value;
726
+ t.value = !0, n.value = null;
727
+ try {
728
+ const U = await W().get("/system/manifest");
729
+ return e.value = U, U;
730
+ } catch (g) {
731
+ throw n.value = g instanceof Error ? g : new Error(String(g)), g;
732
+ } finally {
733
+ t.value = !1;
734
+ }
735
+ }
736
+ function A() {
737
+ e.value = null, n.value = null, t.value = !1;
738
+ }
739
+ return {
740
+ // state
741
+ manifest: e,
742
+ loading: t,
743
+ error: n,
744
+ // getters
745
+ isLoaded: o,
746
+ version: a,
747
+ resources: l,
748
+ screens: i,
749
+ settings: u,
750
+ plugins: f,
751
+ // actions
752
+ getResource: v,
753
+ getScreen: w,
754
+ getSettings: S,
755
+ load: R,
756
+ reset: A
757
+ };
758
+ }), wn = { class: "admin-home" }, $n = { class: "admin-home__title" }, xn = {
759
+ key: 0,
760
+ class: "admin-home__resources"
761
+ }, Cn = { class: "admin-home__grid" }, Sn = ["onClick"], An = { class: "admin-home__card-label" }, Rn = { class: "admin-home__card-slug" }, Un = /* @__PURE__ */ L({
762
+ __name: "HomePage",
763
+ setup(e) {
764
+ const t = ae(), n = Q(), o = ne(), a = p(() => n.user?.name ?? ""), l = p(() => t.manifest?.resources ?? []);
765
+ return (i, u) => (s(), c("div", wn, [
766
+ x(r(q), {
767
+ padding: "lg",
768
+ class: "admin-home__hero"
769
+ }, {
770
+ default: m(() => [
771
+ d("h1", $n, "Добро пожаловать" + h(a.value ? ", " + a.value : ""), 1),
772
+ u[0] || (u[0] = d("p", { class: "admin-home__lead" }, " Админ-панель готова. Воспользуйтесь сайдбаром или переходите к ресурсам ниже. ", -1))
773
+ ]),
774
+ _: 1
775
+ }),
776
+ l.value.length ? (s(), c("section", xn, [
777
+ u[1] || (u[1] = d("h2", { class: "admin-home__heading" }, "Ресурсы", -1)),
778
+ d("ul", Cn, [
779
+ (s(!0), c(T, null, I(l.value, (f) => (s(), c("li", {
780
+ key: f.slug
781
+ }, [
782
+ d("button", {
783
+ type: "button",
784
+ class: "admin-home__card",
785
+ onClick: (v) => r(o).push({ name: `admin.resource.${f.slug}.index` })
786
+ }, [
787
+ d("span", An, h(f.label), 1),
788
+ d("span", Rn, h(f.slug), 1)
789
+ ], 8, Sn)
790
+ ]))), 128))
791
+ ])
792
+ ])) : F("", !0)
793
+ ]));
794
+ }
795
+ }), En = { class: "admin-status-page" }, Fn = /* @__PURE__ */ L({
796
+ __name: "ForbiddenPage",
797
+ setup(e) {
798
+ const t = ne();
799
+ return (n, o) => (s(), c("div", En, [
800
+ x(r(q), {
801
+ padding: "lg",
802
+ class: "admin-status-page__card"
803
+ }, {
804
+ default: m(() => [
805
+ o[2] || (o[2] = d("h1", { class: "admin-status-page__code" }, "403", -1)),
806
+ o[3] || (o[3] = d("p", { class: "admin-status-page__message" }, "Доступ запрещён.", -1)),
807
+ x(r(B), {
808
+ variant: "ghost",
809
+ onClick: o[0] || (o[0] = (a) => r(t).replace({ name: "admin.home" }))
810
+ }, {
811
+ default: m(() => [...o[1] || (o[1] = [
812
+ C(" На главную ", -1)
813
+ ])]),
814
+ _: 1
815
+ })
816
+ ]),
817
+ _: 1
818
+ })
819
+ ]));
820
+ }
821
+ }), Ln = { class: "admin-status-page" }, Pn = /* @__PURE__ */ L({
822
+ __name: "NotFoundPage",
823
+ setup(e) {
824
+ const t = ne();
825
+ return (n, o) => (s(), c("div", Ln, [
826
+ x(r(q), {
827
+ padding: "lg",
828
+ class: "admin-status-page__card"
829
+ }, {
830
+ default: m(() => [
831
+ o[2] || (o[2] = d("h1", { class: "admin-status-page__code" }, "404", -1)),
832
+ o[3] || (o[3] = d("p", { class: "admin-status-page__message" }, "Страница не найдена.", -1)),
833
+ x(r(B), {
834
+ variant: "ghost",
835
+ onClick: o[0] || (o[0] = (a) => r(t).replace({ name: "admin.home" }))
836
+ }, {
837
+ default: m(() => [...o[1] || (o[1] = [
838
+ C(" На главную ", -1)
839
+ ])]),
840
+ _: 1
841
+ })
842
+ ]),
843
+ _: 1
844
+ })
845
+ ]));
846
+ }
847
+ }), Tn = { class: "admin-settings-page" }, Mn = { class: "admin-settings-page__title" }, Nn = {
848
+ key: 0,
849
+ class: "admin-settings-page__hint"
850
+ }, In = {
851
+ key: 1,
852
+ class: "admin-settings-page__debug"
853
+ }, Bn = /* @__PURE__ */ L({
854
+ __name: "SettingsPage",
855
+ setup(e) {
856
+ const t = pe(), n = ae(), o = p(() => String(t.params.slug ?? "")), a = p(() => n.manifest?.settings?.find((l) => l.slug === o.value) ?? null);
857
+ return (l, i) => (s(), c("div", Tn, [
858
+ x(r(q), { padding: "lg" }, {
859
+ default: m(() => [
860
+ d("h1", Mn, h(a.value?.label ?? o.value), 1),
861
+ a.value ? (s(), c("pre", In, h(JSON.stringify(a.value.fields, null, 2)), 1)) : (s(), c("p", Nn, " Settings «" + h(o.value) + "» не найдено в manifest'е. ", 1))
862
+ ]),
863
+ _: 1
864
+ })
865
+ ]));
866
+ }
867
+ }), Vn = { class: "admin-status-page" }, zn = { class: "admin-status-page__title" }, qn = { class: "admin-status-page__hint" }, Dn = /* @__PURE__ */ L({
868
+ __name: "UnknownScreenPage",
869
+ setup(e) {
870
+ const t = pe(), n = p(() => String(t.params.slug ?? "")), o = p(() => String(t.meta?.title ?? n.value));
871
+ return (a, l) => (s(), c("div", Vn, [
872
+ x(r(q), {
873
+ padding: "lg",
874
+ class: "admin-status-page__card"
875
+ }, {
876
+ default: m(() => [
877
+ d("h1", zn, h(o.value), 1),
878
+ d("p", qn, [
879
+ C(" Это заглушка для screen «" + h(n.value) + "». Передайте свой компонент через ", 1),
880
+ l[0] || (l[0] = d("code", null, "createAdminApp(" + h("{") + " pages: " + h("{") + " screen: MyScreen " + h("}") + " " + h("}") + ")", -1)),
881
+ l[1] || (l[1] = C(". ", -1))
882
+ ])
883
+ ]),
884
+ _: 1
885
+ })
886
+ ]));
887
+ }
888
+ }), On = { class: "admin-auth-card__row" }, Wn = ["href"], jn = {
889
+ key: 1,
890
+ style: { "text-align": "center", "font-size": "var(--uid-font-size-xs)", color: "var(--uid-text-secondary)", "padding-top": "4px" }
891
+ }, Kn = ["href"], Gn = /* @__PURE__ */ L({
892
+ __name: "LoginForm",
893
+ props: {
894
+ forgotUrl: { default: null },
895
+ ssoLinkLabel: { default: null },
896
+ ssoUrl: { default: null }
897
+ },
898
+ emits: ["success"],
899
+ setup(e, { emit: t }) {
900
+ const n = t, o = Q(), a = E(""), l = E(""), i = E(!1), u = E(!1), f = E(null), v = E({}), w = p(() => v.value.email?.[0]), S = p(() => v.value.password?.[0]);
901
+ async function R() {
902
+ if (!u.value) {
903
+ u.value = !0, f.value = null, v.value = {};
904
+ try {
905
+ const A = await o.login({
906
+ email: a.value,
907
+ password: l.value,
908
+ remember: i.value
909
+ });
910
+ n("success", A);
911
+ } catch (A) {
912
+ A instanceof Re ? (v.value = A.fields, f.value = A.firstFieldMessage()) : A instanceof Ue ? f.value = "Нет соединения с сервером" : A instanceof Y ? f.value = A.message || "Не удалось войти" : f.value = A.message;
913
+ } finally {
914
+ u.value = !1;
915
+ }
916
+ }
917
+ }
918
+ return (A, _) => (s(), c("form", {
919
+ class: "admin-auth-card__bd",
920
+ novalidate: "",
921
+ onSubmit: Ie(R, ["prevent"])
922
+ }, [
923
+ f.value ? (s(), k(r(J), {
924
+ key: 0,
925
+ variant: "danger",
926
+ class: "admin-auth-card__alert",
927
+ role: "alert"
928
+ }, {
929
+ default: m(() => [
930
+ C(h(f.value), 1)
931
+ ]),
932
+ _: 1
933
+ })) : F("", !0),
934
+ x(r(ie), {
935
+ modelValue: a.value,
936
+ "onUpdate:modelValue": _[0] || (_[0] = (g) => a.value = g),
937
+ type: "email",
938
+ label: "Email",
939
+ placeholder: "you@company.com",
940
+ autocomplete: "username",
941
+ required: !0,
942
+ disabled: u.value,
943
+ error: w.value,
944
+ name: "email"
945
+ }, null, 8, ["modelValue", "disabled", "error"]),
946
+ x(r(ie), {
947
+ modelValue: l.value,
948
+ "onUpdate:modelValue": _[1] || (_[1] = (g) => l.value = g),
949
+ type: "password",
950
+ label: "Пароль",
951
+ autocomplete: "current-password",
952
+ required: !0,
953
+ disabled: u.value,
954
+ error: S.value,
955
+ name: "password"
956
+ }, null, 8, ["modelValue", "disabled", "error"]),
957
+ d("div", On, [
958
+ x(r(we), {
959
+ modelValue: i.value,
960
+ "onUpdate:modelValue": _[2] || (_[2] = (g) => i.value = g),
961
+ disabled: u.value
962
+ }, {
963
+ default: m(() => [..._[3] || (_[3] = [
964
+ C(" Запомнить меня ", -1)
965
+ ])]),
966
+ _: 1
967
+ }, 8, ["modelValue", "disabled"]),
968
+ e.forgotUrl ? (s(), c("a", {
969
+ key: 0,
970
+ href: e.forgotUrl,
971
+ class: "admin-auth-card__link"
972
+ }, " Забыли пароль? ", 8, Wn)) : F("", !0)
973
+ ]),
974
+ x(r(B), {
975
+ type: "submit",
976
+ variant: "primary",
977
+ size: "lg",
978
+ loading: u.value,
979
+ disabled: u.value
980
+ }, {
981
+ default: m(() => [
982
+ C(h(u.value ? "Вход…" : "Войти"), 1)
983
+ ]),
984
+ _: 1
985
+ }, 8, ["loading", "disabled"]),
986
+ e.ssoLinkLabel && e.ssoUrl ? (s(), c("div", jn, [
987
+ _[4] || (_[4] = C(" или войдите через ", -1)),
988
+ d("a", {
989
+ href: e.ssoUrl,
990
+ class: "admin-auth-card__link"
991
+ }, h(e.ssoLinkLabel), 9, Kn)
992
+ ])) : F("", !0)
993
+ ], 32));
994
+ }
995
+ }), Hn = ["value", "disabled", "aria-label", "onInput", "onKeydown"], Xn = { class: "admin-auth-card__row" }, Jn = /* @__PURE__ */ L({
996
+ __name: "TwoFactorForm",
997
+ emits: ["success", "cancel"],
998
+ setup(e, { emit: t }) {
999
+ const n = t, o = Q(), a = E("totp"), l = E(["", "", "", "", "", ""]), i = E(""), u = E([]), f = E(!1), v = E(null), w = E(null), S = p(() => l.value.join("")), R = p(() => a.value === "totp" ? S.value.length === 6 : i.value.trim().length > 0);
1000
+ function A($, V) {
1001
+ V instanceof HTMLInputElement && (u.value[$] = V);
1002
+ }
1003
+ function _($, V) {
1004
+ const j = V.target, D = j.value.replace(/\D/g, "").slice(-1);
1005
+ l.value[$] = D, j.value = D, D && $ < l.value.length - 1 && Le(() => u.value[$ + 1]?.focus()), S.value.length === l.value.length && P();
1006
+ }
1007
+ function g($, V) {
1008
+ V.key === "Backspace" && !l.value[$] && $ > 0 ? Le(() => u.value[$ - 1]?.focus()) : V.key === "ArrowLeft" && $ > 0 ? (u.value[$ - 1]?.focus(), V.preventDefault()) : V.key === "ArrowRight" && $ < l.value.length - 1 && (u.value[$ + 1]?.focus(), V.preventDefault());
1009
+ }
1010
+ function U($) {
1011
+ const j = ($.clipboardData?.getData("text") ?? "").replace(/\D/g, "").slice(0, l.value.length);
1012
+ if (j.length !== 0) {
1013
+ $.preventDefault();
1014
+ for (let D = 0; D < l.value.length; D++)
1015
+ l.value[D] = j[D] ?? "";
1016
+ Le(() => {
1017
+ u.value[Math.min(j.length, l.value.length - 1)]?.focus(), j.length === l.value.length && P();
1018
+ });
1019
+ }
1020
+ }
1021
+ async function P() {
1022
+ if (!(f.value || !R.value)) {
1023
+ f.value = !0, v.value = null;
1024
+ try {
1025
+ if (a.value === "totp")
1026
+ await o.twoFactorChallenge(S.value);
1027
+ else {
1028
+ const $ = await o.twoFactorRecovery(i.value.trim());
1029
+ w.value = $.remaining;
1030
+ }
1031
+ n("success");
1032
+ } catch ($) {
1033
+ $ instanceof Re ? v.value = $.firstFieldMessage() ?? "Неверный код" : $ instanceof Ue ? v.value = "Нет соединения с сервером" : $ instanceof Y ? v.value = $.message || "Не удалось проверить код" : v.value = $.message;
1034
+ } finally {
1035
+ f.value = !1;
1036
+ }
1037
+ }
1038
+ }
1039
+ function b() {
1040
+ o.cancelChallenge(), n("cancel");
1041
+ }
1042
+ function y() {
1043
+ a.value = a.value === "totp" ? "recovery" : "totp", v.value = null;
1044
+ }
1045
+ return ($, V) => (s(), c("form", {
1046
+ class: "admin-auth-card__bd",
1047
+ novalidate: "",
1048
+ onSubmit: Ie(P, ["prevent"])
1049
+ }, [
1050
+ v.value ? (s(), k(r(J), {
1051
+ key: 0,
1052
+ variant: "danger",
1053
+ class: "admin-auth-card__alert",
1054
+ role: "alert"
1055
+ }, {
1056
+ default: m(() => [
1057
+ C(h(v.value), 1)
1058
+ ]),
1059
+ _: 1
1060
+ })) : F("", !0),
1061
+ w.value !== null ? (s(), k(r(J), {
1062
+ key: 1,
1063
+ variant: "info",
1064
+ class: "admin-auth-card__alert",
1065
+ role: "status"
1066
+ }, {
1067
+ default: m(() => [
1068
+ C(" Использован recovery-код. Осталось: " + h(w.value), 1)
1069
+ ]),
1070
+ _: 1
1071
+ })) : F("", !0),
1072
+ a.value === "totp" ? (s(), c("div", {
1073
+ key: 2,
1074
+ class: "admin-code-input",
1075
+ onPaste: U
1076
+ }, [
1077
+ (s(!0), c(T, null, I(l.value, (j, D) => (s(), c("input", {
1078
+ key: D,
1079
+ ref_for: !0,
1080
+ ref: (M) => A(D, M),
1081
+ value: l.value[D],
1082
+ type: "text",
1083
+ inputmode: "numeric",
1084
+ autocomplete: "one-time-code",
1085
+ maxlength: "1",
1086
+ disabled: f.value,
1087
+ "aria-label": `Цифра ${D + 1}`,
1088
+ onInput: (M) => _(D, M),
1089
+ onKeydown: (M) => g(D, M)
1090
+ }, null, 40, Hn))), 128))
1091
+ ], 32)) : (s(), k(r(ie), {
1092
+ key: 3,
1093
+ modelValue: i.value,
1094
+ "onUpdate:modelValue": V[0] || (V[0] = (j) => i.value = j),
1095
+ type: "text",
1096
+ label: "Recovery-код",
1097
+ autocomplete: "one-time-code",
1098
+ disabled: f.value,
1099
+ name: "recovery-code"
1100
+ }, null, 8, ["modelValue", "disabled"])),
1101
+ x(r(B), {
1102
+ type: "submit",
1103
+ variant: "primary",
1104
+ size: "lg",
1105
+ loading: f.value,
1106
+ disabled: f.value || !R.value
1107
+ }, {
1108
+ default: m(() => [
1109
+ C(h(f.value ? "Проверка…" : "Подтвердить"), 1)
1110
+ ]),
1111
+ _: 1
1112
+ }, 8, ["loading", "disabled"]),
1113
+ d("div", Xn, [
1114
+ d("button", {
1115
+ type: "button",
1116
+ class: "admin-auth-card__link",
1117
+ onClick: y
1118
+ }, [
1119
+ a.value === "totp" ? (s(), c(T, { key: 0 }, [
1120
+ C("Использовать recovery-код")
1121
+ ], 64)) : (s(), c(T, { key: 1 }, [
1122
+ C("Вернуться к коду из приложения")
1123
+ ], 64))
1124
+ ]),
1125
+ d("button", {
1126
+ type: "button",
1127
+ class: "admin-auth-card__link",
1128
+ onClick: b
1129
+ }, " Отмена ")
1130
+ ])
1131
+ ], 32));
1132
+ }
1133
+ }), Yn = { class: "admin-auth-page" }, Qn = {
1134
+ key: 0,
1135
+ class: "admin-auth-page__corner"
1136
+ }, Zn = { class: "admin-auth-card__hd" }, ea = ["src", "alt"], ta = {
1137
+ key: 1,
1138
+ "aria-hidden": "true"
1139
+ }, na = { key: 2 }, aa = { class: "admin-auth-card__title" }, la = { class: "admin-auth-card__sub" }, sa = /* @__PURE__ */ L({
1140
+ __name: "LoginPage",
1141
+ props: {
1142
+ brandName: { default: "Laravel Admin" },
1143
+ brandMark: { default: "L" },
1144
+ brandLogo: { default: null },
1145
+ homeRouteName: { default: "admin.home" },
1146
+ redirectQueryKey: { default: "redirect" },
1147
+ forgotUrl: { default: null },
1148
+ ssoLinkLabel: { default: null },
1149
+ ssoUrl: { default: null },
1150
+ showCornerActions: { type: Boolean, default: !0 }
1151
+ },
1152
+ setup(e) {
1153
+ const t = e, n = Q(), o = ne(), a = pe();
1154
+ async function l() {
1155
+ const i = a.query[t.redirectQueryKey];
1156
+ if (typeof i == "string" && i.length > 0 && i.startsWith("/")) {
1157
+ await o.push(i);
1158
+ return;
1159
+ }
1160
+ await o.push({ name: t.homeRouteName });
1161
+ }
1162
+ return te(
1163
+ () => n.isAuthenticated,
1164
+ (i) => {
1165
+ i && l();
1166
+ }
1167
+ ), xe(() => {
1168
+ n.isAuthenticated && l();
1169
+ }), (i, u) => (s(), c("div", Yn, [
1170
+ e.showCornerActions ? (s(), c("div", Qn, [
1171
+ x(ot),
1172
+ x(rt)
1173
+ ])) : F("", !0),
1174
+ x(r(q), {
1175
+ class: X(["admin-auth-card", r(n).isChallengePending ? "admin-auth-card--wide" : ""]),
1176
+ padding: "none"
1177
+ }, {
1178
+ default: m(() => [
1179
+ d("div", Zn, [
1180
+ d("div", {
1181
+ class: X(["admin-auth-card__logo", r(n).isChallengePending ? "admin-auth-card__logo--accent" : ""])
1182
+ }, [
1183
+ e.brandLogo && !r(n).isChallengePending ? (s(), c("img", {
1184
+ key: 0,
1185
+ src: e.brandLogo,
1186
+ alt: e.brandName
1187
+ }, null, 8, ea)) : r(n).isChallengePending ? (s(), c("span", ta, "🛡")) : (s(), c("span", na, h(e.brandMark), 1))
1188
+ ], 2),
1189
+ d("div", aa, [
1190
+ r(n).isChallengePending ? (s(), c(T, { key: 0 }, [
1191
+ C("Двухфакторная проверка")
1192
+ ], 64)) : (s(), c(T, { key: 1 }, [
1193
+ C(h(e.brandName), 1)
1194
+ ], 64))
1195
+ ]),
1196
+ d("div", la, [
1197
+ r(n).isChallengePending ? (s(), c(T, { key: 0 }, [
1198
+ C(" Введите 6-значный код из приложения-аутентификатора ")
1199
+ ], 64)) : (s(), c(T, { key: 1 }, [
1200
+ C("Войдите, чтобы продолжить работу")
1201
+ ], 64))
1202
+ ])
1203
+ ]),
1204
+ r(n).isChallengePending ? (s(), k(Jn, {
1205
+ key: 0,
1206
+ onSuccess: u[0] || (u[0] = () => {
1207
+ }),
1208
+ onCancel: u[1] || (u[1] = () => {
1209
+ })
1210
+ })) : (s(), k(Gn, {
1211
+ key: 1,
1212
+ "forgot-url": e.forgotUrl,
1213
+ "sso-link-label": e.ssoLinkLabel,
1214
+ "sso-url": e.ssoUrl,
1215
+ onSuccess: u[2] || (u[2] = () => {
1216
+ })
1217
+ }, null, 8, ["forgot-url", "sso-link-label", "sso-url"]))
1218
+ ]),
1219
+ _: 1
1220
+ }, 8, ["class"])
1221
+ ]));
1222
+ }
1223
+ }), Ke = { page: 1, per_page: 20, total: 0, last_page: 1 }, ia = Z("admin-resource-index", () => {
1224
+ const e = E(null), t = E([]), n = E({ ...Ke }), o = E(!1), a = E(null), l = E(""), i = E({}), u = E(null), f = E("asc"), v = E(/* @__PURE__ */ new Set()), w = p(() => !o.value && a.value === null && t.value.length === 0), S = p(() => v.value.size), R = p(() => v.value.size > 0), A = p(() => a.value !== null), _ = p(() => v.value.size === 0 || t.value.length === 0 ? "none" : t.value.every((z) => v.value.has(g(z))) ? "all" : "mixed");
1225
+ function g(N) {
1226
+ return N.id ?? N.key ?? "";
1227
+ }
1228
+ function U(N) {
1229
+ e.value !== N && (e.value = N, P());
1230
+ }
1231
+ function P() {
1232
+ t.value = [], n.value = { ...Ke }, o.value = !1, a.value = null, l.value = "", i.value = {}, u.value = null, f.value = "asc", v.value = /* @__PURE__ */ new Set();
1233
+ }
1234
+ function b(N = {}) {
1235
+ const z = {
1236
+ page: N.page ?? n.value.page,
1237
+ per_page: N.per_page ?? n.value.per_page
1238
+ }, _e = N.search ?? l.value;
1239
+ _e && (z.search = _e);
1240
+ const fe = N.sort ?? u.value;
1241
+ fe && (z.sort = fe, z.direction = N.direction ?? f.value);
1242
+ const pt = N.filters ?? i.value;
1243
+ for (const [gt, le] of Object.entries(pt))
1244
+ le == null || le === "" || (z[`filter[${gt}]`] = Array.isArray(le) ? le.join(",") : String(le));
1245
+ return z;
1246
+ }
1247
+ async function y(N = {}) {
1248
+ if (!e.value)
1249
+ throw new Error("useResourceIndexStore.load() called before setSlug()");
1250
+ o.value = !0, a.value = null;
1251
+ try {
1252
+ const z = W(), _e = b(N), fe = await z.get(`/resources/${e.value}/list`, { params: _e });
1253
+ t.value = fe.data, n.value = fe.meta;
1254
+ } catch (z) {
1255
+ throw a.value = z instanceof Error ? z : new Error(String(z)), z;
1256
+ } finally {
1257
+ o.value = !1;
1258
+ }
1259
+ }
1260
+ async function $(N) {
1261
+ l.value = N, n.value.page = 1, await y();
1262
+ }
1263
+ async function V(N, z) {
1264
+ z == null || z === "" ? delete i.value[N] : i.value[N] = z, n.value.page = 1, await y();
1265
+ }
1266
+ async function j() {
1267
+ i.value = {}, n.value.page = 1, await y();
1268
+ }
1269
+ async function D(N, z = "asc") {
1270
+ u.value = N, f.value = z, await y();
1271
+ }
1272
+ async function M(N) {
1273
+ u.value === N ? f.value = f.value === "asc" ? "desc" : "asc" : (u.value = N, f.value = "asc"), await y();
1274
+ }
1275
+ async function O(N) {
1276
+ n.value.page = N, await y();
1277
+ }
1278
+ function G(N) {
1279
+ const z = new Set(v.value);
1280
+ z.has(N) ? z.delete(N) : z.add(N), v.value = z;
1281
+ }
1282
+ function K() {
1283
+ if (_.value === "all") {
1284
+ v.value = /* @__PURE__ */ new Set();
1285
+ return;
1286
+ }
1287
+ const N = new Set(v.value);
1288
+ for (const z of t.value) N.add(g(z));
1289
+ v.value = N;
1290
+ }
1291
+ function ee() {
1292
+ v.value = /* @__PURE__ */ new Set();
1293
+ }
1294
+ function vt(N) {
1295
+ return v.value.has(N);
1296
+ }
1297
+ return {
1298
+ // state
1299
+ slug: e,
1300
+ items: t,
1301
+ meta: n,
1302
+ loading: o,
1303
+ error: a,
1304
+ search: l,
1305
+ filters: i,
1306
+ sortKey: u,
1307
+ sortDirection: f,
1308
+ selection: v,
1309
+ // getters
1310
+ isEmpty: w,
1311
+ hasError: A,
1312
+ hasSelection: R,
1313
+ selectedCount: S,
1314
+ selectionState: _,
1315
+ // actions
1316
+ setSlug: U,
1317
+ reset: P,
1318
+ load: y,
1319
+ setSearch: $,
1320
+ setFilter: V,
1321
+ clearFilters: j,
1322
+ setSort: D,
1323
+ toggleSort: M,
1324
+ setPage: O,
1325
+ toggleRow: G,
1326
+ toggleAllOnPage: K,
1327
+ clearSelection: ee,
1328
+ isSelected: vt,
1329
+ rowId: g
1330
+ };
1331
+ }), oa = { class: "admin-page admin-resource-index" }, ra = { class: "admin-page__hd" }, ua = { class: "admin-page__title-wrap" }, da = { class: "admin-page__title" }, ca = {
1332
+ key: 0,
1333
+ class: "admin-page__count"
1334
+ }, ma = { class: "admin-page__actions" }, fa = {
1335
+ key: 0,
1336
+ class: "admin-bulk-toolbar",
1337
+ role: "toolbar"
1338
+ }, va = { class: "admin-bulk-toolbar__count" }, pa = {
1339
+ key: 1,
1340
+ class: "admin-filter-bar"
1341
+ }, ga = ["value"], ha = {
1342
+ key: 2,
1343
+ class: "admin-resource-index__loading"
1344
+ }, _a = {
1345
+ key: 5,
1346
+ class: "admin-resource-index__table"
1347
+ }, ya = { class: "admin-resource-index__select-header" }, ba = { class: "admin-resource-index__select-overlay" }, ka = ["onClick"], wa = {
1348
+ key: 6,
1349
+ class: "admin-resource-index__footer"
1350
+ }, $a = /* @__PURE__ */ L({
1351
+ __name: "ResourceIndexPage",
1352
+ props: {
1353
+ slug: {},
1354
+ title: { default: null },
1355
+ subtitle: { default: null },
1356
+ createLabel: { default: "Создать" },
1357
+ createRouteName: { default: null }
1358
+ },
1359
+ emits: ["bulk-action", "row-click"],
1360
+ setup(e, { emit: t }) {
1361
+ const n = e, o = t, a = ia(), l = ae(), i = p(() => l.getResource(n.slug)), u = p(
1362
+ () => n.title ?? i.value?.label ?? n.slug
1363
+ ), f = p(() => (i.value?.columns ?? []).map((b) => {
1364
+ const y = b;
1365
+ return {
1366
+ key: String(y.key ?? y.name ?? ""),
1367
+ label: String(y.label ?? y.name ?? ""),
1368
+ sortable: !!y.sortable,
1369
+ align: y.align ?? "left",
1370
+ width: typeof y.width == "string" ? y.width : void 0
1371
+ };
1372
+ }).filter((b) => b.key)), v = p(() => {
1373
+ const P = a.meta.total;
1374
+ return P === 0 ? "" : `${a.items.length} из ${P}`;
1375
+ });
1376
+ xe(async () => {
1377
+ a.setSlug(n.slug), l.manifest === null && await l.load().catch(() => {
1378
+ }), await a.load().catch(() => {
1379
+ });
1380
+ }), te(
1381
+ () => n.slug,
1382
+ async (P, b) => {
1383
+ P !== b && (a.setSlug(P), await a.load().catch(() => {
1384
+ }));
1385
+ }
1386
+ );
1387
+ async function w(P) {
1388
+ await a.toggleSort(P);
1389
+ }
1390
+ async function S(P) {
1391
+ await a.setPage(P);
1392
+ }
1393
+ function R() {
1394
+ a.toggleAllOnPage();
1395
+ }
1396
+ function A(P) {
1397
+ a.toggleRow(P);
1398
+ }
1399
+ function _(P) {
1400
+ o("row-click", P);
1401
+ }
1402
+ function g(P) {
1403
+ o("bulk-action", P, [...a.selection]);
1404
+ }
1405
+ async function U() {
1406
+ await a.load().catch(() => {
1407
+ });
1408
+ }
1409
+ return (P, b) => (s(), c("section", oa, [
1410
+ d("header", ra, [
1411
+ d("div", ua, [
1412
+ d("h1", da, h(u.value), 1),
1413
+ e.subtitle || v.value ? (s(), c("div", ca, [
1414
+ e.subtitle ? (s(), c(T, { key: 0 }, [
1415
+ C(h(e.subtitle), 1)
1416
+ ], 64)) : F("", !0),
1417
+ e.subtitle && v.value ? (s(), c(T, { key: 1 }, [
1418
+ C(" · ")
1419
+ ], 64)) : F("", !0),
1420
+ v.value ? (s(), c(T, { key: 2 }, [
1421
+ C(h(v.value), 1)
1422
+ ], 64)) : F("", !0)
1423
+ ])) : F("", !0)
1424
+ ]),
1425
+ d("div", ma, [
1426
+ H(P.$slots, "actions"),
1427
+ e.createRouteName ? (s(), k(r(B), {
1428
+ key: 0,
1429
+ variant: "primary",
1430
+ onClick: b[0] || (b[0] = (y) => P.$router.push({ name: e.createRouteName }))
1431
+ }, {
1432
+ default: m(() => [
1433
+ C(h(e.createLabel), 1)
1434
+ ]),
1435
+ _: 1
1436
+ })) : F("", !0)
1437
+ ])
1438
+ ]),
1439
+ r(a).hasSelection ? (s(), c("div", fa, [
1440
+ d("span", va, [
1441
+ b[8] || (b[8] = C(" Выбрано ", -1)),
1442
+ d("b", null, h(r(a).selectedCount), 1)
1443
+ ]),
1444
+ b[14] || (b[14] = d("span", { class: "admin-bulk-toolbar__divider" }, null, -1)),
1445
+ x(r(B), {
1446
+ size: "sm",
1447
+ variant: "ghost",
1448
+ onClick: b[1] || (b[1] = (y) => g("publish"))
1449
+ }, {
1450
+ default: m(() => [...b[9] || (b[9] = [
1451
+ C("Опубликовать", -1)
1452
+ ])]),
1453
+ _: 1
1454
+ }),
1455
+ x(r(B), {
1456
+ size: "sm",
1457
+ variant: "ghost",
1458
+ onClick: b[2] || (b[2] = (y) => g("archive"))
1459
+ }, {
1460
+ default: m(() => [...b[10] || (b[10] = [
1461
+ C("Архивировать", -1)
1462
+ ])]),
1463
+ _: 1
1464
+ }),
1465
+ x(r(B), {
1466
+ size: "sm",
1467
+ variant: "ghost",
1468
+ onClick: b[3] || (b[3] = (y) => g("export"))
1469
+ }, {
1470
+ default: m(() => [...b[11] || (b[11] = [
1471
+ C("Экспорт", -1)
1472
+ ])]),
1473
+ _: 1
1474
+ }),
1475
+ x(r(B), {
1476
+ size: "sm",
1477
+ variant: "danger",
1478
+ onClick: b[4] || (b[4] = (y) => g("delete"))
1479
+ }, {
1480
+ default: m(() => [...b[12] || (b[12] = [
1481
+ C("Удалить", -1)
1482
+ ])]),
1483
+ _: 1
1484
+ }),
1485
+ b[15] || (b[15] = d("span", { class: "admin-bulk-toolbar__spacer" }, null, -1)),
1486
+ x(r(B), {
1487
+ size: "sm",
1488
+ variant: "ghost",
1489
+ onClick: r(a).clearSelection
1490
+ }, {
1491
+ default: m(() => [...b[13] || (b[13] = [
1492
+ C(" Снять выделение ", -1)
1493
+ ])]),
1494
+ _: 1
1495
+ }, 8, ["onClick"])
1496
+ ])) : (s(), c("div", pa, [
1497
+ d("input", {
1498
+ value: r(a).search,
1499
+ type: "search",
1500
+ placeholder: "Поиск…",
1501
+ class: "admin-filter-bar__search",
1502
+ onKeydown: b[5] || (b[5] = yt((y) => r(a).setSearch(y.target.value), ["enter"]))
1503
+ }, null, 40, ga),
1504
+ H(P.$slots, "filters", {
1505
+ filters: r(a).filters,
1506
+ setFilter: r(a).setFilter
1507
+ }),
1508
+ b[17] || (b[17] = d("span", { class: "admin-filter-bar__spacer" }, null, -1)),
1509
+ Object.keys(r(a).filters).length > 0 ? (s(), k(r(B), {
1510
+ key: 0,
1511
+ size: "sm",
1512
+ variant: "ghost",
1513
+ onClick: r(a).clearFilters
1514
+ }, {
1515
+ default: m(() => [...b[16] || (b[16] = [
1516
+ C(" Сброс ", -1)
1517
+ ])]),
1518
+ _: 1
1519
+ }, 8, ["onClick"])) : F("", !0)
1520
+ ])),
1521
+ r(a).loading ? (s(), c("div", ha, [
1522
+ (s(), c(T, null, I(8, (y) => x(r(Be), {
1523
+ key: y,
1524
+ height: "40px"
1525
+ })), 64))
1526
+ ])) : r(a).hasError ? (s(), k(r(Ft), {
1527
+ key: 3,
1528
+ title: "Не удалось загрузить данные",
1529
+ description: r(a).error?.message ?? "Попробуйте обновить страницу.",
1530
+ class: "admin-resource-index__state"
1531
+ }, {
1532
+ actions: m(() => [
1533
+ x(r(B), {
1534
+ variant: "primary",
1535
+ onClick: U
1536
+ }, {
1537
+ default: m(() => [...b[18] || (b[18] = [
1538
+ C("Обновить", -1)
1539
+ ])]),
1540
+ _: 1
1541
+ })
1542
+ ]),
1543
+ _: 1
1544
+ }, 8, ["description"])) : r(a).isEmpty ? (s(), k(r(Lt), {
1545
+ key: 4,
1546
+ title: "Пока пусто",
1547
+ description: "Создайте первую запись или измените фильтры.",
1548
+ class: "admin-resource-index__state"
1549
+ }, {
1550
+ actions: m(() => [
1551
+ e.createRouteName ? (s(), k(r(B), {
1552
+ key: 0,
1553
+ variant: "primary",
1554
+ onClick: b[6] || (b[6] = (y) => P.$router.push({ name: e.createRouteName }))
1555
+ }, {
1556
+ default: m(() => [
1557
+ C(h(e.createLabel), 1)
1558
+ ]),
1559
+ _: 1
1560
+ })) : F("", !0)
1561
+ ]),
1562
+ _: 1
1563
+ })) : (s(), c("div", _a, [
1564
+ d("div", ya, [
1565
+ x(r(we), {
1566
+ "model-value": r(a).selectionState === "all",
1567
+ indeterminate: r(a).selectionState === "mixed",
1568
+ "aria-label": "Выделить всё",
1569
+ "onUpdate:modelValue": R
1570
+ }, null, 8, ["model-value", "indeterminate"])
1571
+ ]),
1572
+ x(r(Ve), {
1573
+ columns: f.value,
1574
+ data: r(a).items,
1575
+ "sort-key": r(a).sortKey ?? "",
1576
+ "sort-direction": r(a).sortDirection,
1577
+ "onUpdate:sortKey": w
1578
+ }, Me({ _: 2 }, [
1579
+ I(f.value, (y) => ({
1580
+ name: `cell-${y.key}`,
1581
+ fn: m(($) => [
1582
+ H(P.$slots, `cell-${y.key}`, { row: $ }, () => [
1583
+ C(h($?.[y.key]), 1)
1584
+ ])
1585
+ ])
1586
+ }))
1587
+ ]), 1032, ["columns", "data", "sort-key", "sort-direction"]),
1588
+ d("div", ba, [
1589
+ (s(!0), c(T, null, I(r(a).items, (y) => (s(), c("div", {
1590
+ key: String(r(a).rowId(y)),
1591
+ class: X([
1592
+ "admin-resource-index__row",
1593
+ { "admin-resource-index__row--selected": r(a).isSelected(r(a).rowId(y)) }
1594
+ ]),
1595
+ onClick: ($) => _(y)
1596
+ }, [
1597
+ x(r(we), {
1598
+ "model-value": r(a).isSelected(r(a).rowId(y)),
1599
+ "aria-label": `Строка ${r(a).rowId(y)}`,
1600
+ "onUpdate:modelValue": ($) => A(r(a).rowId(y)),
1601
+ onClick: b[7] || (b[7] = Ie(() => {
1602
+ }, ["stop"]))
1603
+ }, null, 8, ["model-value", "aria-label", "onUpdate:modelValue"])
1604
+ ], 10, ka))), 128))
1605
+ ])
1606
+ ])),
1607
+ !r(a).loading && !r(a).hasError && !r(a).isEmpty ? (s(), c("footer", wa, [
1608
+ x(r(Pt), {
1609
+ "model-value": r(a).meta.page,
1610
+ total: r(a).meta.total,
1611
+ "per-page": r(a).meta.per_page,
1612
+ "onUpdate:modelValue": S
1613
+ }, null, 8, ["model-value", "total", "per-page"])
1614
+ ])) : F("", !0)
1615
+ ]));
1616
+ }
1617
+ }), dt = Z("admin-resource-form", () => {
1618
+ const e = E(null), t = E("create"), n = E(null), o = E({}), a = E({}), l = E({}), i = E(!1), u = E(!1), f = E(!1), v = E(null), w = p(() => t.value === "create"), S = p(() => t.value === "edit"), R = p(() => t.value === "view"), A = p(() => v.value !== null), _ = p(() => {
1619
+ const M = o.value, O = a.value, G = /* @__PURE__ */ new Set([...Object.keys(M), ...Object.keys(O)]);
1620
+ for (const K of G)
1621
+ if (!Object.is(M[K], O[K]))
1622
+ if (typeof M[K] == "object" || typeof O[K] == "object") {
1623
+ if (JSON.stringify(M[K]) !== JSON.stringify(O[K])) return !0;
1624
+ } else
1625
+ return !0;
1626
+ return !1;
1627
+ });
1628
+ function g(M, O) {
1629
+ for (const G of Object.keys(M)) delete M[G];
1630
+ Object.assign(M, O);
1631
+ }
1632
+ function U() {
1633
+ g(o.value, {}), g(a.value, {}), l.value = {}, i.value = !1, u.value = !1, f.value = !1, v.value = null, n.value = null;
1634
+ }
1635
+ function P(M, O = {}) {
1636
+ e.value = M, t.value = "create", n.value = null, g(o.value, O), g(a.value, O), l.value = {}, v.value = null;
1637
+ }
1638
+ async function b(M, O, G = "edit") {
1639
+ e.value = M, t.value = G, n.value = O, i.value = !0, v.value = null, l.value = {};
1640
+ try {
1641
+ const ee = await W().get(`/resources/${M}/read`, {
1642
+ params: { "filter[id]": O }
1643
+ });
1644
+ g(o.value, ee.data), g(a.value, ee.data);
1645
+ } catch (K) {
1646
+ throw v.value = K instanceof Error ? K : new Error(String(K)), K;
1647
+ } finally {
1648
+ i.value = !1;
1649
+ }
1650
+ }
1651
+ function y(M, O) {
1652
+ if (o.value[M] = O, l.value[M]) {
1653
+ const G = { ...l.value };
1654
+ delete G[M], l.value = G;
1655
+ }
1656
+ }
1657
+ function $(M) {
1658
+ l.value = { ...M };
1659
+ }
1660
+ function V() {
1661
+ l.value = {};
1662
+ }
1663
+ async function j() {
1664
+ if (!e.value) throw new Error("useResourceFormStore.save() before slug set");
1665
+ if (u.value) throw new Error("Already saving");
1666
+ u.value = !0, v.value = null, l.value = {};
1667
+ try {
1668
+ const M = W(), O = t.value === "create" ? `/resources/${e.value}/create` : `/resources/${e.value}/update`, G = t.value === "create" ? o.value : { id: n.value, ...o.value }, ee = (await M.post(O, G)).id;
1669
+ return n.value = ee, g(a.value, { ...o.value }), t.value = "edit", ee;
1670
+ } catch (M) {
1671
+ throw M instanceof Re ? l.value = { ...M.fields } : (M instanceof Y || M instanceof Error) && (v.value = M), M;
1672
+ } finally {
1673
+ u.value = !1;
1674
+ }
1675
+ }
1676
+ async function D() {
1677
+ if (!e.value || n.value === null)
1678
+ throw new Error("Nothing to delete");
1679
+ if (f.value) throw new Error("Already deleting");
1680
+ f.value = !0, v.value = null;
1681
+ try {
1682
+ await W().post(`/resources/${e.value}/destroy`, { id: n.value });
1683
+ } catch (M) {
1684
+ throw M instanceof Error && (v.value = M), M;
1685
+ } finally {
1686
+ f.value = !1;
1687
+ }
1688
+ }
1689
+ return {
1690
+ // state
1691
+ slug: e,
1692
+ mode: t,
1693
+ recordId: n,
1694
+ state: o,
1695
+ initial: a,
1696
+ errors: l,
1697
+ loading: i,
1698
+ saving: u,
1699
+ deleting: f,
1700
+ error: v,
1701
+ // getters
1702
+ isCreate: w,
1703
+ isEdit: S,
1704
+ isView: R,
1705
+ isDirty: _,
1706
+ hasError: A,
1707
+ // actions
1708
+ reset: U,
1709
+ prepareCreate: P,
1710
+ load: b,
1711
+ setField: y,
1712
+ setErrors: $,
1713
+ clearErrors: V,
1714
+ save: j,
1715
+ destroy: D
1716
+ };
1717
+ });
1718
+ function Ee() {
1719
+ const e = /* @__PURE__ */ new Map();
1720
+ return {
1721
+ register(t, n) {
1722
+ e.set(t, n);
1723
+ },
1724
+ get(t) {
1725
+ return e.get(t) ?? null;
1726
+ },
1727
+ has(t) {
1728
+ return e.has(t);
1729
+ },
1730
+ list() {
1731
+ return [...e.keys()];
1732
+ },
1733
+ clear() {
1734
+ e.clear();
1735
+ },
1736
+ registerBundle(t) {
1737
+ for (const [n, o] of Object.entries(t))
1738
+ e.set(n, o);
1739
+ }
1740
+ };
1741
+ }
1742
+ const ue = Ee(), de = Ee(), Bi = ue.register, ct = ue.get, Vi = ue.has, zi = ue.list, qi = de.register, Ge = de.get, Di = de.has, Oi = de.list;
1743
+ function Wi() {
1744
+ ue.clear(), de.clear();
1745
+ }
1746
+ function xa(e) {
1747
+ e.fields && ue.registerBundle(e.fields), e.layouts && de.registerBundle(e.layouts);
1748
+ }
1749
+ const mt = /* @__PURE__ */ L({
1750
+ __name: "UnknownField",
1751
+ props: {
1752
+ type: {},
1753
+ name: {}
1754
+ },
1755
+ setup(e) {
1756
+ return (t, n) => (s(), k(r(J), { variant: "warning" }, {
1757
+ title: m(() => [
1758
+ C("Неизвестный тип поля: " + h(e.type), 1)
1759
+ ]),
1760
+ default: m(() => [
1761
+ e.name ? (s(), c(T, { key: 0 }, [
1762
+ d("code", null, h(e.name), 1),
1763
+ n[0] || (n[0] = C(" — зарегистрируйте field-компонент через ", -1)),
1764
+ d("code", null, "registerField('" + h(e.type) + "', YourComponent)", 1),
1765
+ n[1] || (n[1] = C(". ", -1))
1766
+ ], 64)) : F("", !0)
1767
+ ]),
1768
+ _: 1
1769
+ }));
1770
+ }
1771
+ }), ft = /* @__PURE__ */ L({
1772
+ __name: "FieldRenderer",
1773
+ props: {
1774
+ node: {}
1775
+ },
1776
+ setup(e) {
1777
+ const t = e, n = p(() => ct(t.node.type)), o = p(() => {
1778
+ const { type: a, ...l } = t.node;
1779
+ return l;
1780
+ });
1781
+ return (a, l) => n.value ? (s(), k(oe(n.value), Ce(Se({ key: 0 }, o.value)), null, 16)) : (s(), k(mt, {
1782
+ key: 1,
1783
+ type: e.node.type,
1784
+ name: e.node.name
1785
+ }, null, 8, ["type", "name"]));
1786
+ }
1787
+ }), he = /* @__PURE__ */ L({
1788
+ __name: "LayoutRenderer",
1789
+ props: {
1790
+ node: {}
1791
+ },
1792
+ setup(e) {
1793
+ const t = e, n = p(() => {
1794
+ if (t.node.kind === "field")
1795
+ return { kind: "field" };
1796
+ if (t.node.kind === "layout") {
1797
+ const i = Ge(t.node.type);
1798
+ return i ? { kind: "layout", component: i } : { kind: "unknown" };
1799
+ }
1800
+ const l = Ge(t.node.type);
1801
+ return l ? { kind: "layout", component: l } : ct(t.node.type) ? { kind: "field" } : { kind: "unknown" };
1802
+ }), o = p(() => {
1803
+ const { type: l, kind: i, ...u } = t.node;
1804
+ return u;
1805
+ }), a = p(() => t.node);
1806
+ return (l, i) => n.value.kind === "layout" && n.value.component ? (s(), k(oe(n.value.component), Ce(Se({ key: 0 }, o.value)), null, 16)) : n.value.kind === "field" ? (s(), k(ft, {
1807
+ key: 1,
1808
+ node: a.value
1809
+ }, null, 8, ["node"])) : (s(), k(mt, {
1810
+ key: 2,
1811
+ type: e.node.type,
1812
+ name: e.node.name
1813
+ }, null, 8, ["type", "name"]));
1814
+ }
1815
+ }), Ca = { class: "admin-page admin-resource-form" }, Sa = { class: "admin-page__hd" }, Aa = { class: "admin-page__title-wrap" }, Ra = { class: "admin-page__title" }, Ua = { class: "admin-page__actions" }, Ea = {
1816
+ key: 1,
1817
+ class: "admin-resource-form__loading"
1818
+ }, Fa = {
1819
+ key: 3,
1820
+ class: "admin-resource-form__savebar"
1821
+ }, He = /* @__PURE__ */ L({
1822
+ __name: "ResourceFormPage",
1823
+ props: {
1824
+ slug: {},
1825
+ id: { default: null },
1826
+ indexRouteName: { default: "admin.home" }
1827
+ },
1828
+ setup(e) {
1829
+ const t = e, n = dt(), o = ae(), a = ne(), l = it(n.state, n.errors);
1830
+ te(
1831
+ () => n.errors,
1832
+ (_) => {
1833
+ l.setErrors({ ..._ });
1834
+ }
1835
+ );
1836
+ const i = p(() => o.getResource(t.slug)), u = p(
1837
+ () => i.value?.fields ?? []
1838
+ ), f = p(() => n.isCreate ? `Создать: ${i.value?.label ?? t.slug}` : `${i.value?.label ?? t.slug}: запись #${t.id}`), v = p(() => {
1839
+ const _ = n.state.status;
1840
+ return typeof _ == "string" ? _ : null;
1841
+ }), w = p(() => {
1842
+ switch (v.value) {
1843
+ case "published":
1844
+ return "success";
1845
+ case "review":
1846
+ case "draft":
1847
+ return "warning";
1848
+ case "archived":
1849
+ return "danger";
1850
+ default:
1851
+ return "default";
1852
+ }
1853
+ });
1854
+ xe(async () => {
1855
+ o.manifest === null && await o.load().catch(() => {
1856
+ }), t.id !== null && t.id !== void 0 ? await n.load(t.slug, t.id, "edit").catch(() => {
1857
+ }) : n.prepareCreate(t.slug);
1858
+ }), te(
1859
+ () => [t.slug, t.id],
1860
+ async ([_, g]) => {
1861
+ g != null ? await n.load(_, g, "edit").catch(() => {
1862
+ }) : n.prepareCreate(_);
1863
+ }
1864
+ );
1865
+ async function S() {
1866
+ try {
1867
+ const _ = await n.save();
1868
+ n.isCreate && a.push({
1869
+ name: `admin.resource.${t.slug}.edit`,
1870
+ params: { id: _ }
1871
+ }).catch(() => {
1872
+ });
1873
+ } catch {
1874
+ }
1875
+ }
1876
+ async function R() {
1877
+ confirm("Удалить запись?") && (await n.destroy().catch(() => {
1878
+ }), n.hasError || a.push({ name: t.indexRouteName }).catch(() => {
1879
+ }));
1880
+ }
1881
+ function A() {
1882
+ n.isDirty && !confirm("Несохранённые изменения будут потеряны. Продолжить?") || a.push({ name: t.indexRouteName }).catch(() => {
1883
+ });
1884
+ }
1885
+ return (_, g) => (s(), c("section", Ca, [
1886
+ d("header", Sa, [
1887
+ d("div", Aa, [
1888
+ d("a", {
1889
+ class: "admin-resource-form__back",
1890
+ onClick: A
1891
+ }, "← Назад"),
1892
+ d("h1", Ra, h(f.value), 1),
1893
+ v.value ? (s(), k(r(ze), {
1894
+ key: 0,
1895
+ variant: w.value
1896
+ }, {
1897
+ default: m(() => [
1898
+ C(h(v.value), 1)
1899
+ ]),
1900
+ _: 1
1901
+ }, 8, ["variant"])) : F("", !0)
1902
+ ]),
1903
+ d("div", Ua, [
1904
+ x(r(B), {
1905
+ variant: "ghost",
1906
+ disabled: r(n).saving || r(n).deleting,
1907
+ onClick: A
1908
+ }, {
1909
+ default: m(() => [...g[0] || (g[0] = [
1910
+ C(" Отмена ", -1)
1911
+ ])]),
1912
+ _: 1
1913
+ }, 8, ["disabled"]),
1914
+ r(n).isEdit ? (s(), k(r(B), {
1915
+ key: 0,
1916
+ variant: "danger",
1917
+ disabled: r(n).saving || r(n).deleting,
1918
+ loading: r(n).deleting,
1919
+ onClick: R
1920
+ }, {
1921
+ default: m(() => [...g[1] || (g[1] = [
1922
+ C(" Удалить ", -1)
1923
+ ])]),
1924
+ _: 1
1925
+ }, 8, ["disabled", "loading"])) : F("", !0),
1926
+ x(r(B), {
1927
+ variant: "primary",
1928
+ disabled: r(n).saving || r(n).loading,
1929
+ loading: r(n).saving,
1930
+ onClick: S
1931
+ }, {
1932
+ default: m(() => [
1933
+ C(h(r(n).isCreate ? "Создать" : "Сохранить"), 1)
1934
+ ]),
1935
+ _: 1
1936
+ }, 8, ["disabled", "loading"])
1937
+ ])
1938
+ ]),
1939
+ r(n).hasError ? (s(), k(r(J), {
1940
+ key: 0,
1941
+ variant: "danger",
1942
+ class: "admin-resource-form__alert",
1943
+ role: "alert"
1944
+ }, {
1945
+ default: m(() => [
1946
+ C(h(r(n).error?.message ?? "Не удалось сохранить запись"), 1)
1947
+ ]),
1948
+ _: 1
1949
+ })) : F("", !0),
1950
+ r(n).loading ? (s(), c("div", Ea, [
1951
+ (s(), c(T, null, I(6, (U) => x(r(Be), {
1952
+ key: U,
1953
+ height: "40px"
1954
+ })), 64))
1955
+ ])) : (s(), k(r(q), {
1956
+ key: 2,
1957
+ padding: "md",
1958
+ class: "admin-resource-form__body"
1959
+ }, {
1960
+ default: m(() => [
1961
+ (s(!0), c(T, null, I(u.value, (U, P) => (s(), k(he, {
1962
+ key: P,
1963
+ node: U
1964
+ }, null, 8, ["node"]))), 128))
1965
+ ]),
1966
+ _: 1
1967
+ })),
1968
+ r(n).isDirty && !r(n).loading ? (s(), c("div", Fa, [
1969
+ g[4] || (g[4] = d("span", { class: "admin-resource-form__savebar-hint" }, " Есть несохранённые изменения ", -1)),
1970
+ x(r(B), {
1971
+ variant: "ghost",
1972
+ size: "sm",
1973
+ onClick: A
1974
+ }, {
1975
+ default: m(() => [...g[2] || (g[2] = [
1976
+ C("Отмена", -1)
1977
+ ])]),
1978
+ _: 1
1979
+ }),
1980
+ x(r(B), {
1981
+ variant: "primary",
1982
+ size: "sm",
1983
+ loading: r(n).saving,
1984
+ disabled: r(n).saving,
1985
+ onClick: S
1986
+ }, {
1987
+ default: m(() => [...g[3] || (g[3] = [
1988
+ C(" Сохранить ", -1)
1989
+ ])]),
1990
+ _: 1
1991
+ }, 8, ["loading", "disabled"])
1992
+ ])) : F("", !0)
1993
+ ]));
1994
+ }
1995
+ }), ce = Ee(), ji = ce.register, Xe = ce.get, Ki = ce.has, Gi = ce.list, Hi = ce.clear, La = ce.registerBundle, Pa = /* @__PURE__ */ L({
1996
+ __name: "UnknownEntry",
1997
+ props: {
1998
+ type: {},
1999
+ name: {}
2000
+ },
2001
+ setup(e) {
2002
+ return (t, n) => (s(), k(r(J), { variant: "warning" }, {
2003
+ title: m(() => [
2004
+ C("Неизвестный тип infolist-entry: " + h(e.type), 1)
2005
+ ]),
2006
+ default: m(() => [
2007
+ n[0] || (n[0] = C(" Зарегистрируйте через ", -1)),
2008
+ d("code", null, "registerInfolistEntry('" + h(e.type) + "', YourComponent)", 1),
2009
+ n[1] || (n[1] = C(". ", -1))
2010
+ ]),
2011
+ _: 1
2012
+ }));
2013
+ }
2014
+ }), Ta = {
2015
+ key: 1,
2016
+ class: "admin-infolist-rows"
2017
+ }, Ma = {
2018
+ key: 2,
2019
+ class: "admin-infolist-cols"
2020
+ }, Na = {
2021
+ key: 3,
2022
+ class: "admin-infolist-section"
2023
+ }, Ia = {
2024
+ key: 0,
2025
+ class: "admin-infolist-section__hd"
2026
+ }, Ba = {
2027
+ key: 0,
2028
+ class: "admin-infolist-section__title"
2029
+ }, Va = {
2030
+ key: 1,
2031
+ class: "admin-infolist-section__description"
2032
+ }, za = { class: "admin-infolist-section__body" }, qa = {
2033
+ key: 4,
2034
+ class: "admin-infolist-tabs"
2035
+ }, Da = {
2036
+ class: "admin-infolist-tabs__list",
2037
+ role: "tablist"
2038
+ }, Oa = { class: "admin-infolist-tabs__panel" }, Wa = /* @__PURE__ */ L({
2039
+ __name: "InfolistRenderer",
2040
+ props: {
2041
+ node: {}
2042
+ },
2043
+ setup(e) {
2044
+ const t = e, n = /* @__PURE__ */ new Set(["rows", "columns", "section", "block", "tabs"]), o = p(() => {
2045
+ if (t.node.kind === "entry") {
2046
+ const S = Xe(t.node.type);
2047
+ return S ? { kind: "entry", component: S } : { kind: "unknown" };
2048
+ }
2049
+ if (t.node.kind === "layout")
2050
+ return n.has(t.node.type) ? { kind: "layout", layoutType: t.node.type } : { kind: "unknown" };
2051
+ if (n.has(t.node.type))
2052
+ return { kind: "layout", layoutType: t.node.type };
2053
+ const w = Xe(t.node.type);
2054
+ return w ? { kind: "entry", component: w } : { kind: "unknown" };
2055
+ }), a = p(() => {
2056
+ const { type: w, kind: S, items: R, ...A } = t.node;
2057
+ return A;
2058
+ }), l = p(
2059
+ () => t.node.items ?? []
2060
+ ), i = p(() => t.node.title ?? null), u = p(
2061
+ () => t.node.description ?? null
2062
+ ), f = p(() => {
2063
+ const w = t.node.active;
2064
+ return typeof w == "number" ? w : 0;
2065
+ }), v = p(() => t.node.items ?? []);
2066
+ return (w, S) => {
2067
+ const R = Ze("InfolistRenderer", !0);
2068
+ return o.value.kind === "entry" ? (s(), k(oe(o.value.component), Ce(Se({ key: 0 }, a.value)), null, 16)) : o.value.kind === "layout" && o.value.layoutType === "rows" ? (s(), c("div", Ta, [
2069
+ (s(!0), c(T, null, I(l.value, (A, _) => (s(), k(R, {
2070
+ key: _,
2071
+ node: A
2072
+ }, null, 8, ["node"]))), 128))
2073
+ ])) : o.value.kind === "layout" && o.value.layoutType === "columns" ? (s(), c("div", Ma, [
2074
+ (s(!0), c(T, null, I(l.value, (A, _) => (s(), c("div", {
2075
+ key: _,
2076
+ class: "admin-infolist-cols__item",
2077
+ style: Ae({
2078
+ gridColumn: `span ${typeof A.span == "number" ? A.span : Math.max(1, Math.floor(12 / l.value.length))}`
2079
+ })
2080
+ }, [
2081
+ x(R, { node: A }, null, 8, ["node"])
2082
+ ], 4))), 128))
2083
+ ])) : o.value.kind === "layout" && (o.value.layoutType === "section" || o.value.layoutType === "block") ? (s(), c("section", Na, [
2084
+ i.value || u.value ? (s(), c("header", Ia, [
2085
+ i.value ? (s(), c("h3", Ba, h(i.value), 1)) : F("", !0),
2086
+ u.value ? (s(), c("p", Va, h(u.value), 1)) : F("", !0)
2087
+ ])) : F("", !0),
2088
+ d("div", za, [
2089
+ (s(!0), c(T, null, I(l.value, (A, _) => (s(), k(R, {
2090
+ key: _,
2091
+ node: A
2092
+ }, null, 8, ["node"]))), 128))
2093
+ ])
2094
+ ])) : o.value.kind === "layout" && o.value.layoutType === "tabs" ? (s(), c("div", qa, [
2095
+ d("ul", Da, [
2096
+ (s(!0), c(T, null, I(v.value, (A, _) => (s(), c("li", {
2097
+ key: A.key ?? _,
2098
+ class: X([
2099
+ "admin-infolist-tabs__tab",
2100
+ { "admin-infolist-tabs__tab--active": _ === f.value }
2101
+ ])
2102
+ }, h(A.label), 3))), 128))
2103
+ ]),
2104
+ d("div", Oa, [
2105
+ (s(!0), c(T, null, I(v.value[f.value]?.items ?? [], (A, _) => (s(), k(R, {
2106
+ key: _,
2107
+ node: A
2108
+ }, null, 8, ["node"]))), 128))
2109
+ ])
2110
+ ])) : (s(), k(Pa, {
2111
+ key: 5,
2112
+ type: e.node.type,
2113
+ name: e.node.name
2114
+ }, null, 8, ["type", "name"]));
2115
+ };
2116
+ }
2117
+ }), We = /* @__PURE__ */ Symbol("admin.infolist-record");
2118
+ function ja(e) {
2119
+ bt(We, e);
2120
+ }
2121
+ function Xi() {
2122
+ const e = et(We);
2123
+ if (!e)
2124
+ throw new Error("useRecord() called outside of provideRecord() scope");
2125
+ return e;
2126
+ }
2127
+ function Fe() {
2128
+ return et(We, null);
2129
+ }
2130
+ const Ka = { class: "admin-page admin-resource-view" }, Ga = { class: "admin-page__hd" }, Ha = { class: "admin-page__title-wrap" }, Xa = { class: "admin-page__title" }, Ja = { class: "admin-page__actions" }, Ya = {
2131
+ key: 1,
2132
+ class: "admin-resource-view__loading"
2133
+ }, Qa = /* @__PURE__ */ L({
2134
+ __name: "ResourceViewPage",
2135
+ props: {
2136
+ slug: {},
2137
+ id: {},
2138
+ editRouteName: { default: void 0 },
2139
+ indexRouteName: { default: "admin.home" }
2140
+ },
2141
+ setup(e) {
2142
+ const t = e, n = dt(), o = ae(), a = ne();
2143
+ ja(n.state);
2144
+ const l = p(() => o.getResource(t.slug)), i = p(
2145
+ () => l.value?.fields ?? []
2146
+ ), u = p(
2147
+ () => `${l.value?.label ?? t.slug}: запись #${t.id}`
2148
+ );
2149
+ xe(async () => {
2150
+ o.manifest === null && await o.load().catch(() => {
2151
+ }), await n.load(t.slug, t.id, "view").catch(() => {
2152
+ });
2153
+ }), te(
2154
+ () => [t.slug, t.id],
2155
+ async ([w, S]) => {
2156
+ await n.load(w, S, "view").catch(() => {
2157
+ });
2158
+ }
2159
+ );
2160
+ function f() {
2161
+ if (!t.editRouteName) {
2162
+ a.push(`/r/${t.slug}/${t.id}/edit`).catch(() => {
2163
+ });
2164
+ return;
2165
+ }
2166
+ a.push({ name: t.editRouteName, params: { id: t.id } }).catch(() => {
2167
+ });
2168
+ }
2169
+ async function v() {
2170
+ confirm("Удалить запись?") && (await n.destroy().catch(() => {
2171
+ }), n.hasError || a.push({ name: t.indexRouteName }).catch(() => {
2172
+ }));
2173
+ }
2174
+ return (w, S) => (s(), c("section", Ka, [
2175
+ d("header", Ga, [
2176
+ d("div", Ha, [
2177
+ d("h1", Xa, h(u.value), 1)
2178
+ ]),
2179
+ d("div", Ja, [
2180
+ x(r(B), {
2181
+ variant: "ghost",
2182
+ onClick: f
2183
+ }, {
2184
+ default: m(() => [...S[0] || (S[0] = [
2185
+ C("Редактировать", -1)
2186
+ ])]),
2187
+ _: 1
2188
+ }),
2189
+ x(r(B), {
2190
+ variant: "danger",
2191
+ loading: r(n).deleting,
2192
+ disabled: r(n).deleting,
2193
+ onClick: v
2194
+ }, {
2195
+ default: m(() => [...S[1] || (S[1] = [
2196
+ C(" Удалить ", -1)
2197
+ ])]),
2198
+ _: 1
2199
+ }, 8, ["loading", "disabled"])
2200
+ ])
2201
+ ]),
2202
+ r(n).hasError ? (s(), k(r(J), {
2203
+ key: 0,
2204
+ variant: "danger",
2205
+ class: "admin-resource-view__alert",
2206
+ role: "alert"
2207
+ }, {
2208
+ default: m(() => [
2209
+ C(h(r(n).error?.message ?? "Не удалось загрузить запись"), 1)
2210
+ ]),
2211
+ _: 1
2212
+ })) : F("", !0),
2213
+ r(n).loading ? (s(), c("div", Ya, [
2214
+ (s(), c(T, null, I(8, (R) => x(r(Be), {
2215
+ key: R,
2216
+ height: "24px"
2217
+ })), 64))
2218
+ ])) : (s(), k(r(q), {
2219
+ key: 2,
2220
+ padding: "md",
2221
+ class: "admin-resource-view__body"
2222
+ }, {
2223
+ default: m(() => [
2224
+ (s(!0), c(T, null, I(i.value, (R, A) => (s(), k(Wa, {
2225
+ key: A,
2226
+ node: R
2227
+ }, null, 8, ["node"]))), 128))
2228
+ ]),
2229
+ _: 1
2230
+ }))
2231
+ ]));
2232
+ }
2233
+ }), Za = { class: "admin-page admin-profile" }, el = { class: "admin-page__hd" }, tl = { class: "admin-page__title-wrap" }, nl = { class: "admin-page__title" }, al = { class: "admin-page__count" }, ll = { class: "admin-profile__layout" }, sl = {
2234
+ class: "admin-profile__nav",
2235
+ "aria-label": "Profile sections"
2236
+ }, il = ["onClick"], ol = ["data-icon"], rl = { class: "admin-profile__content" }, ul = { class: "admin-profile__hero" }, dl = { class: "admin-profile__hero-text" }, cl = { class: "admin-profile__hero-name" }, ml = { class: "admin-profile__hero-meta" }, fl = { class: "admin-profile__form" }, vl = { class: "admin-profile__card-ft" }, pl = { class: "admin-profile__card-hd" }, gl = {
2237
+ key: 0,
2238
+ class: "admin-profile__hint"
2239
+ }, hl = {
2240
+ key: 1,
2241
+ class: "admin-profile__hint"
2242
+ }, _l = { class: "admin-profile__card-ft" }, yl = { class: "admin-profile__hint" }, bl = /* @__PURE__ */ L({
2243
+ __name: "ProfilePage",
2244
+ props: {
2245
+ title: { default: "Profile" },
2246
+ subtitle: { default: "Личные данные, безопасность, токены" },
2247
+ section: { default: "general" }
2248
+ },
2249
+ emits: ["update:section", "avatar-replace", "two-factor-disable", "two-factor-regenerate", "save"],
2250
+ setup(e, { emit: t }) {
2251
+ const n = e, o = t, a = Q(), l = qe(), i = De(), u = [
2252
+ { id: "general", label: "Основное", icon: "user" },
2253
+ { id: "security", label: "Безопасность", icon: "shield" },
2254
+ { id: "tokens", label: "API токены", icon: "key" },
2255
+ { id: "sessions", label: "Сессии", icon: "monitor" }
2256
+ ], f = E(n.section);
2257
+ function v(b) {
2258
+ f.value = b, o("update:section", b);
2259
+ }
2260
+ const w = E({
2261
+ name: a.user?.name ?? "",
2262
+ email: a.user?.email ?? "",
2263
+ locale: i.current,
2264
+ theme: l.current
2265
+ }), S = p(
2266
+ () => i.available.map((b) => ({ value: b, label: b.toUpperCase() }))
2267
+ ), R = p(
2268
+ () => l.available.map((b) => ({ value: b, label: b === "dark" ? "Тёмная" : b === "light" ? "Светлая" : b }))
2269
+ );
2270
+ function A() {
2271
+ o("save", { ...w.value });
2272
+ }
2273
+ function _() {
2274
+ o("avatar-replace");
2275
+ }
2276
+ function g() {
2277
+ o("two-factor-disable");
2278
+ }
2279
+ function U() {
2280
+ o("two-factor-regenerate");
2281
+ }
2282
+ const P = p(() => !!a.user?.twoFactorEnabled);
2283
+ return (b, y) => (s(), c("section", Za, [
2284
+ d("header", el, [
2285
+ d("div", tl, [
2286
+ d("h1", nl, h(e.title), 1),
2287
+ d("div", al, h(e.subtitle), 1)
2288
+ ])
2289
+ ]),
2290
+ d("div", ll, [
2291
+ d("nav", sl, [
2292
+ (s(), c(T, null, I(u, ($) => d("button", {
2293
+ key: $.id,
2294
+ type: "button",
2295
+ class: X([
2296
+ "admin-profile__nav-item",
2297
+ { "admin-profile__nav-item--active": f.value === $.id }
2298
+ ]),
2299
+ onClick: (V) => v($.id)
2300
+ }, [
2301
+ d("span", {
2302
+ class: "admin-profile__nav-icon",
2303
+ "data-icon": $.icon
2304
+ }, null, 8, ol),
2305
+ d("span", null, h($.label), 1)
2306
+ ], 10, il)), 64))
2307
+ ]),
2308
+ d("div", rl, [
2309
+ f.value === "general" ? (s(), k(r(q), {
2310
+ key: 0,
2311
+ padding: "md"
2312
+ }, {
2313
+ default: m(() => [
2314
+ y[7] || (y[7] = d("header", { class: "admin-profile__card-hd" }, [
2315
+ d("h3", { class: "admin-profile__card-title" }, "Профиль")
2316
+ ], -1)),
2317
+ d("div", ul, [
2318
+ x(r(at), {
2319
+ src: r(a).user?.avatar ?? void 0,
2320
+ name: r(a).user?.name ?? "?",
2321
+ size: "lg"
2322
+ }, null, 8, ["src", "name"]),
2323
+ d("div", dl, [
2324
+ d("div", cl, h(r(a).user?.name ?? "—"), 1),
2325
+ d("div", ml, h(r(a).user?.email ?? "—"), 1)
2326
+ ]),
2327
+ y[5] || (y[5] = d("div", { style: { flex: "1" } }, null, -1)),
2328
+ x(r(B), {
2329
+ variant: "ghost",
2330
+ size: "sm",
2331
+ onClick: _
2332
+ }, {
2333
+ default: m(() => [...y[4] || (y[4] = [
2334
+ C(" Заменить ", -1)
2335
+ ])]),
2336
+ _: 1
2337
+ })
2338
+ ]),
2339
+ d("div", fl, [
2340
+ x(r(ie), {
2341
+ modelValue: w.value.name,
2342
+ "onUpdate:modelValue": y[0] || (y[0] = ($) => w.value.name = $),
2343
+ label: "Имя",
2344
+ name: "name"
2345
+ }, null, 8, ["modelValue"]),
2346
+ x(r(ie), {
2347
+ modelValue: w.value.email,
2348
+ "onUpdate:modelValue": y[1] || (y[1] = ($) => w.value.email = $),
2349
+ label: "Email",
2350
+ type: "email",
2351
+ name: "email"
2352
+ }, null, 8, ["modelValue"]),
2353
+ x(r($e), {
2354
+ modelValue: w.value.locale,
2355
+ "onUpdate:modelValue": y[2] || (y[2] = ($) => w.value.locale = $),
2356
+ options: S.value,
2357
+ label: "Язык"
2358
+ }, null, 8, ["modelValue", "options"]),
2359
+ x(r($e), {
2360
+ modelValue: w.value.theme,
2361
+ "onUpdate:modelValue": y[3] || (y[3] = ($) => w.value.theme = $),
2362
+ options: R.value,
2363
+ label: "Тема"
2364
+ }, null, 8, ["modelValue", "options"])
2365
+ ]),
2366
+ d("footer", vl, [
2367
+ x(r(B), {
2368
+ variant: "primary",
2369
+ onClick: A
2370
+ }, {
2371
+ default: m(() => [...y[6] || (y[6] = [
2372
+ C("Сохранить", -1)
2373
+ ])]),
2374
+ _: 1
2375
+ })
2376
+ ])
2377
+ ]),
2378
+ _: 1
2379
+ })) : f.value === "security" ? (s(), k(r(q), {
2380
+ key: 1,
2381
+ padding: "md"
2382
+ }, {
2383
+ default: m(() => [
2384
+ d("header", pl, [
2385
+ y[8] || (y[8] = d("h3", { class: "admin-profile__card-title" }, "Двухфакторная аутентификация", -1)),
2386
+ x(r(ze), {
2387
+ variant: P.value ? "success" : "default"
2388
+ }, {
2389
+ default: m(() => [
2390
+ C(h(P.value ? "Включена" : "Отключена"), 1)
2391
+ ]),
2392
+ _: 1
2393
+ }, 8, ["variant"])
2394
+ ]),
2395
+ P.value ? (s(), c("p", gl, " 2FA включена. У вас остались recovery-коды на случай потери устройства. ")) : (s(), c("p", hl, " Включите 2FA для дополнительной защиты аккаунта. ")),
2396
+ d("footer", _l, [
2397
+ P.value ? (s(), c(T, { key: 0 }, [
2398
+ x(r(B), {
2399
+ variant: "ghost",
2400
+ size: "sm",
2401
+ onClick: U
2402
+ }, {
2403
+ default: m(() => [...y[9] || (y[9] = [
2404
+ C(" Перегенерировать коды ", -1)
2405
+ ])]),
2406
+ _: 1
2407
+ }),
2408
+ x(r(B), {
2409
+ variant: "danger",
2410
+ size: "sm",
2411
+ onClick: g
2412
+ }, {
2413
+ default: m(() => [...y[10] || (y[10] = [
2414
+ C(" Отключить 2FA ", -1)
2415
+ ])]),
2416
+ _: 1
2417
+ })
2418
+ ], 64)) : H(b.$slots, "enable-2fa", { key: 1 }, () => [
2419
+ x(r(B), {
2420
+ variant: "primary",
2421
+ disabled: ""
2422
+ }, {
2423
+ default: m(() => [...y[11] || (y[11] = [
2424
+ C(" Включить 2FA (host customize) ", -1)
2425
+ ])]),
2426
+ _: 1
2427
+ })
2428
+ ])
2429
+ ])
2430
+ ]),
2431
+ _: 3
2432
+ })) : H(b.$slots, f.value, {
2433
+ key: 2,
2434
+ section: f.value
2435
+ }, () => [
2436
+ x(r(q), { padding: "md" }, {
2437
+ default: m(() => [
2438
+ d("p", yl, " Section «" + h(f.value) + "» не реализована библиотекой — host-проект подключает её через slot " + h(f.value) + ". ", 1)
2439
+ ]),
2440
+ _: 1
2441
+ })
2442
+ ])
2443
+ ])
2444
+ ])
2445
+ ]));
2446
+ }
2447
+ }), me = Ee(), Ji = me.register, kl = me.get, Yi = me.has, Qi = me.list, Zi = me.clear, wl = me.registerBundle, $l = /* @__PURE__ */ L({
2448
+ __name: "UnknownWidget",
2449
+ props: {
2450
+ type: {}
2451
+ },
2452
+ setup(e) {
2453
+ return (t, n) => (s(), k(r(J), { variant: "warning" }, {
2454
+ title: m(() => [
2455
+ C("Неизвестный widget-тип: " + h(e.type), 1)
2456
+ ]),
2457
+ default: m(() => [
2458
+ n[0] || (n[0] = C(" Зарегистрируйте через ", -1)),
2459
+ d("code", null, "registerWidget('" + h(e.type) + "', YourComponent)", 1),
2460
+ n[1] || (n[1] = C(". ", -1))
2461
+ ]),
2462
+ _: 1
2463
+ }));
2464
+ }
2465
+ }), xl = /* @__PURE__ */ L({
2466
+ __name: "WidgetRenderer",
2467
+ props: {
2468
+ node: {}
2469
+ },
2470
+ setup(e) {
2471
+ const t = e, n = p(() => kl(t.node.type)), o = p(() => {
2472
+ const { type: a, span: l, ...i } = t.node;
2473
+ return i;
2474
+ });
2475
+ return (a, l) => n.value ? (s(), k(oe(n.value), Ce(Se({ key: 0 }, o.value)), null, 16)) : (s(), k($l, {
2476
+ key: 1,
2477
+ type: e.node.type
2478
+ }, null, 8, ["type"]));
2479
+ }
2480
+ }), Cl = { class: "admin-page admin-dashboard" }, Sl = { class: "admin-page__hd" }, Al = { class: "admin-page__title-wrap" }, Rl = { class: "admin-page__title" }, Ul = {
2481
+ key: 0,
2482
+ class: "admin-page__count"
2483
+ }, El = { class: "admin-page__actions" }, Fl = { class: "admin-dashboard__grid" }, Ll = /* @__PURE__ */ L({
2484
+ __name: "DashboardPage",
2485
+ props: {
2486
+ slug: { default: void 0 },
2487
+ widgets: { default: void 0 },
2488
+ title: { default: void 0 },
2489
+ subtitle: { default: void 0 }
2490
+ },
2491
+ setup(e) {
2492
+ const t = e, n = ae(), o = p(() => !t.slug || !n.manifest ? null : n.manifest.dashboards?.find((v) => v.slug === t.slug) ?? null), a = p(() => t.widgets ? t.widgets : o.value ? o.value.widgets ?? [] : []), l = p(
2493
+ () => t.title ?? o.value?.label ?? "Dashboard"
2494
+ ), i = p(
2495
+ () => t.subtitle ?? o.value?.description ?? null
2496
+ );
2497
+ function u(f) {
2498
+ const v = typeof f.span == "number" ? f.span : 12;
2499
+ return Math.max(1, Math.min(12, v));
2500
+ }
2501
+ return (f, v) => (s(), c("section", Cl, [
2502
+ d("header", Sl, [
2503
+ d("div", Al, [
2504
+ d("h1", Rl, h(l.value), 1),
2505
+ i.value ? (s(), c("div", Ul, h(i.value), 1)) : F("", !0)
2506
+ ]),
2507
+ d("div", El, [
2508
+ H(f.$slots, "actions")
2509
+ ])
2510
+ ]),
2511
+ d("div", Fl, [
2512
+ (s(!0), c(T, null, I(a.value, (w, S) => (s(), c("div", {
2513
+ key: S,
2514
+ class: "admin-dashboard__cell",
2515
+ style: Ae({ gridColumn: `span ${u(w)} / span ${u(w)}` })
2516
+ }, [
2517
+ x(xl, { node: w }, null, 8, ["node"])
2518
+ ], 4))), 128))
2519
+ ])
2520
+ ]));
2521
+ }
2522
+ }), Pl = /* @__PURE__ */ L({
2523
+ __name: "StatWidget",
2524
+ props: {
2525
+ title: { default: "" },
2526
+ value: { default: 0 },
2527
+ prefix: { default: "" },
2528
+ suffix: { default: "" },
2529
+ trend: { default: void 0 },
2530
+ precision: { default: 0 },
2531
+ tone: { default: "neutral" },
2532
+ loading: { type: Boolean, default: !1 }
2533
+ },
2534
+ setup(e) {
2535
+ const t = e, n = {
2536
+ neutral: "primary",
2537
+ positive: "success",
2538
+ negative: "danger",
2539
+ warning: "warning",
2540
+ info: "info"
2541
+ }, o = p(() => n[t.tone]);
2542
+ return (a, l) => (s(), k(r(be), {
2543
+ title: e.title,
2544
+ value: e.value,
2545
+ prefix: e.prefix,
2546
+ suffix: e.suffix,
2547
+ trend: e.trend,
2548
+ precision: e.precision,
2549
+ tone: o.value,
2550
+ loading: e.loading
2551
+ }, null, 8, ["title", "value", "prefix", "suffix", "trend", "precision", "tone", "loading"]));
2552
+ }
2553
+ }), Tl = {
2554
+ key: 0,
2555
+ class: "admin-widget__hd"
2556
+ }, Ml = {
2557
+ key: 0,
2558
+ class: "admin-widget__title"
2559
+ }, Nl = {
2560
+ key: 1,
2561
+ class: "admin-widget__desc"
2562
+ }, Il = ["viewBox", "height", "aria-label"], Bl = ["x", "y", "width", "height", "fill", "data-label", "data-value"], Vl = /* @__PURE__ */ L({
2563
+ __name: "BarChartWidget",
2564
+ props: {
2565
+ title: { default: "" },
2566
+ description: { default: "" },
2567
+ data: {},
2568
+ accent: { default: "var(--uid-accent)" },
2569
+ height: { default: 200 }
2570
+ },
2571
+ setup(e) {
2572
+ const t = e, n = p(() => Math.max(1, ...t.data.map((a) => a.value))), o = p(() => {
2573
+ const l = 100 / Math.max(1, t.data.length);
2574
+ return t.data.map((i, u) => ({
2575
+ label: i.label,
2576
+ value: i.value,
2577
+ x: u * l + l * 0.1,
2578
+ width: l * 0.8,
2579
+ heightPct: i.value / n.value * 100
2580
+ }));
2581
+ });
2582
+ return (a, l) => (s(), k(r(q), {
2583
+ padding: "md",
2584
+ class: "admin-widget"
2585
+ }, {
2586
+ default: m(() => [
2587
+ e.title || e.description ? (s(), c("header", Tl, [
2588
+ e.title ? (s(), c("h3", Ml, h(e.title), 1)) : F("", !0),
2589
+ e.description ? (s(), c("p", Nl, h(e.description), 1)) : F("", !0)
2590
+ ])) : F("", !0),
2591
+ (s(), c("svg", {
2592
+ class: "admin-widget-bar-chart",
2593
+ viewBox: `0 0 100 ${e.height}`,
2594
+ preserveAspectRatio: "none",
2595
+ height: e.height,
2596
+ width: "100%",
2597
+ role: "img",
2598
+ "aria-label": e.title || "Bar chart"
2599
+ }, [
2600
+ (s(!0), c(T, null, I(o.value, (i, u) => (s(), c("rect", {
2601
+ key: u,
2602
+ x: i.x,
2603
+ y: e.height - i.heightPct / 100 * e.height,
2604
+ width: i.width,
2605
+ height: i.heightPct / 100 * e.height,
2606
+ fill: e.accent,
2607
+ rx: "1",
2608
+ "data-label": i.label,
2609
+ "data-value": i.value
2610
+ }, [
2611
+ d("title", null, h(i.label) + ": " + h(i.value), 1)
2612
+ ], 8, Bl))), 128))
2613
+ ], 8, Il))
2614
+ ]),
2615
+ _: 1
2616
+ }));
2617
+ }
2618
+ }), zl = {
2619
+ key: 0,
2620
+ class: "admin-widget__hd"
2621
+ }, ql = { class: "admin-widget__title" }, Dl = { class: "admin-donut-widget__row" }, Ol = ["aria-label"], Wl = ["d", "fill"], jl = { class: "admin-donut-widget__legend" }, Kl = { class: "admin-donut-widget__label" }, Gl = { class: "admin-donut-widget__value" }, Hl = /* @__PURE__ */ L({
2622
+ __name: "DonutChartWidget",
2623
+ props: {
2624
+ title: { default: "" },
2625
+ data: {}
2626
+ },
2627
+ setup(e) {
2628
+ const t = e, n = [
2629
+ "var(--uid-color-teal-500, #14b8a6)",
2630
+ "var(--uid-color-zinc-700, #3f3f46)",
2631
+ "var(--uid-color-amber-400, #fbbf24)",
2632
+ "var(--uid-color-rose-400, #fb7185)",
2633
+ "var(--uid-color-blue-400, #60a5fa)"
2634
+ ], o = p(() => t.data.reduce((l, i) => l + i.value, 0) || 1), a = p(() => {
2635
+ let l = 0;
2636
+ return t.data.map((i, u) => {
2637
+ const f = l / o.value * 2 * Math.PI;
2638
+ l += i.value;
2639
+ const v = l / o.value * 2 * Math.PI, w = 50, S = 60, R = 60, A = S + w * Math.cos(f - Math.PI / 2), _ = R + w * Math.sin(f - Math.PI / 2), g = S + w * Math.cos(v - Math.PI / 2), U = R + w * Math.sin(v - Math.PI / 2), P = v - f > Math.PI ? 1 : 0, b = t.data.length === 1 ? `M ${S - w} ${R} a ${w} ${w} 0 1 0 ${w * 2} 0 a ${w} ${w} 0 1 0 ${-w * 2} 0` : `M ${S} ${R} L ${A} ${_} A ${w} ${w} 0 ${P} 1 ${g} ${U} Z`;
2640
+ return {
2641
+ ...i,
2642
+ path: b,
2643
+ color: i.color ?? n[u % n.length],
2644
+ pct: (i.value / o.value * 100).toFixed(1)
2645
+ };
2646
+ });
2647
+ });
2648
+ return (l, i) => (s(), k(r(q), {
2649
+ padding: "md",
2650
+ class: "admin-widget admin-donut-widget"
2651
+ }, {
2652
+ default: m(() => [
2653
+ e.title ? (s(), c("header", zl, [
2654
+ d("h3", ql, h(e.title), 1)
2655
+ ])) : F("", !0),
2656
+ d("div", Dl, [
2657
+ (s(), c("svg", {
2658
+ viewBox: "0 0 120 120",
2659
+ class: "admin-donut-widget__svg",
2660
+ role: "img",
2661
+ "aria-label": e.title
2662
+ }, [
2663
+ (s(!0), c(T, null, I(a.value, (u, f) => (s(), c("path", {
2664
+ key: f,
2665
+ d: u.path,
2666
+ fill: u.color
2667
+ }, [
2668
+ d("title", null, h(u.label) + ": " + h(u.value) + " (" + h(u.pct) + "%)", 1)
2669
+ ], 8, Wl))), 128)),
2670
+ i[0] || (i[0] = d("circle", {
2671
+ cx: "60",
2672
+ cy: "60",
2673
+ r: "30",
2674
+ fill: "var(--uid-surface-raised)"
2675
+ }, null, -1))
2676
+ ], 8, Ol)),
2677
+ d("ul", jl, [
2678
+ (s(!0), c(T, null, I(a.value, (u, f) => (s(), c("li", { key: f }, [
2679
+ d("span", {
2680
+ class: "admin-donut-widget__dot",
2681
+ style: Ae({ background: u.color })
2682
+ }, null, 4),
2683
+ d("span", Kl, h(u.label), 1),
2684
+ d("span", Gl, h(u.pct) + "%", 1)
2685
+ ]))), 128))
2686
+ ])
2687
+ ])
2688
+ ]),
2689
+ _: 1
2690
+ }));
2691
+ }
2692
+ }), Xl = {
2693
+ key: 0,
2694
+ class: "admin-widget__hd"
2695
+ }, Jl = { class: "admin-widget__title" }, Yl = /* @__PURE__ */ L({
2696
+ __name: "RecentTableWidget",
2697
+ props: {
2698
+ title: { default: "" },
2699
+ columns: {},
2700
+ rows: {},
2701
+ emptyText: { default: "Нет данных" }
2702
+ },
2703
+ setup(e) {
2704
+ return (t, n) => (s(), k(r(q), {
2705
+ padding: "md",
2706
+ class: "admin-widget"
2707
+ }, {
2708
+ default: m(() => [
2709
+ e.title ? (s(), c("header", Xl, [
2710
+ d("h3", Jl, h(e.title), 1)
2711
+ ])) : F("", !0),
2712
+ x(r(Ve), {
2713
+ columns: e.columns,
2714
+ data: e.rows,
2715
+ "empty-text": e.emptyText
2716
+ }, null, 8, ["columns", "data", "empty-text"])
2717
+ ]),
2718
+ _: 1
2719
+ }));
2720
+ }
2721
+ }), Ql = {
2722
+ key: 0,
2723
+ class: "admin-widget__hd"
2724
+ }, Zl = { class: "admin-widget__title" }, es = /* @__PURE__ */ L({
2725
+ __name: "HeatmapWidget",
2726
+ props: {
2727
+ title: { default: "" },
2728
+ data: {},
2729
+ levels: { default: 5 },
2730
+ color: { default: void 0 },
2731
+ gap: { default: 2 }
2732
+ },
2733
+ setup(e) {
2734
+ return (t, n) => (s(), k(r(q), {
2735
+ padding: "md",
2736
+ class: "admin-widget"
2737
+ }, {
2738
+ default: m(() => [
2739
+ e.title ? (s(), c("header", Ql, [
2740
+ d("h3", Zl, h(e.title), 1)
2741
+ ])) : F("", !0),
2742
+ x(r(Tt), {
2743
+ data: e.data,
2744
+ levels: e.levels,
2745
+ color: e.color,
2746
+ gap: e.gap
2747
+ }, null, 8, ["data", "levels", "color", "gap"])
2748
+ ]),
2749
+ _: 1
2750
+ }));
2751
+ }
2752
+ }), ts = {
2753
+ key: 0,
2754
+ class: "admin-widget__hd"
2755
+ }, ns = { class: "admin-widget__title" }, as = { style: { display: "flex", "justify-content": "center" } }, ls = /* @__PURE__ */ L({
2756
+ __name: "GaugeWidget",
2757
+ props: {
2758
+ title: { default: "" },
2759
+ value: { default: 0 },
2760
+ min: { default: 0 },
2761
+ max: { default: 100 },
2762
+ size: { default: 160 },
2763
+ ranges: { default: () => [] },
2764
+ tone: { default: "neutral" },
2765
+ color: { default: void 0 },
2766
+ label: { default: "" },
2767
+ suffix: { default: "" },
2768
+ precision: { default: 0 }
2769
+ },
2770
+ setup(e) {
2771
+ const t = e, n = {
2772
+ neutral: "primary",
2773
+ positive: "success",
2774
+ warning: "warning",
2775
+ negative: "danger"
2776
+ }, o = p(() => n[t.tone]);
2777
+ return (a, l) => (s(), k(r(q), {
2778
+ padding: "md",
2779
+ class: "admin-widget"
2780
+ }, {
2781
+ default: m(() => [
2782
+ e.title ? (s(), c("header", ts, [
2783
+ d("h3", ns, h(e.title), 1)
2784
+ ])) : F("", !0),
2785
+ d("div", as, [
2786
+ x(r(Mt), {
2787
+ value: e.value,
2788
+ min: e.min,
2789
+ max: e.max,
2790
+ size: e.size,
2791
+ ranges: e.ranges,
2792
+ tone: o.value,
2793
+ color: e.color,
2794
+ label: e.label,
2795
+ suffix: e.suffix,
2796
+ precision: e.precision
2797
+ }, null, 8, ["value", "min", "max", "size", "ranges", "tone", "color", "label", "suffix", "precision"])
2798
+ ])
2799
+ ]),
2800
+ _: 1
2801
+ }));
2802
+ }
2803
+ }), ss = {
2804
+ key: 0,
2805
+ class: "admin-widget__hd"
2806
+ }, is = { class: "admin-widget__title" }, os = { class: "admin-markdown-widget" }, rs = /* @__PURE__ */ L({
2807
+ __name: "MarkdownWidget",
2808
+ props: {
2809
+ title: { default: "" },
2810
+ content: {}
2811
+ },
2812
+ setup(e) {
2813
+ return (t, n) => (s(), k(r(q), {
2814
+ padding: "md",
2815
+ class: "admin-widget"
2816
+ }, {
2817
+ default: m(() => [
2818
+ e.title ? (s(), c("header", ss, [
2819
+ d("h3", is, h(e.title), 1)
2820
+ ])) : F("", !0),
2821
+ d("div", os, h(e.content), 1)
2822
+ ]),
2823
+ _: 1
2824
+ }));
2825
+ }
2826
+ });
2827
+ function us() {
2828
+ wl({
2829
+ stat: Pl,
2830
+ "bar-chart": Vl,
2831
+ "donut-chart": Hl,
2832
+ "recent-table": Yl,
2833
+ heatmap: es,
2834
+ gauge: ls,
2835
+ markdown: rs
2836
+ });
2837
+ }
2838
+ function ds(e) {
2839
+ return e.success === !0;
2840
+ }
2841
+ function eo(e) {
2842
+ return e.success === !1;
2843
+ }
2844
+ function cs(e) {
2845
+ const t = Gt.create({
2846
+ baseURL: e.baseURL,
2847
+ withCredentials: !0,
2848
+ headers: {
2849
+ Accept: "application/json",
2850
+ "X-Requested-With": "XMLHttpRequest"
2851
+ }
2852
+ });
2853
+ e.csrfToken && (t.defaults.headers.common["X-CSRF-TOKEN"] = e.csrfToken), e.locale && (t.defaults.headers.common["X-Admin-Locale"] = e.locale), t.interceptors.request.use((a) => {
2854
+ const l = ms("XSRF-TOKEN");
2855
+ return l && a.headers.set("X-XSRF-TOKEN", decodeURIComponent(l)), a;
2856
+ }), t.interceptors.response.use(
2857
+ (a) => {
2858
+ const l = a.data;
2859
+ if (l && typeof l == "object" && "success" in l) {
2860
+ if (ds(l))
2861
+ return a.data = l.payload, a;
2862
+ throw je(a.status, l.payload);
2863
+ }
2864
+ return a;
2865
+ },
2866
+ (a) => {
2867
+ if (a.response) {
2868
+ const l = a.response.status, i = a.response.data?.payload ?? {
2869
+ errorKey: "unknown",
2870
+ message: a.message
2871
+ }, u = je(l, i);
2872
+ return u instanceof ut && e.onUnauthenticated?.(), Promise.reject(u);
2873
+ }
2874
+ return Promise.reject(new Ue(a.message));
2875
+ }
2876
+ );
2877
+ const n = (a, l, i) => t[a](l, i).then((u) => u.data), o = (a, l, i, u) => t[a](l, i, u).then((f) => f.data);
2878
+ return {
2879
+ raw: t,
2880
+ get: (a, l) => n("get", a, l),
2881
+ delete: (a, l) => n("delete", a, l),
2882
+ post: (a, l, i) => o("post", a, l, i),
2883
+ put: (a, l, i) => o("put", a, l, i),
2884
+ patch: (a, l, i) => o("patch", a, l, i),
2885
+ setLocale: (a) => {
2886
+ t.defaults.headers.common["X-Admin-Locale"] = a;
2887
+ }
2888
+ };
2889
+ }
2890
+ function ms(e) {
2891
+ if (typeof document > "u") return null;
2892
+ const t = document.cookie.match(new RegExp("(^|; )" + fs(e) + "=([^;]*)"));
2893
+ return t ? t[2] : null;
2894
+ }
2895
+ function fs(e) {
2896
+ return e.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
2897
+ }
2898
+ function ye(e, t) {
2899
+ const n = e.permissions?.[t];
2900
+ return typeof n == "string" && n.length > 0 ? [n] : [];
2901
+ }
2902
+ function vs(e, t) {
2903
+ const n = e.permissions?.[t];
2904
+ return typeof n == "string" && n.length > 0 ? [n] : [];
2905
+ }
2906
+ function ps(e) {
2907
+ return Array.isArray(e.permission) ? e.permission : typeof e.permission == "string" && e.permission.length > 0 ? [e.permission] : [];
2908
+ }
2909
+ function gs(e, t) {
2910
+ const n = e.slug, o = `/r/${n}`;
2911
+ return [
2912
+ {
2913
+ path: o,
2914
+ name: `admin.resource.${n}.index`,
2915
+ component: t.resourceIndex,
2916
+ meta: {
2917
+ requiresAuth: !0,
2918
+ kind: "resource",
2919
+ slug: n,
2920
+ title: e.label,
2921
+ permissions: ye(e, "view")
2922
+ }
2923
+ },
2924
+ {
2925
+ path: `${o}/create`,
2926
+ name: `admin.resource.${n}.create`,
2927
+ component: t.resourceCreate,
2928
+ meta: {
2929
+ requiresAuth: !0,
2930
+ kind: "resource",
2931
+ slug: n,
2932
+ title: `${e.label}: создать`,
2933
+ permissions: ye(e, "create")
2934
+ }
2935
+ },
2936
+ {
2937
+ path: `${o}/:id/edit`,
2938
+ name: `admin.resource.${n}.edit`,
2939
+ component: t.resourceEdit,
2940
+ meta: {
2941
+ requiresAuth: !0,
2942
+ kind: "resource",
2943
+ slug: n,
2944
+ title: `${e.label}: редактирование`,
2945
+ permissions: ye(e, "update")
2946
+ },
2947
+ props: !0
2948
+ },
2949
+ {
2950
+ path: `${o}/:id`,
2951
+ name: `admin.resource.${n}.view`,
2952
+ component: t.resourceView,
2953
+ meta: {
2954
+ requiresAuth: !0,
2955
+ kind: "resource",
2956
+ slug: n,
2957
+ title: e.label,
2958
+ permissions: ye(e, "view")
2959
+ },
2960
+ props: !0
2961
+ }
2962
+ ];
2963
+ }
2964
+ function hs(e, t) {
2965
+ return {
2966
+ path: `/screens/${e.slug}`,
2967
+ name: `admin.screen.${e.slug}`,
2968
+ component: t.screen,
2969
+ meta: {
2970
+ requiresAuth: !0,
2971
+ kind: "screen",
2972
+ slug: e.slug,
2973
+ title: e.name,
2974
+ permissions: ps(e)
2975
+ }
2976
+ };
2977
+ }
2978
+ function _s(e, t) {
2979
+ return {
2980
+ path: `/settings/${e.slug}`,
2981
+ name: `admin.settings.${e.slug}`,
2982
+ component: t.settings,
2983
+ meta: {
2984
+ requiresAuth: !0,
2985
+ kind: "settings",
2986
+ slug: e.slug,
2987
+ title: e.label,
2988
+ permissions: vs(e, "view")
2989
+ }
2990
+ };
2991
+ }
2992
+ function ys(e, t) {
2993
+ if (typeof e.slug != "string" || e.slug.length === 0) return null;
2994
+ const n = e.permission, o = Array.isArray(n) ? n : typeof n == "string" && n.length > 0 ? [n] : [];
2995
+ return {
2996
+ path: `/dashboard/${e.slug}`,
2997
+ name: `admin.dashboard.${e.slug}`,
2998
+ component: t.dashboard,
2999
+ meta: {
3000
+ requiresAuth: !0,
3001
+ kind: "dashboard",
3002
+ slug: e.slug,
3003
+ title: e.label ?? "Dashboard",
3004
+ permissions: o
3005
+ }
3006
+ };
3007
+ }
3008
+ function bs(e, t) {
3009
+ if (e === null) return [];
3010
+ const n = [];
3011
+ for (const o of e.resources)
3012
+ n.push(...gs(o, t));
3013
+ for (const o of e.screens)
3014
+ n.push(hs(o, t));
3015
+ for (const o of e.settings)
3016
+ n.push(_s(o, t));
3017
+ for (const o of e.dashboards) {
3018
+ const a = ys(o, t);
3019
+ a && n.push(a);
3020
+ }
3021
+ return n;
3022
+ }
3023
+ function ks(e = {}) {
3024
+ const t = e.loginRouteName ?? "admin.login", n = e.forbiddenRouteName ?? "admin.forbidden", o = e.redirectQueryKey ?? "redirect";
3025
+ return (a) => {
3026
+ if (a.name === t)
3027
+ return !0;
3028
+ const l = Q();
3029
+ if (a.meta?.requiresAuth === !0 && !l.isAuthenticated)
3030
+ return {
3031
+ name: t,
3032
+ query: { [o]: a.fullPath }
3033
+ };
3034
+ if (l.isChallengePending)
3035
+ return {
3036
+ name: t,
3037
+ query: { [o]: a.fullPath }
3038
+ };
3039
+ const u = a.meta?.permissions;
3040
+ return Array.isArray(u) && u.length > 0 && !l.hasAnyPermission(u) ? { name: n } : !0;
3041
+ };
3042
+ }
3043
+ function ws(e = {}) {
3044
+ const t = e.template, n = e.brand ?? "", o = e.fallback ?? "";
3045
+ return (a) => {
3046
+ if (typeof document > "u") return;
3047
+ const l = a.meta?.title ?? o;
3048
+ let i;
3049
+ t ? i = t.replace("{title}", l).replace("{brand}", n) : l && n ? i = `${l} · ${n}` : i = l || n, document.title = i;
3050
+ };
3051
+ }
3052
+ const $s = [
3053
+ "admin.resource.",
3054
+ "admin.screen.",
3055
+ "admin.settings.",
3056
+ "admin.dashboard."
3057
+ ];
3058
+ function xs(e) {
3059
+ return typeof e != "string" ? !1 : $s.some((t) => e.startsWith(t));
3060
+ }
3061
+ function Cs(e) {
3062
+ const t = e.base ?? "/admin", n = e.history ?? tt(t), o = [
3063
+ {
3064
+ path: "/login",
3065
+ name: "admin.login",
3066
+ component: e.components.login,
3067
+ meta: { kind: "auth", title: "Вход" }
3068
+ },
3069
+ {
3070
+ path: "/",
3071
+ name: "admin.home",
3072
+ component: e.components.home,
3073
+ meta: { requiresAuth: !0, kind: "system", title: "Главная" }
3074
+ },
3075
+ {
3076
+ path: "/forbidden",
3077
+ name: "admin.forbidden",
3078
+ component: e.components.forbidden,
3079
+ meta: { requiresAuth: !0, kind: "system", title: "403 — доступ запрещён" }
3080
+ }
3081
+ ];
3082
+ e.components.profile && o.push({
3083
+ path: "/profile",
3084
+ name: "admin.profile",
3085
+ component: e.components.profile,
3086
+ meta: { requiresAuth: !0, kind: "system", title: "Профиль" }
3087
+ }), e.components.notifications && o.push({
3088
+ path: "/notifications",
3089
+ name: "admin.notifications",
3090
+ component: e.components.notifications,
3091
+ meta: { requiresAuth: !0, kind: "system", title: "Уведомления" }
3092
+ });
3093
+ const a = {
3094
+ path: "/:pathMatch(.*)*",
3095
+ name: "admin.notFound",
3096
+ component: e.components.notFound,
3097
+ meta: { kind: "system", title: "404" }
3098
+ }, l = Ct({
3099
+ history: n,
3100
+ routes: [...o, ...e.extraRoutes ?? [], a]
3101
+ });
3102
+ return l.beforeEach(ks(e.authGuard)), l.afterEach(ws(e.titleGuard)), l.replaceManifestRoutes = (i) => {
3103
+ const u = l.getRoutes();
3104
+ for (const v of u)
3105
+ xs(v.name) && l.removeRoute(v.name);
3106
+ l.hasRoute("admin.notFound") && l.removeRoute("admin.notFound");
3107
+ const f = bs(i, e.components);
3108
+ for (const v of f)
3109
+ l.addRoute(v);
3110
+ l.addRoute(a);
3111
+ }, l;
3112
+ }
3113
+ const se = /* @__PURE__ */ L({
3114
+ __name: "TextField",
3115
+ props: {
3116
+ name: {},
3117
+ label: { default: null },
3118
+ help: { default: null },
3119
+ required: { type: Boolean, default: !1 },
3120
+ placeholder: { default: null },
3121
+ inputType: { default: "text" },
3122
+ disabled: { type: Boolean, default: !1 },
3123
+ readonly: { type: Boolean, default: !1 },
3124
+ autocomplete: { default: null }
3125
+ },
3126
+ setup(e) {
3127
+ const t = e, n = re(), o = p(() => n.getField(t.name) ?? ""), a = p(() => n.errors[t.name]?.[0]);
3128
+ function l(i) {
3129
+ n.setField(t.name, i);
3130
+ }
3131
+ return (i, u) => (s(), k(r(ie), {
3132
+ "model-value": o.value,
3133
+ type: e.inputType,
3134
+ label: e.label ?? void 0,
3135
+ hint: e.help ?? void 0,
3136
+ error: a.value,
3137
+ placeholder: e.placeholder ?? void 0,
3138
+ required: e.required,
3139
+ disabled: e.disabled,
3140
+ readonly: e.readonly,
3141
+ name: e.name,
3142
+ autocomplete: e.autocomplete ?? void 0,
3143
+ "onUpdate:modelValue": l
3144
+ }, null, 8, ["model-value", "type", "label", "hint", "error", "placeholder", "required", "disabled", "readonly", "name", "autocomplete"]));
3145
+ }
3146
+ }), Ss = /* @__PURE__ */ L({
3147
+ __name: "TextAreaField",
3148
+ props: {
3149
+ name: {},
3150
+ label: { default: null },
3151
+ help: { default: null },
3152
+ required: { type: Boolean, default: !1 },
3153
+ placeholder: { default: null },
3154
+ rows: { default: 4 },
3155
+ disabled: { type: Boolean, default: !1 },
3156
+ readonly: { type: Boolean, default: !1 }
3157
+ },
3158
+ setup(e) {
3159
+ const t = e, n = re(), o = p(() => n.getField(t.name) ?? ""), a = p(() => n.errors[t.name]?.[0]);
3160
+ function l(i) {
3161
+ n.setField(t.name, i);
3162
+ }
3163
+ return (i, u) => (s(), k(r(ge), {
3164
+ label: e.label ?? void 0,
3165
+ hint: e.help ?? void 0,
3166
+ error: a.value,
3167
+ required: e.required,
3168
+ disabled: e.disabled
3169
+ }, {
3170
+ default: m(() => [
3171
+ x(r(Nt), {
3172
+ "model-value": o.value,
3173
+ rows: e.rows,
3174
+ placeholder: e.placeholder ?? void 0,
3175
+ disabled: e.disabled,
3176
+ readonly: e.readonly,
3177
+ name: e.name,
3178
+ "onUpdate:modelValue": l
3179
+ }, null, 8, ["model-value", "rows", "placeholder", "disabled", "readonly", "name"])
3180
+ ]),
3181
+ _: 1
3182
+ }, 8, ["label", "hint", "error", "required", "disabled"]));
3183
+ }
3184
+ }), As = /* @__PURE__ */ L({
3185
+ __name: "NumberField",
3186
+ props: {
3187
+ name: {},
3188
+ label: { default: null },
3189
+ help: { default: null },
3190
+ required: { type: Boolean, default: !1 },
3191
+ placeholder: { default: null },
3192
+ min: { default: null },
3193
+ max: { default: null },
3194
+ step: { default: null },
3195
+ disabled: { type: Boolean, default: !1 },
3196
+ readonly: { type: Boolean, default: !1 }
3197
+ },
3198
+ setup(e) {
3199
+ const t = e, n = re(), o = p(() => {
3200
+ const i = n.getField(t.name);
3201
+ return i == null || i === "" ? null : typeof i == "number" ? i : Number(i);
3202
+ }), a = p(() => n.errors[t.name]?.[0]);
3203
+ function l(i) {
3204
+ n.setField(t.name, i);
3205
+ }
3206
+ return (i, u) => (s(), k(r(ge), {
3207
+ label: e.label ?? void 0,
3208
+ hint: e.help ?? void 0,
3209
+ error: a.value,
3210
+ required: e.required,
3211
+ disabled: e.disabled
3212
+ }, {
3213
+ default: m(() => [
3214
+ x(r(It), {
3215
+ "model-value": o.value,
3216
+ min: e.min ?? void 0,
3217
+ max: e.max ?? void 0,
3218
+ step: e.step ?? void 0,
3219
+ placeholder: e.placeholder ?? void 0,
3220
+ disabled: e.disabled,
3221
+ readonly: e.readonly,
3222
+ name: e.name,
3223
+ "onUpdate:modelValue": l
3224
+ }, null, 8, ["model-value", "min", "max", "step", "placeholder", "disabled", "readonly", "name"])
3225
+ ]),
3226
+ _: 1
3227
+ }, 8, ["label", "hint", "error", "required", "disabled"]));
3228
+ }
3229
+ }), Rs = /* @__PURE__ */ L({
3230
+ __name: "SelectField",
3231
+ props: {
3232
+ name: {},
3233
+ options: {},
3234
+ label: { default: null },
3235
+ help: { default: null },
3236
+ required: { type: Boolean, default: !1 },
3237
+ placeholder: { default: null },
3238
+ disabled: { type: Boolean, default: !1 },
3239
+ searchable: { type: Boolean, default: !1 },
3240
+ clearable: { type: Boolean, default: !1 },
3241
+ size: { default: "md" }
3242
+ },
3243
+ setup(e) {
3244
+ const t = e, n = re(), o = p(() => {
3245
+ const i = n.getField(t.name);
3246
+ return i == null || i === "" ? null : i;
3247
+ }), a = p(() => n.errors[t.name]?.[0]);
3248
+ function l(i) {
3249
+ n.setField(t.name, i);
3250
+ }
3251
+ return (i, u) => (s(), k(r(ge), {
3252
+ label: e.label ?? void 0,
3253
+ hint: e.help ?? void 0,
3254
+ error: a.value,
3255
+ required: e.required,
3256
+ disabled: e.disabled
3257
+ }, {
3258
+ default: m(() => [
3259
+ x(r($e), {
3260
+ "model-value": o.value,
3261
+ options: e.options,
3262
+ placeholder: e.placeholder ?? void 0,
3263
+ disabled: e.disabled,
3264
+ searchable: e.searchable,
3265
+ clearable: e.clearable,
3266
+ size: e.size,
3267
+ "onUpdate:modelValue": l
3268
+ }, null, 8, ["model-value", "options", "placeholder", "disabled", "searchable", "clearable", "size"])
3269
+ ]),
3270
+ _: 1
3271
+ }, 8, ["label", "hint", "error", "required", "disabled"]));
3272
+ }
3273
+ }), Je = /* @__PURE__ */ L({
3274
+ __name: "CheckboxField",
3275
+ props: {
3276
+ name: {},
3277
+ label: { default: null },
3278
+ help: { default: null },
3279
+ required: { type: Boolean, default: !1 },
3280
+ inlineLabel: { default: null },
3281
+ disabled: { type: Boolean, default: !1 }
3282
+ },
3283
+ setup(e) {
3284
+ const t = e, n = re(), o = p(() => !!n.getField(t.name)), a = p(() => n.errors[t.name]?.[0]);
3285
+ function l(i) {
3286
+ n.setField(t.name, i);
3287
+ }
3288
+ return (i, u) => (s(), k(r(ge), {
3289
+ label: e.label ?? void 0,
3290
+ hint: e.help ?? void 0,
3291
+ error: a.value,
3292
+ required: e.required,
3293
+ disabled: e.disabled
3294
+ }, {
3295
+ default: m(() => [
3296
+ x(r(we), {
3297
+ "model-value": o.value,
3298
+ disabled: e.disabled,
3299
+ name: e.name,
3300
+ "onUpdate:modelValue": l
3301
+ }, {
3302
+ default: m(() => [
3303
+ e.inlineLabel ? (s(), c(T, { key: 0 }, [
3304
+ C(h(e.inlineLabel), 1)
3305
+ ], 64)) : F("", !0)
3306
+ ]),
3307
+ _: 1
3308
+ }, 8, ["model-value", "disabled", "name"])
3309
+ ]),
3310
+ _: 1
3311
+ }, 8, ["label", "hint", "error", "required", "disabled"]));
3312
+ }
3313
+ }), Te = /* @__PURE__ */ L({
3314
+ __name: "DateField",
3315
+ props: {
3316
+ name: {},
3317
+ label: { default: null },
3318
+ help: { default: null },
3319
+ required: { type: Boolean, default: !1 },
3320
+ inputType: { default: "date" },
3321
+ min: { default: null },
3322
+ max: { default: null },
3323
+ disabled: { type: Boolean, default: !1 }
3324
+ },
3325
+ setup(e) {
3326
+ const t = e, n = re(), o = p(() => {
3327
+ const i = n.getField(t.name);
3328
+ return i == null || i === "" ? null : String(i);
3329
+ }), a = p(() => n.errors[t.name]?.[0]);
3330
+ function l(i) {
3331
+ n.setField(t.name, i);
3332
+ }
3333
+ return (i, u) => (s(), k(r(ge), {
3334
+ label: e.label ?? void 0,
3335
+ hint: e.help ?? void 0,
3336
+ error: a.value,
3337
+ required: e.required,
3338
+ disabled: e.disabled
3339
+ }, {
3340
+ default: m(() => [
3341
+ x(r(Bt), {
3342
+ "model-value": o.value,
3343
+ min: e.min ?? void 0,
3344
+ max: e.max ?? void 0,
3345
+ disabled: e.disabled,
3346
+ name: e.name,
3347
+ "onUpdate:modelValue": l
3348
+ }, null, 8, ["model-value", "min", "max", "disabled", "name"])
3349
+ ]),
3350
+ _: 1
3351
+ }, 8, ["label", "hint", "error", "required", "disabled"]));
3352
+ }
3353
+ }), Us = /* @__PURE__ */ L({
3354
+ __name: "RowsLayout",
3355
+ props: {
3356
+ items: {},
3357
+ gap: { default: "var(--uid-space-md)" }
3358
+ },
3359
+ setup(e) {
3360
+ return (t, n) => (s(), k(r(Vt), {
3361
+ direction: "column",
3362
+ gap: e.gap,
3363
+ align: "stretch"
3364
+ }, {
3365
+ default: m(() => [
3366
+ (s(!0), c(T, null, I(e.items, (o, a) => (s(), k(he, {
3367
+ key: a,
3368
+ node: o
3369
+ }, null, 8, ["node"]))), 128))
3370
+ ]),
3371
+ _: 1
3372
+ }, 8, ["gap"]));
3373
+ }
3374
+ }), Es = /* @__PURE__ */ L({
3375
+ __name: "ColumnsLayout",
3376
+ props: {
3377
+ items: {},
3378
+ gap: { default: "var(--uid-space-md)" },
3379
+ cols: { default: 12 }
3380
+ },
3381
+ setup(e) {
3382
+ const t = e, n = p(() => t.items.length === 0 ? t.cols : Math.max(1, Math.floor(t.cols / t.items.length)));
3383
+ function o(a) {
3384
+ const l = a.span;
3385
+ return typeof l == "number" && l > 0 ? Math.min(l, t.cols) : n.value;
3386
+ }
3387
+ return (a, l) => (s(), k(r(zt), {
3388
+ cols: e.cols,
3389
+ gap: e.gap
3390
+ }, {
3391
+ default: m(() => [
3392
+ (s(!0), c(T, null, I(e.items, (i, u) => (s(), c("div", {
3393
+ key: u,
3394
+ class: "admin-columns__item",
3395
+ style: Ae({ gridColumn: `span ${o(i)} / span ${o(i)}` })
3396
+ }, [
3397
+ x(he, { node: i }, null, 8, ["node"])
3398
+ ], 4))), 128))
3399
+ ]),
3400
+ _: 1
3401
+ }, 8, ["cols", "gap"]));
3402
+ }
3403
+ }), Fs = {
3404
+ key: 0,
3405
+ class: "admin-section__header"
3406
+ }, Ls = {
3407
+ key: 0,
3408
+ class: "admin-section__title"
3409
+ }, Ps = {
3410
+ key: 1,
3411
+ class: "admin-section__description"
3412
+ }, Ts = { class: "admin-section__body" }, Ye = /* @__PURE__ */ L({
3413
+ __name: "SectionLayout",
3414
+ props: {
3415
+ items: {},
3416
+ title: { default: null },
3417
+ description: { default: null }
3418
+ },
3419
+ setup(e) {
3420
+ return (t, n) => (s(), k(r(q), {
3421
+ padding: "md",
3422
+ class: "admin-section"
3423
+ }, {
3424
+ default: m(() => [
3425
+ e.title || e.description ? (s(), c("header", Fs, [
3426
+ e.title ? (s(), c("h3", Ls, h(e.title), 1)) : F("", !0),
3427
+ e.description ? (s(), c("p", Ps, h(e.description), 1)) : F("", !0)
3428
+ ])) : F("", !0),
3429
+ d("div", Ts, [
3430
+ (s(!0), c(T, null, I(e.items, (o, a) => (s(), k(he, {
3431
+ key: a,
3432
+ node: o
3433
+ }, null, 8, ["node"]))), 128))
3434
+ ])
3435
+ ]),
3436
+ _: 1
3437
+ }));
3438
+ }
3439
+ }), Ms = /* @__PURE__ */ L({
3440
+ __name: "TabsLayout",
3441
+ props: {
3442
+ items: {},
3443
+ active: { default: 0 }
3444
+ },
3445
+ emits: ["update:active"],
3446
+ setup(e, { emit: t }) {
3447
+ const n = e, o = t;
3448
+ function a(u, f) {
3449
+ return u.key ?? f;
3450
+ }
3451
+ const l = E(n.active ?? a(n.items[0] ?? {}, 0));
3452
+ function i(u) {
3453
+ l.value = u, o("update:active", u);
3454
+ }
3455
+ return (u, f) => (s(), k(r(lt), {
3456
+ "model-value": l.value,
3457
+ "onUpdate:modelValue": i
3458
+ }, {
3459
+ list: m(() => [
3460
+ (s(!0), c(T, null, I(e.items, (v, w) => (s(), k(r(ke), {
3461
+ key: a(v, w),
3462
+ value: a(v, w)
3463
+ }, {
3464
+ default: m(() => [
3465
+ C(h(v.label), 1)
3466
+ ]),
3467
+ _: 2
3468
+ }, 1032, ["value"]))), 128))
3469
+ ]),
3470
+ default: m(() => [
3471
+ (s(!0), c(T, null, I(e.items, (v, w) => (s(), k(r(st), {
3472
+ key: `panel-${a(v, w)}`,
3473
+ value: a(v, w)
3474
+ }, {
3475
+ default: m(() => [
3476
+ (s(!0), c(T, null, I(v.items, (S, R) => (s(), k(he, {
3477
+ key: R,
3478
+ node: S
3479
+ }, null, 8, ["node"]))), 128))
3480
+ ]),
3481
+ _: 2
3482
+ }, 1032, ["value"]))), 128))
3483
+ ]),
3484
+ _: 1
3485
+ }, 8, ["model-value"]));
3486
+ }
3487
+ });
3488
+ function Ns() {
3489
+ xa({
3490
+ fields: {
3491
+ text: se,
3492
+ email: se,
3493
+ url: se,
3494
+ password: se,
3495
+ tel: se,
3496
+ search: se,
3497
+ textarea: Ss,
3498
+ number: As,
3499
+ select: Rs,
3500
+ checkbox: Je,
3501
+ switcher: Je,
3502
+ date: Te,
3503
+ datetime: Te,
3504
+ time: Te
3505
+ },
3506
+ layouts: {
3507
+ rows: Us,
3508
+ columns: Es,
3509
+ section: Ye,
3510
+ block: Ye,
3511
+ tabs: Ms
3512
+ }
3513
+ });
3514
+ }
3515
+ const Is = /* @__PURE__ */ L({
3516
+ __name: "TextEntry",
3517
+ props: {
3518
+ name: { default: "" },
3519
+ label: { default: "" },
3520
+ value: { default: void 0 },
3521
+ placeholder: { default: "—" },
3522
+ mono: { type: Boolean, default: !1 }
3523
+ },
3524
+ setup(e) {
3525
+ const t = e, n = Fe(), o = p(() => {
3526
+ let a = t.value;
3527
+ return a === void 0 && n && t.name && (a = n[t.name]), a == null || a === "" ? t.placeholder : String(a);
3528
+ });
3529
+ return (a, l) => (s(), c("span", {
3530
+ class: X(["admin-infolist-text", e.mono ? "admin-infolist-text--mono" : ""])
3531
+ }, h(o.value), 3));
3532
+ }
3533
+ }), Bs = {
3534
+ key: 1,
3535
+ class: "admin-infolist-text"
3536
+ }, Vs = /* @__PURE__ */ L({
3537
+ __name: "BadgeEntry",
3538
+ props: {
3539
+ name: { default: "" },
3540
+ label: { default: "" },
3541
+ value: { default: void 0 },
3542
+ map: { default: () => ({}) },
3543
+ variant: { default: void 0 }
3544
+ },
3545
+ setup(e) {
3546
+ const t = e, n = Fe(), o = p(() => {
3547
+ let l = t.value;
3548
+ return l === void 0 && n && t.name && (l = n[t.name]), l == null ? "" : String(l);
3549
+ }), a = p(() => t.variant ? t.variant : t.map[o.value] ?? "default");
3550
+ return (l, i) => o.value ? (s(), k(r(ze), {
3551
+ key: 0,
3552
+ variant: a.value
3553
+ }, {
3554
+ default: m(() => [
3555
+ C(h(o.value), 1)
3556
+ ]),
3557
+ _: 1
3558
+ }, 8, ["variant"])) : (s(), c("span", Bs, "—"));
3559
+ }
3560
+ }), zs = ["data-icon"], qs = { key: 0 }, Ds = /* @__PURE__ */ L({
3561
+ __name: "IconEntry",
3562
+ props: {
3563
+ name: { default: "" },
3564
+ label: { default: "" },
3565
+ value: { type: [Boolean, null], default: void 0 },
3566
+ trueIcon: { default: "check-circle-2" },
3567
+ falseIcon: { default: "circle" },
3568
+ trueLabel: { default: "" },
3569
+ falseLabel: { default: "" }
3570
+ },
3571
+ setup(e) {
3572
+ const t = e, n = Fe(), o = p(() => {
3573
+ let i = t.value;
3574
+ return i === void 0 && n && t.name && (i = n[t.name]), !!i;
3575
+ }), a = p(() => o.value ? t.trueLabel : t.falseLabel), l = p(() => o.value ? t.trueIcon : t.falseIcon);
3576
+ return (i, u) => (s(), c("span", {
3577
+ class: X(["admin-infolist-icon", o.value ? "admin-infolist-icon--on" : "admin-infolist-icon--off"])
3578
+ }, [
3579
+ d("span", {
3580
+ class: "admin-infolist-icon__glyph",
3581
+ "data-icon": l.value
3582
+ }, null, 8, zs),
3583
+ a.value ? (s(), c("span", qs, h(a.value), 1)) : F("", !0)
3584
+ ], 2));
3585
+ }
3586
+ }), Os = {
3587
+ key: 1,
3588
+ class: "admin-infolist-text"
3589
+ }, Qe = /* @__PURE__ */ L({
3590
+ __name: "KeyValueEntry",
3591
+ props: {
3592
+ name: { default: "" },
3593
+ label: { default: "" },
3594
+ value: { default: void 0 }
3595
+ },
3596
+ setup(e) {
3597
+ const t = e, n = Fe(), o = p(() => {
3598
+ let l = t.value;
3599
+ return l === void 0 && n && t.name && (l = n[t.name]), l == null ? [] : typeof l != "object" ? [] : Object.entries(l);
3600
+ });
3601
+ function a(l) {
3602
+ return l == null ? "—" : typeof l == "object" ? JSON.stringify(l) : String(l);
3603
+ }
3604
+ return (l, i) => o.value.length > 0 ? (s(), k(r(qt), {
3605
+ key: 0,
3606
+ direction: "vertical",
3607
+ columns: 1
3608
+ }, {
3609
+ default: m(() => [
3610
+ (s(!0), c(T, null, I(o.value, ([u, f]) => (s(), k(r(Dt), {
3611
+ key: u,
3612
+ label: u
3613
+ }, {
3614
+ default: m(() => [
3615
+ C(h(a(f)), 1)
3616
+ ]),
3617
+ _: 2
3618
+ }, 1032, ["label"]))), 128))
3619
+ ]),
3620
+ _: 1
3621
+ })) : (s(), c("span", Os, "—"));
3622
+ }
3623
+ });
3624
+ function Ws() {
3625
+ La({
3626
+ text: Is,
3627
+ badge: Vs,
3628
+ icon: Ds,
3629
+ keyvalue: Qe,
3630
+ "key-value": Qe
3631
+ });
3632
+ }
3633
+ function to(e, t = {}) {
3634
+ const n = t.pages ?? {}, o = t.base ?? js(e.baseUrl) ?? "/admin", a = cs({
3635
+ baseURL: e.apiUrl,
3636
+ csrfToken: e.csrf
3637
+ });
3638
+ Ht(a);
3639
+ const l = kt(kn), i = $t();
3640
+ l.use(i), Q().hydrate(e), De().hydrate(e), qe().hydrate(e), Oe().hydrate(e), Ns(), us(), Ws();
3641
+ const u = Cs({
3642
+ base: o,
3643
+ history: t.router?.history ?? tt(o),
3644
+ components: {
3645
+ login: n.login ?? sa,
3646
+ home: n.home ?? Un,
3647
+ forbidden: n.forbidden ?? Fn,
3648
+ notFound: n.notFound ?? Pn,
3649
+ profile: n.profile ?? bl,
3650
+ resourceIndex: n.resourceIndex ?? $a,
3651
+ resourceCreate: n.resourceCreate ?? He,
3652
+ resourceEdit: n.resourceEdit ?? He,
3653
+ resourceView: n.resourceView ?? Qa,
3654
+ dashboard: n.dashboard ?? Ll,
3655
+ settings: n.settings ?? Bn,
3656
+ screen: n.screen ?? Dn
3657
+ },
3658
+ extraRoutes: t.router?.extraRoutes,
3659
+ authGuard: t.router?.authGuard,
3660
+ titleGuard: t.router?.titleGuard
3661
+ });
3662
+ return l.use(u), t.skipManifestLoad || ae().load().then((v) => {
3663
+ u.replaceManifestRoutes(v);
3664
+ }).catch((v) => {
3665
+ typeof console < "u" && console.error("[laravel-admin] manifest load failed:", v);
3666
+ }), t.onAppCreated?.(l), { app: l, router: u, client: a };
3667
+ }
3668
+ function js(e) {
3669
+ if (!e) return null;
3670
+ try {
3671
+ return new URL(e).pathname || "/admin";
3672
+ } catch {
3673
+ return e.startsWith("/") ? e : null;
3674
+ }
3675
+ }
3676
+ async function no(e = {}) {
3677
+ const t = Ks();
3678
+ if (t)
3679
+ return t;
3680
+ if (e.client)
3681
+ try {
3682
+ const n = e.xhrUrl ?? "/system/bootstrap";
3683
+ return await e.client.get(n);
3684
+ } catch (n) {
3685
+ if (n instanceof Ue)
3686
+ return null;
3687
+ throw n;
3688
+ }
3689
+ return null;
3690
+ }
3691
+ function Ks() {
3692
+ return typeof window > "u" ? null : window.__ADMIN_BOOTSTRAP__ ?? null;
3693
+ }
3694
+ function ao() {
3695
+ return typeof document > "u" ? null : document.querySelector('meta[name="csrf-token"]')?.getAttribute("content") ?? null;
3696
+ }
3697
+ const Gs = { class: "admin-notifs__hd" }, Hs = { class: "admin-notifs__title" }, Xs = {
3698
+ key: 0,
3699
+ class: "admin-notifs__count"
3700
+ }, Js = { class: "admin-notifs__list" }, Ys = {
3701
+ key: 0,
3702
+ class: "admin-notifs__empty"
3703
+ }, Qs = {
3704
+ key: 1,
3705
+ class: "admin-notifs__empty"
3706
+ }, Zs = ["onClick"], ei = ["data-kind"], ti = { class: "admin-notifs__body" }, ni = { class: "admin-notifs__row1" }, ai = {
3707
+ key: 0,
3708
+ class: "admin-notifs__title-strong"
3709
+ }, li = {
3710
+ key: 1,
3711
+ class: "admin-notifs__title-soft"
3712
+ }, si = { class: "admin-notifs__time" }, ii = {
3713
+ key: 0,
3714
+ class: "admin-notifs__text"
3715
+ }, oi = ["onClick"], lo = /* @__PURE__ */ L({
3716
+ __name: "NotificationsDrawer",
3717
+ props: {
3718
+ open: { type: Boolean }
3719
+ },
3720
+ emits: ["update:open", "select-item"],
3721
+ setup(e, { emit: t }) {
3722
+ const n = e, o = t, a = Oe();
3723
+ function l(g) {
3724
+ o("update:open", g);
3725
+ }
3726
+ te(
3727
+ () => n.open,
3728
+ async (g) => {
3729
+ g && await a.load(a.lastFilter ?? "all", 1).catch(() => {
3730
+ });
3731
+ },
3732
+ { immediate: !0 }
3733
+ );
3734
+ const i = p(() => a.lastFilter ?? "all");
3735
+ async function u(g) {
3736
+ await a.load(g, 1).catch(() => {
3737
+ });
3738
+ }
3739
+ async function f() {
3740
+ await a.markAllAsRead().catch(() => {
3741
+ });
3742
+ }
3743
+ async function v(g) {
3744
+ o("select-item", g), g.read_at || await a.markAsRead(g.id).catch(() => {
3745
+ });
3746
+ }
3747
+ async function w(g, U) {
3748
+ U.stopPropagation(), await a.destroy(g.id).catch(() => {
3749
+ });
3750
+ }
3751
+ function S(g) {
3752
+ const U = g.data.level;
3753
+ return U === "success" || U === "warning" || U === "danger" ? U : "info";
3754
+ }
3755
+ function R(g) {
3756
+ return g.data.title ?? "—";
3757
+ }
3758
+ function A(g) {
3759
+ return g.data.body ?? "";
3760
+ }
3761
+ function _(g) {
3762
+ if (!g) return "";
3763
+ const U = new Date(g), P = Math.max(0, Date.now() - U.getTime()), b = Math.floor(P / 6e4);
3764
+ if (b < 1) return "только что";
3765
+ if (b < 60) return `${b} мин назад`;
3766
+ const y = Math.floor(b / 60);
3767
+ if (y < 24) return `${y} ч назад`;
3768
+ const $ = Math.floor(y / 24);
3769
+ return $ < 7 ? `${$} д назад` : U.toLocaleDateString("ru-RU");
3770
+ }
3771
+ return (g, U) => (s(), k(r(Ot), {
3772
+ "model-value": e.open,
3773
+ side: "right",
3774
+ width: "400px",
3775
+ title: "Уведомления",
3776
+ "onUpdate:modelValue": l
3777
+ }, {
3778
+ header: m(() => [
3779
+ d("div", Gs, [
3780
+ d("h2", Hs, [
3781
+ U[0] || (U[0] = C(" Уведомления ", -1)),
3782
+ r(a).unreadCount > 0 ? (s(), c("span", Xs, " (" + h(r(a).unreadCount) + ") ", 1)) : F("", !0)
3783
+ ]),
3784
+ r(a).unreadCount > 0 ? (s(), k(r(B), {
3785
+ key: 0,
3786
+ variant: "ghost",
3787
+ size: "sm",
3788
+ onClick: f
3789
+ }, {
3790
+ default: m(() => [...U[1] || (U[1] = [
3791
+ C(" Прочитать все ", -1)
3792
+ ])]),
3793
+ _: 1
3794
+ })) : F("", !0)
3795
+ ])
3796
+ ]),
3797
+ default: m(() => [
3798
+ x(r(lt), {
3799
+ "model-value": i.value,
3800
+ "onUpdate:modelValue": u
3801
+ }, {
3802
+ list: m(() => [
3803
+ x(r(ke), { value: "all" }, {
3804
+ default: m(() => [...U[2] || (U[2] = [
3805
+ C("Все", -1)
3806
+ ])]),
3807
+ _: 1
3808
+ }),
3809
+ x(r(ke), { value: "unread" }, {
3810
+ default: m(() => [
3811
+ U[3] || (U[3] = C(" Непрочитанные", -1)),
3812
+ r(a).unreadCount > 0 ? (s(), c(T, { key: 0 }, [
3813
+ C(" (" + h(r(a).unreadCount) + ") ", 1)
3814
+ ], 64)) : F("", !0)
3815
+ ]),
3816
+ _: 1
3817
+ }),
3818
+ x(r(ke), { value: "read" }, {
3819
+ default: m(() => [...U[4] || (U[4] = [
3820
+ C("Прочитанные", -1)
3821
+ ])]),
3822
+ _: 1
3823
+ })
3824
+ ]),
3825
+ default: m(() => [
3826
+ (s(), c(T, null, I(["all", "unread", "read"], (P) => x(r(st), {
3827
+ key: P,
3828
+ value: P
3829
+ }, {
3830
+ default: m(() => [
3831
+ d("ul", Js, [
3832
+ r(a).loading ? (s(), c("li", Ys, " Загрузка… ")) : r(a).items.length === 0 ? (s(), c("li", Qs, " Нет уведомлений ")) : F("", !0),
3833
+ (s(!0), c(T, null, I(r(a).items, (b) => (s(), c("li", {
3834
+ key: b.id,
3835
+ class: X([
3836
+ "admin-notifs__item",
3837
+ `admin-notifs__item--${S(b)}`,
3838
+ { "admin-notifs__item--unread": !b.read_at }
3839
+ ]),
3840
+ onClick: (y) => v(b)
3841
+ }, [
3842
+ d("span", {
3843
+ class: "admin-notifs__icon",
3844
+ "data-kind": S(b)
3845
+ }, null, 8, ei),
3846
+ d("div", ti, [
3847
+ d("div", ni, [
3848
+ b.read_at ? (s(), c("span", li, h(R(b)), 1)) : (s(), c("strong", ai, h(R(b)), 1)),
3849
+ d("span", si, h(_(b.created_at)), 1)
3850
+ ]),
3851
+ A(b) ? (s(), c("p", ii, h(A(b)), 1)) : F("", !0)
3852
+ ]),
3853
+ d("button", {
3854
+ type: "button",
3855
+ class: "admin-notifs__close",
3856
+ "aria-label": "Удалить",
3857
+ onClick: (y) => w(b, y)
3858
+ }, " × ", 8, oi)
3859
+ ], 10, Zs))), 128))
3860
+ ])
3861
+ ]),
3862
+ _: 1
3863
+ }, 8, ["value"])), 64))
3864
+ ]),
3865
+ _: 1
3866
+ }, 8, ["model-value"])
3867
+ ]),
3868
+ _: 1
3869
+ }, 8, ["model-value"]));
3870
+ }
3871
+ }), ri = { class: "admin-page admin-import-wizard" }, ui = { class: "admin-page__hd" }, di = { class: "admin-page__title-wrap" }, ci = { class: "admin-page__title" }, mi = { class: "admin-page__actions" }, fi = {
3872
+ key: 0,
3873
+ class: "admin-import-wizard__empty"
3874
+ }, vi = {
3875
+ key: 1,
3876
+ class: "admin-import-wizard__mapping"
3877
+ }, pi = { class: "admin-import-wizard__map-source" }, gi = {
3878
+ key: 0,
3879
+ class: "admin-import-wizard__map-sample"
3880
+ }, hi = { class: "admin-import-wizard__card-hd" }, _i = {
3881
+ key: 2,
3882
+ class: "admin-import-wizard__empty"
3883
+ }, yi = {
3884
+ key: 0,
3885
+ class: "admin-import-wizard__empty"
3886
+ }, bi = { class: "admin-import-wizard__kpi" }, ki = { class: "admin-import-wizard__nav" }, so = /* @__PURE__ */ L({
3887
+ __name: "ImportWizardPage",
3888
+ props: {
3889
+ title: { default: "Импорт" },
3890
+ fieldOptions: {},
3891
+ headers: { default: () => [] },
3892
+ preview: { default: () => [] },
3893
+ previewColumns: { default: () => [] },
3894
+ progress: { default: null },
3895
+ step: { default: void 0 }
3896
+ },
3897
+ emits: ["file-uploaded", "mapping-submit", "run-import", "cancel"],
3898
+ setup(e, { emit: t }) {
3899
+ const n = e, o = t, a = [
3900
+ { label: "Загрузка", description: "CSV / TSV / XLSX" },
3901
+ { label: "Сопоставление", description: "Колонки файла → поля" },
3902
+ { label: "Предпросмотр", description: "Проверка первых строк" },
3903
+ { label: "Импорт", description: "Запуск + сводка" }
3904
+ ], l = E(0), i = p(() => n.step ?? l.value);
3905
+ function u(y) {
3906
+ n.step === void 0 && (y < 0 || y >= a.length || (l.value = y));
3907
+ }
3908
+ const f = E([]);
3909
+ function v(y) {
3910
+ f.value = y, y.length > 0 && o("file-uploaded", y[0].file);
3911
+ }
3912
+ const w = E({});
3913
+ function S(y, $) {
3914
+ w.value[y] = $ === null || $ === "" ? null : String($);
3915
+ }
3916
+ function R() {
3917
+ return n.headers.map((y) => ({
3918
+ source: y.key,
3919
+ target: w.value[y.key] ?? null
3920
+ }));
3921
+ }
3922
+ function A() {
3923
+ o("mapping-submit", R()), u(2);
3924
+ }
3925
+ function _() {
3926
+ o("run-import"), u(3);
3927
+ }
3928
+ const g = p(() => i.value > 0), U = p(() => {
3929
+ switch (i.value) {
3930
+ case 0:
3931
+ return f.value.length > 0;
3932
+ case 1:
3933
+ return Object.values(w.value).some((y) => y !== null);
3934
+ case 2:
3935
+ return !0;
3936
+ default:
3937
+ return !1;
3938
+ }
3939
+ }), P = p(() => [
3940
+ { value: "", label: "Не импортировать" },
3941
+ ...n.fieldOptions
3942
+ ]);
3943
+ function b() {
3944
+ o("cancel");
3945
+ }
3946
+ return (y, $) => (s(), c("section", ri, [
3947
+ d("header", ui, [
3948
+ d("div", di, [
3949
+ d("h1", ci, h(e.title), 1)
3950
+ ]),
3951
+ d("div", mi, [
3952
+ x(r(B), {
3953
+ variant: "ghost",
3954
+ onClick: b
3955
+ }, {
3956
+ default: m(() => [...$[2] || ($[2] = [
3957
+ C("Отмена", -1)
3958
+ ])]),
3959
+ _: 1
3960
+ })
3961
+ ])
3962
+ ]),
3963
+ x(r(Wt), {
3964
+ steps: a,
3965
+ current: i.value
3966
+ }, null, 8, ["current"]),
3967
+ i.value === 0 ? (s(), k(r(q), {
3968
+ key: 0,
3969
+ padding: "md",
3970
+ class: "admin-import-wizard__card"
3971
+ }, {
3972
+ default: m(() => [
3973
+ $[3] || ($[3] = d("header", { class: "admin-import-wizard__card-hd" }, [
3974
+ d("h3", null, "1. Загрузите файл"),
3975
+ d("p", null, "CSV / TSV / XLSX, до 50 MB")
3976
+ ], -1)),
3977
+ x(r(jt), {
3978
+ "model-value": f.value,
3979
+ accept: ".csv,.tsv,.xlsx",
3980
+ "max-size": 50 * 1024 * 1024,
3981
+ "max-files": 1,
3982
+ "primary-text": "Перетащите файл сюда или",
3983
+ "secondary-text": "нажмите чтобы выбрать",
3984
+ "onUpdate:modelValue": v
3985
+ }, null, 8, ["model-value"])
3986
+ ]),
3987
+ _: 1
3988
+ })) : i.value === 1 ? (s(), k(r(q), {
3989
+ key: 1,
3990
+ padding: "md",
3991
+ class: "admin-import-wizard__card"
3992
+ }, {
3993
+ default: m(() => [
3994
+ $[5] || ($[5] = d("header", { class: "admin-import-wizard__card-hd" }, [
3995
+ d("h3", null, "2. Сопоставьте колонки"),
3996
+ d("p", null, "Выберите поле ресурса для каждой колонки файла")
3997
+ ], -1)),
3998
+ e.headers.length === 0 ? (s(), c("div", fi, " Нет данных — host ещё не отдал headers. Загрузите файл сначала. ")) : (s(), c("div", vi, [
3999
+ (s(!0), c(T, null, I(e.headers, (V) => (s(), c("div", {
4000
+ key: V.key,
4001
+ class: "admin-import-wizard__map-row"
4002
+ }, [
4003
+ d("div", pi, [
4004
+ d("strong", null, h(V.label), 1),
4005
+ V.sample ? (s(), c("span", gi, " «" + h(V.sample) + "» ", 1)) : F("", !0)
4006
+ ]),
4007
+ $[4] || ($[4] = d("span", { class: "admin-import-wizard__map-arrow" }, "→", -1)),
4008
+ x(r($e), {
4009
+ "model-value": w.value[V.key] ?? "",
4010
+ options: P.value,
4011
+ placeholder: "Не импортировать",
4012
+ "onUpdate:modelValue": (j) => S(V.key, j)
4013
+ }, null, 8, ["model-value", "options", "onUpdate:modelValue"])
4014
+ ]))), 128))
4015
+ ]))
4016
+ ]),
4017
+ _: 1
4018
+ })) : i.value === 2 ? (s(), k(r(q), {
4019
+ key: 2,
4020
+ padding: "md",
4021
+ class: "admin-import-wizard__card"
4022
+ }, {
4023
+ default: m(() => [
4024
+ d("header", hi, [
4025
+ $[6] || ($[6] = d("h3", null, "3. Предпросмотр", -1)),
4026
+ d("p", null, "Первые " + h(e.preview.length) + " строк перед импортом", 1)
4027
+ ]),
4028
+ e.preview.some((V) => V.__warning) ? (s(), k(r(J), {
4029
+ key: 0,
4030
+ variant: "warning",
4031
+ style: { "margin-bottom": "var(--uid-space-md)" }
4032
+ }, {
4033
+ default: m(() => [...$[7] || ($[7] = [
4034
+ C(" Часть строк имеет предупреждения — проверьте перед импортом. ", -1)
4035
+ ])]),
4036
+ _: 1
4037
+ })) : F("", !0),
4038
+ e.previewColumns.length > 0 ? (s(), k(r(Ve), {
4039
+ key: 1,
4040
+ columns: e.previewColumns,
4041
+ data: e.preview
4042
+ }, null, 8, ["columns", "data"])) : (s(), c("div", _i, " Host не передал previewColumns/preview. "))
4043
+ ]),
4044
+ _: 1
4045
+ })) : (s(), k(r(q), {
4046
+ key: 3,
4047
+ padding: "md",
4048
+ class: "admin-import-wizard__card"
4049
+ }, {
4050
+ default: m(() => [
4051
+ $[8] || ($[8] = d("header", { class: "admin-import-wizard__card-hd" }, [
4052
+ d("h3", null, "4. Импорт")
4053
+ ], -1)),
4054
+ e.progress ? (s(), c(T, { key: 1 }, [
4055
+ e.progress.total > 0 ? (s(), k(r(Kt), {
4056
+ key: 0,
4057
+ "model-value": e.progress.created + e.progress.updated + e.progress.errors,
4058
+ max: e.progress.total
4059
+ }, null, 8, ["model-value", "max"])) : F("", !0),
4060
+ d("div", bi, [
4061
+ x(r(be), {
4062
+ title: "Создано",
4063
+ value: e.progress.created,
4064
+ tone: "success"
4065
+ }, null, 8, ["value"]),
4066
+ x(r(be), {
4067
+ title: "Обновлено",
4068
+ value: e.progress.updated,
4069
+ tone: "info"
4070
+ }, null, 8, ["value"]),
4071
+ x(r(be), {
4072
+ title: "Ошибки",
4073
+ value: e.progress.errors,
4074
+ tone: "danger"
4075
+ }, null, 8, ["value"])
4076
+ ])
4077
+ ], 64)) : (s(), c("div", yi, " Запускается импорт… "))
4078
+ ]),
4079
+ _: 1
4080
+ })),
4081
+ d("footer", ki, [
4082
+ g.value ? (s(), k(r(B), {
4083
+ key: 0,
4084
+ variant: "ghost",
4085
+ onClick: $[0] || ($[0] = (V) => u(i.value - 1))
4086
+ }, {
4087
+ default: m(() => [...$[9] || ($[9] = [
4088
+ C(" Назад ", -1)
4089
+ ])]),
4090
+ _: 1
4091
+ })) : F("", !0),
4092
+ $[13] || ($[13] = d("span", { style: { flex: "1" } }, null, -1)),
4093
+ i.value === 0 ? (s(), k(r(B), {
4094
+ key: 1,
4095
+ variant: "primary",
4096
+ disabled: !U.value,
4097
+ onClick: $[1] || ($[1] = (V) => u(1))
4098
+ }, {
4099
+ default: m(() => [...$[10] || ($[10] = [
4100
+ C(" Далее ", -1)
4101
+ ])]),
4102
+ _: 1
4103
+ }, 8, ["disabled"])) : i.value === 1 ? (s(), k(r(B), {
4104
+ key: 2,
4105
+ variant: "primary",
4106
+ disabled: !U.value,
4107
+ onClick: A
4108
+ }, {
4109
+ default: m(() => [...$[11] || ($[11] = [
4110
+ C(" Подтвердить mapping ", -1)
4111
+ ])]),
4112
+ _: 1
4113
+ }, 8, ["disabled"])) : i.value === 2 ? (s(), k(r(B), {
4114
+ key: 3,
4115
+ variant: "primary",
4116
+ onClick: _
4117
+ }, {
4118
+ default: m(() => [...$[12] || ($[12] = [
4119
+ C(" Запустить импорт ", -1)
4120
+ ])]),
4121
+ _: 1
4122
+ })) : F("", !0)
4123
+ ])
4124
+ ]));
4125
+ }
4126
+ }), wi = { class: "admin-page admin-field-gallery" }, $i = { class: "admin-gallery__group-title" }, xi = { class: "admin-gallery__grid" }, Ci = { class: "admin-gallery__card-hd" }, Si = { class: "admin-gallery__card-title" }, Ai = { class: "admin-gallery__card-type" }, Ri = { class: "admin-gallery__card-desc" }, Ui = { class: "admin-gallery__card-demo" }, io = /* @__PURE__ */ L({
4127
+ __name: "FieldGalleryPage",
4128
+ setup(e) {
4129
+ const t = [
4130
+ // Текстовые
4131
+ {
4132
+ type: "text",
4133
+ group: "Текстовые",
4134
+ title: "Input",
4135
+ description: "Простой текстовый input. type=email/url/password/tel доступны через inputType.",
4136
+ node: { type: "text", name: "demo_text", label: "Заголовок статьи", placeholder: "Например: Введение в Laravel" },
4137
+ initial: { demo_text: "Hello World" }
4138
+ },
4139
+ {
4140
+ type: "textarea",
4141
+ group: "Текстовые",
4142
+ title: "Textarea",
4143
+ description: "Многострочный input с настраиваемым числом rows.",
4144
+ node: { type: "textarea", name: "demo_textarea", label: "Описание", rows: 4 },
4145
+ initial: { demo_textarea: "Multi-line text..." }
4146
+ },
4147
+ {
4148
+ type: "number",
4149
+ group: "Текстовые",
4150
+ title: "NumberInput",
4151
+ description: "Числовой input. Empty/NaN автоматически конвертируются в null.",
4152
+ node: { type: "number", name: "demo_number", label: "Цена", min: 0, max: 1e3 },
4153
+ initial: { demo_number: 42 }
4154
+ },
4155
+ // Выбор
4156
+ {
4157
+ type: "select",
4158
+ group: "Выбор",
4159
+ title: "Select",
4160
+ description: "Single-select с options. Поддерживает searchable + clearable.",
4161
+ node: {
4162
+ type: "select",
4163
+ name: "demo_select",
4164
+ label: "Категория",
4165
+ options: [
4166
+ { value: "frontend", label: "Frontend" },
4167
+ { value: "backend", label: "Backend" },
4168
+ { value: "devops", label: "DevOps" }
4169
+ ]
4170
+ },
4171
+ initial: { demo_select: "backend" }
4172
+ },
4173
+ {
4174
+ type: "checkbox",
4175
+ group: "Выбор",
4176
+ title: "Checkbox",
4177
+ description: "Boolean toggle. inlineLabel рядом с боксом.",
4178
+ node: { type: "checkbox", name: "demo_checkbox", label: "Опубликовать", inlineLabel: "Сделать доступным всем" },
4179
+ initial: { demo_checkbox: !0 }
4180
+ },
4181
+ // Дата/время
4182
+ {
4183
+ type: "date",
4184
+ group: "Дата/время",
4185
+ title: "DatePicker",
4186
+ description: "date / datetime-local / time через inputType.",
4187
+ node: { type: "date", name: "demo_date", label: "Дата публикации", inputType: "date" },
4188
+ initial: { demo_date: "2026-05-01" }
4189
+ }
4190
+ ], n = t.reduce((a, l) => (a[l.group] || (a[l.group] = []), a[l.group].push(l), a), {}), o = wt(
4191
+ t.reduce((a, l) => Object.assign(a, l.initial), {})
4192
+ );
4193
+ return it(o), (a, l) => (s(), c("section", wi, [
4194
+ l[0] || (l[0] = d("header", { class: "admin-page__hd" }, [
4195
+ d("div", { class: "admin-page__title-wrap" }, [
4196
+ d("h1", { class: "admin-page__title" }, "Field Gallery"),
4197
+ d("div", { class: "admin-page__count" }, " Каталог встроенных field-компонентов library + примеры использования ")
4198
+ ])
4199
+ ], -1)),
4200
+ (s(!0), c(T, null, I(r(n), (i, u) => (s(), c("section", {
4201
+ key: u,
4202
+ class: "admin-gallery__group"
4203
+ }, [
4204
+ d("h2", $i, h(u), 1),
4205
+ d("div", xi, [
4206
+ (s(!0), c(T, null, I(i, (f) => (s(), k(r(q), {
4207
+ key: f.type + f.title,
4208
+ padding: "md",
4209
+ class: "admin-gallery__card"
4210
+ }, {
4211
+ default: m(() => [
4212
+ d("header", Ci, [
4213
+ d("h3", Si, h(f.title), 1),
4214
+ d("code", Ai, "type: " + h(f.type), 1)
4215
+ ]),
4216
+ d("p", Ri, h(f.description), 1),
4217
+ d("div", Ui, [
4218
+ x(ft, {
4219
+ node: f.node
4220
+ }, null, 8, ["node"])
4221
+ ])
4222
+ ]),
4223
+ _: 2
4224
+ }, 1024))), 128))
4225
+ ])
4226
+ ]))), 128))
4227
+ ]));
4228
+ }
4229
+ });
4230
+ export {
4231
+ kn as AdminApp,
4232
+ bn as AdminShell,
4233
+ hn as AdminSidebar,
4234
+ rn as AdminTopBar,
4235
+ Y as ApiError,
4236
+ Vs as BadgeEntry,
4237
+ Vl as BarChartWidget,
4238
+ Je as CheckboxField,
4239
+ Es as ColumnsLayout,
4240
+ Ll as DashboardPage,
4241
+ Te as DateField,
4242
+ Hl as DonutChartWidget,
4243
+ io as FieldGalleryPage,
4244
+ ft as FieldRenderer,
4245
+ en as ForbiddenError,
4246
+ Fn as ForbiddenPage,
4247
+ ls as GaugeWidget,
4248
+ es as HeatmapWidget,
4249
+ Un as HomePage,
4250
+ Ds as IconEntry,
4251
+ so as ImportWizardPage,
4252
+ Wa as InfolistRenderer,
4253
+ Qe as KeyValueEntry,
4254
+ he as LayoutRenderer,
4255
+ rt as LocaleSwitcher,
4256
+ Gn as LoginForm,
4257
+ sa as LoginPage,
4258
+ rs as MarkdownWidget,
4259
+ Ue as NetworkError,
4260
+ tn as NotFoundError,
4261
+ Pn as NotFoundPage,
4262
+ Zt as NotificationBell,
4263
+ lo as NotificationsDrawer,
4264
+ As as NumberField,
4265
+ bl as ProfilePage,
4266
+ Yl as RecentTableWidget,
4267
+ He as ResourceFormPage,
4268
+ $a as ResourceIndexPage,
4269
+ Qa as ResourceViewPage,
4270
+ Us as RowsLayout,
4271
+ Ye as SectionLayout,
4272
+ Rs as SelectField,
4273
+ Bn as SettingsPage,
4274
+ Pl as StatWidget,
4275
+ Ms as TabsLayout,
4276
+ Ss as TextAreaField,
4277
+ Is as TextEntry,
4278
+ se as TextField,
4279
+ ot as ThemeToggle,
4280
+ Jn as TwoFactorForm,
4281
+ ut as UnauthenticatedError,
4282
+ Pa as UnknownEntry,
4283
+ mt as UnknownField,
4284
+ Dn as UnknownScreenPage,
4285
+ $l as UnknownWidget,
4286
+ an as UserMenu,
4287
+ Re as ValidationError,
4288
+ xl as WidgetRenderer,
4289
+ bs as buildRoutesFromManifest,
4290
+ Ni as clearAdminClient,
4291
+ Hi as clearInfolistRegistry,
4292
+ Wi as clearRegistry,
4293
+ Zi as clearWidgetRegistry,
4294
+ to as createAdminApp,
4295
+ cs as createAdminClient,
4296
+ Cs as createAdminRouter,
4297
+ ks as createAuthGuard,
4298
+ ws as createTitleGuard,
4299
+ W as getAdminClient,
4300
+ ct as getField,
4301
+ Xe as getInfolistEntry,
4302
+ Ge as getLayout,
4303
+ kl as getWidget,
4304
+ Ii as hasAdminClient,
4305
+ Vi as hasField,
4306
+ Ki as hasInfolistEntry,
4307
+ Di as hasLayout,
4308
+ Yi as hasWidget,
4309
+ eo as isError,
4310
+ ds as isSuccess,
4311
+ zi as listFields,
4312
+ Gi as listInfolistEntries,
4313
+ Oi as listLayouts,
4314
+ Qi as listWidgets,
4315
+ no as loadBootstrap,
4316
+ it as provideFormState,
4317
+ ja as provideRecord,
4318
+ ao as readCsrfFromMeta,
4319
+ Ks as readInlineBootstrap,
4320
+ Ns as registerBuiltinComponents,
4321
+ Ws as registerBuiltinInfolistEntries,
4322
+ us as registerBuiltinWidgets,
4323
+ xa as registerComponents,
4324
+ Bi as registerField,
4325
+ La as registerInfolistEntries,
4326
+ ji as registerInfolistEntry,
4327
+ qi as registerLayout,
4328
+ Ji as registerWidget,
4329
+ wl as registerWidgets,
4330
+ Ht as setAdminClient,
4331
+ je as toApiError,
4332
+ uo as tryUseFormState,
4333
+ Fe as tryUseRecord,
4334
+ Q as useAuthStore,
4335
+ re as useFormState,
4336
+ De as useLocaleStore,
4337
+ ae as useManifestStore,
4338
+ un as useMenuStore,
4339
+ Oe as useNotificationsStore,
4340
+ Xi as useRecord,
4341
+ dt as useResourceFormStore,
4342
+ ia as useResourceIndexStore,
4343
+ qe as useThemeStore
4344
+ };
4345
+ //# sourceMappingURL=index.mjs.map