@dskripchenko/laravel-admin 1.2.1 → 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../node_modules/lucide-vue-next/dist/esm/shared/src/utils.js","../node_modules/lucide-vue-next/dist/esm/defaultAttributes.js","../node_modules/lucide-vue-next/dist/esm/Icon.js","../node_modules/lucide-vue-next/dist/esm/createLucideIcon.js","../node_modules/lucide-vue-next/dist/esm/icons/activity.js","../node_modules/lucide-vue-next/dist/esm/icons/archive.js","../node_modules/lucide-vue-next/dist/esm/icons/arrow-left.js","../node_modules/lucide-vue-next/dist/esm/icons/bell.js","../node_modules/lucide-vue-next/dist/esm/icons/bookmark.js","../node_modules/lucide-vue-next/dist/esm/icons/box.js","../node_modules/lucide-vue-next/dist/esm/icons/briefcase.js","../node_modules/lucide-vue-next/dist/esm/icons/calendar.js","../node_modules/lucide-vue-next/dist/esm/icons/chart-column.js","../node_modules/lucide-vue-next/dist/esm/icons/chart-line.js","../node_modules/lucide-vue-next/dist/esm/icons/chart-pie.js","../node_modules/lucide-vue-next/dist/esm/icons/check.js","../node_modules/lucide-vue-next/dist/esm/icons/chevron-down.js","../node_modules/lucide-vue-next/dist/esm/icons/circle-alert.js","../node_modules/lucide-vue-next/dist/esm/icons/circle-check-big.js","../node_modules/lucide-vue-next/dist/esm/icons/circle-help.js","../node_modules/lucide-vue-next/dist/esm/icons/circle-user.js","../node_modules/lucide-vue-next/dist/esm/icons/circle-x.js","../node_modules/lucide-vue-next/dist/esm/icons/clock.js","../node_modules/lucide-vue-next/dist/esm/icons/code.js","../node_modules/lucide-vue-next/dist/esm/icons/cog.js","../node_modules/lucide-vue-next/dist/esm/icons/columns-2.js","../node_modules/lucide-vue-next/dist/esm/icons/command.js","../node_modules/lucide-vue-next/dist/esm/icons/database.js","../node_modules/lucide-vue-next/dist/esm/icons/download.js","../node_modules/lucide-vue-next/dist/esm/icons/ellipsis.js","../node_modules/lucide-vue-next/dist/esm/icons/eye.js","../node_modules/lucide-vue-next/dist/esm/icons/file-clock.js","../node_modules/lucide-vue-next/dist/esm/icons/file-text.js","../node_modules/lucide-vue-next/dist/esm/icons/files.js","../node_modules/lucide-vue-next/dist/esm/icons/flag.js","../node_modules/lucide-vue-next/dist/esm/icons/folder-open.js","../node_modules/lucide-vue-next/dist/esm/icons/folder.js","../node_modules/lucide-vue-next/dist/esm/icons/gauge.js","../node_modules/lucide-vue-next/dist/esm/icons/globe.js","../node_modules/lucide-vue-next/dist/esm/icons/grid-3x3.js","../node_modules/lucide-vue-next/dist/esm/icons/grip-vertical.js","../node_modules/lucide-vue-next/dist/esm/icons/hard-drive.js","../node_modules/lucide-vue-next/dist/esm/icons/hash.js","../node_modules/lucide-vue-next/dist/esm/icons/heart.js","../node_modules/lucide-vue-next/dist/esm/icons/history.js","../node_modules/lucide-vue-next/dist/esm/icons/house.js","../node_modules/lucide-vue-next/dist/esm/icons/image.js","../node_modules/lucide-vue-next/dist/esm/icons/images.js","../node_modules/lucide-vue-next/dist/esm/icons/inbox.js","../node_modules/lucide-vue-next/dist/esm/icons/info.js","../node_modules/lucide-vue-next/dist/esm/icons/key.js","../node_modules/lucide-vue-next/dist/esm/icons/layers.js","../node_modules/lucide-vue-next/dist/esm/icons/layout-dashboard.js","../node_modules/lucide-vue-next/dist/esm/icons/layout-grid.js","../node_modules/lucide-vue-next/dist/esm/icons/life-buoy.js","../node_modules/lucide-vue-next/dist/esm/icons/link.js","../node_modules/lucide-vue-next/dist/esm/icons/list-checks.js","../node_modules/lucide-vue-next/dist/esm/icons/list.js","../node_modules/lucide-vue-next/dist/esm/icons/lock.js","../node_modules/lucide-vue-next/dist/esm/icons/log-out.js","../node_modules/lucide-vue-next/dist/esm/icons/mail.js","../node_modules/lucide-vue-next/dist/esm/icons/map-pin.js","../node_modules/lucide-vue-next/dist/esm/icons/map.js","../node_modules/lucide-vue-next/dist/esm/icons/message-square.js","../node_modules/lucide-vue-next/dist/esm/icons/monitor.js","../node_modules/lucide-vue-next/dist/esm/icons/moon.js","../node_modules/lucide-vue-next/dist/esm/icons/package.js","../node_modules/lucide-vue-next/dist/esm/icons/panel-left.js","../node_modules/lucide-vue-next/dist/esm/icons/panels-top-left.js","../node_modules/lucide-vue-next/dist/esm/icons/paperclip.js","../node_modules/lucide-vue-next/dist/esm/icons/pencil.js","../node_modules/lucide-vue-next/dist/esm/icons/plus.js","../node_modules/lucide-vue-next/dist/esm/icons/refresh-cw.js","../node_modules/lucide-vue-next/dist/esm/icons/rotate-ccw.js","../node_modules/lucide-vue-next/dist/esm/icons/search.js","../node_modules/lucide-vue-next/dist/esm/icons/send.js","../node_modules/lucide-vue-next/dist/esm/icons/server.js","../node_modules/lucide-vue-next/dist/esm/icons/settings.js","../node_modules/lucide-vue-next/dist/esm/icons/shield.js","../node_modules/lucide-vue-next/dist/esm/icons/shopping-bag.js","../node_modules/lucide-vue-next/dist/esm/icons/shopping-cart.js","../node_modules/lucide-vue-next/dist/esm/icons/sliders-vertical.js","../node_modules/lucide-vue-next/dist/esm/icons/square-pen.js","../node_modules/lucide-vue-next/dist/esm/icons/star.js","../node_modules/lucide-vue-next/dist/esm/icons/store.js","../node_modules/lucide-vue-next/dist/esm/icons/sun.js","../node_modules/lucide-vue-next/dist/esm/icons/tag.js","../node_modules/lucide-vue-next/dist/esm/icons/tags.js","../node_modules/lucide-vue-next/dist/esm/icons/terminal.js","../node_modules/lucide-vue-next/dist/esm/icons/trash-2.js","../node_modules/lucide-vue-next/dist/esm/icons/trending-up.js","../node_modules/lucide-vue-next/dist/esm/icons/triangle-alert.js","../node_modules/lucide-vue-next/dist/esm/icons/upload.js","../node_modules/lucide-vue-next/dist/esm/icons/user-plus.js","../node_modules/lucide-vue-next/dist/esm/icons/user.js","../node_modules/lucide-vue-next/dist/esm/icons/users.js","../node_modules/lucide-vue-next/dist/esm/icons/x.js","../node_modules/lucide-vue-next/dist/esm/icons/zap.js","../resources/ts/stores/registry.ts","../resources/ts/stores/theme.ts","../resources/ts/components/shell/widgets/ThemeToggle.vue","../resources/ts/stores/locale.ts","../resources/ts/components/shell/widgets/LocaleSwitcher.vue","../resources/ts/stores/notifications.ts","../resources/ts/components/shell/widgets/NotificationBell.vue","../resources/ts/api/errors.ts","../resources/ts/stores/auth.ts","../resources/ts/components/shell/widgets/UserMenu.vue","../resources/ts/components/shell/AdminTopBar.vue","../resources/ts/stores/menu.ts","../resources/ts/components/shell/BrandLogo.vue","../resources/ts/components/shell/iconRegistry.ts","../resources/ts/components/shell/AdminSidebar.vue","../resources/ts/components/shell/AdminShell.vue","../resources/ts/stores/navigation.ts","../resources/ts/components/AdminLoadingBar.vue","../resources/ts/components/shell/NotificationsDrawer.vue","../resources/ts/stores/manifest.ts","../resources/ts/stores/toast.ts","../resources/ts/components/AdminApp.vue","../resources/ts/stores/dashboard.ts","../resources/ts/stores/i18n.ts","../resources/ts/components/createComponentRegistry.ts","../resources/ts/components/dashboard/registry.ts","../resources/ts/components/dashboard/UnknownWidget.vue","../resources/ts/components/dashboard/WidgetRenderer.vue","../resources/ts/components/dashboard/WidgetActionsOverlay.vue","../resources/ts/components/dashboard/WidgetConfigDialog.vue","../resources/ts/components/dashboard/DashboardPage.vue","../resources/ts/components/HomePage.vue","../resources/ts/components/ForbiddenPage.vue","../resources/ts/components/NotFoundPage.vue","../resources/ts/components/SettingsPage.vue","../resources/ts/components/UnknownScreenPage.vue","../resources/ts/components/auth/LoginForm.vue","../resources/ts/components/auth/TwoFactorForm.vue","../resources/ts/components/auth/LoginPage.vue","../resources/ts/components/auth/ForgotPasswordPage.vue","../resources/ts/components/auth/ResetPasswordPage.vue","../resources/ts/stores/resourceIndex.ts","../resources/ts/components/resource/cellFormat.ts","../resources/ts/components/resource/FilterEditor.ts","../resources/ts/components/resource/AdminFilterToolbar.vue","../resources/ts/components/resource/InlineEditCell.vue","../resources/ts/components/resource/ResourceIndexPage.vue","../resources/ts/stores/resourceForm.ts","../resources/ts/components/render/registry.ts","../resources/ts/components/fields/UnknownField.vue","../resources/ts/components/render/FieldRenderer.vue","../resources/ts/components/render/LayoutRenderer.vue","../resources/ts/components/resource/ResourceFormPage.vue","../resources/ts/components/infolist/registry.ts","../resources/ts/components/infolist/UnknownEntry.vue","../resources/ts/components/infolist/InfolistRenderer.vue","../resources/ts/components/infolist/recordContext.ts","../resources/ts/components/resource/AuditTimeline.vue","../resources/ts/components/resource/ResourceViewPage.vue","../resources/ts/components/profile/ProfilePage.vue","../resources/ts/components/dashboard/StatWidget.vue","../resources/ts/components/dashboard/BarChartWidget.vue","../resources/ts/components/dashboard/DonutChartWidget.vue","../resources/ts/components/dashboard/RecentTableWidget.vue","../resources/ts/components/dashboard/HeatmapWidget.vue","../resources/ts/components/dashboard/GaugeWidget.vue","../resources/ts/components/dashboard/MarkdownWidget.vue","../resources/ts/components/dashboard/ChartWidget.vue","../resources/ts/components/dashboard/builtin.ts","../resources/ts/api/envelope.ts","../resources/ts/api/client.ts","../resources/ts/router/builder.ts","../resources/ts/router/guards.ts","../resources/ts/router/index.ts","../resources/ts/components/fields/TextField.vue","../resources/ts/components/fields/TextAreaField.vue","../resources/ts/components/fields/NumberField.vue","../resources/ts/components/fields/SelectField.vue","../resources/ts/components/fields/CheckboxField.vue","../resources/ts/components/fields/DateField.vue","../resources/ts/components/fields/TagsField.vue","../resources/ts/components/fields/TranslatableField.vue","../resources/ts/components/layouts/RowsLayout.vue","../resources/ts/components/layouts/ColumnsLayout.vue","../resources/ts/components/layouts/SectionLayout.vue","../resources/ts/components/layouts/TabsLayout.vue","../resources/ts/components/render/builtin.ts","../resources/ts/components/infolist/TextEntry.vue","../resources/ts/components/infolist/BadgeEntry.vue","../resources/ts/components/infolist/IconEntry.vue","../resources/ts/components/infolist/KeyValueEntry.vue","../resources/ts/components/infolist/builtin.ts","../resources/ts/createAdminApp.ts","../resources/ts/api/bootstrap.ts","../resources/ts/components/notifications/NotificationsDrawer.vue","../resources/ts/components/import/ImportWizardPage.vue","../resources/ts/components/gallery/FieldGalleryPage.vue"],"sourcesContent":["/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst toKebabCase = (string) => string.replace(/([a-z0-9])([A-Z])/g, \"$1-$2\").toLowerCase();\n\nexport { toKebabCase };\n//# sourceMappingURL=utils.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nvar defaultAttributes = {\n xmlns: \"http://www.w3.org/2000/svg\",\n width: 24,\n height: 24,\n viewBox: \"0 0 24 24\",\n fill: \"none\",\n stroke: \"currentColor\",\n \"stroke-width\": 2,\n \"stroke-linecap\": \"round\",\n \"stroke-linejoin\": \"round\"\n};\n\nexport { defaultAttributes as default };\n//# sourceMappingURL=defaultAttributes.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport { h } from 'vue';\nimport { toKebabCase } from './shared/src/utils.js';\nimport defaultAttributes from './defaultAttributes.js';\n\nconst Icon = ({ size, strokeWidth = 2, absoluteStrokeWidth, color, iconNode, name, class: classes, ...props }, { slots }) => {\n return h(\n \"svg\",\n {\n ...defaultAttributes,\n width: size || defaultAttributes.width,\n height: size || defaultAttributes.height,\n stroke: color || defaultAttributes.stroke,\n \"stroke-width\": absoluteStrokeWidth ? Number(strokeWidth) * 24 / Number(size) : strokeWidth,\n class: [\"lucide\", `lucide-${toKebabCase(name ?? \"icon\")}`],\n ...props\n },\n [...iconNode.map((child) => h(...child)), ...slots.default ? [slots.default()] : []]\n );\n};\n\nexport { Icon as default };\n//# sourceMappingURL=Icon.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport { h } from 'vue';\nimport Icon from './Icon.js';\n\nconst createLucideIcon = (iconName, iconNode) => (props, { slots }) => h(\n Icon,\n {\n ...props,\n iconNode,\n name: iconName\n },\n slots\n);\n\nexport { createLucideIcon as default };\n//# sourceMappingURL=createLucideIcon.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Activity = createLucideIcon(\"ActivityIcon\", [\n [\n \"path\",\n {\n d: \"M22 12h-2.48a2 2 0 0 0-1.93 1.46l-2.35 8.36a.25.25 0 0 1-.48 0L9.24 2.18a.25.25 0 0 0-.48 0l-2.35 8.36A2 2 0 0 1 4.49 12H2\",\n key: \"169zse\"\n }\n ]\n]);\n\nexport { Activity as default };\n//# sourceMappingURL=activity.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Archive = createLucideIcon(\"ArchiveIcon\", [\n [\"rect\", { width: \"20\", height: \"5\", x: \"2\", y: \"3\", rx: \"1\", key: \"1wp1u1\" }],\n [\"path\", { d: \"M4 8v11a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8\", key: \"1s80jp\" }],\n [\"path\", { d: \"M10 12h4\", key: \"a56b0p\" }]\n]);\n\nexport { Archive as default };\n//# sourceMappingURL=archive.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst ArrowLeft = createLucideIcon(\"ArrowLeftIcon\", [\n [\"path\", { d: \"m12 19-7-7 7-7\", key: \"1l729n\" }],\n [\"path\", { d: \"M19 12H5\", key: \"x3x0zl\" }]\n]);\n\nexport { ArrowLeft as default };\n//# sourceMappingURL=arrow-left.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Bell = createLucideIcon(\"BellIcon\", [\n [\"path\", { d: \"M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9\", key: \"1qo2s2\" }],\n [\"path\", { d: \"M10.3 21a1.94 1.94 0 0 0 3.4 0\", key: \"qgo35s\" }]\n]);\n\nexport { Bell as default };\n//# sourceMappingURL=bell.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Bookmark = createLucideIcon(\"BookmarkIcon\", [\n [\"path\", { d: \"m19 21-7-4-7 4V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v16z\", key: \"1fy3hk\" }]\n]);\n\nexport { Bookmark as default };\n//# sourceMappingURL=bookmark.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Box = createLucideIcon(\"BoxIcon\", [\n [\n \"path\",\n {\n d: \"M21 8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16Z\",\n key: \"hh9hay\"\n }\n ],\n [\"path\", { d: \"m3.3 7 8.7 5 8.7-5\", key: \"g66t2b\" }],\n [\"path\", { d: \"M12 22V12\", key: \"d0xqtd\" }]\n]);\n\nexport { Box as default };\n//# sourceMappingURL=box.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Briefcase = createLucideIcon(\"BriefcaseIcon\", [\n [\"path\", { d: \"M16 20V4a2 2 0 0 0-2-2h-4a2 2 0 0 0-2 2v16\", key: \"jecpp\" }],\n [\"rect\", { width: \"20\", height: \"14\", x: \"2\", y: \"6\", rx: \"2\", key: \"i6l2r4\" }]\n]);\n\nexport { Briefcase as default };\n//# sourceMappingURL=briefcase.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Calendar = createLucideIcon(\"CalendarIcon\", [\n [\"path\", { d: \"M8 2v4\", key: \"1cmpym\" }],\n [\"path\", { d: \"M16 2v4\", key: \"4m81vk\" }],\n [\"rect\", { width: \"18\", height: \"18\", x: \"3\", y: \"4\", rx: \"2\", key: \"1hopcy\" }],\n [\"path\", { d: \"M3 10h18\", key: \"8toen8\" }]\n]);\n\nexport { Calendar as default };\n//# sourceMappingURL=calendar.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst ChartColumn = createLucideIcon(\"ChartColumnIcon\", [\n [\"path\", { d: \"M3 3v16a2 2 0 0 0 2 2h16\", key: \"c24i48\" }],\n [\"path\", { d: \"M18 17V9\", key: \"2bz60n\" }],\n [\"path\", { d: \"M13 17V5\", key: \"1frdt8\" }],\n [\"path\", { d: \"M8 17v-3\", key: \"17ska0\" }]\n]);\n\nexport { ChartColumn as default };\n//# sourceMappingURL=chart-column.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst ChartLine = createLucideIcon(\"ChartLineIcon\", [\n [\"path\", { d: \"M3 3v16a2 2 0 0 0 2 2h16\", key: \"c24i48\" }],\n [\"path\", { d: \"m19 9-5 5-4-4-3 3\", key: \"2osh9i\" }]\n]);\n\nexport { ChartLine as default };\n//# sourceMappingURL=chart-line.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst ChartPie = createLucideIcon(\"ChartPieIcon\", [\n [\n \"path\",\n {\n d: \"M21 12c.552 0 1.005-.449.95-.998a10 10 0 0 0-8.953-8.951c-.55-.055-.998.398-.998.95v8a1 1 0 0 0 1 1z\",\n key: \"pzmjnu\"\n }\n ],\n [\"path\", { d: \"M21.21 15.89A10 10 0 1 1 8 2.83\", key: \"k2fpak\" }]\n]);\n\nexport { ChartPie as default };\n//# sourceMappingURL=chart-pie.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Check = createLucideIcon(\"CheckIcon\", [[\"path\", { d: \"M20 6 9 17l-5-5\", key: \"1gmf2c\" }]]);\n\nexport { Check as default };\n//# sourceMappingURL=check.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst ChevronDown = createLucideIcon(\"ChevronDownIcon\", [\n [\"path\", { d: \"m6 9 6 6 6-6\", key: \"qrunsl\" }]\n]);\n\nexport { ChevronDown as default };\n//# sourceMappingURL=chevron-down.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst CircleAlert = createLucideIcon(\"CircleAlertIcon\", [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"10\", key: \"1mglay\" }],\n [\"line\", { x1: \"12\", x2: \"12\", y1: \"8\", y2: \"12\", key: \"1pkeuh\" }],\n [\"line\", { x1: \"12\", x2: \"12.01\", y1: \"16\", y2: \"16\", key: \"4dfq90\" }]\n]);\n\nexport { CircleAlert as default };\n//# sourceMappingURL=circle-alert.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst CircleCheckBig = createLucideIcon(\"CircleCheckBigIcon\", [\n [\"path\", { d: \"M21.801 10A10 10 0 1 1 17 3.335\", key: \"yps3ct\" }],\n [\"path\", { d: \"m9 11 3 3L22 4\", key: \"1pflzl\" }]\n]);\n\nexport { CircleCheckBig as default };\n//# sourceMappingURL=circle-check-big.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst CircleHelp = createLucideIcon(\"CircleHelpIcon\", [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"10\", key: \"1mglay\" }],\n [\"path\", { d: \"M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3\", key: \"1u773s\" }],\n [\"path\", { d: \"M12 17h.01\", key: \"p32p05\" }]\n]);\n\nexport { CircleHelp as default };\n//# sourceMappingURL=circle-help.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst CircleUser = createLucideIcon(\"CircleUserIcon\", [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"10\", key: \"1mglay\" }],\n [\"circle\", { cx: \"12\", cy: \"10\", r: \"3\", key: \"ilqhr7\" }],\n [\"path\", { d: \"M7 20.662V19a2 2 0 0 1 2-2h6a2 2 0 0 1 2 2v1.662\", key: \"154egf\" }]\n]);\n\nexport { CircleUser as default };\n//# sourceMappingURL=circle-user.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst CircleX = createLucideIcon(\"CircleXIcon\", [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"10\", key: \"1mglay\" }],\n [\"path\", { d: \"m15 9-6 6\", key: \"1uzhvr\" }],\n [\"path\", { d: \"m9 9 6 6\", key: \"z0biqf\" }]\n]);\n\nexport { CircleX as default };\n//# sourceMappingURL=circle-x.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Clock = createLucideIcon(\"ClockIcon\", [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"10\", key: \"1mglay\" }],\n [\"polyline\", { points: \"12 6 12 12 16 14\", key: \"68esgv\" }]\n]);\n\nexport { Clock as default };\n//# sourceMappingURL=clock.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Code = createLucideIcon(\"CodeIcon\", [\n [\"polyline\", { points: \"16 18 22 12 16 6\", key: \"z7tu5w\" }],\n [\"polyline\", { points: \"8 6 2 12 8 18\", key: \"1eg1df\" }]\n]);\n\nexport { Code as default };\n//# sourceMappingURL=code.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Cog = createLucideIcon(\"CogIcon\", [\n [\"path\", { d: \"M12 20a8 8 0 1 0 0-16 8 8 0 0 0 0 16Z\", key: \"sobvz5\" }],\n [\"path\", { d: \"M12 14a2 2 0 1 0 0-4 2 2 0 0 0 0 4Z\", key: \"11i496\" }],\n [\"path\", { d: \"M12 2v2\", key: \"tus03m\" }],\n [\"path\", { d: \"M12 22v-2\", key: \"1osdcq\" }],\n [\"path\", { d: \"m17 20.66-1-1.73\", key: \"eq3orb\" }],\n [\"path\", { d: \"M11 10.27 7 3.34\", key: \"16pf9h\" }],\n [\"path\", { d: \"m20.66 17-1.73-1\", key: \"sg0v6f\" }],\n [\"path\", { d: \"m3.34 7 1.73 1\", key: \"1ulond\" }],\n [\"path\", { d: \"M14 12h8\", key: \"4f43i9\" }],\n [\"path\", { d: \"M2 12h2\", key: \"1t8f8n\" }],\n [\"path\", { d: \"m20.66 7-1.73 1\", key: \"1ow05n\" }],\n [\"path\", { d: \"m3.34 17 1.73-1\", key: \"nuk764\" }],\n [\"path\", { d: \"m17 3.34-1 1.73\", key: \"2wel8s\" }],\n [\"path\", { d: \"m11 13.73-4 6.93\", key: \"794ttg\" }]\n]);\n\nexport { Cog as default };\n//# sourceMappingURL=cog.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Columns2 = createLucideIcon(\"Columns2Icon\", [\n [\"rect\", { width: \"18\", height: \"18\", x: \"3\", y: \"3\", rx: \"2\", key: \"afitv7\" }],\n [\"path\", { d: \"M12 3v18\", key: \"108xh3\" }]\n]);\n\nexport { Columns2 as default };\n//# sourceMappingURL=columns-2.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Command = createLucideIcon(\"CommandIcon\", [\n [\n \"path\",\n { d: \"M15 6v12a3 3 0 1 0 3-3H6a3 3 0 1 0 3 3V6a3 3 0 1 0-3 3h12a3 3 0 1 0-3-3\", key: \"11bfej\" }\n ]\n]);\n\nexport { Command as default };\n//# sourceMappingURL=command.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Database = createLucideIcon(\"DatabaseIcon\", [\n [\"ellipse\", { cx: \"12\", cy: \"5\", rx: \"9\", ry: \"3\", key: \"msslwz\" }],\n [\"path\", { d: \"M3 5V19A9 3 0 0 0 21 19V5\", key: \"1wlel7\" }],\n [\"path\", { d: \"M3 12A9 3 0 0 0 21 12\", key: \"mv7ke4\" }]\n]);\n\nexport { Database as default };\n//# sourceMappingURL=database.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Download = createLucideIcon(\"DownloadIcon\", [\n [\"path\", { d: \"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\", key: \"ih7n3h\" }],\n [\"polyline\", { points: \"7 10 12 15 17 10\", key: \"2ggqvy\" }],\n [\"line\", { x1: \"12\", x2: \"12\", y1: \"15\", y2: \"3\", key: \"1vk2je\" }]\n]);\n\nexport { Download as default };\n//# sourceMappingURL=download.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Ellipsis = createLucideIcon(\"EllipsisIcon\", [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"1\", key: \"41hilf\" }],\n [\"circle\", { cx: \"19\", cy: \"12\", r: \"1\", key: \"1wjl8i\" }],\n [\"circle\", { cx: \"5\", cy: \"12\", r: \"1\", key: \"1pcz8c\" }]\n]);\n\nexport { Ellipsis as default };\n//# sourceMappingURL=ellipsis.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Eye = createLucideIcon(\"EyeIcon\", [\n [\n \"path\",\n {\n d: \"M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0\",\n key: \"1nclc0\"\n }\n ],\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"3\", key: \"1v7zrd\" }]\n]);\n\nexport { Eye as default };\n//# sourceMappingURL=eye.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst FileClock = createLucideIcon(\"FileClockIcon\", [\n [\"path\", { d: \"M16 22h2a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v3\", key: \"37hlfg\" }],\n [\"path\", { d: \"M14 2v4a2 2 0 0 0 2 2h4\", key: \"tnqrlb\" }],\n [\"circle\", { cx: \"8\", cy: \"16\", r: \"6\", key: \"10v15b\" }],\n [\"path\", { d: \"M9.5 17.5 8 16.25V14\", key: \"1o80t2\" }]\n]);\n\nexport { FileClock as default };\n//# sourceMappingURL=file-clock.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst FileText = createLucideIcon(\"FileTextIcon\", [\n [\"path\", { d: \"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z\", key: \"1rqfz7\" }],\n [\"path\", { d: \"M14 2v4a2 2 0 0 0 2 2h4\", key: \"tnqrlb\" }],\n [\"path\", { d: \"M10 9H8\", key: \"b1mrlr\" }],\n [\"path\", { d: \"M16 13H8\", key: \"t4e002\" }],\n [\"path\", { d: \"M16 17H8\", key: \"z1uh3a\" }]\n]);\n\nexport { FileText as default };\n//# sourceMappingURL=file-text.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Files = createLucideIcon(\"FilesIcon\", [\n [\"path\", { d: \"M20 7h-3a2 2 0 0 1-2-2V2\", key: \"x099mo\" }],\n [\"path\", { d: \"M9 18a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h7l4 4v10a2 2 0 0 1-2 2Z\", key: \"18t6ie\" }],\n [\"path\", { d: \"M3 7.6v12.8A1.6 1.6 0 0 0 4.6 22h9.8\", key: \"1nja0z\" }]\n]);\n\nexport { Files as default };\n//# sourceMappingURL=files.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Flag = createLucideIcon(\"FlagIcon\", [\n [\"path\", { d: \"M4 15s1-1 4-1 5 2 8 2 4-1 4-1V3s-1 1-4 1-5-2-8-2-4 1-4 1z\", key: \"i9b6wo\" }],\n [\"line\", { x1: \"4\", x2: \"4\", y1: \"22\", y2: \"15\", key: \"1cm3nv\" }]\n]);\n\nexport { Flag as default };\n//# sourceMappingURL=flag.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst FolderOpen = createLucideIcon(\"FolderOpenIcon\", [\n [\n \"path\",\n {\n d: \"m6 14 1.5-2.9A2 2 0 0 1 9.24 10H20a2 2 0 0 1 1.94 2.5l-1.54 6a2 2 0 0 1-1.95 1.5H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H18a2 2 0 0 1 2 2v2\",\n key: \"usdka0\"\n }\n ]\n]);\n\nexport { FolderOpen as default };\n//# sourceMappingURL=folder-open.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Folder = createLucideIcon(\"FolderIcon\", [\n [\n \"path\",\n {\n d: \"M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z\",\n key: \"1kt360\"\n }\n ]\n]);\n\nexport { Folder as default };\n//# sourceMappingURL=folder.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Gauge = createLucideIcon(\"GaugeIcon\", [\n [\"path\", { d: \"m12 14 4-4\", key: \"9kzdfg\" }],\n [\"path\", { d: \"M3.34 19a10 10 0 1 1 17.32 0\", key: \"19p75a\" }]\n]);\n\nexport { Gauge as default };\n//# sourceMappingURL=gauge.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Globe = createLucideIcon(\"GlobeIcon\", [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"10\", key: \"1mglay\" }],\n [\"path\", { d: \"M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20\", key: \"13o1zl\" }],\n [\"path\", { d: \"M2 12h20\", key: \"9i4pu4\" }]\n]);\n\nexport { Globe as default };\n//# sourceMappingURL=globe.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Grid3x3 = createLucideIcon(\"Grid3x3Icon\", [\n [\"rect\", { width: \"18\", height: \"18\", x: \"3\", y: \"3\", rx: \"2\", key: \"afitv7\" }],\n [\"path\", { d: \"M3 9h18\", key: \"1pudct\" }],\n [\"path\", { d: \"M3 15h18\", key: \"5xshup\" }],\n [\"path\", { d: \"M9 3v18\", key: \"fh3hqa\" }],\n [\"path\", { d: \"M15 3v18\", key: \"14nvp0\" }]\n]);\n\nexport { Grid3x3 as default };\n//# sourceMappingURL=grid-3x3.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst GripVertical = createLucideIcon(\"GripVerticalIcon\", [\n [\"circle\", { cx: \"9\", cy: \"12\", r: \"1\", key: \"1vctgf\" }],\n [\"circle\", { cx: \"9\", cy: \"5\", r: \"1\", key: \"hp0tcf\" }],\n [\"circle\", { cx: \"9\", cy: \"19\", r: \"1\", key: \"fkjjf6\" }],\n [\"circle\", { cx: \"15\", cy: \"12\", r: \"1\", key: \"1tmaij\" }],\n [\"circle\", { cx: \"15\", cy: \"5\", r: \"1\", key: \"19l28e\" }],\n [\"circle\", { cx: \"15\", cy: \"19\", r: \"1\", key: \"f4zoj3\" }]\n]);\n\nexport { GripVertical as default };\n//# sourceMappingURL=grip-vertical.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst HardDrive = createLucideIcon(\"HardDriveIcon\", [\n [\"line\", { x1: \"22\", x2: \"2\", y1: \"12\", y2: \"12\", key: \"1y58io\" }],\n [\n \"path\",\n {\n d: \"M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z\",\n key: \"oot6mr\"\n }\n ],\n [\"line\", { x1: \"6\", x2: \"6.01\", y1: \"16\", y2: \"16\", key: \"sgf278\" }],\n [\"line\", { x1: \"10\", x2: \"10.01\", y1: \"16\", y2: \"16\", key: \"1l4acy\" }]\n]);\n\nexport { HardDrive as default };\n//# sourceMappingURL=hard-drive.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Hash = createLucideIcon(\"HashIcon\", [\n [\"line\", { x1: \"4\", x2: \"20\", y1: \"9\", y2: \"9\", key: \"4lhtct\" }],\n [\"line\", { x1: \"4\", x2: \"20\", y1: \"15\", y2: \"15\", key: \"vyu0kd\" }],\n [\"line\", { x1: \"10\", x2: \"8\", y1: \"3\", y2: \"21\", key: \"1ggp8o\" }],\n [\"line\", { x1: \"16\", x2: \"14\", y1: \"3\", y2: \"21\", key: \"weycgp\" }]\n]);\n\nexport { Hash as default };\n//# sourceMappingURL=hash.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Heart = createLucideIcon(\"HeartIcon\", [\n [\n \"path\",\n {\n d: \"M19 14c1.49-1.46 3-3.21 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.76 0-3 .5-4.5 2-1.5-1.5-2.74-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.3 1.5 4.05 3 5.5l7 7Z\",\n key: \"c3ymky\"\n }\n ]\n]);\n\nexport { Heart as default };\n//# sourceMappingURL=heart.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst History = createLucideIcon(\"HistoryIcon\", [\n [\"path\", { d: \"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8\", key: \"1357e3\" }],\n [\"path\", { d: \"M3 3v5h5\", key: \"1xhq8a\" }],\n [\"path\", { d: \"M12 7v5l4 2\", key: \"1fdv2h\" }]\n]);\n\nexport { History as default };\n//# sourceMappingURL=history.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst House = createLucideIcon(\"HouseIcon\", [\n [\"path\", { d: \"M15 21v-8a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v8\", key: \"5wwlr5\" }],\n [\n \"path\",\n {\n d: \"M3 10a2 2 0 0 1 .709-1.528l7-5.999a2 2 0 0 1 2.582 0l7 5.999A2 2 0 0 1 21 10v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z\",\n key: \"1d0kgt\"\n }\n ]\n]);\n\nexport { House as default };\n//# sourceMappingURL=house.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Image = createLucideIcon(\"ImageIcon\", [\n [\"rect\", { width: \"18\", height: \"18\", x: \"3\", y: \"3\", rx: \"2\", ry: \"2\", key: \"1m3agn\" }],\n [\"circle\", { cx: \"9\", cy: \"9\", r: \"2\", key: \"af1f0g\" }],\n [\"path\", { d: \"m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21\", key: \"1xmnt7\" }]\n]);\n\nexport { Image as default };\n//# sourceMappingURL=image.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Images = createLucideIcon(\"ImagesIcon\", [\n [\"path\", { d: \"M18 22H4a2 2 0 0 1-2-2V6\", key: \"pblm9e\" }],\n [\"path\", { d: \"m22 13-1.296-1.296a2.41 2.41 0 0 0-3.408 0L11 18\", key: \"nf6bnh\" }],\n [\"circle\", { cx: \"12\", cy: \"8\", r: \"2\", key: \"1822b1\" }],\n [\"rect\", { width: \"16\", height: \"16\", x: \"6\", y: \"2\", rx: \"2\", key: \"12espp\" }]\n]);\n\nexport { Images as default };\n//# sourceMappingURL=images.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Inbox = createLucideIcon(\"InboxIcon\", [\n [\"polyline\", { points: \"22 12 16 12 14 15 10 15 8 12 2 12\", key: \"o97t9d\" }],\n [\n \"path\",\n {\n d: \"M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z\",\n key: \"oot6mr\"\n }\n ]\n]);\n\nexport { Inbox as default };\n//# sourceMappingURL=inbox.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Info = createLucideIcon(\"InfoIcon\", [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"10\", key: \"1mglay\" }],\n [\"path\", { d: \"M12 16v-4\", key: \"1dtifu\" }],\n [\"path\", { d: \"M12 8h.01\", key: \"e9boi3\" }]\n]);\n\nexport { Info as default };\n//# sourceMappingURL=info.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Key = createLucideIcon(\"KeyIcon\", [\n [\"path\", { d: \"m15.5 7.5 2.3 2.3a1 1 0 0 0 1.4 0l2.1-2.1a1 1 0 0 0 0-1.4L19 4\", key: \"g0fldk\" }],\n [\"path\", { d: \"m21 2-9.6 9.6\", key: \"1j0ho8\" }],\n [\"circle\", { cx: \"7.5\", cy: \"15.5\", r: \"5.5\", key: \"yqb3hr\" }]\n]);\n\nexport { Key as default };\n//# sourceMappingURL=key.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Layers = createLucideIcon(\"LayersIcon\", [\n [\n \"path\",\n {\n d: \"m12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83Z\",\n key: \"8b97xw\"\n }\n ],\n [\"path\", { d: \"m22 17.65-9.17 4.16a2 2 0 0 1-1.66 0L2 17.65\", key: \"dd6zsq\" }],\n [\"path\", { d: \"m22 12.65-9.17 4.16a2 2 0 0 1-1.66 0L2 12.65\", key: \"ep9fru\" }]\n]);\n\nexport { Layers as default };\n//# sourceMappingURL=layers.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst LayoutDashboard = createLucideIcon(\"LayoutDashboardIcon\", [\n [\"rect\", { width: \"7\", height: \"9\", x: \"3\", y: \"3\", rx: \"1\", key: \"10lvy0\" }],\n [\"rect\", { width: \"7\", height: \"5\", x: \"14\", y: \"3\", rx: \"1\", key: \"16une8\" }],\n [\"rect\", { width: \"7\", height: \"9\", x: \"14\", y: \"12\", rx: \"1\", key: \"1hutg5\" }],\n [\"rect\", { width: \"7\", height: \"5\", x: \"3\", y: \"16\", rx: \"1\", key: \"ldoo1y\" }]\n]);\n\nexport { LayoutDashboard as default };\n//# sourceMappingURL=layout-dashboard.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst LayoutGrid = createLucideIcon(\"LayoutGridIcon\", [\n [\"rect\", { width: \"7\", height: \"7\", x: \"3\", y: \"3\", rx: \"1\", key: \"1g98yp\" }],\n [\"rect\", { width: \"7\", height: \"7\", x: \"14\", y: \"3\", rx: \"1\", key: \"6d4xhi\" }],\n [\"rect\", { width: \"7\", height: \"7\", x: \"14\", y: \"14\", rx: \"1\", key: \"nxv5o0\" }],\n [\"rect\", { width: \"7\", height: \"7\", x: \"3\", y: \"14\", rx: \"1\", key: \"1bb6yr\" }]\n]);\n\nexport { LayoutGrid as default };\n//# sourceMappingURL=layout-grid.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst LifeBuoy = createLucideIcon(\"LifeBuoyIcon\", [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"10\", key: \"1mglay\" }],\n [\"path\", { d: \"m4.93 4.93 4.24 4.24\", key: \"1ymg45\" }],\n [\"path\", { d: \"m14.83 9.17 4.24-4.24\", key: \"1cb5xl\" }],\n [\"path\", { d: \"m14.83 14.83 4.24 4.24\", key: \"q42g0n\" }],\n [\"path\", { d: \"m9.17 14.83-4.24 4.24\", key: \"bqpfvv\" }],\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"4\", key: \"4exip2\" }]\n]);\n\nexport { LifeBuoy as default };\n//# sourceMappingURL=life-buoy.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Link = createLucideIcon(\"LinkIcon\", [\n [\"path\", { d: \"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\", key: \"1cjeqo\" }],\n [\"path\", { d: \"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\", key: \"19qd67\" }]\n]);\n\nexport { Link as default };\n//# sourceMappingURL=link.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst ListChecks = createLucideIcon(\"ListChecksIcon\", [\n [\"path\", { d: \"m3 17 2 2 4-4\", key: \"1jhpwq\" }],\n [\"path\", { d: \"m3 7 2 2 4-4\", key: \"1obspn\" }],\n [\"path\", { d: \"M13 6h8\", key: \"15sg57\" }],\n [\"path\", { d: \"M13 12h8\", key: \"h98zly\" }],\n [\"path\", { d: \"M13 18h8\", key: \"oe0vm4\" }]\n]);\n\nexport { ListChecks as default };\n//# sourceMappingURL=list-checks.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst List = createLucideIcon(\"ListIcon\", [\n [\"path\", { d: \"M3 12h.01\", key: \"nlz23k\" }],\n [\"path\", { d: \"M3 18h.01\", key: \"1tta3j\" }],\n [\"path\", { d: \"M3 6h.01\", key: \"1rqtza\" }],\n [\"path\", { d: \"M8 12h13\", key: \"1za7za\" }],\n [\"path\", { d: \"M8 18h13\", key: \"1lx6n3\" }],\n [\"path\", { d: \"M8 6h13\", key: \"ik3vkj\" }]\n]);\n\nexport { List as default };\n//# sourceMappingURL=list.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Lock = createLucideIcon(\"LockIcon\", [\n [\"rect\", { width: \"18\", height: \"11\", x: \"3\", y: \"11\", rx: \"2\", ry: \"2\", key: \"1w4ew1\" }],\n [\"path\", { d: \"M7 11V7a5 5 0 0 1 10 0v4\", key: \"fwvmzm\" }]\n]);\n\nexport { Lock as default };\n//# sourceMappingURL=lock.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst LogOut = createLucideIcon(\"LogOutIcon\", [\n [\"path\", { d: \"M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4\", key: \"1uf3rs\" }],\n [\"polyline\", { points: \"16 17 21 12 16 7\", key: \"1gabdz\" }],\n [\"line\", { x1: \"21\", x2: \"9\", y1: \"12\", y2: \"12\", key: \"1uyos4\" }]\n]);\n\nexport { LogOut as default };\n//# sourceMappingURL=log-out.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Mail = createLucideIcon(\"MailIcon\", [\n [\"rect\", { width: \"20\", height: \"16\", x: \"2\", y: \"4\", rx: \"2\", key: \"18n3k1\" }],\n [\"path\", { d: \"m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7\", key: \"1ocrg3\" }]\n]);\n\nexport { Mail as default };\n//# sourceMappingURL=mail.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst MapPin = createLucideIcon(\"MapPinIcon\", [\n [\n \"path\",\n {\n d: \"M20 10c0 4.993-5.539 10.193-7.399 11.799a1 1 0 0 1-1.202 0C9.539 20.193 4 14.993 4 10a8 8 0 0 1 16 0\",\n key: \"1r0f0z\"\n }\n ],\n [\"circle\", { cx: \"12\", cy: \"10\", r: \"3\", key: \"ilqhr7\" }]\n]);\n\nexport { MapPin as default };\n//# sourceMappingURL=map-pin.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Map = createLucideIcon(\"MapIcon\", [\n [\n \"path\",\n {\n d: \"M14.106 5.553a2 2 0 0 0 1.788 0l3.659-1.83A1 1 0 0 1 21 4.619v12.764a1 1 0 0 1-.553.894l-4.553 2.277a2 2 0 0 1-1.788 0l-4.212-2.106a2 2 0 0 0-1.788 0l-3.659 1.83A1 1 0 0 1 3 19.381V6.618a1 1 0 0 1 .553-.894l4.553-2.277a2 2 0 0 1 1.788 0z\",\n key: \"169xi5\"\n }\n ],\n [\"path\", { d: \"M15 5.764v15\", key: \"1pn4in\" }],\n [\"path\", { d: \"M9 3.236v15\", key: \"1uimfh\" }]\n]);\n\nexport { Map as default };\n//# sourceMappingURL=map.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst MessageSquare = createLucideIcon(\"MessageSquareIcon\", [\n [\"path\", { d: \"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\", key: \"1lielz\" }]\n]);\n\nexport { MessageSquare as default };\n//# sourceMappingURL=message-square.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Monitor = createLucideIcon(\"MonitorIcon\", [\n [\"rect\", { width: \"20\", height: \"14\", x: \"2\", y: \"3\", rx: \"2\", key: \"48i651\" }],\n [\"line\", { x1: \"8\", x2: \"16\", y1: \"21\", y2: \"21\", key: \"1svkeh\" }],\n [\"line\", { x1: \"12\", x2: \"12\", y1: \"17\", y2: \"21\", key: \"vw1qmm\" }]\n]);\n\nexport { Monitor as default };\n//# sourceMappingURL=monitor.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Moon = createLucideIcon(\"MoonIcon\", [\n [\"path\", { d: \"M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z\", key: \"a7tn18\" }]\n]);\n\nexport { Moon as default };\n//# sourceMappingURL=moon.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Package = createLucideIcon(\"PackageIcon\", [\n [\n \"path\",\n {\n d: \"M11 21.73a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73z\",\n key: \"1a0edw\"\n }\n ],\n [\"path\", { d: \"M12 22V12\", key: \"d0xqtd\" }],\n [\"path\", { d: \"m3.3 7 7.703 4.734a2 2 0 0 0 1.994 0L20.7 7\", key: \"yx3hmr\" }],\n [\"path\", { d: \"m7.5 4.27 9 5.15\", key: \"1c824w\" }]\n]);\n\nexport { Package as default };\n//# sourceMappingURL=package.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst PanelLeft = createLucideIcon(\"PanelLeftIcon\", [\n [\"rect\", { width: \"18\", height: \"18\", x: \"3\", y: \"3\", rx: \"2\", key: \"afitv7\" }],\n [\"path\", { d: \"M9 3v18\", key: \"fh3hqa\" }]\n]);\n\nexport { PanelLeft as default };\n//# sourceMappingURL=panel-left.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst PanelsTopLeft = createLucideIcon(\"PanelsTopLeftIcon\", [\n [\"rect\", { width: \"18\", height: \"18\", x: \"3\", y: \"3\", rx: \"2\", key: \"afitv7\" }],\n [\"path\", { d: \"M3 9h18\", key: \"1pudct\" }],\n [\"path\", { d: \"M9 21V9\", key: \"1oto5p\" }]\n]);\n\nexport { PanelsTopLeft as default };\n//# sourceMappingURL=panels-top-left.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Paperclip = createLucideIcon(\"PaperclipIcon\", [\n [\n \"path\",\n {\n d: \"m21.44 11.05-9.19 9.19a6 6 0 0 1-8.49-8.49l8.57-8.57A4 4 0 1 1 18 8.84l-8.59 8.57a2 2 0 0 1-2.83-2.83l8.49-8.48\",\n key: \"1u3ebp\"\n }\n ]\n]);\n\nexport { Paperclip as default };\n//# sourceMappingURL=paperclip.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Pencil = createLucideIcon(\"PencilIcon\", [\n [\n \"path\",\n {\n d: \"M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z\",\n key: \"1a8usu\"\n }\n ],\n [\"path\", { d: \"m15 5 4 4\", key: \"1mk7zo\" }]\n]);\n\nexport { Pencil as default };\n//# sourceMappingURL=pencil.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Plus = createLucideIcon(\"PlusIcon\", [\n [\"path\", { d: \"M5 12h14\", key: \"1ays0h\" }],\n [\"path\", { d: \"M12 5v14\", key: \"s699le\" }]\n]);\n\nexport { Plus as default };\n//# sourceMappingURL=plus.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst RefreshCw = createLucideIcon(\"RefreshCwIcon\", [\n [\"path\", { d: \"M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8\", key: \"v9h5vc\" }],\n [\"path\", { d: \"M21 3v5h-5\", key: \"1q7to0\" }],\n [\"path\", { d: \"M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16\", key: \"3uifl3\" }],\n [\"path\", { d: \"M8 16H3v5\", key: \"1cv678\" }]\n]);\n\nexport { RefreshCw as default };\n//# sourceMappingURL=refresh-cw.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst RotateCcw = createLucideIcon(\"RotateCcwIcon\", [\n [\"path\", { d: \"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8\", key: \"1357e3\" }],\n [\"path\", { d: \"M3 3v5h5\", key: \"1xhq8a\" }]\n]);\n\nexport { RotateCcw as default };\n//# sourceMappingURL=rotate-ccw.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Search = createLucideIcon(\"SearchIcon\", [\n [\"circle\", { cx: \"11\", cy: \"11\", r: \"8\", key: \"4ej97u\" }],\n [\"path\", { d: \"m21 21-4.3-4.3\", key: \"1qie3q\" }]\n]);\n\nexport { Search as default };\n//# sourceMappingURL=search.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Send = createLucideIcon(\"SendIcon\", [\n [\n \"path\",\n {\n d: \"M14.536 21.686a.5.5 0 0 0 .937-.024l6.5-19a.496.496 0 0 0-.635-.635l-19 6.5a.5.5 0 0 0-.024.937l7.93 3.18a2 2 0 0 1 1.112 1.11z\",\n key: \"1ffxy3\"\n }\n ],\n [\"path\", { d: \"m21.854 2.147-10.94 10.939\", key: \"12cjpa\" }]\n]);\n\nexport { Send as default };\n//# sourceMappingURL=send.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Server = createLucideIcon(\"ServerIcon\", [\n [\"rect\", { width: \"20\", height: \"8\", x: \"2\", y: \"2\", rx: \"2\", ry: \"2\", key: \"ngkwjq\" }],\n [\"rect\", { width: \"20\", height: \"8\", x: \"2\", y: \"14\", rx: \"2\", ry: \"2\", key: \"iecqi9\" }],\n [\"line\", { x1: \"6\", x2: \"6.01\", y1: \"6\", y2: \"6\", key: \"16zg32\" }],\n [\"line\", { x1: \"6\", x2: \"6.01\", y1: \"18\", y2: \"18\", key: \"nzw8ys\" }]\n]);\n\nexport { Server as default };\n//# sourceMappingURL=server.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Settings = createLucideIcon(\"SettingsIcon\", [\n [\n \"path\",\n {\n d: \"M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z\",\n key: \"1qme2f\"\n }\n ],\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"3\", key: \"1v7zrd\" }]\n]);\n\nexport { Settings as default };\n//# sourceMappingURL=settings.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Shield = createLucideIcon(\"ShieldIcon\", [\n [\n \"path\",\n {\n d: \"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z\",\n key: \"oel41y\"\n }\n ]\n]);\n\nexport { Shield as default };\n//# sourceMappingURL=shield.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst ShoppingBag = createLucideIcon(\"ShoppingBagIcon\", [\n [\"path\", { d: \"M6 2 3 6v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6l-3-4Z\", key: \"hou9p0\" }],\n [\"path\", { d: \"M3 6h18\", key: \"d0wm0j\" }],\n [\"path\", { d: \"M16 10a4 4 0 0 1-8 0\", key: \"1ltviw\" }]\n]);\n\nexport { ShoppingBag as default };\n//# sourceMappingURL=shopping-bag.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst ShoppingCart = createLucideIcon(\"ShoppingCartIcon\", [\n [\"circle\", { cx: \"8\", cy: \"21\", r: \"1\", key: \"jimo8o\" }],\n [\"circle\", { cx: \"19\", cy: \"21\", r: \"1\", key: \"13723u\" }],\n [\n \"path\",\n {\n d: \"M2.05 2.05h2l2.66 12.42a2 2 0 0 0 2 1.58h9.78a2 2 0 0 0 1.95-1.57l1.65-7.43H5.12\",\n key: \"9zh506\"\n }\n ]\n]);\n\nexport { ShoppingCart as default };\n//# sourceMappingURL=shopping-cart.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst SlidersVertical = createLucideIcon(\"SlidersVerticalIcon\", [\n [\"line\", { x1: \"4\", x2: \"4\", y1: \"21\", y2: \"14\", key: \"1p332r\" }],\n [\"line\", { x1: \"4\", x2: \"4\", y1: \"10\", y2: \"3\", key: \"gb41h5\" }],\n [\"line\", { x1: \"12\", x2: \"12\", y1: \"21\", y2: \"12\", key: \"hf2csr\" }],\n [\"line\", { x1: \"12\", x2: \"12\", y1: \"8\", y2: \"3\", key: \"1kfi7u\" }],\n [\"line\", { x1: \"20\", x2: \"20\", y1: \"21\", y2: \"16\", key: \"1lhrwl\" }],\n [\"line\", { x1: \"20\", x2: \"20\", y1: \"12\", y2: \"3\", key: \"16vvfq\" }],\n [\"line\", { x1: \"2\", x2: \"6\", y1: \"14\", y2: \"14\", key: \"1uebub\" }],\n [\"line\", { x1: \"10\", x2: \"14\", y1: \"8\", y2: \"8\", key: \"1yglbp\" }],\n [\"line\", { x1: \"18\", x2: \"22\", y1: \"16\", y2: \"16\", key: \"1jxqpz\" }]\n]);\n\nexport { SlidersVertical as default };\n//# sourceMappingURL=sliders-vertical.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst SquarePen = createLucideIcon(\"SquarePenIcon\", [\n [\"path\", { d: \"M12 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7\", key: \"1m0v6g\" }],\n [\n \"path\",\n {\n d: \"M18.375 2.625a1 1 0 0 1 3 3l-9.013 9.014a2 2 0 0 1-.853.505l-2.873.84a.5.5 0 0 1-.62-.62l.84-2.873a2 2 0 0 1 .506-.852z\",\n key: \"ohrbg2\"\n }\n ]\n]);\n\nexport { SquarePen as default };\n//# sourceMappingURL=square-pen.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Star = createLucideIcon(\"StarIcon\", [\n [\n \"path\",\n {\n d: \"M11.525 2.295a.53.53 0 0 1 .95 0l2.31 4.679a2.123 2.123 0 0 0 1.595 1.16l5.166.756a.53.53 0 0 1 .294.904l-3.736 3.638a2.123 2.123 0 0 0-.611 1.878l.882 5.14a.53.53 0 0 1-.771.56l-4.618-2.428a2.122 2.122 0 0 0-1.973 0L6.396 21.01a.53.53 0 0 1-.77-.56l.881-5.139a2.122 2.122 0 0 0-.611-1.879L2.16 9.795a.53.53 0 0 1 .294-.906l5.165-.755a2.122 2.122 0 0 0 1.597-1.16z\",\n key: \"r04s7s\"\n }\n ]\n]);\n\nexport { Star as default };\n//# sourceMappingURL=star.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Store = createLucideIcon(\"StoreIcon\", [\n [\"path\", { d: \"m2 7 4.41-4.41A2 2 0 0 1 7.83 2h8.34a2 2 0 0 1 1.42.59L22 7\", key: \"ztvudi\" }],\n [\"path\", { d: \"M4 12v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8\", key: \"1b2hhj\" }],\n [\"path\", { d: \"M15 22v-4a2 2 0 0 0-2-2h-2a2 2 0 0 0-2 2v4\", key: \"2ebpfo\" }],\n [\"path\", { d: \"M2 7h20\", key: \"1fcdvo\" }],\n [\n \"path\",\n {\n d: \"M22 7v3a2 2 0 0 1-2 2a2.7 2.7 0 0 1-1.59-.63.7.7 0 0 0-.82 0A2.7 2.7 0 0 1 16 12a2.7 2.7 0 0 1-1.59-.63.7.7 0 0 0-.82 0A2.7 2.7 0 0 1 12 12a2.7 2.7 0 0 1-1.59-.63.7.7 0 0 0-.82 0A2.7 2.7 0 0 1 8 12a2.7 2.7 0 0 1-1.59-.63.7.7 0 0 0-.82 0A2.7 2.7 0 0 1 4 12a2 2 0 0 1-2-2V7\",\n key: \"6c3vgh\"\n }\n ]\n]);\n\nexport { Store as default };\n//# sourceMappingURL=store.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Sun = createLucideIcon(\"SunIcon\", [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"4\", key: \"4exip2\" }],\n [\"path\", { d: \"M12 2v2\", key: \"tus03m\" }],\n [\"path\", { d: \"M12 20v2\", key: \"1lh1kg\" }],\n [\"path\", { d: \"m4.93 4.93 1.41 1.41\", key: \"149t6j\" }],\n [\"path\", { d: \"m17.66 17.66 1.41 1.41\", key: \"ptbguv\" }],\n [\"path\", { d: \"M2 12h2\", key: \"1t8f8n\" }],\n [\"path\", { d: \"M20 12h2\", key: \"1q8mjw\" }],\n [\"path\", { d: \"m6.34 17.66-1.41 1.41\", key: \"1m8zz5\" }],\n [\"path\", { d: \"m19.07 4.93-1.41 1.41\", key: \"1shlcs\" }]\n]);\n\nexport { Sun as default };\n//# sourceMappingURL=sun.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Tag = createLucideIcon(\"TagIcon\", [\n [\n \"path\",\n {\n d: \"M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z\",\n key: \"vktsd0\"\n }\n ],\n [\"circle\", { cx: \"7.5\", cy: \"7.5\", r: \".5\", fill: \"currentColor\", key: \"kqv944\" }]\n]);\n\nexport { Tag as default };\n//# sourceMappingURL=tag.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Tags = createLucideIcon(\"TagsIcon\", [\n [\"path\", { d: \"m15 5 6.3 6.3a2.4 2.4 0 0 1 0 3.4L17 19\", key: \"1cbfv1\" }],\n [\n \"path\",\n {\n d: \"M9.586 5.586A2 2 0 0 0 8.172 5H3a1 1 0 0 0-1 1v5.172a2 2 0 0 0 .586 1.414L8.29 18.29a2.426 2.426 0 0 0 3.42 0l3.58-3.58a2.426 2.426 0 0 0 0-3.42z\",\n key: \"135mg7\"\n }\n ],\n [\"circle\", { cx: \"6.5\", cy: \"9.5\", r: \".5\", fill: \"currentColor\", key: \"5pm5xn\" }]\n]);\n\nexport { Tags as default };\n//# sourceMappingURL=tags.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Terminal = createLucideIcon(\"TerminalIcon\", [\n [\"polyline\", { points: \"4 17 10 11 4 5\", key: \"akl6gq\" }],\n [\"line\", { x1: \"12\", x2: \"20\", y1: \"19\", y2: \"19\", key: \"q2wloq\" }]\n]);\n\nexport { Terminal as default };\n//# sourceMappingURL=terminal.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Trash2 = createLucideIcon(\"Trash2Icon\", [\n [\"path\", { d: \"M3 6h18\", key: \"d0wm0j\" }],\n [\"path\", { d: \"M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6\", key: \"4alrt4\" }],\n [\"path\", { d: \"M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2\", key: \"v07s0e\" }],\n [\"line\", { x1: \"10\", x2: \"10\", y1: \"11\", y2: \"17\", key: \"1uufr5\" }],\n [\"line\", { x1: \"14\", x2: \"14\", y1: \"11\", y2: \"17\", key: \"xtxkd\" }]\n]);\n\nexport { Trash2 as default };\n//# sourceMappingURL=trash-2.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst TrendingUp = createLucideIcon(\"TrendingUpIcon\", [\n [\"polyline\", { points: \"22 7 13.5 15.5 8.5 10.5 2 17\", key: \"126l90\" }],\n [\"polyline\", { points: \"16 7 22 7 22 13\", key: \"kwv8wd\" }]\n]);\n\nexport { TrendingUp as default };\n//# sourceMappingURL=trending-up.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst TriangleAlert = createLucideIcon(\"TriangleAlertIcon\", [\n [\n \"path\",\n {\n d: \"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3\",\n key: \"wmoenq\"\n }\n ],\n [\"path\", { d: \"M12 9v4\", key: \"juzpu7\" }],\n [\"path\", { d: \"M12 17h.01\", key: \"p32p05\" }]\n]);\n\nexport { TriangleAlert as default };\n//# sourceMappingURL=triangle-alert.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Upload = createLucideIcon(\"UploadIcon\", [\n [\"path\", { d: \"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\", key: \"ih7n3h\" }],\n [\"polyline\", { points: \"17 8 12 3 7 8\", key: \"t8dd8p\" }],\n [\"line\", { x1: \"12\", x2: \"12\", y1: \"3\", y2: \"15\", key: \"widbto\" }]\n]);\n\nexport { Upload as default };\n//# sourceMappingURL=upload.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst UserPlus = createLucideIcon(\"UserPlusIcon\", [\n [\"path\", { d: \"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2\", key: \"1yyitq\" }],\n [\"circle\", { cx: \"9\", cy: \"7\", r: \"4\", key: \"nufk8\" }],\n [\"line\", { x1: \"19\", x2: \"19\", y1: \"8\", y2: \"14\", key: \"1bvyxn\" }],\n [\"line\", { x1: \"22\", x2: \"16\", y1: \"11\", y2: \"11\", key: \"1shjgl\" }]\n]);\n\nexport { UserPlus as default };\n//# sourceMappingURL=user-plus.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst User = createLucideIcon(\"UserIcon\", [\n [\"path\", { d: \"M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2\", key: \"975kel\" }],\n [\"circle\", { cx: \"12\", cy: \"7\", r: \"4\", key: \"17ys0d\" }]\n]);\n\nexport { User as default };\n//# sourceMappingURL=user.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Users = createLucideIcon(\"UsersIcon\", [\n [\"path\", { d: \"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2\", key: \"1yyitq\" }],\n [\"circle\", { cx: \"9\", cy: \"7\", r: \"4\", key: \"nufk8\" }],\n [\"path\", { d: \"M22 21v-2a4 4 0 0 0-3-3.87\", key: \"kshegd\" }],\n [\"path\", { d: \"M16 3.13a4 4 0 0 1 0 7.75\", key: \"1da9ce\" }]\n]);\n\nexport { Users as default };\n//# sourceMappingURL=users.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst X = createLucideIcon(\"XIcon\", [\n [\"path\", { d: \"M18 6 6 18\", key: \"1bl5f8\" }],\n [\"path\", { d: \"m6 6 12 12\", key: \"d8bk6v\" }]\n]);\n\nexport { X as default };\n//# sourceMappingURL=x.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Zap = createLucideIcon(\"ZapIcon\", [\n [\n \"path\",\n {\n d: \"M4 14a1 1 0 0 1-.78-1.63l9.9-10.2a.5.5 0 0 1 .86.46l-1.92 6.02A1 1 0 0 0 13 10h7a1 1 0 0 1 .78 1.63l-9.9 10.2a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14z\",\n key: \"1xq2db\"\n }\n ]\n]);\n\nexport { Zap as default };\n//# sourceMappingURL=zap.js.map\n","/**\n * Глобальный registry AdminClient'а для Pinia stores.\n *\n * Stores не получают client через параметры — это сильно усложняет API\n * (`useAuthStore(client)` каждый раз). Вместо этого client регистрируется\n * один раз при bootstrap'е приложения через `setAdminClient()`, и stores\n * читают его через `getAdminClient()`.\n *\n * Это singleton-pattern — допустим в случае admin-SPA, потому что\n * client всегда один на весь жизненный цикл.\n */\n\nimport type { AdminClient } from '../api/client'\n\nlet _client: AdminClient | null = null\n\nexport function setAdminClient(client: AdminClient): void {\n _client = client\n}\n\nexport function getAdminClient(): AdminClient {\n if (_client === null) {\n throw new Error(\n '[admin] AdminClient is not registered. Call setAdminClient(...) before using stores.',\n )\n }\n return _client\n}\n\nexport function clearAdminClient(): void {\n _client = null\n}\n\nexport function hasAdminClient(): boolean {\n return _client !== null\n}\n","/**\n * Theme store: текущая тема + список доступных + persist через API.\n *\n * Side effect: применяет `<html data-theme=\"...\">` при изменении.\n * SPA рассчитывает на это для CSS-vars overrides.\n */\n\nimport { defineStore } from 'pinia'\nimport { computed, ref } from 'vue'\nimport { getAdminClient } from './registry'\nimport type { AdminBootstrap } from '../types/bootstrap'\n\nexport const useThemeStore = defineStore('admin-theme', () => {\n const current = ref<string>('light')\n const available = ref<string[]>(['light', 'dark'])\n\n const isDark = computed(() => current.value === 'dark')\n\n function hydrate(bootstrap: AdminBootstrap): void {\n current.value = bootstrap.theme\n available.value = bootstrap.availableThemes\n applyHtmlAttr(bootstrap.theme)\n }\n\n /**\n * Локальное переключение без round-trip'а. Используется когда нужно\n * мгновенно применить тему до получения ответа от сервера.\n */\n function applyLocal(theme: string): void {\n if (!available.value.includes(theme)) {\n throw new Error(`Theme \"${theme}\" is not available`)\n }\n current.value = theme\n applyHtmlAttr(theme)\n }\n\n /**\n * POST /system/setTheme — persist в user.theme + cookie.\n * Применяет тему к DOM немедленно (optimistic update).\n */\n async function setTheme(theme: string): Promise<void> {\n if (!available.value.includes(theme)) {\n throw new Error(`Theme \"${theme}\" is not available`)\n }\n\n const previous = current.value\n applyLocal(theme)\n\n try {\n const client = getAdminClient()\n await client.post('/system/setTheme', { theme })\n } catch (err) {\n // Откатываем optimistic update.\n applyLocal(previous)\n throw err\n }\n }\n\n function applyHtmlAttr(theme: string): void {\n if (typeof document !== 'undefined' && document.documentElement) {\n document.documentElement.setAttribute('data-theme', theme)\n }\n }\n\n return {\n current,\n available,\n isDark,\n hydrate,\n applyLocal,\n setTheme,\n }\n})\n","<script setup lang=\"ts\">\n/**\n * Toggle между light/dark поверх @dskripchenko/ui. Использует topbar\n * icon-button-стиль (.admin-topbar__icon-btn) для визуальной согласованности\n * с остальными widget'ами в баре.\n */\nimport { computed } from 'vue'\nimport { Moon, Sun } from 'lucide-vue-next'\nimport { UidIcon } from '@dskripchenko/ui'\nimport { useThemeStore } from '../../../stores/theme'\n\nconst theme = useThemeStore()\n\nconst isDark = computed(() => theme.current === 'dark')\nconst icon = computed(() => (isDark.value ? Sun : Moon))\nconst iconName = computed(() => (isDark.value ? 'sun' : 'moon'))\nconst ariaLabel = computed(() =>\n isDark.value ? 'Переключить на светлую тему' : 'Переключить на тёмную тему',\n)\n\nasync function toggle(): Promise<void> {\n const next = isDark.value ? 'light' : 'dark'\n await theme.setTheme(next)\n}\n</script>\n\n<template>\n <button\n type=\"button\"\n class=\"admin-topbar__icon-btn\"\n :aria-label=\"ariaLabel\"\n :aria-pressed=\"isDark\"\n @click=\"toggle\"\n >\n <UidIcon :icon=\"icon\" :size=\"18\" :data-icon=\"iconName\" />\n </button>\n</template>\n","/**\n * Locale store: текущая локаль + persist + sync с AdminClient.\n *\n * Side effects при смене:\n * - `<html lang=\"...\">` обновляется\n * - AdminClient.setLocale() — все следующие запросы получат правильный\n * X-Admin-Locale header\n * - POST /system/setLocale → persist в user.locale + cookie\n */\n\nimport { defineStore } from 'pinia'\nimport { ref } from 'vue'\nimport { getAdminClient } from './registry'\nimport type { AdminBootstrap } from '../types/bootstrap'\n\nexport const useLocaleStore = defineStore('admin-locale', () => {\n const current = ref<string>('ru')\n const available = ref<string[]>(['ru', 'en'])\n\n function hydrate(bootstrap: AdminBootstrap): void {\n current.value = bootstrap.locale\n available.value = bootstrap.availableLocales\n applySideEffects(bootstrap.locale)\n }\n\n function applyLocal(locale: string): void {\n if (!available.value.includes(locale)) {\n throw new Error(`Locale \"${locale}\" is not available`)\n }\n current.value = locale\n applySideEffects(locale)\n }\n\n async function setLocale(locale: string): Promise<void> {\n if (!available.value.includes(locale)) {\n throw new Error(`Locale \"${locale}\" is not available`)\n }\n\n const previous = current.value\n applyLocal(locale)\n\n try {\n const client = getAdminClient()\n await client.post('/system/setLocale', { locale })\n } catch (err) {\n applyLocal(previous)\n throw err\n }\n }\n\n function applySideEffects(locale: string): void {\n if (typeof document !== 'undefined' && document.documentElement) {\n document.documentElement.setAttribute('lang', locale)\n }\n // Try-catch потому что в test-окружении registry может быть пуст.\n try {\n getAdminClient().setLocale(locale)\n } catch {\n // ignore — клиент ещё не зарегистрирован\n }\n }\n\n return {\n current,\n available,\n hydrate,\n applyLocal,\n setLocale,\n }\n})\n","<script setup lang=\"ts\">\n/**\n * Переключение локали через UidMenu. В topbar показываем компактно\n * (icon + uppercase-код), под ним выпадает список доступных локалей.\n */\nimport { Globe } from 'lucide-vue-next'\nimport { UidIcon, UidMenu, UidMenuItem } from '@dskripchenko/ui'\nimport { useLocaleStore } from '../../../stores/locale'\n\nconst locale = useLocaleStore()\n\nasync function pick(loc: string): Promise<void> {\n if (loc === locale.current) return\n await locale.setLocale(loc)\n}\n</script>\n\n<template>\n <UidMenu>\n <template #trigger>\n <button\n type=\"button\"\n class=\"admin-topbar__icon-btn\"\n style=\"width: auto; padding: 0 8px; gap: 4px; font-size: 12px;\"\n aria-label=\"Сменить локаль\"\n >\n <UidIcon :icon=\"Globe\" :size=\"14\" data-icon=\"globe\" />\n <span>{{ (locale.current ?? '').toUpperCase() }}</span>\n </button>\n </template>\n\n <UidMenuItem\n v-for=\"loc in locale.available\"\n :key=\"loc\"\n @click=\"pick(loc)\"\n >\n {{ loc.toUpperCase() }}\n </UidMenuItem>\n </UidMenu>\n</template>\n","/**\n * Notifications store: список + unread count + read/delete actions.\n *\n * Bell-badge polling реализуется на уровне UI через setInterval +\n * вызов loadUnread() — store сам не polling'ит, чтобы не дублировать\n * SetInterval'ы между tab'ами.\n */\n\nimport { defineStore } from 'pinia'\nimport { computed, ref } from 'vue'\nimport { getAdminClient } from './registry'\nimport type { AdminBootstrap } from '../types/bootstrap'\n\nexport interface NotificationItem {\n id: string\n type: string\n data: Record<string, unknown>\n read_at: string | null\n created_at: string | null\n}\n\nexport type NotificationFilter = 'all' | 'unread' | 'read'\n\nexport const useNotificationsStore = defineStore('admin-notifications', () => {\n const items = ref<NotificationItem[]>([])\n const unreadCount = ref(0)\n const loading = ref(false)\n const lastFilter = ref<NotificationFilter>('all')\n const meta = ref<{ page: number; per_page: number; total: number; last_page: number } | null>(null)\n /**\n * Slide-in drawer state. Bell-кнопка в топбаре toggle'ит этот флаг,\n * NotificationsDrawer (mounted в AdminApp root) реагирует на него.\n */\n const isOpen = ref<boolean>(false)\n\n const hasUnread = computed(() => unreadCount.value > 0)\n\n function openDrawer(): void {\n isOpen.value = true\n }\n function closeDrawer(): void {\n isOpen.value = false\n }\n function toggleDrawer(): void {\n isOpen.value = !isOpen.value\n }\n\n function hydrate(bootstrap: AdminBootstrap): void {\n unreadCount.value = bootstrap.unread_notifications_count\n }\n\n async function load(filter: NotificationFilter = 'all', page = 1): Promise<void> {\n loading.value = true\n try {\n const client = getAdminClient()\n const result = await client.get<{\n data: NotificationItem[]\n meta: { page: number; per_page: number; total: number; last_page: number; unread_count: number }\n }>(`/notifications/list?type=${filter}&page=${page}`)\n items.value = result.data\n unreadCount.value = result.meta.unread_count\n meta.value = {\n page: result.meta.page,\n per_page: result.meta.per_page,\n total: result.meta.total,\n last_page: result.meta.last_page,\n }\n lastFilter.value = filter\n } finally {\n loading.value = false\n }\n }\n\n /**\n * Лёгкий polling-endpoint — только count + последние 20.\n * Для bell-badge.\n */\n async function loadUnread(): Promise<void> {\n const client = getAdminClient()\n const result = await client.get<{ count: number; data: NotificationItem[] }>(\n '/notifications/unread',\n )\n unreadCount.value = result.count\n // Не подменяем items если в данный момент open'нут другой filter.\n if (lastFilter.value === 'unread') {\n items.value = result.data\n }\n }\n\n async function markAsRead(id: string): Promise<void> {\n const client = getAdminClient()\n await client.post('/notifications/markAsRead', { id })\n // Optimistic update в локальном state.\n const item = items.value.find((n) => n.id === id)\n if (item && item.read_at === null) {\n item.read_at = new Date().toISOString()\n unreadCount.value = Math.max(0, unreadCount.value - 1)\n }\n }\n\n async function markAllAsRead(): Promise<void> {\n const client = getAdminClient()\n await client.post('/notifications/markAllAsRead')\n const now = new Date().toISOString()\n for (const item of items.value) {\n if (item.read_at === null) item.read_at = now\n }\n unreadCount.value = 0\n }\n\n async function destroy(id: string): Promise<void> {\n const client = getAdminClient()\n await client.post('/notifications/destroy', { id })\n const index = items.value.findIndex((n) => n.id === id)\n if (index !== -1) {\n const wasUnread = items.value[index].read_at === null\n items.value.splice(index, 1)\n if (wasUnread) {\n unreadCount.value = Math.max(0, unreadCount.value - 1)\n }\n }\n }\n\n return {\n items,\n unreadCount,\n loading,\n meta,\n lastFilter,\n isOpen,\n hasUnread,\n hydrate,\n load,\n loadUnread,\n markAsRead,\n markAllAsRead,\n destroy,\n openDrawer,\n closeDrawer,\n toggleDrawer,\n }\n})\n","<script setup lang=\"ts\">\n/**\n * Bell с unread-badge — toggle'ит slide-in drawer NotificationsDrawer.\n * Сам drawer mounted один раз в AdminApp.vue (Teleport to body).\n */\nimport { computed } from 'vue'\nimport { Bell } from 'lucide-vue-next'\nimport { UidIcon } from '@dskripchenko/ui'\nimport { useNotificationsStore } from '../../../stores/notifications'\n\nconst notifications = useNotificationsStore()\n\nconst display = computed(() => {\n const n = notifications.unreadCount\n if (n <= 0) return null\n return n > 99 ? '99+' : String(n)\n})\n\nfunction onClick(): void {\n notifications.toggleDrawer()\n}\n</script>\n\n<template>\n <button\n type=\"button\"\n class=\"admin-topbar__icon-btn\"\n aria-label=\"Уведомления\"\n aria-haspopup=\"dialog\"\n :aria-expanded=\"notifications.isOpen\"\n @click=\"onClick\"\n >\n <UidIcon :icon=\"Bell\" :size=\"18\" data-icon=\"bell\" />\n <span\n v-if=\"display !== null\"\n class=\"admin-topbar__bell-badge\"\n :title=\"`Непрочитанных: ${notifications.unreadCount}`\"\n >\n {{ display }}\n </span>\n </button>\n</template>\n","/**\n * Кастомные Error-классы для admin API.\n *\n * Все API-ошибки бросаются как ApiError или его подклассы. Потребители\n * могут делать `instanceof ValidationError` для специфичной обработки.\n */\n\nimport type { ErrorEnvelope } from './envelope'\n\nexport class ApiError extends Error {\n public readonly status: number\n public readonly errorKey: string\n public readonly payload: ErrorEnvelope['payload']\n\n constructor(status: number, payload: ErrorEnvelope['payload']) {\n super(payload.message ?? `API error ${status}`)\n this.name = 'ApiError'\n this.status = status\n this.errorKey = payload.errorKey ?? 'unknown'\n this.payload = payload\n }\n}\n\nexport class UnauthenticatedError extends ApiError {\n constructor(payload: ErrorEnvelope['payload']) {\n super(401, payload)\n this.name = 'UnauthenticatedError'\n }\n}\n\nexport class ForbiddenError extends ApiError {\n constructor(payload: ErrorEnvelope['payload']) {\n super(403, payload)\n this.name = 'ForbiddenError'\n }\n}\n\nexport class NotFoundError extends ApiError {\n constructor(payload: ErrorEnvelope['payload']) {\n super(404, payload)\n this.name = 'NotFoundError'\n }\n}\n\nexport class ValidationError extends ApiError {\n /** Field-keyed map of error messages. */\n public readonly fields: Record<string, string[]>\n\n constructor(payload: ErrorEnvelope['payload']) {\n super(422, payload)\n this.name = 'ValidationError'\n this.fields = payload.messages ?? {}\n }\n\n /** Первое сообщение из field'а — удобно для toast. */\n firstFieldMessage(): string | null {\n for (const messages of Object.values(this.fields)) {\n if (messages.length > 0) {\n return messages[0]\n }\n }\n return null\n }\n}\n\n/**\n * Network-failure (не дошли до сервера). Отдельный класс чтобы UI мог\n * показать «Нет соединения» вместо «500 Server Error».\n */\nexport class NetworkError extends Error {\n constructor(message = 'Network error') {\n super(message)\n this.name = 'NetworkError'\n }\n}\n\n/**\n * Превращает HTTP-status + envelope в правильный подкласс ApiError.\n */\nexport function toApiError(status: number, payload: ErrorEnvelope['payload']): ApiError {\n switch (status) {\n case 401: return new UnauthenticatedError(payload)\n case 403: return new ForbiddenError(payload)\n case 404: return new NotFoundError(payload)\n case 422: return new ValidationError(payload)\n default: return new ApiError(status, payload)\n }\n}\n","/**\n * Auth store: текущий user, permissions, login/logout/2FA flow.\n *\n * Wildcard в permissions:\n * - `*` — полный доступ ко всему.\n * - `admin.users.*` — доступ ко всем admin.users.{view,create,update,delete}.\n *\n * 2FA flow:\n * 1. login() с верными creds + 2FA включена → success: false +\n * errorKey: 'two_factor_required' + challenge_token. State переходит в\n * `pendingChallenge`.\n * 2. UI показывает 2FA-форму. twoFactorChallenge(code) или\n * twoFactorRecovery(recovery_code) → success login flow.\n */\n\nimport { defineStore } from 'pinia'\nimport { computed, ref } from 'vue'\nimport { getAdminClient } from './registry'\nimport { ApiError } from '../api/errors'\nimport type { AdminUser, AdminBootstrap } from '../types/bootstrap'\n\nexport interface PendingChallenge {\n challengeToken: string\n remember: boolean\n}\n\nexport interface LoginPayload {\n email: string\n password: string\n remember?: boolean\n}\n\nexport const useAuthStore = defineStore('admin-auth', () => {\n const user = ref<AdminUser | null>(null)\n const permissions = ref<string[]>([])\n const pendingChallenge = ref<PendingChallenge | null>(null)\n\n const isAuthenticated = computed(() => user.value !== null)\n const isChallengePending = computed(() => pendingChallenge.value !== null)\n\n /** Заполнить store из bootstrap-payload'а (стартовая инициализация). */\n function hydrate(bootstrap: AdminBootstrap): void {\n user.value = bootstrap.user\n permissions.value = bootstrap.permissions\n }\n\n /**\n * Проверить permission. Поддерживает wildcards:\n * - `*` — даёт доступ всем.\n * - `admin.users.*` — даёт доступ ко всем admin.users.X.\n */\n function hasPermission(key: string): boolean {\n if (permissions.value.includes('*')) return true\n if (permissions.value.includes(key)) return true\n return permissions.value.some((permission) => {\n if (!permission.endsWith('.*')) return false\n const prefix = permission.slice(0, -1) // 'admin.users.'\n return key.startsWith(prefix)\n })\n }\n\n function hasAnyPermission(keys: string[]): boolean {\n return keys.some(hasPermission)\n }\n\n function hasAllPermissions(keys: string[]): boolean {\n return keys.every(hasPermission)\n }\n\n /**\n * POST /auth/login. При 2FA-required envelope success:false +\n * errorKey:'two_factor_required' конвертируется interceptor'ом в ApiError;\n * мы ловим его, переходим в challenge-mode и возвращаем 'two_factor_required'.\n * На полный success — заполняем user и возвращаем 'authenticated'.\n * На реальную ошибку — throw'ит ApiError выше.\n */\n async function login(payload: LoginPayload): Promise<'authenticated' | 'two_factor_required'> {\n const client = getAdminClient()\n try {\n const result = await client.post<{ user?: AdminUser; permissions?: string[] }>(\n '/auth/login',\n payload,\n )\n if (result?.user) {\n user.value = result.user\n }\n if (Array.isArray(result?.permissions)) {\n permissions.value = result.permissions\n }\n pendingChallenge.value = null\n return 'authenticated'\n } catch (err) {\n if (err instanceof ApiError && err.errorKey === 'two_factor_required') {\n const challengeToken = (err.payload as Record<string, unknown>).challenge_token\n pendingChallenge.value = {\n challengeToken: typeof challengeToken === 'string' ? challengeToken : '',\n remember: payload.remember ?? false,\n }\n return 'two_factor_required'\n }\n throw err\n }\n }\n\n /** POST /auth/twoFactorChallenge. Завершает login. */\n async function twoFactorChallenge(code: string): Promise<void> {\n if (pendingChallenge.value === null) {\n throw new Error('No pending 2FA challenge')\n }\n const client = getAdminClient()\n const result = await client.post<{ user: AdminUser }>('/auth/twoFactorChallenge', {\n challenge_token: pendingChallenge.value.challengeToken,\n code,\n })\n user.value = result.user\n pendingChallenge.value = null\n }\n\n /** POST /auth/twoFactorRecovery. Использует recovery-код вместо TOTP. */\n async function twoFactorRecovery(recoveryCode: string): Promise<{ remaining: number }> {\n if (pendingChallenge.value === null) {\n throw new Error('No pending 2FA challenge')\n }\n const client = getAdminClient()\n const result = await client.post<{\n user: AdminUser\n recovery_codes_remaining: number\n }>('/auth/twoFactorRecovery', {\n challenge_token: pendingChallenge.value.challengeToken,\n recovery_code: recoveryCode,\n })\n user.value = result.user\n pendingChallenge.value = null\n return { remaining: result.recovery_codes_remaining }\n }\n\n /** Сбросить pending challenge — для возврата на login-форму. */\n function cancelChallenge(): void {\n pendingChallenge.value = null\n }\n\n /** POST /auth/logout. Чистит store. */\n async function logout(): Promise<void> {\n const client = getAdminClient()\n try {\n await client.post('/auth/logout')\n } finally {\n user.value = null\n permissions.value = []\n pendingChallenge.value = null\n }\n }\n\n return {\n // state\n user,\n permissions,\n pendingChallenge,\n // getters\n isAuthenticated,\n isChallengePending,\n // actions\n hydrate,\n hasPermission,\n hasAnyPermission,\n hasAllPermissions,\n login,\n twoFactorChallenge,\n twoFactorRecovery,\n cancelChallenge,\n logout,\n }\n})\n","<script setup lang=\"ts\">\n/**\n * UserMenu с avatar + dropdown через UidMenu из @dskripchenko/ui.\n * В trigger'е — UidAvatar (с инициалами либо src, размер sm).\n */\nimport { UidAvatar, UidMenu, UidMenuItem, UidMenuSeparator } from '@dskripchenko/ui'\nimport { useRouter } from 'vue-router'\nimport { useAuthStore } from '../../../stores/auth'\n\nconst auth = useAuthStore()\nconst router = useRouter()\n\nasync function logout(): Promise<void> {\n try {\n await auth.logout()\n } finally {\n await router.push({ name: 'admin.login' })\n }\n}\n\nfunction goProfile(): void {\n void router.push({ name: 'admin.profile' })\n}\n</script>\n\n<template>\n <UidMenu>\n <template #trigger>\n <button\n type=\"button\"\n class=\"admin-topbar__icon-btn admin-user-menu__trigger\"\n aria-label=\"Меню пользователя\"\n aria-haspopup=\"menu\"\n style=\"width: auto; padding: 0 4px; gap: 8px;\"\n >\n <UidAvatar\n :src=\"auth.user?.avatar ?? undefined\"\n :name=\"auth.user?.name ?? '?'\"\n :alt=\"auth.user?.name ?? 'User'\"\n size=\"sm\"\n />\n </button>\n </template>\n\n <UidMenuItem @click=\"goProfile\">Профиль</UidMenuItem>\n <UidMenuSeparator />\n <UidMenuItem variant=\"danger\" @click=\"logout\">Выйти</UidMenuItem>\n </UidMenu>\n</template>\n","<script setup lang=\"ts\">\n/**\n * Admin top bar поверх UID-токенов. Структура из docs/design_handoff_laravel_admin/\n * screens-shell.jsx (Topbar): collapse-toggle / breadcrumbs / spacer /\n * search-pill / bell / theme / locale / avatar.\n *\n * Slots:\n * - actions — host может вставить дополнительные actions перед widget'ами\n * - search — кастомизация ⌘K command-palette pill (по умолчанию — статичный\n * placeholder; host сверху поднимет UidCommand или свой)\n * - breadcrumbs — переопределить хлебные крошки\n */\nimport { computed } from 'vue'\nimport { PanelLeft, Search } from 'lucide-vue-next'\nimport { UidIcon } from '@dskripchenko/ui'\nimport ThemeToggle from './widgets/ThemeToggle.vue'\nimport LocaleSwitcher from './widgets/LocaleSwitcher.vue'\nimport NotificationBell from './widgets/NotificationBell.vue'\nimport UserMenu from './widgets/UserMenu.vue'\n\ninterface Crumb {\n label: string\n to?: string | Record<string, unknown> | null\n}\n\ninterface Props {\n /** Хлебные крошки. Последний элемент — текущая страница (без to). */\n breadcrumbs?: Crumb[]\n /** Показывать кнопку collapse сайдбара (только в shell-layout'е). */\n showCollapseToggle?: boolean\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n breadcrumbs: () => [],\n showCollapseToggle: true,\n})\n\nconst emit = defineEmits<{\n 'toggle-sidebar': []\n}>()\n\nconst lastIdx = computed(() => props.breadcrumbs.length - 1)\n</script>\n\n<template>\n <header class=\"admin-topbar\">\n <button\n v-if=\"showCollapseToggle\"\n type=\"button\"\n class=\"admin-topbar__icon-btn\"\n aria-label=\"Свернуть меню\"\n @click=\"emit('toggle-sidebar')\"\n >\n <UidIcon :icon=\"PanelLeft\" :size=\"18\" data-icon=\"panel-left\" />\n </button>\n\n <div class=\"admin-topbar__breadcrumbs\">\n <slot name=\"breadcrumbs\">\n <template v-for=\"(crumb, idx) in breadcrumbs\" :key=\"idx\">\n <span v-if=\"idx > 0\" class=\"sep\">›</span>\n <component\n :is=\"crumb.to ? 'a' : 'span'\"\n :href=\"typeof crumb.to === 'string' ? crumb.to : undefined\"\n :class=\"idx === lastIdx ? 'cur' : ''\"\n >\n {{ crumb.label }}\n </component>\n </template>\n </slot>\n </div>\n\n <div class=\"admin-topbar__spacer\" />\n\n <slot name=\"search\">\n <div class=\"admin-topbar__search\" role=\"button\" tabindex=\"0\">\n <UidIcon :icon=\"Search\" :size=\"14\" data-icon=\"search\" />\n <span>Поиск везде…</span>\n <kbd>⌘K</kbd>\n </div>\n </slot>\n\n <slot name=\"actions\" />\n <NotificationBell />\n <ThemeToggle />\n <LocaleSwitcher />\n <UserMenu />\n </header>\n</template>\n","/**\n * Menu store: дерево пунктов сайдбара.\n *\n * Источник — /system/menu (backend строит из ResourceRegistry/ScreenRegistry/\n * Settings + plugin-вкладов). Фронт фильтрует по permission'ам залогиненного\n * пользователя через auth-store.\n */\n\nimport { defineStore } from 'pinia'\nimport { computed, ref } from 'vue'\nimport { getAdminClient } from './registry'\nimport { useAuthStore } from './auth'\n\nexport interface MenuItem {\n /** Уникальный идентификатор. */\n key: string\n /** Текст пункта. */\n label: string\n /** Имя icon'а (опционально — host-проект сам резолвит icon-set). */\n icon?: string | null\n /** URL (внутренний router-target) либо null для группы. */\n url?: string | null\n /** Имя router-route (если задано — приоритет над url). */\n routeName?: string | null\n /** Бейдж справа (число unread, ярлык вроде \"new\"). */\n badge?: string | number | null\n /** Группа (header в sidebar). */\n group?: string | null\n /** Сортировочный вес. */\n order?: number\n /** Permission-keys; если заданы — пункт виден только при hasAnyPermission. */\n permissions?: string[]\n /** Вложенные пункты. */\n children?: MenuItem[]\n}\n\nexport interface MenuGroup {\n /** Заголовок группы (null = пункты без группы). */\n group: string | null\n items: MenuItem[]\n}\n\ninterface MenuResponse {\n items: MenuItem[]\n}\n\nexport const useMenuStore = defineStore('admin-menu', () => {\n const items = ref<MenuItem[]>([])\n const loading = ref(false)\n const error = ref<Error | null>(null)\n const isLoaded = ref(false)\n\n /**\n * Видимые пункты — отфильтрованные по permission'ам через auth-store.\n * Поддерживает wildcards (`*`, `admin.users.*`) через auth.hasAnyPermission.\n * Items без permissions считаются открытыми всем.\n */\n const visibleItems = computed<MenuItem[]>(() => {\n const auth = useAuthStore()\n const filter = (it: MenuItem): MenuItem | null => {\n if (Array.isArray(it.permissions) && it.permissions.length > 0) {\n if (!auth.hasAnyPermission(it.permissions)) return null\n }\n const filteredChildren = (it.children ?? [])\n .map(filter)\n .filter((c): c is MenuItem => c !== null)\n return { ...it, children: filteredChildren }\n }\n return items.value.map(filter).filter((i): i is MenuItem => i !== null)\n })\n\n /**\n * Группированный список — для рендера в sidebar по секциям.\n * Сортировка: order по возрастанию, затем label по алфавиту.\n */\n const groupedItems = computed<MenuGroup[]>(() => {\n const groups = new Map<string | null, MenuItem[]>()\n for (const item of visibleItems.value) {\n const groupKey = item.group ?? null\n if (!groups.has(groupKey)) groups.set(groupKey, [])\n groups.get(groupKey)!.push(item)\n }\n const result: MenuGroup[] = []\n for (const [group, list] of groups) {\n list.sort((a, b) => {\n const orderDiff = (a.order ?? 0) - (b.order ?? 0)\n if (orderDiff !== 0) return orderDiff\n return a.label.localeCompare(b.label)\n })\n result.push({ group, items: list })\n }\n return result\n })\n\n /** Загрузить меню с backend'а. Кэшируется до reset()/force=true. */\n async function load(force = false): Promise<MenuItem[]> {\n if (isLoaded.value && !force) return items.value\n loading.value = true\n error.value = null\n try {\n const client = getAdminClient()\n const response = await client.get<MenuResponse>('/system/menu')\n items.value = Array.isArray(response.items) ? response.items : []\n isLoaded.value = true\n return items.value\n } catch (err) {\n error.value = err instanceof Error ? err : new Error(String(err))\n throw err\n } finally {\n loading.value = false\n }\n }\n\n /** Установить items напрямую (например, host-проект построил из manifest'а). */\n function setItems(next: MenuItem[]): void {\n items.value = next\n isLoaded.value = true\n error.value = null\n }\n\n function reset(): void {\n items.value = []\n isLoaded.value = false\n error.value = null\n loading.value = false\n }\n\n return {\n items,\n loading,\n error,\n isLoaded,\n visibleItems,\n groupedItems,\n load,\n setItems,\n reset,\n }\n})\n","<script setup lang=\"ts\">\n/**\n * LAdmin brand mark — \"Terminal Block\".\n * Vue-порт docs/design_handoff_laravel_admin/brand/Logo.tsx.\n *\n * Палитра — zinc-900 фон + teal-400 \">_\" с мигающим курсором.\n * Все внутренние размеры скейлятся от prop `size`, так что mark\n * остаётся чётким при любом px (28 для sidebar, 40 на login и т.д.).\n *\n * При prefers-reduced-motion курсор не анимируется (см. CSS ниже).\n */\nimport { computed } from 'vue'\n\ninterface Props {\n /** Сторона квадрата в px. */\n size?: number\n /** Мигающий курсор. */\n animated?: boolean\n /** color = бренд-палитра, mono = single-tone через currentColor. */\n variant?: 'color' | 'mono'\n title?: string\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n size: 28,\n animated: true,\n variant: 'color',\n title: 'LAdmin',\n})\n\nconst TEAL = '#2dd4bf'\nconst INK = '#18181b'\n\nconst radius = computed(() => Math.round(props.size * 0.25))\nconst fontSize = computed(() => Math.round(props.size * 0.42))\nconst padX = computed(() => Math.round(props.size * 0.18))\nconst cursorW = computed(() => Math.max(2, Math.round(props.size * 0.18)))\nconst cursorH = computed(() => Math.round(props.size * 0.3))\nconst cursorGap = computed(() => Math.max(1, Math.round(props.size * 0.04)))\n\nconst bg = computed(() => (props.variant === 'mono' ? 'currentColor' : INK))\nconst fg = computed(() =>\n props.variant === 'mono' ? 'var(--ladmin-logo-fg, #fff)' : TEAL,\n)\n\nconst wrapStyle = computed(() => ({\n width: `${props.size}px`,\n height: `${props.size}px`,\n padding: `0 ${padX.value}px`,\n borderRadius: `${radius.value}px`,\n background: bg.value,\n color: fg.value,\n fontSize: `${fontSize.value}px`,\n}))\n\nconst cursorStyle = computed(() => ({\n width: `${cursorW.value}px`,\n height: `${cursorH.value}px`,\n marginLeft: `${cursorGap.value}px`,\n background: fg.value,\n}))\n</script>\n\n<template>\n <span\n role=\"img\"\n :aria-label=\"title\"\n class=\"ladmin-logo\"\n :class=\"{ 'ladmin-logo--animated': animated }\"\n :style=\"wrapStyle\"\n >\n <span aria-hidden=\"true\">&gt;_</span>\n <span aria-hidden=\"true\" class=\"ladmin-logo__cursor\" :style=\"cursorStyle\" />\n </span>\n</template>\n\n<style>\n.ladmin-logo {\n display: inline-flex;\n align-items: center;\n justify-content: flex-start;\n font-family: ui-monospace, 'IBM Plex Mono', 'Fira Code', Menlo, monospace;\n font-weight: 700;\n letter-spacing: -0.02em;\n line-height: 1;\n flex: none;\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06);\n}\n.ladmin-logo--animated .ladmin-logo__cursor {\n animation: ladmin-cursor 1.1s steps(1, end) infinite;\n}\n@keyframes ladmin-cursor {\n 50% { opacity: 0; }\n}\n@media (prefers-reduced-motion: reduce) {\n .ladmin-logo--animated .ladmin-logo__cursor { animation: none; }\n}\n</style>\n","/**\n * Резолвер kebab-имени lucide-иконки → Vue-компонент.\n *\n * MenuItem.icon приходит из backend'а строкой (например 'file-text', 'users').\n * Чтобы не тащить весь lucide-vue-next в bundle — держим whitelist\n * популярных имён. Host может расширить через registerIcon(name, comp).\n *\n * Не найденное имя возвращает fallback (Box) — sidebar item никогда не\n * рендерится без иконки.\n */\nimport type { Component } from 'vue'\nimport {\n Activity,\n AlertCircle,\n Archive,\n BarChart3,\n Bell,\n Bookmark,\n Box,\n Briefcase,\n Calendar,\n CheckCircle,\n Clock,\n Code,\n Cog,\n Command,\n Database,\n Download,\n FileText,\n FileClock,\n Files,\n Flag,\n FolderOpen,\n Folder,\n Gauge,\n Globe,\n Grid,\n HardDrive,\n Hash,\n Heart,\n HelpCircle,\n History,\n Home,\n Image,\n Images,\n Inbox,\n Info,\n Key,\n Layers,\n LayoutDashboard,\n Layout,\n LifeBuoy,\n LineChart,\n Link,\n List,\n ListChecks,\n Lock,\n LogOut,\n Mail,\n MapPin,\n Map,\n MessageSquare,\n Monitor,\n Package,\n Paperclip,\n PieChart,\n RefreshCw,\n Search,\n Send,\n Server,\n Settings,\n Shield,\n ShoppingBag,\n ShoppingCart,\n Sliders,\n Star,\n Store,\n Tag,\n Tags,\n Terminal,\n TrendingUp,\n Upload,\n User,\n UserCircle,\n Users,\n XCircle,\n Zap,\n} from 'lucide-vue-next'\n\nconst REGISTRY: Record<string, Component> = {\n 'activity': Activity,\n 'alert-circle': AlertCircle,\n 'archive': Archive,\n 'bar-chart': BarChart3,\n 'bar-chart-3': BarChart3,\n 'bell': Bell,\n 'bookmark': Bookmark,\n 'box': Box,\n 'briefcase': Briefcase,\n 'calendar': Calendar,\n 'check-circle': CheckCircle,\n 'clock': Clock,\n 'code': Code,\n 'cog': Cog,\n 'command': Command,\n 'database': Database,\n 'download': Download,\n 'file': FileText,\n 'file-text': FileText,\n 'file-clock': FileClock,\n 'files': Files,\n 'flag': Flag,\n 'folder': Folder,\n 'folder-open': FolderOpen,\n 'gauge': Gauge,\n 'globe': Globe,\n 'grid': Grid,\n 'hard-drive': HardDrive,\n 'hash': Hash,\n 'health-check': CheckCircle,\n 'heart': Heart,\n 'help-circle': HelpCircle,\n 'history': History,\n 'home': Home,\n 'image': Image,\n 'images': Images,\n 'inbox': Inbox,\n 'info': Info,\n 'key': Key,\n 'layers': Layers,\n 'layout': Layout,\n 'layout-dashboard': LayoutDashboard,\n 'life-buoy': LifeBuoy,\n 'line-chart': LineChart,\n 'link': Link,\n 'list': List,\n 'list-checks': ListChecks,\n 'lock': Lock,\n 'log-out': LogOut,\n 'mail': Mail,\n 'map': Map,\n 'map-pin': MapPin,\n 'media': Image,\n 'message-square': MessageSquare,\n 'monitor': Monitor,\n 'notifications': Bell,\n 'package': Package,\n 'paperclip': Paperclip,\n 'pie-chart': PieChart,\n 'refresh-cw': RefreshCw,\n 'reports': BarChart3,\n 'roles': Shield,\n 'search': Search,\n 'send': Send,\n 'server': Server,\n 'settings': Settings,\n 'shield': Shield,\n 'shopping-bag': ShoppingBag,\n 'shopping-cart': ShoppingCart,\n 'sliders': Sliders,\n 'star': Star,\n 'store': Store,\n 'tag': Tag,\n 'tags': Tags,\n 'terminal': Terminal,\n 'trending-up': TrendingUp,\n 'upload': Upload,\n 'user': User,\n 'user-circle': UserCircle,\n 'users': Users,\n 'x-circle': XCircle,\n 'zap': Zap,\n}\n\n/**\n * Найти иконку по имени. Не найдена — null (вызывающий код решает рендерить\n * fallback или ничего).\n */\nexport function resolveIcon(name: string | null | undefined): Component | null {\n if (!name) return null\n return REGISTRY[name] ?? null\n}\n\n/** Зарегистрировать дополнительную иконку (host-проект). */\nexport function registerIcon(name: string, component: Component): void {\n REGISTRY[name] = component\n}\n","<script setup lang=\"ts\">\n/**\n * Sidebar admin-каркаса поверх UidSidebar/UidSidebarGroup/UidSidebarItem.\n *\n * Источник данных — useMenuStore (groupedItems, отфильтрованные по permission'ам\n * через auth.hasAnyPermission). UidSidebarItem поддерживает вложенный icon-slot\n * + active + badge — маппим прямо из MenuItem.\n *\n * Brand-row сверху + опциональный tenant-block + footer с версией/docs —\n * по эталону docs/design_handoff_laravel_admin/screens-shell.jsx (Sidebar).\n */\nimport { computed, h, type Component } from 'vue'\nimport { useRoute } from 'vue-router'\nimport { Box } from 'lucide-vue-next'\nimport { UidIcon, UidSidebar, UidSidebarGroup, UidSidebarItem } from '@dskripchenko/ui'\nimport { useMenuStore, type MenuItem } from '../../stores/menu'\nimport BrandLogo from './BrandLogo.vue'\nimport { resolveIcon } from './iconRegistry'\n\ninterface Props {\n collapsed?: boolean\n /** Заголовок бренда. */\n brandName?: string\n /**\n * Custom mark (если задан — рендерится вместо BrandLogo). Полезно\n * host-проекту с собственным логотипом.\n */\n brandMark?: string | null\n /** Named-route для click'а по brand-row. */\n homeRouteName?: string\n /** Тенант / workspace — опционально показывается под брендом. */\n tenant?: { label: string; name: string } | null\n /** Версия + ссылка на docs в footer'е. */\n version?: string | null\n docsUrl?: string | null\n}\n\nwithDefaults(defineProps<Props>(), {\n collapsed: false,\n brandName: 'Laravel Admin',\n brandMark: null,\n homeRouteName: 'admin.home',\n tenant: null,\n version: null,\n docsUrl: null,\n})\n\nconst menu = useMenuStore()\nconst route = useRoute()\n\nconst groups = computed(() => menu.groupedItems)\n\nfunction isActive(item: MenuItem): boolean {\n if (item.routeName && route.name === item.routeName) return true\n if (item.url && route.path === item.url) return true\n return false\n}\n\n/**\n * UidSidebarItem ожидает icon-slot. MenuItem.icon — строка (имя lucide-иконки\n * в kebab-case). Резолвим через iconRegistry; если имя не зарегистрировано —\n * fallback на Box, чтобы каждый item всегда имел иконку (иначе collapsed\n * mode превращается в бесполезные пустые квадраты).\n *\n * Host-проект может расширить registry через registerIcon(name, comp).\n */\nfunction iconSlot(name?: string | null): Component {\n const resolved = resolveIcon(name) ?? Box\n return () => h(UidIcon, { icon: resolved, size: 16 })\n}\n\n/** UidSidebarItem.to принимает string | object; routeName маппим через route-object. */\nfunction itemTarget(item: MenuItem): string | Record<string, unknown> | undefined {\n // URL приоритетнее routeName — vue-router бросает \"no match for {name}\" если\n // route'а ещё нет (dynamic-routes добавляются async после manifest.load).\n // URL-based navigation матчится в любой момент через path.\n if (item.url) return item.url\n if (item.routeName) return { name: item.routeName }\n return undefined\n}\n</script>\n\n<template>\n <UidSidebar :collapsed=\"collapsed\">\n <template #header>\n <router-link\n :to=\"{ name: homeRouteName }\"\n class=\"admin-sidebar-brand\"\n :title=\"collapsed ? brandName : undefined\"\n :aria-label=\"brandName\"\n >\n <div v-if=\"brandMark\" class=\"admin-sidebar-brand__mark\">{{ brandMark }}</div>\n <BrandLogo v-else :size=\"28\" />\n <div v-if=\"!collapsed\" class=\"admin-sidebar-brand__name\">{{ brandName }}</div>\n </router-link>\n <div v-if=\"tenant && !collapsed\" class=\"admin-sidebar-tenant\">\n <span>{{ tenant.label }}</span>\n <b>{{ tenant.name }}</b>\n </div>\n </template>\n\n <template #nav>\n <UidSidebarGroup\n v-for=\"(grp, idx) in groups\"\n :key=\"`grp-${idx}`\"\n :title=\"grp.group ?? undefined\"\n >\n <UidSidebarItem\n v-for=\"item in grp.items\"\n :key=\"item.key\"\n :to=\"itemTarget(item)\"\n :active=\"isActive(item)\"\n :badge=\"item.badge ?? undefined\"\n :title=\"collapsed ? item.label : undefined\"\n >\n <template #icon>\n <component :is=\"iconSlot(item.icon)\" />\n </template>\n {{ item.label }}\n </UidSidebarItem>\n </UidSidebarGroup>\n </template>\n\n <template #footer>\n <div class=\"admin-sidebar-foot\">\n <span class=\"admin-sidebar-foot__text\" :title=\"version ?? 'Laravel Admin'\">\n <template v-if=\"!collapsed\">{{ version ?? 'Laravel Admin' }}</template>\n <template v-else>·</template>\n </span>\n <a\n v-if=\"docsUrl && !collapsed\"\n :href=\"docsUrl\"\n class=\"admin-sidebar-foot__text admin-sidebar-foot__link\"\n >\n Docs\n </a>\n </div>\n </template>\n </UidSidebar>\n</template>\n\n<style>\n/*\n * Sidebar header выровнен по AdminTopBar (height: 56px + 1px border).\n * Padding у uid-pattern-sidebar__header обнулён — brand занимает ровно\n * одну строку шапки. Border-bottom UI-kit'а оставляем — он совпадает\n * по Y с border-bottom топбара, образуя единую горизонталь над nav\n * и контентной частью.\n */\n.uid-pattern-sidebar__header:has(.admin-sidebar-brand) {\n padding: 0;\n}\n.admin-sidebar-brand {\n display: flex;\n align-items: center;\n gap: 10px;\n height: 56px;\n padding: 0 16px;\n text-decoration: none;\n color: inherit;\n transition: background var(--uid-duration-fast, 120ms) var(--uid-ease-out, ease);\n}\n.admin-sidebar-brand:hover {\n background: var(--uid-color-surface-hover, rgba(0, 0, 0, 0.04));\n}\n.admin-sidebar-brand:focus-visible {\n outline: 2px solid var(--uid-color-focus-ring, var(--uid-accent));\n outline-offset: -2px;\n}\n.admin-sidebar-brand__mark {\n width: 28px;\n height: 28px;\n border-radius: 7px;\n flex: none;\n background: var(--uid-text-primary);\n color: var(--uid-surface-raised);\n display: grid;\n place-items: center;\n font-family: var(--uid-font-family-display);\n font-weight: var(--uid-font-weight-bold);\n font-size: 14px;\n letter-spacing: -0.02em;\n}\n.admin-sidebar-brand__name {\n font-family: var(--uid-font-family-display);\n font-size: 14px;\n font-weight: var(--uid-font-weight-semibold);\n letter-spacing: -0.01em;\n white-space: nowrap;\n overflow: hidden;\n color: var(--uid-text-primary);\n}\n.admin-sidebar-tenant {\n margin: 8px;\n display: flex;\n align-items: center;\n gap: 8px;\n height: 32px;\n padding: 0 8px;\n border: 1px solid var(--uid-border-subtle);\n border-radius: var(--uid-radius-md);\n font-size: var(--uid-font-size-xs);\n color: var(--uid-text-secondary);\n background: var(--uid-surface-base);\n}\n.admin-sidebar-tenant b { color: var(--uid-text-primary); font-weight: 500; }\n.admin-sidebar-foot {\n /*\n * Высота строго через --admin-foot-height — совпадает с .admin-main-footer\n * (см. AdminShell.vue), чтобы border-top sidebar foot и border-top main\n * footer проходили по одной Y и давали единую горизонталь под экраном.\n */\n height: var(--admin-foot-height, 32px);\n padding: 0 16px;\n border-top: 1px solid var(--uid-border-subtle);\n display: flex;\n align-items: center;\n justify-content: space-between;\n font-size: 11px;\n color: var(--uid-text-tertiary);\n}\n.admin-sidebar-foot__link { cursor: pointer; }\n.admin-sidebar-foot__link:hover { color: var(--uid-text-primary); }\n\n.admin-sidebar__icon {\n width: 16px;\n height: 16px;\n display: inline-block;\n flex: none;\n color: currentColor;\n}\n</style>\n","<script setup lang=\"ts\">\n/**\n * Корневой layout admin-панели поверх UidSidebarLayout из @dskripchenko/ui.\n *\n * Slots:\n * - sidebar — обычно AdminSidebar (default)\n * - header — AdminTopBar (default)\n * - default — main-area (host рендерит <RouterView/>)\n *\n * v-model — boolean флаг сворачивания сайдбара (240→56 px, transition в uid).\n *\n * Impersonation: prop `impersonation` показывает 32-px amber бейдж над shell'ом\n * с кнопкой выхода — стиль из docs/design_handoff_laravel_admin/app.css:159\n * (.imp-banner). На <html> ставим data-impersonating='true' чтобы корректно\n * сместить sticky-элементы вниз.\n */\nimport { computed, onBeforeUnmount, ref, watch } from 'vue'\nimport { UidSidebarLayout } from '@dskripchenko/ui'\nimport AdminTopBar from './AdminTopBar.vue'\nimport AdminSidebar from './AdminSidebar.vue'\n\ninterface ImpersonationData {\n /** Имя того, в кого вошли. */\n asName: string\n}\n\ninterface Props {\n /**\n * v-model:collapsed — состояние сворачивания. Опционально: если host\n * не передаёт, AdminShell использует internal ref'ом, чтобы collapse\n * toggle работал out-of-the-box.\n */\n collapsed?: boolean\n /** Если задано — показывает amber-banner и сдвигает контент. */\n impersonation?: ImpersonationData | null\n}\nconst props = withDefaults(defineProps<Props>(), {\n collapsed: undefined,\n impersonation: null,\n})\n\nconst emit = defineEmits<{\n 'update:collapsed': [value: boolean]\n 'exit-impersonation': []\n}>()\n\n// Internal fallback state — используется когда host не передал v-model.\nconst internalCollapsed = ref<boolean>(false)\nconst isExternallyControlled = computed<boolean>(() => props.collapsed !== undefined)\nconst collapsed = computed<boolean>(\n () => (isExternallyControlled.value ? (props.collapsed as boolean) : internalCollapsed.value),\n)\n\nfunction onCollapseChange(value: boolean): void {\n if (!isExternallyControlled.value) internalCollapsed.value = value\n emit('update:collapsed', value)\n}\n\nfunction exitImpersonation(): void {\n emit('exit-impersonation')\n}\n\n// Маркер на <html> — для shell-classes которые делают paddding-top + sticky-offset.\nconst HTML_ATTR = 'data-admin-impersonating'\n\nwatch(\n () => props.impersonation,\n (val) => {\n if (typeof document === 'undefined') return\n if (val !== null) document.documentElement.setAttribute(HTML_ATTR, 'true')\n else document.documentElement.removeAttribute(HTML_ATTR)\n },\n { immediate: true },\n)\n\nonBeforeUnmount(() => {\n if (typeof document !== 'undefined') {\n document.documentElement.removeAttribute(HTML_ATTR)\n }\n})\n</script>\n\n<template>\n <div class=\"admin-shell-root\">\n <div v-if=\"impersonation\" class=\"admin-impersonation-banner\" role=\"status\">\n <span>\n Вы вошли как <b>{{ impersonation.asName }}</b> · режим имперсонации\n </span>\n <button\n type=\"button\"\n class=\"admin-impersonation-banner__exit\"\n @click=\"exitImpersonation\"\n >\n Выйти из режима\n </button>\n </div>\n <UidSidebarLayout\n :model-value=\"collapsed\"\n class=\"admin-shell\"\n @update:model-value=\"onCollapseChange\"\n >\n <template #sidebar>\n <slot name=\"sidebar\">\n <AdminSidebar :collapsed=\"collapsed\" />\n </slot>\n </template>\n <template #header>\n <slot name=\"topbar\">\n <AdminTopBar @toggle-sidebar=\"onCollapseChange(!collapsed)\" />\n </slot>\n </template>\n <slot />\n <template #footer>\n <slot name=\"footer\">\n <!--\n Default footer-bar: горизонталь снизу контентной части, совпадает\n по Y с footer'ом sidebar'а — общая высота через --admin-foot-height.\n Host может переопределить полностью через slot=footer.\n -->\n <div class=\"admin-main-footer\" />\n </slot>\n </template>\n </UidSidebarLayout>\n </div>\n</template>\n\n<style>\n.admin-shell-root[data-admin-impersonating='true'] {\n /* Sidebar/topbar sticky уже учтут `--admin-page-pad` и offset через CSS-классы. */\n padding-top: 32px;\n}\n:root[data-admin-impersonating='true'] {\n scroll-padding-top: 32px;\n}\n\n/*\n * Full-viewport layout: sidebar и main каждый имеют own scroll контейнер.\n * Window сам не прокручивается (overflow:hidden на корне), вся прокрутка\n * локализована внутри:\n * - sidebar __nav (свой scroll в списке пунктов когда их больше высоты)\n * - main-content (правая контентная часть)\n *\n * Топбар внутри main всегда виден (flex none / position:sticky top:0).\n *\n * Все правила скоупированы в `.admin-shell` чтобы не задеть UidSidebarLayout\n * в других контекстах (storybook UI-kit'а, тесты).\n */\n.admin-shell.uid-layout-sidebar {\n height: 100vh;\n min-height: 0;\n max-height: 100vh;\n overflow: hidden;\n}\n.admin-shell .uid-layout-sidebar__sidebar {\n height: 100vh;\n}\n.admin-shell .uid-pattern-sidebar {\n height: 100%;\n display: flex;\n flex-direction: column;\n}\n.admin-shell .uid-pattern-sidebar__nav {\n flex: 1 1 0;\n min-height: 0;\n overflow-y: auto;\n overscroll-behavior: contain;\n}\n.admin-shell .uid-pattern-sidebar__footer {\n flex: none;\n}\n.admin-shell .uid-layout-sidebar__main {\n height: 100vh;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n min-width: 0;\n}\n.admin-shell .uid-layout-sidebar__main-header {\n flex: none;\n}\n.admin-shell .uid-layout-sidebar__main-content {\n flex: 1 1 0;\n min-height: 0;\n overflow-y: auto;\n overscroll-behavior: contain;\n}\n\n/* impersonation banner добавляет 32px над shell — корректируем высоту. */\n.admin-shell-root[data-admin-impersonating='true'] .admin-shell.uid-layout-sidebar,\n.admin-shell-root[data-admin-impersonating='true'] .admin-shell .uid-layout-sidebar__sidebar,\n.admin-shell-root[data-admin-impersonating='true'] .admin-shell .uid-layout-sidebar__main {\n height: calc(100vh - 32px);\n max-height: calc(100vh - 32px);\n}\n\n/*\n * Main-footer — пустая горизонтальная полоса под content-area. Высоту\n * держит --admin-foot-height (см. styles/admin.css), такую же как у\n * sidebar footer'а — тогда обе нижние линии (border-top main + border-top\n * sidebar) проходят по одной Y, образуя единую горизонталь через весь экран.\n */\n.admin-main-footer {\n height: var(--admin-foot-height, 32px);\n border-top: 1px solid var(--uid-border-subtle);\n background: var(--uid-surface-base);\n flex: none;\n}\n</style>\n","/**\n * useNavigationStore — глобальный pending-counter для top-loading-bar.\n *\n * При router.beforeEach (старт навигации) — вызываем `start()`.\n * При router.afterEach + resource-page завершила data-fetch — вызываем `end()`.\n *\n * Counter (а не bool) защищает от race condition'ов: если несколько\n * параллельных fetch'ей, bar остаётся видимым пока хоть один pending.\n */\n\nimport { defineStore } from 'pinia'\nimport { computed, ref } from 'vue'\n\nexport const useNavigationStore = defineStore('admin-navigation', () => {\n const pending = ref<number>(0)\n const isLoading = computed<boolean>(() => pending.value > 0)\n\n function start(): void {\n pending.value += 1\n }\n\n function end(): void {\n if (pending.value > 0) pending.value -= 1\n }\n\n /** Сбросить counter (на случай зависшего pending в dev). */\n function reset(): void {\n pending.value = 0\n }\n\n return { pending, isLoading, start, end, reset }\n})\n","<script setup lang=\"ts\">\n/**\n * Top loading bar (как у YouTube/GitHub/Vercel).\n *\n * Реактивно отображает useNavigationStore.isLoading. Indeterminate-anim\n * (CSS keyframes) — slide bar слева направо в бесконечном цикле пока\n * pending > 0.\n *\n * Hide-delay 120ms: если pending быстро спадает к 0, bar успевает\n * мигнуть в полный размер вместо instant-cutoff.\n */\nimport { computed, ref, watch } from 'vue'\nimport { useNavigationStore } from '../stores/navigation'\n\nconst nav = useNavigationStore()\n\n// Soft-hide: bar остаётся 120ms после end() для плавности.\nconst visible = ref<boolean>(false)\nlet hideTimer: ReturnType<typeof setTimeout> | null = null\n\nwatch(\n () => nav.isLoading,\n (loading) => {\n if (loading) {\n if (hideTimer !== null) {\n clearTimeout(hideTimer)\n hideTimer = null\n }\n visible.value = true\n } else {\n hideTimer = setTimeout(() => {\n visible.value = false\n hideTimer = null\n }, 120)\n }\n },\n { immediate: true },\n)\n\nconst cls = computed(() => ({\n 'admin-loading-bar': true,\n 'admin-loading-bar--visible': visible.value,\n}))\n</script>\n\n<template>\n <div :class=\"cls\" role=\"progressbar\" aria-busy=\"true\" />\n</template>\n\n<style>\n.admin-loading-bar {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n height: 2px;\n z-index: var(--uid-z-toast, 9999);\n pointer-events: none;\n opacity: 0;\n transition: opacity 120ms ease-out;\n background: transparent;\n}\n\n.admin-loading-bar--visible {\n opacity: 1;\n}\n\n.admin-loading-bar--visible::before {\n content: '';\n position: absolute;\n inset: 0;\n background: var(--uid-accent, var(--uid-color-primary, #14b8a6));\n transform-origin: 0 50%;\n animation: admin-loading-bar-slide 1.4s cubic-bezier(0.4, 0, 0.2, 1) infinite;\n}\n\n@keyframes admin-loading-bar-slide {\n 0% {\n transform: translateX(-100%) scaleX(0.4);\n }\n 50% {\n transform: translateX(0%) scaleX(0.7);\n }\n 100% {\n transform: translateX(100%) scaleX(0.4);\n }\n}\n\n/* Reduced-motion: статичный bar 60% width. */\n@media (prefers-reduced-motion: reduce) {\n .admin-loading-bar--visible::before {\n animation: none;\n width: 60%;\n transform: none;\n }\n}\n</style>\n","<script setup lang=\"ts\">\n/**\n * NotificationsDrawer — slide-in справа панель с уведомлениями.\n *\n * Структура по docs/design_handoff_laravel_admin (Notifications):\n * Header — title + unread badge + \"Прочитать все\" + close\n * Tabs — Все (count) | Непрочитанные (count) | Прочитанные\n * List — items с иконкой, title, time, description, unread-dot\n * Backdrop — закрывает по клику\n *\n * Открывается через notificationsStore.toggleDrawer() из NotificationBell\n * в топбаре. Drawer mounted один раз в AdminApp.vue, стейт открытости —\n * в pinia store (см. stores/notifications.ts).\n */\nimport { computed, onUnmounted, watch } from 'vue'\nimport {\n AlertTriangle,\n Check,\n CheckCircle,\n MessageSquare,\n Trash2,\n UserPlus,\n X,\n type LucideIcon,\n} from 'lucide-vue-next'\nimport { UidIcon } from '@dskripchenko/ui'\nimport {\n useNotificationsStore,\n type NotificationFilter,\n type NotificationItem,\n} from '../../stores/notifications'\n\nconst notifications = useNotificationsStore()\n\nconst isOpen = computed<boolean>(() => notifications.isOpen)\n\nconst tabs: Array<{ key: NotificationFilter; label: string }> = [\n { key: 'all', label: 'Все' },\n { key: 'unread', label: 'Непрочитанные' },\n { key: 'read', label: 'Прочитанные' },\n]\n\nasync function selectTab(key: NotificationFilter): Promise<void> {\n if (notifications.lastFilter === key) return\n await notifications.load(key, 1).catch(() => undefined)\n}\n\nasync function onMarkAll(): Promise<void> {\n await notifications.markAllAsRead().catch(() => undefined)\n}\n\nasync function onItemClick(item: NotificationItem): Promise<void> {\n if (item.read_at === null) {\n await notifications.markAsRead(item.id).catch(() => undefined)\n }\n // Если у уведомления есть ссылка в data — открываем; иначе остаёмся.\n const url = item.data.url\n if (typeof url === 'string' && url.length > 0) {\n if (url.startsWith('http://') || url.startsWith('https://')) {\n window.open(url, '_blank', 'noopener')\n } else {\n // SPA-навигация — закроем drawer и оставим решение router'у через href.\n notifications.closeDrawer()\n window.location.href = url\n }\n }\n}\n\nasync function onDelete(item: NotificationItem, e: MouseEvent): Promise<void> {\n e.stopPropagation()\n await notifications.destroy(item.id).catch(() => undefined)\n}\n\nfunction close(): void {\n notifications.closeDrawer()\n}\n\n/**\n * Иконка по типу уведомления. Backend laravel-notifications использует FQCN\n * в `type` ('App\\\\Notifications\\\\ImportFinished' и т.п.) — пробуем находить\n * по подстроке. Default — bell.\n */\nfunction iconFor(item: NotificationItem): LucideIcon {\n const t = item.type.toLowerCase()\n if (t.includes('import') || t.includes('finished') || t.includes('success')) return CheckCircle\n if (t.includes('comment') || t.includes('message') || t.includes('mention')) return MessageSquare\n if (t.includes('user') || t.includes('member') || t.includes('role')) return UserPlus\n if (t.includes('warning') || t.includes('schedule')) return AlertTriangle\n if (t.includes('delete') || t.includes('failed') || t.includes('error')) return Trash2\n return CheckCircle\n}\n\nfunction variantFor(item: NotificationItem): 'success' | 'info' | 'warning' | 'danger' | 'neutral' {\n const t = item.type.toLowerCase()\n if (t.includes('import') || t.includes('success') || t.includes('finished')) return 'success'\n if (t.includes('warning') || t.includes('schedule')) return 'warning'\n if (t.includes('delete') || t.includes('failed') || t.includes('error')) return 'danger'\n if (t.includes('comment') || t.includes('message')) return 'info'\n return 'neutral'\n}\n\nfunction relativeTime(iso: string | null): string {\n if (!iso) return ''\n const ts = new Date(iso).getTime()\n if (Number.isNaN(ts)) return ''\n const diff = (Date.now() - ts) / 1000\n if (diff < 60) return `${Math.max(1, Math.floor(diff))} сек назад`\n if (diff < 3600) return `${Math.floor(diff / 60)} мин назад`\n if (diff < 86_400) return `${Math.floor(diff / 3600)} ч назад`\n if (diff < 86_400 * 2) return 'вчера'\n if (diff < 86_400 * 7) return `${Math.floor(diff / 86_400)} д назад`\n return new Date(iso).toLocaleDateString('ru-RU')\n}\n\ninterface ItemView {\n title: string\n description: string\n}\nfunction viewOf(item: NotificationItem): ItemView {\n // Backend кладёт payload в `data`; поддерживаем стандартные ключи\n // `title`/`message`/`description` + fallback на data.text.\n const d = item.data\n const title =\n typeof d.title === 'string' ? d.title : typeof d.subject === 'string' ? d.subject : 'Уведомление'\n const description =\n typeof d.description === 'string'\n ? d.description\n : typeof d.message === 'string'\n ? d.message\n : typeof d.text === 'string'\n ? d.text\n : ''\n return { title, description }\n}\n\nconst tabCounts = computed<Record<NotificationFilter, number>>(() => {\n const meta = notifications.meta\n const total = meta?.total ?? notifications.items.length\n const unread = notifications.unreadCount\n const read = Math.max(0, total - unread)\n return { all: total, unread, read }\n})\n\n// Загружаем при первом открытии. И каждый раз — чтобы свежие данные.\nwatch(isOpen, async (open) => {\n if (open) {\n await notifications.load(notifications.lastFilter, 1).catch(() => undefined)\n document.addEventListener('keydown', onKey)\n } else {\n document.removeEventListener('keydown', onKey)\n }\n})\n\nfunction onKey(e: KeyboardEvent): void {\n if (e.key === 'Escape') close()\n}\n\nonUnmounted(() => {\n document.removeEventListener('keydown', onKey)\n})\n</script>\n\n<template>\n <Teleport to=\"body\">\n <Transition name=\"admin-notif-drawer\">\n <div\n v-if=\"isOpen\"\n class=\"admin-notif-drawer\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"admin-notif-drawer-title\"\n >\n <div class=\"admin-notif-drawer__backdrop\" @click=\"close\" />\n <aside class=\"admin-notif-drawer__panel\">\n <header class=\"admin-notif-drawer__hd\">\n <h2 id=\"admin-notif-drawer-title\" class=\"admin-notif-drawer__title\">\n Уведомления\n <span\n v-if=\"notifications.unreadCount > 0\"\n class=\"admin-notif-drawer__unread-badge\"\n >{{ notifications.unreadCount }}</span>\n </h2>\n <div class=\"admin-notif-drawer__hd-actions\">\n <button\n v-if=\"notifications.unreadCount > 0\"\n type=\"button\"\n class=\"admin-notif-drawer__mark-all\"\n @click=\"onMarkAll\"\n >\n <UidIcon :icon=\"Check\" :size=\"14\" />\n Прочитать все\n </button>\n <button\n type=\"button\"\n class=\"admin-notif-drawer__close\"\n aria-label=\"Закрыть\"\n @click=\"close\"\n >\n <UidIcon :icon=\"X\" :size=\"16\" />\n </button>\n </div>\n </header>\n\n <nav class=\"admin-notif-drawer__tabs\" role=\"tablist\">\n <button\n v-for=\"tab in tabs\"\n :key=\"tab.key\"\n type=\"button\"\n role=\"tab\"\n :class=\"[\n 'admin-notif-drawer__tab',\n {\n 'admin-notif-drawer__tab--active': notifications.lastFilter === tab.key,\n },\n ]\"\n :aria-selected=\"notifications.lastFilter === tab.key\"\n @click=\"selectTab(tab.key)\"\n >\n {{ tab.label }}\n <span class=\"admin-notif-drawer__tab-count\">{{ tabCounts[tab.key] }}</span>\n </button>\n </nav>\n\n <div class=\"admin-notif-drawer__body\">\n <div\n v-if=\"notifications.loading && notifications.items.length === 0\"\n class=\"admin-notif-drawer__empty\"\n >\n Загрузка…\n </div>\n <div\n v-else-if=\"notifications.items.length === 0\"\n class=\"admin-notif-drawer__empty\"\n >\n Нет уведомлений\n </div>\n <ol v-else class=\"admin-notif-drawer__list\">\n <li\n v-for=\"item in notifications.items\"\n :key=\"item.id\"\n :class=\"[\n 'admin-notif-drawer__item',\n { 'admin-notif-drawer__item--unread': item.read_at === null },\n ]\"\n @click=\"onItemClick(item)\"\n >\n <span\n class=\"admin-notif-drawer__icon\"\n :data-variant=\"variantFor(item)\"\n aria-hidden=\"true\"\n >\n <UidIcon :icon=\"iconFor(item)\" :size=\"14\" />\n </span>\n <div class=\"admin-notif-drawer__content\">\n <div class=\"admin-notif-drawer__row\">\n <span class=\"admin-notif-drawer__item-title\">{{ viewOf(item).title }}</span>\n <span class=\"admin-notif-drawer__item-time\">\n {{ relativeTime(item.created_at) }}\n </span>\n </div>\n <div\n v-if=\"viewOf(item).description\"\n class=\"admin-notif-drawer__item-description\"\n >\n {{ viewOf(item).description }}\n </div>\n </div>\n <span\n v-if=\"item.read_at === null\"\n class=\"admin-notif-drawer__unread-dot\"\n aria-hidden=\"true\"\n />\n <button\n type=\"button\"\n class=\"admin-notif-drawer__item-delete\"\n aria-label=\"Удалить\"\n @click.stop=\"onDelete(item, $event)\"\n >\n <UidIcon :icon=\"X\" :size=\"12\" />\n </button>\n </li>\n </ol>\n </div>\n </aside>\n </div>\n </Transition>\n </Teleport>\n</template>\n\n<style>\n.admin-notif-drawer {\n position: fixed;\n inset: 0;\n z-index: var(--uid-z-drawer, 400);\n pointer-events: none;\n}\n.admin-notif-drawer__backdrop {\n position: absolute;\n inset: 0;\n /*\n * Полупрозрачный затеняющий слой над основным интерфейсом. Не используем\n * --uid-color-overlay — в @dskripchenko/ui это opaque surface для popover'ов\n * (white в light / dark-grey в dark), и backdrop становится непрозрачным,\n * закрывая контент полностью. Берём жёсткий rgba(0,0,0,0.4) — стандартный\n * dim для модальных слоёв.\n */\n background: rgba(0, 0, 0, 0.4);\n pointer-events: auto;\n}\n.admin-notif-drawer__panel {\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n width: min(480px, 100%);\n display: flex;\n flex-direction: column;\n background: var(--uid-surface-raised);\n border-left: 1px solid var(--uid-border-subtle);\n box-shadow: var(--uid-shadow-lg);\n pointer-events: auto;\n}\n\n/* Header */\n.admin-notif-drawer__hd {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--uid-space-sm);\n padding: var(--uid-space-md);\n border-bottom: 1px solid var(--uid-border-subtle);\n}\n.admin-notif-drawer__title {\n display: inline-flex;\n align-items: center;\n gap: var(--uid-space-xs);\n margin: 0;\n font-family: var(--uid-font-family-display);\n font-size: 16px;\n font-weight: var(--uid-font-weight-semibold);\n color: var(--uid-text-primary);\n}\n.admin-notif-drawer__unread-badge {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 20px;\n padding: 2px 6px;\n border-radius: 10px;\n background: color-mix(in srgb, var(--uid-color-danger, #dc2626) 14%, transparent);\n color: var(--uid-color-danger, #dc2626);\n font-size: 11px;\n font-weight: var(--uid-font-weight-semibold);\n line-height: 1;\n}\n.admin-notif-drawer__hd-actions {\n display: inline-flex;\n align-items: center;\n gap: var(--uid-space-xs);\n}\n.admin-notif-drawer__mark-all {\n display: inline-flex;\n align-items: center;\n gap: var(--uid-space-2xs);\n padding: 6px 10px;\n border: 0;\n background: transparent;\n border-radius: var(--uid-radius-sm);\n color: var(--uid-text-secondary);\n font-size: 13px;\n cursor: pointer;\n}\n.admin-notif-drawer__mark-all:hover {\n background: var(--uid-color-surface-hover, var(--uid-border-subtle));\n color: var(--uid-text-primary);\n}\n.admin-notif-drawer__close {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n border: 0;\n background: transparent;\n border-radius: var(--uid-radius-sm);\n color: var(--uid-text-secondary);\n cursor: pointer;\n}\n.admin-notif-drawer__close:hover {\n background: var(--uid-color-surface-hover, var(--uid-border-subtle));\n color: var(--uid-text-primary);\n}\n\n/* Tabs */\n.admin-notif-drawer__tabs {\n display: flex;\n align-items: center;\n gap: var(--uid-space-md);\n padding: 0 var(--uid-space-md);\n border-bottom: 1px solid var(--uid-border-subtle);\n}\n.admin-notif-drawer__tab {\n display: inline-flex;\n align-items: center;\n gap: var(--uid-space-2xs);\n padding: 12px 0;\n border: 0;\n border-bottom: 2px solid transparent;\n background: transparent;\n color: var(--uid-text-secondary);\n font-size: 13px;\n font-weight: var(--uid-font-weight-medium);\n cursor: pointer;\n}\n.admin-notif-drawer__tab:hover { color: var(--uid-text-primary); }\n.admin-notif-drawer__tab--active {\n color: var(--uid-text-primary);\n border-bottom-color: var(--uid-accent);\n}\n.admin-notif-drawer__tab-count {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 18px;\n padding: 1px 6px;\n border-radius: 9px;\n background: var(--uid-border-subtle);\n color: var(--uid-text-tertiary);\n font-size: 11px;\n font-weight: var(--uid-font-weight-semibold);\n}\n.admin-notif-drawer__tab--active .admin-notif-drawer__tab-count {\n background: color-mix(in srgb, var(--uid-color-danger, #dc2626) 14%, transparent);\n color: var(--uid-color-danger, #dc2626);\n}\n\n/* Body / list */\n.admin-notif-drawer__body {\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n}\n.admin-notif-drawer__empty {\n padding: var(--uid-space-xl);\n text-align: center;\n color: var(--uid-text-tertiary);\n font-size: 13px;\n}\n.admin-notif-drawer__list {\n list-style: none;\n margin: 0;\n padding: 0;\n}\n.admin-notif-drawer__item {\n position: relative;\n display: flex;\n align-items: flex-start;\n gap: var(--uid-space-sm);\n padding: var(--uid-space-md);\n border-bottom: 1px solid var(--uid-border-subtle);\n cursor: pointer;\n transition: background var(--uid-duration-fast, 120ms) var(--uid-ease-out, ease);\n}\n.admin-notif-drawer__item:hover {\n background: var(--uid-color-surface-hover, var(--uid-border-subtle));\n}\n.admin-notif-drawer__item--unread {\n background: color-mix(in srgb, var(--uid-accent) 5%, transparent);\n}\n.admin-notif-drawer__icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex: none;\n width: 32px;\n height: 32px;\n border-radius: 50%;\n}\n.admin-notif-drawer__icon[data-variant='success'] {\n background: color-mix(in srgb, var(--uid-color-success, #10b981) 14%, transparent);\n color: var(--uid-color-success, #10b981);\n}\n.admin-notif-drawer__icon[data-variant='warning'] {\n background: color-mix(in srgb, var(--uid-color-warning, #f59e0b) 14%, transparent);\n color: var(--uid-color-warning, #f59e0b);\n}\n.admin-notif-drawer__icon[data-variant='danger'] {\n background: color-mix(in srgb, var(--uid-color-danger, #dc2626) 14%, transparent);\n color: var(--uid-color-danger, #dc2626);\n}\n.admin-notif-drawer__icon[data-variant='info'] {\n background: color-mix(in srgb, var(--uid-accent) 14%, transparent);\n color: var(--uid-accent);\n}\n.admin-notif-drawer__icon[data-variant='neutral'] {\n background: var(--uid-border-subtle);\n color: var(--uid-text-secondary);\n}\n\n.admin-notif-drawer__content {\n flex: 1;\n min-width: 0;\n}\n.admin-notif-drawer__row {\n display: flex;\n justify-content: space-between;\n align-items: baseline;\n gap: var(--uid-space-sm);\n}\n.admin-notif-drawer__item-title {\n font-size: 13px;\n font-weight: var(--uid-font-weight-semibold);\n color: var(--uid-text-primary);\n}\n.admin-notif-drawer__item-time {\n font-size: 11px;\n color: var(--uid-text-tertiary);\n flex: none;\n}\n.admin-notif-drawer__item-description {\n margin-top: 2px;\n font-size: 13px;\n color: var(--uid-text-secondary);\n line-height: 1.45;\n display: -webkit-box;\n -webkit-line-clamp: 3;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n.admin-notif-drawer__unread-dot {\n position: absolute;\n top: 16px;\n right: 36px;\n width: 8px;\n height: 8px;\n border-radius: 50%;\n background: var(--uid-color-success, #10b981);\n}\n.admin-notif-drawer__item-delete {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 22px;\n border: 0;\n background: transparent;\n border-radius: 50%;\n color: var(--uid-text-tertiary);\n cursor: pointer;\n opacity: 0;\n flex: none;\n align-self: flex-start;\n margin-top: -2px;\n}\n.admin-notif-drawer__item:hover .admin-notif-drawer__item-delete { opacity: 1; }\n.admin-notif-drawer__item-delete:hover {\n background: color-mix(in srgb, var(--uid-color-danger, #dc2626) 14%, transparent);\n color: var(--uid-color-danger, #dc2626);\n}\n\n/* Slide transition */\n.admin-notif-drawer-enter-active,\n.admin-notif-drawer-leave-active {\n transition: opacity 200ms ease-out;\n}\n.admin-notif-drawer-enter-active .admin-notif-drawer__panel,\n.admin-notif-drawer-leave-active .admin-notif-drawer__panel {\n transition: transform 240ms cubic-bezier(0.2, 0.8, 0.2, 1);\n}\n.admin-notif-drawer-enter-from,\n.admin-notif-drawer-leave-to {\n opacity: 0;\n}\n.admin-notif-drawer-enter-from .admin-notif-drawer__panel,\n.admin-notif-drawer-leave-to .admin-notif-drawer__panel {\n transform: translateX(100%);\n}\n</style>\n","/**\n * Manifest store: lazy-load JSON-манифеста админки + кеширование по version.\n *\n * Manifest содержит описание всех Resource'ов, Screen'ов, Settings'ов,\n * Plugin'ов. SPA загружает один раз на старте и переиспользует.\n *\n * ETag-based 304 Not Modified backend-side — фронт ничего особенного не\n * делает (axios + browser handle If-None-Match). Свежий version записывается\n * в lastVersion для cheap-сравнения.\n */\n\nimport { defineStore } from 'pinia'\nimport { computed, ref } from 'vue'\nimport { getAdminClient } from './registry'\n\n/**\n * Узел manifest'а с обязательным `type`. Совместим с LayoutNode/FieldNode/\n * InfolistNode — позволяет передавать массив прямо в renderer без cast'а.\n */\nexport interface ManifestNode extends Record<string, unknown> {\n type: string\n}\n\nexport interface ManifestResourceMeta {\n slug: string\n label: string\n icon?: string\n group?: string | null\n /**\n * Eloquent morph-class либо FQCN модели — нужен AuditTimeline'у как\n * `subject_type` параметр для /audit/timeline endpoint'а.\n */\n subject_type?: string | null\n permissions: Record<string, string>\n fields: ManifestNode[]\n /** Read-only entries для view-page. Default — auto-generated из fields(). */\n infolist?: ManifestNode[]\n columns: ManifestNode[]\n filters: ManifestNode[]\n actions: ManifestNode[]\n searchable: string[]\n with: string[]\n features: Record<string, unknown>\n screens?: Record<string, unknown>\n}\n\nexport interface ManifestScreenMeta {\n slug: string\n name: string\n description: string | null\n permission: string[] | string | null\n}\n\nexport interface ManifestSettingsMeta {\n kind: 'settings'\n slug: string\n label: string\n permissions: Record<string, string>\n fields: ManifestNode[]\n}\n\nexport interface AdminManifest {\n version: string\n locale: string\n resources: ManifestResourceMeta[]\n screens: ManifestScreenMeta[]\n settings: ManifestSettingsMeta[]\n dashboards: unknown[]\n plugins: string[]\n permissions: unknown[]\n}\n\nexport const useManifestStore = defineStore('admin-manifest', () => {\n const manifest = ref<AdminManifest | null>(null)\n const loading = ref(false)\n const error = ref<Error | null>(null)\n /**\n * Boot-resolution gate. true как только начальный flow \"load manifest →\n * replaceManifestRoutes → router.replace(currentFullPath)\" завершён,\n * либо если manifest заведомо не нужен (login flow / skipManifestLoad).\n *\n * AdminApp.vue использует этот флаг чтобы скрыть NotFoundPage пока не\n * закончился initial re-resolve — иначе deep-link reload даёт вспышку\n * 404 между первым match'ем catch-all и последующим router.replace.\n *\n * Проставляется createAdminApp.loadAndApply() в finally — точное место,\n * где route уже re-resolved, а manifest либо загружен, либо упал ошибкой.\n */\n const bootResolved = ref(false)\n\n const isLoaded = computed(() => manifest.value !== null)\n const version = computed(() => manifest.value?.version ?? null)\n const resources = computed(() => manifest.value?.resources ?? [])\n const screens = computed(() => manifest.value?.screens ?? [])\n const settings = computed(() => manifest.value?.settings ?? [])\n const plugins = computed(() => manifest.value?.plugins ?? [])\n\n function getResource(slug: string): ManifestResourceMeta | null {\n return resources.value.find((r) => r.slug === slug) ?? null\n }\n\n function getScreen(slug: string): ManifestScreenMeta | null {\n return screens.value.find((s) => s.slug === slug) ?? null\n }\n\n function getSettings(slug: string): ManifestSettingsMeta | null {\n return settings.value.find((s) => s.slug === slug) ?? null\n }\n\n /**\n * Загрузить manifest. Если уже загружен — возвращает cached.\n * Force=true принудительно обновит с сервера.\n */\n async function load(force = false): Promise<AdminManifest> {\n if (manifest.value !== null && !force) {\n return manifest.value\n }\n\n loading.value = true\n error.value = null\n try {\n const client = getAdminClient()\n const result = await client.get<AdminManifest>('/system/manifest')\n manifest.value = result\n return result\n } catch (err) {\n error.value = err instanceof Error ? err : new Error(String(err))\n throw err\n } finally {\n loading.value = false\n }\n }\n\n function reset(): void {\n manifest.value = null\n error.value = null\n loading.value = false\n bootResolved.value = false\n }\n\n return {\n // state\n manifest,\n loading,\n error,\n bootResolved,\n // getters\n isLoaded,\n version,\n resources,\n screens,\n settings,\n plugins,\n // actions\n getResource,\n getScreen,\n getSettings,\n load,\n reset,\n }\n})\n","/**\n * adminToast — фасад над useToast() из @dskripchenko/ui для admin-flows.\n *\n * Компонент @dskripchenko/ui/composables/useToast хранит массив toast'ов\n * в module-singleton'е (общий стек на всё приложение). Мы оборачиваем\n * методы success/error/info/warning в простые функции с дефолтными\n * длительностями + используется AdminClient ApiError для извлечения\n * понятных сообщений.\n */\nimport { useToast } from '@dskripchenko/ui'\n\ninterface Options {\n title?: string\n /** Длительность в ms (0 = не закрывать автоматически). */\n duration?: number\n}\n\nfunction shorthand(message: string, opts?: Options) {\n return { message, ...(opts ?? {}) }\n}\n\nexport const adminToast = {\n success(message: string, opts?: Options): void {\n useToast().success(shorthand(message, opts))\n },\n error(message: string, opts?: Options): void {\n useToast().error(shorthand(message, { duration: 6000, ...(opts ?? {}) }))\n },\n warning(message: string, opts?: Options): void {\n useToast().warning(shorthand(message, opts))\n },\n info(message: string, opts?: Options): void {\n useToast().info(shorthand(message, opts))\n },\n}\n\n/**\n * fromError — извлекает message из ApiError / Error / unknown и пушит toast.\n */\nexport function toastError(err: unknown, fallback = 'Произошла ошибка'): void {\n const msg =\n err instanceof Error\n ? err.message || fallback\n : typeof err === 'string'\n ? err\n : fallback\n adminToast.error(msg)\n}\n","<script setup lang=\"ts\">\n/**\n * Root компонент SPA admin'а — рендерит router-view, оборачивая его в\n * AdminShell layout (TopBar + Sidebar + content) для аутентифицированных\n * роутов. Auth-роуты (login, 403, 404) и роуты с meta.fullscreen рендерятся\n * без shell.\n *\n * Используется createAdminApp() как root-component. Host'ы редко\n * переопределяют — обычно достаточно настроить отдельные pages через опции.\n */\nimport { computed } from 'vue'\nimport { useRoute } from 'vue-router'\nimport { UidToastProvider } from '@dskripchenko/ui'\nimport AdminShell from './shell/AdminShell.vue'\nimport AdminLoadingBar from './AdminLoadingBar.vue'\nimport NotificationsDrawer from './shell/NotificationsDrawer.vue'\nimport { useManifestStore } from '../stores/manifest'\nimport { useAuthStore } from '../stores/auth'\nimport { adminToast } from '../stores/toast'\n\nconst route = useRoute()\nconst manifest = useManifestStore()\nconst auth = useAuthStore()\n\n/**\n * Impersonation state — backend кладёт в bootstrap.user.impersonator\n * объект `{name, email}`, если активный сеанс — impersonation. Frontend\n * отображает баннер сверху shell'а.\n */\nconst impersonation = computed<{ asName: string } | null>(() => {\n const u = auth.user as Record<string, unknown> | null\n const imp = u?.impersonator as Record<string, unknown> | null | undefined\n if (!imp) return null\n // u.name — кого мы изображаем; imp.name — кто настоящий админ.\n return { asName: String(u?.name ?? '?') }\n})\n\nasync function exitImpersonation(): Promise<void> {\n try {\n const { getAdminClient } = await import('../stores/registry')\n const client = getAdminClient()\n await client.post('/auth/stopImpersonation')\n window.location.reload()\n } catch {\n adminToast.error('Не удалось выйти из режима импертонации.')\n }\n}\n\nconst useShell = computed<boolean>(() => {\n if (route.meta?.fullscreen === true) return false\n if (route.meta?.kind === 'auth') return false\n if (route.name === 'admin.notFound') return false\n return true\n})\n\n/**\n * При reload deep-link страницы (/admin/r/articles/1/edit) Vue Router\n * сначала матчит против static routes (dynamic resource routes ещё не\n * добавлены — manifest async-load в createAdminApp), и фолбэк-резолв\n * попадает в catch-all `admin.notFound`. Через 50-200ms manifest приходит,\n * createAdminApp re-resolve'ит current route → правильная страница.\n *\n * Чтобы избежать вспышки 404 в этот промежуток — скрываем NotFoundPage\n * пока initial manifest+re-resolve не закончился (manifest.bootResolved).\n * Гейт открывается createAdminApp.loadAndApply() в finally — после того,\n * как router.replace(currentFullPath) уже отработал. Это закрывает окно\n * между \"manifest пришёл\" и \"route переключился\", где иначе виден 404.\n */\nconst suppressNotFound = computed<boolean>(\n () => route.name === 'admin.notFound' && !manifest.bootResolved,\n)\n</script>\n\n<template>\n <!-- Top loading-bar: показывается пока nav/data не закончили (см. useNavigationStore). -->\n <AdminLoadingBar />\n\n <AdminShell\n v-if=\"useShell\"\n :impersonation=\"impersonation\"\n @exit-impersonation=\"exitImpersonation\"\n >\n <div class=\"admin-page-host\">\n <router-view v-slot=\"{ Component }\">\n <Transition name=\"admin-page\">\n <component v-if=\"!suppressNotFound\" :is=\"Component\" />\n <div v-else class=\"admin-page-host__suspended\" aria-busy=\"true\" />\n </Transition>\n </router-view>\n </div>\n </AdminShell>\n <router-view v-else v-slot=\"{ Component }\">\n <Transition name=\"admin-page\">\n <component v-if=\"!suppressNotFound\" :is=\"Component\" />\n <div v-else class=\"admin-page-host__suspended\" aria-busy=\"true\" />\n </Transition>\n </router-view>\n\n <!-- Slide-in drawer уведомлений; mounted один раз, открывается через\n notificationsStore.toggleDrawer() (см. NotificationBell). -->\n <NotificationsDrawer />\n\n <!-- Toast-stack для админских уведомлений (success/error/info).\n useToast() из @dskripchenko/ui — push'ит сообщения в общий store. -->\n <UidToastProvider />\n</template>\n\n<style>\n/*\n * Page-host: relative контейнер. Старая страница leaving делается absolute\n * (overlay поверх новой), entering в нормальном flow с slide-from-right.\n *\n * Тайминги (по запросу):\n * - leaving fade-out: 140ms ease-out (быстро уходит).\n * - entering slide-from-right + fade-in: 320ms cubic-bezier easing,\n * с 60ms delay чтобы старая успела \"пропасть до того как новая\n * доберётся до позиции\".\n *\n * overflow:hidden на host — slide справа не вылезает за viewport.\n */\n.admin-page-host {\n position: relative;\n min-height: 200px;\n overflow: hidden;\n}\n\n/* Заглушка-noop пока manifest не resolved — заменяет потенциальный flash\n NotFoundPage при reload deep-link. Top loading-bar показывает что\n что-то происходит. */\n.admin-page-host__suspended {\n min-height: 320px;\n}\n\n/* Leaving page absolute — не двигает layout, остаётся на месте пока fade'ится. */\n.admin-page-leave-active {\n position: absolute;\n inset: 0;\n width: 100%;\n transition: opacity 140ms ease-out;\n}\n\n.admin-page-leave-to {\n opacity: 0;\n}\n\n/* Entering page: slide-in справа + fade-in. Delay 60ms — старая уже почти ушла. */\n.admin-page-enter-active {\n transition:\n opacity 320ms cubic-bezier(0.2, 0.8, 0.2, 1) 60ms,\n transform 320ms cubic-bezier(0.2, 0.8, 0.2, 1) 60ms;\n}\n\n.admin-page-enter-from {\n opacity: 0;\n transform: translateX(28px);\n}\n\n.admin-page-enter-to {\n opacity: 1;\n transform: translateX(0);\n}\n\n@media (prefers-reduced-motion: reduce) {\n .admin-page-enter-active,\n .admin-page-leave-active {\n transition: opacity 80ms ease-out;\n }\n .admin-page-enter-from {\n transform: none;\n }\n}\n</style>\n","/**\n * Dashboard store: edit-mode + working-copy layout + save/load.\n *\n * Backend контракт:\n * GET /api/admin/dashboard/get?key={dashboard_slug} → { layout: WidgetItem[] | null }\n * POST /api/admin/dashboard/save body { key, widgets[] }\n * POST /api/admin/dashboard/reset body { key }\n *\n * WidgetItem — это per-user override:\n * { slug, size, position, hidden, config?, type? }\n *\n * `slug` — backend Widget::slug() (для встроенных) либо user-generated\n * (для виджетов добавленных через Add Widget — host сохраняет config\n * в `config` поле, type — в `type`).\n */\n\nimport { defineStore } from 'pinia'\nimport { computed, ref } from 'vue'\nimport { getAdminClient } from './registry'\n\nexport interface WidgetLayoutItem {\n slug: string\n size?: number\n position?: number\n hidden?: boolean\n /** Тип widget'а (для user-added; для backend — синхронизируется с Widget). */\n type?: string\n /** Title override + per-type конфигурация. */\n config?: Record<string, unknown>\n}\n\nexport const useDashboardStore = defineStore('admin-dashboard', () => {\n /** Текущий dashboard-slug (открытый в DashboardPage). */\n const slug = ref<string | null>(null)\n /** Edit-mode флаг — показывает overlay'и поверх виджетов. */\n const editMode = ref<boolean>(false)\n /** Working-copy layout (то что юзер редактирует, до save). */\n const draft = ref<WidgetLayoutItem[]>([])\n /** Изначальный layout — для cancel/restore. */\n const original = ref<WidgetLayoutItem[]>([])\n /** Loading state для load/save. */\n const saving = ref<boolean>(false)\n const loading = ref<boolean>(false)\n\n const isDirty = computed<boolean>(() => {\n return JSON.stringify(draft.value) !== JSON.stringify(original.value)\n })\n\n /** Открыть dashboard — load persisted layout если есть. */\n async function openDashboard(dashboardSlug: string): Promise<void> {\n slug.value = dashboardSlug\n loading.value = true\n try {\n const client = getAdminClient()\n const result = await client.get<{ layout: WidgetLayoutItem[] | null }>(\n `/dashboard/get?key=${encodeURIComponent(dashboardSlug)}`,\n )\n const items = (result.layout ?? []).map((it, idx) => ({\n ...it,\n position: it.position ?? idx,\n }))\n original.value = items\n draft.value = items.map((it) => ({ ...it }))\n } catch {\n original.value = []\n draft.value = []\n } finally {\n loading.value = false\n }\n }\n\n function enterEditMode(): void {\n editMode.value = true\n }\n\n function cancelEdit(): void {\n draft.value = original.value.map((it) => ({ ...it }))\n editMode.value = false\n }\n\n async function saveLayout(): Promise<void> {\n if (slug.value === null) return\n saving.value = true\n try {\n const client = getAdminClient()\n // Перед save нумеруем position в порядке текущего draft (drag-order).\n const widgets = draft.value.map((it, idx) => ({\n slug: it.slug,\n size: it.size,\n position: idx,\n hidden: it.hidden ?? false,\n type: it.type,\n config: it.config,\n }))\n await client.post('/dashboard/save', { key: slug.value, widgets })\n original.value = draft.value.map((it) => ({ ...it }))\n editMode.value = false\n } finally {\n saving.value = false\n }\n }\n\n async function resetToDefault(): Promise<void> {\n if (slug.value === null) return\n saving.value = true\n try {\n const client = getAdminClient()\n await client.post('/dashboard/reset', { key: slug.value })\n original.value = []\n draft.value = []\n editMode.value = false\n } finally {\n saving.value = false\n }\n }\n\n function addWidget(item: WidgetLayoutItem): void {\n draft.value = [\n ...draft.value,\n { ...item, position: draft.value.length },\n ]\n }\n\n function removeWidget(slugKey: string): void {\n draft.value = draft.value.filter((it) => it.slug !== slugKey)\n }\n\n function updateWidget(slugKey: string, patch: Partial<WidgetLayoutItem>): void {\n draft.value = draft.value.map((it) =>\n it.slug === slugKey ? { ...it, ...patch } : it,\n )\n }\n\n function moveWidget(fromIdx: number, toIdx: number): void {\n if (fromIdx === toIdx) return\n const next = [...draft.value]\n const [moved] = next.splice(fromIdx, 1)\n next.splice(toIdx, 0, moved)\n draft.value = next\n }\n\n function reset(): void {\n slug.value = null\n editMode.value = false\n draft.value = []\n original.value = []\n }\n\n return {\n slug,\n editMode,\n draft,\n original,\n saving,\n loading,\n isDirty,\n openDashboard,\n enterEditMode,\n cancelEdit,\n saveLayout,\n resetToDefault,\n addWidget,\n removeWidget,\n updateWidget,\n moveWidget,\n reset,\n }\n})\n","/**\n * i18n store — простой message-bag + t() helper.\n *\n * Backend кладёт translations bag в `bootstrap.translations` (Record<key, string>).\n * При смене локали (`/system/setLocale`) bootstrap переподнимается либо\n * helper зовёт `loadLocale(locale)`, который POST'ит messages.\n *\n * Формат:\n * t('admin.dashboard.add_widget') // 'Add widget'\n * t('admin.records.count', { n: 42 }) // 'Записей: 42' (interpolation :n)\n *\n * Fallback: если ключ не найден — возвращает сам ключ (помогает быстро\n * увидеть отсутствующие переводы во время разработки).\n */\nimport { defineStore } from 'pinia'\nimport { computed, ref } from 'vue'\nimport type { AdminBootstrap } from '../types/bootstrap'\n\nexport const useI18nStore = defineStore('admin-i18n', () => {\n const messages = ref<Record<string, string>>({})\n const locale = ref<string>('ru')\n\n function hydrate(bootstrap: AdminBootstrap): void {\n // Backend кладёт translations в bootstrap (опционально).\n const t = (bootstrap as unknown as { translations?: Record<string, string> }).translations\n if (t && typeof t === 'object') {\n messages.value = { ...t }\n }\n locale.value = bootstrap.locale ?? 'ru'\n }\n\n function setMessages(next: Record<string, string>): void {\n messages.value = { ...next }\n }\n\n /**\n * Translate. Поддерживает interpolation вида `:name` (Laravel-стиль).\n * Если ключ отсутствует — возвращается сам ключ (visible-fallback).\n */\n function t(key: string, replace: Record<string, string | number> = {}): string {\n let str = messages.value[key] ?? key\n for (const [k, v] of Object.entries(replace)) {\n str = str.replace(new RegExp(`:${k}`, 'g'), String(v))\n }\n return str\n }\n\n const has = (key: string): boolean => key in messages.value\n\n return {\n messages,\n locale,\n hydrate,\n setMessages,\n t,\n has,\n keys: computed(() => Object.keys(messages.value)),\n }\n})\n\n/**\n * Convenience: глобальный t() для не-Vue контекстов (utils, services).\n * В Vue-компонентах предпочтительнее `const { t } = useI18nStore()`.\n */\nexport function tRaw(key: string, replace?: Record<string, string | number>): string {\n return useI18nStore().t(key, replace ?? {})\n}\n","/**\n * Generic factory для component-registry'ов (fields, layouts, widgets,\n * infolist entries и т.п.).\n *\n * Все component-registry в admin'е по сути одинаковы: keyed Map<string, Component>\n * + register/get/has/list/clear/registerBundle. Этот factory вытаскивает паттерн\n * один раз; конкретные модули просто переименовывают экспорты.\n *\n * const reg = createComponentRegistry<Component>()\n * export const registerWidget = reg.register\n * export const getWidget = reg.get\n * // ...\n */\n\nexport interface ComponentRegistry<T> {\n register(type: string, value: T): void\n get(type: string): T | null\n has(type: string): boolean\n list(): string[]\n clear(): void\n registerBundle(bundle: Record<string, T>): void\n}\n\nexport function createComponentRegistry<T>(): ComponentRegistry<T> {\n const store = new Map<string, T>()\n\n return {\n register(type, value) {\n store.set(type, value)\n },\n get(type) {\n return store.get(type) ?? null\n },\n has(type) {\n return store.has(type)\n },\n list() {\n return [...store.keys()]\n },\n clear() {\n store.clear()\n },\n registerBundle(bundle) {\n for (const [type, value] of Object.entries(bundle)) {\n store.set(type, value)\n }\n },\n }\n}\n","/**\n * Реестр dashboard widget-компонентов.\n *\n * Manifest узлы dashboard выглядят так:\n * {\n * slug: 'main',\n * label: 'Главный',\n * widgets: [\n * { type: 'stat', name: 'total', title: 'Всего', value: 1284,\n * span: 3, trend: 12 },\n * { type: 'bar-chart', span: 8, ... },\n * { type: 'recent-table', span: 8, columns: [...], rows: [...] },\n * ]\n * }\n *\n * Host регистрирует кастомные widget'ы через `registerWidget()` /\n * `registerWidgets()` bundle.\n */\n\nimport type { Component } from 'vue'\nimport { createComponentRegistry } from '../createComponentRegistry'\n\nconst widgets = createComponentRegistry<Component>()\n\nexport const registerWidget = widgets.register\nexport const getWidget = widgets.get\nexport const hasWidget = widgets.has\nexport const listWidgets = widgets.list\nexport const clearWidgetRegistry = widgets.clear\nexport const registerWidgets = widgets.registerBundle\n","<script setup lang=\"ts\">\nimport { UidAlert } from '@dskripchenko/ui'\n\ninterface Props {\n type: string\n}\ndefineProps<Props>()\n</script>\n\n<template>\n <UidAlert variant=\"warning\">\n <template #title>Неизвестный widget-тип: {{ type }}</template>\n Зарегистрируйте через <code>registerWidget('{{ type }}', YourComponent)</code>.\n </UidAlert>\n</template>\n","<script setup lang=\"ts\">\n/**\n * Резолвит widget-компонент по `node.type` и forwards остальные props.\n */\nimport { computed } from 'vue'\nimport { getWidget } from './registry'\nimport UnknownWidget from './UnknownWidget.vue'\n\nexport interface WidgetNode extends Record<string, unknown> {\n type: string\n /** Сколько колонок занимает в 12-grid (1..12). */\n span?: number\n}\n\ninterface Props {\n node: WidgetNode\n}\nconst props = defineProps<Props>()\n\nconst component = computed(() => getWidget(props.node.type))\nconst widgetProps = computed(() => {\n const { type: _type, span: _span, ...rest } = props.node\n return rest\n})\n</script>\n\n<template>\n <component :is=\"component\" v-if=\"component\" v-bind=\"widgetProps\" />\n <UnknownWidget v-else :type=\"node.type\" />\n</template>\n","<script setup lang=\"ts\">\n/**\n * Overlay с action-кнопками поверх widget'а в edit-mode:\n * ☰ — drag-handle для пересортировки\n * ⚙ — настройки widget'а\n * × — удалить\n */\nimport { GripVertical, Settings, X } from 'lucide-vue-next'\nimport { UidIcon } from '@dskripchenko/ui'\n\ndefineEmits<{\n configure: []\n remove: []\n}>()\n</script>\n\n<template>\n <div class=\"admin-widget-actions\" role=\"toolbar\" aria-label=\"Действия с виджетом\">\n <button\n type=\"button\"\n class=\"admin-widget-actions__btn admin-widget-actions__drag\"\n aria-label=\"Перетащить\"\n title=\"Перетащить\"\n data-drag-handle=\"true\"\n >\n <UidIcon :icon=\"GripVertical\" :size=\"14\" />\n </button>\n <button\n type=\"button\"\n class=\"admin-widget-actions__btn\"\n aria-label=\"Настройки\"\n title=\"Настройки\"\n @click=\"$emit('configure')\"\n >\n <UidIcon :icon=\"Settings\" :size=\"14\" />\n </button>\n <button\n type=\"button\"\n class=\"admin-widget-actions__btn admin-widget-actions__btn--danger\"\n aria-label=\"Удалить\"\n title=\"Удалить\"\n @click=\"$emit('remove')\"\n >\n <UidIcon :icon=\"X\" :size=\"14\" />\n </button>\n </div>\n</template>\n\n<style>\n.admin-widget-actions {\n position: absolute;\n top: 8px;\n right: 8px;\n display: inline-flex;\n align-items: center;\n gap: 2px;\n padding: 2px;\n background: var(--uid-surface-raised);\n border: 1px solid var(--uid-border-subtle);\n border-radius: var(--uid-radius-md);\n box-shadow: var(--uid-shadow-sm);\n z-index: 5;\n}\n.admin-widget-actions__btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n border: 0;\n background: transparent;\n border-radius: var(--uid-radius-sm);\n color: var(--uid-text-secondary);\n cursor: pointer;\n}\n.admin-widget-actions__btn:hover {\n background: var(--uid-color-surface-hover, var(--uid-border-subtle));\n color: var(--uid-text-primary);\n}\n.admin-widget-actions__btn--danger:hover {\n background: color-mix(in srgb, var(--uid-color-danger, #dc2626) 14%, transparent);\n color: var(--uid-color-danger, #dc2626);\n}\n.admin-widget-actions__drag {\n cursor: grab;\n}\n.admin-widget-actions__drag:active {\n cursor: grabbing;\n}\n</style>\n","<script setup lang=\"ts\">\n/**\n * WidgetConfigDialog — единый dialog для двух use-case'ов:\n *\n * mode='add' — выбор типа из registry + первичная настройка\n * mode='configure'— редактирование существующего widget'а (тип фиксирован)\n *\n * Поля:\n * - title (всегда)\n * - size 1..12 (всегда)\n * - type-specific config (зависит от type):\n * markdown → content\n * stat/stats → label + value\n * gauge → value (0..100)\n * chart/bar-chart/donut-chart → labels + datasets[0].data (CSV)\n * recent-table → resource slug + limit\n * heatmap → нет настраиваемых (рендерится из data, host'ит backend)\n *\n * @add — emit готового WidgetLayoutItem (родитель кладёт в store).\n * @save — emit patch'а для существующего widget'а.\n */\nimport { computed, ref, watch } from 'vue'\nimport { X } from 'lucide-vue-next'\nimport {\n UidButton,\n UidIcon,\n UidInput,\n} from '@dskripchenko/ui'\nimport { listWidgets } from './registry'\nimport type { WidgetLayoutItem } from '../../stores/dashboard'\n\ninterface Props {\n open: boolean\n /** 'add' — выбор типа; 'configure' — редактирование существующего. */\n mode?: 'add' | 'configure'\n /** Initial-state для configure (slug + type + size + config). */\n item?: WidgetLayoutItem | null\n /** Title виджета на момент открытия (для configure-mode из manifest'а). */\n initialTitle?: string\n}\nconst props = withDefaults(defineProps<Props>(), {\n mode: 'add',\n item: null,\n initialTitle: '',\n})\n\nconst emit = defineEmits<{\n close: []\n add: [item: WidgetLayoutItem]\n save: [patch: Partial<WidgetLayoutItem>]\n}>()\n\nconst types = computed<string[]>(() => listWidgets())\nconst selectedType = ref<string>('')\nconst title = ref<string>('')\nconst size = ref<string>('6')\n\nconst markdownContent = ref<string>('# Новая заметка\\n\\nТекст…')\nconst statLabel = ref<string>('LABEL')\nconst statValue = ref<string>('0')\nconst gaugeValue = ref<string>('50')\nconst chartLabels = ref<string>('Янв, Фев, Мар, Апр')\nconst chartValues = ref<string>('10, 20, 15, 30')\nconst recentResource = ref<string>('')\nconst recentLimit = ref<string>('5')\n\nwatch(\n () => props.open,\n (open) => {\n if (!open) return\n if (props.mode === 'configure' && props.item) {\n const cfg = (props.item.config ?? {}) as Record<string, unknown>\n selectedType.value = props.item.type ?? ''\n title.value = (cfg.title as string | undefined) ?? props.initialTitle\n size.value = String(props.item.size ?? 6)\n // Преварительно заполняем type-specific поля.\n markdownContent.value = (cfg.content as string | undefined) ?? markdownContent.value\n const firstStat = (cfg.stats as Array<Record<string, unknown>> | undefined)?.[0]\n if (firstStat) {\n statLabel.value = String(firstStat.label ?? '')\n statValue.value = String(firstStat.value ?? '')\n }\n gaugeValue.value = String((cfg.value as number | undefined) ?? 50)\n // Chart labels/values — flatten из cfg.labels / cfg.datasets[0].data.\n const labels = cfg.labels as string[] | undefined\n const datasets = cfg.datasets as Array<{ data?: number[] }> | undefined\n if (labels && labels.length > 0) chartLabels.value = labels.join(', ')\n if (datasets && datasets[0]?.data) chartValues.value = datasets[0].data.join(', ')\n recentResource.value = (cfg.resource as string | undefined) ?? ''\n recentLimit.value = String(cfg.limit ?? 5)\n } else {\n // Add-mode: чистый state.\n selectedType.value = ''\n title.value = ''\n size.value = '6'\n }\n },\n)\n\nconst canSubmit = computed<boolean>(\n () => selectedType.value !== '' && title.value.trim() !== '',\n)\n\nconst labelOf: Record<string, string> = {\n stat: 'Stat — карточка с числом',\n stats: 'Stats overview — несколько метрик',\n chart: 'Chart — линия / столбцы / донат',\n 'bar-chart': 'Bar chart — гистограмма',\n 'donut-chart': 'Donut — кольцевая диаграмма',\n 'recent-table': 'Recent list — последние записи',\n recent_list: 'Recent list — последние записи',\n 'recent-list': 'Recent list — последние записи',\n heatmap: 'Heatmap — тепловая карта',\n gauge: 'Gauge — шкала со значением',\n markdown: 'Markdown — заметка / текст',\n}\n\ntype ConfigKind =\n | 'markdown'\n | 'stat'\n | 'gauge'\n | 'chart'\n | 'recent'\n | null\n\nfunction configKind(t: string): ConfigKind {\n if (t === 'markdown') return 'markdown'\n if (t === 'stat' || t === 'stats') return 'stat'\n if (t === 'gauge') return 'gauge'\n if (t === 'chart' || t === 'bar-chart' || t === 'donut-chart') return 'chart'\n if (t === 'recent-table' || t === 'recent_list' || t === 'recent-list') return 'recent'\n return null\n}\n\nfunction buildConfig(): Record<string, unknown> {\n const base: Record<string, unknown> = { title: title.value }\n switch (configKind(selectedType.value)) {\n case 'markdown':\n base.content = markdownContent.value\n break\n case 'stat':\n base.stats = [{ label: statLabel.value, value: statValue.value }]\n break\n case 'gauge':\n base.value = Number(gaugeValue.value) || 0\n base.min = 0\n base.max = 100\n break\n case 'chart': {\n const labels = chartLabels.value.split(',').map((s) => s.trim()).filter(Boolean)\n const data = chartValues.value\n .split(',')\n .map((s) => Number(s.trim()))\n .filter((n) => !Number.isNaN(n))\n base.labels = labels\n base.datasets = [{ label: title.value, data }]\n base.type = selectedType.value === 'donut-chart' ? 'doughnut' : 'bar'\n break\n }\n case 'recent':\n base.resource = recentResource.value\n base.limit = Number(recentLimit.value) || 5\n break\n }\n return base\n}\n\nfunction onSubmit(): void {\n if (!canSubmit.value) return\n const sizeNum = Math.max(1, Math.min(12, Number(size.value) || 6))\n const config = buildConfig()\n\n if (props.mode === 'configure' && props.item) {\n emit('save', { size: sizeNum, type: selectedType.value, config })\n } else {\n const slug = `custom.${selectedType.value}.${Date.now()}`\n emit('add', {\n slug,\n type: selectedType.value,\n size: sizeNum,\n config,\n })\n }\n emit('close')\n}\n\nfunction close(): void {\n emit('close')\n}\n</script>\n\n<template>\n <Teleport to=\"body\">\n <Transition name=\"admin-dialog\">\n <div\n v-if=\"open\"\n class=\"admin-dialog-root\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"widget-config-title\"\n >\n <div class=\"admin-dialog-root__backdrop\" @click=\"close\" />\n <div class=\"admin-dialog\">\n <header class=\"admin-dialog__hd\">\n <h2 id=\"widget-config-title\" class=\"admin-dialog__title\">\n {{ mode === 'add' ? 'Добавить виджет' : 'Настроить виджет' }}\n </h2>\n <button\n type=\"button\"\n class=\"admin-dialog__close\"\n aria-label=\"Закрыть\"\n @click=\"close\"\n >\n <UidIcon :icon=\"X\" :size=\"16\" />\n </button>\n </header>\n\n <div class=\"admin-dialog__body\">\n <!-- Type selector — только в add-mode. -->\n <div v-if=\"mode === 'add'\" class=\"admin-dialog__field\">\n <label class=\"admin-dialog__label\">Тип виджета</label>\n <div class=\"admin-dialog__type-grid\">\n <button\n v-for=\"t in types\"\n :key=\"t\"\n type=\"button\"\n :class=\"[\n 'admin-dialog__type-card',\n { 'admin-dialog__type-card--active': selectedType === t },\n ]\"\n @click=\"selectedType = t\"\n >\n <span class=\"admin-dialog__type-name\">{{ t }}</span>\n <span class=\"admin-dialog__type-help\">{{ labelOf[t] ?? '' }}</span>\n </button>\n </div>\n </div>\n <div v-else class=\"admin-dialog__field\">\n <label class=\"admin-dialog__label\">Тип</label>\n <div class=\"admin-dialog__readonly\">{{ selectedType || 'unknown' }}</div>\n </div>\n\n <div class=\"admin-dialog__field\">\n <label class=\"admin-dialog__label\">Заголовок</label>\n <UidInput v-model=\"title\" placeholder=\"Название виджета\" />\n </div>\n\n <div class=\"admin-dialog__field\">\n <label class=\"admin-dialog__label\">Ширина (1..12)</label>\n <UidInput v-model=\"size\" type=\"number\" />\n </div>\n\n <!-- Type-specific config -->\n <template v-if=\"configKind(selectedType) === 'markdown'\">\n <div class=\"admin-dialog__field\">\n <label class=\"admin-dialog__label\">Markdown содержимое</label>\n <textarea\n v-model=\"markdownContent\"\n class=\"admin-dialog__textarea\"\n rows=\"6\"\n />\n </div>\n </template>\n <template v-else-if=\"configKind(selectedType) === 'stat'\">\n <div class=\"admin-dialog__field\">\n <label class=\"admin-dialog__label\">Метка</label>\n <UidInput v-model=\"statLabel\" />\n </div>\n <div class=\"admin-dialog__field\">\n <label class=\"admin-dialog__label\">Значение</label>\n <UidInput v-model=\"statValue\" />\n </div>\n </template>\n <template v-else-if=\"configKind(selectedType) === 'gauge'\">\n <div class=\"admin-dialog__field\">\n <label class=\"admin-dialog__label\">Значение (0..100)</label>\n <UidInput v-model=\"gaugeValue\" type=\"number\" />\n </div>\n </template>\n <template v-else-if=\"configKind(selectedType) === 'chart'\">\n <div class=\"admin-dialog__field\">\n <label class=\"admin-dialog__label\">Метки (через запятую)</label>\n <UidInput v-model=\"chartLabels\" placeholder=\"Янв, Фев, Мар\" />\n </div>\n <div class=\"admin-dialog__field\">\n <label class=\"admin-dialog__label\">Значения (через запятую)</label>\n <UidInput v-model=\"chartValues\" placeholder=\"10, 20, 15\" />\n </div>\n </template>\n <template v-else-if=\"configKind(selectedType) === 'recent'\">\n <div class=\"admin-dialog__field\">\n <label class=\"admin-dialog__label\">Resource slug</label>\n <UidInput v-model=\"recentResource\" placeholder=\"articles\" />\n </div>\n <div class=\"admin-dialog__field\">\n <label class=\"admin-dialog__label\">Limit</label>\n <UidInput v-model=\"recentLimit\" type=\"number\" />\n </div>\n </template>\n </div>\n\n <footer class=\"admin-dialog__ft\">\n <UidButton variant=\"ghost\" @click=\"close\">Отмена</UidButton>\n <UidButton variant=\"primary\" :disabled=\"!canSubmit\" @click=\"onSubmit\">\n {{ mode === 'add' ? 'Добавить' : 'Сохранить' }}\n </UidButton>\n </footer>\n </div>\n </div>\n </Transition>\n </Teleport>\n</template>\n\n<style>\n.admin-dialog__readonly {\n padding: 8px 10px;\n background: var(--uid-surface-base);\n border: 1px solid var(--uid-border-subtle);\n border-radius: var(--uid-radius-md);\n font-family: var(--uid-font-family-mono, ui-monospace, monospace);\n font-size: 13px;\n color: var(--uid-text-secondary);\n}\n</style>\n","<script setup lang=\"ts\">\n/**\n * DashboardPage — 12-col grid из widget'ов с поддержкой edit-mode.\n *\n * Источник widget'ов:\n * - Manifest.dashboards (host-side declared, через DashboardScreen).\n * - Per-user persisted layout (DashboardLayout / dashboard store) —\n * накладывается поверх manifest'ной декларации: переупорядочение,\n * resize, hidden, удаление + user-added widgets через AddWidget.\n *\n * Edit-mode:\n * 1. «Редактировать» в toolbar → editMode=true. На каждом widget'е\n * появляются [☰][⚙][×] (см. WidgetActionsOverlay).\n * 2. Drag-handle ☰ позволяет менять порядок (HTML5 drag).\n * 3. Resize-handle ↘ в правом-нижнем углу — изменяет span (1..12).\n * 4. + Add widget → AddWidgetDialog → store.addWidget.\n * 5. «Сохранить» → POST /dashboard/save с draft. «Отменить» → restore.\n */\nimport { computed, ref } from 'vue'\nimport {\n Calendar,\n ChevronDown,\n Download,\n Pencil,\n Plus,\n RotateCcw,\n} from 'lucide-vue-next'\nimport {\n UidButton,\n UidIcon,\n UidMenu,\n UidMenuItem,\n} from '@dskripchenko/ui'\nimport { useManifestStore } from '../../stores/manifest'\nimport { useI18nStore } from '../../stores/i18n'\nimport { useDashboardStore, type WidgetLayoutItem } from '../../stores/dashboard'\nimport WidgetRenderer, { type WidgetNode } from './WidgetRenderer.vue'\nimport WidgetActionsOverlay from './WidgetActionsOverlay.vue'\nimport WidgetConfigDialog from './WidgetConfigDialog.vue'\n\ninterface DashboardManifest {\n slug: string\n label?: string\n description?: string | null\n widgets: WidgetNode[]\n}\n\ninterface Props {\n slug?: string\n widgets?: WidgetNode[]\n title?: string\n subtitle?: string\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n slug: undefined,\n widgets: undefined,\n title: undefined,\n subtitle: undefined,\n})\n\nconst emit = defineEmits<{\n 'change-period': [value: string]\n 'export': []\n}>()\n\nconst manifest = useManifestStore()\nconst dashboardStore = useDashboardStore()\nconst i18n = useI18nStore()\nconst t = (key: string, fallback: string): string => {\n // Если backend lang-bag прислал нужный ключ — используем; иначе ru-fallback.\n // Это позволяет постепенно мигрировать без breaking changes.\n return i18n.has(key) ? i18n.t(key) : fallback\n}\n\nconst dashboard = computed<DashboardManifest | null>(() => {\n if (!props.slug || !manifest.manifest) return null\n const dashboards = manifest.manifest.dashboards as DashboardManifest[] | undefined\n return dashboards?.find((d) => d.slug === props.slug) ?? null\n})\n\nconst manifestWidgets = computed<WidgetNode[]>(() => {\n if (props.widgets) return props.widgets\n // refreshedWidgets — свежие data после смены period (через /dashboard/widgets).\n // Имеют приоритет над manifest'ным snapshot'ом.\n if (refreshedWidgets.value !== null) return refreshedWidgets.value\n return dashboard.value?.widgets ?? []\n})\n\nconst resolvedTitle = computed(\n () => props.title ?? dashboard.value?.label ?? 'Dashboard',\n)\nconst resolvedSubtitle = computed(\n () => props.subtitle ?? dashboard.value?.description ?? null,\n)\n\n/**\n * Финальный список виджетов с применённым per-user layout'ом:\n * - manifest widgets индексируются по slug;\n * - draft layout (из store) задаёт порядок, size, hidden;\n * - user-added (есть type/config, но нет manifest-исходника) рендерятся как самостоятельные;\n * - manifest widget'ы которых нет в draft — добавляются в конец (новые в коде).\n */\nconst renderedWidgets = computed<Array<{ node: WidgetNode; layoutSlug: string }>>(() => {\n const bySlug = new Map<string, WidgetNode>()\n for (const w of manifestWidgets.value) {\n const slug = String((w as Record<string, unknown>).slug ?? '')\n if (slug) bySlug.set(slug, w)\n }\n\n const draft = dashboardStore.draft\n const out: Array<{ node: WidgetNode; layoutSlug: string }> = []\n\n if (draft.length > 0) {\n for (const item of draft) {\n if (item.hidden) continue\n let node: WidgetNode | null = null\n if (bySlug.has(item.slug)) {\n // Manifest-widget с per-user override size.\n const base = bySlug.get(item.slug) as WidgetNode\n node = {\n ...base,\n size: item.size ?? (base as Record<string, unknown>).size ?? 12,\n } as WidgetNode\n bySlug.delete(item.slug)\n } else if (item.type) {\n // User-added widget — рендерится по type + config.\n const cfg = (item.config ?? {}) as Record<string, unknown>\n node = {\n slug: item.slug,\n type: item.type,\n title: (cfg.title as string | undefined) ?? '',\n size: item.size ?? 6,\n data: cfg,\n } as WidgetNode\n }\n if (node) out.push({ node, layoutSlug: item.slug })\n }\n // Новые manifest-widgets (которых ещё нет в persisted layout'е).\n for (const [slug, w] of bySlug.entries()) {\n out.push({ node: w, layoutSlug: slug })\n }\n } else {\n // Нет draft'а — рендерим manifest как есть.\n for (const w of manifestWidgets.value) {\n out.push({ node: w, layoutSlug: String((w as Record<string, unknown>).slug ?? '') })\n }\n }\n\n return out\n})\n\nfunction spanFor(w: WidgetNode): number {\n const raw = (w as Record<string, unknown>).size ?? (w as Record<string, unknown>).span\n const s = typeof raw === 'number' ? raw : 12\n return Math.max(1, Math.min(12, s))\n}\n\n// === Toolbar period ===\nconst periods = computed(() => [\n { key: '7d', label: t('admin.dashboard.period.7d', 'За 7 дней') },\n { key: '30d', label: t('admin.dashboard.period.30d', 'За 30 дней') },\n { key: '90d', label: t('admin.dashboard.period.90d', 'За 90 дней') },\n { key: 'all', label: t('admin.dashboard.period.all', 'Всё время') },\n])\nconst selectedPeriod = ref<string>('30d')\n/** Свежие widget data полученные через /dashboard/widgets?period=. */\nconst refreshedWidgets = ref<WidgetNode[] | null>(null)\n\nasync function setPeriod(key: string, close: () => void): Promise<void> {\n selectedPeriod.value = key\n emit('change-period', key)\n close()\n await refetchPeriod()\n}\n\nasync function refetchPeriod(): Promise<void> {\n if (!props.slug) return\n try {\n const { getAdminClient } = await import('../../stores/registry')\n const client = getAdminClient()\n const result = await client.get<{ widgets: WidgetNode[]; period: string }>(\n `/dashboard/widgets?key=${encodeURIComponent(props.slug)}&period=${encodeURIComponent(selectedPeriod.value)}`,\n )\n refreshedWidgets.value = result.widgets\n } catch {\n // silent — оставляем manifest-данные.\n }\n}\n\nconst periodLabel = computed(\n () => periods.value.find((p) => p.key === selectedPeriod.value)?.label ?? t('admin.dashboard.period.label', 'Период'),\n)\n\n// === Edit-mode actions ===\nconst dialogMode = ref<'add' | 'configure' | null>(null)\nconst dialogItem = ref<WidgetLayoutItem | null>(null)\nconst dialogInitialTitle = ref<string>('')\nfunction openAdd(): void {\n dialogMode.value = 'add'\n dialogItem.value = null\n dialogInitialTitle.value = ''\n}\nfunction closeDialog(): void {\n dialogMode.value = null\n}\n\nfunction onEnterEdit(): void {\n dashboardStore.enterEditMode()\n}\nfunction onCancelEdit(): void {\n dashboardStore.cancelEdit()\n}\nasync function onSaveLayout(): Promise<void> {\n await dashboardStore.saveLayout().catch(() => undefined)\n}\n\nfunction onRemoveWidget(layoutSlug: string): void {\n // Если widget есть в draft — удаляем, иначе делаем hidden override.\n const inDraft = dashboardStore.draft.some((it) => it.slug === layoutSlug)\n if (inDraft) {\n dashboardStore.removeWidget(layoutSlug)\n } else {\n // Manifest widget — добавляем как hidden override.\n dashboardStore.addWidget({ slug: layoutSlug, hidden: true })\n }\n}\n\nfunction onConfigureWidget(layoutSlug: string): void {\n ensureDraftReflectsRendered()\n const draftItem = dashboardStore.draft.find((it) => it.slug === layoutSlug) ?? null\n // Для manifest-widget'ов (которые ещё не попали в draft) собираем\n // initial-state из renderedWidgets — там уже посчитанный node.\n const rendered = renderedWidgets.value.find((r) => r.layoutSlug === layoutSlug)\n const node = rendered?.node as Record<string, unknown> | undefined\n dialogItem.value = draftItem ?? {\n slug: layoutSlug,\n type: (node?.type as string | undefined) ?? '',\n size: (node?.size as number | undefined) ?? 6,\n config: {},\n }\n dialogInitialTitle.value = (node?.title as string | undefined) ?? ''\n dialogMode.value = 'configure'\n}\n\nfunction onAddWidget(item: WidgetLayoutItem): void {\n dashboardStore.addWidget(item)\n}\n\nfunction onSaveConfig(patch: Partial<WidgetLayoutItem>): void {\n if (!dialogItem.value) return\n const slug = dialogItem.value.slug\n // Если widget ещё не в draft — добавляем; иначе patch.\n const inDraft = dashboardStore.draft.some((it) => it.slug === slug)\n if (inDraft) {\n // merge config с предыдущим (а не replace).\n const existing = dashboardStore.draft.find((it) => it.slug === slug)\n dashboardStore.updateWidget(slug, {\n ...patch,\n config: { ...(existing?.config ?? {}), ...(patch.config ?? {}) },\n })\n } else {\n dashboardStore.addWidget({\n slug,\n type: dialogItem.value.type,\n ...patch,\n })\n }\n}\n\n// === Drag-reorder (нативный HTML5) ===\nconst dragSourceIdx = ref<number | null>(null)\nfunction onDragStart(idx: number, e: DragEvent): void {\n if (!dashboardStore.editMode) return\n if (e.dataTransfer === null) return\n // Разрешаем drag только если он начался с [data-drag-handle] —\n // иначе пользователь не сможет кликать по контенту виджета (selectable\n // text, ссылки, кнопки) без случайного перетаскивания всей карточки.\n const target = e.target as HTMLElement | null\n if (!target?.closest('[data-drag-handle=\"true\"]')) {\n e.preventDefault()\n return\n }\n dragSourceIdx.value = idx\n e.dataTransfer.effectAllowed = 'move'\n e.dataTransfer.setData('text/plain', String(idx))\n}\nfunction onDragOver(e: DragEvent): void {\n if (dashboardStore.editMode && dragSourceIdx.value !== null) {\n e.preventDefault()\n }\n}\nfunction onDrop(toIdx: number, e: DragEvent): void {\n e.preventDefault()\n if (!dashboardStore.editMode || dragSourceIdx.value === null) return\n // Reorder в store. Если widget не в draft — сначала \"поднимаем\" его\n // из manifest'а, чтобы layout сохранил позицию.\n const sourceIdx = dragSourceIdx.value\n ensureDraftReflectsRendered()\n dashboardStore.moveWidget(sourceIdx, toIdx)\n dragSourceIdx.value = null\n}\n\n/**\n * Перед drag/resize гарантируем, что текущий rendered порядок отражён\n * в store.draft (иначе reorder работает на пустом draft'е и теряет\n * manifest widget'ы).\n */\nfunction ensureDraftReflectsRendered(): void {\n if (dashboardStore.draft.length === renderedWidgets.value.length) return\n const items: WidgetLayoutItem[] = renderedWidgets.value.map(({ node, layoutSlug }, idx) => {\n const existing = dashboardStore.draft.find((it) => it.slug === layoutSlug)\n return {\n slug: layoutSlug,\n size: spanFor(node),\n position: idx,\n hidden: existing?.hidden ?? false,\n type: existing?.type ?? (node as Record<string, unknown>).type as string | undefined,\n config: existing?.config,\n }\n })\n dashboardStore.draft = items\n}\n\n// === Resize via mouse ===\nconst resizing = ref<{ slug: string; startX: number; startSpan: number } | null>(null)\nlet resizeContainerWidth = 0\nfunction onResizeStart(e: MouseEvent, layoutSlug: string, currentSpan: number): void {\n if (!dashboardStore.editMode) return\n e.preventDefault()\n e.stopPropagation()\n ensureDraftReflectsRendered()\n resizing.value = { slug: layoutSlug, startX: e.clientX, startSpan: currentSpan }\n const grid = (e.target as HTMLElement).closest('.admin-dashboard__grid') as HTMLElement | null\n resizeContainerWidth = grid?.getBoundingClientRect().width ?? 1200\n window.addEventListener('mousemove', onResizeMove)\n window.addEventListener('mouseup', onResizeEnd)\n}\nfunction onResizeMove(e: MouseEvent): void {\n if (!resizing.value) return\n const colWidth = resizeContainerWidth / 12\n const delta = Math.round((e.clientX - resizing.value.startX) / colWidth)\n const nextSpan = Math.max(1, Math.min(12, resizing.value.startSpan + delta))\n const item = dashboardStore.draft.find((it) => it.slug === resizing.value!.slug)\n if (item && item.size !== nextSpan) {\n dashboardStore.updateWidget(resizing.value.slug, { size: nextSpan })\n }\n}\nfunction onResizeEnd(): void {\n resizing.value = null\n window.removeEventListener('mousemove', onResizeMove)\n window.removeEventListener('mouseup', onResizeEnd)\n}\n\nfunction onExport(): void {\n emit('export')\n}\n</script>\n\n<template>\n <section class=\"admin-page admin-dashboard\">\n <header class=\"admin-page__hd\">\n <div class=\"admin-page__title-wrap\">\n <h1 class=\"admin-page__title\">{{ resolvedTitle }}</h1>\n <div v-if=\"resolvedSubtitle\" class=\"admin-page__count\">\n {{ resolvedSubtitle }}\n </div>\n </div>\n <div class=\"admin-page__actions\">\n <slot name=\"actions\" />\n\n <UidMenu>\n <template #trigger>\n <UidButton variant=\"ghost\" size=\"md\">\n <template #prepend><UidIcon :icon=\"Calendar\" :size=\"14\" /></template>\n {{ periodLabel }}\n <template #append><UidIcon :icon=\"ChevronDown\" :size=\"14\" /></template>\n </UidButton>\n </template>\n <UidMenuItem\n v-for=\"p in periods\"\n :key=\"p.key\"\n @click=\"setPeriod(p.key, () => undefined)\"\n >\n {{ p.label }}\n </UidMenuItem>\n </UidMenu>\n\n <UidButton variant=\"secondary\" size=\"md\" @click=\"onExport\">\n <template #prepend><UidIcon :icon=\"Download\" :size=\"14\" /></template>\n Export\n </UidButton>\n\n <!-- Edit-mode toggle -->\n <template v-if=\"!dashboardStore.editMode\">\n <UidButton variant=\"secondary\" size=\"md\" @click=\"onEnterEdit\">\n <template #prepend><UidIcon :icon=\"Pencil\" :size=\"14\" /></template>\n Редактировать\n </UidButton>\n </template>\n <template v-else>\n <UidButton variant=\"secondary\" size=\"md\" @click=\"openAdd\">\n <template #prepend><UidIcon :icon=\"Plus\" :size=\"14\" /></template>\n Add widget\n </UidButton>\n <UidButton variant=\"ghost\" size=\"md\" @click=\"onCancelEdit\">\n <template #prepend><UidIcon :icon=\"RotateCcw\" :size=\"14\" /></template>\n Отмена\n </UidButton>\n <UidButton\n variant=\"primary\"\n size=\"md\"\n :loading=\"dashboardStore.saving\"\n :disabled=\"dashboardStore.saving\"\n @click=\"onSaveLayout\"\n >\n Сохранить\n </UidButton>\n </template>\n </div>\n </header>\n\n <div\n :class=\"[\n 'admin-dashboard__grid',\n { 'admin-dashboard__grid--editing': dashboardStore.editMode },\n ]\"\n >\n <div\n v-for=\"(item, idx) in renderedWidgets\"\n :key=\"item.layoutSlug\"\n class=\"admin-dashboard__cell\"\n :class=\"{ 'admin-dashboard__cell--editing': dashboardStore.editMode }\"\n :draggable=\"dashboardStore.editMode\"\n :style=\"{ gridColumn: `span ${spanFor(item.node)} / span ${spanFor(item.node)}` }\"\n @dragstart=\"onDragStart(idx, $event)\"\n @dragover=\"onDragOver\"\n @drop=\"onDrop(idx, $event)\"\n >\n <WidgetRenderer :node=\"item.node\" />\n <WidgetActionsOverlay\n v-if=\"dashboardStore.editMode\"\n @configure=\"onConfigureWidget(item.layoutSlug)\"\n @remove=\"onRemoveWidget(item.layoutSlug)\"\n />\n <span\n v-if=\"dashboardStore.editMode\"\n class=\"admin-dashboard__resize\"\n aria-label=\"Изменить размер\"\n @mousedown=\"onResizeStart($event, item.layoutSlug, spanFor(item.node))\"\n />\n </div>\n </div>\n\n <WidgetConfigDialog\n :open=\"dialogMode !== null\"\n :mode=\"dialogMode ?? 'add'\"\n :item=\"dialogItem\"\n :initial-title=\"dialogInitialTitle\"\n @close=\"closeDialog\"\n @add=\"onAddWidget\"\n @save=\"onSaveConfig\"\n />\n </section>\n</template>\n\n<style>\n.admin-dashboard__grid {\n display: grid;\n grid-template-columns: repeat(12, minmax(0, 1fr));\n gap: var(--uid-space-md);\n}\n.admin-dashboard__grid--editing .admin-dashboard__cell {\n outline: 1px dashed transparent;\n transition: outline-color 120ms ease;\n}\n.admin-dashboard__grid--editing .admin-dashboard__cell:hover {\n outline-color: var(--uid-accent);\n}\n.admin-dashboard__cell {\n position: relative;\n min-width: 0;\n}\n/*\n * cursor: default на cell — дёргать карточку можно только за [☰]-handle\n * (см. WidgetActionsOverlay). Это позволяет в edit-mode по-прежнему\n * взаимодействовать с интерактивными элементами внутри виджета.\n */\n.admin-dashboard__resize {\n position: absolute;\n bottom: 4px;\n right: 4px;\n width: 14px;\n height: 14px;\n cursor: nwse-resize;\n background:\n linear-gradient(135deg, transparent 0 50%, var(--uid-text-tertiary) 50% 60%, transparent 60% 70%, var(--uid-text-tertiary) 70% 80%, transparent 80%);\n z-index: 4;\n}\n</style>\n","<script setup lang=\"ts\">\n/**\n * Default home-страница admin'а — показывает первый зарегистрированный\n * Dashboard (host регистрирует через `Admin::screens([DashboardScreen])`),\n * иначе fallback на welcome-карточку со списком Resource'ов.\n *\n * Host может полностью переопределить через\n * `createAdminApp({ pages: { home: MyHome } })`.\n */\nimport { computed, watch } from 'vue'\nimport { useRouter } from 'vue-router'\nimport { UidCard } from '@dskripchenko/ui'\nimport { useManifestStore } from '../stores/manifest'\nimport { useAuthStore } from '../stores/auth'\nimport { useDashboardStore } from '../stores/dashboard'\nimport DashboardPage from './dashboard/DashboardPage.vue'\n\ninterface DashboardManifest {\n slug: string\n label?: string\n description?: string | null\n widgets: unknown[]\n}\n\nconst manifest = useManifestStore()\nconst auth = useAuthStore()\nconst router = useRouter()\n\nconst userName = computed(() => auth.user?.name ?? '')\nconst resources = computed(() => manifest.manifest?.resources ?? [])\n\nconst dashboards = computed<DashboardManifest[]>(\n () => (manifest.manifest?.dashboards ?? []) as DashboardManifest[],\n)\nconst primaryDashboardSlug = computed<string | null>(\n () => dashboards.value[0]?.slug ?? null,\n)\n\n// Загружаем persisted layout из dashboard store на mount/смену slug.\nconst dashboardStore = useDashboardStore()\nwatch(\n primaryDashboardSlug,\n (slug) => {\n if (slug) void dashboardStore.openDashboard(slug)\n },\n { immediate: true },\n)\n</script>\n\n<template>\n <DashboardPage\n v-if=\"primaryDashboardSlug\"\n :slug=\"primaryDashboardSlug\"\n />\n\n <div v-else class=\"admin-home\">\n <UidCard padding=\"lg\" class=\"admin-home__hero\">\n <h1 class=\"admin-home__title\">Добро пожаловать{{ userName ? ', ' + userName : '' }}</h1>\n <p class=\"admin-home__lead\">\n Админ-панель готова. Зарегистрируйте DashboardScreen чтобы увидеть widget-grid здесь,\n либо переходите к ресурсам ниже.\n </p>\n </UidCard>\n\n <section v-if=\"resources.length\" class=\"admin-home__resources\">\n <h2 class=\"admin-home__heading\">Ресурсы</h2>\n <ul class=\"admin-home__grid\">\n <li v-for=\"r in resources\" :key=\"r.slug\">\n <button\n type=\"button\"\n class=\"admin-home__card\"\n @click=\"router.push({ name: `admin.resource.${r.slug}.index` })\"\n >\n <span class=\"admin-home__card-label\">{{ r.label }}</span>\n <span class=\"admin-home__card-slug\">{{ r.slug }}</span>\n </button>\n </li>\n </ul>\n </section>\n </div>\n</template>\n\n<style>\n.admin-home {\n display: flex;\n flex-direction: column;\n gap: var(--uid-space-lg);\n padding: var(--uid-space-md);\n}\n.admin-home__title {\n font-size: var(--uid-font-size-2xl);\n font-weight: var(--uid-font-weight-bold);\n margin: 0 0 var(--uid-space-sm);\n}\n.admin-home__lead {\n color: var(--uid-text-secondary);\n margin: 0;\n}\n.admin-home__heading {\n font-size: var(--uid-font-size-lg);\n font-weight: var(--uid-font-weight-semibold);\n margin: 0 0 var(--uid-space-sm);\n}\n.admin-home__grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));\n gap: var(--uid-space-sm);\n list-style: none;\n padding: 0;\n margin: 0;\n}\n.admin-home__card {\n display: flex;\n flex-direction: column;\n gap: var(--uid-space-2xs);\n padding: var(--uid-space-md);\n border: 1px solid var(--uid-border-subtle);\n border-radius: var(--uid-radius-md);\n background: var(--uid-surface-raised);\n text-align: left;\n cursor: pointer;\n transition: border-color 0.15s ease, transform 0.15s ease;\n}\n.admin-home__card:hover {\n border-color: var(--uid-accent);\n transform: translateY(-1px);\n}\n.admin-home__card-label {\n font-weight: var(--uid-font-weight-medium);\n}\n.admin-home__card-slug {\n font-size: var(--uid-font-size-xs);\n color: var(--uid-text-tertiary);\n}\n</style>\n","<script setup lang=\"ts\">\n/**\n * 403 fallback. Host может переопределить через createAdminApp({ pages: { forbidden } }).\n */\nimport { UidCard, UidButton } from '@dskripchenko/ui'\nimport { useRouter } from 'vue-router'\n\nconst router = useRouter()\n</script>\n\n<template>\n <div class=\"admin-status-page\">\n <UidCard padding=\"lg\" class=\"admin-status-page__card\">\n <h1 class=\"admin-status-page__code\">403</h1>\n <p class=\"admin-status-page__message\">Доступ запрещён.</p>\n <UidButton variant=\"ghost\" @click=\"router.replace({ name: 'admin.home' })\">\n На главную\n </UidButton>\n </UidCard>\n </div>\n</template>\n\n<style>\n.admin-status-page {\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 60vh;\n padding: var(--uid-space-lg);\n}\n.admin-status-page__card {\n text-align: center;\n max-width: 480px;\n}\n.admin-status-page__code {\n font-size: 64px;\n font-weight: var(--uid-font-weight-bold);\n margin: 0 0 var(--uid-space-sm);\n color: var(--uid-text-secondary);\n}\n.admin-status-page__message {\n margin: 0 0 var(--uid-space-md);\n color: var(--uid-text-secondary);\n}\n</style>\n","<script setup lang=\"ts\">\n/**\n * 404 fallback. Host может переопределить через createAdminApp({ pages: { notFound } }).\n */\nimport { UidCard, UidButton } from '@dskripchenko/ui'\nimport { useRouter } from 'vue-router'\n\nconst router = useRouter()\n</script>\n\n<template>\n <div class=\"admin-status-page\">\n <UidCard padding=\"lg\" class=\"admin-status-page__card\">\n <h1 class=\"admin-status-page__code\">404</h1>\n <p class=\"admin-status-page__message\">Страница не найдена.</p>\n <UidButton variant=\"ghost\" @click=\"router.replace({ name: 'admin.home' })\">\n На главную\n </UidButton>\n </UidCard>\n </div>\n</template>\n","<script setup lang=\"ts\">\n/**\n * Default страница для admin.settings.{slug} роутов.\n *\n * Загружает settings-meta из manifest'а и рендерит fields через LayoutRenderer\n * с form-state поверх SettingsApiClient. Host'ы переопределяют через\n * createAdminApp({ pages: { settings: MySettings } }) если нужна более\n * специфичная UX (например, side-tab навигация по Settings-классам).\n */\nimport { computed } from 'vue'\nimport { useRoute } from 'vue-router'\nimport { UidCard } from '@dskripchenko/ui'\nimport { useManifestStore } from '../stores/manifest'\n\nconst route = useRoute()\nconst manifest = useManifestStore()\n\nconst slug = computed(() => String(route.params.slug ?? ''))\nconst meta = computed(() => manifest.manifest?.settings?.find((s) => s.slug === slug.value) ?? null)\n</script>\n\n<template>\n <div class=\"admin-settings-page\">\n <UidCard padding=\"lg\">\n <h1 class=\"admin-settings-page__title\">{{ meta?.label ?? slug }}</h1>\n <p v-if=\"!meta\" class=\"admin-settings-page__hint\">\n Settings «{{ slug }}» не найдено в manifest'е.\n </p>\n <pre v-else class=\"admin-settings-page__debug\">{{ JSON.stringify(meta.fields, null, 2) }}</pre>\n </UidCard>\n </div>\n</template>\n\n<style>\n.admin-settings-page {\n padding: var(--uid-space-md);\n}\n.admin-settings-page__title {\n font-size: var(--uid-font-size-xl);\n font-weight: var(--uid-font-weight-semibold);\n margin: 0 0 var(--uid-space-sm);\n}\n.admin-settings-page__debug {\n background: var(--uid-surface-raised);\n border: 1px solid var(--uid-border-subtle);\n padding: var(--uid-space-sm);\n border-radius: var(--uid-radius-sm);\n font-family: var(--uid-font-mono);\n font-size: var(--uid-font-size-xs);\n overflow: auto;\n max-height: 60vh;\n}\n.admin-settings-page__hint {\n color: var(--uid-text-secondary);\n}\n</style>\n","<script setup lang=\"ts\">\n/**\n * Заглушка для произвольных Screen-роутов из manifest'а.\n * Host'ы переопределяют через createAdminApp({ pages: { screen: MyScreen } })\n * и кастомным компонентом рендерят `route.params.slug` через любой template.\n */\nimport { computed } from 'vue'\nimport { useRoute } from 'vue-router'\nimport { UidCard } from '@dskripchenko/ui'\n\nconst route = useRoute()\nconst slug = computed(() => String(route.params.slug ?? ''))\nconst title = computed(() => String(route.meta?.title ?? slug.value))\n</script>\n\n<template>\n <div class=\"admin-status-page\">\n <UidCard padding=\"lg\" class=\"admin-status-page__card\">\n <h1 class=\"admin-status-page__title\">{{ title }}</h1>\n <p class=\"admin-status-page__hint\">\n Это заглушка для screen «{{ slug }}». Передайте свой компонент через\n <code>createAdminApp({{ '{' }} pages: {{ '{' }} screen: MyScreen {{ '}' }} {{ '}' }})</code>.\n </p>\n </UidCard>\n </div>\n</template>\n\n<style>\n.admin-status-page__title {\n font-size: var(--uid-font-size-xl);\n font-weight: var(--uid-font-weight-semibold);\n margin: 0 0 var(--uid-space-sm);\n}\n.admin-status-page__hint {\n margin: 0;\n color: var(--uid-text-secondary);\n font-size: var(--uid-font-size-sm);\n}\n</style>\n","<script setup lang=\"ts\">\n/**\n * LoginForm — email/password/remember поверх UidInput/UidButton/UidCheckbox/\n * UidAlert. Архитектура auth-card по docs/design_handoff_laravel_admin/\n * screens-secondary.jsx (LoginScreen).\n */\nimport { computed, ref } from 'vue'\nimport { UidAlert, UidButton, UidCheckbox, UidInput } from '@dskripchenko/ui'\nimport { useAuthStore } from '../../stores/auth'\nimport { ApiError, NetworkError, ValidationError } from '../../api/errors'\n\ninterface Props {\n /** URL «Забыли пароль?» — если задан, показывается link справа от remember. */\n forgotUrl?: string | null\n /** Текст SSO-ссылки или null чтобы скрыть. */\n ssoLinkLabel?: string | null\n ssoUrl?: string | null\n}\n\nwithDefaults(defineProps<Props>(), {\n forgotUrl: null,\n ssoLinkLabel: null,\n ssoUrl: null,\n})\n\nconst emit = defineEmits<{\n success: [result: 'authenticated' | 'two_factor_required']\n}>()\n\nconst auth = useAuthStore()\n\nconst email = ref('')\nconst password = ref('')\nconst remember = ref(false)\n\nconst submitting = ref(false)\nconst generalError = ref<string | null>(null)\nconst fieldErrors = ref<Record<string, string[]>>({})\n\nconst emailError = computed<string | undefined>(() => fieldErrors.value.email?.[0])\nconst passwordError = computed<string | undefined>(() => fieldErrors.value.password?.[0])\n\nasync function submit(): Promise<void> {\n if (submitting.value) return\n submitting.value = true\n generalError.value = null\n fieldErrors.value = {}\n\n try {\n const result = await auth.login({\n email: email.value,\n password: password.value,\n remember: remember.value,\n })\n emit('success', result)\n } catch (err) {\n if (err instanceof ValidationError) {\n fieldErrors.value = err.fields\n generalError.value = err.firstFieldMessage()\n } else if (err instanceof NetworkError) {\n generalError.value = 'Нет соединения с сервером'\n } else if (err instanceof ApiError) {\n generalError.value = err.message || 'Не удалось войти'\n } else {\n generalError.value = (err as Error).message\n }\n } finally {\n submitting.value = false\n }\n}\n</script>\n\n<template>\n <form class=\"admin-auth-card__bd\" novalidate @submit.prevent=\"submit\">\n <UidAlert\n v-if=\"generalError\"\n variant=\"danger\"\n class=\"admin-auth-card__alert\"\n role=\"alert\"\n >\n {{ generalError }}\n </UidAlert>\n\n <UidInput\n v-model=\"email\"\n type=\"email\"\n label=\"Email\"\n placeholder=\"you@company.com\"\n autocomplete=\"username\"\n :required=\"true\"\n :disabled=\"submitting\"\n :error=\"emailError\"\n name=\"email\"\n />\n\n <UidInput\n v-model=\"password\"\n type=\"password\"\n label=\"Пароль\"\n autocomplete=\"current-password\"\n :required=\"true\"\n :disabled=\"submitting\"\n :error=\"passwordError\"\n name=\"password\"\n />\n\n <div class=\"admin-auth-card__row\">\n <UidCheckbox v-model=\"remember\" :disabled=\"submitting\">\n Запомнить меня\n </UidCheckbox>\n <a v-if=\"forgotUrl\" :href=\"forgotUrl\" class=\"admin-auth-card__link\">\n Забыли пароль?\n </a>\n </div>\n\n <UidButton\n type=\"submit\"\n variant=\"primary\"\n size=\"lg\"\n :loading=\"submitting\"\n :disabled=\"submitting\"\n >\n {{ submitting ? 'Вход…' : 'Войти' }}\n </UidButton>\n\n <div\n v-if=\"ssoLinkLabel && ssoUrl\"\n style=\"text-align: center; font-size: var(--uid-font-size-xs); color: var(--uid-text-secondary); padding-top: 4px;\"\n >\n или войдите через\n <a :href=\"ssoUrl\" class=\"admin-auth-card__link\">{{ ssoLinkLabel }}</a>\n </div>\n </form>\n</template>\n","<script setup lang=\"ts\">\n/**\n * 2FA-форма: 6-cell mono TOTP-input + alt recovery-code.\n *\n * Эталон — docs/design_handoff_laravel_admin/screens-secondary.jsx (TwoFactor):\n * 6 input'ов 44×52, IBM Plex Mono 22px, при заполнении одного — фокус\n * автопереходит на следующий, paste-event раскладывает 6 цифр сразу.\n */\nimport { computed, nextTick, ref } from 'vue'\nimport { UidAlert, UidButton, UidInput } from '@dskripchenko/ui'\nimport { useAuthStore } from '../../stores/auth'\nimport { ApiError, NetworkError, ValidationError } from '../../api/errors'\n\nconst emit = defineEmits<{\n success: []\n cancel: []\n}>()\n\nconst auth = useAuthStore()\n\nconst mode = ref<'totp' | 'recovery'>('totp')\nconst cells = ref<string[]>(['', '', '', '', '', ''])\nconst recoveryCode = ref('')\nconst cellRefs = ref<HTMLInputElement[]>([])\n\nconst submitting = ref(false)\nconst generalError = ref<string | null>(null)\nconst remaining = ref<number | null>(null)\n\nconst totpCode = computed(() => cells.value.join(''))\nconst isValid = computed(() => {\n if (mode.value === 'totp') return totpCode.value.length === 6\n return recoveryCode.value.trim().length > 0\n})\n\nfunction setCellRef(idx: number, el: Element | null): void {\n if (el instanceof HTMLInputElement) cellRefs.value[idx] = el\n}\n\nfunction onCellInput(idx: number, event: Event): void {\n const target = event.target as HTMLInputElement\n // Только цифры; обрезаем до 1 символа.\n const digit = target.value.replace(/\\D/g, '').slice(-1)\n cells.value[idx] = digit\n target.value = digit\n if (digit && idx < cells.value.length - 1) {\n void nextTick(() => cellRefs.value[idx + 1]?.focus())\n }\n if (totpCode.value.length === cells.value.length) {\n void submit()\n }\n}\n\nfunction onCellKeydown(idx: number, event: KeyboardEvent): void {\n if (event.key === 'Backspace' && !cells.value[idx] && idx > 0) {\n void nextTick(() => cellRefs.value[idx - 1]?.focus())\n } else if (event.key === 'ArrowLeft' && idx > 0) {\n cellRefs.value[idx - 1]?.focus()\n event.preventDefault()\n } else if (event.key === 'ArrowRight' && idx < cells.value.length - 1) {\n cellRefs.value[idx + 1]?.focus()\n event.preventDefault()\n }\n}\n\nfunction onPaste(event: ClipboardEvent): void {\n const pasted = event.clipboardData?.getData('text') ?? ''\n const digits = pasted.replace(/\\D/g, '').slice(0, cells.value.length)\n if (digits.length === 0) return\n event.preventDefault()\n for (let i = 0; i < cells.value.length; i++) {\n cells.value[i] = digits[i] ?? ''\n }\n void nextTick(() => {\n cellRefs.value[Math.min(digits.length, cells.value.length - 1)]?.focus()\n if (digits.length === cells.value.length) void submit()\n })\n}\n\nasync function submit(): Promise<void> {\n if (submitting.value || !isValid.value) return\n submitting.value = true\n generalError.value = null\n\n try {\n if (mode.value === 'totp') {\n await auth.twoFactorChallenge(totpCode.value)\n } else {\n const res = await auth.twoFactorRecovery(recoveryCode.value.trim())\n remaining.value = res.remaining\n }\n emit('success')\n } catch (err) {\n if (err instanceof ValidationError) {\n generalError.value = err.firstFieldMessage() ?? 'Неверный код'\n } else if (err instanceof NetworkError) {\n generalError.value = 'Нет соединения с сервером'\n } else if (err instanceof ApiError) {\n generalError.value = err.message || 'Не удалось проверить код'\n } else {\n generalError.value = (err as Error).message\n }\n } finally {\n submitting.value = false\n }\n}\n\nfunction cancel(): void {\n auth.cancelChallenge()\n emit('cancel')\n}\n\nfunction switchMode(): void {\n mode.value = mode.value === 'totp' ? 'recovery' : 'totp'\n generalError.value = null\n}\n</script>\n\n<template>\n <form class=\"admin-auth-card__bd\" novalidate @submit.prevent=\"submit\">\n <UidAlert\n v-if=\"generalError\"\n variant=\"danger\"\n class=\"admin-auth-card__alert\"\n role=\"alert\"\n >\n {{ generalError }}\n </UidAlert>\n <UidAlert\n v-if=\"remaining !== null\"\n variant=\"info\"\n class=\"admin-auth-card__alert\"\n role=\"status\"\n >\n Использован recovery-код. Осталось: {{ remaining }}\n </UidAlert>\n\n <div v-if=\"mode === 'totp'\" class=\"admin-code-input\" @paste=\"onPaste\">\n <input\n v-for=\"(_, idx) in cells\"\n :key=\"idx\"\n :ref=\"(el) => setCellRef(idx, el as Element | null)\"\n :value=\"cells[idx]\"\n type=\"text\"\n inputmode=\"numeric\"\n autocomplete=\"one-time-code\"\n maxlength=\"1\"\n :disabled=\"submitting\"\n :aria-label=\"`Цифра ${idx + 1}`\"\n @input=\"onCellInput(idx, $event)\"\n @keydown=\"onCellKeydown(idx, $event)\"\n />\n </div>\n\n <UidInput\n v-else\n v-model=\"recoveryCode\"\n type=\"text\"\n label=\"Recovery-код\"\n autocomplete=\"one-time-code\"\n :disabled=\"submitting\"\n name=\"recovery-code\"\n />\n\n <UidButton\n type=\"submit\"\n variant=\"primary\"\n size=\"lg\"\n :loading=\"submitting\"\n :disabled=\"submitting || !isValid\"\n >\n {{ submitting ? 'Проверка…' : 'Подтвердить' }}\n </UidButton>\n\n <div class=\"admin-auth-card__row\">\n <button type=\"button\" class=\"admin-auth-card__link\" @click=\"switchMode\">\n <template v-if=\"mode === 'totp'\">Использовать recovery-код</template>\n <template v-else>Вернуться к коду из приложения</template>\n </button>\n <button type=\"button\" class=\"admin-auth-card__link\" @click=\"cancel\">\n Отмена\n </button>\n </div>\n </form>\n</template>\n","<script setup lang=\"ts\">\n/**\n * LoginPage поверх UID design handoff: centered auth-card 400/440 px на\n * `--uid-surface-base`-фоне с corner-actions (theme + locale toggles).\n *\n * Композиция: LoginForm либо TwoFactorForm в зависимости от\n * auth.isChallengePending. Редирект на main завязан на watch\n * (auth.isAuthenticated) — это переживает unmount форм при смене ветки.\n *\n * `?redirect`-query учитывает только относительные пути (защита от\n * open-redirect).\n */\nimport { onMounted, watch } from 'vue'\nimport { useRouter, useRoute } from 'vue-router'\nimport { UidCard } from '@dskripchenko/ui'\nimport { useAuthStore } from '../../stores/auth'\nimport LoginForm from './LoginForm.vue'\nimport TwoFactorForm from './TwoFactorForm.vue'\nimport ThemeToggle from '../shell/widgets/ThemeToggle.vue'\nimport LocaleSwitcher from '../shell/widgets/LocaleSwitcher.vue'\nimport BrandLogo from '../shell/BrandLogo.vue'\n\ninterface Props {\n brandName?: string\n /**\n * Custom mark (если задан — рендерится вместо BrandLogo). Полезно\n * host'у с собственным брендом.\n */\n brandMark?: string | null\n brandLogo?: string | null\n homeRouteName?: string\n redirectQueryKey?: string\n /** URL «Забыли пароль?» — пробрасывается в LoginForm. */\n forgotUrl?: string | null\n /** SSO-link (label + url) — пробрасывается в LoginForm. */\n ssoLinkLabel?: string | null\n ssoUrl?: string | null\n /** Показывать ли theme/locale toggle'ы в углу. */\n showCornerActions?: boolean\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n brandName: 'Laravel Admin',\n brandMark: null,\n brandLogo: null,\n homeRouteName: 'admin.home',\n redirectQueryKey: 'redirect',\n forgotUrl: null,\n ssoLinkLabel: null,\n ssoUrl: null,\n showCornerActions: true,\n})\n\nconst auth = useAuthStore()\nconst router = useRouter()\nconst route = useRoute()\n\nasync function redirectToHome(): Promise<void> {\n const target = route.query[props.redirectQueryKey]\n if (typeof target === 'string' && target.length > 0 && target.startsWith('/')) {\n await router.push(target)\n return\n }\n await router.push({ name: props.homeRouteName })\n}\n\nwatch(\n () => auth.isAuthenticated,\n (next) => {\n if (next) void redirectToHome()\n },\n)\nonMounted(() => {\n if (auth.isAuthenticated) void redirectToHome()\n})\n</script>\n\n<template>\n <div class=\"admin-auth-page\">\n <div v-if=\"showCornerActions\" class=\"admin-auth-page__corner\">\n <ThemeToggle />\n <LocaleSwitcher />\n </div>\n\n <UidCard\n :class=\"['admin-auth-card', auth.isChallengePending ? 'admin-auth-card--wide' : '']\"\n padding=\"none\"\n >\n <div class=\"admin-auth-card__hd\">\n <div\n :class=\"['admin-auth-card__logo', auth.isChallengePending ? 'admin-auth-card__logo--accent' : '']\"\n >\n <img v-if=\"brandLogo && !auth.isChallengePending\" :src=\"brandLogo\" :alt=\"brandName\" />\n <span v-else-if=\"auth.isChallengePending\" aria-hidden=\"true\">🛡</span>\n <span v-else-if=\"brandMark\">{{ brandMark }}</span>\n <BrandLogo v-else :size=\"40\" />\n </div>\n <div class=\"admin-auth-card__title\">\n <template v-if=\"auth.isChallengePending\">Двухфакторная проверка</template>\n <template v-else>{{ brandName }}</template>\n </div>\n <div class=\"admin-auth-card__sub\">\n <template v-if=\"auth.isChallengePending\">\n Введите 6-значный код из приложения-аутентификатора\n </template>\n <template v-else>Войдите, чтобы продолжить работу</template>\n </div>\n </div>\n\n <TwoFactorForm\n v-if=\"auth.isChallengePending\"\n @success=\"() => undefined\"\n @cancel=\"() => undefined\"\n />\n <LoginForm\n v-else\n :forgot-url=\"forgotUrl\"\n :sso-link-label=\"ssoLinkLabel\"\n :sso-url=\"ssoUrl\"\n @success=\"() => undefined\"\n />\n </UidCard>\n </div>\n</template>\n","<script setup lang=\"ts\">\n/**\n * ForgotPasswordPage — простой email-input + submit.\n * Backend: POST /auth/forgotPassword body {email} → отправляет письмо.\n */\nimport { ref } from 'vue'\nimport { useRouter } from 'vue-router'\nimport { Mail } from 'lucide-vue-next'\nimport { UidButton, UidCard, UidIcon, UidInput } from '@dskripchenko/ui'\nimport { adminToast } from '../../stores/toast'\nimport BrandLogo from '../shell/BrandLogo.vue'\n\ninterface Props {\n brandName?: string\n loginRouteName?: string\n}\nwithDefaults(defineProps<Props>(), {\n brandName: 'Laravel Admin',\n loginRouteName: 'admin.login',\n})\n\nconst router = useRouter()\nconst email = ref<string>('')\nconst submitted = ref<boolean>(false)\nconst busy = ref<boolean>(false)\n\nasync function submit(): Promise<void> {\n if (email.value.trim() === '') {\n adminToast.error('Введите email.')\n return\n }\n busy.value = true\n try {\n const { getAdminClient } = await import('../../stores/registry')\n const client = getAdminClient()\n await client.post('/auth/forgotPassword', { email: email.value.trim() })\n submitted.value = true\n } catch {\n // Backend для безопасности не палит существование email — отображаем\n // success в любом случае.\n submitted.value = true\n } finally {\n busy.value = false\n }\n}\n</script>\n\n<template>\n <div class=\"admin-auth-page\">\n <UidCard padding=\"none\" class=\"admin-auth-card\">\n <div class=\"admin-auth-card__hd\">\n <div class=\"admin-auth-card__logo\">\n <BrandLogo :size=\"40\" />\n </div>\n <div class=\"admin-auth-card__title\">Восстановление пароля</div>\n <div class=\"admin-auth-card__sub\">\n {{ submitted\n ? 'Если такой email зарегистрирован — мы отправили письмо со ссылкой на сброс.'\n : 'Введите email — отправим ссылку для сброса пароля.' }}\n </div>\n </div>\n <div class=\"admin-auth-card__body\">\n <form v-if=\"!submitted\" @submit.prevent=\"submit\">\n <UidInput\n v-model=\"email\"\n type=\"email\"\n placeholder=\"you@example.com\"\n autocomplete=\"email\"\n required\n />\n <UidButton\n type=\"submit\"\n variant=\"primary\"\n class=\"admin-auth-card__submit\"\n :loading=\"busy\"\n >\n <template #prepend><UidIcon :icon=\"Mail\" :size=\"14\" /></template>\n Отправить ссылку\n </UidButton>\n </form>\n <UidButton\n variant=\"ghost\"\n class=\"admin-auth-card__back\"\n @click=\"router.push({ name: loginRouteName })\"\n >\n ← Назад ко входу\n </UidButton>\n </div>\n </UidCard>\n </div>\n</template>\n\n<style>\n.admin-auth-card__submit { width: 100%; margin-top: var(--uid-space-sm); }\n.admin-auth-card__back { width: 100%; margin-top: var(--uid-space-sm); }\n</style>\n","<script setup lang=\"ts\">\n/**\n * ResetPasswordPage — форма сброса пароля по token + email из ссылки в письме.\n * URL: /admin/reset-password?token=...&email=... (параметры из query).\n *\n * Backend: POST /auth/resetPassword {token, email, password, password_confirmation}.\n */\nimport { computed, ref } from 'vue'\nimport { useRouter, useRoute } from 'vue-router'\nimport { Check } from 'lucide-vue-next'\nimport { UidButton, UidCard, UidIcon, UidInput } from '@dskripchenko/ui'\nimport { adminToast } from '../../stores/toast'\nimport BrandLogo from '../shell/BrandLogo.vue'\n\ninterface Props {\n loginRouteName?: string\n}\nconst props = withDefaults(defineProps<Props>(), {\n loginRouteName: 'admin.login',\n})\n\nconst router = useRouter()\nconst route = useRoute()\n\nconst token = computed<string>(() => String(route.query.token ?? ''))\nconst email = ref<string>(String(route.query.email ?? ''))\nconst password = ref<string>('')\nconst confirm = ref<string>('')\nconst busy = ref<boolean>(false)\nconst error = ref<string>('')\n\nasync function submit(): Promise<void> {\n error.value = ''\n if (password.value.length < 8) {\n error.value = 'Пароль должен быть не менее 8 символов.'\n return\n }\n if (password.value !== confirm.value) {\n error.value = 'Пароли не совпадают.'\n return\n }\n busy.value = true\n try {\n const { getAdminClient } = await import('../../stores/registry')\n const client = getAdminClient()\n await client.post('/auth/resetPassword', {\n token: token.value,\n email: email.value,\n password: password.value,\n password_confirmation: confirm.value,\n })\n adminToast.success('Пароль обновлён. Войдите с новым паролем.')\n await router.push({ name: props.loginRouteName })\n } catch {\n error.value = 'Не удалось сбросить пароль. Возможно, ссылка устарела.'\n } finally {\n busy.value = false\n }\n}\n</script>\n\n<template>\n <div class=\"admin-auth-page\">\n <UidCard padding=\"none\" class=\"admin-auth-card\">\n <div class=\"admin-auth-card__hd\">\n <div class=\"admin-auth-card__logo\">\n <BrandLogo :size=\"40\" />\n </div>\n <div class=\"admin-auth-card__title\">Новый пароль</div>\n <div class=\"admin-auth-card__sub\">Задайте новый пароль для своего аккаунта.</div>\n </div>\n <div class=\"admin-auth-card__body\">\n <form @submit.prevent=\"submit\">\n <UidInput v-model=\"email\" type=\"email\" placeholder=\"email\" required />\n <UidInput\n v-model=\"password\"\n type=\"password\"\n placeholder=\"Новый пароль (мин. 8)\"\n autocomplete=\"new-password\"\n required\n />\n <UidInput\n v-model=\"confirm\"\n type=\"password\"\n placeholder=\"Повторите пароль\"\n autocomplete=\"new-password\"\n required\n />\n <p v-if=\"error\" class=\"admin-auth-card__error\">{{ error }}</p>\n <UidButton\n type=\"submit\"\n variant=\"primary\"\n class=\"admin-auth-card__submit\"\n :loading=\"busy\"\n >\n <template #prepend><UidIcon :icon=\"Check\" :size=\"14\" /></template>\n Сохранить пароль\n </UidButton>\n </form>\n </div>\n </UidCard>\n </div>\n</template>\n\n<style>\n.admin-auth-card__error {\n color: var(--uid-color-danger, #dc2626);\n font-size: 13px;\n margin: var(--uid-space-xs) 0 0;\n}\n</style>\n","/**\n * useResourceIndexStore — list-page state для одного Resource'а.\n *\n * Поддерживает:\n * - items + pagination meta из envelope payload\n * - filters (typed Record<string, unknown>) — отправляются как query\n * - sort (key + direction)\n * - selection (Set<row-id>) для bulk-actions; tri-state header-checkbox\n * - loading/error состояния (UI рендерит UidSkeleton/UidErrorState)\n *\n * Один store-instance переиспользуется на разных Resource-страницах через\n * `useResourceIndexStore(slug)` с явным `setSlug` — это даёт чистый reset\n * между resource'ами.\n */\n\nimport { defineStore } from 'pinia'\nimport { computed, ref } from 'vue'\nimport { getAdminClient } from './registry'\n\nexport interface IndexMeta {\n page: number\n per_page: number\n total: number\n last_page: number\n}\n\nexport type SortDirection = 'asc' | 'desc' | null\n\nexport interface IndexParams {\n page?: number\n per_page?: number\n sort?: string | null\n direction?: SortDirection\n search?: string | null\n filters?: Record<string, unknown>\n}\n\ninterface ListResponse {\n data: Array<Record<string, unknown>>\n meta: IndexMeta\n}\n\nconst DEFAULT_META: IndexMeta = { page: 1, per_page: 20, total: 0, last_page: 1 }\n\nexport const useResourceIndexStore = defineStore('admin-resource-index', () => {\n /** Текущий resource-slug (urls/users/posts/etc). */\n const slug = ref<string | null>(null)\n\n const items = ref<Array<Record<string, unknown>>>([])\n const meta = ref<IndexMeta>({ ...DEFAULT_META })\n\n const loading = ref(false)\n /**\n * `slowLoading` = true только если loading длится > SLOW_LOADING_DELAY мс.\n * UI использует это для skeleton — чтобы быстрые ответы (<200мс) не\n * мерцали 'data → skeleton → data'. Если запрос быстрый, skeleton\n * никогда не показывается.\n */\n const slowLoading = ref(false)\n const error = ref<Error | null>(null)\n let slowLoadingTimer: ReturnType<typeof setTimeout> | null = null\n const SLOW_LOADING_DELAY = 200\n\n const search = ref<string>('')\n const filters = ref<Record<string, unknown>>({})\n const sortKey = ref<string | null>(null)\n const sortDirection = ref<SortDirection>(null)\n\n /** Set ID-шников выбранных строк (bulk-actions). */\n const selection = ref<Set<string | number>>(new Set())\n\n const isEmpty = computed(() => !loading.value && error.value === null && items.value.length === 0)\n const selectedCount = computed(() => selection.value.size)\n const hasSelection = computed(() => selection.value.size > 0)\n const hasError = computed(() => error.value !== null)\n\n /** Tri-state: 'all' / 'mixed' / 'none' для header-checkbox. */\n const selectionState = computed<'all' | 'mixed' | 'none'>(() => {\n if (selection.value.size === 0) return 'none'\n if (items.value.length === 0) return 'none'\n const allSelected = items.value.every((row) => selection.value.has(rowId(row)))\n return allSelected ? 'all' : 'mixed'\n })\n\n /** Извлекает ID строки. По умолчанию — поле `id`; host может переопределить. */\n function rowId(row: Record<string, unknown>): string | number {\n return (row.id ?? row.key ?? '') as string | number\n }\n\n /**\n * Сменить ресурс — сброс state'а.\n *\n * `loading=true` ставится сразу, чтобы в окне между setSlug() и load() не\n * рендерилась EmptyState (\"Нет данных\") — это вызывало flicker при\n * navigation между Resource'ами.\n */\n function setSlug(next: string | null): void {\n if (slug.value === next) return\n slug.value = next\n reset()\n loading.value = true\n }\n\n function reset(): void {\n items.value = []\n meta.value = { ...DEFAULT_META }\n loading.value = false\n error.value = null\n search.value = ''\n filters.value = {}\n sortKey.value = null\n sortDirection.value = null\n selection.value = new Set()\n }\n\n function buildParams(override: IndexParams = {}): Record<string, unknown> {\n const params: Record<string, unknown> = {\n page: override.page ?? meta.value.page,\n per_page: override.per_page ?? meta.value.per_page,\n }\n // Free-text: backend ждёт `q`. См. HttpFilterParser::searchTerm.\n const ss = override.search ?? search.value\n if (ss) params.q = ss\n\n // Order: массив {column, direction}. Backend читает `order[]` через input('order').\n // Если direction === null → не добавляем order (3-режимная sort: off).\n const sk = override.sort ?? sortKey.value\n const dir = override.direction ?? sortDirection.value\n if (sk && dir !== null) {\n params.order = [{ column: sk, direction: dir }]\n }\n\n // Filters: map-style {column: value} — HttpFilterParser auto-detect режим 1.\n const f = override.filters ?? filters.value\n const filtersMap: Record<string, unknown> = {}\n for (const [k, v] of Object.entries(f)) {\n if (v === null || v === undefined || v === '') continue\n filtersMap[k] = Array.isArray(v) ? v.join(',') : v\n }\n if (Object.keys(filtersMap).length > 0) params.filters = filtersMap\n\n return params\n }\n\n /** Загрузить страницу. Без аргументов — текущие фильтры/сортировка/page. */\n async function load(override: IndexParams = {}): Promise<void> {\n if (!slug.value) {\n throw new Error('useResourceIndexStore.load() called before setSlug()')\n }\n loading.value = true\n error.value = null\n // Debounced flag для skeleton: true только если запрос длится > 200мс.\n if (slowLoadingTimer !== null) clearTimeout(slowLoadingTimer)\n slowLoadingTimer = setTimeout(() => {\n slowLoading.value = true\n }, SLOW_LOADING_DELAY)\n try {\n const client = getAdminClient()\n const body = buildParams(override)\n // Backend ResourceController.search: POST /{slug}/search.\n // Тело — параметры (фильтры/сортировка/пагинация). Возвращает\n // {data, meta:{page,per_page,total,last_page,...}}.\n const res = await client.post<ListResponse>(`/${slug.value}/search`, body)\n items.value = res.data\n meta.value = res.meta\n } catch (err) {\n error.value = err instanceof Error ? err : new Error(String(err))\n throw err\n } finally {\n loading.value = false\n slowLoading.value = false\n if (slowLoadingTimer !== null) {\n clearTimeout(slowLoadingTimer)\n slowLoadingTimer = null\n }\n }\n }\n\n async function setSearch(value: string): Promise<void> {\n search.value = value\n meta.value.page = 1\n await load()\n }\n\n async function setFilter(key: string, value: unknown): Promise<void> {\n if (value === null || value === undefined || value === '') {\n delete filters.value[key]\n } else {\n filters.value[key] = value\n }\n meta.value.page = 1\n await load()\n }\n\n async function clearFilters(): Promise<void> {\n filters.value = {}\n meta.value.page = 1\n await load()\n }\n\n async function setSort(key: string | null, direction: SortDirection = 'asc'): Promise<void> {\n sortKey.value = key\n sortDirection.value = direction\n await load()\n }\n\n /**\n * 3-режимная sort. Click по same key → asc → desc → off (sort=null).\n * Click по другому key → asc.\n */\n async function toggleSort(key: string): Promise<void> {\n if (sortKey.value === key) {\n if (sortDirection.value === 'asc') {\n sortDirection.value = 'desc'\n } else if (sortDirection.value === 'desc') {\n sortKey.value = null\n sortDirection.value = null\n } else {\n sortDirection.value = 'asc'\n }\n } else {\n sortKey.value = key\n sortDirection.value = 'asc'\n }\n await load()\n }\n\n async function setPage(page: number): Promise<void> {\n meta.value.page = page\n await load()\n }\n\n function toggleRow(id: string | number): void {\n const next = new Set(selection.value)\n if (next.has(id)) next.delete(id)\n else next.add(id)\n selection.value = next\n }\n\n /** Toggle: выделить все на странице если что-то не выбрано, иначе очистить. */\n function toggleAllOnPage(): void {\n if (selectionState.value === 'all') {\n selection.value = new Set()\n return\n }\n const next = new Set(selection.value)\n for (const row of items.value) next.add(rowId(row))\n selection.value = next\n }\n\n function clearSelection(): void {\n selection.value = new Set()\n }\n\n /** Проверить выбор конкретной строки. */\n function isSelected(id: string | number): boolean {\n return selection.value.has(id)\n }\n\n return {\n // state\n slug,\n items,\n meta,\n loading,\n slowLoading,\n error,\n search,\n filters,\n sortKey,\n sortDirection,\n selection,\n // getters\n isEmpty,\n hasError,\n hasSelection,\n selectedCount,\n selectionState,\n // actions\n setSlug,\n reset,\n load,\n setSearch,\n setFilter,\n clearFilters,\n setSort,\n toggleSort,\n setPage,\n toggleRow,\n toggleAllOnPage,\n clearSelection,\n isSelected,\n rowId,\n }\n})\n","/**\n * Formatter cell-значений для ResourceIndexPage.\n *\n * Backend-side TableColumn presets:\n * - text → as-is (string).\n * - date → 'd.m.Y' (default).\n * - datetime → 'd.m.Y H:i:s' (default).\n * - money → '{value} {currency}' с decimals.\n * - boolean → trueLabel / falseLabel из meta.\n * - badge → текст; стилизация на UI рендере (через slot или CSS-class).\n * - bytes → human-readable размер.\n * - text → fallback.\n *\n * `auto-format` для колонок без явного preset'а: если значение похоже на ISO\n * datetime (`*_at` или строка с T...Z) — применяется default datetime формат.\n */\n\nexport type CellPreset = 'text' | 'date' | 'datetime' | 'money' | 'boolean' | 'badge' | 'bytes'\n\nexport interface CellMeta {\n format?: string\n currency?: string\n decimals?: number\n trueLabel?: string | null\n falseLabel?: string | null\n [key: string]: unknown\n}\n\nconst DEFAULT_DATETIME = 'd.m.Y H:i:s'\nconst DEFAULT_DATE = 'd.m.Y'\n\nconst ISO_DATETIME_RE = /^\\d{4}-\\d{2}-\\d{2}[T\\s]\\d{2}:\\d{2}/\n\nexport function formatCell(\n value: unknown,\n preset: string | undefined,\n meta: CellMeta = {},\n): string {\n if (value === null || value === undefined) return ''\n\n // Auto-detection ISO datetime для колонок без preset'а.\n if (!preset && typeof value === 'string' && ISO_DATETIME_RE.test(value)) {\n return formatDateString(value, DEFAULT_DATETIME)\n }\n\n switch (preset) {\n case 'date':\n return formatDateString(String(value), meta.format ?? DEFAULT_DATE)\n case 'datetime':\n return formatDateString(String(value), meta.format ?? DEFAULT_DATETIME)\n case 'money':\n return formatMoney(value, meta.currency ?? 'RUB', meta.decimals ?? 2)\n case 'boolean':\n return formatBoolean(value, meta.trueLabel ?? 'Да', meta.falseLabel ?? 'Нет')\n case 'bytes':\n return formatBytes(value)\n default:\n return String(value)\n }\n}\n\n/**\n * PHP-стиль format strings → JS-Date.\n *\n * Поддерживаемые токены:\n * d → 01-31, m → 01-12, Y → 2026, y → 26\n * H → 00-23, h → 12-hour, i → minutes, s → seconds\n * D → Mon-Sun (3-letter), l → full day name, M → Jan, F → January\n * N → 1-7 (ISO weekday), w → 0-6\n * U → Unix timestamp, c → ISO 8601\n */\nfunction formatDateString(input: string, format: string): string {\n const date = new Date(input)\n if (isNaN(date.getTime())) return input\n\n const pad = (n: number, w = 2): string => String(n).padStart(w, '0')\n\n const tokens: Record<string, string> = {\n d: pad(date.getDate()),\n m: pad(date.getMonth() + 1),\n Y: String(date.getFullYear()),\n y: pad(date.getFullYear() % 100),\n H: pad(date.getHours()),\n h: pad(((date.getHours() + 11) % 12) + 1),\n i: pad(date.getMinutes()),\n s: pad(date.getSeconds()),\n U: String(Math.floor(date.getTime() / 1000)),\n c: date.toISOString(),\n N: String(((date.getDay() + 6) % 7) + 1),\n w: String(date.getDay()),\n }\n\n // Замена с учётом escape '\\\\' (PHP: backslash escapes the next char).\n let out = ''\n for (let i = 0; i < format.length; i++) {\n const ch = format[i]\n if (ch === '\\\\' && i + 1 < format.length) {\n out += format[i + 1]\n i++\n continue\n }\n out += tokens[ch] ?? ch\n }\n return out\n}\n\nfunction formatMoney(value: unknown, currency: string, decimals: number): string {\n const n = typeof value === 'number' ? value : Number(value)\n if (isNaN(n)) return String(value)\n return `${n.toFixed(decimals)} ${currency}`\n}\n\nfunction formatBoolean(value: unknown, trueLabel: string, falseLabel: string): string {\n const truthy = value === true || value === 1 || value === '1' || value === 'true'\n return truthy ? trueLabel : falseLabel\n}\n\nfunction formatBytes(value: unknown): string {\n const n = typeof value === 'number' ? value : Number(value)\n if (isNaN(n)) return String(value)\n if (n < 1024) return `${n} B`\n if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)} KB`\n if (n < 1024 * 1024 * 1024) return `${(n / 1024 / 1024).toFixed(1)} MB`\n return `${(n / 1024 / 1024 / 1024).toFixed(1)} GB`\n}\n","/**\n * FilterEditor — render-функция для редактора одного filter'а.\n *\n * Отдельный модуль (не SFC), потому что компонент чисто render-based —\n * выбирает control под filter.type без шаблона и состояния.\n */\nimport { defineComponent, h, type PropType } from 'vue'\n\nexport interface FilterOption {\n value: string | number\n label: string\n}\n\nexport interface FilterDef {\n name: string\n label: string\n type: string\n icon?: string | null\n options?: FilterOption[] | null\n multiple?: boolean\n default?: unknown\n placeholder?: string\n}\n\nexport const FilterEditor = defineComponent({\n name: 'FilterEditor',\n props: {\n filter: { type: Object as PropType<FilterDef>, required: true },\n draft: { type: null as unknown as PropType<unknown>, required: false, default: null as unknown },\n isChecked: {\n type: Function as PropType<(v: string | number) => boolean>,\n required: true,\n },\n },\n emits: ['toggle-option', 'set-draft'],\n setup(props, { emit }) {\n return () => {\n const f = props.filter\n\n // OptionsFilter (single/multi) — single render как radio, multi — checkbox.\n if (f.type === 'options' && f.options && f.options.length > 0) {\n return h(\n 'div',\n { class: 'admin-toolbar__editor admin-toolbar__editor--options' },\n f.options.map((opt) =>\n h(\n 'label',\n {\n key: String(opt.value),\n class: 'admin-toolbar__list-item admin-toolbar__list-item--checkbox',\n },\n [\n h('input', {\n type: f.multiple ? 'checkbox' : 'radio',\n checked: props.isChecked(opt.value),\n onChange: () => emit('toggle-option', opt.value),\n }),\n h('span', null, opt.label),\n ],\n ),\n ),\n )\n }\n\n // DateRangeFilter — два input type=date.\n if (f.type === 'date_range') {\n const v = (props.draft ?? {}) as { from?: string; to?: string }\n return h('div', { class: 'admin-toolbar__editor admin-toolbar__editor--dates' }, [\n h('input', {\n type: 'date',\n value: v.from ?? '',\n class: 'admin-toolbar__input',\n placeholder: 'От',\n onChange: (e: Event) =>\n emit('set-draft', { ...v, from: (e.target as HTMLInputElement).value }),\n }),\n h('input', {\n type: 'date',\n value: v.to ?? '',\n class: 'admin-toolbar__input',\n placeholder: 'До',\n onChange: (e: Event) =>\n emit('set-draft', { ...v, to: (e.target as HTMLInputElement).value }),\n }),\n ])\n }\n\n // TrashedFilter — tri-state (without / with / only).\n if (f.type === 'trashed') {\n const options = [\n { value: 'without', label: 'Без удалённых' },\n { value: 'with', label: 'С удалёнными' },\n { value: 'only', label: 'Только удалённые' },\n ]\n return h(\n 'div',\n { class: 'admin-toolbar__editor admin-toolbar__editor--options' },\n options.map((opt) =>\n h(\n 'label',\n {\n key: opt.value,\n class: 'admin-toolbar__list-item admin-toolbar__list-item--checkbox',\n },\n [\n h('input', {\n type: 'radio',\n checked: props.draft === opt.value,\n onChange: () => emit('set-draft', opt.value),\n }),\n h('span', null, opt.label),\n ],\n ),\n ),\n )\n }\n\n // SwitcherFilter — yes/no.\n if (f.type === 'switcher') {\n return h('div', { class: 'admin-toolbar__editor' }, [\n h('label', { class: 'admin-toolbar__list-item admin-toolbar__list-item--checkbox' }, [\n h('input', {\n type: 'radio',\n checked: props.draft === true,\n onChange: () => emit('set-draft', true),\n }),\n h('span', null, 'Да'),\n ]),\n h('label', { class: 'admin-toolbar__list-item admin-toolbar__list-item--checkbox' }, [\n h('input', {\n type: 'radio',\n checked: props.draft === false,\n onChange: () => emit('set-draft', false),\n }),\n h('span', null, 'Нет'),\n ]),\n ])\n }\n\n // Default: text input (input / select_from_model / unknown type).\n return h('input', {\n type: 'text',\n value: props.draft ?? '',\n class: 'admin-toolbar__input',\n placeholder: f.placeholder ?? f.label,\n onChange: (e: Event) => emit('set-draft', (e.target as HTMLInputElement).value),\n })\n }\n },\n})\n\nexport default FilterEditor\n","<script setup lang=\"ts\">\n/**\n * AdminFilterToolbar — двухстрочный toolbar над таблицей Resource'а:\n *\n * Row 1 (filter bar): search | active-chips, inactive-buttons | + Filter | Сбросить\n * Row 2 (action bar): Группировать | Колонки | Сохранить\n *\n * Конфигурируется через manifest:\n * - filters[] — Resource->filters() (type/options/multiple/icon/...)\n * - columns[] — Resource->columns() (key/label/groupable/...)\n * - searchable[] — список колонок поиска (placeholder подставляется\n * автоматически: \"Поиск по {label}…\")\n *\n * UI-фолбэк: для каждого filter-type (options / date_range / switcher /\n * input / select_from_model / trashed) рендерим универсальный popover-\n * редактор, чтобы Resource без custom-UI всё равно получил рабочий toolbar.\n */\nimport { computed, ref, watch } from 'vue'\nimport {\n Bookmark,\n Check,\n Columns,\n LayoutGrid,\n Plus,\n RotateCcw,\n Search,\n X,\n} from 'lucide-vue-next'\nimport { UidButton, UidIcon, UidMenu } from '@dskripchenko/ui'\nimport { resolveIcon } from '../shell/iconRegistry'\nimport { FilterEditor, type FilterDef, type FilterOption } from './FilterEditor'\n\ninterface ColumnDef {\n key?: string\n name?: string\n label?: string\n groupable?: boolean\n hidden?: boolean\n}\n\ninterface Props {\n search: string\n searchPlaceholder?: string\n filters: FilterDef[]\n values: Record<string, unknown>\n columns: ColumnDef[]\n /** Group-by column key (если выбран). */\n groupBy?: string | null\n /** Visibility map для column-toggle. true = видна. */\n columnVisibility?: Record<string, boolean>\n /** Показывать ли \"Сохранить\" (saved-views) — host управляет наличием feature. */\n enableSavedViews?: boolean\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n searchPlaceholder: 'Поиск…',\n groupBy: null,\n columnVisibility: () => ({}),\n enableSavedViews: true,\n})\n\nconst emit = defineEmits<{\n 'update:search': [value: string]\n 'apply-filter': [name: string, value: unknown]\n 'reset': []\n 'group-by': [column: string | null]\n 'columns-visibility': [next: Record<string, boolean>]\n 'save-view': [label: string]\n}>()\n\n// === Search local state (commit on Enter / blur) ===\nconst localSearch = ref<string>(props.search)\nwatch(\n () => props.search,\n (v) => {\n localSearch.value = v\n },\n)\nfunction commitSearch(): void {\n if (localSearch.value !== props.search) emit('update:search', localSearch.value)\n}\n\n// === Active / inactive filter partitioning ===\nfunction hasValue(v: unknown): boolean {\n if (v === null || v === undefined || v === '') return false\n if (Array.isArray(v) && v.length === 0) return false\n if (typeof v === 'object' && !Array.isArray(v)) {\n const obj = v as Record<string, unknown>\n return Object.values(obj).some((x) => x !== null && x !== '' && x !== undefined)\n }\n return true\n}\n\nconst activeFilters = computed(() =>\n props.filters.filter((f) => hasValue(props.values[f.name])),\n)\nconst inactiveFilters = computed(() =>\n props.filters.filter((f) => !hasValue(props.values[f.name])),\n)\n\nconst VISIBLE_LIMIT = 4\nconst revealed = ref<Set<string>>(new Set())\nconst inactiveVisible = computed(() =>\n inactiveFilters.value.filter(\n (f, i) => revealed.value.has(f.name) || i < VISIBLE_LIMIT,\n ),\n)\nconst inactiveHidden = computed(() =>\n inactiveFilters.value.filter(\n (f, i) => !revealed.value.has(f.name) && i >= VISIBLE_LIMIT,\n ),\n)\nfunction reveal(name: string): void {\n const next = new Set(revealed.value)\n next.add(name)\n revealed.value = next\n}\n\nconst hasActiveAnything = computed<boolean>(\n () => props.search !== '' || activeFilters.value.length > 0,\n)\n\nfunction clearFilter(name: string): void {\n emit('apply-filter', name, null)\n}\n\n// === Filter chip label formatting ===\nfunction chipText(f: FilterDef): string {\n const v = props.values[f.name]\n if (f.options && f.options.length > 0) {\n const arr = Array.isArray(v) ? v : [v]\n const labels = arr.map(\n (val) => f.options?.find((o) => String(o.value) === String(val))?.label ?? String(val),\n )\n return `${f.label}: ${labels.join(', ')}`\n }\n if (f.type === 'date_range' && v && typeof v === 'object') {\n const r = v as { from?: string; to?: string }\n return `${f.label}: ${r.from ?? ''} – ${r.to ?? ''}`\n }\n if (f.type === 'switcher') {\n return `${f.label}: ${v ? 'да' : 'нет'}`\n }\n return `${f.label}: ${String(v)}`\n}\n\n// === Multi-select working-copy (буфер до Apply) ===\nconst draftValues = ref<Record<string, unknown>>({})\nfunction getDraft(name: string): unknown {\n if (!(name in draftValues.value)) {\n draftValues.value[name] = props.values[name] ?? null\n }\n return draftValues.value[name]\n}\nfunction setDraft(name: string, value: unknown): void {\n draftValues.value = { ...draftValues.value, [name]: value }\n}\nfunction applyDraft(name: string, close: () => void): void {\n emit('apply-filter', name, draftValues.value[name] ?? null)\n close()\n}\nfunction toggleOption(name: string, value: FilterOption['value'], multiple: boolean): void {\n if (!multiple) {\n setDraft(name, value)\n return\n }\n const cur = getDraft(name)\n const arr = Array.isArray(cur) ? [...(cur as Array<string | number>)] : []\n const idx = arr.findIndex((x) => String(x) === String(value))\n if (idx >= 0) arr.splice(idx, 1)\n else arr.push(value)\n setDraft(name, arr)\n}\nfunction isOptionChecked(name: string, value: FilterOption['value']): boolean {\n const cur = getDraft(name)\n if (Array.isArray(cur)) return cur.some((x) => String(x) === String(value))\n return cur !== null && cur !== undefined && String(cur) === String(value)\n}\n\n// === Group-by + Columns + Saved-view ===\nconst groupableColumns = computed<ColumnDef[]>(() =>\n props.columns.filter((c) => c.groupable === true && (c.key ?? c.name)),\n)\nfunction setGroupBy(col: string | null, close: () => void): void {\n emit('group-by', col)\n close()\n}\n\nfunction colKey(c: ColumnDef): string {\n return String(c.key ?? c.name ?? '')\n}\nfunction colLabel(c: ColumnDef): string {\n return String(c.label ?? c.name ?? c.key ?? '')\n}\nfunction isVisible(c: ColumnDef): boolean {\n const k = colKey(c)\n if (k in props.columnVisibility) return props.columnVisibility[k]\n return true\n}\nfunction toggleVisibility(c: ColumnDef): void {\n const k = colKey(c)\n emit('columns-visibility', { ...props.columnVisibility, [k]: !isVisible(c) })\n}\n\nconst newViewLabel = ref<string>('')\nfunction saveView(close: () => void): void {\n if (newViewLabel.value.trim() === '') return\n emit('save-view', newViewLabel.value.trim())\n newViewLabel.value = ''\n close()\n}\n\nfunction iconFor(name: string | null | undefined) {\n return resolveIcon(name) ?? null\n}\n</script>\n\n<template>\n <div class=\"admin-toolbar\">\n <!-- Row 1: search + filters -->\n <div class=\"admin-toolbar__row admin-toolbar__row--filters\">\n <label class=\"admin-toolbar__search\">\n <UidIcon :icon=\"Search\" :size=\"14\" class=\"admin-toolbar__search-icon\" />\n <input\n v-model=\"localSearch\"\n type=\"search\"\n :placeholder=\"searchPlaceholder\"\n class=\"admin-toolbar__search-input\"\n @keydown.enter=\"commitSearch\"\n @blur=\"commitSearch\"\n />\n </label>\n\n <span v-if=\"filters.length > 0\" class=\"admin-toolbar__divider\" />\n\n <!-- Active filter chips: filled style + X для сброса -->\n <UidMenu\n v-for=\"f in activeFilters\"\n :key=\"`active-${f.name}`\"\n >\n <template #trigger>\n <button\n type=\"button\"\n class=\"admin-toolbar__chip admin-toolbar__chip--active\"\n >\n <UidIcon\n v-if=\"iconFor(f.icon) !== null\"\n :icon=\"(iconFor(f.icon) as never)\"\n :size=\"14\"\n />\n <span class=\"admin-toolbar__chip-text\">{{ chipText(f) }}</span>\n <span\n role=\"button\"\n tabindex=\"0\"\n aria-label=\"Сбросить фильтр\"\n class=\"admin-toolbar__chip-x\"\n @click.stop=\"clearFilter(f.name)\"\n @keydown.enter.stop=\"clearFilter(f.name)\"\n >\n <UidIcon :icon=\"X\" :size=\"12\" />\n </span>\n </button>\n </template>\n <div\n class=\"admin-toolbar__popover\"\n @keydown.stop\n >\n <FilterEditor\n :filter=\"f\"\n :draft=\"(getDraft(f.name) as never)\"\n :is-checked=\"(v) => isOptionChecked(f.name, v)\"\n @toggle-option=\"(v) => toggleOption(f.name, v, f.multiple ?? false)\"\n @set-draft=\"(v) => setDraft(f.name, v)\"\n />\n <div class=\"admin-toolbar__popover-actions\">\n <UidButton size=\"sm\" variant=\"ghost\" @click=\"setDraft(f.name, null)\">\n Очистить\n </UidButton>\n <UidButton\n size=\"sm\"\n variant=\"primary\"\n @click=\"applyDraft(f.name, () => undefined)\"\n >\n Применить\n </UidButton>\n </div>\n </div>\n </UidMenu>\n\n <!-- Inactive filter buttons: outlined, открывают popover -->\n <UidMenu\n v-for=\"f in inactiveVisible\"\n :key=\"`inactive-${f.name}`\"\n >\n <template #trigger>\n <button\n type=\"button\"\n class=\"admin-toolbar__chip\"\n >\n <UidIcon\n v-if=\"iconFor(f.icon) !== null\"\n :icon=\"(iconFor(f.icon) as never)\"\n :size=\"14\"\n />\n <span class=\"admin-toolbar__chip-text\">{{ f.label }}</span>\n </button>\n </template>\n <div\n class=\"admin-toolbar__popover\"\n @keydown.stop\n >\n <FilterEditor\n :filter=\"f\"\n :draft=\"(getDraft(f.name) as never)\"\n :is-checked=\"(v) => isOptionChecked(f.name, v)\"\n @toggle-option=\"(v) => toggleOption(f.name, v, f.multiple ?? false)\"\n @set-draft=\"(v) => setDraft(f.name, v)\"\n />\n <div class=\"admin-toolbar__popover-actions\">\n <UidButton size=\"sm\" variant=\"ghost\" @click=\"setDraft(f.name, null)\">\n Очистить\n </UidButton>\n <UidButton\n size=\"sm\"\n variant=\"primary\"\n @click=\"applyDraft(f.name, () => undefined)\"\n >\n Применить\n </UidButton>\n </div>\n </div>\n </UidMenu>\n\n <!-- + Filter dropdown с скрытыми filter'ами -->\n <UidMenu v-if=\"inactiveHidden.length > 0\">\n <template #trigger>\n <button type=\"button\" class=\"admin-toolbar__chip\">\n <UidIcon :icon=\"Plus\" :size=\"14\" />\n <span class=\"admin-toolbar__chip-text\">Filter</span>\n </button>\n </template>\n <div class=\"admin-toolbar__popover admin-toolbar__popover--list\" @keydown.stop>\n <button\n v-for=\"f in inactiveHidden\"\n :key=\"f.name\"\n type=\"button\"\n role=\"menuitem\"\n class=\"admin-toolbar__list-item\"\n @click=\"reveal(f.name)\"\n >\n <UidIcon\n v-if=\"iconFor(f.icon) !== null\"\n :icon=\"(iconFor(f.icon) as never)\"\n :size=\"14\"\n />\n {{ f.label }}\n </button>\n </div>\n </UidMenu>\n\n <span class=\"admin-toolbar__spacer\" />\n\n <UidButton\n v-if=\"hasActiveAnything\"\n variant=\"ghost\"\n size=\"md\"\n @click=\"emit('reset')\"\n >\n <template #prepend><UidIcon :icon=\"RotateCcw\" :size=\"14\" /></template>\n Сбросить\n </UidButton>\n </div>\n\n <!-- Row 2: actions (группировать / колонки / сохранить) -->\n <div\n v-if=\"groupableColumns.length > 0 || columns.length > 0 || enableSavedViews\"\n class=\"admin-toolbar__row admin-toolbar__row--actions\"\n >\n <!-- Группировать -->\n <UidMenu v-if=\"groupableColumns.length > 0\">\n <template #trigger>\n <button type=\"button\" class=\"admin-toolbar__chip\">\n <UidIcon :icon=\"LayoutGrid\" :size=\"14\" />\n <span class=\"admin-toolbar__chip-text\">\n {{ groupBy\n ? `Группа: ${colLabel(columns.find((c) => colKey(c) === groupBy) ?? {})}`\n : 'Группировать' }}\n </span>\n </button>\n </template>\n <div class=\"admin-toolbar__popover admin-toolbar__popover--list\" @keydown.stop>\n <button\n type=\"button\"\n role=\"menuitem\"\n class=\"admin-toolbar__list-item\"\n @click=\"setGroupBy(null, () => undefined)\"\n >\n <UidIcon v-if=\"!groupBy\" :icon=\"Check\" :size=\"14\" />\n <span>Без группировки</span>\n </button>\n <button\n v-for=\"c in groupableColumns\"\n :key=\"colKey(c)\"\n type=\"button\"\n role=\"menuitem\"\n class=\"admin-toolbar__list-item\"\n @click=\"setGroupBy(colKey(c), () => undefined)\"\n >\n <UidIcon v-if=\"groupBy === colKey(c)\" :icon=\"Check\" :size=\"14\" />\n <span>{{ colLabel(c) }}</span>\n </button>\n </div>\n </UidMenu>\n\n <!-- Колонки -->\n <UidMenu v-if=\"columns.length > 0\">\n <template #trigger>\n <button type=\"button\" class=\"admin-toolbar__chip\">\n <UidIcon :icon=\"Columns\" :size=\"14\" />\n <span class=\"admin-toolbar__chip-text\">Колонки</span>\n </button>\n </template>\n <div class=\"admin-toolbar__popover admin-toolbar__popover--list\" @keydown.stop>\n <label\n v-for=\"c in columns.filter((col) => colKey(col) !== '')\"\n :key=\"colKey(c)\"\n class=\"admin-toolbar__list-item admin-toolbar__list-item--checkbox\"\n >\n <input\n type=\"checkbox\"\n :checked=\"isVisible(c)\"\n @change=\"toggleVisibility(c)\"\n />\n <span>{{ colLabel(c) }}</span>\n </label>\n </div>\n </UidMenu>\n\n <!-- Сохранить (saved views) -->\n <UidMenu v-if=\"enableSavedViews\">\n <template #trigger>\n <button type=\"button\" class=\"admin-toolbar__chip\">\n <UidIcon :icon=\"Bookmark\" :size=\"14\" />\n <span class=\"admin-toolbar__chip-text\">Сохранить</span>\n </button>\n </template>\n <div class=\"admin-toolbar__popover\" @keydown.stop>\n <input\n v-model=\"newViewLabel\"\n type=\"text\"\n placeholder=\"Название view\"\n class=\"admin-toolbar__input\"\n @keydown.enter=\"saveView(() => undefined)\"\n />\n <div class=\"admin-toolbar__popover-actions\">\n <UidButton\n size=\"sm\"\n variant=\"primary\"\n :disabled=\"newViewLabel.trim() === ''\"\n @click=\"saveView(() => undefined)\"\n >\n Сохранить view\n </UidButton>\n </div>\n </div>\n </UidMenu>\n </div>\n </div>\n</template>\n\n<style>\n.admin-toolbar {\n display: flex;\n flex-direction: column;\n gap: var(--uid-space-xs);\n padding: var(--uid-space-sm) var(--uid-space-md);\n border: 1px solid var(--uid-border-subtle);\n background: var(--uid-surface-raised);\n border-radius: var(--uid-radius-lg) var(--uid-radius-lg) 0 0;\n border-bottom: 0;\n margin-top: var(--uid-space-md);\n}\n\n.admin-toolbar__row {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--uid-space-xs);\n}\n\n.admin-toolbar__divider {\n width: 1px;\n height: 22px;\n background: var(--uid-border-subtle);\n flex: none;\n margin: 0 var(--uid-space-2xs);\n}\n\n.admin-toolbar__spacer { flex: 1; }\n\n/* Search input */\n.admin-toolbar__search {\n position: relative;\n display: inline-flex;\n align-items: center;\n flex: 1 1 200px;\n max-width: 360px;\n height: 32px;\n padding: 0 var(--uid-space-sm);\n border: 1px solid var(--uid-border-subtle);\n background: var(--uid-surface-base);\n border-radius: var(--uid-radius-md);\n gap: var(--uid-space-2xs);\n}\n.admin-toolbar__search:focus-within {\n border-color: var(--uid-accent);\n outline: 2px solid color-mix(in srgb, var(--uid-accent) 18%, transparent);\n}\n.admin-toolbar__search-icon { color: var(--uid-text-tertiary); flex: none; }\n.admin-toolbar__search-input {\n flex: 1;\n height: 100%;\n border: 0;\n outline: none;\n background: transparent;\n font: inherit;\n font-size: 13px;\n color: var(--uid-text-primary);\n}\n.admin-toolbar__search-input::placeholder { color: var(--uid-text-tertiary); }\n\n/* Chip / button (общая база для active/inactive) */\n.admin-toolbar__chip {\n display: inline-flex;\n align-items: center;\n gap: var(--uid-space-2xs);\n height: 32px;\n padding: 0 var(--uid-space-sm);\n border: 1px solid var(--uid-border-subtle);\n background: var(--uid-surface-base);\n border-radius: var(--uid-radius-md);\n color: var(--uid-text-secondary);\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: background var(--uid-duration-fast, 120ms) var(--uid-ease-out, ease),\n border-color var(--uid-duration-fast, 120ms) var(--uid-ease-out, ease),\n color var(--uid-duration-fast, 120ms) var(--uid-ease-out, ease);\n}\n.admin-toolbar__chip:hover {\n background: var(--uid-color-surface-hover, var(--uid-border-subtle));\n color: var(--uid-text-primary);\n}\n.admin-toolbar__chip--active {\n background: color-mix(in srgb, var(--uid-accent) 12%, transparent);\n border-color: color-mix(in srgb, var(--uid-accent) 35%, transparent);\n color: var(--uid-accent);\n}\n.admin-toolbar__chip--active:hover {\n background: color-mix(in srgb, var(--uid-accent) 18%, transparent);\n color: var(--uid-accent);\n}\n.admin-toolbar__chip-text {\n white-space: nowrap;\n max-width: 240px;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.admin-toolbar__chip-x {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 16px;\n height: 16px;\n border-radius: 50%;\n cursor: pointer;\n margin-left: var(--uid-space-2xs);\n}\n.admin-toolbar__chip-x:hover {\n background: color-mix(in srgb, var(--uid-accent) 25%, transparent);\n}\n\n/* Popover content */\n.admin-toolbar__popover {\n display: flex;\n flex-direction: column;\n gap: var(--uid-space-sm);\n padding: var(--uid-space-sm);\n min-width: 220px;\n max-width: 320px;\n}\n.admin-toolbar__popover--list {\n padding: var(--uid-space-2xs);\n gap: 0;\n}\n.admin-toolbar__popover-actions {\n display: flex;\n justify-content: flex-end;\n gap: var(--uid-space-2xs);\n border-top: 1px solid var(--uid-border-subtle);\n padding-top: var(--uid-space-sm);\n}\n.admin-toolbar__list-item {\n display: flex;\n align-items: center;\n gap: var(--uid-space-2xs);\n padding: var(--uid-space-2xs) var(--uid-space-sm);\n border-radius: var(--uid-radius-sm);\n cursor: pointer;\n background: transparent;\n border: 0;\n font-size: 13px;\n text-align: left;\n color: var(--uid-text-primary);\n}\n.admin-toolbar__list-item:hover { background: var(--uid-color-surface-hover, var(--uid-border-subtle)); }\n.admin-toolbar__list-item--checkbox { cursor: pointer; }\n.admin-toolbar__editor { display: flex; flex-direction: column; gap: var(--uid-space-2xs); }\n.admin-toolbar__editor--dates { gap: var(--uid-space-xs); }\n.admin-toolbar__input {\n height: 32px;\n padding: 0 var(--uid-space-sm);\n border: 1px solid var(--uid-border-subtle);\n background: var(--uid-surface-base);\n border-radius: var(--uid-radius-md);\n color: var(--uid-text-primary);\n font-size: 13px;\n outline: none;\n}\n.admin-toolbar__input:focus {\n border-color: var(--uid-accent);\n outline: 2px solid color-mix(in srgb, var(--uid-accent) 18%, transparent);\n}\n</style>\n","<script setup lang=\"ts\">\n/**\n * InlineEditCell — обёртка над текстом cell'а с double-click → input.\n *\n * Backend контракт: POST /{slug}/inlineUpdate body {id, column, value}.\n * Резолв правил валидации backend делает на стороне TableColumn->editable.\n *\n * Поведение:\n * - Idle: рендерит текст (через slot default).\n * - Edit: input (text) с автофокусом, Enter — save, Esc/Blur — cancel.\n * - Saving: отключённый input, статус.\n */\nimport { nextTick, ref } from 'vue'\nimport { adminToast } from '../../stores/toast'\n\ninterface Props {\n resourceSlug: string\n rowId: string | number\n column: string\n value: unknown\n /** Если false — двойной клик ничего не делает (read-only cell). */\n editable?: boolean\n}\nconst props = withDefaults(defineProps<Props>(), {\n editable: true,\n})\n\nconst emit = defineEmits<{\n saved: [value: unknown]\n}>()\n\nconst editing = ref<boolean>(false)\nconst draft = ref<string>('')\nconst saving = ref<boolean>(false)\nconst inputRef = ref<HTMLInputElement | null>(null)\n\nasync function startEdit(): Promise<void> {\n if (!props.editable || saving.value) return\n draft.value = props.value === null || props.value === undefined ? '' : String(props.value)\n editing.value = true\n await nextTick()\n inputRef.value?.focus()\n inputRef.value?.select()\n}\n\nfunction cancel(): void {\n editing.value = false\n}\n\nasync function commit(): Promise<void> {\n if (!editing.value || saving.value) return\n // Без изменений — просто закрываем.\n if (draft.value === String(props.value ?? '')) {\n editing.value = false\n return\n }\n saving.value = true\n try {\n const { getAdminClient } = await import('../../stores/registry')\n const client = getAdminClient()\n await client.post(`/${props.resourceSlug}/inlineUpdate`, {\n id: props.rowId,\n column: props.column,\n value: draft.value,\n })\n emit('saved', draft.value)\n editing.value = false\n } catch (err) {\n if (typeof console !== 'undefined') console.error('[admin] inline-update failed:', err)\n adminToast.error(`Не удалось обновить «${props.column}».`)\n } finally {\n saving.value = false\n }\n}\n\nfunction onKeydown(e: KeyboardEvent): void {\n if (e.key === 'Enter') {\n e.preventDefault()\n void commit()\n } else if (e.key === 'Escape') {\n e.preventDefault()\n cancel()\n }\n}\n</script>\n\n<template>\n <span\n v-if=\"!editing\"\n :class=\"['admin-inline-edit', { 'admin-inline-edit--editable': editable }]\"\n :title=\"editable ? 'Двойной клик для редактирования' : undefined\"\n @dblclick.stop=\"startEdit\"\n >\n <slot>{{ value }}</slot>\n </span>\n <input\n v-else\n ref=\"inputRef\"\n v-model=\"draft\"\n type=\"text\"\n class=\"admin-inline-edit__input\"\n :disabled=\"saving\"\n @keydown=\"onKeydown\"\n @blur=\"commit\"\n @click.stop\n />\n</template>\n\n<style>\n.admin-inline-edit {\n display: inline-block;\n max-width: 100%;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n vertical-align: middle;\n}\n.admin-inline-edit--editable {\n cursor: text;\n border-radius: 3px;\n transition: background 120ms ease;\n}\n.admin-inline-edit--editable:hover {\n background: color-mix(in srgb, var(--uid-accent) 8%, transparent);\n}\n.admin-inline-edit__input {\n width: 100%;\n height: 26px;\n padding: 0 6px;\n border: 1px solid var(--uid-accent);\n background: var(--uid-surface-base);\n border-radius: var(--uid-radius-sm);\n outline: 2px solid color-mix(in srgb, var(--uid-accent) 18%, transparent);\n font: inherit;\n font-size: 13px;\n color: var(--uid-text-primary);\n}\n</style>\n","<script setup lang=\"ts\">\n/**\n * ResourceIndexPage — list-screen для одного Resource'а из manifest'а.\n * Архитектура по docs/design_handoff_laravel_admin/screens-shell.jsx (Resource List).\n *\n * Композиция:\n * - Page header (title + count + actions cluster)\n * - Filter bar с search + chips\n * - Bulk toolbar (заменяет filter bar при selectedCount > 0)\n * - UidTable с manifest.columns\n * - States: loading (UidSkeleton ×8) / empty (UidEmptyState) / error (UidErrorState)\n * - UidPagination внизу\n *\n * Host рендерит page через router. resource-slug приходит из props (либо\n * из route.params).\n */\nimport { computed, nextTick, onMounted, onUnmounted, ref, watch } from 'vue'\nimport { useRouter } from 'vue-router'\nimport {\n Bookmark,\n ChevronDown,\n Eye,\n GripVertical,\n MoreHorizontal,\n Pencil,\n Plus,\n RotateCcw,\n Trash2,\n Upload,\n} from 'lucide-vue-next'\nimport {\n UidButton,\n UidEmptyState,\n UidErrorState,\n UidIcon,\n UidMenu,\n UidMenuItem,\n UidPagination,\n UidSkeleton,\n UidTable,\n type UidTableColumn,\n} from '@dskripchenko/ui'\nimport { useResourceIndexStore } from '../../stores/resourceIndex'\nimport { useManifestStore } from '../../stores/manifest'\nimport { useNavigationStore } from '../../stores/navigation'\nimport { formatCell, type CellMeta } from './cellFormat'\nimport AdminFilterToolbar from './AdminFilterToolbar.vue'\nimport InlineEditCell from './InlineEditCell.vue'\nimport { adminToast } from '../../stores/toast'\n\ninterface Props {\n /** Slug ресурса (users/articles/etc). */\n slug: string\n /** Заголовок страницы. Если не задан — берётся из manifest'а. */\n title?: string | null\n /** Подпись под заголовком (например \"Аналитика контента\"). */\n subtitle?: string | null\n /** Текст primary-кнопки «Создать». */\n createLabel?: string\n /** Имя router-route для action «Создать». */\n createRouteName?: string | null\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n title: null,\n subtitle: null,\n createLabel: 'Создать',\n createRouteName: null,\n})\n\nconst emit = defineEmits<{\n /** Bulk-action triggered с текущим Set'ом id. */\n 'bulk-action': [action: string, ids: Array<string | number>]\n /** Click на row — host решает (push edit / open view). */\n 'row-click': [row: Record<string, unknown>]\n /** Header-action: import — host вешает обработчик загрузки CSV/JSON. */\n 'import': []\n /** Header more-menu action — произвольный ключ из additional-items. */\n 'header-action': [action: string]\n}>()\n\nconst index = useResourceIndexStore()\nconst manifest = useManifestStore()\nconst nav = useNavigationStore()\nconst router = useRouter()\n\nconst resourceMeta = computed(() => manifest.getResource(props.slug))\n\nconst displayTitle = computed(\n () => props.title ?? resourceMeta.value?.label ?? props.slug,\n)\n\n/**\n * Auto-derive create route name. Резервный вариант — стандартный pattern\n * из router/builder.ts (`admin.resource.{slug}.create`). Кнопка \"Создать\"\n * рендерится если route действительно зарегистрирован — у read-only\n * Resource'а его не будет (backend не отдаст create permission).\n */\nconst resolvedCreateRouteName = computed<string | null>(() => {\n if (props.createRouteName !== null) {\n return router.hasRoute(props.createRouteName) ? props.createRouteName : null\n }\n const candidate = `admin.resource.${props.slug}.create`\n return router.hasRoute(candidate) ? candidate : null\n})\n\n/**\n * Header actions из manifest.actions — Resource->actions() в backend.\n * Каждый node имеет {key, label, icon?, confirm?, ...}. Рендерятся в\n * more-menu (...). По клику вызываем onCustomAction → POST на\n * /{slug}/action/{key}.\n */\ninterface HeaderAction {\n key: string\n label: string\n confirm?: string\n icon?: string\n}\nconst headerActions = computed<HeaderAction[]>(() => {\n const raw = (resourceMeta.value?.actions ?? []) as Array<Record<string, unknown>>\n return raw\n .map((a) => ({\n key: String(a.key ?? a.name ?? ''),\n label: String(a.label ?? a.name ?? a.key ?? ''),\n confirm: typeof a.confirm === 'string' ? a.confirm : undefined,\n icon: typeof a.icon === 'string' ? a.icon : undefined,\n }))\n .filter((a) => a.key !== '' && a.label !== '')\n})\n\nasync function onCustomAction(action: HeaderAction): Promise<void> {\n if (action.confirm && !window.confirm(action.confirm)) return\n emit('header-action', action.key)\n try {\n nav.start()\n const { getAdminClient } = await import('../../stores/registry')\n const client = getAdminClient()\n // Backend контракт: POST /{slug}/action body {key, ids[], payload?}.\n // Action резолвится через Resource->actions() по name.\n const result = await client.post<{ affected?: number; message?: string }>(\n `/${props.slug}/action`,\n {\n key: action.key,\n ids: [...index.selection],\n },\n )\n await index.load().catch(() => undefined)\n adminToast.success(\n result?.message ?? `Action «${action.label}» применён к ${result?.affected ?? 0} записям.`,\n )\n } catch (err) {\n if (typeof console !== 'undefined') console.error('[admin] header-action failed:', err)\n adminToast.error(`Не удалось выполнить action «${action.label}».`)\n } finally {\n nav.end()\n }\n}\n\n/**\n * Export — POST /{slug}/export?format=csv|json|xlsx|pdf. Backend\n * ExporterRegistry резолвит format. Ответ blob, скачиваем через <a download>.\n *\n * Доступные форматы зависят от установленных composer-пакетов:\n * - csv / json — всегда (без deps)\n * - xlsx — openspout/openspout\n * - pdf — mpdf/mpdf или dompdf/dompdf\n */\nasync function onExport(format: 'csv' | 'json' | 'xlsx' | 'pdf' = 'csv'): Promise<void> {\n emit('header-action', 'export')\n try {\n nav.start()\n const { getAdminClient } = await import('../../stores/registry')\n const client = getAdminClient()\n const blob = await client.post<Blob>(\n `/${props.slug}/export`,\n { format, filters: index.filters, search: index.search },\n { responseType: 'blob' as const },\n )\n const url = URL.createObjectURL(blob as unknown as Blob)\n const a = document.createElement('a')\n a.href = url\n a.download = `${props.slug}-${new Date().toISOString().slice(0, 10)}.${format}`\n document.body.appendChild(a)\n a.click()\n a.remove()\n URL.revokeObjectURL(url)\n } catch (err) {\n if (typeof console !== 'undefined') console.error('[admin] export failed:', err)\n adminToast.error(`Не удалось экспортировать данные в формате ${format.toUpperCase()}.`)\n } finally {\n nav.end()\n }\n}\n\n/**\n * Import — file picker → POST multipart на /{slug}/import. После успеха\n * перезагружаем list. Если backend не поддерживает — alert.\n */\nconst importInput = ref<HTMLInputElement | null>(null)\nfunction onImportClick(): void {\n emit('import')\n importInput.value?.click()\n}\n/**\n * Default import flow поверх Dskripchenko\\LaravelAdmin\\Import\\ImportController:\n * 1. POST /import/upload (file + resource=slug) → uploadId\n * 2. POST /import/preview → auto-mapping (headers ↔ fields)\n * 3. POST /import/start (uploadId + mapping) → processId\n * 4. polling /import/status?processId=… до status === 'done' | 'failed'\n *\n * Auto-mapping автоматически связывает имена колонок CSV/JSON со своими\n * Resource-полями. Host может перехватить @import до этого flow и открыть\n * собственный wizard.\n */\nasync function onImportFileChange(e: Event): Promise<void> {\n const input = e.target as HTMLInputElement\n const file = input.files?.[0]\n if (!file) return\n try {\n nav.start()\n const { getAdminClient } = await import('../../stores/registry')\n const client = getAdminClient()\n\n // 1. Upload\n const uploadForm = new FormData()\n uploadForm.append('file', file)\n uploadForm.append('resource', props.slug)\n const uploaded = await client.post<{ upload_id: string }>(\n '/import/upload',\n uploadForm,\n )\n\n // 2. Preview (для auto-mapping)\n const preview = await client.post<{ mapping: Record<string, string> }>(\n '/import/preview',\n { resource: props.slug, upload_id: uploaded.upload_id },\n )\n\n // 3. Start\n const started = await client.post<{ process_id: string }>(\n '/import/start',\n {\n resource: props.slug,\n upload_id: uploaded.upload_id,\n mapping: preview.mapping,\n },\n )\n\n // 4. Poll status\n const finalStatus = await pollImportStatus(client, started.process_id)\n const imported = finalStatus.imported ?? 0\n const failed = finalStatus.failed ?? 0\n if (failed > 0) {\n adminToast.warning(`Импорт завершён с ошибками: ${imported} записей, ${failed} ошибок.`)\n } else {\n adminToast.success(`Импортировано записей: ${imported}.`)\n }\n await index.load().catch(() => undefined)\n } catch (err) {\n if (typeof console !== 'undefined') console.error('[admin] import failed:', err)\n adminToast.error(\n 'Импорт не удался. Проверьте формат файла и поля ресурса либо обратитесь к администратору.',\n )\n } finally {\n input.value = ''\n nav.end()\n }\n}\n\ninterface ImportStatus {\n status: 'pending' | 'running' | 'done' | 'failed'\n imported?: number\n failed?: number\n}\nasync function pollImportStatus(\n client: { get<T>(url: string): Promise<T> },\n processId: string,\n): Promise<ImportStatus> {\n // Polling каждые 800ms, но не дольше 90 секунд (сырая защита от вечного loop'а).\n const deadline = Date.now() + 90_000\n while (Date.now() < deadline) {\n await new Promise((resolve) => setTimeout(resolve, 800))\n const status = await client.get<ImportStatus>(\n `/import/status?process_id=${encodeURIComponent(processId)}`,\n )\n if (status.status === 'done' || status.status === 'failed') return status\n }\n return { status: 'failed', failed: 1 }\n}\n\nconst ACTIONS_KEY = '__row_actions__'\nconst REORDER_KEY = '__row_reorder__'\n\n/** Resource поддерживает reorder если features.reorderable=true. */\nconst isReorderable = computed<boolean>(() => {\n const features = (resourceMeta.value?.features ?? {}) as Record<string, unknown>\n return features.reorderable === true\n})\n\nconst columns = computed<UidTableColumn[]>(() => {\n const cols = resourceMeta.value?.columns ?? []\n const mapped = cols.map((c) => {\n const col = c as Record<string, unknown>\n return {\n key: String(col.key ?? col.name ?? ''),\n label: String(col.label ?? col.name ?? ''),\n sortable: Boolean(col.sortable),\n align: (col.align as 'left' | 'center' | 'right' | undefined) ?? 'left',\n width: typeof col.width === 'string' ? col.width : undefined,\n }\n })\n .filter((c) => c.key)\n // Применяем visibility-state из toolbar'а (Колонки): если явно false —\n // колонку не рендерим. По умолчанию (отсутствует в map) считаем visible.\n .filter((c) => columnVisibility.value[c.key] !== false)\n // Если Resource reorderable — впереди колонка с drag-handle.\n const head: UidTableColumn[] = isReorderable.value\n ? [{\n key: REORDER_KEY,\n label: '',\n sortable: false,\n align: 'center',\n width: '32px',\n }]\n : []\n // Хвостовая колонка с per-row actions (Просмотр / Редактировать / Удалить).\n // ResourceIndexPage добавляет её всегда — host может скрыть через\n // useShowActions=false (TODO prop).\n return [\n ...head,\n ...mapped,\n {\n key: ACTIONS_KEY,\n label: '',\n sortable: false,\n align: 'right',\n width: '120px',\n },\n ]\n})\n\n// Колоночная meta (preset / format / currency / editable / etc.) из manifest'а.\n// Используется для formatCell (datetime → 'd.m.Y H:i:s', money → '{val} {ccy}')\n// + InlineEditCell проверяет editable.\nfunction columnIsEditable(key: string): boolean {\n const cols = resourceMeta.value?.columns ?? []\n for (const c of cols) {\n const col = c as Record<string, unknown>\n const k = String(col.key ?? col.name ?? '')\n if (k === key) {\n // Backend кладёт editable как объект {rules:...} или null.\n return col.editable !== null && col.editable !== undefined\n }\n }\n return false\n}\nconst columnMeta = computed<Record<string, { preset?: string; meta: CellMeta }>>(() => {\n const cols = resourceMeta.value?.columns ?? []\n const result: Record<string, { preset?: string; meta: CellMeta }> = {}\n for (const c of cols) {\n const col = c as Record<string, unknown>\n const key = String(col.key ?? col.name ?? '')\n if (!key) continue\n result[key] = {\n preset: typeof col.preset === 'string' ? col.preset : undefined,\n meta: (col.meta as CellMeta) ?? {},\n }\n }\n return result\n})\n\nfunction renderCell(key: string, slotProps: unknown): string {\n // UidTable scoped-slot передаёт {row: actualRow}.\n const row = (slotProps as { row?: Record<string, unknown> } | undefined)?.row\n const value = row?.[key]\n const m = columnMeta.value[key]\n return formatCell(value, m?.preset, m?.meta ?? {})\n}\n\nfunction rowFromSlot(slotProps: unknown): Record<string, unknown> | undefined {\n return (slotProps as { row?: Record<string, unknown> } | undefined)?.row\n}\n\n/**\n * Показывать ли filter-toolbar:\n * - если есть данные → всегда (search + фильтры внутри);\n * - если данных нет, но есть активный search/filter → ДА (чтобы пользователь\n * мог сбросить и снова увидеть items);\n * - если данных нет и фильтры/поиск пустые → НЕТ (initial empty state).\n */\nconst hasActiveFilters = computed<boolean>(\n () => index.search !== '' || Object.keys(index.filters).length > 0,\n)\nconst showFilterBar = computed<boolean>(\n () => !index.isEmpty || hasActiveFilters.value,\n)\n\n// Filter / column / view state — toolbar делегирует это сюда.\nconst manifestFilters = computed(\n () => (resourceMeta.value?.filters ?? []) as unknown as Array<Record<string, unknown>>,\n)\nconst manifestColumns = computed(\n () => (resourceMeta.value?.columns ?? []) as unknown as Array<Record<string, unknown>>,\n)\nconst searchPlaceholder = computed(() => {\n const label = (resourceMeta.value?.label ?? props.slug).toLowerCase()\n return `Поиск по ${label}…`\n})\n\nconst groupByCol = ref<string | null>(null)\nconst columnVisibility = ref<Record<string, boolean>>({})\n\nasync function onFilterApply(name: string, value: unknown): Promise<void> {\n await index.setFilter(name, value)\n}\nasync function onSearchUpdate(v: string): Promise<void> {\n await index.setSearch(v)\n}\nasync function onResetFilters(): Promise<void> {\n index.search = ''\n await index.clearFilters()\n}\nasync function onGroupBy(col: string | null): Promise<void> {\n groupByCol.value = col\n // Backend может или не может поддерживать group-by — пробрасываем\n // в search payload как `group_by`. Если не поддерживается — просто\n // игнорируется. Cast через unknown-bridge т.к. IndexParams strict.\n await index.load({ group_by: col } as unknown as Parameters<typeof index.load>[0])\n}\nfunction onColumnsVisibility(next: Record<string, boolean>): void {\n columnVisibility.value = next\n}\n/**\n * Saved views: state + load + apply/delete. Backend — SavedViewsController,\n * URL pattern /{slug}_views/{action}. Active view хранится локально и\n * подсвечивается в scope-dropdown'е.\n */\ninterface SavedViewItem {\n id: number\n name: string\n state: Record<string, unknown>\n is_default: boolean\n owned: boolean\n}\nconst savedViews = ref<SavedViewItem[]>([])\nconst activeViewId = ref<number | null>(null)\n\nasync function loadSavedViews(): Promise<void> {\n try {\n const { getAdminClient } = await import('../../stores/registry')\n const client = getAdminClient()\n const result = await client.get<{ data: SavedViewItem[] }>(`/${props.slug}_views/list`)\n savedViews.value = result.data ?? []\n } catch {\n // Тихо — endpoint опционален. Возможно ресурс без permission или backend\n // не зарегистрировал views.\n savedViews.value = []\n }\n}\n\nasync function onApplyView(view: SavedViewItem): Promise<void> {\n activeViewId.value = view.id\n const s = view.state as {\n search?: string\n filters?: Record<string, unknown>\n sort?: { key?: string | null; direction?: 'asc' | 'desc' | null }\n group_by?: string | null\n columns?: Record<string, boolean>\n }\n index.search = s.search ?? ''\n index.filters = { ...(s.filters ?? {}) }\n index.sortKey = s.sort?.key ?? null\n index.sortDirection = s.sort?.direction ?? null\n groupByCol.value = s.group_by ?? null\n columnVisibility.value = { ...(s.columns ?? {}) }\n index.meta.page = 1\n await loadWithProgress()\n}\n\nasync function onResetView(): Promise<void> {\n activeViewId.value = null\n index.search = ''\n index.filters = {}\n index.sortKey = null\n index.sortDirection = null\n groupByCol.value = null\n columnVisibility.value = {}\n index.meta.page = 1\n await loadWithProgress()\n}\n\nasync function onDeleteView(view: SavedViewItem, e?: MouseEvent): Promise<void> {\n e?.stopPropagation()\n if (!view.owned) return\n if (!window.confirm(`Удалить view «${view.name}»?`)) return\n try {\n nav.start()\n const { getAdminClient } = await import('../../stores/registry')\n const client = getAdminClient()\n await client.post(`/${props.slug}_views/delete`, { id: view.id })\n if (activeViewId.value === view.id) activeViewId.value = null\n await loadSavedViews()\n } catch (err) {\n if (typeof console !== 'undefined') console.error('[admin] delete-view failed:', err)\n } finally {\n nav.end()\n }\n}\n\nasync function onSaveView(label: string): Promise<void> {\n try {\n nav.start()\n const { getAdminClient } = await import('../../stores/registry')\n const client = getAdminClient()\n // Backend: ResourceCompiler регистрирует controller key `{slug}_views`,\n // SavedViewsController::create — POST /{slug}_views/create.\n // Validation: {name: required string, state: required array, is_default?}\n const result = await client.post<{ view: SavedViewItem }>(\n `/${props.slug}_views/create`,\n {\n name: label,\n state: {\n search: index.search,\n filters: index.filters,\n sort: { key: index.sortKey, direction: index.sortDirection },\n group_by: groupByCol.value,\n columns: columnVisibility.value,\n },\n },\n )\n // Сразу актуализируем локальный список и помечаем view активным.\n if (result?.view) {\n activeViewId.value = result.view.id\n }\n await loadSavedViews()\n adminToast.success('Представление сохранено.')\n } catch (err) {\n if (typeof console !== 'undefined') console.error('[admin] save-view failed:', err)\n adminToast.error(\n 'Не удалось сохранить view. Возможно, недостаточно прав либо ресурс не зарегистрирован.',\n )\n } finally {\n nav.end()\n }\n}\n\nconst totalLabel = computed(() => {\n const t = index.meta.total\n if (t === 0) return ''\n return `${index.items.length} из ${t} ${pluralRecords(t)}`\n})\n\n/**\n * Русская плюрализация для \"записей\". Backend локаль RU; для других локалей\n * host может пропатчить через slot `subtitle`.\n */\nfunction pluralRecords(n: number): string {\n const mod10 = n % 10\n const mod100 = n % 100\n if (mod10 === 1 && mod100 !== 11) return 'запись'\n if (mod10 >= 2 && mod10 <= 4 && (mod100 < 10 || mod100 >= 20)) return 'записи'\n return 'записей'\n}\n\n/**\n * Live-status: timestamp последнего успешного load + \"tick\" каждые 30s,\n * чтобы текст \"обновлено 1 мин назад\" реально обновлялся без re-load.\n *\n * lastLoadedAt = null до первой удачи; после успешного store.load() ставим\n * Date.now(). Используем watch на index.loading: переход true → false без\n * error = успех.\n */\nconst lastLoadedAt = ref<number | null>(null)\nconst tick = ref<number>(0)\nlet tickTimer: ReturnType<typeof setInterval> | null = null\n\nwatch(\n () => index.loading,\n (isLoading, wasLoading) => {\n if (wasLoading && !isLoading && index.error === null) {\n lastLoadedAt.value = Date.now()\n }\n },\n)\n\nonMounted(() => {\n tickTimer = setInterval(() => {\n tick.value += 1\n }, 30_000)\n})\nonUnmounted(() => {\n if (tickTimer !== null) clearInterval(tickTimer)\n})\n\nconst liveStatus = computed<string | null>(() => {\n // tick — dependency для re-compute. Без него computed замёрзнет на initial value.\n void tick.value\n if (lastLoadedAt.value === null) return null\n const diffSec = Math.floor((Date.now() - lastLoadedAt.value) / 1000)\n if (diffSec < 5) return 'обновлено только что'\n if (diffSec < 60) return `обновлено ${diffSec} сек назад`\n const min = Math.floor(diffSec / 60)\n if (min < 60) return `обновлено ${min} мин назад`\n const hr = Math.floor(min / 60)\n if (hr < 24) return `обновлено ${hr} ч назад`\n return 'обновлено более суток назад'\n})\n\nconst scopeLabel = computed<string>(() => {\n // Активный view → его имя; иначе \"Все {ресурс в lowercase}\".\n if (activeViewId.value !== null) {\n const v = savedViews.value.find((x) => x.id === activeViewId.value)\n if (v) return v.name\n }\n const label = resourceMeta.value?.label ?? props.slug\n return `Все ${label.toLowerCase()}`\n})\n\n/**\n * Обёртка над index.load — увеличивает navigation pending counter\n * (top loading-bar) на время запроса. router.beforeEach уже инкрементирует\n * counter при start navigation; этот wrap держит bar до конца data-fetch'а.\n */\nasync function loadWithProgress(): Promise<void> {\n nav.start()\n try {\n await index.load()\n } catch {\n // silent; ошибка отображается в hasError state\n } finally {\n nav.end()\n }\n}\n\n/**\n * Mount-init: setSlug + load data.\n *\n * При SPA navigation от router.push первичный data-fetch также делается\n * в router.beforeResolve (см. createAdminApp.ts) — он держит navigation\n * в pending пока данные не пришли. Здесь load всё равно вызываем как\n * resilient fallback (direct page mount, page reload, test).\n */\nonMounted(async () => {\n index.setSlug(props.slug)\n if (manifest.manifest === null) {\n await manifest.load().catch(() => undefined)\n }\n void loadSavedViews()\n await loadWithProgress()\n})\n\nwatch(\n () => props.slug,\n async (next, prev) => {\n if (next === prev) return\n index.setSlug(next)\n activeViewId.value = null\n void loadSavedViews()\n await loadWithProgress()\n },\n)\n\nasync function onSortKeyUpdate(key: string | null): Promise<void> {\n // UidTable управляет своим 3-режимным cycle; здесь только применяем итог.\n // sortDirection приходит отдельным событием — apply через setSort одним\n // вызовом (после nextTick — Vue batches событий).\n await nextTick()\n await index.setSort(key, index.sortDirection)\n}\n\nasync function onSortDirUpdate(dir: 'asc' | 'desc' | null): Promise<void> {\n await nextTick()\n await index.setSort(index.sortKey, dir)\n}\n\nfunction onSelectionUpdate(next: Set<string | number>): void {\n index.selection = next\n}\n\nasync function onPageChange(page: number): Promise<void> {\n await index.setPage(page)\n}\n\nfunction rowId(row: Record<string, unknown>): string | number | null {\n const v = row?.id ?? row?.key\n return typeof v === 'string' || typeof v === 'number' ? v : null\n}\n\nfunction onRowClick(row: Record<string, unknown>): void {\n emit('row-click', row)\n // По умолчанию click по строке открывает view-screen записи.\n // Host может перехватить через @row-click и сделать e.preventDefault.\n const id = rowId(row)\n if (id !== null) {\n void router.push({ name: `admin.resource.${props.slug}.view`, params: { id: String(id) } })\n }\n}\n\nfunction onView(row: Record<string, unknown>, e?: MouseEvent): void {\n e?.stopPropagation()\n const id = rowId(row)\n if (id !== null) {\n void router.push({ name: `admin.resource.${props.slug}.view`, params: { id: String(id) } })\n }\n}\n\nfunction onEdit(row: Record<string, unknown>, e?: MouseEvent): void {\n e?.stopPropagation()\n const id = rowId(row)\n if (id !== null) {\n void router.push({ name: `admin.resource.${props.slug}.edit`, params: { id: String(id) } })\n }\n}\n\nasync function onDelete(row: Record<string, unknown>, e?: MouseEvent): Promise<void> {\n e?.stopPropagation()\n const id = rowId(row)\n if (id === null) return\n if (!window.confirm('Удалить запись?')) return\n try {\n nav.start()\n const { getAdminClient } = await import('../../stores/registry')\n const client = getAdminClient()\n await client.post(`/${props.slug}/delete`, { id })\n await index.load().catch(() => undefined)\n adminToast.success('Запись удалена.')\n } catch (err) {\n if (typeof console !== 'undefined') console.error('[admin] delete failed:', err)\n adminToast.error('Не удалось удалить запись.')\n } finally {\n nav.end()\n }\n}\n\n/** Soft-deleted rows имеют непустой `deleted_at`. */\nfunction isTrashed(row: Record<string, unknown>): boolean {\n return row.deleted_at !== null && row.deleted_at !== undefined\n}\n\nasync function onRestore(row: Record<string, unknown>, e?: MouseEvent): Promise<void> {\n e?.stopPropagation()\n const id = rowId(row)\n if (id === null) return\n try {\n nav.start()\n const { getAdminClient } = await import('../../stores/registry')\n const client = getAdminClient()\n await client.post(`/${props.slug}/restore`, { id })\n await index.load().catch(() => undefined)\n adminToast.success('Запись восстановлена.')\n } catch (err) {\n if (typeof console !== 'undefined') console.error('[admin] restore failed:', err)\n adminToast.error('Не удалось восстановить запись.')\n } finally {\n nav.end()\n }\n}\n\n// === Row reorder (HTML5 drag) ===\nconst dragRowIdx = ref<number | null>(null)\nfunction onRowDragStart(idx: number, e: DragEvent): void {\n if (!isReorderable.value || !e.dataTransfer) return\n // Drag только если начался с reorder-handle.\n const t = e.target as HTMLElement | null\n if (!t?.closest('[data-row-drag-handle=\"true\"]')) {\n e.preventDefault()\n return\n }\n dragRowIdx.value = idx\n e.dataTransfer.effectAllowed = 'move'\n e.dataTransfer.setData('text/plain', String(idx))\n}\nfunction onRowDragOver(e: DragEvent): void {\n if (isReorderable.value && dragRowIdx.value !== null) e.preventDefault()\n}\nasync function onRowDrop(toIdx: number, e: DragEvent): Promise<void> {\n e.preventDefault()\n if (!isReorderable.value || dragRowIdx.value === null) return\n const fromIdx = dragRowIdx.value\n dragRowIdx.value = null\n if (fromIdx === toIdx) return\n // Локальный reorder для мгновенного отклика.\n const items = [...index.items]\n const [moved] = items.splice(fromIdx, 1)\n items.splice(toIdx, 0, moved)\n index.items = items\n // Backend persistence: POST /{slug}/reorder body {ids: [orderedIds]}.\n try {\n nav.start()\n const { getAdminClient } = await import('../../stores/registry')\n const client = getAdminClient()\n const ids = items.map((r) => index.rowId(r))\n await client.post(`/${props.slug}/reorder`, { ids })\n adminToast.success('Порядок сохранён.')\n } catch (err) {\n if (typeof console !== 'undefined') console.error('[admin] reorder failed:', err)\n adminToast.error('Не удалось сохранить порядок.')\n await index.load().catch(() => undefined)\n } finally {\n nav.end()\n }\n}\n\nasync function onForceDelete(row: Record<string, unknown>, e?: MouseEvent): Promise<void> {\n e?.stopPropagation()\n const id = rowId(row)\n if (id === null) return\n if (!window.confirm('Удалить запись НАВСЕГДА? Действие необратимо.')) return\n try {\n nav.start()\n const { getAdminClient } = await import('../../stores/registry')\n const client = getAdminClient()\n await client.post(`/${props.slug}/forceDelete`, { id })\n await index.load().catch(() => undefined)\n adminToast.success('Запись удалена навсегда.')\n } catch (err) {\n if (typeof console !== 'undefined') console.error('[admin] force-delete failed:', err)\n adminToast.error('Не удалось удалить запись навсегда.')\n } finally {\n nav.end()\n }\n}\n\nfunction bulkAction(action: string): void {\n emit('bulk-action', action, [...index.selection])\n}\n\nasync function retryLoad(): Promise<void> {\n await index.load().catch(() => undefined)\n}\n</script>\n\n<template>\n <section class=\"admin-page admin-resource-index\">\n <!-- Header — следует docs/design_handoff_laravel_admin/screens-resource.jsx\n (Resource Index): title-row с live-status, под ним counter,\n справа — scope dropdown / more-menu / Import / Создать. -->\n <header class=\"admin-page__hd\">\n <div class=\"admin-page__title-wrap\">\n <div class=\"admin-page__title-row\">\n <h1 class=\"admin-page__title\">{{ displayTitle }}</h1>\n <span v-if=\"liveStatus\" class=\"admin-page__live\" role=\"status\">\n <span class=\"admin-page__live-dot\" aria-hidden=\"true\" />\n {{ liveStatus }}\n </span>\n </div>\n <div v-if=\"subtitle || totalLabel\" class=\"admin-page__count\">\n <template v-if=\"subtitle\">{{ subtitle }}</template>\n <template v-if=\"subtitle && totalLabel\"> · </template>\n <template v-if=\"totalLabel\">{{ totalLabel }}</template>\n </div>\n </div>\n <div class=\"admin-page__actions\">\n <slot name=\"actions\" />\n <UidMenu>\n <template #trigger>\n <UidButton variant=\"ghost\" size=\"md\" class=\"admin-page__scope\">\n <template #prepend><UidIcon :icon=\"Bookmark\" :size=\"14\" /></template>\n {{ scopeLabel }}\n <template #append><UidIcon :icon=\"ChevronDown\" :size=\"14\" /></template>\n </UidButton>\n </template>\n <UidMenuItem @click=\"onResetView\">\n Все {{ (resourceMeta?.label ?? slug).toLowerCase() }}\n </UidMenuItem>\n <UidMenuItem\n v-for=\"v in savedViews\"\n :key=\"v.id\"\n @click=\"onApplyView(v)\"\n >\n <span class=\"admin-page__view-row\">\n <span class=\"admin-page__view-name\">\n {{ v.name }}\n <span v-if=\"v.is_default\" class=\"admin-page__view-badge\">default</span>\n </span>\n <button\n v-if=\"v.owned\"\n type=\"button\"\n class=\"admin-page__view-delete\"\n aria-label=\"Удалить view\"\n @click.stop=\"onDeleteView(v, $event)\"\n >\n <UidIcon :icon=\"Trash2\" :size=\"12\" />\n </button>\n </span>\n </UidMenuItem>\n </UidMenu>\n <UidMenu>\n <template #trigger>\n <UidButton variant=\"ghost\" size=\"md\" aria-label=\"Действия\" class=\"admin-page__more\">\n <UidIcon :icon=\"MoreHorizontal\" :size=\"16\" />\n </UidButton>\n </template>\n <UidMenuItem @click=\"retryLoad\">Обновить</UidMenuItem>\n <UidMenuItem @click=\"onExport('csv')\">Экспорт CSV</UidMenuItem>\n <UidMenuItem @click=\"onExport('json')\">Экспорт JSON</UidMenuItem>\n <UidMenuItem @click=\"onExport('xlsx')\">Экспорт XLSX</UidMenuItem>\n <UidMenuItem @click=\"onExport('pdf')\">Экспорт PDF</UidMenuItem>\n <!-- Кастомные действия от backend Resource->actions(). -->\n <UidMenuItem\n v-for=\"action in headerActions\"\n :key=\"action.key\"\n @click=\"onCustomAction(action)\"\n >\n {{ action.label }}\n </UidMenuItem>\n <slot name=\"header-menu\" />\n </UidMenu>\n <UidButton variant=\"secondary\" size=\"md\" @click=\"onImportClick\">\n <template #prepend><UidIcon :icon=\"Upload\" :size=\"14\" /></template>\n Import\n </UidButton>\n <input\n ref=\"importInput\"\n type=\"file\"\n class=\"admin-page__import-input\"\n accept=\".csv,.json,.xlsx,.xls,application/json,text/csv\"\n @change=\"onImportFileChange\"\n />\n <UidButton\n v-if=\"resolvedCreateRouteName\"\n variant=\"primary\"\n size=\"md\"\n @click=\"$router.push({ name: resolvedCreateRouteName })\"\n >\n <template #prepend><UidIcon :icon=\"Plus\" :size=\"14\" /></template>\n {{ createLabel }}\n </UidButton>\n </div>\n </header>\n\n <!-- Bulk toolbar (selection > 0) ИЛИ filter bar -->\n <div v-if=\"index.hasSelection\" class=\"admin-bulk-toolbar\" role=\"toolbar\">\n <span class=\"admin-bulk-toolbar__count\">\n Выбрано <b>{{ index.selectedCount }}</b>\n </span>\n <span class=\"admin-bulk-toolbar__divider\" />\n <UidButton size=\"sm\" variant=\"ghost\" @click=\"bulkAction('publish')\">Опубликовать</UidButton>\n <UidButton size=\"sm\" variant=\"ghost\" @click=\"bulkAction('archive')\">Архивировать</UidButton>\n <UidButton size=\"sm\" variant=\"ghost\" @click=\"bulkAction('export')\">Экспорт</UidButton>\n <UidButton size=\"sm\" variant=\"danger\" @click=\"bulkAction('delete')\">Удалить</UidButton>\n <span class=\"admin-bulk-toolbar__spacer\" />\n <UidButton size=\"sm\" variant=\"ghost\" @click=\"index.clearSelection\">\n Снять выделение\n </UidButton>\n </div>\n\n <AdminFilterToolbar\n v-else-if=\"showFilterBar\"\n :search=\"index.search\"\n :search-placeholder=\"searchPlaceholder\"\n :filters=\"(manifestFilters as never)\"\n :values=\"index.filters\"\n :columns=\"(manifestColumns as never)\"\n :group-by=\"groupByCol\"\n :column-visibility=\"columnVisibility\"\n @update:search=\"onSearchUpdate\"\n @apply-filter=\"onFilterApply\"\n @reset=\"onResetFilters\"\n @group-by=\"onGroupBy\"\n @columns-visibility=\"onColumnsVisibility\"\n @save-view=\"onSaveView\"\n >\n <template #extra>\n <slot name=\"filters\" :filters=\"index.filters\" :set-filter=\"index.setFilter\" />\n </template>\n </AdminFilterToolbar>\n\n <!-- States -->\n <!-- Initial-loading стейт (между setSlug и первым успехом load).\n Показываем placeholder вместо UidTable — иначе сама таблица\n рендерит \"Нет данных\" empty state, что создаёт flicker\n \"Нет данных → реальные строки\" при navigation. -->\n <div\n v-if=\"index.loading && index.items.length === 0\"\n class=\"admin-resource-index__loading\"\n >\n <UidSkeleton\n v-if=\"index.slowLoading\"\n v-for=\"i in 8\"\n :key=\"i\"\n height=\"40px\"\n />\n </div>\n <UidErrorState\n v-else-if=\"index.hasError\"\n title=\"Не удалось загрузить данные\"\n :description=\"index.error?.message ?? 'Попробуйте обновить страницу.'\"\n class=\"admin-resource-index__state\"\n >\n <template #actions>\n <UidButton variant=\"primary\" @click=\"retryLoad\">Обновить</UidButton>\n </template>\n </UidErrorState>\n <UidEmptyState\n v-else-if=\"index.isEmpty\"\n title=\"Пока пусто\"\n description=\"Создайте первую запись или измените фильтры.\"\n class=\"admin-resource-index__state\"\n >\n <template #actions>\n <UidButton\n v-if=\"createRouteName\"\n variant=\"primary\"\n @click=\"$router.push({ name: createRouteName })\"\n >\n {{ createLabel }}\n </UidButton>\n </template>\n </UidEmptyState>\n\n <!-- Таблица — UidTable native selection (UidTable.selectable + selection prop). -->\n <div v-else class=\"admin-resource-index__table\">\n <UidTable\n :columns=\"columns\"\n :data=\"index.items\"\n :sort-key=\"index.sortKey\"\n :sort-direction=\"index.sortDirection\"\n selectable\n :selection=\"index.selection\"\n :row-key=\"(row) => index.rowId(row)\"\n @update:sort-key=\"onSortKeyUpdate\"\n @update:sort-direction=\"onSortDirUpdate\"\n @update:selection=\"onSelectionUpdate\"\n @row-click=\"onRowClick\"\n >\n <template\n v-for=\"col in columns\"\n #[col.key]=\"slotProps\"\n :key=\"col.key\"\n >\n <!-- Колонка drag-handle для reorderable resource'а -->\n <span\n v-if=\"col.key === REORDER_KEY\"\n class=\"admin-resource-index__row-drag\"\n data-row-drag-handle=\"true\"\n :draggable=\"isReorderable\"\n title=\"Перетащить\"\n @dragstart=\"(e: DragEvent) => onRowDragStart(\n index.items.indexOf((rowFromSlot(slotProps) ?? {}) as Record<string, unknown>),\n e,\n )\"\n @dragover=\"onRowDragOver\"\n @drop=\"(e: DragEvent) => onRowDrop(\n index.items.indexOf((rowFromSlot(slotProps) ?? {}) as Record<string, unknown>),\n e,\n )\"\n >\n <UidIcon :icon=\"GripVertical\" :size=\"14\" />\n </span>\n\n <!-- Колонка row-actions (View / Edit / Delete) — рендерим всегда последней. -->\n <div\n v-else-if=\"col.key === ACTIONS_KEY\"\n class=\"admin-resource-index__row-actions\"\n >\n <button\n type=\"button\"\n class=\"admin-resource-index__row-action\"\n title=\"Просмотр\"\n @click.stop=\"onView(rowFromSlot(slotProps) ?? {}, $event)\"\n >\n <UidIcon :icon=\"Eye\" :size=\"16\" />\n </button>\n <template v-if=\"!isTrashed(rowFromSlot(slotProps) ?? {})\">\n <button\n type=\"button\"\n class=\"admin-resource-index__row-action\"\n title=\"Редактировать\"\n @click.stop=\"onEdit(rowFromSlot(slotProps) ?? {}, $event)\"\n >\n <UidIcon :icon=\"Pencil\" :size=\"16\" />\n </button>\n <button\n type=\"button\"\n class=\"admin-resource-index__row-action admin-resource-index__row-action--danger\"\n title=\"Удалить\"\n @click.stop=\"onDelete(rowFromSlot(slotProps) ?? {}, $event)\"\n >\n <UidIcon :icon=\"Trash2\" :size=\"16\" />\n </button>\n </template>\n <template v-else>\n <button\n type=\"button\"\n class=\"admin-resource-index__row-action\"\n title=\"Восстановить\"\n @click.stop=\"onRestore(rowFromSlot(slotProps) ?? {}, $event)\"\n >\n <UidIcon :icon=\"RotateCcw\" :size=\"16\" />\n </button>\n <button\n type=\"button\"\n class=\"admin-resource-index__row-action admin-resource-index__row-action--danger\"\n title=\"Удалить навсегда\"\n @click.stop=\"onForceDelete(rowFromSlot(slotProps) ?? {}, $event)\"\n >\n <UidIcon :icon=\"Trash2\" :size=\"16\" />\n </button>\n </template>\n </div>\n <slot\n v-else\n :name=\"`cell-${col.key}`\"\n :row=\"rowFromSlot(slotProps)\"\n >\n <!--\n Default cell renderer: значение в одну строку с ellipsis при\n переполнении. max-width задаёт «адекватную» ширину колонки\n через CSS-var --admin-cell-max-width (по умолчанию 320px).\n Полный текст доступен через native browser tooltip (title=).\n Для editable-колонок double-click открывает inline editor.\n -->\n <InlineEditCell\n v-if=\"columnIsEditable(col.key)\"\n :resource-slug=\"slug\"\n :row-id=\"(rowId(rowFromSlot(slotProps) ?? {}) ?? '') as string | number\"\n :column=\"col.key\"\n :value=\"(rowFromSlot(slotProps) ?? {})[col.key]\"\n :editable=\"true\"\n @saved=\"(v) => {\n const r = rowFromSlot(slotProps)\n if (r) r[col.key] = v\n }\"\n >\n <span class=\"admin-cell-truncate\">{{ renderCell(col.key, slotProps) }}</span>\n </InlineEditCell>\n <span\n v-else\n class=\"admin-cell-truncate\"\n :title=\"renderCell(col.key, slotProps)\"\n >{{ renderCell(col.key, slotProps) }}</span>\n </slot>\n </template>\n </UidTable>\n </div>\n\n <!-- Pagination -->\n <footer\n v-if=\"!index.loading && !index.hasError && !index.isEmpty\"\n class=\"admin-resource-index__footer\"\n >\n <UidPagination\n :model-value=\"index.meta.page\"\n :total=\"index.meta.total\"\n :per-page=\"index.meta.per_page\"\n @update:model-value=\"onPageChange\"\n />\n </footer>\n </section>\n</template>\n\n<style>\n.admin-resource-index__loading {\n display: flex;\n flex-direction: column;\n gap: var(--uid-space-sm);\n margin-top: var(--uid-space-md);\n /* min-height предотвращает layout-collapse при первом mount'е,\n когда slowLoading ещё false (быстрый запрос — placeholder пустой). */\n min-height: 320px;\n}\n\n/* Drag-handle для reorderable resource'а — первая колонка. */\n.admin-resource-index__row-drag {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n cursor: grab;\n color: var(--uid-text-tertiary);\n border-radius: var(--uid-radius-sm);\n}\n.admin-resource-index__row-drag:hover {\n background: var(--uid-color-surface-hover, var(--uid-border-subtle));\n color: var(--uid-text-primary);\n}\n.admin-resource-index__row-drag:active { cursor: grabbing; }\n\n/* Row actions: View / Edit / Delete иконки в последней колонке таблицы. */\n.admin-resource-index__row-actions {\n display: flex;\n align-items: center;\n justify-content: flex-end;\n gap: var(--uid-space-2xs);\n}\n.admin-resource-index__row-action {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n padding: 0;\n border: 1px solid transparent;\n border-radius: var(--uid-radius-sm);\n background: transparent;\n color: var(--uid-text-secondary);\n cursor: pointer;\n transition: background var(--uid-duration-fast) var(--uid-ease-out),\n color var(--uid-duration-fast) var(--uid-ease-out),\n border-color var(--uid-duration-fast) var(--uid-ease-out);\n}\n.admin-resource-index__row-action:hover {\n background: var(--uid-color-surface-hover);\n color: var(--uid-text-primary);\n border-color: var(--uid-border-subtle);\n}\n.admin-resource-index__row-action--danger:hover {\n color: var(--uid-color-danger, #dc2626);\n}\n.admin-resource-index__state {\n margin-top: var(--uid-space-xl);\n}\n.admin-resource-index__table {\n /* table визуально приклеена к filter-bar / bulk-toolbar сверху —\n убираем gap, скругляем только нижние углы у table-wrap'а. */\n margin-top: 0;\n}\n.admin-resource-index__table .uid-table-wrap {\n border: 1px solid var(--uid-border-subtle);\n border-top: 0;\n border-radius: 0 0 var(--uid-radius-lg) var(--uid-radius-lg);\n}\n\n/*\n * Compact-mode table: уменьшаем padding td/th под --admin-row-h:32px и\n * font-size 13px. Оригинальный UidTable ставит padding:12px — для compact\n * это много. Переопределяем точечно внутри admin-resource-index'а чтобы\n * не задеть UidTable в других контекстах (storybook, custom widgets).\n */\n.admin-resource-index__table .uid-table__td,\n.admin-resource-index__table .uid-table__th {\n padding: 6px var(--uid-space-md);\n font-size: var(--admin-row-fs, 13px);\n height: var(--admin-row-h, 32px);\n line-height: 1.3;\n}\n\n/*\n * Cell truncate — 1 строка с ellipsis, max-width адекватный (320px по\n * умолчанию). Long-words переносятся внутри ограничения макс. до 3 строк\n * (line-clamp) на случай когда host переопределит white-space через slot.\n *\n * Tooltip с полным значением — нативный browser-tooltip через title=\n * атрибут (см. ResourceIndexPage.vue cell renderer).\n */\n.admin-cell-truncate {\n display: inline-block;\n max-width: var(--admin-cell-max-width, 320px);\n vertical-align: middle;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.admin-cell-truncate--multi {\n display: -webkit-box;\n white-space: normal;\n -webkit-line-clamp: 3;\n -webkit-box-orient: vertical;\n word-break: break-word;\n}\n.admin-resource-index__footer {\n display: flex;\n justify-content: flex-end;\n padding: var(--uid-space-md) 0;\n}\n\n/* Filter bar */\n.admin-filter-bar {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--uid-space-sm);\n padding: var(--uid-space-sm) var(--uid-space-md);\n border: 1px solid var(--uid-border-subtle);\n background: var(--uid-surface-raised);\n border-radius: var(--uid-radius-lg) var(--uid-radius-lg) 0 0;\n border-bottom: 0;\n margin-top: var(--uid-space-md);\n}\n.admin-filter-bar__search {\n flex: 1;\n min-width: 200px;\n max-width: 320px;\n height: 28px;\n padding: 0 var(--uid-space-sm);\n border: 1px solid var(--uid-border-subtle);\n background: var(--uid-surface-base);\n border-radius: var(--uid-radius-md);\n color: var(--uid-text-primary);\n font-size: 13px;\n outline: none;\n}\n.admin-filter-bar__search:focus {\n border-color: var(--uid-accent);\n outline: 2px solid color-mix(in srgb, var(--uid-accent) 18%, transparent);\n}\n.admin-filter-bar__spacer { flex: 1; }\n\n/* Bulk toolbar — dark zinc-900 surface, заменяет filter bar */\n.admin-bulk-toolbar {\n display: flex;\n align-items: center;\n gap: var(--uid-space-sm);\n padding: var(--uid-space-sm) var(--uid-space-md);\n background: var(--uid-color-zinc-900, #18181b);\n color: var(--uid-color-zinc-100, #f4f4f5);\n border-radius: var(--uid-radius-lg) var(--uid-radius-lg) 0 0;\n border: 1px solid var(--uid-color-zinc-900, #18181b);\n border-bottom: 0;\n margin-top: var(--uid-space-md);\n}\n.admin-bulk-toolbar__count { font-size: 13px; }\n.admin-bulk-toolbar__count b { font-weight: var(--uid-font-weight-semibold); }\n.admin-bulk-toolbar__divider {\n width: 1px;\n height: 20px;\n background: rgba(255, 255, 255, 0.15);\n}\n.admin-bulk-toolbar__spacer { flex: 1; }\n.admin-bulk-toolbar .uid-button {\n background: transparent;\n border-color: rgba(255, 255, 255, 0.15);\n color: var(--uid-color-zinc-100, #f4f4f5);\n}\n.admin-bulk-toolbar .uid-button:hover:not([disabled]) {\n background: rgba(255, 255, 255, 0.08);\n}\n.admin-bulk-toolbar .uid-button--danger {\n color: var(--uid-color-rose-400, #fb7185);\n}\n\n/* Selected row tint */\n.admin-resource-index__row--selected {\n background: color-mix(in srgb, var(--uid-accent) 8%, transparent);\n}\n</style>\n","/**\n * useResourceFormStore — state для Resource Create/Edit/View screens.\n *\n * Управляет:\n * - mode ('create' | 'edit' | 'view')\n * - record (raw из API), state (working copy в form-state, но мы держим\n * reference на initial для unsaved-changes detection)\n * - errors (field-keyed) — устанавливаются при ValidationError\n * - loading/saving/deleting — для disable submit / show spinner\n * - dirty (computed) — есть ли несохранённые изменения\n *\n * Endpoints (laravel-admin contract):\n * GET /{slug}/read — fetch one (id в query)\n * POST /{slug}/create\n * POST /{slug}/update\n * POST /{slug}/delete\n */\n\nimport { defineStore } from 'pinia'\nimport { computed, ref } from 'vue'\nimport { getAdminClient } from './registry'\nimport { ApiError, ValidationError } from '../api/errors'\n\nexport type FormMode = 'create' | 'edit' | 'view'\n\ninterface ReadResponse {\n // backend ResourceController::read возвращает payload {record}.\n record: Record<string, unknown>\n}\n\ninterface SaveResponse {\n // backend create/update возвращает payload {record, redirect_url, message}.\n record?: Record<string, unknown>\n id?: string | number\n redirect_url?: string\n message?: string\n}\n\nexport const useResourceFormStore = defineStore('admin-resource-form', () => {\n const slug = ref<string | null>(null)\n const mode = ref<FormMode>('create')\n const recordId = ref<string | number | null>(null)\n\n /** Текущее состояние формы — мутируется через setField. */\n const state = ref<Record<string, unknown>>({})\n /** Snapshot изначальных значений (после load) — для dirty-detection. */\n const initial = ref<Record<string, unknown>>({})\n\n /** Field-keyed errors. Очищаются при successful save. */\n const errors = ref<Record<string, string[]>>({})\n\n const loading = ref(false)\n const saving = ref(false)\n const deleting = ref(false)\n const error = ref<Error | null>(null)\n\n const isCreate = computed(() => mode.value === 'create')\n const isEdit = computed(() => mode.value === 'edit')\n const isView = computed(() => mode.value === 'view')\n const hasError = computed(() => error.value !== null)\n\n /** Dirty: state отличается от initial хотя бы по одному ключу. */\n const isDirty = computed(() => {\n const a = state.value\n const b = initial.value\n const keys = new Set([...Object.keys(a), ...Object.keys(b)])\n for (const k of keys) {\n if (!Object.is(a[k], b[k])) {\n // Простое сравнение скаляров; объекты/массивы сравниваем JSON-сериализацией.\n if (typeof a[k] === 'object' || typeof b[k] === 'object') {\n if (JSON.stringify(a[k]) !== JSON.stringify(b[k])) return true\n } else {\n return true\n }\n }\n }\n return false\n })\n\n /** In-place мутация reactive-объекта — сохраняет identity для provide/inject. */\n function replaceObject(target: Record<string, unknown>, next: Record<string, unknown>): void {\n for (const k of Object.keys(target)) delete target[k]\n Object.assign(target, next)\n }\n\n function reset(): void {\n replaceObject(state.value, {})\n replaceObject(initial.value, {})\n errors.value = {}\n loading.value = false\n saving.value = false\n deleting.value = false\n error.value = null\n recordId.value = null\n }\n\n /** Подготовить store для create-mode на ресурсе. */\n function prepareCreate(resourceSlug: string, defaults: Record<string, unknown> = {}): void {\n slug.value = resourceSlug\n mode.value = 'create'\n recordId.value = null\n replaceObject(state.value, defaults)\n replaceObject(initial.value, defaults)\n errors.value = {}\n error.value = null\n }\n\n /** Загрузить запись для edit либо view-режима. */\n async function load(\n resourceSlug: string,\n id: string | number,\n targetMode: 'edit' | 'view' = 'edit',\n ): Promise<void> {\n slug.value = resourceSlug\n mode.value = targetMode\n recordId.value = id\n loading.value = true\n error.value = null\n errors.value = {}\n\n try {\n const client = getAdminClient()\n const res = await client.get<ReadResponse>(`/${resourceSlug}/read`, {\n params: { id },\n })\n replaceObject(state.value, res.record)\n replaceObject(initial.value, res.record)\n } catch (err) {\n error.value = err instanceof Error ? err : new Error(String(err))\n throw err\n } finally {\n loading.value = false\n }\n }\n\n /** Установить значение поля (через FormState composable обычно). */\n function setField(name: string, value: unknown): void {\n state.value[name] = value\n if (errors.value[name]) {\n // Очищаем ошибку конкретного поля при изменении (стандартный UX).\n const next = { ...errors.value }\n delete next[name]\n errors.value = next\n }\n }\n\n function setErrors(next: Record<string, string[]>): void {\n errors.value = { ...next }\n }\n\n function clearErrors(): void {\n errors.value = {}\n }\n\n /**\n * Сохранить. На create — POST /create; на edit — POST /update с id.\n * Возвращает new id (для post-create редиректа).\n */\n async function save(): Promise<string | number> {\n if (!slug.value) throw new Error('useResourceFormStore.save() before slug set')\n if (saving.value) throw new Error('Already saving')\n\n saving.value = true\n error.value = null\n errors.value = {}\n\n try {\n const client = getAdminClient()\n const url =\n mode.value === 'create'\n ? `/${slug.value}/create`\n : `/${slug.value}/update`\n\n const payload =\n mode.value === 'create'\n ? state.value\n : { id: recordId.value, ...state.value }\n\n const res = await client.post<SaveResponse>(url, payload)\n // Backend отдаёт `record: {id, ...}`. Старый формат `{id}` тоже поддерживаем.\n const newId = (res.record?.id ?? res.id) as string | number | undefined\n if (newId === undefined) {\n throw new Error('save: backend response does not contain record.id')\n }\n recordId.value = newId\n // После успешного save обновим initial = state, чтобы dirty=false.\n replaceObject(initial.value, { ...state.value })\n mode.value = 'edit'\n return newId\n } catch (err) {\n if (err instanceof ValidationError) {\n errors.value = { ...err.fields }\n } else if (err instanceof ApiError) {\n error.value = err\n } else if (err instanceof Error) {\n error.value = err\n }\n throw err\n } finally {\n saving.value = false\n }\n }\n\n /** Удалить текущую запись (только в edit-mode). */\n async function destroy(): Promise<void> {\n if (!slug.value || recordId.value === null) {\n throw new Error('Nothing to delete')\n }\n if (deleting.value) throw new Error('Already deleting')\n\n deleting.value = true\n error.value = null\n try {\n const client = getAdminClient()\n await client.post(`/${slug.value}/delete`, { id: recordId.value })\n } catch (err) {\n if (err instanceof Error) error.value = err\n throw err\n } finally {\n deleting.value = false\n }\n }\n\n return {\n // state\n slug,\n mode,\n recordId,\n state,\n initial,\n errors,\n loading,\n saving,\n deleting,\n error,\n // getters\n isCreate,\n isEdit,\n isView,\n isDirty,\n hasError,\n // actions\n reset,\n prepareCreate,\n load,\n setField,\n setErrors,\n clearErrors,\n save,\n destroy,\n }\n})\n","/**\n * Реестр Vue-компонентов для JSON-driven рендеринга.\n *\n * Содержит две Map'ы — для `field`-типов (input'ы, контролы) и для\n * `layout`-типов (контейнеры). LayoutRenderer и FieldRenderer резолвят тип\n * через эти реестры; host-проект может зарегистрировать кастомные компоненты\n * через `registerField()` / `registerLayout()`.\n *\n * Singleton — один регистр на admin-instance. Тестовый сценарий —\n * `clearRegistry()` + `registerField()` в `beforeEach`.\n */\n\nimport type { Component } from 'vue'\nimport { createComponentRegistry } from '../createComponentRegistry'\n\nconst fields = createComponentRegistry<Component>()\nconst layouts = createComponentRegistry<Component>()\n\nexport const registerField = fields.register\nexport const getField = fields.get\nexport const hasField = fields.has\nexport const listFields = fields.list\n\nexport const registerLayout = layouts.register\nexport const getLayout = layouts.get\nexport const hasLayout = layouts.has\nexport const listLayouts = layouts.list\n\n/** Очистить оба реестра. Используется в тестах. */\nexport function clearRegistry(): void {\n fields.clear()\n layouts.clear()\n}\n\n/**\n * Зарегистрировать сразу несколько компонентов.\n *\n * registerComponents({\n * fields: { text: TextField, select: SelectField },\n * layouts: { rows: RowsLayout, tabs: TabsLayout },\n * })\n */\nexport interface ComponentBundle {\n fields?: Record<string, Component>\n layouts?: Record<string, Component>\n}\n\nexport function registerComponents(bundle: ComponentBundle): void {\n if (bundle.fields) fields.registerBundle(bundle.fields)\n if (bundle.layouts) layouts.registerBundle(bundle.layouts)\n}\n","<script setup lang=\"ts\">\n/**\n * Fallback на missing field-registration. Видимый dev-warn вместо silent fail —\n * host-проект сразу замечает unregistered field-type.\n */\nimport { UidAlert } from '@dskripchenko/ui'\n\ninterface Props {\n type: string\n name?: string\n}\ndefineProps<Props>()\n</script>\n\n<template>\n <UidAlert variant=\"warning\">\n <template #title>Неизвестный тип поля: {{ type }}</template>\n <template v-if=\"name\">\n <code>{{ name }}</code> — зарегистрируйте field-компонент через\n <code>registerField('{{ type }}', YourComponent)</code>.\n </template>\n </UidAlert>\n</template>\n","<script setup lang=\"ts\">\n/**\n * FieldRenderer резолвит конкретный field-компонент по `node.type` из реестра\n * и forwards остальные props через v-bind.\n *\n * Узлы манифеста имеют форму:\n * { type: 'text', name: 'title', label: 'Заголовок', required: true, ... }\n *\n * Field хранит value через provide/inject form-state — узлу не передаётся\n * `modelValue` напрямую. Это позволяет строить произвольно-глубокие layout'ы\n * без явного proppin'га state'а.\n */\nimport { computed } from 'vue'\nimport { getField } from './registry'\nimport UnknownField from '../fields/UnknownField.vue'\n\nexport interface FieldNode extends Record<string, unknown> {\n type: string\n name: string\n}\n\ninterface Props {\n node: FieldNode\n}\n\nconst props = defineProps<Props>()\nconst component = computed(() => getField(props.node.type))\nconst fieldProps = computed(() => {\n // Backend Field::toArray() кладёт type-specific опции в `attributes`\n // (suggestions, options, multiple, currency и т.п.). Разворачиваем их\n // на верхний уровень — Field-компоненты ожидают props без обёртки.\n const { type: _type, attributes, ...rest } = props.node\n const attrs = (attributes as Record<string, unknown> | undefined) ?? {}\n return { ...rest, ...attrs }\n})\n</script>\n\n<template>\n <component :is=\"component\" v-if=\"component\" v-bind=\"fieldProps\" />\n <UnknownField v-else :type=\"node.type\" :name=\"node.name\" />\n</template>\n","<script setup lang=\"ts\">\n/**\n * Универсальный рекурсивный renderer manifest-узлов.\n *\n * Узел вида `{ kind: 'field', type: 'text', name: 'title', ... }` рендерится\n * через FieldRenderer. Узел вида `{ kind: 'layout', type: 'rows', items: [...] }`\n * — через зарегистрированный layout-компонент с children-списком.\n *\n * Для совместимости со старыми JSON'ами без `kind` — если type есть в\n * field-registry, считаем field; если в layout-registry — считаем layout;\n * иначе — UnknownField fallback.\n */\nimport { computed } from 'vue'\nimport { getField, getLayout } from './registry'\nimport FieldRenderer, { type FieldNode } from './FieldRenderer.vue'\nimport UnknownField from '../fields/UnknownField.vue'\n\nexport interface LayoutNode extends Record<string, unknown> {\n type: string\n kind?: 'field' | 'layout'\n items?: LayoutNode[]\n}\n\ninterface Props {\n node: LayoutNode\n}\nconst props = defineProps<Props>()\n\ntype Resolved =\n | { kind: 'field' }\n | { kind: 'layout'; component: ReturnType<typeof getLayout> }\n | { kind: 'unknown' }\n\nconst resolved = computed<Resolved>(() => {\n // Явный hint через `kind` всегда приоритетнее.\n if (props.node.kind === 'field') {\n return { kind: 'field' }\n }\n if (props.node.kind === 'layout') {\n const component = getLayout(props.node.type)\n return component ? { kind: 'layout', component } : { kind: 'unknown' }\n }\n // Auto-detect.\n const layoutComponent = getLayout(props.node.type)\n if (layoutComponent) return { kind: 'layout', component: layoutComponent }\n if (getField(props.node.type)) return { kind: 'field' }\n return { kind: 'unknown' }\n})\n\nconst layoutProps = computed(() => {\n const { type: _type, kind: _kind, ...rest } = props.node\n return rest\n})\n\nconst fieldNode = computed<FieldNode>(() => props.node as unknown as FieldNode)\n</script>\n\n<template>\n <component\n :is=\"resolved.component\"\n v-if=\"resolved.kind === 'layout' && resolved.component\"\n v-bind=\"layoutProps\"\n />\n <FieldRenderer v-else-if=\"resolved.kind === 'field'\" :node=\"fieldNode\" />\n <UnknownField v-else :type=\"node.type\" :name=\"(node.name as string | undefined)\" />\n</template>\n","<script setup lang=\"ts\">\n/**\n * ResourceFormPage — unified create/edit page для Resource'а.\n *\n * Архитектура по docs/design_handoff_laravel_admin/screens-shell.jsx\n * (Resource Form):\n * - Header: back-breadcrumb + title + status-badge + actions\n * (Preview / Удалить / Сохранить-primary)\n * - Body: layout из manifest.fields (LayoutRenderer + provideFormState)\n * - Sticky save-bar внизу с unsaved-changes hint\n *\n * Mode определяется наличием `id`-prop'а: id=null → create, иначе → edit.\n *\n * Form-state предоставляется через provideFormState из useResourceFormStore.state.\n * FieldRenderer'ы внутри форм автоматически подхватывают через useFormState.\n */\nimport { computed, onMounted, watch } from 'vue'\nimport { useRouter } from 'vue-router'\nimport {\n UidAlert,\n UidBadge,\n UidButton,\n UidCard,\n UidSkeleton,\n} from '@dskripchenko/ui'\nimport { useResourceFormStore } from '../../stores/resourceForm'\nimport { useManifestStore } from '../../stores/manifest'\nimport { provideFormState } from '../render/formState'\nimport LayoutRenderer from '../render/LayoutRenderer.vue'\nimport type { LayoutNode } from '../render/LayoutRenderer.vue'\n\ninterface Props {\n /** Slug ресурса (articles/users/etc). */\n slug: string\n /** ID записи. null/undefined → create-mode; число/строка → edit. */\n id?: string | number | null\n /**\n * Override имени router-route для back-redirect после save/delete.\n * По умолчанию выводится из slug: `admin.resource.{slug}.index`.\n */\n indexRouteName?: string | null\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n id: null,\n indexRouteName: null,\n})\n\nconst form = useResourceFormStore()\nconst manifest = useManifestStore()\nconst router = useRouter()\n\n// provideFormState ОБЯЗАН вызываться в setup() — связываем со store.state.\n// Сам form-context форвардит setField → store.setField (с auto-clear errors).\nconst ctx = provideFormState(form.state, form.errors)\n\n// Watcher: при изменениях через ctx.setField (обёртка которой) — синхронизируем\n// в store, чтобы isDirty работало. Поскольку state.value === ctx.state (тот же\n// reactive object — provideFormState не делает копию), мутации видны напрямую\n// в store. setField'у в ctx достаточно.\nwatch(\n () => form.errors,\n (next) => {\n // При обновлении store.errors — выкидываем в form-context.\n ctx.setErrors({ ...next })\n },\n)\n\nconst resourceMeta = computed(() => manifest.getResource(props.slug))\n\nconst layoutNodes = computed<LayoutNode[]>(\n () => resourceMeta.value?.fields ?? [],\n)\n\nconst titleLabel = computed(() => {\n if (form.isCreate) return `Создать: ${resourceMeta.value?.label ?? props.slug}`\n return `${resourceMeta.value?.label ?? props.slug}: запись #${props.id}`\n})\n\nconst statusValue = computed<string | null>(() => {\n const v = form.state.status\n return typeof v === 'string' ? v : null\n})\n\nconst statusBadgeVariant = computed<'success' | 'warning' | 'danger' | 'default'>(() => {\n switch (statusValue.value) {\n case 'published': return 'success'\n case 'review':\n case 'draft': return 'warning'\n case 'archived': return 'danger'\n default: return 'default'\n }\n})\n\nonMounted(async () => {\n if (manifest.manifest === null) {\n await manifest.load().catch(() => undefined)\n }\n if (props.id !== null && props.id !== undefined) {\n await form.load(props.slug, props.id, 'edit').catch(() => undefined)\n } else {\n form.prepareCreate(props.slug)\n }\n})\n\nwatch(\n () => [props.slug, props.id] as const,\n async ([nextSlug, nextId]) => {\n if (nextId !== null && nextId !== undefined) {\n await form.load(nextSlug, nextId, 'edit').catch(() => undefined)\n } else {\n form.prepareCreate(nextSlug)\n }\n },\n)\n\nasync function onSave(): Promise<void> {\n try {\n const newId = await form.save()\n if (form.isCreate) {\n // create → редирект на edit с новым id (host route'ит).\n void router.push({\n name: `admin.resource.${props.slug}.edit`,\n params: { id: newId },\n }).catch(() => undefined)\n }\n } catch {\n // ValidationError уже превратился в form.errors через store; остальные\n // ошибки попали в form.error и отрисуются как UidAlert ниже.\n }\n}\n\n/**\n * Auto-derive index route name из slug (`admin.resource.{slug}.index`),\n * если host не передал indexRouteName явно. Это нужно чтобы back/cancel\n * вели на список ресурса, а не на главную админки.\n */\nconst resolvedIndexRouteName = computed<string>(\n () => props.indexRouteName ?? `admin.resource.${props.slug}.index`,\n)\n\nasync function onDelete(): Promise<void> {\n if (!confirm('Удалить запись?')) return\n await form.destroy().catch(() => undefined)\n if (!form.hasError) {\n void router.push({ name: resolvedIndexRouteName.value }).catch(() => undefined)\n }\n}\n\nfunction onCancel(): void {\n if (form.isDirty && !confirm('Несохранённые изменения будут потеряны. Продолжить?')) {\n return\n }\n void router.push({ name: resolvedIndexRouteName.value }).catch(() => undefined)\n}\n</script>\n\n<template>\n <section class=\"admin-page admin-resource-form\">\n <header class=\"admin-page__hd\">\n <div class=\"admin-page__title-wrap\">\n <a class=\"admin-resource-form__back\" @click=\"onCancel\">← Назад</a>\n <h1 class=\"admin-page__title\">{{ titleLabel }}</h1>\n <UidBadge v-if=\"statusValue\" :variant=\"statusBadgeVariant\">\n {{ statusValue }}\n </UidBadge>\n </div>\n <div class=\"admin-page__actions\">\n <UidButton\n variant=\"ghost\"\n :disabled=\"form.saving || form.deleting\"\n @click=\"onCancel\"\n >\n Отмена\n </UidButton>\n <UidButton\n v-if=\"form.isEdit\"\n variant=\"danger\"\n :disabled=\"form.saving || form.deleting\"\n :loading=\"form.deleting\"\n @click=\"onDelete\"\n >\n Удалить\n </UidButton>\n <UidButton\n variant=\"primary\"\n :disabled=\"form.saving || form.loading\"\n :loading=\"form.saving\"\n @click=\"onSave\"\n >\n {{ form.isCreate ? 'Создать' : 'Сохранить' }}\n </UidButton>\n </div>\n </header>\n\n <UidAlert\n v-if=\"form.hasError\"\n variant=\"danger\"\n class=\"admin-resource-form__alert\"\n role=\"alert\"\n >\n {{ form.error?.message ?? 'Не удалось сохранить запись' }}\n </UidAlert>\n\n <!-- Loading state — UidSkeleton imitates form-rows -->\n <div v-if=\"form.loading\" class=\"admin-resource-form__loading\">\n <UidSkeleton v-for=\"i in 6\" :key=\"i\" height=\"40px\" />\n </div>\n\n <!-- Body: layout из manifest -->\n <UidCard v-else padding=\"md\" class=\"admin-resource-form__body\">\n <LayoutRenderer\n v-for=\"(node, idx) in layoutNodes\"\n :key=\"idx\"\n :node=\"node\"\n />\n </UidCard>\n\n <!-- Sticky save-bar — показывается при unsaved-changes -->\n <div v-if=\"form.isDirty && !form.loading\" class=\"admin-resource-form__savebar\">\n <span class=\"admin-resource-form__savebar-hint\">\n Есть несохранённые изменения\n </span>\n <UidButton variant=\"ghost\" size=\"sm\" @click=\"onCancel\">Отмена</UidButton>\n <UidButton\n variant=\"primary\"\n size=\"sm\"\n :loading=\"form.saving\"\n :disabled=\"form.saving\"\n @click=\"onSave\"\n >\n Сохранить\n </UidButton>\n </div>\n </section>\n</template>\n\n<style>\n.admin-resource-form__back {\n font-size: var(--uid-font-size-xs);\n color: var(--uid-text-secondary);\n cursor: pointer;\n text-decoration: none;\n display: inline-block;\n margin-bottom: 4px;\n}\n.admin-resource-form__back:hover { color: var(--uid-text-primary); }\n\n.admin-resource-form__alert {\n margin-bottom: var(--uid-space-md);\n}\n.admin-resource-form__loading {\n display: flex;\n flex-direction: column;\n gap: var(--uid-space-sm);\n}\n.admin-resource-form__body { margin-bottom: var(--uid-space-2xl); }\n\n.admin-resource-form__savebar {\n position: sticky;\n bottom: 0;\n display: flex;\n align-items: center;\n gap: var(--uid-space-sm);\n padding: var(--uid-space-sm) var(--uid-space-md);\n background: var(--uid-surface-raised);\n border-top: 1px solid var(--uid-border-default);\n border-radius: var(--uid-radius-md);\n box-shadow: var(--uid-shadow-md);\n margin-top: var(--uid-space-md);\n}\n.admin-resource-form__savebar-hint {\n flex: 1;\n font-size: 13px;\n color: var(--uid-warning);\n}\n</style>\n","/**\n * Реестр infolist-entry-компонентов.\n *\n * Аналог field-registry, но для read-only display'я. Узлы манифеста имеют\n * форму:\n * { type: 'text', name: 'title', label: 'Заголовок', value?: '...' }\n * либо без явного `value` — тогда entry извлекает `record[name]` из\n * provide'нутого `record`.\n *\n * Host регистрирует кастомные entry через `registerInfolistEntry()` /\n * `registerInfolistEntries()` bundle.\n */\n\nimport type { Component } from 'vue'\nimport { createComponentRegistry } from '../createComponentRegistry'\n\nconst entries = createComponentRegistry<Component>()\n\nexport const registerInfolistEntry = entries.register\nexport const getInfolistEntry = entries.get\nexport const hasInfolistEntry = entries.has\nexport const listInfolistEntries = entries.list\nexport const clearInfolistRegistry = entries.clear\nexport const registerInfolistEntries = entries.registerBundle\n","<script setup lang=\"ts\">\nimport { UidAlert } from '@dskripchenko/ui'\n\ninterface Props {\n type: string\n name?: string\n}\ndefineProps<Props>()\n</script>\n\n<template>\n <UidAlert variant=\"warning\">\n <template #title>Неизвестный тип infolist-entry: {{ type }}</template>\n Зарегистрируйте через <code>registerInfolistEntry('{{ type }}', YourComponent)</code>.\n </UidAlert>\n</template>\n","<script setup lang=\"ts\">\n/**\n * InfolistRenderer — read-only аналог LayoutRenderer для view-страниц.\n *\n * Узлы:\n * { type: 'text', name: 'title', label: 'Заголовок' } — entry (leaf)\n * { type: 'rows', items: [ ... ] } — layout (recurse)\n * { type: 'section', title: 'X', items: [ ... ] } — layout\n * { type: 'columns', items: [ ... ] } — layout\n *\n * Внимание: layout-узлы рендерятся СВОИМ внутренним wrapper'ом, а не\n * registered uid-layouts из render/registry, потому что те делегируют детей\n * в LayoutRenderer (field-registry → useFormState ОБЯЗАТЕЛЕН). Здесь record-\n * read-only режим — детей рендерим через сам InfolistRenderer.\n */\nimport { computed } from 'vue'\nimport { getInfolistEntry } from './registry'\nimport UnknownEntry from './UnknownEntry.vue'\n\nexport interface InfolistNode extends Record<string, unknown> {\n type: string\n /** Hint: 'entry' либо 'layout'. */\n kind?: 'entry' | 'layout'\n items?: InfolistNode[]\n}\n\ninterface Props {\n node: InfolistNode\n}\nconst props = defineProps<Props>()\n\nconst KNOWN_LAYOUTS = new Set(['rows', 'columns', 'section', 'block', 'tabs'])\n\ntype Resolved =\n | { kind: 'entry'; component: NonNullable<ReturnType<typeof getInfolistEntry>> }\n | { kind: 'layout'; layoutType: string }\n | { kind: 'unknown' }\n\nconst resolved = computed<Resolved>(() => {\n if (props.node.kind === 'entry') {\n const c = getInfolistEntry(props.node.type)\n return c ? { kind: 'entry', component: c } : { kind: 'unknown' }\n }\n if (props.node.kind === 'layout') {\n return KNOWN_LAYOUTS.has(props.node.type)\n ? { kind: 'layout', layoutType: props.node.type }\n : { kind: 'unknown' }\n }\n // Auto-detect: layouts по имени, entries по registry.\n if (KNOWN_LAYOUTS.has(props.node.type)) {\n return { kind: 'layout', layoutType: props.node.type }\n }\n const entry = getInfolistEntry(props.node.type)\n if (entry) return { kind: 'entry', component: entry }\n return { kind: 'unknown' }\n})\n\nconst entryProps = computed(() => {\n const { type: _t, kind: _k, items: _i, attributes, ...rest } = props.node\n // Backend кладёт preset/format/etc в `attributes` под-объект (см.\n // Infolist\\Entry::toArray). Flat'имся для удобства Vue v-bind:\n // attributes.preset → preset prop, attributes.format → meta.format.\n const attrs = (attributes as Record<string, unknown> | undefined) ?? {}\n const { preset, format, currency, decimals, trueLabel, falseLabel, ...rest2 } = attrs\n const meta: Record<string, unknown> = {}\n if (format !== undefined) meta.format = format\n if (currency !== undefined) meta.currency = currency\n if (decimals !== undefined) meta.decimals = decimals\n if (trueLabel !== undefined) meta.trueLabel = trueLabel\n if (falseLabel !== undefined) meta.falseLabel = falseLabel\n return { ...rest, ...rest2, preset, meta }\n})\n\nconst items = computed<InfolistNode[]>(\n () => (props.node.items ?? []) as InfolistNode[],\n)\n\nconst sectionTitle = computed(() => (props.node.title as string | undefined) ?? null)\nconst sectionDescription = computed(\n () => (props.node.description as string | undefined) ?? null,\n)\nconst tabsActive = computed<number>(() => {\n const a = props.node.active\n return typeof a === 'number' ? a : 0\n})\n\ninterface InfolistTab {\n key?: string\n label: string\n items: InfolistNode[]\n}\nconst tabsList = computed<InfolistTab[]>(() => {\n return (props.node.items ?? []) as unknown as InfolistTab[]\n})\n</script>\n\n<template>\n <!-- Entry -->\n <component\n :is=\"resolved.component\"\n v-if=\"resolved.kind === 'entry'\"\n v-bind=\"entryProps\"\n />\n\n <!-- Layout: rows -->\n <div\n v-else-if=\"resolved.kind === 'layout' && resolved.layoutType === 'rows'\"\n class=\"admin-infolist-rows\"\n >\n <InfolistRenderer\n v-for=\"(child, idx) in items\"\n :key=\"idx\"\n :node=\"child\"\n />\n </div>\n\n <!-- Layout: columns (12-grid с per-item span) -->\n <div\n v-else-if=\"resolved.kind === 'layout' && resolved.layoutType === 'columns'\"\n class=\"admin-infolist-cols\"\n >\n <div\n v-for=\"(child, idx) in items\"\n :key=\"idx\"\n class=\"admin-infolist-cols__item\"\n :style=\"{\n gridColumn: `span ${\n typeof (child as Record<string, unknown>).span === 'number'\n ? (child as Record<string, unknown>).span\n : Math.max(1, Math.floor(12 / items.length))\n }`,\n }\"\n >\n <InfolistRenderer :node=\"child\" />\n </div>\n </div>\n\n <!-- Layout: section / block -->\n <section\n v-else-if=\"resolved.kind === 'layout' && (resolved.layoutType === 'section' || resolved.layoutType === 'block')\"\n class=\"admin-infolist-section\"\n >\n <header v-if=\"sectionTitle || sectionDescription\" class=\"admin-infolist-section__hd\">\n <h3 v-if=\"sectionTitle\" class=\"admin-infolist-section__title\">{{ sectionTitle }}</h3>\n <p v-if=\"sectionDescription\" class=\"admin-infolist-section__description\">\n {{ sectionDescription }}\n </p>\n </header>\n <div class=\"admin-infolist-section__body\">\n <InfolistRenderer\n v-for=\"(child, idx) in items\"\n :key=\"idx\"\n :node=\"child\"\n />\n </div>\n </section>\n\n <!-- Layout: tabs (минимальные — без переключения, показываем active по prop'у) -->\n <div\n v-else-if=\"resolved.kind === 'layout' && resolved.layoutType === 'tabs'\"\n class=\"admin-infolist-tabs\"\n >\n <ul class=\"admin-infolist-tabs__list\" role=\"tablist\">\n <li\n v-for=\"(tab, idx) in tabsList\"\n :key=\"tab.key ?? idx\"\n :class=\"[\n 'admin-infolist-tabs__tab',\n { 'admin-infolist-tabs__tab--active': idx === tabsActive },\n ]\"\n >\n {{ tab.label }}\n </li>\n </ul>\n <div class=\"admin-infolist-tabs__panel\">\n <InfolistRenderer\n v-for=\"(child, idx) in tabsList[tabsActive]?.items ?? []\"\n :key=\"idx\"\n :node=\"child\"\n />\n </div>\n </div>\n\n <UnknownEntry v-else :type=\"node.type\" :name=\"(node.name as string | undefined)\" />\n</template>\n\n<style>\n.admin-infolist-rows {\n display: flex;\n flex-direction: column;\n gap: var(--uid-space-sm);\n}\n.admin-infolist-cols {\n display: grid;\n grid-template-columns: repeat(12, minmax(0, 1fr));\n gap: var(--uid-space-md);\n}\n.admin-infolist-section {\n margin-bottom: var(--uid-space-md);\n padding: var(--uid-space-md);\n border: 1px solid var(--uid-border-subtle);\n border-radius: var(--uid-radius-lg);\n background: var(--uid-surface-raised);\n}\n.admin-infolist-section__hd { margin-bottom: var(--uid-space-sm); }\n.admin-infolist-section__title {\n margin: 0;\n font-size: var(--uid-font-size-sm);\n font-weight: var(--uid-font-weight-semibold);\n}\n.admin-infolist-section__description {\n margin: var(--uid-space-2xs) 0 0;\n font-size: var(--uid-font-size-xs);\n color: var(--uid-text-tertiary);\n}\n.admin-infolist-section__body {\n display: flex;\n flex-direction: column;\n gap: var(--uid-space-sm);\n}\n.admin-infolist-tabs__list {\n list-style: none;\n margin: 0 0 var(--uid-space-sm);\n padding: 0;\n display: flex;\n gap: var(--uid-space-xs);\n border-bottom: 1px solid var(--uid-border-subtle);\n}\n.admin-infolist-tabs__tab {\n padding: var(--uid-space-sm) var(--uid-space-sm);\n font-size: 13px;\n color: var(--uid-text-secondary);\n border-bottom: 2px solid transparent;\n}\n.admin-infolist-tabs__tab--active {\n color: var(--uid-text-primary);\n border-bottom-color: var(--uid-accent);\n font-weight: var(--uid-font-weight-medium);\n}\n</style>\n","/**\n * Composable для read-only record-контекста, передаваемого Infolist'ом.\n *\n * Контейнер (ResourceViewPage) вызывает `provideRecord(record)`, entry-\n * компоненты — `useRecord()` для чтения значения.\n */\n\nimport { inject, provide, type InjectionKey } from 'vue'\n\nconst RecordKey: InjectionKey<Record<string, unknown>> = Symbol('admin.infolist-record')\n\nexport function provideRecord(record: Record<string, unknown>): void {\n provide(RecordKey, record)\n}\n\nexport function useRecord(): Record<string, unknown> {\n const r = inject(RecordKey)\n if (!r) {\n throw new Error('useRecord() called outside of provideRecord() scope')\n }\n return r\n}\n\nexport function tryUseRecord(): Record<string, unknown> | null {\n return inject(RecordKey, null) as Record<string, unknown> | null\n}\n","<script setup lang=\"ts\">\n/**\n * AuditTimeline — список изменений конкретной записи.\n *\n * Грузит GET /audit/timeline?subject_type={…}&subject_id={…} (см. backend\n * AuditController::timeline) и рендерит вертикальный timeline по дизайну\n * docs/design_handoff_laravel_admin (Resource View → История изменений).\n *\n * subjectType — Eloquent morph-class модели (например 'App\\\\Models\\\\Article'\n * или 'article' если используется map). Если не задан — компонент молча\n * не рендерит timeline (host не включил аудит).\n */\nimport { computed, onMounted, ref, watch } from 'vue'\nimport {\n Edit,\n Plus,\n Tag,\n Trash2,\n type LucideIcon,\n} from 'lucide-vue-next'\nimport { UidAvatar, UidIcon, UidSkeleton } from '@dskripchenko/ui'\n\ninterface AuditActor {\n id: number | string\n type: string\n name: string | null\n}\ninterface AuditEntry {\n id: number\n event: string\n created_at: string\n actor: AuditActor | null\n summary: string\n diff: Array<{ field: string; before: unknown; after: unknown }> | null\n}\n\ninterface Props {\n /**\n * Eloquent morph-class либо FQCN модели. Может быть пустой строкой /\n * null — компонент в этом случае не делает запрос и показывает\n * пустой state. Это нужно чтобы блок «История изменений» был всегда\n * виден на view-странице даже когда у Resource не задан model-class.\n */\n subjectType: string | null\n subjectId: string | number\n}\nconst props = defineProps<Props>()\n\nconst items = ref<AuditEntry[]>([])\nconst loading = ref<boolean>(false)\nconst error = ref<Error | null>(null)\n\nasync function load(): Promise<void> {\n // Без subject_type делать запрос бессмысленно — backend ожидает required\n // строку. Просто показываем пустой state.\n if (!props.subjectType || props.subjectType === '') {\n items.value = []\n loading.value = false\n error.value = null\n return\n }\n loading.value = true\n error.value = null\n try {\n const { getAdminClient } = await import('../../stores/registry')\n const client = getAdminClient()\n const result = await client.get<{ data: AuditEntry[] }>(\n `/audit/timeline?subject_type=${encodeURIComponent(props.subjectType)}&subject_id=${encodeURIComponent(String(props.subjectId))}`,\n )\n items.value = result.data ?? []\n } catch (err) {\n error.value = err instanceof Error ? err : new Error(String(err))\n items.value = []\n } finally {\n loading.value = false\n }\n}\n\nonMounted(load)\nwatch(() => [props.subjectType, props.subjectId] as const, load)\n\nconst hasItems = computed<boolean>(() => items.value.length > 0)\n\nfunction eventIcon(event: string): LucideIcon {\n if (event === 'created') return Plus\n if (event === 'deleted' || event === 'destroyed') return Trash2\n if (event.includes('tag') || event.includes('label')) return Tag\n return Edit\n}\n\nfunction eventLabel(event: string): string {\n const map: Record<string, string> = {\n created: 'создал',\n updated: 'отредактировал',\n deleted: 'удалил',\n destroyed: 'удалил',\n restored: 'восстановил',\n published: 'опубликовал',\n }\n return map[event] ?? event\n}\n\nfunction relativeTime(iso: string): string {\n const ts = new Date(iso).getTime()\n if (Number.isNaN(ts)) return ''\n const diff = (Date.now() - ts) / 1000\n if (diff < 60) return `${Math.max(1, Math.floor(diff))} сек назад`\n if (diff < 3600) return `${Math.floor(diff / 60)} мин назад`\n if (diff < 86_400) return `${Math.floor(diff / 3600)} ч назад`\n if (diff < 86_400 * 30) return `${Math.floor(diff / 86_400)} д назад`\n return new Date(iso).toLocaleDateString('ru-RU')\n}\n\nfunction diffSummary(entry: AuditEntry): string {\n if (entry.summary) return entry.summary\n if (!entry.diff || entry.diff.length === 0) return ''\n if (entry.diff.length === 1) {\n const d = entry.diff[0]\n return `Поле ${d.field}: ${formatVal(d.before)} → ${formatVal(d.after)}`\n }\n const fields = entry.diff.slice(0, 4).map((d) => d.field).join(', ')\n return `Изменены ${entry.diff.length} поля: ${fields}`\n}\n\nfunction formatVal(v: unknown): string {\n if (v === null || v === undefined) return '∅'\n if (typeof v === 'string') return v.length > 20 ? `${v.slice(0, 20)}…` : v\n return String(v)\n}\n</script>\n\n<template>\n <section class=\"admin-audit-timeline\">\n <h2 class=\"admin-audit-timeline__title\">История изменений</h2>\n\n <div v-if=\"loading\" class=\"admin-audit-timeline__loading\">\n <UidSkeleton v-for=\"i in 3\" :key=\"i\" height=\"48px\" />\n </div>\n\n <div v-else-if=\"error\" class=\"admin-audit-timeline__error\">\n Не удалось загрузить историю: {{ error.message }}\n </div>\n\n <div v-else-if=\"!hasItems\" class=\"admin-audit-timeline__empty\">\n Записей в истории пока нет.\n </div>\n\n <ol v-else class=\"admin-audit-timeline__list\">\n <li\n v-for=\"entry in items\"\n :key=\"entry.id\"\n class=\"admin-audit-timeline__item\"\n >\n <span class=\"admin-audit-timeline__icon\" aria-hidden=\"true\">\n <UidIcon :icon=\"eventIcon(entry.event)\" :size=\"14\" />\n </span>\n <div class=\"admin-audit-timeline__body\">\n <div class=\"admin-audit-timeline__row\">\n <UidAvatar\n :name=\"entry.actor?.name ?? '?'\"\n :alt=\"entry.actor?.name ?? 'Неизвестный'\"\n size=\"xs\"\n />\n <span class=\"admin-audit-timeline__actor\">\n {{ entry.actor?.name ?? 'Система' }}\n </span>\n <span class=\"admin-audit-timeline__verb\">\n {{ eventLabel(entry.event) }}\n </span>\n <span class=\"admin-audit-timeline__when\">\n {{ relativeTime(entry.created_at) }}\n </span>\n </div>\n <div v-if=\"diffSummary(entry)\" class=\"admin-audit-timeline__detail\">\n {{ diffSummary(entry) }}\n </div>\n </div>\n </li>\n </ol>\n </section>\n</template>\n\n<style>\n.admin-audit-timeline {\n display: flex;\n flex-direction: column;\n gap: var(--uid-space-sm);\n}\n.admin-audit-timeline__title {\n margin: 0;\n font-family: var(--uid-font-family-display);\n font-size: var(--uid-font-size-lg, 16px);\n font-weight: var(--uid-font-weight-semibold);\n color: var(--uid-text-primary);\n}\n.admin-audit-timeline__list {\n list-style: none;\n margin: 0;\n padding: 0;\n display: flex;\n flex-direction: column;\n gap: var(--uid-space-md);\n position: relative;\n}\n.admin-audit-timeline__list::before {\n content: '';\n position: absolute;\n left: 11px;\n top: 12px;\n bottom: 12px;\n width: 2px;\n background: var(--uid-border-subtle);\n}\n.admin-audit-timeline__item {\n position: relative;\n display: flex;\n gap: var(--uid-space-sm);\n padding-left: 2px;\n}\n.admin-audit-timeline__icon {\n position: relative;\n z-index: 1;\n flex: none;\n width: 24px;\n height: 24px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border-radius: 50%;\n background: var(--uid-surface-base);\n border: 1px solid var(--uid-border-subtle);\n color: var(--uid-text-secondary);\n}\n.admin-audit-timeline__body {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 2px;\n padding-top: 2px;\n}\n.admin-audit-timeline__row {\n display: flex;\n align-items: center;\n gap: var(--uid-space-2xs);\n flex-wrap: wrap;\n}\n.admin-audit-timeline__actor {\n font-size: 13px;\n font-weight: var(--uid-font-weight-semibold);\n color: var(--uid-text-primary);\n}\n.admin-audit-timeline__verb {\n font-size: 13px;\n color: var(--uid-text-secondary);\n}\n.admin-audit-timeline__when {\n margin-left: auto;\n font-size: 12px;\n color: var(--uid-text-tertiary);\n}\n.admin-audit-timeline__detail {\n font-size: 12px;\n color: var(--uid-text-tertiary);\n}\n.admin-audit-timeline__empty,\n.admin-audit-timeline__error {\n font-size: 13px;\n color: var(--uid-text-tertiary);\n}\n.admin-audit-timeline__error { color: var(--uid-color-danger, #dc2626); }\n.admin-audit-timeline__loading {\n display: flex;\n flex-direction: column;\n gap: var(--uid-space-xs);\n}\n</style>\n","<script setup lang=\"ts\">\n/**\n * ResourceViewPage — read-only зеркало form-страницы по дизайну\n * docs/design_handoff_laravel_admin (Resource View):\n *\n * ← Articles Edit … (more menu)\n * {Title}\n * ● Status badge · A-{id}\n *\n * ┌──────────────────────────────┬─────────────────┐\n * │ Card \"Основные данные\" │ Card \"Метрики\" │\n * │ Infolist (manifest.infolist) │ <slot=sidebar> │\n * ├──────────────────────────────┤ │\n * │ Card \"История изменений\" │ │\n * │ AuditTimeline │ │\n * └──────────────────────────────┴─────────────────┘\n */\nimport { computed, onMounted, watch } from 'vue'\nimport { useRouter } from 'vue-router'\nimport { ArrowLeft, MoreHorizontal, Pencil, Trash2 } from 'lucide-vue-next'\nimport {\n UidAlert,\n UidButton,\n UidCard,\n UidIcon,\n UidMenu,\n UidMenuItem,\n UidSkeleton,\n} from '@dskripchenko/ui'\nimport { useResourceFormStore } from '../../stores/resourceForm'\nimport { useManifestStore } from '../../stores/manifest'\nimport InfolistRenderer from '../infolist/InfolistRenderer.vue'\nimport type { InfolistNode } from '../infolist/InfolistRenderer.vue'\nimport { provideRecord } from '../infolist/recordContext'\nimport AuditTimeline from './AuditTimeline.vue'\n\ninterface Props {\n slug: string\n id: string | number\n /** Имя router-route для перехода в edit. */\n editRouteName?: string\n /**\n * Override имени router-route для back-link / возврата после delete.\n * По умолчанию выводится из slug: `admin.resource.{slug}.index`. Если\n * у host'а собственное имя — передаётся явно.\n */\n indexRouteName?: string | null\n /**\n * Override Eloquent morph-class. По умолчанию резолвится из\n * `manifest.resources[slug].subject_type` (Resource::meta()).\n */\n auditSubjectType?: string | null\n /** Поле в record, по которому считать status badge. По умолчанию `status`. */\n statusField?: string\n /** Префикс UID-метки рядом со статусом. Например 'A-' даёт 'A-1284'. */\n uidPrefix?: string\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n editRouteName: undefined,\n indexRouteName: null,\n auditSubjectType: null,\n statusField: 'status',\n uidPrefix: '#',\n})\n\nconst form = useResourceFormStore()\nconst manifest = useManifestStore()\nconst router = useRouter()\n\nprovideRecord(form.state)\n\nconst resourceMeta = computed(() => manifest.getResource(props.slug))\nconst layoutNodes = computed<InfolistNode[]>(\n () => (resourceMeta.value?.infolist ?? resourceMeta.value?.fields ?? []) as InfolistNode[],\n)\n\n/**\n * subject_type для AuditTimeline. Берём в порядке приоритета:\n * 1. props.auditSubjectType (host явно задал) — даже null допустим как\n * explicit \"не показывать\".\n * 2. manifest.resources[slug].subject_type — backend Resource::meta()\n * кладёт morph-alias / FQCN модели.\n *\n * Если оба пусты — timeline не рендерится (Resource без модели либо\n * morph-class не известен фронту).\n */\nconst resolvedSubjectType = computed<string | null>(() => {\n if (props.auditSubjectType !== null) return props.auditSubjectType\n return (resourceMeta.value?.subject_type as string | null | undefined) ?? null\n})\n\n/**\n * Default metrics: created_at / updated_at / created_by из record.\n * Показываем всегда если у записи есть хоть одно из этих полей —\n * стандартные timestamps Eloquent есть у большинства моделей.\n */\ninterface MetricRow {\n label: string\n value: string\n}\nconst defaultMetrics = computed<MetricRow[]>(() => {\n const r = form.state as Record<string, unknown>\n const rows: MetricRow[] = []\n const fmt = (iso: unknown): string | null => {\n if (typeof iso !== 'string' || iso === '') return null\n const ts = new Date(iso)\n if (Number.isNaN(ts.getTime())) return null\n return ts.toLocaleString('ru-RU', {\n day: '2-digit',\n month: '2-digit',\n year: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n })\n }\n const created = fmt(r.created_at)\n if (created) rows.push({ label: 'Создано', value: created })\n const updated = fmt(r.updated_at)\n if (updated && updated !== created) rows.push({ label: 'Обновлено', value: updated })\n const author =\n typeof r.created_by_name === 'string' && r.created_by_name !== ''\n ? r.created_by_name\n : typeof r.author === 'string'\n ? r.author\n : null\n if (author) rows.push({ label: 'Автор', value: author })\n return rows\n})\nconst recordTitle = computed<string>(() => {\n // Запись может иметь поле `title` / `name` / `label` — пробуем по очереди.\n // Иначе fallback на \"{ResourceLabel}: запись #{id}\".\n const r = form.state as Record<string, unknown>\n const t = r.title ?? r.name ?? r.label\n if (typeof t === 'string' && t.length > 0) return t\n return `${resourceMeta.value?.label ?? props.slug}: запись #${props.id}`\n})\nconst indexLabel = computed<string>(\n () => resourceMeta.value?.label ?? props.slug,\n)\nconst uidLabel = computed<string>(() => `${props.uidPrefix}${props.id}`)\n\nconst statusValue = computed<string | null>(() => {\n const r = form.state as Record<string, unknown>\n const v = r[props.statusField]\n return typeof v === 'string' && v.length > 0 ? v : null\n})\n\n/**\n * Маппинг status-значения → визуальный variant. Расширяемо через CSS:\n * `.admin-status-badge[data-status=\"custom\"] { ... }`.\n */\nconst STATUS_VARIANT: Record<string, string> = {\n published: 'success',\n active: 'success',\n enabled: 'success',\n draft: 'neutral',\n pending: 'warning',\n review: 'warning',\n archived: 'muted',\n disabled: 'muted',\n inactive: 'muted',\n deleted: 'danger',\n failed: 'danger',\n error: 'danger',\n}\nfunction statusVariant(s: string): string {\n return STATUS_VARIANT[s.toLowerCase()] ?? 'neutral'\n}\n\n/**\n * Header more-actions — показываем те же `actions[]` из manifest'а что\n * и в index page; здесь они применяются к одной записи (id). Реальный\n * endpoint POST `/{slug}/action/{key}` с body {ids:[id]}.\n */\ninterface HeaderAction {\n key: string\n label: string\n confirm?: string\n}\nconst headerActions = computed<HeaderAction[]>(() => {\n const raw = (resourceMeta.value?.actions ?? []) as Array<Record<string, unknown>>\n return raw\n .map((a) => ({\n key: String(a.key ?? a.name ?? ''),\n label: String(a.label ?? a.name ?? a.key ?? ''),\n confirm: typeof a.confirm === 'string' ? a.confirm : undefined,\n }))\n .filter((a) => a.key !== '' && a.label !== '')\n})\n\nasync function onCustomAction(action: HeaderAction): Promise<void> {\n if (action.confirm && !window.confirm(action.confirm)) return\n try {\n const { getAdminClient } = await import('../../stores/registry')\n const client = getAdminClient()\n await client.post(`/${props.slug}/action/${action.key}`, { ids: [props.id] })\n await form.load(props.slug, props.id, 'view').catch(() => undefined)\n } catch (err) {\n if (typeof console !== 'undefined') console.error('[admin] action failed:', err)\n }\n}\n\nonMounted(async () => {\n if (manifest.manifest === null) {\n await manifest.load().catch(() => undefined)\n }\n await form.load(props.slug, props.id, 'view').catch(() => undefined)\n})\n\nwatch(\n () => [props.slug, props.id] as const,\n async ([s, id]) => {\n await form.load(s, id, 'view').catch(() => undefined)\n },\n)\n\n/**\n * Имя index-роута для back-link и redirect после delete. Default —\n * `admin.resource.{slug}.index` (зарегистрирован buildResourceRoutes).\n * Host может override через prop indexRouteName.\n */\nconst resolvedIndexRouteName = computed<string>(\n () => props.indexRouteName ?? `admin.resource.${props.slug}.index`,\n)\n\nfunction onBack(): void {\n router.push({ name: resolvedIndexRouteName.value }).catch(() => {\n // Fallback на path-based push если route не найден.\n void router.push(`/r/${props.slug}`)\n })\n}\n\nfunction onEdit(): void {\n if (!props.editRouteName) {\n router\n .push(`/r/${props.slug}/${props.id}/edit`)\n .catch(() => undefined)\n return\n }\n router\n .push({ name: props.editRouteName, params: { id: props.id } })\n .catch(() => undefined)\n}\n\nasync function onDelete(): Promise<void> {\n if (!confirm('Удалить запись?')) return\n await form.destroy().catch(() => undefined)\n if (!form.hasError) {\n router.push({ name: resolvedIndexRouteName.value }).catch(() => undefined)\n }\n}\n</script>\n\n<template>\n <section class=\"admin-page admin-resource-view\">\n <header class=\"admin-resource-view__hd\">\n <div class=\"admin-resource-view__hd-left\">\n <button type=\"button\" class=\"admin-resource-view__back\" @click=\"onBack\">\n <UidIcon :icon=\"ArrowLeft\" :size=\"14\" />\n {{ indexLabel }}\n </button>\n <h1 class=\"admin-page__title\">{{ recordTitle }}</h1>\n <div class=\"admin-resource-view__meta\">\n <span\n v-if=\"statusValue\"\n class=\"admin-status-badge\"\n :data-variant=\"statusVariant(statusValue)\"\n :data-status=\"statusValue\"\n >\n <span class=\"admin-status-badge__dot\" aria-hidden=\"true\" />\n {{ statusValue }}\n </span>\n <span class=\"admin-resource-view__uid\">{{ uidLabel }}</span>\n </div>\n </div>\n <div class=\"admin-resource-view__hd-right\">\n <UidButton variant=\"secondary\" size=\"md\" @click=\"onEdit\">\n <template #prepend><UidIcon :icon=\"Pencil\" :size=\"14\" /></template>\n Редактировать\n </UidButton>\n <UidMenu>\n <template #trigger>\n <UidButton variant=\"ghost\" size=\"md\" aria-label=\"Действия\" class=\"admin-page__more\">\n <UidIcon :icon=\"MoreHorizontal\" :size=\"16\" />\n </UidButton>\n </template>\n <UidMenuItem\n v-for=\"a in headerActions\"\n :key=\"a.key\"\n @click=\"onCustomAction(a)\"\n >\n {{ a.label }}\n </UidMenuItem>\n <UidMenuItem variant=\"danger\" @click=\"onDelete\">\n <template #icon><UidIcon :icon=\"Trash2\" :size=\"14\" /></template>\n Удалить\n </UidMenuItem>\n </UidMenu>\n </div>\n </header>\n\n <UidAlert\n v-if=\"form.hasError\"\n variant=\"danger\"\n class=\"admin-resource-view__alert\"\n role=\"alert\"\n >\n {{ form.error?.message ?? 'Не удалось загрузить запись' }}\n </UidAlert>\n\n <div v-if=\"form.loading\" class=\"admin-resource-view__loading\">\n <UidSkeleton v-for=\"i in 8\" :key=\"i\" height=\"24px\" />\n </div>\n\n <div v-else class=\"admin-resource-view__grid\">\n <div class=\"admin-resource-view__main\">\n <UidCard padding=\"md\" class=\"admin-resource-view__card\">\n <h2 class=\"admin-resource-view__card-title\">Основные данные</h2>\n <InfolistRenderer\n v-for=\"(node, idx) in layoutNodes\"\n :key=\"idx\"\n :node=\"node\"\n />\n </UidCard>\n\n <UidCard\n padding=\"md\"\n class=\"admin-resource-view__card\"\n >\n <AuditTimeline\n :subject-type=\"resolvedSubjectType\"\n :subject-id=\"id\"\n />\n </UidCard>\n </div>\n\n <aside class=\"admin-resource-view__aside\">\n <!--\n Default «Метрики» card — created_at / updated_at / автор из record.\n Host может полностью переопределить через slot=sidebar.\n -->\n <UidCard\n v-if=\"defaultMetrics.length > 0\"\n padding=\"md\"\n class=\"admin-resource-view__card\"\n >\n <h2 class=\"admin-resource-view__card-title\">Метрики</h2>\n <dl class=\"admin-resource-view__metrics\">\n <template v-for=\"row in defaultMetrics\" :key=\"row.label\">\n <dt class=\"admin-resource-view__metric-label\">{{ row.label }}</dt>\n <dd class=\"admin-resource-view__metric-value\">{{ row.value }}</dd>\n </template>\n </dl>\n </UidCard>\n\n <slot name=\"sidebar\" :record=\"form.state\" :resource=\"resourceMeta\" />\n </aside>\n </div>\n </section>\n</template>\n\n<style>\n.admin-resource-view__alert {\n margin-bottom: var(--uid-space-md);\n}\n.admin-resource-view__loading {\n display: flex;\n flex-direction: column;\n gap: var(--uid-space-sm);\n}\n\n/* Header */\n.admin-resource-view__hd {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: var(--uid-space-md);\n margin-bottom: var(--uid-space-md);\n}\n.admin-resource-view__hd-left {\n display: flex;\n flex-direction: column;\n gap: var(--uid-space-2xs);\n min-width: 0;\n}\n.admin-resource-view__hd-right {\n display: flex;\n align-items: center;\n gap: var(--uid-space-sm);\n flex: none;\n}\n.admin-resource-view__back {\n display: inline-flex;\n align-items: center;\n gap: var(--uid-space-2xs);\n padding: 0;\n margin: 0;\n font-size: 13px;\n color: var(--uid-text-tertiary);\n background: transparent;\n border: 0;\n cursor: pointer;\n align-self: flex-start;\n}\n.admin-resource-view__back:hover {\n color: var(--uid-text-primary);\n}\n.admin-resource-view__meta {\n display: flex;\n align-items: center;\n gap: var(--uid-space-sm);\n margin-top: var(--uid-space-2xs);\n}\n.admin-resource-view__uid {\n font-family: var(--uid-font-family-mono, ui-monospace, monospace);\n font-size: 12px;\n color: var(--uid-text-tertiary);\n letter-spacing: 0.02em;\n}\n\n/* Status badge */\n.admin-status-badge {\n display: inline-flex;\n align-items: center;\n gap: var(--uid-space-2xs);\n padding: 2px 8px 2px 6px;\n border-radius: var(--uid-radius-sm);\n font-size: 12px;\n font-weight: var(--uid-font-weight-medium);\n text-transform: capitalize;\n}\n.admin-status-badge__dot {\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: currentColor;\n flex: none;\n}\n.admin-status-badge[data-variant='success'] {\n background: color-mix(in srgb, var(--uid-color-success, #10b981) 15%, transparent);\n color: var(--uid-color-success, #10b981);\n}\n.admin-status-badge[data-variant='warning'] {\n background: color-mix(in srgb, var(--uid-color-warning, #f59e0b) 15%, transparent);\n color: var(--uid-color-warning, #f59e0b);\n}\n.admin-status-badge[data-variant='danger'] {\n background: color-mix(in srgb, var(--uid-color-danger, #dc2626) 15%, transparent);\n color: var(--uid-color-danger, #dc2626);\n}\n.admin-status-badge[data-variant='neutral'],\n.admin-status-badge[data-variant='muted'] {\n background: var(--uid-border-subtle);\n color: var(--uid-text-secondary);\n}\n\n/* Two-column grid */\n.admin-resource-view__grid {\n display: grid;\n grid-template-columns: minmax(0, 1fr) 320px;\n gap: var(--uid-space-md);\n align-items: start;\n}\n@media (max-width: 1024px) {\n .admin-resource-view__grid {\n grid-template-columns: 1fr;\n }\n}\n.admin-resource-view__main {\n display: flex;\n flex-direction: column;\n gap: var(--uid-space-md);\n min-width: 0;\n}\n.admin-resource-view__aside {\n display: flex;\n flex-direction: column;\n gap: var(--uid-space-md);\n}\n.admin-resource-view__card {\n display: flex;\n flex-direction: column;\n gap: var(--uid-space-md);\n}\n.admin-resource-view__card-title {\n margin: 0;\n font-family: var(--uid-font-family-display);\n font-size: var(--uid-font-size-lg, 16px);\n font-weight: var(--uid-font-weight-semibold);\n color: var(--uid-text-primary);\n}\n\n/* Metrics list — label/value pair stacked vertically. */\n.admin-resource-view__metrics {\n display: flex;\n flex-direction: column;\n gap: var(--uid-space-md);\n margin: 0;\n padding: 0;\n}\n.admin-resource-view__metric-label {\n font-size: 11px;\n letter-spacing: 0.06em;\n text-transform: uppercase;\n font-weight: var(--uid-font-weight-medium);\n color: var(--uid-text-tertiary);\n margin: 0;\n}\n.admin-resource-view__metric-value {\n font-size: 14px;\n color: var(--uid-text-primary);\n margin: 4px 0 0;\n font-variant-numeric: tabular-nums;\n}\n</style>\n","<script setup lang=\"ts\">\n/**\n * ProfilePage — профильный экран по эталону handoff'а (screens-secondary.jsx\n * → Profile). Layout 200px nav / 1fr cards.\n *\n * Slot model: каждая section экспонирует свою карточку. По умолчанию\n * library рендерит общие \"Основное\" + \"Безопасность\" (на existing-данных\n * auth.user). Host подмешивает свои \"API токены\" и \"Сессии\" через slot'ы.\n */\nimport { computed, ref, watch } from 'vue'\nimport {\n UidAvatar,\n UidBadge,\n UidButton,\n UidCard,\n UidInput,\n UidSelect,\n} from '@dskripchenko/ui'\nimport { useAuthStore } from '../../stores/auth'\nimport { useThemeStore } from '../../stores/theme'\nimport { useLocaleStore } from '../../stores/locale'\n\ninterface Props {\n /** Заголовок страницы (по умолчанию «Profile»). */\n title?: string\n /** Подзаголовок (по умолчанию из handoff'а). */\n subtitle?: string\n /** Какая section активна. */\n section?: 'general' | 'security' | 'tokens' | 'sessions' | string\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n title: 'Profile',\n subtitle: 'Личные данные, безопасность, токены',\n section: 'general',\n})\n\nconst emit = defineEmits<{\n 'update:section': [value: string]\n /** Host реагирует — например запросом /me/uploadAvatar. */\n 'avatar-replace': []\n /** 2FA disable triggered — host показывает confirmation modal. */\n 'two-factor-disable': []\n /** 2FA recovery-codes regenerate. */\n 'two-factor-regenerate': []\n /** Save profile fields. */\n save: [payload: { name: string; email: string; locale: string; theme: string }]\n}>()\n\nconst auth = useAuthStore()\nconst theme = useThemeStore()\nconst locale = useLocaleStore()\n\nconst navItems = [\n { id: 'general', label: 'Основное', icon: 'user' },\n { id: 'security', label: 'Безопасность', icon: 'shield' },\n { id: 'tokens', label: 'API токены', icon: 'key' },\n { id: 'sessions', label: 'Сессии', icon: 'monitor' },\n]\n\nconst localSection = ref(props.section)\nfunction selectSection(id: string): void {\n localSection.value = id\n emit('update:section', id)\n}\n\n// Form-state для general-tab.\nconst profile = ref({\n name: auth.user?.name ?? '',\n email: auth.user?.email ?? '',\n locale: locale.current,\n theme: theme.current,\n})\n\nconst localeOptions = computed(() =>\n locale.available.map((l) => ({ value: l, label: l.toUpperCase() })),\n)\nconst themeOptions = computed(() =>\n theme.available.map((t) => ({ value: t, label: t === 'dark' ? 'Тёмная' : t === 'light' ? 'Светлая' : t })),\n)\n\n// Locale / theme применяются мгновенно при изменении select'а — не требуют\n// клика \"Сохранить\". Это стандартный admin-UX (как в GitHub/Vercel/Linear).\nwatch(\n () => profile.value.locale,\n (next, prev) => {\n if (next === prev || !next) return\n void locale.setLocale(next).catch(() => undefined)\n },\n)\n\nwatch(\n () => profile.value.theme,\n (next, prev) => {\n if (next === prev || !next) return\n void theme.setTheme(next).catch(() => undefined)\n },\n)\n\nfunction onSave(): void {\n emit('save', { ...profile.value })\n}\n\nfunction onAvatarReplace(): void {\n emit('avatar-replace')\n}\n\nfunction on2FADisable(): void {\n emit('two-factor-disable')\n}\n\nfunction on2FARegenerate(): void {\n emit('two-factor-regenerate')\n}\n\nconst has2FA = computed(() => Boolean(auth.user?.twoFactorEnabled))\n</script>\n\n<template>\n <section class=\"admin-page admin-profile\">\n <header class=\"admin-page__hd\">\n <div class=\"admin-page__title-wrap\">\n <h1 class=\"admin-page__title\">{{ title }}</h1>\n <div class=\"admin-page__count\">{{ subtitle }}</div>\n </div>\n </header>\n\n <div class=\"admin-profile__layout\">\n <nav class=\"admin-profile__nav\" aria-label=\"Profile sections\">\n <button\n v-for=\"item in navItems\"\n :key=\"item.id\"\n type=\"button\"\n :class=\"[\n 'admin-profile__nav-item',\n { 'admin-profile__nav-item--active': localSection === item.id },\n ]\"\n @click=\"selectSection(item.id)\"\n >\n <span class=\"admin-profile__nav-icon\" :data-icon=\"item.icon\" />\n <span>{{ item.label }}</span>\n </button>\n </nav>\n\n <div class=\"admin-profile__content\">\n <!-- General -->\n <UidCard v-if=\"localSection === 'general'\" padding=\"md\">\n <header class=\"admin-profile__card-hd\">\n <h3 class=\"admin-profile__card-title\">Профиль</h3>\n </header>\n\n <div class=\"admin-profile__hero\">\n <UidAvatar\n :src=\"auth.user?.avatar ?? undefined\"\n :name=\"auth.user?.name ?? '?'\"\n size=\"lg\"\n />\n <div class=\"admin-profile__hero-text\">\n <div class=\"admin-profile__hero-name\">{{ auth.user?.name ?? '—' }}</div>\n <div class=\"admin-profile__hero-meta\">\n {{ auth.user?.email ?? '—' }}\n </div>\n </div>\n <div style=\"flex:1\" />\n <UidButton variant=\"ghost\" size=\"sm\" @click=\"onAvatarReplace\">\n Заменить\n </UidButton>\n </div>\n\n <div class=\"admin-profile__form\">\n <UidInput\n v-model=\"profile.name\"\n label=\"Имя\"\n name=\"name\"\n />\n <UidInput\n v-model=\"profile.email\"\n label=\"Email\"\n type=\"email\"\n name=\"email\"\n />\n <UidSelect\n v-model=\"profile.locale\"\n :options=\"localeOptions\"\n label=\"Язык\"\n />\n <UidSelect\n v-model=\"profile.theme\"\n :options=\"themeOptions\"\n label=\"Тема\"\n />\n </div>\n\n <footer class=\"admin-profile__card-ft\">\n <UidButton variant=\"primary\" @click=\"onSave\">Сохранить</UidButton>\n </footer>\n </UidCard>\n\n <!-- Security -->\n <UidCard v-else-if=\"localSection === 'security'\" padding=\"md\">\n <header class=\"admin-profile__card-hd\">\n <h3 class=\"admin-profile__card-title\">Двухфакторная аутентификация</h3>\n <UidBadge :variant=\"has2FA ? 'success' : 'default'\">\n {{ has2FA ? 'Включена' : 'Отключена' }}\n </UidBadge>\n </header>\n\n <p v-if=\"has2FA\" class=\"admin-profile__hint\">\n 2FA включена. У вас остались recovery-коды на случай потери устройства.\n </p>\n <p v-else class=\"admin-profile__hint\">\n Включите 2FA для дополнительной защиты аккаунта.\n </p>\n\n <footer class=\"admin-profile__card-ft\">\n <template v-if=\"has2FA\">\n <UidButton variant=\"ghost\" size=\"sm\" @click=\"on2FARegenerate\">\n Перегенерировать коды\n </UidButton>\n <UidButton variant=\"danger\" size=\"sm\" @click=\"on2FADisable\">\n Отключить 2FA\n </UidButton>\n </template>\n <template v-else>\n <slot name=\"enable-2fa\">\n <UidButton variant=\"primary\" disabled>\n Включить 2FA (host customize)\n </UidButton>\n </slot>\n </template>\n </footer>\n </UidCard>\n\n <!-- Tokens / Sessions / другое — host рендерит через slot -->\n <slot v-else :name=\"localSection\" :section=\"localSection\">\n <UidCard padding=\"md\">\n <p class=\"admin-profile__hint\">\n Section «{{ localSection }}» не реализована библиотекой —\n host-проект подключает её через slot {{ localSection }}.\n </p>\n </UidCard>\n </slot>\n </div>\n </div>\n </section>\n</template>\n\n<style>\n.admin-profile__layout {\n display: grid;\n grid-template-columns: 200px 1fr;\n gap: var(--uid-space-lg);\n align-items: start;\n}\n.admin-profile__nav {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n.admin-profile__nav-item {\n appearance: none;\n border: 0;\n background: transparent;\n text-align: left;\n display: flex;\n align-items: center;\n gap: var(--uid-space-sm);\n padding: var(--uid-space-sm) var(--uid-space-sm);\n border-radius: var(--uid-radius-md);\n font-size: 13px;\n color: var(--uid-text-secondary);\n cursor: pointer;\n}\n.admin-profile__nav-item:hover {\n background: var(--uid-surface-hover);\n color: var(--uid-text-primary);\n}\n.admin-profile__nav-item--active {\n background: var(--uid-surface-base);\n color: var(--uid-text-primary);\n font-weight: var(--uid-font-weight-medium);\n}\n.admin-profile__nav-icon {\n width: 14px;\n height: 14px;\n flex: none;\n}\n.admin-profile__content {\n display: flex;\n flex-direction: column;\n gap: var(--uid-space-md);\n}\n\n.admin-profile__card-hd {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: var(--uid-space-md);\n}\n.admin-profile__card-title {\n margin: 0;\n font-size: var(--uid-font-size-sm);\n font-weight: var(--uid-font-weight-semibold);\n}\n.admin-profile__card-ft {\n margin-top: var(--uid-space-md);\n display: flex;\n gap: var(--uid-space-sm);\n}\n.admin-profile__hint {\n margin: 0;\n font-size: var(--uid-font-size-sm);\n color: var(--uid-text-secondary);\n}\n\n.admin-profile__hero {\n display: flex;\n align-items: center;\n gap: var(--uid-space-md);\n margin-bottom: var(--uid-space-md);\n}\n.admin-profile__hero-text { display: flex; flex-direction: column; gap: 4px; }\n.admin-profile__hero-name {\n font-weight: var(--uid-font-weight-semibold);\n color: var(--uid-text-primary);\n}\n.admin-profile__hero-meta {\n font-size: var(--uid-font-size-xs);\n color: var(--uid-text-tertiary);\n}\n\n.admin-profile__form {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: var(--uid-space-md);\n}\n@media (max-width: 720px) {\n .admin-profile__form { grid-template-columns: 1fr; }\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { UidStat } from '@dskripchenko/ui'\nimport type { StatTone } from '@dskripchenko/ui'\n\ntype SemanticTone = 'neutral' | 'positive' | 'negative' | 'warning' | 'info'\n\ninterface Props {\n title?: string\n value?: number | string\n prefix?: string\n suffix?: string\n trend?: number\n precision?: number\n tone?: SemanticTone\n loading?: boolean\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n title: '',\n value: 0,\n prefix: '',\n suffix: '',\n trend: undefined,\n precision: 0,\n tone: 'neutral',\n loading: false,\n})\n\nconst TONE_MAP: Record<SemanticTone, StatTone> = {\n neutral: 'primary',\n positive: 'success',\n negative: 'danger',\n warning: 'warning',\n info: 'info',\n}\n\nconst uidTone = computed<StatTone>(() => TONE_MAP[props.tone])\n</script>\n\n<template>\n <UidStat\n :title=\"title\"\n :value=\"value\"\n :prefix=\"prefix\"\n :suffix=\"suffix\"\n :trend=\"trend\"\n :precision=\"precision\"\n :tone=\"uidTone\"\n :loading=\"loading\"\n />\n</template>\n","<script setup lang=\"ts\">\n/**\n * BarChartWidget — простой SVG-bar chart без внешних зависимостей.\n *\n * Manifest:\n * { type: 'bar-chart', title: '30 дней',\n * data: [{ label: '01', value: 12 }, ...],\n * accent: 'var(--uid-accent)' }\n */\nimport { computed } from 'vue'\nimport { UidCard } from '@dskripchenko/ui'\n\ninterface Datum {\n label: string\n value: number\n}\n\ninterface Props {\n title?: string\n description?: string\n data: Datum[]\n accent?: string\n height?: number\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n title: '',\n description: '',\n accent: 'var(--uid-accent)',\n height: 200,\n})\n\nconst maxValue = computed(() => Math.max(1, ...props.data.map((d) => d.value)))\n\nconst bars = computed(() => {\n const n = Math.max(1, props.data.length)\n const barWidth = 100 / n\n return props.data.map((d, i) => ({\n label: d.label,\n value: d.value,\n x: i * barWidth + barWidth * 0.1,\n width: barWidth * 0.8,\n heightPct: (d.value / maxValue.value) * 100,\n }))\n})\n</script>\n\n<template>\n <UidCard padding=\"md\" class=\"admin-widget\">\n <header v-if=\"title || description\" class=\"admin-widget__hd\">\n <h3 v-if=\"title\" class=\"admin-widget__title\">{{ title }}</h3>\n <p v-if=\"description\" class=\"admin-widget__desc\">{{ description }}</p>\n </header>\n <svg\n class=\"admin-widget-bar-chart\"\n :viewBox=\"`0 0 100 ${height}`\"\n preserveAspectRatio=\"none\"\n :height=\"height\"\n width=\"100%\"\n role=\"img\"\n :aria-label=\"title || 'Bar chart'\"\n >\n <rect\n v-for=\"(bar, idx) in bars\"\n :key=\"idx\"\n :x=\"bar.x\"\n :y=\"height - (bar.heightPct / 100) * height\"\n :width=\"bar.width\"\n :height=\"(bar.heightPct / 100) * height\"\n :fill=\"accent\"\n rx=\"1\"\n :data-label=\"bar.label\"\n :data-value=\"bar.value\"\n >\n <title>{{ bar.label }}: {{ bar.value }}</title>\n </rect>\n </svg>\n </UidCard>\n</template>\n\n<style>\n.admin-widget__hd { margin-bottom: var(--uid-space-sm); }\n.admin-widget__title {\n margin: 0;\n font-size: var(--uid-font-size-sm);\n font-weight: var(--uid-font-weight-semibold);\n color: var(--uid-text-primary);\n}\n.admin-widget__desc {\n margin: var(--uid-space-2xs) 0 0;\n font-size: var(--uid-font-size-xs);\n color: var(--uid-text-tertiary);\n}\n.admin-widget-bar-chart {\n display: block;\n width: 100%;\n}\n</style>\n","<script setup lang=\"ts\">\n/**\n * DonutChartWidget — SVG donut + legend.\n *\n * Manifest:\n * { type: 'donut-chart', title: 'Status',\n * data: [{ label: 'Published', value: 156, color: '...' }, ...] }\n */\nimport { computed } from 'vue'\nimport { UidCard } from '@dskripchenko/ui'\n\ninterface Slice {\n label: string\n value: number\n color?: string\n}\n\ninterface Props {\n title?: string\n data: Slice[]\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n title: '',\n})\n\nconst PALETTE = [\n 'var(--uid-color-teal-500, #14b8a6)',\n 'var(--uid-color-zinc-700, #3f3f46)',\n 'var(--uid-color-amber-400, #fbbf24)',\n 'var(--uid-color-rose-400, #fb7185)',\n 'var(--uid-color-blue-400, #60a5fa)',\n]\n\nconst total = computed(() => props.data.reduce((s, x) => s + x.value, 0) || 1)\n\nconst slices = computed(() => {\n let cumulative = 0\n return props.data.map((s, idx) => {\n const startAngle = (cumulative / total.value) * 2 * Math.PI\n cumulative += s.value\n const endAngle = (cumulative / total.value) * 2 * Math.PI\n\n const r = 50\n const cx = 60\n const cy = 60\n\n const x1 = cx + r * Math.cos(startAngle - Math.PI / 2)\n const y1 = cy + r * Math.sin(startAngle - Math.PI / 2)\n const x2 = cx + r * Math.cos(endAngle - Math.PI / 2)\n const y2 = cy + r * Math.sin(endAngle - Math.PI / 2)\n\n const largeArc = endAngle - startAngle > Math.PI ? 1 : 0\n\n const path = props.data.length === 1\n ? `M ${cx - r} ${cy} a ${r} ${r} 0 1 0 ${r * 2} 0 a ${r} ${r} 0 1 0 ${-r * 2} 0`\n : `M ${cx} ${cy} L ${x1} ${y1} A ${r} ${r} 0 ${largeArc} 1 ${x2} ${y2} Z`\n\n return {\n ...s,\n path,\n color: s.color ?? PALETTE[idx % PALETTE.length],\n pct: ((s.value / total.value) * 100).toFixed(1),\n }\n })\n})\n</script>\n\n<template>\n <UidCard padding=\"md\" class=\"admin-widget admin-donut-widget\">\n <header v-if=\"title\" class=\"admin-widget__hd\">\n <h3 class=\"admin-widget__title\">{{ title }}</h3>\n </header>\n <div class=\"admin-donut-widget__row\">\n <svg viewBox=\"0 0 120 120\" class=\"admin-donut-widget__svg\" role=\"img\" :aria-label=\"title\">\n <path\n v-for=\"(s, idx) in slices\"\n :key=\"idx\"\n :d=\"s.path\"\n :fill=\"s.color\"\n >\n <title>{{ s.label }}: {{ s.value }} ({{ s.pct }}%)</title>\n </path>\n <circle cx=\"60\" cy=\"60\" r=\"30\" fill=\"var(--uid-surface-raised)\" />\n </svg>\n <ul class=\"admin-donut-widget__legend\">\n <li v-for=\"(s, idx) in slices\" :key=\"idx\">\n <span class=\"admin-donut-widget__dot\" :style=\"{ background: s.color }\" />\n <span class=\"admin-donut-widget__label\">{{ s.label }}</span>\n <span class=\"admin-donut-widget__value\">{{ s.pct }}%</span>\n </li>\n </ul>\n </div>\n </UidCard>\n</template>\n\n<style>\n.admin-donut-widget__row {\n display: flex;\n align-items: center;\n gap: var(--uid-space-md);\n}\n.admin-donut-widget__svg {\n width: 120px;\n height: 120px;\n flex: none;\n}\n.admin-donut-widget__legend {\n list-style: none;\n margin: 0;\n padding: 0;\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: var(--uid-space-xs);\n}\n.admin-donut-widget__legend li {\n display: flex;\n align-items: center;\n gap: var(--uid-space-sm);\n font-size: var(--uid-font-size-xs);\n}\n.admin-donut-widget__dot {\n width: 10px;\n height: 10px;\n border-radius: var(--uid-radius-full);\n flex: none;\n}\n.admin-donut-widget__label { flex: 1; color: var(--uid-text-primary); }\n.admin-donut-widget__value {\n color: var(--uid-text-tertiary);\n font-variant-numeric: tabular-nums;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { UidCard, UidTable, type UidTableColumn } from '@dskripchenko/ui'\n\ninterface Props {\n title?: string\n columns: UidTableColumn[]\n rows: Record<string, unknown>[]\n emptyText?: string\n}\n\nwithDefaults(defineProps<Props>(), {\n title: '',\n emptyText: 'Нет данных',\n})\n</script>\n\n<template>\n <UidCard padding=\"md\" class=\"admin-widget\">\n <header v-if=\"title\" class=\"admin-widget__hd\">\n <h3 class=\"admin-widget__title\">{{ title }}</h3>\n </header>\n <UidTable :columns=\"columns\" :data=\"rows\" :empty-text=\"emptyText\" />\n </UidCard>\n</template>\n","<script setup lang=\"ts\">\nimport { UidCard, UidHeatmap } from '@dskripchenko/ui'\n\ninterface HeatmapPoint {\n date: string\n value: number\n}\n\ninterface Props {\n title?: string\n data: HeatmapPoint[]\n levels?: number\n color?: string\n gap?: number\n}\n\nwithDefaults(defineProps<Props>(), {\n title: '',\n levels: 5,\n color: undefined,\n gap: 2,\n})\n</script>\n\n<template>\n <UidCard padding=\"md\" class=\"admin-widget\">\n <header v-if=\"title\" class=\"admin-widget__hd\">\n <h3 class=\"admin-widget__title\">{{ title }}</h3>\n </header>\n <UidHeatmap :data=\"data\" :levels=\"levels\" :color=\"color\" :gap=\"gap\" />\n </UidCard>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { UidCard, UidGauge } from '@dskripchenko/ui'\nimport type { GaugeTone, GaugeRange } from '@dskripchenko/ui'\n\ntype SemanticTone = 'neutral' | 'positive' | 'warning' | 'negative'\n\ninterface Props {\n title?: string\n value?: number\n min?: number\n max?: number\n size?: number\n ranges?: GaugeRange[]\n tone?: SemanticTone\n color?: string\n label?: string\n suffix?: string\n precision?: number\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n title: '',\n value: 0,\n min: 0,\n max: 100,\n size: 160,\n ranges: () => [],\n tone: 'neutral',\n color: undefined,\n label: '',\n suffix: '',\n precision: 0,\n})\n\nconst TONE_MAP: Record<SemanticTone, GaugeTone> = {\n neutral: 'primary',\n positive: 'success',\n warning: 'warning',\n negative: 'danger',\n}\n\nconst uidTone = computed<GaugeTone>(() => TONE_MAP[props.tone])\n</script>\n\n<template>\n <UidCard padding=\"md\" class=\"admin-widget\">\n <header v-if=\"title\" class=\"admin-widget__hd\">\n <h3 class=\"admin-widget__title\">{{ title }}</h3>\n </header>\n <div style=\"display:flex; justify-content:center;\">\n <UidGauge\n :value=\"value\"\n :min=\"min\"\n :max=\"max\"\n :size=\"size\"\n :ranges=\"ranges\"\n :tone=\"uidTone\"\n :color=\"color\"\n :label=\"label\"\n :suffix=\"suffix\"\n :precision=\"precision\"\n />\n </div>\n </UidCard>\n</template>\n","<script setup lang=\"ts\">\n/**\n * Markdown widget — простой preformatted-блок. Для production хост может\n * подкинуть свой widget с marked/MDX через registerWidget('markdown', ...).\n *\n * Тут — fallback с базовым форматированием через line-break preserve.\n */\nimport { UidCard } from '@dskripchenko/ui'\n\ninterface Props {\n title?: string\n content: string\n}\n\nwithDefaults(defineProps<Props>(), { title: '' })\n</script>\n\n<template>\n <UidCard padding=\"md\" class=\"admin-widget\">\n <header v-if=\"title\" class=\"admin-widget__hd\">\n <h3 class=\"admin-widget__title\">{{ title }}</h3>\n </header>\n <div class=\"admin-markdown-widget\">{{ content }}</div>\n </UidCard>\n</template>\n\n<style>\n.admin-markdown-widget {\n font-size: var(--uid-font-size-sm);\n color: var(--uid-text-secondary);\n white-space: pre-wrap;\n line-height: var(--uid-line-height-normal);\n}\n</style>\n","<script setup lang=\"ts\">\n/**\n * ChartWidget — диспетчер по `data.type` (bar / line / pie / doughnut / area).\n *\n * Backend ChartWidget::data() отдаёт `{type, labels, datasets, ...}`. Эта\n * frontend-обёртка трансформирует структуру в plain Datum/Slice массивы\n * и делегирует рисование специализированным компонентам (Bar/Donut/...).\n */\nimport { computed } from 'vue'\nimport BarChartWidget from './BarChartWidget.vue'\nimport DonutChartWidget from './DonutChartWidget.vue'\nimport UnknownWidget from './UnknownWidget.vue'\n\ninterface ChartDataset {\n label: string\n data: number[]\n color?: string\n}\ninterface ChartData {\n type?: string\n labels?: string[]\n datasets?: ChartDataset[]\n}\n\ninterface Props {\n type?: string\n title?: string\n size?: number\n data?: ChartData\n}\nconst props = defineProps<Props>()\n\nconst chartType = computed<string>(() => props.data?.type ?? 'bar')\n\n/**\n * Палитра по умолчанию для donut/pie. Берём из --uid-* токенов, fallback —\n * статические цвета. Backend может прислать `color` в dataset — тогда\n * предпочтение ему.\n */\nconst DEFAULT_PALETTE = [\n '#10b981', // teal-500\n '#f59e0b', // amber-500\n '#9ca3af', // gray-400\n '#3b82f6', // blue-500\n '#dc2626', // red-600\n '#a855f7', // purple-500\n '#ec4899', // pink-500\n]\n\n/**\n * Bar/line/area-чарты ожидают список {label, value}.\n * Берём первый dataset (multi-dataset stacked будет реализован в следующей\n * итерации).\n */\nconst barData = computed(() => {\n const ds = props.data?.datasets?.[0]\n if (!ds) return []\n return ds.data.map((v, i) => ({\n label: props.data?.labels?.[i] ?? String(i + 1),\n value: v,\n }))\n})\n\nconst barAccent = computed<string | undefined>(\n () => props.data?.datasets?.[0]?.color,\n)\n\n/** Donut/pie — каждый item получает свою долю общего total. */\nconst donutData = computed(() => {\n const ds = props.data?.datasets?.[0]\n if (!ds) return []\n return ds.data.map((v, i) => ({\n label: props.data?.labels?.[i] ?? String(i + 1),\n value: v,\n color: ds.color ?? DEFAULT_PALETTE[i % DEFAULT_PALETTE.length],\n }))\n})\n</script>\n\n<template>\n <DonutChartWidget\n v-if=\"chartType === 'doughnut' || chartType === 'pie'\"\n :title=\"title\"\n :data=\"donutData\"\n />\n <BarChartWidget\n v-else-if=\"chartType === 'bar' || chartType === 'line' || chartType === 'area'\"\n :title=\"title\"\n :data=\"barData\"\n :accent=\"barAccent\"\n />\n <UnknownWidget v-else :type=\"`chart:${chartType}`\" />\n</template>\n","/**\n * Default-bundle с минимальным набором builtin widget-типов.\n */\n\nimport { registerWidgets } from './registry'\nimport StatWidget from './StatWidget.vue'\nimport BarChartWidget from './BarChartWidget.vue'\nimport DonutChartWidget from './DonutChartWidget.vue'\nimport ChartWidget from './ChartWidget.vue'\nimport RecentTableWidget from './RecentTableWidget.vue'\nimport HeatmapWidget from './HeatmapWidget.vue'\nimport GaugeWidget from './GaugeWidget.vue'\nimport MarkdownWidget from './MarkdownWidget.vue'\n\n/**\n * Регистрирует встроенные widget-компоненты + backend-aliases. Имена\n * слева совпадают с тем что отдают backend Widget::widgetType()\n * (`stats`/`chart`/`recent_list` и т.д.); справа — frontend Vue-компонент.\n */\nexport function registerBuiltinWidgets(): void {\n registerWidgets({\n // Stat / Stats overview\n stat: StatWidget,\n stats: StatWidget,\n // Charts: универсальный диспетчер по data.type → bar/donut/...\n chart: ChartWidget,\n 'bar-chart': BarChartWidget,\n 'donut-chart': DonutChartWidget,\n // Recent list (таблица последних записей)\n 'recent-table': RecentTableWidget,\n recent_list: RecentTableWidget,\n 'recent-list': RecentTableWidget,\n // Heatmap / Gauge / Markdown\n heatmap: HeatmapWidget,\n gauge: GaugeWidget,\n markdown: MarkdownWidget,\n })\n}\n","/**\n * Контракт ответов laravel-api: каждое тело — `{success, payload}`.\n *\n * Success: `{success: true, payload: {...}}`\n * Error: `{success: false, payload: {errorKey, message, ...}}`\n *\n * Helper'ы здесь — для type-narrowing'а в потребителях.\n */\n\nexport interface SuccessEnvelope<T = unknown> {\n success: true\n payload: T\n}\n\nexport interface ErrorEnvelope {\n success: false\n payload: {\n errorKey: string\n message: string\n messages?: Record<string, string[]>\n [key: string]: unknown\n }\n}\n\nexport type ApiEnvelope<T = unknown> = SuccessEnvelope<T> | ErrorEnvelope\n\nexport function isSuccess<T>(env: ApiEnvelope<T>): env is SuccessEnvelope<T> {\n return env.success === true\n}\n\nexport function isError(env: ApiEnvelope): env is ErrorEnvelope {\n return env.success === false\n}\n","/**\n * Axios-клиент для admin API.\n *\n * Особенности:\n * - baseURL берётся из bootstrap.apiUrl (либо передаётся явно).\n * - X-XSRF-TOKEN добавляется автоматически из cookie (Laravel Sanctum/web).\n * - X-CSRF-TOKEN — fallback из meta[name=csrf-token] (Blade-injection).\n * - X-Admin-Locale выставляется при наличии текущей локали.\n * - Response interceptor разворачивает envelope и бросает ApiError.\n * - 401 → onUnauthenticated callback (редирект на login на стороне consumer'а).\n */\n\nimport axios, { AxiosError, type AxiosInstance, type AxiosRequestConfig } from 'axios'\nimport { isSuccess, type ApiEnvelope, type ErrorEnvelope } from './envelope'\nimport { NetworkError, toApiError, UnauthenticatedError } from './errors'\n\nexport interface ClientOptions {\n baseURL: string\n csrfToken?: string\n locale?: string\n /** Вызывается при 401. Обычно — push на /admin/login. */\n onUnauthenticated?: () => void\n}\n\nexport interface AdminClient {\n /** Низкоуровневый axios — для специфичных случаев. */\n raw: AxiosInstance\n get<T = unknown>(url: string, config?: AxiosRequestConfig): Promise<T>\n post<T = unknown>(url: string, data?: unknown, config?: AxiosRequestConfig): Promise<T>\n put<T = unknown>(url: string, data?: unknown, config?: AxiosRequestConfig): Promise<T>\n patch<T = unknown>(url: string, data?: unknown, config?: AxiosRequestConfig): Promise<T>\n delete<T = unknown>(url: string, config?: AxiosRequestConfig): Promise<T>\n setLocale(locale: string): void\n}\n\nexport function createAdminClient(opts: ClientOptions): AdminClient {\n const instance = axios.create({\n baseURL: opts.baseURL,\n withCredentials: true,\n headers: {\n Accept: 'application/json',\n 'X-Requested-With': 'XMLHttpRequest',\n },\n })\n\n if (opts.csrfToken) {\n instance.defaults.headers.common['X-CSRF-TOKEN'] = opts.csrfToken\n }\n if (opts.locale) {\n instance.defaults.headers.common['X-Admin-Locale'] = opts.locale\n }\n\n // Подцепляем XSRF из cookie на каждый запрос — браузер сам обновит\n // его после первого 419, но axios reads на вызове.\n instance.interceptors.request.use((config) => {\n const xsrf = readCookie('XSRF-TOKEN')\n if (xsrf) {\n config.headers.set('X-XSRF-TOKEN', decodeURIComponent(xsrf))\n }\n return config\n })\n\n // Response interceptor — разворачиваем envelope, бросаем правильную ошибку.\n instance.interceptors.response.use(\n (response) => {\n const env = response.data as ApiEnvelope\n if (env && typeof env === 'object' && 'success' in env) {\n if (isSuccess(env)) {\n // payload подменяет data — теперь callers получают чистый payload.\n response.data = env.payload\n return response\n }\n // success: false → throw как ApiError\n throw toApiError(response.status, env.payload)\n }\n // Не envelope (например, бинарный stream) — пропускаем как есть.\n return response\n },\n (error: AxiosError<ErrorEnvelope>) => {\n if (error.response) {\n const status = error.response.status\n const payload =\n error.response.data?.payload ?? {\n errorKey: 'unknown',\n message: error.message,\n }\n const apiError = toApiError(status, payload)\n if (apiError instanceof UnauthenticatedError) {\n opts.onUnauthenticated?.()\n }\n return Promise.reject(apiError)\n }\n // network failure / timeout\n return Promise.reject(new NetworkError(error.message))\n },\n )\n\n const wrap = <T>(method: 'get' | 'delete', url: string, config?: AxiosRequestConfig): Promise<T> =>\n instance[method]<unknown, { data: T }>(url, config).then((r) => r.data)\n\n const wrapBody = <T>(\n method: 'post' | 'put' | 'patch',\n url: string,\n data?: unknown,\n config?: AxiosRequestConfig,\n ): Promise<T> => instance[method]<unknown, { data: T }>(url, data, config).then((r) => r.data)\n\n return {\n raw: instance,\n get: <T>(url: string, config?: AxiosRequestConfig) => wrap<T>('get', url, config),\n delete: <T>(url: string, config?: AxiosRequestConfig) => wrap<T>('delete', url, config),\n post: <T>(url: string, data?: unknown, config?: AxiosRequestConfig) =>\n wrapBody<T>('post', url, data, config),\n put: <T>(url: string, data?: unknown, config?: AxiosRequestConfig) =>\n wrapBody<T>('put', url, data, config),\n patch: <T>(url: string, data?: unknown, config?: AxiosRequestConfig) =>\n wrapBody<T>('patch', url, data, config),\n setLocale: (locale: string): void => {\n instance.defaults.headers.common['X-Admin-Locale'] = locale\n },\n }\n}\n\n/** Читает cookie из document.cookie. Returns null если нет. */\nfunction readCookie(name: string): string | null {\n if (typeof document === 'undefined') return null\n const match = document.cookie.match(new RegExp('(^|; )' + escapeRegex(name) + '=([^;]*)'))\n return match ? match[2] : null\n}\n\nfunction escapeRegex(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n}\n","/**\n * buildRoutesFromManifest — превращает AdminManifest в массив RouteRecordRaw.\n *\n * Маппинг:\n * - resource{slug} → /r/{slug} (index)\n * /r/{slug}/create (create)\n * /r/{slug}/:id/edit (edit)\n * /r/{slug}/:id (view, опционально)\n * - screen{slug} → /screens/{slug}\n * - settings{slug} → /settings/{slug}\n * - dashboard{slug} → /dashboard/{slug}\n *\n * Component'ы передаются через resolver — host-проект решает, что отрисовать.\n * Это позволяет library не тащить рендереры внутрь себя жёстко.\n */\n\nimport type { RouteRecordRaw } from 'vue-router'\nimport type { Component } from 'vue'\nimport type {\n AdminManifest,\n ManifestResourceMeta,\n ManifestScreenMeta,\n ManifestSettingsMeta,\n} from '../stores/manifest'\n\n/** Vue Component либо async-loader (для code-splitting). */\nexport type AdminRouteComponent = Component | (() => Promise<Component>)\n\nexport interface RouteMeta {\n /** Требует залогиненного пользователя. */\n requiresAuth?: boolean\n /** Permissions, нужные для входа. ANY-логика (хотя бы одно совпадение). */\n permissions?: string[]\n /** Заголовок страницы (рендерим в <title> через router.afterEach). */\n title?: string\n /** Тип админ-роута — для UI breadcrumbs/active-state. */\n kind?: 'resource' | 'screen' | 'settings' | 'dashboard' | 'system' | 'auth'\n /** Slug сущности из манифеста — для извлечения мета внутри компонента. */\n slug?: string\n}\n\ndeclare module 'vue-router' {\n // eslint-disable-next-line @typescript-eslint/no-empty-object-type\n interface RouteMeta extends Record<string, unknown> {}\n}\n\n/**\n * Resolver компонентов для динамических роутов.\n *\n * Host-проект передаёт конкретные Vue-компоненты для каждой роли.\n * Library не зависит от конкретных view'ов.\n */\nexport interface RouteComponentResolver {\n resourceIndex: AdminRouteComponent\n resourceCreate: AdminRouteComponent\n resourceEdit: AdminRouteComponent\n resourceView: AdminRouteComponent\n screen: AdminRouteComponent\n settings: AdminRouteComponent\n dashboard: AdminRouteComponent\n}\n\n/**\n * Извлекает permissions из meta'ы ресурса / скрина / settings'а.\n *\n * resource.permissions = { view: 'admin.users.view', ... } → ['admin.users.view']\n * (для index используется view; для create/edit — соответственно).\n */\nfunction pickResourcePermission(\n resource: ManifestResourceMeta,\n ability: 'view' | 'create' | 'update',\n): string[] {\n const perm = resource.permissions?.[ability]\n return typeof perm === 'string' && perm.length > 0 ? [perm] : []\n}\n\nfunction pickSettingsPermission(s: ManifestSettingsMeta, ability: 'view' | 'update'): string[] {\n const perm = s.permissions?.[ability]\n return typeof perm === 'string' && perm.length > 0 ? [perm] : []\n}\n\nfunction pickScreenPermission(s: ManifestScreenMeta): string[] {\n if (Array.isArray(s.permission)) return s.permission\n if (typeof s.permission === 'string' && s.permission.length > 0) return [s.permission]\n return []\n}\n\nfunction buildResourceRoutes(\n resource: ManifestResourceMeta,\n components: RouteComponentResolver,\n): RouteRecordRaw[] {\n const slug = resource.slug\n const base = `/r/${slug}`\n\n return [\n {\n path: base,\n name: `admin.resource.${slug}.index`,\n component: components.resourceIndex,\n meta: {\n requiresAuth: true,\n kind: 'resource',\n slug,\n title: resource.label,\n permissions: pickResourcePermission(resource, 'view'),\n },\n // slug передаётся в page-component'ы как prop. Конкретный slug запекаем в\n // function-mode, чтобы page видел его одинаково и через named-route, и через\n // path-routing (без params).\n props: { slug },\n },\n {\n path: `${base}/create`,\n name: `admin.resource.${slug}.create`,\n component: components.resourceCreate,\n meta: {\n requiresAuth: true,\n kind: 'resource',\n slug,\n title: `${resource.label}: создать`,\n permissions: pickResourcePermission(resource, 'create'),\n },\n props: { slug },\n },\n {\n path: `${base}/:id/edit`,\n name: `admin.resource.${slug}.edit`,\n component: components.resourceEdit,\n meta: {\n requiresAuth: true,\n kind: 'resource',\n slug,\n title: `${resource.label}: редактирование`,\n permissions: pickResourcePermission(resource, 'update'),\n },\n // slug запекаем, id из route-params.\n props: (route) => ({ slug, id: route.params.id }),\n },\n {\n path: `${base}/:id`,\n name: `admin.resource.${slug}.view`,\n component: components.resourceView,\n meta: {\n requiresAuth: true,\n kind: 'resource',\n slug,\n title: resource.label,\n permissions: pickResourcePermission(resource, 'view'),\n },\n props: (route) => ({ slug, id: route.params.id }),\n },\n ]\n}\n\nfunction buildScreenRoute(\n screen: ManifestScreenMeta,\n components: RouteComponentResolver,\n): RouteRecordRaw {\n return {\n path: `/screens/${screen.slug}`,\n name: `admin.screen.${screen.slug}`,\n component: components.screen,\n meta: {\n requiresAuth: true,\n kind: 'screen',\n slug: screen.slug,\n title: screen.name,\n permissions: pickScreenPermission(screen),\n },\n }\n}\n\nfunction buildSettingsRoute(\n settings: ManifestSettingsMeta,\n components: RouteComponentResolver,\n): RouteRecordRaw {\n return {\n path: `/settings/${settings.slug}`,\n name: `admin.settings.${settings.slug}`,\n component: components.settings,\n meta: {\n requiresAuth: true,\n kind: 'settings',\n slug: settings.slug,\n title: settings.label,\n permissions: pickSettingsPermission(settings, 'view'),\n },\n }\n}\n\ninterface DashboardMeta {\n slug?: string\n label?: string\n permission?: string | string[] | null\n}\n\nfunction buildDashboardRoute(\n dashboard: DashboardMeta,\n components: RouteComponentResolver,\n): RouteRecordRaw | null {\n if (typeof dashboard.slug !== 'string' || dashboard.slug.length === 0) return null\n const permission = dashboard.permission\n const permissions = Array.isArray(permission)\n ? permission\n : typeof permission === 'string' && permission.length > 0\n ? [permission]\n : []\n return {\n path: `/dashboard/${dashboard.slug}`,\n name: `admin.dashboard.${dashboard.slug}`,\n component: components.dashboard,\n meta: {\n requiresAuth: true,\n kind: 'dashboard',\n slug: dashboard.slug,\n title: dashboard.label ?? 'Dashboard',\n permissions,\n },\n }\n}\n\nexport function buildRoutesFromManifest(\n manifest: AdminManifest | null,\n components: RouteComponentResolver,\n): RouteRecordRaw[] {\n if (manifest === null) return []\n\n const routes: RouteRecordRaw[] = []\n\n for (const resource of manifest.resources) {\n routes.push(...buildResourceRoutes(resource, components))\n }\n for (const screen of manifest.screens) {\n routes.push(buildScreenRoute(screen, components))\n }\n for (const s of manifest.settings) {\n routes.push(buildSettingsRoute(s, components))\n }\n for (const d of manifest.dashboards as DashboardMeta[]) {\n const route = buildDashboardRoute(d, components)\n if (route) routes.push(route)\n }\n\n return routes\n}\n","/**\n * Router-guards: auth + permissions.\n *\n * Логика:\n * 1. Если route.meta.requiresAuth и пользователь не залогинен → /login\n * с ?redirect=...\n * 2. Если у user'а есть pendingChallenge (2FA) — все защищённые роуты\n * редиректят на /login (challenge-form там).\n * 3. Если route.meta.permissions заданы — проверяем hasAnyPermission().\n * Нет ни одного → /forbidden (или роут с name='admin.forbidden').\n *\n * Guards используют useAuthStore — но НЕ берут client напрямую: всё через\n * permissions/isAuthenticated/pendingChallenge state. Stores должны быть\n * захайдрейчены до setup'а router'а.\n */\n\nimport type { RouteLocationNormalized, RouteLocationRaw } from 'vue-router'\nimport { useAuthStore } from '../stores/auth'\n\n/** Тип возвращаемого значения guard'а — true (passthrough) либо redirect-target. */\ntype GuardResult = boolean | RouteLocationRaw\n\n/**\n * Простая 3-арг функция (то что router.beforeEach принимает).\n * Не используем NavigationGuardWithThis<undefined>, т.к. она требует\n * `this: undefined` что неудобно для прямого вызова в тестах.\n */\ntype SimpleGuard = (\n to: RouteLocationNormalized,\n from: RouteLocationNormalized,\n next?: unknown,\n) => GuardResult\n\nexport interface AuthGuardOptions {\n /** Имя login-роута. По умолчанию 'admin.login'. */\n loginRouteName?: string\n /** Имя роута 403-страницы. По умолчанию 'admin.forbidden'. */\n forbiddenRouteName?: string\n /**\n * Имя query-параметра для возврата на исходную страницу после login.\n * По умолчанию 'redirect'.\n */\n redirectQueryKey?: string\n}\n\n/**\n * Создаёт beforeEach guard. Pinia должна быть activeInstance к моменту\n * вызова guard'а (router.beforeEach срабатывает на каждой навигации,\n * включая первую — Pinia уже должна быть установлена).\n */\nexport function createAuthGuard(opts: AuthGuardOptions = {}): SimpleGuard {\n const loginRouteName = opts.loginRouteName ?? 'admin.login'\n const forbiddenRouteName = opts.forbiddenRouteName ?? 'admin.forbidden'\n const redirectQueryKey = opts.redirectQueryKey ?? 'redirect'\n\n return (to: RouteLocationNormalized) => {\n // Login-роут всегда доступен.\n if (to.name === loginRouteName) {\n return true\n }\n\n const auth = useAuthStore()\n const requiresAuth = to.meta?.requiresAuth === true\n\n if (requiresAuth && !auth.isAuthenticated) {\n return {\n name: loginRouteName,\n query: { [redirectQueryKey]: to.fullPath },\n }\n }\n\n // Залогиненный, но в процессе 2FA — нельзя ходить никуда кроме login.\n if (auth.isChallengePending) {\n return {\n name: loginRouteName,\n query: { [redirectQueryKey]: to.fullPath },\n }\n }\n\n // Permission-check. ANY-логика (хотя бы одно permission совпало).\n const permissionsMeta = to.meta?.permissions\n if (Array.isArray(permissionsMeta) && permissionsMeta.length > 0) {\n const allowed = auth.hasAnyPermission(permissionsMeta as string[])\n if (!allowed) {\n return { name: forbiddenRouteName }\n }\n }\n\n return true\n }\n}\n\nexport interface TitleGuardOptions {\n /** Шаблон заголовка. {title} — meta.title, {brand} — название бренда. */\n template?: string\n /** Имя бренда. */\n brand?: string\n /** Default title если в meta нет. */\n fallback?: string\n}\n\n/**\n * Создаёт afterEach hook, обновляющий document.title.\n *\n * Шаблон по умолчанию: '{title} · {brand}' если оба, иначе один из.\n */\nexport function createTitleGuard(\n opts: TitleGuardOptions = {},\n): (to: RouteLocationNormalized, from?: RouteLocationNormalized, failure?: unknown) => void {\n const template = opts.template\n const brand = opts.brand ?? ''\n const fallback = opts.fallback ?? ''\n\n return (to) => {\n if (typeof document === 'undefined') return\n const t = (to.meta?.title as string | undefined) ?? fallback\n let title: string\n if (template) {\n title = template.replace('{title}', t).replace('{brand}', brand)\n } else if (t && brand) {\n title = `${t} · ${brand}`\n } else {\n title = t || brand\n }\n document.title = title\n }\n}\n","/**\n * createAdminRouter — фабрика admin-router'а.\n *\n * Использование:\n *\n * const router = createAdminRouter({\n * base: '/admin',\n * components: { ... },\n * brand: 'My App',\n * })\n * await router.replaceManifestRoutes(manifestStore.manifest)\n * app.use(router)\n *\n * Library намеренно не делает createWebHistory выбор за host'а — host передаёт\n * объект history (createWebHistory / createWebHashHistory).\n */\n\nimport {\n createRouter,\n createWebHistory,\n type Router,\n type RouteRecordRaw,\n type RouterHistory,\n} from 'vue-router'\nimport type { AdminManifest } from '../stores/manifest'\nimport { buildRoutesFromManifest, type RouteComponentResolver, type AdminRouteComponent } from './builder'\nimport { createAuthGuard, createTitleGuard, type AuthGuardOptions, type TitleGuardOptions } from './guards'\n\nexport interface AdminRouterOptions {\n /** Base URL admin-панели. По умолчанию '/admin'. */\n base?: string\n /** History-implementation. По умолчанию createWebHistory(base). */\n history?: RouterHistory\n /** Component resolver для resource/screen/settings/dashboard роутов. */\n components: RouteComponentResolver & {\n /** Login. */\n login: AdminRouteComponent\n /** Главная (либо overview-dashboard). */\n home: AdminRouteComponent\n /** 403 forbidden. */\n forbidden: AdminRouteComponent\n /** 404 not found. */\n notFound: AdminRouteComponent\n /** Страница профиля. */\n profile?: AdminRouteComponent\n /** Страница уведомлений. */\n notifications?: AdminRouteComponent\n /** Forgot password. */\n forgotPassword?: AdminRouteComponent\n /** Reset password (по token + email из query). */\n resetPassword?: AdminRouteComponent\n }\n /** Дополнительные руты сверху динамики. */\n extraRoutes?: RouteRecordRaw[]\n /** Опции auth-guard. */\n authGuard?: AuthGuardOptions\n /** Опции title-guard. */\n titleGuard?: TitleGuardOptions\n}\n\n/**\n * Расширенный Router с возможностью пере-построить динамические роуты.\n */\nexport interface AdminRouter extends Router {\n /**\n * Пере-собрать динамические роуты из manifest'а.\n * Удаляет старые admin.resource.* / admin.screen.* / admin.settings.* / admin.dashboard.*\n * и заменяет на актуальные. Полезно при перезагрузке manifest'а.\n */\n replaceManifestRoutes(manifest: AdminManifest | null): void\n}\n\n/**\n * Префиксы dynamic-роутов которые подменяются при replaceManifestRoutes.\n */\nconst DYNAMIC_NAME_PREFIXES = [\n 'admin.resource.',\n 'admin.screen.',\n 'admin.settings.',\n 'admin.dashboard.',\n]\n\nfunction isDynamicRouteName(name: unknown): boolean {\n if (typeof name !== 'string') return false\n return DYNAMIC_NAME_PREFIXES.some((p) => name.startsWith(p))\n}\n\nexport function createAdminRouter(opts: AdminRouterOptions): AdminRouter {\n const base = opts.base ?? '/admin'\n const history = opts.history ?? createWebHistory(base)\n\n const staticRoutes: RouteRecordRaw[] = [\n {\n path: '/login',\n name: 'admin.login',\n component: opts.components.login,\n meta: { kind: 'auth', title: 'Вход' },\n },\n {\n path: '/',\n name: 'admin.home',\n component: opts.components.home,\n meta: { requiresAuth: true, kind: 'system', title: 'Главная' },\n },\n {\n path: '/forbidden',\n name: 'admin.forbidden',\n component: opts.components.forbidden,\n meta: { requiresAuth: true, kind: 'system', title: '403 — доступ запрещён' },\n },\n ]\n\n if (opts.components.profile) {\n staticRoutes.push({\n path: '/profile',\n name: 'admin.profile',\n component: opts.components.profile,\n meta: { requiresAuth: true, kind: 'system', title: 'Профиль' },\n })\n }\n\n if (opts.components.notifications) {\n staticRoutes.push({\n path: '/notifications',\n name: 'admin.notifications',\n component: opts.components.notifications,\n meta: { requiresAuth: true, kind: 'system', title: 'Уведомления' },\n })\n }\n\n if (opts.components.forgotPassword) {\n staticRoutes.push({\n path: '/forgot-password',\n name: 'admin.forgotPassword',\n component: opts.components.forgotPassword,\n meta: { kind: 'auth', title: 'Восстановление пароля' },\n })\n }\n if (opts.components.resetPassword) {\n staticRoutes.push({\n path: '/reset-password',\n name: 'admin.resetPassword',\n component: opts.components.resetPassword,\n meta: { kind: 'auth', title: 'Новый пароль' },\n })\n }\n\n // Catch-all 404 кладём в конец — vue-router matches in order и динамика\n // может быть добавлена позже через addRoute.\n const notFoundRoute: RouteRecordRaw = {\n path: '/:pathMatch(.*)*',\n name: 'admin.notFound',\n component: opts.components.notFound,\n meta: { kind: 'system', title: '404' },\n }\n\n const router = createRouter({\n history,\n routes: [...staticRoutes, ...(opts.extraRoutes ?? []), notFoundRoute],\n }) as AdminRouter\n\n router.beforeEach(createAuthGuard(opts.authGuard))\n router.afterEach(createTitleGuard(opts.titleGuard))\n\n router.replaceManifestRoutes = (manifest: AdminManifest | null): void => {\n // Удаляем все старые динамические роуты по name.\n const allRoutes = router.getRoutes()\n for (const route of allRoutes) {\n if (isDynamicRouteName(route.name)) {\n router.removeRoute(route.name as string)\n }\n }\n\n // Удаляем catch-all чтобы потом добавить его обратно последним.\n if (router.hasRoute('admin.notFound')) {\n router.removeRoute('admin.notFound')\n }\n\n const dynamic = buildRoutesFromManifest(manifest, opts.components)\n for (const route of dynamic) {\n router.addRoute(route)\n }\n router.addRoute(notFoundRoute)\n }\n\n return router\n}\n\nexport { buildRoutesFromManifest } from './builder'\nexport type { RouteComponentResolver, RouteMeta, AdminRouteComponent } from './builder'\nexport { createAuthGuard, createTitleGuard } from './guards'\nexport type { AuthGuardOptions, TitleGuardOptions } from './guards'\n","<script setup lang=\"ts\">\n/**\n * TextField — wrapper над UidInput из @dskripchenko/ui. Двусторонняя связь\n * с form-state через provideFormState/useFormState. Тип input'а (text/email/\n * url/password/tel/search) пробрасывается как `type`.\n */\nimport { computed } from 'vue'\nimport { UidInput } from '@dskripchenko/ui'\nimport { useFormState } from '../render/formState'\n\ninterface Props {\n name: string\n label?: string | null\n help?: string | null\n required?: boolean\n placeholder?: string | null\n inputType?: 'text' | 'email' | 'url' | 'password' | 'tel' | 'search'\n disabled?: boolean\n readonly?: boolean\n autocomplete?: string | null\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n label: null,\n help: null,\n placeholder: null,\n inputType: 'text',\n required: false,\n disabled: false,\n readonly: false,\n autocomplete: null,\n})\n\nconst form = useFormState()\nconst value = computed<string>(() => (form.getField(props.name) as string | null | undefined) ?? '')\nconst errorMsg = computed<string | undefined>(() => form.errors[props.name]?.[0])\n\nfunction onUpdate(next: string): void {\n form.setField(props.name, next)\n}\n</script>\n\n<template>\n <UidInput\n :model-value=\"value\"\n :type=\"inputType\"\n :label=\"label ?? undefined\"\n :hint=\"help ?? undefined\"\n :error=\"errorMsg\"\n :placeholder=\"placeholder ?? undefined\"\n :required=\"required\"\n :disabled=\"disabled\"\n :readonly=\"readonly\"\n :name=\"name\"\n :autocomplete=\"autocomplete ?? undefined\"\n @update:model-value=\"onUpdate\"\n />\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { UidTextarea, UidFormField } from '@dskripchenko/ui'\nimport { useFormState } from '../render/formState'\n\ninterface Props {\n name: string\n label?: string | null\n help?: string | null\n required?: boolean\n placeholder?: string | null\n rows?: number\n disabled?: boolean\n readonly?: boolean\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n label: null,\n help: null,\n placeholder: null,\n rows: 4,\n required: false,\n disabled: false,\n readonly: false,\n})\n\nconst form = useFormState()\nconst value = computed<string>(() => (form.getField(props.name) as string | null | undefined) ?? '')\nconst errorMsg = computed<string | undefined>(() => form.errors[props.name]?.[0])\n\nfunction onUpdate(next: string): void {\n form.setField(props.name, next)\n}\n</script>\n\n<template>\n <UidFormField\n :label=\"label ?? undefined\"\n :hint=\"help ?? undefined\"\n :error=\"errorMsg\"\n :required=\"required\"\n :disabled=\"disabled\"\n >\n <UidTextarea\n :model-value=\"value\"\n :rows=\"rows\"\n :placeholder=\"placeholder ?? undefined\"\n :disabled=\"disabled\"\n :readonly=\"readonly\"\n :name=\"name\"\n @update:model-value=\"onUpdate\"\n />\n </UidFormField>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { UidNumberInput, UidFormField } from '@dskripchenko/ui'\nimport { useFormState } from '../render/formState'\n\ninterface Props {\n name: string\n label?: string | null\n help?: string | null\n required?: boolean\n placeholder?: string | null\n min?: number | null\n max?: number | null\n step?: number | null\n disabled?: boolean\n readonly?: boolean\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n label: null,\n help: null,\n placeholder: null,\n min: null,\n max: null,\n step: null,\n required: false,\n disabled: false,\n readonly: false,\n})\n\nconst form = useFormState()\nconst value = computed<number | null>(() => {\n const v = form.getField(props.name)\n if (v === null || v === undefined || v === '') return null\n return typeof v === 'number' ? v : Number(v)\n})\nconst errorMsg = computed<string | undefined>(() => form.errors[props.name]?.[0])\n\nfunction onUpdate(next: number | null): void {\n form.setField(props.name, next)\n}\n</script>\n\n<template>\n <UidFormField\n :label=\"label ?? undefined\"\n :hint=\"help ?? undefined\"\n :error=\"errorMsg\"\n :required=\"required\"\n :disabled=\"disabled\"\n >\n <UidNumberInput\n :model-value=\"value\"\n :min=\"min ?? undefined\"\n :max=\"max ?? undefined\"\n :step=\"step ?? undefined\"\n :placeholder=\"placeholder ?? undefined\"\n :disabled=\"disabled\"\n :readonly=\"readonly\"\n :name=\"name\"\n @update:model-value=\"onUpdate\"\n />\n </UidFormField>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { UidSelect, UidFormField } from '@dskripchenko/ui'\nimport { useFormState } from '../render/formState'\n\nexport interface SelectOption {\n value: string | number\n label: string\n disabled?: boolean\n}\n\ninterface Props {\n name: string\n options: SelectOption[]\n label?: string | null\n help?: string | null\n required?: boolean\n placeholder?: string | null\n disabled?: boolean\n searchable?: boolean\n clearable?: boolean\n size?: 'sm' | 'md' | 'lg'\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n label: null,\n help: null,\n placeholder: null,\n required: false,\n disabled: false,\n searchable: false,\n clearable: false,\n size: 'md',\n})\n\nconst form = useFormState()\nconst value = computed<string | number | null>(() => {\n const v = form.getField(props.name)\n if (v === null || v === undefined || v === '') return null\n return v as string | number\n})\nconst errorMsg = computed<string | undefined>(() => form.errors[props.name]?.[0])\n\nfunction onUpdate(next: string | number | null): void {\n form.setField(props.name, next)\n}\n</script>\n\n<template>\n <UidFormField\n :label=\"label ?? undefined\"\n :hint=\"help ?? undefined\"\n :error=\"errorMsg\"\n :required=\"required\"\n :disabled=\"disabled\"\n >\n <UidSelect\n :model-value=\"value\"\n :options=\"options\"\n :placeholder=\"placeholder ?? undefined\"\n :disabled=\"disabled\"\n :searchable=\"searchable\"\n :clearable=\"clearable\"\n :size=\"size\"\n @update:model-value=\"onUpdate\"\n />\n </UidFormField>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { UidCheckbox, UidFormField } from '@dskripchenko/ui'\nimport { useFormState } from '../render/formState'\n\ninterface Props {\n name: string\n label?: string | null\n help?: string | null\n required?: boolean\n inlineLabel?: string | null\n disabled?: boolean\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n label: null,\n help: null,\n inlineLabel: null,\n required: false,\n disabled: false,\n})\n\nconst form = useFormState()\nconst checked = computed<boolean>(() => Boolean(form.getField(props.name)))\nconst errorMsg = computed<string | undefined>(() => form.errors[props.name]?.[0])\n\nfunction onUpdate(next: boolean): void {\n form.setField(props.name, next)\n}\n</script>\n\n<template>\n <UidFormField\n :label=\"label ?? undefined\"\n :hint=\"help ?? undefined\"\n :error=\"errorMsg\"\n :required=\"required\"\n :disabled=\"disabled\"\n >\n <UidCheckbox\n :model-value=\"checked\"\n :disabled=\"disabled\"\n :name=\"name\"\n @update:model-value=\"onUpdate\"\n >\n <template v-if=\"inlineLabel\">{{ inlineLabel }}</template>\n </UidCheckbox>\n </UidFormField>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { UidDatePicker, UidFormField } from '@dskripchenko/ui'\nimport { useFormState } from '../render/formState'\n\ninterface Props {\n name: string\n label?: string | null\n help?: string | null\n required?: boolean\n /**\n * Тип input'а: 'date' (default), 'datetime-local', 'time'.\n * UidDatePicker внутри обрабатывает формат через свои props; для совместимости\n * со старым API оставляем prop.\n */\n inputType?: 'date' | 'datetime-local' | 'time'\n min?: string | null\n max?: string | null\n disabled?: boolean\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n label: null,\n help: null,\n inputType: 'date',\n min: null,\n max: null,\n required: false,\n disabled: false,\n})\n\nconst form = useFormState()\nconst value = computed<string | null>(() => {\n const v = form.getField(props.name)\n return v === null || v === undefined || v === '' ? null : String(v)\n})\nconst errorMsg = computed<string | undefined>(() => form.errors[props.name]?.[0])\n\nfunction onUpdate(next: string | null): void {\n form.setField(props.name, next)\n}\n</script>\n\n<template>\n <UidFormField\n :label=\"label ?? undefined\"\n :hint=\"help ?? undefined\"\n :error=\"errorMsg\"\n :required=\"required\"\n :disabled=\"disabled\"\n >\n <UidDatePicker\n :model-value=\"value\"\n :min=\"min ?? undefined\"\n :max=\"max ?? undefined\"\n :disabled=\"disabled\"\n :name=\"name\"\n @update:model-value=\"onUpdate\"\n />\n </UidFormField>\n</template>\n","<script setup lang=\"ts\">\n/**\n * TagsField — input для list<string> с chip'ами и free-form вводом.\n *\n * Backend Field-класс — Dskripchenko\\LaravelAdmin\\Field\\TagsInput с\n * fieldType()='tags'. Frontend builtin-registry маппит 'tags' сюда.\n *\n * Особенности:\n * - Free input: Enter / separator (`,` или ';') добавляют новый chip,\n * даже если такого нет в suggestions — это критично для wildcard'ов\n * ('admin.content.*') и других произвольных ключей.\n * - Suggestions: backend кладёт `attributes.suggestions: string[]`. При\n * наличии — рендерим dropdown с фильтром по введённому query.\n * - Backspace на пустом input удаляет последний chip.\n * - Click на chip × удаляет.\n */\nimport { computed, nextTick, ref, watch } from 'vue'\nimport { X } from 'lucide-vue-next'\nimport { UidIcon } from '@dskripchenko/ui'\nimport { useFormState } from '../render/formState'\n\ninterface SuggestionGroup {\n label: string\n items: string[]\n}\n\ninterface Props {\n name: string\n label?: string | null\n help?: string | null\n required?: boolean\n placeholder?: string | null\n /** Плоский список подсказок (compat-вариант). */\n suggestions?: string[]\n /**\n * Группированные подсказки. Когда заданы — dropdown рендерится с\n * заголовками групп. Имеет приоритет над `suggestions`.\n */\n suggestionsByGroup?: SuggestionGroup[]\n /** Лимит количества тегов. */\n maxItems?: number\n /**\n * Дополнительный разделитель (помимо Enter). Например `,` или `;`.\n * При вводе одного из этих символов value до него превращается в chip.\n */\n separator?: string\n disabled?: boolean\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n label: null,\n help: null,\n placeholder: 'Введите ключ и нажмите Enter…',\n required: false,\n suggestions: () => [],\n suggestionsByGroup: () => [],\n maxItems: 0,\n separator: ',',\n disabled: false,\n})\n\nconst form = useFormState()\n\nconst tags = computed<string[]>(() => {\n const v = form.getField(props.name)\n if (Array.isArray(v)) return v.map((x) => String(x))\n if (typeof v === 'string' && v !== '') return v.split(',').map((s) => s.trim()).filter(Boolean)\n return []\n})\n\nconst errorMsg = computed<string | undefined>(() => form.errors[props.name]?.[0])\n\nconst query = ref<string>('')\nconst focused = ref<boolean>(false)\nconst inputRef = ref<HTMLInputElement | null>(null)\nconst containerRef = ref<HTMLElement | null>(null)\n\nfunction setTags(next: string[]): void {\n // Дедуплицируем + лимит.\n const seen = new Set<string>()\n const out: string[] = []\n for (const t of next) {\n const trimmed = t.trim()\n if (trimmed === '' || seen.has(trimmed)) continue\n seen.add(trimmed)\n out.push(trimmed)\n if (props.maxItems > 0 && out.length >= props.maxItems) break\n }\n form.setField(props.name, out)\n}\n\nfunction addTag(value: string): void {\n const v = value.trim()\n if (v === '') return\n if (tags.value.includes(v)) {\n query.value = ''\n return\n }\n setTags([...tags.value, v])\n query.value = ''\n}\n\nfunction removeTag(idx: number): void {\n const next = [...tags.value]\n next.splice(idx, 1)\n setTags(next)\n}\n\nfunction onKeydown(e: KeyboardEvent): void {\n if (e.key === 'Enter') {\n e.preventDefault()\n if (activeIdx.value >= 0 && filteredFlat.value[activeIdx.value]) {\n addTag(filteredFlat.value[activeIdx.value])\n } else if (query.value.trim() !== '') {\n addTag(query.value)\n }\n } else if (e.key === 'Backspace' && query.value === '' && tags.value.length > 0) {\n removeTag(tags.value.length - 1)\n } else if (e.key === 'ArrowDown') {\n e.preventDefault()\n activeIdx.value = Math.min(activeIdx.value + 1, filteredFlat.value.length - 1)\n } else if (e.key === 'ArrowUp') {\n e.preventDefault()\n activeIdx.value = Math.max(activeIdx.value - 1, -1)\n } else if (e.key === 'Escape') {\n focused.value = false\n inputRef.value?.blur()\n }\n}\n\nfunction onInput(e: Event): void {\n const v = (e.target as HTMLInputElement).value\n // Обработка separator-символа: если есть — обрезаем до него и коммитим.\n if (props.separator && v.includes(props.separator)) {\n const parts = v.split(props.separator)\n const completed = parts.slice(0, -1).map((p) => p.trim()).filter(Boolean)\n completed.forEach(addTag)\n query.value = parts[parts.length - 1] ?? ''\n return\n }\n query.value = v\n}\n\nconst activeIdx = ref<number>(-1)\n\n/**\n * Если backend передал suggestionsByGroup — рендерим с заголовками групп,\n * иначе — flat list. Формируем единый отфильтрованный массив для индексной\n * навигации стрелками (activeIdx указывает на index в `filteredFlat`).\n */\nconst grouped = computed<boolean>(\n () => Array.isArray(props.suggestionsByGroup) && props.suggestionsByGroup.length > 0,\n)\n\nconst filteredGroups = computed<SuggestionGroup[]>(() => {\n const q = query.value.trim().toLowerCase()\n const used = new Set(tags.value)\n if (!grouped.value) return []\n return props.suggestionsByGroup\n .map((g) => ({\n label: g.label,\n items: g.items.filter(\n (s) => !used.has(s) && (q === '' || s.toLowerCase().includes(q)),\n ),\n }))\n .filter((g) => g.items.length > 0)\n})\n\nconst filteredFlat = computed<string[]>(() => {\n if (grouped.value) {\n return filteredGroups.value.flatMap((g) => g.items)\n }\n const q = query.value.trim().toLowerCase()\n const used = new Set(tags.value)\n return props.suggestions\n .filter((s) => !used.has(s))\n .filter((s) => q === '' || s.toLowerCase().includes(q))\n .slice(0, 200)\n})\n\n/** Сколько групп выше текущего item'а (для shift при index лookup). */\nfunction isItemActive(globalIdx: number): boolean {\n return globalIdx === activeIdx.value\n}\n\nwatch(query, () => {\n activeIdx.value = -1\n})\n\nfunction onContainerClick(): void {\n if (!props.disabled) inputRef.value?.focus()\n}\n\nfunction onSelectSuggestion(s: string): void {\n addTag(s)\n nextTick(() => inputRef.value?.focus())\n}\n\nfunction onBlur(): void {\n // delay чтобы успел сработать click по dropdown'у\n window.setTimeout(() => {\n focused.value = false\n if (query.value.trim() !== '') {\n addTag(query.value)\n }\n }, 120)\n}\n</script>\n\n<template>\n <div :class=\"['admin-field', { 'admin-field--invalid': errorMsg !== undefined }]\">\n <label v-if=\"label\" class=\"admin-field__label\">\n <span>{{ label }}</span>\n <span v-if=\"required\" class=\"admin-field__required\" aria-hidden=\"true\">*</span>\n </label>\n <div\n ref=\"containerRef\"\n :class=\"[\n 'admin-field__control admin-tags',\n {\n 'admin-tags--focused': focused,\n 'admin-tags--disabled': disabled,\n },\n ]\"\n @click=\"onContainerClick\"\n >\n <span\n v-for=\"(tag, idx) in tags\"\n :key=\"`${tag}-${idx}`\"\n class=\"admin-tags__chip\"\n >\n <span class=\"admin-tags__chip-text\">{{ tag }}</span>\n <button\n v-if=\"!disabled\"\n type=\"button\"\n class=\"admin-tags__chip-remove\"\n aria-label=\"Удалить\"\n @click.stop=\"removeTag(idx)\"\n >\n <UidIcon :icon=\"X\" :size=\"10\" />\n </button>\n </span>\n <input\n ref=\"inputRef\"\n :value=\"query\"\n :placeholder=\"tags.length === 0 ? (placeholder ?? '') : ''\"\n :disabled=\"disabled\"\n class=\"admin-tags__input\"\n type=\"text\"\n @input=\"onInput\"\n @keydown=\"onKeydown\"\n @focus=\"focused = true\"\n @blur=\"onBlur\"\n />\n\n <div\n v-if=\"focused && filteredFlat.length > 0\"\n class=\"admin-tags__dropdown\"\n role=\"listbox\"\n >\n <!-- Grouped рендер: заголовок группы + items внутри -->\n <template v-if=\"grouped\">\n <template\n v-for=\"(g, gi) in filteredGroups\"\n :key=\"`g-${gi}-${g.label}`\"\n >\n <div class=\"admin-tags__group-label\">{{ g.label }}</div>\n <button\n v-for=\"s in g.items\"\n :key=\"s\"\n type=\"button\"\n role=\"option\"\n :class=\"[\n 'admin-tags__option',\n {\n 'admin-tags__option--active': isItemActive(\n filteredFlat.indexOf(s),\n ),\n },\n ]\"\n :aria-selected=\"isItemActive(filteredFlat.indexOf(s))\"\n @mousedown.prevent=\"onSelectSuggestion(s)\"\n @mouseenter=\"activeIdx = filteredFlat.indexOf(s)\"\n >\n {{ s }}\n </button>\n </template>\n </template>\n\n <!-- Flat рендер (без групп) — обратная совместимость -->\n <template v-else>\n <button\n v-for=\"(s, idx) in filteredFlat\"\n :key=\"s\"\n type=\"button\"\n role=\"option\"\n :class=\"['admin-tags__option', { 'admin-tags__option--active': idx === activeIdx }]\"\n :aria-selected=\"idx === activeIdx\"\n @mousedown.prevent=\"onSelectSuggestion(s)\"\n @mouseenter=\"activeIdx = idx\"\n >\n {{ s }}\n </button>\n </template>\n </div>\n </div>\n <p v-if=\"errorMsg\" class=\"admin-field__error\">{{ errorMsg }}</p>\n <p v-else-if=\"help\" class=\"admin-field__help\">{{ help }}</p>\n </div>\n</template>\n\n<style>\n.admin-tags {\n position: relative;\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 4px;\n min-height: 36px;\n padding: 4px 8px;\n border: 1px solid var(--uid-border-subtle);\n background: var(--uid-surface-base);\n border-radius: var(--uid-radius-md);\n cursor: text;\n}\n.admin-tags--focused {\n border-color: var(--uid-accent);\n outline: 2px solid color-mix(in srgb, var(--uid-accent) 18%, transparent);\n}\n.admin-tags--disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n.admin-tags__chip {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 2px 6px 2px 8px;\n background: color-mix(in srgb, var(--uid-accent) 14%, transparent);\n color: var(--uid-accent);\n border-radius: var(--uid-radius-sm);\n font-size: 12px;\n font-weight: 500;\n font-family: var(--uid-font-family-mono, ui-monospace, monospace);\n}\n.admin-tags__chip-remove {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 16px;\n height: 16px;\n border: 0;\n background: transparent;\n color: inherit;\n border-radius: 50%;\n cursor: pointer;\n}\n.admin-tags__chip-remove:hover {\n background: color-mix(in srgb, var(--uid-accent) 28%, transparent);\n}\n.admin-tags__input {\n flex: 1;\n min-width: 80px;\n height: 24px;\n padding: 0 4px;\n border: 0;\n background: transparent;\n outline: none;\n font: inherit;\n font-size: 13px;\n color: var(--uid-text-primary);\n}\n.admin-tags__dropdown {\n position: absolute;\n top: calc(100% + 4px);\n left: 0;\n right: 0;\n z-index: 10;\n margin: 0;\n padding: 4px;\n display: flex;\n flex-direction: column;\n background: var(--uid-surface-raised);\n border: 1px solid var(--uid-border-subtle);\n border-radius: var(--uid-radius-md);\n box-shadow: var(--uid-shadow-md);\n max-height: 320px;\n overflow-y: auto;\n}\n.admin-tags__group-label {\n padding: 8px 10px 4px;\n font-size: 11px;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n color: var(--uid-text-tertiary);\n font-weight: var(--uid-font-weight-semibold);\n position: sticky;\n top: 0;\n background: var(--uid-surface-raised);\n z-index: 1;\n}\n.admin-tags__group-label:first-child { padding-top: 4px; }\n.admin-tags__option {\n display: block;\n width: 100%;\n text-align: left;\n padding: 6px 10px;\n border: 0;\n background: transparent;\n border-radius: var(--uid-radius-sm);\n font-size: 13px;\n cursor: pointer;\n color: var(--uid-text-primary);\n font-family: var(--uid-font-family-mono, ui-monospace, monospace);\n}\n.admin-tags__option:hover,\n.admin-tags__option--active {\n background: var(--uid-color-surface-hover, var(--uid-border-subtle));\n}\n</style>\n","<script setup lang=\"ts\">\n/**\n * TranslatableField — input с табами по локалям для translatable-моделей.\n *\n * Backend laravel-translatable хранит переводы в pivot-таблице. Для admin\n * Resource сериализует значение поля как `{ru: '...', en: '...'}`. Этот\n * компонент рендерит таб'ы по локалям и редактирует каждое значение\n * отдельно.\n *\n * Локали:\n * - resource manifest имеет `meta.locale` + `bootstrap.availableLocales`;\n * - prop `locales` явно перебивает (для случаев когда модель ограничена\n * подмножеством локалей).\n *\n * Backend payload — Object keyed by locale. Form-state сохраняет тот же\n * shape; bridge `TranslatableFieldBridge::extract()` извлекает на стороне\n * ResourceController при save.\n */\nimport { computed, ref } from 'vue'\nimport { UidInput } from '@dskripchenko/ui'\nimport { useFormState } from '../render/formState'\nimport { useLocaleStore } from '../../stores/locale'\n\ninterface Props {\n name: string\n label?: string | null\n help?: string | null\n required?: boolean\n placeholder?: string | null\n /** Override доступных локалей. Default — locale.available. */\n locales?: string[]\n /** Использовать textarea вместо input (для длинных полей body/description). */\n multiline?: boolean\n rows?: number\n disabled?: boolean\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n label: null,\n help: null,\n placeholder: null,\n required: false,\n locales: undefined,\n multiline: false,\n rows: 3,\n disabled: false,\n})\n\nconst form = useFormState()\nconst localeStore = useLocaleStore()\n\nconst availableLocales = computed<string[]>(\n () => props.locales ?? localeStore.available ?? [localeStore.current ?? 'ru'],\n)\nconst activeLocale = ref<string>(localeStore.current ?? availableLocales.value[0] ?? 'ru')\n\nconst value = computed<Record<string, string>>(() => {\n const v = form.getField(props.name)\n if (v && typeof v === 'object' && !Array.isArray(v)) {\n return v as Record<string, string>\n }\n // Если поле пришло как plain-string (legacy non-translatable), оборачиваем.\n if (typeof v === 'string') return { [activeLocale.value]: v }\n return {}\n})\n\nfunction update(locale: string, next: string): void {\n const current = { ...value.value }\n current[locale] = next\n form.setField(props.name, current)\n}\n\nconst errorMsg = computed<string | undefined>(() => {\n // Backend может возвращать ошибки per-locale (`field.ru` / `field.en`).\n const errors = form.errors[props.name]\n if (errors?.[0]) return errors[0]\n for (const loc of availableLocales.value) {\n const e = form.errors[`${props.name}.${loc}`]?.[0]\n if (e) return `[${loc}] ${e}`\n }\n return undefined\n})\n\nfunction isFilled(locale: string): boolean {\n const v = value.value[locale]\n return typeof v === 'string' && v.trim() !== ''\n}\n</script>\n\n<template>\n <div :class=\"['admin-field', { 'admin-field--invalid': errorMsg !== undefined }]\">\n <label v-if=\"label\" class=\"admin-field__label\">\n <span>{{ label }}</span>\n <span v-if=\"required\" class=\"admin-field__required\" aria-hidden=\"true\">*</span>\n </label>\n <div class=\"admin-translatable\">\n <div class=\"admin-translatable__tabs\" role=\"tablist\">\n <button\n v-for=\"loc in availableLocales\"\n :key=\"loc\"\n type=\"button\"\n role=\"tab\"\n :class=\"[\n 'admin-translatable__tab',\n {\n 'admin-translatable__tab--active': activeLocale === loc,\n 'admin-translatable__tab--filled': isFilled(loc),\n },\n ]\"\n :aria-selected=\"activeLocale === loc\"\n @click=\"activeLocale = loc\"\n >\n {{ loc.toUpperCase() }}\n <span v-if=\"isFilled(loc)\" class=\"admin-translatable__dot\" aria-hidden=\"true\" />\n </button>\n </div>\n <div class=\"admin-translatable__panel\">\n <UidInput\n v-if=\"!multiline\"\n :model-value=\"value[activeLocale] ?? ''\"\n :placeholder=\"placeholder ?? ''\"\n :disabled=\"disabled\"\n @update:model-value=\"(v) => update(activeLocale, v as string)\"\n />\n <textarea\n v-else\n :value=\"value[activeLocale] ?? ''\"\n :placeholder=\"placeholder ?? ''\"\n :rows=\"rows\"\n :disabled=\"disabled\"\n class=\"admin-translatable__textarea\"\n @input=\"(e) => update(activeLocale, (e.target as HTMLTextAreaElement).value)\"\n />\n </div>\n </div>\n <p v-if=\"errorMsg\" class=\"admin-field__error\">{{ errorMsg }}</p>\n <p v-else-if=\"help\" class=\"admin-field__help\">{{ help }}</p>\n </div>\n</template>\n\n<style>\n.admin-translatable { display: flex; flex-direction: column; gap: 6px; }\n.admin-translatable__tabs {\n display: inline-flex;\n align-items: center;\n gap: 2px;\n align-self: flex-start;\n padding: 2px;\n background: var(--uid-surface-base);\n border: 1px solid var(--uid-border-subtle);\n border-radius: var(--uid-radius-md);\n}\n.admin-translatable__tab {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 4px 10px;\n border: 0;\n background: transparent;\n border-radius: var(--uid-radius-sm);\n font-size: 11px;\n font-weight: 600;\n color: var(--uid-text-secondary);\n cursor: pointer;\n letter-spacing: 0.04em;\n}\n.admin-translatable__tab:hover { color: var(--uid-text-primary); }\n.admin-translatable__tab--active {\n background: var(--uid-surface-raised);\n color: var(--uid-text-primary);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);\n}\n.admin-translatable__dot {\n width: 5px;\n height: 5px;\n border-radius: 50%;\n background: var(--uid-color-success, #10b981);\n}\n.admin-translatable__textarea {\n width: 100%;\n padding: 8px 10px;\n border: 1px solid var(--uid-border-subtle);\n background: var(--uid-surface-base);\n border-radius: var(--uid-radius-md);\n color: var(--uid-text-primary);\n font: inherit;\n font-size: 13px;\n resize: vertical;\n}\n.admin-translatable__textarea:focus {\n outline: 2px solid color-mix(in srgb, var(--uid-accent) 18%, transparent);\n border-color: var(--uid-accent);\n}\n</style>\n","<script setup lang=\"ts\">\n/**\n * Rows-layout — UidStack column.\n */\nimport { UidStack } from '@dskripchenko/ui'\nimport LayoutRenderer from '../render/LayoutRenderer.vue'\nimport type { LayoutNode } from '../render/LayoutRenderer.vue'\n\ninterface Props {\n items: LayoutNode[]\n /** CSS-зазор между элементами (token либо px), по умолчанию --uid-space-md. */\n gap?: string\n}\nwithDefaults(defineProps<Props>(), { gap: 'var(--uid-space-md)' })\n</script>\n\n<template>\n <UidStack direction=\"column\" :gap=\"gap\" align=\"stretch\">\n <LayoutRenderer v-for=\"(child, idx) in items\" :key=\"idx\" :node=\"child\" />\n </UidStack>\n</template>\n","<script setup lang=\"ts\">\n/**\n * Columns: 12-колоночный grid поверх UidGrid из @dskripchenko/ui.\n * Каждый item.span (1..cols) задаёт ширину; default равные доли.\n */\nimport { computed } from 'vue'\nimport { UidGrid } from '@dskripchenko/ui'\nimport LayoutRenderer from '../render/LayoutRenderer.vue'\nimport type { LayoutNode } from '../render/LayoutRenderer.vue'\n\ninterface Props {\n items: LayoutNode[]\n /** Зазор между ячейками (CSS, token или px). */\n gap?: string\n /** Сколько колонок в гриде (default 12). */\n cols?: number\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n gap: 'var(--uid-space-md)',\n cols: 12,\n})\n\nconst defaultSpan = computed(() => {\n if (props.items.length === 0) return props.cols\n return Math.max(1, Math.floor(props.cols / props.items.length))\n})\n\nfunction spanFor(item: LayoutNode): number {\n const s = (item as Record<string, unknown>).span\n if (typeof s === 'number' && s > 0) return Math.min(s, props.cols)\n return defaultSpan.value\n}\n</script>\n\n<template>\n <UidGrid :cols=\"cols\" :gap=\"gap\">\n <div\n v-for=\"(child, idx) in items\"\n :key=\"idx\"\n class=\"admin-columns__item\"\n :style=\"{ gridColumn: `span ${spanFor(child)} / span ${spanFor(child)}` }\"\n >\n <LayoutRenderer :node=\"child\" />\n </div>\n </UidGrid>\n</template>\n","<script setup lang=\"ts\">\n/**\n * Section/Block layout — UidCard с заголовком + опциональным описанием.\n */\nimport { UidCard } from '@dskripchenko/ui'\nimport LayoutRenderer from '../render/LayoutRenderer.vue'\nimport type { LayoutNode } from '../render/LayoutRenderer.vue'\n\ninterface Props {\n items: LayoutNode[]\n title?: string | null\n description?: string | null\n}\n\nwithDefaults(defineProps<Props>(), {\n title: null,\n description: null,\n})\n</script>\n\n<template>\n <UidCard padding=\"md\" class=\"admin-section\">\n <header v-if=\"title || description\" class=\"admin-section__header\">\n <h3 v-if=\"title\" class=\"admin-section__title\">{{ title }}</h3>\n <p v-if=\"description\" class=\"admin-section__description\">{{ description }}</p>\n </header>\n <div class=\"admin-section__body\">\n <LayoutRenderer v-for=\"(child, idx) in items\" :key=\"idx\" :node=\"child\" />\n </div>\n </UidCard>\n</template>\n\n<style>\n.admin-section { margin-bottom: var(--uid-space-md); }\n.admin-section__header { margin-bottom: var(--uid-space-sm); }\n.admin-section__title {\n margin: 0;\n font-size: var(--uid-font-size-sm);\n font-weight: var(--uid-font-weight-semibold);\n color: var(--uid-text-primary);\n}\n.admin-section__description {\n margin: var(--uid-space-2xs) 0 0;\n font-size: var(--uid-font-size-xs);\n color: var(--uid-text-tertiary);\n}\n.admin-section__body {\n display: flex;\n flex-direction: column;\n gap: var(--uid-space-sm);\n}\n</style>\n","<script setup lang=\"ts\">\n/**\n * TabsLayout поверх UidTabs/UidTab/UidTabPanel.\n * Активная вкладка двусторонне связана через v-model:active.\n */\nimport { ref } from 'vue'\nimport { UidTabs, UidTab, UidTabPanel } from '@dskripchenko/ui'\nimport LayoutRenderer from '../render/LayoutRenderer.vue'\nimport type { LayoutNode } from '../render/LayoutRenderer.vue'\n\nexport interface TabNode {\n /** Уникальный ключ вкладки. Если не задан — берётся индекс. */\n key?: string\n /** Текст вкладки. */\n label: string\n icon?: string | null\n items: LayoutNode[]\n}\n\ninterface Props {\n items: TabNode[]\n /** Активная вкладка (key либо индекс при отсутствии key). */\n active?: string | number\n}\n\nconst props = withDefaults(defineProps<Props>(), { active: 0 })\nconst emit = defineEmits<{ 'update:active': [value: string | number] }>()\n\nfunction tabKey(tab: TabNode, idx: number): string | number {\n return tab.key ?? idx\n}\n\nconst localActive = ref<string | number>(props.active ?? tabKey(props.items[0] ?? { label: '' }, 0))\n\nfunction onUpdate(value: string | number): void {\n localActive.value = value\n emit('update:active', value)\n}\n</script>\n\n<template>\n <UidTabs :model-value=\"localActive\" @update:model-value=\"onUpdate\">\n <template #list>\n <UidTab\n v-for=\"(tab, idx) in items\"\n :key=\"tabKey(tab, idx)\"\n :value=\"tabKey(tab, idx)\"\n >\n {{ tab.label }}\n </UidTab>\n </template>\n\n <UidTabPanel\n v-for=\"(tab, idx) in items\"\n :key=\"`panel-${tabKey(tab, idx)}`\"\n :value=\"tabKey(tab, idx)\"\n >\n <LayoutRenderer\n v-for=\"(child, cidx) in tab.items\"\n :key=\"cidx\"\n :node=\"child\"\n />\n </UidTabPanel>\n </UidTabs>\n</template>\n","/**\n * Default-bundle с минимальным набором builtin-компонентов.\n *\n * Использование:\n *\n * import { registerBuiltinComponents } from '@dskripchenko/laravel-admin'\n * registerBuiltinComponents()\n */\n\nimport { registerComponents } from './registry'\nimport TextField from '../fields/TextField.vue'\nimport TextAreaField from '../fields/TextAreaField.vue'\nimport NumberField from '../fields/NumberField.vue'\nimport SelectField from '../fields/SelectField.vue'\nimport CheckboxField from '../fields/CheckboxField.vue'\nimport DateField from '../fields/DateField.vue'\nimport TagsField from '../fields/TagsField.vue'\nimport TranslatableField from '../fields/TranslatableField.vue'\nimport RowsLayout from '../layouts/RowsLayout.vue'\nimport ColumnsLayout from '../layouts/ColumnsLayout.vue'\nimport SectionLayout from '../layouts/SectionLayout.vue'\nimport TabsLayout from '../layouts/TabsLayout.vue'\n\nexport function registerBuiltinComponents(): void {\n registerComponents({\n fields: {\n // Backend Field-классы из dskripchenko/laravel-admin отдают эти fieldType()\n // строки. Соответствие см. core/src/Field/{Input,TextArea,Select,...}.php.\n input: TextField,\n text: TextField,\n email: TextField,\n url: TextField,\n password: TextField,\n tel: TextField,\n search: TextField,\n slug: TextField,\n hidden: TextField,\n label: TextField,\n textarea: TextAreaField,\n // Fallback для wysiwyg/markdown/code — обычный TextAreaField.\n // Реальный rich-editor host подключает через subpath:\n // import { QuillField } from '@dskripchenko/laravel-admin/quill'\n // registerField('wysiwyg', QuillField)\n wysiwyg: TextAreaField,\n markdown: TextAreaField,\n code: TextAreaField,\n number: NumberField,\n slider: NumberField,\n rating: NumberField,\n select: SelectField,\n combobox: SelectField,\n radio: SelectField,\n tags: TagsField,\n // Translatable: backend Field\\TranslatableInput → fieldType()='translatable'.\n // Хранит value как Record<locale, string>; UI показывает табы по локалям.\n translatable: TranslatableField,\n 'translatable-text': TranslatableField,\n 'morph-switcher': SelectField,\n relation: SelectField,\n cascader: SelectField,\n 'tree-select': SelectField,\n checkbox: CheckboxField,\n switch: CheckboxField,\n switcher: CheckboxField,\n boolean: CheckboxField,\n date: DateField,\n datetime: DateField,\n datepicker: DateField,\n 'date-range': DateField,\n time: DateField,\n 'time-picker': DateField,\n 'color-picker': TextField,\n },\n layouts: {\n rows: RowsLayout,\n columns: ColumnsLayout,\n section: SectionLayout,\n block: SectionLayout,\n tabs: TabsLayout,\n accordion: SectionLayout,\n group: RowsLayout,\n step: SectionLayout,\n wizard: SectionLayout,\n },\n })\n}\n","<script setup lang=\"ts\">\n/**\n * TextEntry — строковое read-only значение со встроенным label.\n *\n * Render-режим:\n * - если label задан → row с label сверху и value снизу (admin-form display).\n * - если label пустой → inline span (для обёрток типа BadgeEntry).\n *\n * Auto-formatting через formatCell (см. resource/cellFormat.ts) — преобразует\n * ISO datetime в d.m.Y H:i:s и т.д., если preset указан.\n */\nimport { computed } from 'vue'\nimport { tryUseRecord } from './recordContext'\nimport { formatCell } from '../resource/cellFormat'\n\ninterface Props {\n name?: string\n label?: string\n value?: string | number | null\n /** Заместитель пустого значения. */\n placeholder?: string\n /** Применить mono-font (например для ID/UUID). */\n mono?: boolean\n /** Preset форматтер: datetime/date/money/boolean/bytes. */\n preset?: string\n meta?: Record<string, unknown>\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n name: '',\n label: '',\n value: undefined,\n placeholder: '—',\n mono: false,\n preset: undefined,\n meta: () => ({}),\n})\n\nconst record = tryUseRecord()\nconst display = computed<string>(() => {\n let v: unknown = props.value\n if (v === undefined && record && props.name) {\n v = record[props.name]\n }\n if (v === null || v === undefined || v === '') return props.placeholder\n const formatted = formatCell(v, props.preset, props.meta as Record<string, unknown>)\n return formatted === '' ? props.placeholder : formatted\n})\n\nconst hasLabel = computed<boolean>(() => Boolean(props.label))\n</script>\n\n<template>\n <div v-if=\"hasLabel\" class=\"admin-infolist-entry\">\n <span class=\"admin-infolist-entry__label\">{{ label }}</span>\n <span :class=\"['admin-infolist-entry__value', mono ? 'admin-infolist-entry__value--mono' : '']\">\n {{ display }}\n </span>\n </div>\n <span\n v-else\n :class=\"['admin-infolist-text', mono ? 'admin-infolist-text--mono' : '']\"\n >\n {{ display }}\n </span>\n</template>\n\n<style>\n.admin-infolist-entry {\n display: flex;\n flex-direction: column;\n gap: var(--uid-space-2xs);\n padding: var(--uid-space-sm) 0;\n}\n.admin-infolist-entry + .admin-infolist-entry {\n border-top: 1px solid var(--uid-border-subtle);\n}\n.admin-infolist-entry__label {\n font-size: var(--uid-font-size-xs);\n color: var(--uid-text-tertiary);\n text-transform: uppercase;\n letter-spacing: 0.04em;\n font-weight: var(--uid-font-weight-medium);\n}\n.admin-infolist-entry__value {\n font-size: var(--uid-font-size-sm);\n color: var(--uid-text-primary);\n word-break: break-word;\n white-space: pre-wrap;\n}\n.admin-infolist-entry__value--mono {\n font-family: var(--uid-font-family-mono);\n font-size: var(--uid-font-size-xs);\n}\n\n.admin-infolist-text {\n font-size: var(--uid-font-size-sm);\n color: var(--uid-text-primary);\n}\n.admin-infolist-text--mono {\n font-family: var(--uid-font-family-mono);\n font-size: var(--uid-font-size-xs);\n}\n</style>\n","<script setup lang=\"ts\">\n/**\n * BadgeEntry — строковое значение в виде UidBadge с variant'ом по value-mapping.\n *\n * Manifest:\n * { type: 'badge', name: 'status', label: 'Status',\n * map: { published: 'success', draft: 'warning', archived: 'danger' } }\n */\nimport { computed } from 'vue'\nimport { UidBadge } from '@dskripchenko/ui'\nimport { tryUseRecord } from './recordContext'\n\ntype BadgeVariant = 'default' | 'success' | 'warning' | 'danger' | 'info'\n\ninterface Props {\n name?: string\n label?: string\n value?: string | null\n /** map value → variant. Если не задан — default. */\n map?: Record<string, BadgeVariant>\n /** Принудительный variant. */\n variant?: BadgeVariant\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n name: '',\n label: '',\n value: undefined,\n map: () => ({}),\n variant: undefined,\n})\n\nconst record = tryUseRecord()\nconst value = computed<string>(() => {\n let v: unknown = props.value\n if (v === undefined && record && props.name) {\n v = record[props.name]\n }\n return v === null || v === undefined ? '' : String(v)\n})\nconst resolvedVariant = computed<BadgeVariant>(() => {\n if (props.variant) return props.variant\n return props.map[value.value] ?? 'default'\n})\n</script>\n\n<template>\n <UidBadge v-if=\"value\" :variant=\"resolvedVariant\">\n {{ value }}\n </UidBadge>\n <span v-else class=\"admin-infolist-text\">—</span>\n</template>\n","<script setup lang=\"ts\">\n/**\n * IconEntry — boolean-флаг как иконка (true → check, false → x).\n * Опционально labels: '{ true: \"Опубликовано\", false: \"Черновик\" }'.\n */\nimport { computed } from 'vue'\nimport { tryUseRecord } from './recordContext'\n\ninterface Props {\n name?: string\n label?: string\n value?: boolean | null\n /** Имя icon'и для true (lucide-key, например 'check-circle-2'). */\n trueIcon?: string\n /** Имя icon'и для false. */\n falseIcon?: string\n /** Текстовые подписи. */\n trueLabel?: string\n falseLabel?: string\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n name: '',\n label: '',\n value: undefined,\n trueIcon: 'check-circle-2',\n falseIcon: 'circle',\n trueLabel: '',\n falseLabel: '',\n})\n\nconst record = tryUseRecord()\nconst flag = computed<boolean>(() => {\n let v: unknown = props.value\n if (v === undefined && record && props.name) {\n v = record[props.name]\n }\n return Boolean(v)\n})\nconst displayLabel = computed(() => (flag.value ? props.trueLabel : props.falseLabel))\nconst iconName = computed(() => (flag.value ? props.trueIcon : props.falseIcon))\n</script>\n\n<template>\n <span :class=\"['admin-infolist-icon', flag ? 'admin-infolist-icon--on' : 'admin-infolist-icon--off']\">\n <span class=\"admin-infolist-icon__glyph\" :data-icon=\"iconName\" />\n <span v-if=\"displayLabel\">{{ displayLabel }}</span>\n </span>\n</template>\n\n<style>\n.admin-infolist-icon {\n display: inline-flex;\n align-items: center;\n gap: var(--uid-space-xs);\n font-size: var(--uid-font-size-sm);\n}\n.admin-infolist-icon--on { color: var(--uid-success); }\n.admin-infolist-icon--off { color: var(--uid-text-tertiary); }\n.admin-infolist-icon__glyph {\n display: inline-block;\n width: 14px;\n height: 14px;\n}\n</style>\n","<script setup lang=\"ts\">\n/**\n * KeyValueEntry — словарь {key: value} как UidDescriptionList.\n * Source: prop.value (Record) либо record[name].\n */\nimport { computed } from 'vue'\nimport { UidDescriptionList, UidDescriptionItem } from '@dskripchenko/ui'\nimport { tryUseRecord } from './recordContext'\n\ninterface Props {\n name?: string\n label?: string\n value?: Record<string, unknown>\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n name: '',\n label: '',\n value: undefined,\n})\n\nconst record = tryUseRecord()\nconst items = computed<Array<[string, unknown]>>(() => {\n let v: unknown = props.value\n if (v === undefined && record && props.name) {\n v = record[props.name]\n }\n if (v === null || v === undefined) return []\n if (typeof v !== 'object') return []\n return Object.entries(v as Record<string, unknown>)\n})\n\nfunction formatValue(v: unknown): string {\n if (v === null || v === undefined) return '—'\n if (typeof v === 'object') return JSON.stringify(v)\n return String(v)\n}\n</script>\n\n<template>\n <UidDescriptionList v-if=\"items.length > 0\" direction=\"vertical\" :columns=\"1\">\n <UidDescriptionItem\n v-for=\"[k, v] in items\"\n :key=\"k\"\n :label=\"k\"\n >\n {{ formatValue(v) }}\n </UidDescriptionItem>\n </UidDescriptionList>\n <span v-else class=\"admin-infolist-text\">—</span>\n</template>\n","/**\n * Default-bundle с минимальным набором builtin infolist-entry'ев.\n *\n * View-страница (ResourceViewPage) использует те же type-strings что и\n * form-page (ResourceFormPage) — backend Field::fieldType() возвращает\n * одинаковое имя в обоих контекстах. Поэтому infolist-mapping должен\n * покрывать те же типы что registerBuiltinComponents — fallback на\n * TextEntry для всех stdread-only представлений.\n */\n\nimport { registerInfolistEntries } from './registry'\nimport TextEntry from './TextEntry.vue'\nimport BadgeEntry from './BadgeEntry.vue'\nimport IconEntry from './IconEntry.vue'\nimport KeyValueEntry from './KeyValueEntry.vue'\n\nexport function registerBuiltinInfolistEntries(): void {\n registerInfolistEntries({\n // Дефолтные типы infolist (BadgeEntry::make() и т.п.).\n text: TextEntry,\n badge: BadgeEntry,\n icon: IconEntry,\n keyvalue: KeyValueEntry,\n 'key-value': KeyValueEntry,\n // Маппинг от backend Field::fieldType() → TextEntry для view-режима.\n // Host'ы могут перебить registerInfolistEntry('wysiwyg', WysiwygEntry).\n input: TextEntry,\n email: TextEntry,\n url: TextEntry,\n password: TextEntry,\n tel: TextEntry,\n search: TextEntry,\n slug: TextEntry,\n hidden: TextEntry,\n label: TextEntry,\n textarea: TextEntry,\n wysiwyg: TextEntry,\n markdown: TextEntry,\n code: TextEntry,\n number: TextEntry,\n slider: TextEntry,\n rating: TextEntry,\n select: TextEntry,\n combobox: TextEntry,\n radio: TextEntry,\n tags: TextEntry,\n 'morph-switcher': TextEntry,\n relation: TextEntry,\n cascader: TextEntry,\n 'tree-select': TextEntry,\n checkbox: TextEntry,\n switch: TextEntry,\n switcher: TextEntry,\n boolean: TextEntry,\n date: TextEntry,\n datetime: TextEntry,\n datepicker: TextEntry,\n 'date-range': TextEntry,\n time: TextEntry,\n 'time-picker': TextEntry,\n 'color-picker': TextEntry,\n })\n}\n","/**\n * createAdminApp — фабрика-helper для host-проектов.\n *\n * Собирает Vue-app со всем нужным: Pinia, Router, AdminClient, hydrated\n * stores, built-in fields/layouts/widgets/infolist, default страницы.\n * Возвращает объект где `app` готов к `.mount('#admin-app')`.\n *\n * Минимальный пример (host's resources/js/admin.js):\n *\n * import { createAdminApp } from '@dskripchenko/laravel-admin'\n * import '@dskripchenko/laravel-admin/style.css'\n *\n * const { app } = createAdminApp(window.__ADMIN_BOOTSTRAP__)\n * app.mount('#admin-app')\n *\n * Расширенное использование с переопределением страниц:\n *\n * const { app } = createAdminApp(window.__ADMIN_BOOTSTRAP__, {\n * pages: { home: MyDashboard },\n * onAppCreated: (app) => app.use(SomePlugin),\n * })\n */\n\nimport { createApp, watch, type App, type Component } from 'vue'\nimport { createPinia } from 'pinia'\nimport { createWebHistory } from 'vue-router'\n\nimport AdminApp from './components/AdminApp.vue'\nimport HomePage from './components/HomePage.vue'\nimport ForbiddenPage from './components/ForbiddenPage.vue'\nimport NotFoundPage from './components/NotFoundPage.vue'\nimport SettingsPage from './components/SettingsPage.vue'\nimport UnknownScreenPage from './components/UnknownScreenPage.vue'\nimport { LoginPage } from './components/auth'\nimport ForgotPasswordPage from './components/auth/ForgotPasswordPage.vue'\nimport ResetPasswordPage from './components/auth/ResetPasswordPage.vue'\nimport {\n ResourceIndexPage,\n ResourceFormPage,\n ResourceViewPage,\n} from './components/resource'\nimport { ProfilePage } from './components/profile'\nimport { DashboardPage } from './components/dashboard'\n\nimport { createAdminClient, type AdminClient } from './api/client'\nimport { setAdminClient } from './stores'\nimport { useAuthStore } from './stores/auth'\nimport { useLocaleStore } from './stores/locale'\nimport { useI18nStore } from './stores/i18n'\nimport { useThemeStore } from './stores/theme'\nimport { useNotificationsStore } from './stores/notifications'\nimport { useManifestStore } from './stores/manifest'\nimport { useMenuStore } from './stores/menu'\nimport { useNavigationStore } from './stores/navigation'\n\nimport { createAdminRouter, type AdminRouter, type AdminRouterOptions } from './router'\nimport { registerBuiltinComponents } from './components/render/builtin'\nimport { registerBuiltinWidgets } from './components/dashboard/builtin'\nimport { registerBuiltinInfolistEntries } from './components/infolist/builtin'\n\nimport type { AdminBootstrap } from './types/bootstrap'\n\nexport interface CreateAdminAppPages {\n /** Login page. По умолчанию core'овский LoginPage. */\n login?: Component\n /** Главная (после login). По умолчанию HomePage. */\n home?: Component\n /** 403. По умолчанию ForbiddenPage. */\n forbidden?: Component\n /** 404. По умолчанию NotFoundPage. */\n notFound?: Component\n /** Профиль. По умолчанию ProfilePage. */\n profile?: Component\n /** Auth: forgot/reset password. По умолчанию core'овские. */\n forgotPassword?: Component\n resetPassword?: Component\n /** Resource index/form/view. По умолчанию core'овские. */\n resourceIndex?: Component\n resourceCreate?: Component\n resourceEdit?: Component\n resourceView?: Component\n /** Dashboard страница (для роутов admin.dashboard.*). */\n dashboard?: Component\n /** Settings page (для admin.settings.*). */\n settings?: Component\n /** Custom Screen page (для admin.screen.*). */\n screen?: Component\n}\n\nexport interface CreateAdminAppOptions {\n /**\n * Базовый URL admin-панели. По умолчанию берётся из bootstrap.baseUrl\n * (если он pathname вида '/admin'), иначе '/admin'.\n */\n base?: string\n /** Override отдельных страниц. */\n pages?: CreateAdminAppPages\n /** Дополнительные опции router'а (extraRoutes, history, guards). */\n router?: Partial<Omit<AdminRouterOptions, 'components'>>\n /** Hook для до-настройки app перед mount (app.use(plugin), app.provide(...)). */\n onAppCreated?: (app: App) => void\n /**\n * Не вызывать manifestStore.load() автоматически. По умолчанию false —\n * createAdminApp сам подгружает manifest и выстраивает динамические роуты.\n */\n skipManifestLoad?: boolean\n}\n\nexport interface AdminAppHandle {\n app: App\n router: AdminRouter\n client: AdminClient\n}\n\n/**\n * Создать Vue admin-app, готовый к `.mount('#admin-app')`.\n *\n * Шаги внутри:\n * 1. Pinia + AdminClient (axios через bootstrap.csrf/apiUrl).\n * 2. Hydrate auth/locale/theme/notifications stores из bootstrap.\n * 3. Регистрация built-in fields/layouts/widgets/infolist entries.\n * 4. Router со static-routes (login/home/profile/forbidden/notFound) +\n * async manifest load → replaceManifestRoutes для resource/screen/\n * settings/dashboard.\n * 5. Возврат `{ app, router, client }`. Host вызывает `app.mount(...)`.\n */\nexport function createAdminApp(\n bootstrap: AdminBootstrap,\n options: CreateAdminAppOptions = {},\n): AdminAppHandle {\n const pages = options.pages ?? {}\n const base = options.base ?? deriveBase(bootstrap.baseUrl) ?? '/admin'\n\n // 1. AdminClient\n const client = createAdminClient({\n baseURL: bootstrap.apiUrl,\n csrfToken: bootstrap.csrf,\n })\n setAdminClient(client)\n\n // 2. Vue app + Pinia\n const app = createApp(AdminApp)\n const pinia = createPinia()\n app.use(pinia)\n\n // 3. Pinia stores hydrate\n useAuthStore().hydrate(bootstrap)\n useLocaleStore().hydrate(bootstrap)\n useThemeStore().hydrate(bootstrap)\n useNotificationsStore().hydrate(bootstrap)\n useI18nStore().hydrate(bootstrap)\n\n // 4. Builtin field/layout/widget/infolist registries\n registerBuiltinComponents()\n registerBuiltinWidgets()\n registerBuiltinInfolistEntries()\n\n // 5. Router\n const router = createAdminRouter({\n base,\n history: options.router?.history ?? createWebHistory(base),\n components: {\n login: pages.login ?? LoginPage,\n home: pages.home ?? HomePage,\n forbidden: pages.forbidden ?? ForbiddenPage,\n notFound: pages.notFound ?? NotFoundPage,\n profile: pages.profile ?? ProfilePage,\n forgotPassword: pages.forgotPassword ?? ForgotPasswordPage,\n resetPassword: pages.resetPassword ?? ResetPasswordPage,\n resourceIndex: pages.resourceIndex ?? ResourceIndexPage,\n resourceCreate: pages.resourceCreate ?? ResourceFormPage,\n resourceEdit: pages.resourceEdit ?? ResourceFormPage,\n resourceView: pages.resourceView ?? ResourceViewPage,\n dashboard: pages.dashboard ?? DashboardPage,\n settings: pages.settings ?? SettingsPage,\n screen: pages.screen ?? UnknownScreenPage,\n },\n extraRoutes: options.router?.extraRoutes,\n authGuard: options.router?.authGuard,\n titleGuard: options.router?.titleGuard,\n })\n app.use(router)\n\n // 5.1 Top loading-bar hooks: pending++ при старте навигации, pending--\n // при её завершении.\n const navStore = useNavigationStore()\n router.beforeEach((to, from, next) => {\n if (to.fullPath !== from.fullPath) navStore.start()\n next()\n })\n router.afterEach(() => {\n navStore.end()\n })\n router.onError(() => {\n navStore.end()\n })\n\n // 5.2 Pre-fetch resource data ДО mount страницы. Это держит navigation в\n // pending'е — старая страница остаётся в DOM пока новая загружает данные.\n // После resolve hook'а Vue Router монтирует новую страницу с уже\n // наполненным store'ом, что устраняет flash \"пустая страница →\n // данные приехали\" (без необходимости в Suspense).\n router.beforeResolve(async (to, _from, next) => {\n // Только resource.index роуты предзагружают свой dataset.\n const name = typeof to.name === 'string' ? to.name : null\n if (name && name.startsWith('admin.resource.') && name.endsWith('.index')) {\n const slug = (to.params.slug as string | undefined) ?? (to.meta.slug as string | undefined)\n if (slug) {\n try {\n // Lazy-import чтобы избежать circular в createAdminApp init.\n const { useResourceIndexStore } = await import('./stores/resourceIndex')\n const indexStore = useResourceIndexStore()\n if (indexStore.slug !== slug || indexStore.items.length === 0) {\n indexStore.setSlug(slug)\n await indexStore.load().catch(() => undefined)\n }\n } catch {\n // silent — page mount упадёт в свой error-state.\n }\n }\n }\n next()\n })\n\n // 6. Manifest async-load + dynamic routes (только если authenticated;\n // при появлении user после login — manifest подгружается автоматически).\n if (!options.skipManifestLoad) {\n const manifestStore = useManifestStore()\n const authStore = useAuthStore()\n\n const menuStore = useMenuStore()\n\n const loadAndApply = async (): Promise<void> => {\n // Параллельно с manifest'ом тянем sidebar-меню (от backend menu endpoint).\n void menuStore.load().catch(() => undefined)\n\n try {\n const manifest = await manifestStore.load()\n router.replaceManifestRoutes(manifest)\n // Если текущий route был разрешён в catch-all notFound (deep-link\n // на /r/articles/123/edit при первом mount, когда динамические\n // роуты ещё не были добавлены) — перерезолвим его теперь, когда\n // routes есть. Дожидаемся router.replace ДО того как выставим\n // bootResolved — иначе AdminApp на одном кадре увидит\n // (manifest !== null, route.name === 'admin.notFound') и сверкнёт 404.\n const current = router.currentRoute.value\n if (current.name === 'admin.notFound' && current.fullPath !== '/') {\n await router.replace(current.fullPath).catch(() => undefined)\n }\n } catch (error) {\n // Silent fail — host может перехватить через onAppCreated →\n // app.config.errorHandler. Manifest перезагрузится при следующем\n // появлении user (watch ниже).\n if (typeof console !== 'undefined') {\n console.error('[laravel-admin] manifest load failed:', error)\n }\n } finally {\n // Открываем гейт NotFoundPage. После этой точки реальный 404\n // (несуществующий URL) уже корректно отрисуется без вспышки.\n manifestStore.bootResolved = true\n }\n }\n\n if (authStore.isAuthenticated) {\n // Inline-bootstrap уже принёс user'а — грузим сразу.\n void loadAndApply()\n } else {\n // Login flow — manifest не нужен прямо сейчас; гейт открыт сразу,\n // чтобы LoginPage / NotFoundPage отрисовались штатно.\n manifestStore.bootResolved = true\n }\n // Если user'а ещё нет (login flow) либо появится позже —\n // подписываемся и грузим когда появится. immediate: false чтобы не\n // дублировать вызов при isAuthenticated=true выше.\n watch(\n () => authStore.user,\n (newUser, oldUser) => {\n if (newUser && !oldUser) {\n // Новый login → требуется свежий manifest, гейт сбрасываем.\n manifestStore.bootResolved = false\n void loadAndApply()\n }\n },\n )\n } else {\n // Host явно отключил manifest — гейт открыт сразу.\n useManifestStore().bootResolved = true\n }\n\n // 7. host hook\n options.onAppCreated?.(app)\n\n return { app, router, client }\n}\n\n/**\n * Извлечь base path из bootstrap.baseUrl ('http://app.test/admin' → '/admin').\n */\nfunction deriveBase(baseUrl: string | undefined): string | null {\n if (!baseUrl) return null\n try {\n const url = new URL(baseUrl)\n return url.pathname || '/admin'\n } catch {\n return baseUrl.startsWith('/') ? baseUrl : null\n }\n}\n","/**\n * Загрузка bootstrap-payload'а в SPA.\n *\n * Поддерживает обе стратегии:\n * - 'inline' — читает window.__ADMIN_BOOTSTRAP__ (инжект через\n * shell.blade при strategy=inline).\n * - 'xhr' — fetch'ит /api/admin/system/bootstrap.\n *\n * Если оба способа не дали результата — throw'ит. SPA должна это поймать\n * и показать full-screen error.\n */\n\nimport type { AdminBootstrap } from '../types/bootstrap'\nimport type { AdminClient } from './client'\nimport { NetworkError } from './errors'\n\nexport interface LoadBootstrapOptions {\n /** Если задан client — fallback на xhr через него. */\n client?: AdminClient\n /** Override URL для xhr. Default: '/system/bootstrap'. */\n xhrUrl?: string\n}\n\n/**\n * Возвращает bootstrap или null если не загрузился.\n *\n * Порядок:\n * 1. window.__ADMIN_BOOTSTRAP__ (inline-strategy).\n * 2. xhr fetch если передан client.\n * 3. null — caller решает что делать (показать error-screen).\n */\nexport async function loadBootstrap(\n opts: LoadBootstrapOptions = {},\n): Promise<AdminBootstrap | null> {\n const inline = readInlineBootstrap()\n if (inline) {\n return inline\n }\n\n if (opts.client) {\n try {\n const url = opts.xhrUrl ?? '/system/bootstrap'\n return await opts.client.get<AdminBootstrap>(url)\n } catch (err) {\n if (err instanceof NetworkError) {\n // Network failure — caller должен показать offline-screen.\n return null\n }\n throw err\n }\n }\n\n return null\n}\n\n/**\n * Прочитать bootstrap из window — только в браузерном контексте.\n */\nexport function readInlineBootstrap(): AdminBootstrap | null {\n if (typeof window === 'undefined') return null\n return window.__ADMIN_BOOTSTRAP__ ?? null\n}\n\n/**\n * Прочитать CSRF-token из meta-tag (Blade-injection через `csrf_token()`).\n *\n * Используется как fallback если bootstrap.csrf отсутствует.\n */\nexport function readCsrfFromMeta(): string | null {\n if (typeof document === 'undefined') return null\n const meta = document.querySelector('meta[name=\"csrf-token\"]')\n return meta?.getAttribute('content') ?? null\n}\n","<script setup lang=\"ts\">\n/**\n * NotificationsDrawer — UidDrawer (right, 400px) с tabs (Все/Непрочитанные/\n * Прочитанные) и списком notification-items.\n *\n * Эталон handoff'а (screens-secondary.jsx → NotificationDrawer):\n * - Header: «Уведомления (3)» + actions (Прочитать все)\n * - Tabs: counts, активный tab подсвечен accent\n * - Item: kind-coloured icon (info/success/warning/error) +\n * title (bold если unread) + body + relative timestamp;\n * unread items имеют tinted background + dot слева\n * - Click на item → переход на data.url + auto markAsRead\n * - Hover показывает кнопку '×' (destroy)\n */\nimport { computed, watch } from 'vue'\nimport { UidButton, UidDrawer, UidTabs, UidTab, UidTabPanel } from '@dskripchenko/ui'\nimport { useNotificationsStore, type NotificationFilter, type NotificationItem } from '../../stores/notifications'\n\ninterface Props {\n /** v-model:open. */\n open: boolean\n}\n\nconst props = defineProps<Props>()\nconst emit = defineEmits<{\n 'update:open': [value: boolean]\n /** Click on notification item — host обрабатывает navigation на data.url. */\n 'select-item': [item: NotificationItem]\n}>()\n\nconst notifications = useNotificationsStore()\n\nfunction setOpen(v: boolean): void {\n emit('update:open', v)\n}\n\n// Загружаем при открытии.\nwatch(\n () => props.open,\n async (next) => {\n if (next) {\n await notifications.load(notifications.lastFilter ?? 'all', 1).catch(() => undefined)\n }\n },\n { immediate: true },\n)\n\nconst activeFilter = computed<NotificationFilter>(() => notifications.lastFilter ?? 'all')\n\nasync function setFilter(filter: NotificationFilter | string | number): Promise<void> {\n await notifications\n .load(filter as NotificationFilter, 1)\n .catch(() => undefined)\n}\n\nasync function markAllRead(): Promise<void> {\n await notifications.markAllAsRead().catch(() => undefined)\n}\n\nasync function onItemClick(item: NotificationItem): Promise<void> {\n emit('select-item', item)\n if (!item.read_at) {\n await notifications.markAsRead(item.id).catch(() => undefined)\n }\n}\n\nasync function onDestroy(item: NotificationItem, event: Event): Promise<void> {\n event.stopPropagation()\n await notifications.destroy(item.id).catch(() => undefined)\n}\n\nfunction itemKind(item: NotificationItem): 'info' | 'success' | 'warning' | 'danger' {\n const lvl = item.data.level\n if (lvl === 'success' || lvl === 'warning' || lvl === 'danger') return lvl\n return 'info'\n}\n\nfunction itemTitle(item: NotificationItem): string {\n return (item.data.title as string | undefined) ?? '—'\n}\n\nfunction itemBody(item: NotificationItem): string {\n return (item.data.body as string | undefined) ?? ''\n}\n\nfunction relTime(iso: string | null): string {\n if (!iso) return ''\n const dt = new Date(iso)\n const diff = Math.max(0, Date.now() - dt.getTime())\n const mins = Math.floor(diff / 60000)\n if (mins < 1) return 'только что'\n if (mins < 60) return `${mins} мин назад`\n const hours = Math.floor(mins / 60)\n if (hours < 24) return `${hours} ч назад`\n const days = Math.floor(hours / 24)\n if (days < 7) return `${days} д назад`\n return dt.toLocaleDateString('ru-RU')\n}\n</script>\n\n<template>\n <UidDrawer\n :model-value=\"open\"\n side=\"right\"\n width=\"400px\"\n title=\"Уведомления\"\n @update:model-value=\"setOpen\"\n >\n <template #header>\n <div class=\"admin-notifs__hd\">\n <h2 class=\"admin-notifs__title\">\n Уведомления\n <span v-if=\"notifications.unreadCount > 0\" class=\"admin-notifs__count\">\n ({{ notifications.unreadCount }})\n </span>\n </h2>\n <UidButton\n v-if=\"notifications.unreadCount > 0\"\n variant=\"ghost\"\n size=\"sm\"\n @click=\"markAllRead\"\n >\n Прочитать все\n </UidButton>\n </div>\n </template>\n\n <UidTabs :model-value=\"activeFilter\" @update:model-value=\"setFilter\">\n <template #list>\n <UidTab value=\"all\">Все</UidTab>\n <UidTab value=\"unread\">\n Непрочитанные<template v-if=\"notifications.unreadCount > 0\">\n ({{ notifications.unreadCount }})\n </template>\n </UidTab>\n <UidTab value=\"read\">Прочитанные</UidTab>\n </template>\n\n <UidTabPanel v-for=\"filter in (['all','unread','read'] as const)\" :key=\"filter\" :value=\"filter\">\n <ul class=\"admin-notifs__list\">\n <li v-if=\"notifications.loading\" class=\"admin-notifs__empty\">\n Загрузка…\n </li>\n <li v-else-if=\"notifications.items.length === 0\" class=\"admin-notifs__empty\">\n Нет уведомлений\n </li>\n <li\n v-for=\"item in notifications.items\"\n :key=\"item.id\"\n :class=\"[\n 'admin-notifs__item',\n `admin-notifs__item--${itemKind(item)}`,\n { 'admin-notifs__item--unread': !item.read_at },\n ]\"\n @click=\"onItemClick(item)\"\n >\n <span class=\"admin-notifs__icon\" :data-kind=\"itemKind(item)\" />\n <div class=\"admin-notifs__body\">\n <div class=\"admin-notifs__row1\">\n <strong v-if=\"!item.read_at\" class=\"admin-notifs__title-strong\">\n {{ itemTitle(item) }}\n </strong>\n <span v-else class=\"admin-notifs__title-soft\">{{ itemTitle(item) }}</span>\n <span class=\"admin-notifs__time\">{{ relTime(item.created_at) }}</span>\n </div>\n <p v-if=\"itemBody(item)\" class=\"admin-notifs__text\">{{ itemBody(item) }}</p>\n </div>\n <button\n type=\"button\"\n class=\"admin-notifs__close\"\n :aria-label=\"'Удалить'\"\n @click=\"onDestroy(item, $event)\"\n >\n ×\n </button>\n </li>\n </ul>\n </UidTabPanel>\n </UidTabs>\n </UidDrawer>\n</template>\n\n<style>\n.admin-notifs__hd {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--uid-space-sm);\n}\n.admin-notifs__title {\n margin: 0;\n font-size: var(--uid-font-size-md);\n font-weight: var(--uid-font-weight-semibold);\n}\n.admin-notifs__count {\n color: var(--uid-text-tertiary);\n font-weight: var(--uid-font-weight-regular);\n font-size: var(--uid-font-size-sm);\n}\n\n.admin-notifs__list {\n list-style: none;\n margin: 0;\n padding: 0;\n}\n.admin-notifs__empty {\n padding: var(--uid-space-xl) var(--uid-space-md);\n text-align: center;\n color: var(--uid-text-tertiary);\n font-size: var(--uid-font-size-sm);\n}\n.admin-notifs__item {\n position: relative;\n display: flex;\n gap: var(--uid-space-sm);\n padding: var(--uid-space-sm) var(--uid-space-md);\n cursor: pointer;\n border-bottom: 1px solid var(--uid-border-subtle);\n}\n.admin-notifs__item:hover { background: var(--uid-surface-hover); }\n.admin-notifs__item--unread {\n background: color-mix(in srgb, var(--uid-accent) 6%, transparent);\n}\n.admin-notifs__item--unread:hover {\n background: color-mix(in srgb, var(--uid-accent) 10%, transparent);\n}\n\n.admin-notifs__icon {\n width: 28px;\n height: 28px;\n border-radius: var(--uid-radius-md);\n flex: none;\n margin-top: 2px;\n}\n.admin-notifs__icon[data-kind='info'] {\n background: color-mix(in srgb, var(--uid-info) 14%, transparent);\n}\n.admin-notifs__icon[data-kind='success'] {\n background: color-mix(in srgb, var(--uid-success) 14%, transparent);\n}\n.admin-notifs__icon[data-kind='warning'] {\n background: color-mix(in srgb, var(--uid-warning) 14%, transparent);\n}\n.admin-notifs__icon[data-kind='danger'] {\n background: color-mix(in srgb, var(--uid-danger) 14%, transparent);\n}\n\n.admin-notifs__body { flex: 1; min-width: 0; }\n.admin-notifs__row1 {\n display: flex;\n align-items: baseline;\n gap: var(--uid-space-sm);\n margin-bottom: 2px;\n}\n.admin-notifs__title-strong {\n font-size: var(--uid-font-size-sm);\n font-weight: var(--uid-font-weight-semibold);\n color: var(--uid-text-primary);\n flex: 1;\n min-width: 0;\n}\n.admin-notifs__title-soft {\n font-size: var(--uid-font-size-sm);\n color: var(--uid-text-primary);\n flex: 1;\n min-width: 0;\n}\n.admin-notifs__time {\n font-size: 11px;\n color: var(--uid-text-tertiary);\n flex: none;\n font-variant-numeric: tabular-nums;\n}\n.admin-notifs__text {\n margin: 0;\n font-size: var(--uid-font-size-xs);\n color: var(--uid-text-secondary);\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n.admin-notifs__close {\n position: absolute;\n top: 6px;\n right: 8px;\n appearance: none;\n border: 0;\n background: transparent;\n color: var(--uid-text-tertiary);\n cursor: pointer;\n font-size: 18px;\n width: 22px;\n height: 22px;\n border-radius: var(--uid-radius-sm);\n opacity: 0;\n transition: opacity var(--uid-duration-fast, 100ms);\n}\n.admin-notifs__item:hover .admin-notifs__close { opacity: 1; }\n.admin-notifs__close:hover {\n background: var(--uid-surface-hover);\n color: var(--uid-text-primary);\n}\n</style>\n","<script setup lang=\"ts\">\n/**\n * ImportWizardPage — 4-step wizard для импорта данных в Resource.\n *\n * Эталон: docs/design_handoff_laravel_admin/screens-secondary.jsx (ImportWizard).\n *\n * Шаги:\n * 1. Загрузка файла — UidFileUpload (CSV/TSV/XLSX)\n * 2. Сопоставление колонок — header'ы файла → field-name'ы ресурса\n * 3. Предпросмотр — таблица первых N строк с warning'ами\n * 4. Импорт — progress-bar + KPI (created/updated/errors)\n *\n * Library предоставляет каркас + state. Конкретные API-вызовы (analyze\n * uploaded file → headers/sample, mapping submit → preview, run import →\n * progress events) — host реализует через emit'ы.\n */\nimport { computed, ref } from 'vue'\nimport {\n UidAlert,\n UidButton,\n UidCard,\n UidFileUpload,\n UidProgress,\n UidSelect,\n UidStat,\n UidStepper,\n UidTable,\n type UidTableColumn,\n} from '@dskripchenko/ui'\n\ninterface ColumnHeader {\n key: string\n label: string\n sample?: string\n}\n\ninterface Mapping {\n /** Header из файла. */\n source: string\n /** Field-name в ресурсе либо null = пропустить. */\n target: string | null\n}\n\ninterface PreviewRow extends Record<string, unknown> {\n __warning?: string | null\n}\n\ninterface ImportProgress {\n created: number\n updated: number\n errors: number\n total: number\n}\n\ninterface Props {\n /** Заголовок страницы. */\n title?: string\n /** Опции для select'а target field'а на step 2. */\n fieldOptions: Array<{ value: string; label: string }>\n /** Headers + sample из uploaded file (host передаёт после step 1). */\n headers?: ColumnHeader[]\n /** Preview rows с warning'ами (host передаёт после step 2 submit). */\n preview?: PreviewRow[]\n /** Preview-table columns (host передаёт). */\n previewColumns?: UidTableColumn[]\n /** Финальная сводка импорта. */\n progress?: ImportProgress | null\n /** Внешне controlled-mode current step (опц.). */\n step?: number\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n title: 'Импорт',\n headers: () => [],\n preview: () => [],\n previewColumns: () => [],\n progress: null,\n step: undefined,\n})\n\nconst emit = defineEmits<{\n /** Файл загружен — host анализирует, отдаёт headers через v-bind. */\n 'file-uploaded': [file: File]\n /** Mapping submit — host генерирует preview. */\n 'mapping-submit': [mapping: Mapping[]]\n /** Run import — host выполняет с реальной записью. */\n 'run-import': []\n /** Cancel wizard. */\n cancel: []\n}>()\n\nconst STEPS = [\n { label: 'Загрузка', description: 'CSV / TSV / XLSX' },\n { label: 'Сопоставление', description: 'Колонки файла → поля' },\n { label: 'Предпросмотр', description: 'Проверка первых строк' },\n { label: 'Импорт', description: 'Запуск + сводка' },\n]\n\nconst internalStep = ref(0)\nconst currentStep = computed(() => props.step ?? internalStep.value)\n\nfunction setStep(idx: number): void {\n if (props.step !== undefined) return // controlled mode — host сам сдвигает\n if (idx < 0 || idx >= STEPS.length) return\n internalStep.value = idx\n}\n\n// Step 1: file upload\nconst uploadedFiles = ref<Array<{ file: File; id: string }>>([])\nfunction onUpload(files: Array<{ file: File; id: string }>): void {\n uploadedFiles.value = files\n if (files.length > 0) {\n emit('file-uploaded', files[0].file)\n }\n}\n\n// Step 2: mapping\nconst mapping = ref<Record<string, string | null>>({})\n\nfunction setTarget(source: string, value: string | number | null): void {\n mapping.value[source] = value === null || value === '' ? null : String(value)\n}\n\nfunction buildMapping(): Mapping[] {\n return props.headers.map((h) => ({\n source: h.key,\n target: mapping.value[h.key] ?? null,\n }))\n}\n\nfunction onMappingSubmit(): void {\n emit('mapping-submit', buildMapping())\n setStep(2)\n}\n\n// Step 3 → 4\nfunction onConfirmRun(): void {\n emit('run-import')\n setStep(3)\n}\n\n// Кнопки навигации\nconst canGoBack = computed(() => currentStep.value > 0)\nconst canGoNext = computed(() => {\n switch (currentStep.value) {\n case 0: return uploadedFiles.value.length > 0\n case 1: return Object.values(mapping.value).some((v) => v !== null)\n case 2: return true\n default: return false\n }\n})\n\nconst fileOptions = computed<Array<{ value: string; label: string }>>(() => {\n return [\n { value: '', label: 'Не импортировать' },\n ...props.fieldOptions,\n ]\n})\n\nfunction onCancel(): void {\n emit('cancel')\n}\n</script>\n\n<template>\n <section class=\"admin-page admin-import-wizard\">\n <header class=\"admin-page__hd\">\n <div class=\"admin-page__title-wrap\">\n <h1 class=\"admin-page__title\">{{ title }}</h1>\n </div>\n <div class=\"admin-page__actions\">\n <UidButton variant=\"ghost\" @click=\"onCancel\">Отмена</UidButton>\n </div>\n </header>\n\n <UidStepper :steps=\"STEPS\" :current=\"currentStep\" />\n\n <!-- Step 1: Upload -->\n <UidCard v-if=\"currentStep === 0\" padding=\"md\" class=\"admin-import-wizard__card\">\n <header class=\"admin-import-wizard__card-hd\">\n <h3>1. Загрузите файл</h3>\n <p>CSV / TSV / XLSX, до 50 MB</p>\n </header>\n <UidFileUpload\n :model-value=\"uploadedFiles\"\n accept=\".csv,.tsv,.xlsx\"\n :max-size=\"50 * 1024 * 1024\"\n :max-files=\"1\"\n primary-text=\"Перетащите файл сюда или\"\n secondary-text=\"нажмите чтобы выбрать\"\n @update:model-value=\"onUpload\"\n />\n </UidCard>\n\n <!-- Step 2: Mapping -->\n <UidCard v-else-if=\"currentStep === 1\" padding=\"md\" class=\"admin-import-wizard__card\">\n <header class=\"admin-import-wizard__card-hd\">\n <h3>2. Сопоставьте колонки</h3>\n <p>Выберите поле ресурса для каждой колонки файла</p>\n </header>\n\n <div v-if=\"headers.length === 0\" class=\"admin-import-wizard__empty\">\n Нет данных — host ещё не отдал headers. Загрузите файл сначала.\n </div>\n\n <div v-else class=\"admin-import-wizard__mapping\">\n <div v-for=\"h in headers\" :key=\"h.key\" class=\"admin-import-wizard__map-row\">\n <div class=\"admin-import-wizard__map-source\">\n <strong>{{ h.label }}</strong>\n <span v-if=\"h.sample\" class=\"admin-import-wizard__map-sample\">\n «{{ h.sample }}»\n </span>\n </div>\n <span class=\"admin-import-wizard__map-arrow\">→</span>\n <UidSelect\n :model-value=\"mapping[h.key] ?? ''\"\n :options=\"fileOptions\"\n placeholder=\"Не импортировать\"\n @update:model-value=\"(v) => setTarget(h.key, v)\"\n />\n </div>\n </div>\n </UidCard>\n\n <!-- Step 3: Preview -->\n <UidCard v-else-if=\"currentStep === 2\" padding=\"md\" class=\"admin-import-wizard__card\">\n <header class=\"admin-import-wizard__card-hd\">\n <h3>3. Предпросмотр</h3>\n <p>Первые {{ preview.length }} строк перед импортом</p>\n </header>\n\n <UidAlert\n v-if=\"preview.some((r) => r.__warning)\"\n variant=\"warning\"\n style=\"margin-bottom: var(--uid-space-md);\"\n >\n Часть строк имеет предупреждения — проверьте перед импортом.\n </UidAlert>\n\n <UidTable\n v-if=\"previewColumns.length > 0\"\n :columns=\"previewColumns\"\n :data=\"preview\"\n />\n <div v-else class=\"admin-import-wizard__empty\">\n Host не передал previewColumns/preview.\n </div>\n </UidCard>\n\n <!-- Step 4: Run + Summary -->\n <UidCard v-else padding=\"md\" class=\"admin-import-wizard__card\">\n <header class=\"admin-import-wizard__card-hd\">\n <h3>4. Импорт</h3>\n </header>\n\n <div v-if=\"!progress\" class=\"admin-import-wizard__empty\">\n Запускается импорт…\n </div>\n <template v-else>\n <UidProgress\n v-if=\"progress.total > 0\"\n :model-value=\"progress.created + progress.updated + progress.errors\"\n :max=\"progress.total\"\n />\n <div class=\"admin-import-wizard__kpi\">\n <UidStat title=\"Создано\" :value=\"progress.created\" tone=\"success\" />\n <UidStat title=\"Обновлено\" :value=\"progress.updated\" tone=\"info\" />\n <UidStat title=\"Ошибки\" :value=\"progress.errors\" tone=\"danger\" />\n </div>\n </template>\n </UidCard>\n\n <!-- Navigation buttons -->\n <footer class=\"admin-import-wizard__nav\">\n <UidButton\n v-if=\"canGoBack\"\n variant=\"ghost\"\n @click=\"setStep(currentStep - 1)\"\n >\n Назад\n </UidButton>\n <span style=\"flex:1\" />\n <UidButton\n v-if=\"currentStep === 0\"\n variant=\"primary\"\n :disabled=\"!canGoNext\"\n @click=\"setStep(1)\"\n >\n Далее\n </UidButton>\n <UidButton\n v-else-if=\"currentStep === 1\"\n variant=\"primary\"\n :disabled=\"!canGoNext\"\n @click=\"onMappingSubmit\"\n >\n Подтвердить mapping\n </UidButton>\n <UidButton\n v-else-if=\"currentStep === 2\"\n variant=\"primary\"\n @click=\"onConfirmRun\"\n >\n Запустить импорт\n </UidButton>\n </footer>\n </section>\n</template>\n\n<style>\n.admin-import-wizard {\n max-width: 1100px;\n margin: 0 auto;\n}\n.admin-import-wizard__card {\n margin-top: var(--uid-space-md);\n}\n.admin-import-wizard__card-hd {\n margin-bottom: var(--uid-space-md);\n}\n.admin-import-wizard__card-hd h3 {\n margin: 0 0 var(--uid-space-2xs);\n font-size: var(--uid-font-size-md);\n font-weight: var(--uid-font-weight-semibold);\n}\n.admin-import-wizard__card-hd p {\n margin: 0;\n font-size: var(--uid-font-size-xs);\n color: var(--uid-text-tertiary);\n}\n.admin-import-wizard__empty {\n padding: var(--uid-space-md);\n text-align: center;\n color: var(--uid-text-tertiary);\n font-size: var(--uid-font-size-sm);\n}\n.admin-import-wizard__mapping {\n display: flex;\n flex-direction: column;\n gap: var(--uid-space-sm);\n}\n.admin-import-wizard__map-row {\n display: grid;\n grid-template-columns: 1fr auto 1fr;\n gap: var(--uid-space-md);\n align-items: center;\n}\n.admin-import-wizard__map-source {\n display: flex;\n align-items: center;\n gap: var(--uid-space-sm);\n}\n.admin-import-wizard__map-sample {\n color: var(--uid-text-tertiary);\n font-size: var(--uid-font-size-xs);\n font-style: italic;\n}\n.admin-import-wizard__map-arrow {\n color: var(--uid-text-tertiary);\n font-size: var(--uid-font-size-md);\n}\n.admin-import-wizard__kpi {\n display: grid;\n grid-template-columns: repeat(3, minmax(0, 1fr));\n gap: var(--uid-space-md);\n margin-top: var(--uid-space-md);\n}\n.admin-import-wizard__nav {\n display: flex;\n align-items: center;\n gap: var(--uid-space-sm);\n margin-top: var(--uid-space-md);\n}\n</style>\n","<script setup lang=\"ts\">\n/**\n * FieldGalleryPage — каталог field-компонентов.\n *\n * Эталон: docs/design_handoff_laravel_admin/screens-secondary.jsx (FieldGallery).\n *\n * 3-col grid из demo-cards. Каждая card:\n * - Group label (например \"Текстовые\")\n * - Тип поля (json type-key)\n * - Демо-компонент с sample-данными\n * - Краткое описание\n *\n * Используется как:\n * 1. Тестовая площадка для devs (визуально все Uid* fields на одной странице)\n * 2. Docs / referencer для host'ов\n *\n * Все секции рендерятся через FieldRenderer + provideFormState с локальной\n * state-mock'ой.\n */\nimport { reactive } from 'vue'\nimport { UidCard } from '@dskripchenko/ui'\nimport FieldRenderer, { type FieldNode } from '../render/FieldRenderer.vue'\nimport { provideFormState } from '../render/formState'\n\ninterface Demo {\n type: string\n group: string\n title: string\n description: string\n /** Demo node для FieldRenderer'а. */\n node: FieldNode\n /** Initial state для form-context. */\n initial: Record<string, unknown>\n}\n\nconst DEMOS: Demo[] = [\n // Текстовые\n {\n type: 'text',\n group: 'Текстовые',\n title: 'Input',\n description: 'Простой текстовый input. type=email/url/password/tel доступны через inputType.',\n node: { type: 'text', name: 'demo_text', label: 'Заголовок статьи', placeholder: 'Например: Введение в Laravel' },\n initial: { demo_text: 'Hello World' },\n },\n {\n type: 'textarea',\n group: 'Текстовые',\n title: 'Textarea',\n description: 'Многострочный input с настраиваемым числом rows.',\n node: { type: 'textarea', name: 'demo_textarea', label: 'Описание', rows: 4 },\n initial: { demo_textarea: 'Multi-line text...' },\n },\n {\n type: 'number',\n group: 'Текстовые',\n title: 'NumberInput',\n description: 'Числовой input. Empty/NaN автоматически конвертируются в null.',\n node: { type: 'number', name: 'demo_number', label: 'Цена', min: 0, max: 1000 },\n initial: { demo_number: 42 },\n },\n // Выбор\n {\n type: 'select',\n group: 'Выбор',\n title: 'Select',\n description: 'Single-select с options. Поддерживает searchable + clearable.',\n node: {\n type: 'select',\n name: 'demo_select',\n label: 'Категория',\n options: [\n { value: 'frontend', label: 'Frontend' },\n { value: 'backend', label: 'Backend' },\n { value: 'devops', label: 'DevOps' },\n ],\n },\n initial: { demo_select: 'backend' },\n },\n {\n type: 'checkbox',\n group: 'Выбор',\n title: 'Checkbox',\n description: 'Boolean toggle. inlineLabel рядом с боксом.',\n node: { type: 'checkbox', name: 'demo_checkbox', label: 'Опубликовать', inlineLabel: 'Сделать доступным всем' },\n initial: { demo_checkbox: true },\n },\n // Дата/время\n {\n type: 'date',\n group: 'Дата/время',\n title: 'DatePicker',\n description: 'date / datetime-local / time через inputType.',\n node: { type: 'date', name: 'demo_date', label: 'Дата публикации', inputType: 'date' },\n initial: { demo_date: '2026-05-01' },\n },\n]\n\n// Группируем для рендера.\nconst groupedDemos = DEMOS.reduce<Record<string, Demo[]>>((acc, d) => {\n if (!acc[d.group]) acc[d.group] = []\n acc[d.group].push(d)\n return acc\n}, {})\n\n// provideFormState на корневом уровне — все demo'и шарят один form-context\n// (имена не пересекаются благодаря demo_ префиксу).\nconst allInitial = reactive<Record<string, unknown>>(\n DEMOS.reduce<Record<string, unknown>>((acc, d) => Object.assign(acc, d.initial), {}),\n)\nprovideFormState(allInitial)\n</script>\n\n<template>\n <section class=\"admin-page admin-field-gallery\">\n <header class=\"admin-page__hd\">\n <div class=\"admin-page__title-wrap\">\n <h1 class=\"admin-page__title\">Field Gallery</h1>\n <div class=\"admin-page__count\">\n Каталог встроенных field-компонентов library + примеры использования\n </div>\n </div>\n </header>\n\n <section v-for=\"(items, group) in groupedDemos\" :key=\"group\" class=\"admin-gallery__group\">\n <h2 class=\"admin-gallery__group-title\">{{ group }}</h2>\n <div class=\"admin-gallery__grid\">\n <UidCard\n v-for=\"demo in items\"\n :key=\"demo.type + demo.title\"\n padding=\"md\"\n class=\"admin-gallery__card\"\n >\n <header class=\"admin-gallery__card-hd\">\n <h3 class=\"admin-gallery__card-title\">{{ demo.title }}</h3>\n <code class=\"admin-gallery__card-type\">type: {{ demo.type }}</code>\n </header>\n <p class=\"admin-gallery__card-desc\">{{ demo.description }}</p>\n <div class=\"admin-gallery__card-demo\">\n <FieldRenderer :node=\"demo.node\" />\n </div>\n </UidCard>\n </div>\n </section>\n </section>\n</template>\n\n<style>\n.admin-gallery__group {\n margin-bottom: var(--uid-space-2xl);\n}\n.admin-gallery__group-title {\n margin: 0 0 var(--uid-space-md);\n font-size: var(--uid-font-size-lg);\n font-weight: var(--uid-font-weight-semibold);\n color: var(--uid-text-primary);\n}\n.admin-gallery__grid {\n display: grid;\n grid-template-columns: repeat(3, minmax(0, 1fr));\n gap: var(--uid-space-md);\n}\n@media (max-width: 960px) {\n .admin-gallery__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }\n}\n@media (max-width: 640px) {\n .admin-gallery__grid { grid-template-columns: 1fr; }\n}\n.admin-gallery__card {\n display: flex;\n flex-direction: column;\n}\n.admin-gallery__card-hd {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--uid-space-sm);\n margin-bottom: var(--uid-space-xs);\n}\n.admin-gallery__card-title {\n margin: 0;\n font-size: var(--uid-font-size-sm);\n font-weight: var(--uid-font-weight-semibold);\n}\n.admin-gallery__card-type {\n font-family: var(--uid-font-family-mono);\n font-size: 11px;\n color: var(--uid-text-tertiary);\n background: var(--uid-surface-base);\n padding: 1px 6px;\n border-radius: var(--uid-radius-sm);\n border: 1px solid var(--uid-border-subtle);\n}\n.admin-gallery__card-desc {\n margin: 0 0 var(--uid-space-md);\n font-size: var(--uid-font-size-xs);\n color: var(--uid-text-tertiary);\n line-height: var(--uid-line-height-normal);\n}\n.admin-gallery__card-demo {\n flex: 1;\n display: flex;\n flex-direction: column;\n justify-content: flex-end;\n}\n</style>\n"],"names":["toKebabCase","string","defaultAttributes","Icon","size","strokeWidth","absoluteStrokeWidth","color","iconNode","name","classes","props","slots","h","child","createLucideIcon","iconName","Activity","Archive","ArrowLeft","Bell","Bookmark","Box","Briefcase","Calendar","ChartColumn","ChartLine","ChartPie","Check","ChevronDown","CircleAlert","CircleCheckBig","CircleHelp","CircleUser","CircleX","Clock","Code","Cog","Columns2","Command","Database","Download","Ellipsis","Eye","FileClock","FileText","Files","Flag","FolderOpen","Folder","Gauge","Globe","Grid3x3","GripVertical","HardDrive","Hash","Heart","History","House","Image","Images","Inbox","Info","Key","Layers","LayoutDashboard","LayoutGrid","LifeBuoy","Link","ListChecks","List","Lock","LogOut","Mail","MapPin","Map","MessageSquare","Monitor","Moon","Package","PanelLeft","PanelsTopLeft","Paperclip","Pencil","Plus","RefreshCw","RotateCcw","Search","Send","Server","Settings","Shield","ShoppingBag","ShoppingCart","SlidersVertical","SquarePen","Star","Store","Sun","Tag","Tags","Terminal","Trash2","TrendingUp","TriangleAlert","Upload","UserPlus","User","Users","X","Zap","_client","setAdminClient","client","getAdminClient","clearAdminClient","hasAdminClient","useThemeStore","defineStore","current","ref","available","isDark","computed","hydrate","bootstrap","applyHtmlAttr","applyLocal","theme","setTheme","previous","err","icon","ariaLabel","toggle","next","_createElementBlock","_createVNode","_unref","UidIcon","useLocaleStore","applySideEffects","locale","setLocale","pick","loc","_createBlock","UidMenu","_createElementVNode","_hoisted_1","_toDisplayString","_openBlock","_Fragment","_renderList","UidMenuItem","$event","_createTextVNode","useNotificationsStore","items","unreadCount","loading","lastFilter","meta","isOpen","hasUnread","openDrawer","closeDrawer","toggleDrawer","load","filter","page","result","loadUnread","markAsRead","id","item","n","markAllAsRead","now","destroy","index","wasUnread","notifications","display","onClick","_hoisted_2","ApiError","status","payload","UnauthenticatedError","ForbiddenError","NotFoundError","ValidationError","messages","NetworkError","message","toApiError","useAuthStore","user","permissions","pendingChallenge","isAuthenticated","isChallengePending","hasPermission","key","permission","prefix","hasAnyPermission","keys","hasAllPermissions","login","challengeToken","twoFactorChallenge","code","twoFactorRecovery","recoveryCode","cancelChallenge","logout","auth","router","useRouter","goProfile","UidAvatar","_cache","UidMenuSeparator","__props","emit","__emit","lastIdx","_renderSlot","_ctx","crumb","idx","_hoisted_3","_resolveDynamicComponent","_normalizeClass","_hoisted_4","NotificationBell","ThemeToggle","LocaleSwitcher","UserMenu","useMenuStore","error","isLoaded","visibleItems","it","filteredChildren","c","i","groupedItems","groups","groupKey","group","list","a","b","orderDiff","force","response","setItems","reset","TEAL","INK","radius","fontSize","padX","cursorW","cursorH","cursorGap","bg","fg","wrapStyle","cursorStyle","REGISTRY","AlertCircle","BarChart3","CheckCircle","Grid","HelpCircle","Home","Layout","LineChart","PieChart","Sliders","UserCircle","XCircle","resolveIcon","menu","route","useRoute","isActive","iconSlot","resolved","itemTarget","UidSidebar","_component_router_link","BrandLogo","grp","UidSidebarGroup","UidSidebarItem","_hoisted_6","HTML_ATTR","internalCollapsed","isExternallyControlled","collapsed","onCollapseChange","value","exitImpersonation","watch","val","onBeforeUnmount","UidSidebarLayout","AdminSidebar","AdminTopBar","useNavigationStore","pending","isLoading","start","end","nav","visible","hideTimer","cls","tabs","selectTab","onMarkAll","onItemClick","url","onDelete","e","close","iconFor","t","AlertTriangle","variantFor","relativeTime","iso","ts","diff","viewOf","d","title","description","tabCounts","total","unread","read","open","onKey","onUnmounted","_Teleport","_Transition","_hoisted_5","_hoisted_7","tab","_hoisted_9","_hoisted_10","_hoisted_11","_hoisted_12","_hoisted_13","_hoisted_16","_hoisted_17","_hoisted_18","_hoisted_19","_hoisted_20","_hoisted_21","_withModifiers","useManifestStore","manifest","bootResolved","version","resources","screens","settings","plugins","getResource","slug","r","getScreen","s","getSettings","shorthand","opts","adminToast","useToast","impersonation","registry","useShell","suppressNotFound","AdminLoadingBar","AdminShell","_component_router_view","_withCtx","Component","NotificationsDrawer","UidToastProvider","useDashboardStore","editMode","draft","original","saving","isDirty","openDashboard","dashboardSlug","enterEditMode","cancelEdit","saveLayout","widgets","resetToDefault","addWidget","removeWidget","slugKey","updateWidget","patch","moveWidget","fromIdx","toIdx","moved","useI18nStore","setMessages","replace","str","k","v","createComponentRegistry","store","type","bundle","registerWidget","getWidget","hasWidget","listWidgets","clearWidgetRegistry","registerWidgets","UidAlert","component","widgetProps","_type","_span","rest","_normalizeProps","_mergeProps","UnknownWidget","$emit","types","selectedType","markdownContent","statLabel","statValue","gaugeValue","chartLabels","chartValues","recentResource","recentLimit","cfg","firstStat","labels","datasets","canSubmit","labelOf","configKind","buildConfig","base","data","onSubmit","sizeNum","config","UidInput","_hoisted_14","_hoisted_15","_hoisted_22","_hoisted_23","UidButton","dashboardStore","i18n","fallback","dashboard","manifestWidgets","refreshedWidgets","resolvedTitle","resolvedSubtitle","renderedWidgets","bySlug","w","out","node","spanFor","raw","periods","selectedPeriod","setPeriod","refetchPeriod","periodLabel","p","dialogMode","dialogItem","dialogInitialTitle","openAdd","closeDialog","onEnterEdit","onCancelEdit","onSaveLayout","onRemoveWidget","layoutSlug","onConfigureWidget","ensureDraftReflectsRendered","draftItem","onAddWidget","onSaveConfig","existing","dragSourceIdx","onDragStart","onDragOver","onDrop","sourceIdx","resizing","resizeContainerWidth","onResizeStart","currentSpan","onResizeMove","onResizeEnd","colWidth","delta","nextSpan","onExport","_normalizeStyle","WidgetRenderer","WidgetActionsOverlay","WidgetConfigDialog","userName","dashboards","primaryDashboardSlug","DashboardPage","UidCard","email","password","remember","submitting","generalError","fieldErrors","emailError","passwordError","submit","UidCheckbox","mode","cells","cellRefs","remaining","totpCode","isValid","setCellRef","el","onCellInput","event","target","digit","nextTick","onCellKeydown","onPaste","digits","res","cancel","switchMode","_","redirectToHome","onMounted","_hoisted_8","TwoFactorForm","LoginForm","submitted","busy","token","confirm","DEFAULT_META","useResourceIndexStore","slowLoading","slowLoadingTimer","SLOW_LOADING_DELAY","search","filters","sortKey","sortDirection","selection","isEmpty","selectedCount","hasSelection","hasError","selectionState","row","rowId","setSlug","buildParams","override","params","ss","sk","dir","f","filtersMap","body","setSearch","setFilter","clearFilters","setSort","direction","toggleSort","setPage","toggleRow","toggleAllOnPage","clearSelection","isSelected","DEFAULT_DATETIME","DEFAULT_DATE","ISO_DATETIME_RE","formatCell","preset","formatDateString","formatMoney","formatBoolean","formatBytes","input","format","date","pad","tokens","ch","currency","decimals","trueLabel","falseLabel","FilterEditor","defineComponent","opt","options","VISIBLE_LIMIT","localSearch","commitSearch","hasValue","activeFilters","inactiveFilters","revealed","inactiveVisible","inactiveHidden","reveal","hasActiveAnything","clearFilter","chipText","o","draftValues","getDraft","setDraft","applyDraft","toggleOption","multiple","cur","arr","x","isOptionChecked","groupableColumns","setGroupBy","col","colKey","colLabel","isVisible","toggleVisibility","newViewLabel","saveView","_withKeys","Columns","editing","inputRef","startEdit","commit","onKeydown","ACTIONS_KEY","REORDER_KEY","resourceMeta","displayTitle","resolvedCreateRouteName","candidate","headerActions","onCustomAction","action","blob","importInput","onImportClick","onImportFileChange","file","uploadForm","uploaded","preview","started","finalStatus","pollImportStatus","imported","failed","processId","deadline","resolve","isReorderable","columns","mapped","columnVisibility","columnIsEditable","cols","columnMeta","renderCell","slotProps","m","rowFromSlot","hasActiveFilters","showFilterBar","manifestFilters","manifestColumns","searchPlaceholder","groupByCol","onFilterApply","onSearchUpdate","onResetFilters","onGroupBy","onColumnsVisibility","savedViews","activeViewId","loadSavedViews","onApplyView","view","loadWithProgress","onResetView","onDeleteView","onSaveView","label","totalLabel","pluralRecords","mod10","mod100","lastLoadedAt","tick","tickTimer","wasLoading","liveStatus","diffSec","min","hr","scopeLabel","prev","onSortKeyUpdate","onSortDirUpdate","onSelectionUpdate","onPageChange","onRowClick","onView","onEdit","isTrashed","onRestore","dragRowIdx","onRowDragStart","onRowDragOver","onRowDrop","ids","onForceDelete","bulkAction","retryLoad","MoreHorizontal","$router","AdminFilterToolbar","UidSkeleton","UidErrorState","UidEmptyState","UidTable","InlineEditCell","_hoisted_24","_hoisted_25","_hoisted_26","UidPagination","useResourceFormStore","recordId","state","initial","errors","deleting","isCreate","isEdit","isView","replaceObject","prepareCreate","resourceSlug","defaults","targetMode","setField","setErrors","clearErrors","save","newId","fields","layouts","registerField","getField","hasField","listFields","registerLayout","getLayout","hasLayout","listLayouts","clearRegistry","registerComponents","fieldProps","attributes","UnknownField","layoutComponent","layoutProps","_kind","fieldNode","FieldRenderer","form","ctx","provideFormState","layoutNodes","titleLabel","statusValue","statusBadgeVariant","nextSlug","nextId","onSave","resolvedIndexRouteName","onCancel","UidBadge","LayoutRenderer","entries","registerInfolistEntry","getInfolistEntry","hasInfolistEntry","listInfolistEntries","clearInfolistRegistry","registerInfolistEntries","KNOWN_LAYOUTS","entry","entryProps","_t","_k","_i","attrs","rest2","sectionTitle","sectionDescription","tabsActive","tabsList","_component_InfolistRenderer","UnknownEntry","RecordKey","provideRecord","record","provide","useRecord","inject","tryUseRecord","hasItems","eventIcon","Edit","eventLabel","diffSummary","formatVal","resolvedSubjectType","defaultMetrics","rows","fmt","created","updated","author","recordTitle","indexLabel","uidLabel","STATUS_VARIANT","statusVariant","onBack","InfolistRenderer","AuditTimeline","navItems","localSection","selectSection","profile","localeOptions","l","themeOptions","onAvatarReplace","on2FADisable","on2FARegenerate","has2FA","UidSelect","TONE_MAP","uidTone","UidStat","maxValue","bars","barWidth","bar","PALETTE","slices","cumulative","startAngle","endAngle","cx","cy","x1","y1","x2","y2","largeArc","path","UidHeatmap","UidGauge","chartType","DEFAULT_PALETTE","barData","ds","barAccent","donutData","DonutChartWidget","BarChartWidget","registerBuiltinWidgets","StatWidget","ChartWidget","RecentTableWidget","HeatmapWidget","GaugeWidget","MarkdownWidget","isSuccess","env","isError","createAdminClient","instance","axios","xsrf","readCookie","apiError","wrap","method","wrapBody","match","escapeRegex","pickResourcePermission","resource","ability","perm","pickSettingsPermission","pickScreenPermission","buildResourceRoutes","components","buildScreenRoute","screen","buildSettingsRoute","buildDashboardRoute","buildRoutesFromManifest","routes","createAuthGuard","loginRouteName","forbiddenRouteName","redirectQueryKey","to","permissionsMeta","createTitleGuard","template","brand","DYNAMIC_NAME_PREFIXES","isDynamicRouteName","createAdminRouter","history","createWebHistory","staticRoutes","notFoundRoute","createRouter","allRoutes","dynamic","useFormState","errorMsg","onUpdate","UidFormField","UidTextarea","UidNumberInput","checked","UidDatePicker","tags","query","focused","containerRef","setTags","seen","trimmed","addTag","removeTag","activeIdx","filteredFlat","onInput","parts","grouped","filteredGroups","q","used","g","isItemActive","globalIdx","onContainerClick","onSelectSuggestion","onBlur","tag","gi","localeStore","availableLocales","activeLocale","update","isFilled","UidStack","defaultSpan","UidGrid","tabKey","localActive","UidTabs","UidTab","UidTabPanel","cidx","registerBuiltinComponents","TextField","TextAreaField","NumberField","SelectField","TagsField","TranslatableField","CheckboxField","DateField","RowsLayout","ColumnsLayout","SectionLayout","TabsLayout","formatted","hasLabel","resolvedVariant","flag","displayLabel","formatValue","UidDescriptionList","UidDescriptionItem","registerBuiltinInfolistEntries","TextEntry","BadgeEntry","IconEntry","KeyValueEntry","createAdminApp","pages","deriveBase","app","createApp","AdminApp","pinia","createPinia","LoginPage","HomePage","ForbiddenPage","NotFoundPage","ProfilePage","ForgotPasswordPage","ResetPasswordPage","ResourceIndexPage","ResourceFormPage","ResourceViewPage","SettingsPage","UnknownScreenPage","navStore","from","_from","resourceIndex","indexStore","manifestStore","authStore","menuStore","loadAndApply","newUser","oldUser","baseUrl","loadBootstrap","inline","readInlineBootstrap","readCsrfFromMeta","setOpen","activeFilter","markAllRead","onDestroy","itemKind","lvl","itemTitle","itemBody","relTime","dt","mins","hours","days","UidDrawer","STEPS","internalStep","currentStep","setStep","uploadedFiles","onUpload","files","mapping","setTarget","source","buildMapping","onMappingSubmit","onConfirmRun","canGoBack","canGoNext","fileOptions","UidStepper","UidFileUpload","UidProgress","DEMOS","groupedDemos","acc","allInitial","reactive","demo"],"mappings":"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","x_google_ignoreList":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97]}
1
+ {"version":3,"file":"index.cjs","sources":["../node_modules/lucide-vue-next/dist/esm/shared/src/utils.js","../node_modules/lucide-vue-next/dist/esm/defaultAttributes.js","../node_modules/lucide-vue-next/dist/esm/Icon.js","../node_modules/lucide-vue-next/dist/esm/createLucideIcon.js","../node_modules/lucide-vue-next/dist/esm/icons/activity.js","../node_modules/lucide-vue-next/dist/esm/icons/archive.js","../node_modules/lucide-vue-next/dist/esm/icons/arrow-left.js","../node_modules/lucide-vue-next/dist/esm/icons/bell.js","../node_modules/lucide-vue-next/dist/esm/icons/bookmark.js","../node_modules/lucide-vue-next/dist/esm/icons/box.js","../node_modules/lucide-vue-next/dist/esm/icons/briefcase.js","../node_modules/lucide-vue-next/dist/esm/icons/calendar.js","../node_modules/lucide-vue-next/dist/esm/icons/chart-column.js","../node_modules/lucide-vue-next/dist/esm/icons/chart-line.js","../node_modules/lucide-vue-next/dist/esm/icons/chart-pie.js","../node_modules/lucide-vue-next/dist/esm/icons/check.js","../node_modules/lucide-vue-next/dist/esm/icons/chevron-down.js","../node_modules/lucide-vue-next/dist/esm/icons/circle-alert.js","../node_modules/lucide-vue-next/dist/esm/icons/circle-check-big.js","../node_modules/lucide-vue-next/dist/esm/icons/circle-help.js","../node_modules/lucide-vue-next/dist/esm/icons/circle-user.js","../node_modules/lucide-vue-next/dist/esm/icons/circle-x.js","../node_modules/lucide-vue-next/dist/esm/icons/clock.js","../node_modules/lucide-vue-next/dist/esm/icons/code.js","../node_modules/lucide-vue-next/dist/esm/icons/cog.js","../node_modules/lucide-vue-next/dist/esm/icons/columns-2.js","../node_modules/lucide-vue-next/dist/esm/icons/command.js","../node_modules/lucide-vue-next/dist/esm/icons/database.js","../node_modules/lucide-vue-next/dist/esm/icons/download.js","../node_modules/lucide-vue-next/dist/esm/icons/ellipsis.js","../node_modules/lucide-vue-next/dist/esm/icons/eye.js","../node_modules/lucide-vue-next/dist/esm/icons/file-clock.js","../node_modules/lucide-vue-next/dist/esm/icons/file-text.js","../node_modules/lucide-vue-next/dist/esm/icons/files.js","../node_modules/lucide-vue-next/dist/esm/icons/flag.js","../node_modules/lucide-vue-next/dist/esm/icons/folder-open.js","../node_modules/lucide-vue-next/dist/esm/icons/folder.js","../node_modules/lucide-vue-next/dist/esm/icons/gauge.js","../node_modules/lucide-vue-next/dist/esm/icons/globe.js","../node_modules/lucide-vue-next/dist/esm/icons/grid-3x3.js","../node_modules/lucide-vue-next/dist/esm/icons/grip-vertical.js","../node_modules/lucide-vue-next/dist/esm/icons/hard-drive.js","../node_modules/lucide-vue-next/dist/esm/icons/hash.js","../node_modules/lucide-vue-next/dist/esm/icons/heart.js","../node_modules/lucide-vue-next/dist/esm/icons/history.js","../node_modules/lucide-vue-next/dist/esm/icons/house.js","../node_modules/lucide-vue-next/dist/esm/icons/image.js","../node_modules/lucide-vue-next/dist/esm/icons/images.js","../node_modules/lucide-vue-next/dist/esm/icons/inbox.js","../node_modules/lucide-vue-next/dist/esm/icons/info.js","../node_modules/lucide-vue-next/dist/esm/icons/key.js","../node_modules/lucide-vue-next/dist/esm/icons/layers.js","../node_modules/lucide-vue-next/dist/esm/icons/layout-dashboard.js","../node_modules/lucide-vue-next/dist/esm/icons/layout-grid.js","../node_modules/lucide-vue-next/dist/esm/icons/life-buoy.js","../node_modules/lucide-vue-next/dist/esm/icons/link.js","../node_modules/lucide-vue-next/dist/esm/icons/list-checks.js","../node_modules/lucide-vue-next/dist/esm/icons/list.js","../node_modules/lucide-vue-next/dist/esm/icons/lock.js","../node_modules/lucide-vue-next/dist/esm/icons/log-out.js","../node_modules/lucide-vue-next/dist/esm/icons/mail.js","../node_modules/lucide-vue-next/dist/esm/icons/map-pin.js","../node_modules/lucide-vue-next/dist/esm/icons/map.js","../node_modules/lucide-vue-next/dist/esm/icons/message-square.js","../node_modules/lucide-vue-next/dist/esm/icons/monitor.js","../node_modules/lucide-vue-next/dist/esm/icons/moon.js","../node_modules/lucide-vue-next/dist/esm/icons/package.js","../node_modules/lucide-vue-next/dist/esm/icons/panel-left.js","../node_modules/lucide-vue-next/dist/esm/icons/panels-top-left.js","../node_modules/lucide-vue-next/dist/esm/icons/paperclip.js","../node_modules/lucide-vue-next/dist/esm/icons/pencil.js","../node_modules/lucide-vue-next/dist/esm/icons/plus.js","../node_modules/lucide-vue-next/dist/esm/icons/refresh-cw.js","../node_modules/lucide-vue-next/dist/esm/icons/rotate-ccw.js","../node_modules/lucide-vue-next/dist/esm/icons/search.js","../node_modules/lucide-vue-next/dist/esm/icons/send.js","../node_modules/lucide-vue-next/dist/esm/icons/server.js","../node_modules/lucide-vue-next/dist/esm/icons/settings.js","../node_modules/lucide-vue-next/dist/esm/icons/shield.js","../node_modules/lucide-vue-next/dist/esm/icons/shopping-bag.js","../node_modules/lucide-vue-next/dist/esm/icons/shopping-cart.js","../node_modules/lucide-vue-next/dist/esm/icons/sliders-vertical.js","../node_modules/lucide-vue-next/dist/esm/icons/square-pen.js","../node_modules/lucide-vue-next/dist/esm/icons/star.js","../node_modules/lucide-vue-next/dist/esm/icons/store.js","../node_modules/lucide-vue-next/dist/esm/icons/sun.js","../node_modules/lucide-vue-next/dist/esm/icons/tag.js","../node_modules/lucide-vue-next/dist/esm/icons/tags.js","../node_modules/lucide-vue-next/dist/esm/icons/terminal.js","../node_modules/lucide-vue-next/dist/esm/icons/trash-2.js","../node_modules/lucide-vue-next/dist/esm/icons/trending-up.js","../node_modules/lucide-vue-next/dist/esm/icons/triangle-alert.js","../node_modules/lucide-vue-next/dist/esm/icons/upload.js","../node_modules/lucide-vue-next/dist/esm/icons/user-plus.js","../node_modules/lucide-vue-next/dist/esm/icons/user.js","../node_modules/lucide-vue-next/dist/esm/icons/users.js","../node_modules/lucide-vue-next/dist/esm/icons/x.js","../node_modules/lucide-vue-next/dist/esm/icons/zap.js","../resources/ts/stores/registry.ts","../resources/ts/stores/theme.ts","../resources/ts/components/shell/widgets/ThemeToggle.vue","../resources/ts/stores/locale.ts","../resources/ts/components/shell/widgets/LocaleSwitcher.vue","../resources/ts/stores/notifications.ts","../resources/ts/components/shell/widgets/NotificationBell.vue","../resources/ts/api/errors.ts","../resources/ts/stores/auth.ts","../resources/ts/components/shell/widgets/UserMenu.vue","../resources/ts/components/shell/AdminTopBar.vue","../resources/ts/stores/menu.ts","../resources/ts/components/shell/BrandLogo.vue","../resources/ts/components/shell/iconRegistry.ts","../resources/ts/components/shell/AdminSidebar.vue","../resources/ts/components/shell/AdminShell.vue","../resources/ts/stores/navigation.ts","../resources/ts/components/AdminLoadingBar.vue","../resources/ts/components/shell/NotificationsDrawer.vue","../resources/ts/stores/manifest.ts","../resources/ts/stores/toast.ts","../resources/ts/components/AdminApp.vue","../resources/ts/stores/dashboard.ts","../resources/ts/stores/i18n.ts","../resources/ts/components/createComponentRegistry.ts","../resources/ts/components/dashboard/registry.ts","../resources/ts/components/dashboard/UnknownWidget.vue","../resources/ts/components/dashboard/WidgetRenderer.vue","../resources/ts/components/dashboard/WidgetActionsOverlay.vue","../resources/ts/components/dashboard/WidgetConfigDialog.vue","../resources/ts/components/dashboard/DashboardPage.vue","../resources/ts/components/HomePage.vue","../resources/ts/components/ForbiddenPage.vue","../resources/ts/components/NotFoundPage.vue","../resources/ts/components/SettingsPage.vue","../resources/ts/components/UnknownScreenPage.vue","../resources/ts/components/auth/LoginForm.vue","../resources/ts/components/auth/TwoFactorForm.vue","../resources/ts/components/auth/LoginPage.vue","../resources/ts/components/auth/ForgotPasswordPage.vue","../resources/ts/components/auth/ResetPasswordPage.vue","../resources/ts/stores/resourceIndex.ts","../resources/ts/components/resource/cellFormat.ts","../resources/ts/components/resource/FilterEditor.ts","../resources/ts/components/resource/AdminFilterToolbar.vue","../resources/ts/components/resource/InlineEditCell.vue","../resources/ts/components/resource/ResourceIndexPage.vue","../resources/ts/stores/resourceForm.ts","../resources/ts/components/render/registry.ts","../resources/ts/components/fields/UnknownField.vue","../resources/ts/components/render/FieldRenderer.vue","../resources/ts/components/render/LayoutRenderer.vue","../resources/ts/components/resource/ResourceFormPage.vue","../resources/ts/components/infolist/registry.ts","../resources/ts/components/infolist/UnknownEntry.vue","../resources/ts/components/infolist/InfolistRenderer.vue","../resources/ts/components/infolist/recordContext.ts","../resources/ts/components/resource/AuditTimeline.vue","../resources/ts/components/resource/ResourceViewPage.vue","../resources/ts/components/profile/ProfilePage.vue","../resources/ts/components/dashboard/StatWidget.vue","../resources/ts/components/dashboard/BarChartWidget.vue","../resources/ts/components/dashboard/DonutChartWidget.vue","../resources/ts/components/dashboard/RecentTableWidget.vue","../resources/ts/components/dashboard/HeatmapWidget.vue","../resources/ts/components/dashboard/GaugeWidget.vue","../resources/ts/components/dashboard/MarkdownWidget.vue","../resources/ts/components/dashboard/ChartWidget.vue","../resources/ts/components/dashboard/builtin.ts","../resources/ts/api/envelope.ts","../resources/ts/api/client.ts","../resources/ts/router/builder.ts","../resources/ts/router/guards.ts","../resources/ts/router/index.ts","../resources/ts/components/fields/TextField.vue","../resources/ts/components/fields/TextAreaField.vue","../resources/ts/components/fields/NumberField.vue","../resources/ts/components/fields/SelectField.vue","../resources/ts/components/fields/CheckboxField.vue","../resources/ts/components/fields/DateField.vue","../resources/ts/components/fields/TagsField.vue","../resources/ts/components/fields/TranslatableField.vue","../resources/ts/components/layouts/RowsLayout.vue","../resources/ts/components/layouts/ColumnsLayout.vue","../resources/ts/components/layouts/SectionLayout.vue","../resources/ts/components/layouts/TabsLayout.vue","../resources/ts/components/render/builtin.ts","../resources/ts/components/infolist/TextEntry.vue","../resources/ts/components/infolist/BadgeEntry.vue","../resources/ts/components/infolist/IconEntry.vue","../resources/ts/components/infolist/KeyValueEntry.vue","../resources/ts/components/infolist/builtin.ts","../resources/ts/createAdminApp.ts","../resources/ts/api/bootstrap.ts","../resources/ts/components/notifications/NotificationsDrawer.vue","../resources/ts/components/import/ImportWizardPage.vue","../resources/ts/components/gallery/FieldGalleryPage.vue"],"sourcesContent":["/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst toKebabCase = (string) => string.replace(/([a-z0-9])([A-Z])/g, \"$1-$2\").toLowerCase();\n\nexport { toKebabCase };\n//# sourceMappingURL=utils.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nvar defaultAttributes = {\n xmlns: \"http://www.w3.org/2000/svg\",\n width: 24,\n height: 24,\n viewBox: \"0 0 24 24\",\n fill: \"none\",\n stroke: \"currentColor\",\n \"stroke-width\": 2,\n \"stroke-linecap\": \"round\",\n \"stroke-linejoin\": \"round\"\n};\n\nexport { defaultAttributes as default };\n//# sourceMappingURL=defaultAttributes.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport { h } from 'vue';\nimport { toKebabCase } from './shared/src/utils.js';\nimport defaultAttributes from './defaultAttributes.js';\n\nconst Icon = ({ size, strokeWidth = 2, absoluteStrokeWidth, color, iconNode, name, class: classes, ...props }, { slots }) => {\n return h(\n \"svg\",\n {\n ...defaultAttributes,\n width: size || defaultAttributes.width,\n height: size || defaultAttributes.height,\n stroke: color || defaultAttributes.stroke,\n \"stroke-width\": absoluteStrokeWidth ? Number(strokeWidth) * 24 / Number(size) : strokeWidth,\n class: [\"lucide\", `lucide-${toKebabCase(name ?? \"icon\")}`],\n ...props\n },\n [...iconNode.map((child) => h(...child)), ...slots.default ? [slots.default()] : []]\n );\n};\n\nexport { Icon as default };\n//# sourceMappingURL=Icon.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport { h } from 'vue';\nimport Icon from './Icon.js';\n\nconst createLucideIcon = (iconName, iconNode) => (props, { slots }) => h(\n Icon,\n {\n ...props,\n iconNode,\n name: iconName\n },\n slots\n);\n\nexport { createLucideIcon as default };\n//# sourceMappingURL=createLucideIcon.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Activity = createLucideIcon(\"ActivityIcon\", [\n [\n \"path\",\n {\n d: \"M22 12h-2.48a2 2 0 0 0-1.93 1.46l-2.35 8.36a.25.25 0 0 1-.48 0L9.24 2.18a.25.25 0 0 0-.48 0l-2.35 8.36A2 2 0 0 1 4.49 12H2\",\n key: \"169zse\"\n }\n ]\n]);\n\nexport { Activity as default };\n//# sourceMappingURL=activity.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Archive = createLucideIcon(\"ArchiveIcon\", [\n [\"rect\", { width: \"20\", height: \"5\", x: \"2\", y: \"3\", rx: \"1\", key: \"1wp1u1\" }],\n [\"path\", { d: \"M4 8v11a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8\", key: \"1s80jp\" }],\n [\"path\", { d: \"M10 12h4\", key: \"a56b0p\" }]\n]);\n\nexport { Archive as default };\n//# sourceMappingURL=archive.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst ArrowLeft = createLucideIcon(\"ArrowLeftIcon\", [\n [\"path\", { d: \"m12 19-7-7 7-7\", key: \"1l729n\" }],\n [\"path\", { d: \"M19 12H5\", key: \"x3x0zl\" }]\n]);\n\nexport { ArrowLeft as default };\n//# sourceMappingURL=arrow-left.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Bell = createLucideIcon(\"BellIcon\", [\n [\"path\", { d: \"M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9\", key: \"1qo2s2\" }],\n [\"path\", { d: \"M10.3 21a1.94 1.94 0 0 0 3.4 0\", key: \"qgo35s\" }]\n]);\n\nexport { Bell as default };\n//# sourceMappingURL=bell.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Bookmark = createLucideIcon(\"BookmarkIcon\", [\n [\"path\", { d: \"m19 21-7-4-7 4V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v16z\", key: \"1fy3hk\" }]\n]);\n\nexport { Bookmark as default };\n//# sourceMappingURL=bookmark.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Box = createLucideIcon(\"BoxIcon\", [\n [\n \"path\",\n {\n d: \"M21 8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16Z\",\n key: \"hh9hay\"\n }\n ],\n [\"path\", { d: \"m3.3 7 8.7 5 8.7-5\", key: \"g66t2b\" }],\n [\"path\", { d: \"M12 22V12\", key: \"d0xqtd\" }]\n]);\n\nexport { Box as default };\n//# sourceMappingURL=box.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Briefcase = createLucideIcon(\"BriefcaseIcon\", [\n [\"path\", { d: \"M16 20V4a2 2 0 0 0-2-2h-4a2 2 0 0 0-2 2v16\", key: \"jecpp\" }],\n [\"rect\", { width: \"20\", height: \"14\", x: \"2\", y: \"6\", rx: \"2\", key: \"i6l2r4\" }]\n]);\n\nexport { Briefcase as default };\n//# sourceMappingURL=briefcase.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Calendar = createLucideIcon(\"CalendarIcon\", [\n [\"path\", { d: \"M8 2v4\", key: \"1cmpym\" }],\n [\"path\", { d: \"M16 2v4\", key: \"4m81vk\" }],\n [\"rect\", { width: \"18\", height: \"18\", x: \"3\", y: \"4\", rx: \"2\", key: \"1hopcy\" }],\n [\"path\", { d: \"M3 10h18\", key: \"8toen8\" }]\n]);\n\nexport { Calendar as default };\n//# sourceMappingURL=calendar.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst ChartColumn = createLucideIcon(\"ChartColumnIcon\", [\n [\"path\", { d: \"M3 3v16a2 2 0 0 0 2 2h16\", key: \"c24i48\" }],\n [\"path\", { d: \"M18 17V9\", key: \"2bz60n\" }],\n [\"path\", { d: \"M13 17V5\", key: \"1frdt8\" }],\n [\"path\", { d: \"M8 17v-3\", key: \"17ska0\" }]\n]);\n\nexport { ChartColumn as default };\n//# sourceMappingURL=chart-column.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst ChartLine = createLucideIcon(\"ChartLineIcon\", [\n [\"path\", { d: \"M3 3v16a2 2 0 0 0 2 2h16\", key: \"c24i48\" }],\n [\"path\", { d: \"m19 9-5 5-4-4-3 3\", key: \"2osh9i\" }]\n]);\n\nexport { ChartLine as default };\n//# sourceMappingURL=chart-line.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst ChartPie = createLucideIcon(\"ChartPieIcon\", [\n [\n \"path\",\n {\n d: \"M21 12c.552 0 1.005-.449.95-.998a10 10 0 0 0-8.953-8.951c-.55-.055-.998.398-.998.95v8a1 1 0 0 0 1 1z\",\n key: \"pzmjnu\"\n }\n ],\n [\"path\", { d: \"M21.21 15.89A10 10 0 1 1 8 2.83\", key: \"k2fpak\" }]\n]);\n\nexport { ChartPie as default };\n//# sourceMappingURL=chart-pie.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Check = createLucideIcon(\"CheckIcon\", [[\"path\", { d: \"M20 6 9 17l-5-5\", key: \"1gmf2c\" }]]);\n\nexport { Check as default };\n//# sourceMappingURL=check.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst ChevronDown = createLucideIcon(\"ChevronDownIcon\", [\n [\"path\", { d: \"m6 9 6 6 6-6\", key: \"qrunsl\" }]\n]);\n\nexport { ChevronDown as default };\n//# sourceMappingURL=chevron-down.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst CircleAlert = createLucideIcon(\"CircleAlertIcon\", [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"10\", key: \"1mglay\" }],\n [\"line\", { x1: \"12\", x2: \"12\", y1: \"8\", y2: \"12\", key: \"1pkeuh\" }],\n [\"line\", { x1: \"12\", x2: \"12.01\", y1: \"16\", y2: \"16\", key: \"4dfq90\" }]\n]);\n\nexport { CircleAlert as default };\n//# sourceMappingURL=circle-alert.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst CircleCheckBig = createLucideIcon(\"CircleCheckBigIcon\", [\n [\"path\", { d: \"M21.801 10A10 10 0 1 1 17 3.335\", key: \"yps3ct\" }],\n [\"path\", { d: \"m9 11 3 3L22 4\", key: \"1pflzl\" }]\n]);\n\nexport { CircleCheckBig as default };\n//# sourceMappingURL=circle-check-big.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst CircleHelp = createLucideIcon(\"CircleHelpIcon\", [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"10\", key: \"1mglay\" }],\n [\"path\", { d: \"M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3\", key: \"1u773s\" }],\n [\"path\", { d: \"M12 17h.01\", key: \"p32p05\" }]\n]);\n\nexport { CircleHelp as default };\n//# sourceMappingURL=circle-help.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst CircleUser = createLucideIcon(\"CircleUserIcon\", [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"10\", key: \"1mglay\" }],\n [\"circle\", { cx: \"12\", cy: \"10\", r: \"3\", key: \"ilqhr7\" }],\n [\"path\", { d: \"M7 20.662V19a2 2 0 0 1 2-2h6a2 2 0 0 1 2 2v1.662\", key: \"154egf\" }]\n]);\n\nexport { CircleUser as default };\n//# sourceMappingURL=circle-user.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst CircleX = createLucideIcon(\"CircleXIcon\", [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"10\", key: \"1mglay\" }],\n [\"path\", { d: \"m15 9-6 6\", key: \"1uzhvr\" }],\n [\"path\", { d: \"m9 9 6 6\", key: \"z0biqf\" }]\n]);\n\nexport { CircleX as default };\n//# sourceMappingURL=circle-x.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Clock = createLucideIcon(\"ClockIcon\", [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"10\", key: \"1mglay\" }],\n [\"polyline\", { points: \"12 6 12 12 16 14\", key: \"68esgv\" }]\n]);\n\nexport { Clock as default };\n//# sourceMappingURL=clock.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Code = createLucideIcon(\"CodeIcon\", [\n [\"polyline\", { points: \"16 18 22 12 16 6\", key: \"z7tu5w\" }],\n [\"polyline\", { points: \"8 6 2 12 8 18\", key: \"1eg1df\" }]\n]);\n\nexport { Code as default };\n//# sourceMappingURL=code.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Cog = createLucideIcon(\"CogIcon\", [\n [\"path\", { d: \"M12 20a8 8 0 1 0 0-16 8 8 0 0 0 0 16Z\", key: \"sobvz5\" }],\n [\"path\", { d: \"M12 14a2 2 0 1 0 0-4 2 2 0 0 0 0 4Z\", key: \"11i496\" }],\n [\"path\", { d: \"M12 2v2\", key: \"tus03m\" }],\n [\"path\", { d: \"M12 22v-2\", key: \"1osdcq\" }],\n [\"path\", { d: \"m17 20.66-1-1.73\", key: \"eq3orb\" }],\n [\"path\", { d: \"M11 10.27 7 3.34\", key: \"16pf9h\" }],\n [\"path\", { d: \"m20.66 17-1.73-1\", key: \"sg0v6f\" }],\n [\"path\", { d: \"m3.34 7 1.73 1\", key: \"1ulond\" }],\n [\"path\", { d: \"M14 12h8\", key: \"4f43i9\" }],\n [\"path\", { d: \"M2 12h2\", key: \"1t8f8n\" }],\n [\"path\", { d: \"m20.66 7-1.73 1\", key: \"1ow05n\" }],\n [\"path\", { d: \"m3.34 17 1.73-1\", key: \"nuk764\" }],\n [\"path\", { d: \"m17 3.34-1 1.73\", key: \"2wel8s\" }],\n [\"path\", { d: \"m11 13.73-4 6.93\", key: \"794ttg\" }]\n]);\n\nexport { Cog as default };\n//# sourceMappingURL=cog.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Columns2 = createLucideIcon(\"Columns2Icon\", [\n [\"rect\", { width: \"18\", height: \"18\", x: \"3\", y: \"3\", rx: \"2\", key: \"afitv7\" }],\n [\"path\", { d: \"M12 3v18\", key: \"108xh3\" }]\n]);\n\nexport { Columns2 as default };\n//# sourceMappingURL=columns-2.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Command = createLucideIcon(\"CommandIcon\", [\n [\n \"path\",\n { d: \"M15 6v12a3 3 0 1 0 3-3H6a3 3 0 1 0 3 3V6a3 3 0 1 0-3 3h12a3 3 0 1 0-3-3\", key: \"11bfej\" }\n ]\n]);\n\nexport { Command as default };\n//# sourceMappingURL=command.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Database = createLucideIcon(\"DatabaseIcon\", [\n [\"ellipse\", { cx: \"12\", cy: \"5\", rx: \"9\", ry: \"3\", key: \"msslwz\" }],\n [\"path\", { d: \"M3 5V19A9 3 0 0 0 21 19V5\", key: \"1wlel7\" }],\n [\"path\", { d: \"M3 12A9 3 0 0 0 21 12\", key: \"mv7ke4\" }]\n]);\n\nexport { Database as default };\n//# sourceMappingURL=database.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Download = createLucideIcon(\"DownloadIcon\", [\n [\"path\", { d: \"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\", key: \"ih7n3h\" }],\n [\"polyline\", { points: \"7 10 12 15 17 10\", key: \"2ggqvy\" }],\n [\"line\", { x1: \"12\", x2: \"12\", y1: \"15\", y2: \"3\", key: \"1vk2je\" }]\n]);\n\nexport { Download as default };\n//# sourceMappingURL=download.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Ellipsis = createLucideIcon(\"EllipsisIcon\", [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"1\", key: \"41hilf\" }],\n [\"circle\", { cx: \"19\", cy: \"12\", r: \"1\", key: \"1wjl8i\" }],\n [\"circle\", { cx: \"5\", cy: \"12\", r: \"1\", key: \"1pcz8c\" }]\n]);\n\nexport { Ellipsis as default };\n//# sourceMappingURL=ellipsis.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Eye = createLucideIcon(\"EyeIcon\", [\n [\n \"path\",\n {\n d: \"M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0\",\n key: \"1nclc0\"\n }\n ],\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"3\", key: \"1v7zrd\" }]\n]);\n\nexport { Eye as default };\n//# sourceMappingURL=eye.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst FileClock = createLucideIcon(\"FileClockIcon\", [\n [\"path\", { d: \"M16 22h2a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v3\", key: \"37hlfg\" }],\n [\"path\", { d: \"M14 2v4a2 2 0 0 0 2 2h4\", key: \"tnqrlb\" }],\n [\"circle\", { cx: \"8\", cy: \"16\", r: \"6\", key: \"10v15b\" }],\n [\"path\", { d: \"M9.5 17.5 8 16.25V14\", key: \"1o80t2\" }]\n]);\n\nexport { FileClock as default };\n//# sourceMappingURL=file-clock.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst FileText = createLucideIcon(\"FileTextIcon\", [\n [\"path\", { d: \"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z\", key: \"1rqfz7\" }],\n [\"path\", { d: \"M14 2v4a2 2 0 0 0 2 2h4\", key: \"tnqrlb\" }],\n [\"path\", { d: \"M10 9H8\", key: \"b1mrlr\" }],\n [\"path\", { d: \"M16 13H8\", key: \"t4e002\" }],\n [\"path\", { d: \"M16 17H8\", key: \"z1uh3a\" }]\n]);\n\nexport { FileText as default };\n//# sourceMappingURL=file-text.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Files = createLucideIcon(\"FilesIcon\", [\n [\"path\", { d: \"M20 7h-3a2 2 0 0 1-2-2V2\", key: \"x099mo\" }],\n [\"path\", { d: \"M9 18a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h7l4 4v10a2 2 0 0 1-2 2Z\", key: \"18t6ie\" }],\n [\"path\", { d: \"M3 7.6v12.8A1.6 1.6 0 0 0 4.6 22h9.8\", key: \"1nja0z\" }]\n]);\n\nexport { Files as default };\n//# sourceMappingURL=files.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Flag = createLucideIcon(\"FlagIcon\", [\n [\"path\", { d: \"M4 15s1-1 4-1 5 2 8 2 4-1 4-1V3s-1 1-4 1-5-2-8-2-4 1-4 1z\", key: \"i9b6wo\" }],\n [\"line\", { x1: \"4\", x2: \"4\", y1: \"22\", y2: \"15\", key: \"1cm3nv\" }]\n]);\n\nexport { Flag as default };\n//# sourceMappingURL=flag.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst FolderOpen = createLucideIcon(\"FolderOpenIcon\", [\n [\n \"path\",\n {\n d: \"m6 14 1.5-2.9A2 2 0 0 1 9.24 10H20a2 2 0 0 1 1.94 2.5l-1.54 6a2 2 0 0 1-1.95 1.5H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H18a2 2 0 0 1 2 2v2\",\n key: \"usdka0\"\n }\n ]\n]);\n\nexport { FolderOpen as default };\n//# sourceMappingURL=folder-open.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Folder = createLucideIcon(\"FolderIcon\", [\n [\n \"path\",\n {\n d: \"M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z\",\n key: \"1kt360\"\n }\n ]\n]);\n\nexport { Folder as default };\n//# sourceMappingURL=folder.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Gauge = createLucideIcon(\"GaugeIcon\", [\n [\"path\", { d: \"m12 14 4-4\", key: \"9kzdfg\" }],\n [\"path\", { d: \"M3.34 19a10 10 0 1 1 17.32 0\", key: \"19p75a\" }]\n]);\n\nexport { Gauge as default };\n//# sourceMappingURL=gauge.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Globe = createLucideIcon(\"GlobeIcon\", [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"10\", key: \"1mglay\" }],\n [\"path\", { d: \"M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20\", key: \"13o1zl\" }],\n [\"path\", { d: \"M2 12h20\", key: \"9i4pu4\" }]\n]);\n\nexport { Globe as default };\n//# sourceMappingURL=globe.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Grid3x3 = createLucideIcon(\"Grid3x3Icon\", [\n [\"rect\", { width: \"18\", height: \"18\", x: \"3\", y: \"3\", rx: \"2\", key: \"afitv7\" }],\n [\"path\", { d: \"M3 9h18\", key: \"1pudct\" }],\n [\"path\", { d: \"M3 15h18\", key: \"5xshup\" }],\n [\"path\", { d: \"M9 3v18\", key: \"fh3hqa\" }],\n [\"path\", { d: \"M15 3v18\", key: \"14nvp0\" }]\n]);\n\nexport { Grid3x3 as default };\n//# sourceMappingURL=grid-3x3.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst GripVertical = createLucideIcon(\"GripVerticalIcon\", [\n [\"circle\", { cx: \"9\", cy: \"12\", r: \"1\", key: \"1vctgf\" }],\n [\"circle\", { cx: \"9\", cy: \"5\", r: \"1\", key: \"hp0tcf\" }],\n [\"circle\", { cx: \"9\", cy: \"19\", r: \"1\", key: \"fkjjf6\" }],\n [\"circle\", { cx: \"15\", cy: \"12\", r: \"1\", key: \"1tmaij\" }],\n [\"circle\", { cx: \"15\", cy: \"5\", r: \"1\", key: \"19l28e\" }],\n [\"circle\", { cx: \"15\", cy: \"19\", r: \"1\", key: \"f4zoj3\" }]\n]);\n\nexport { GripVertical as default };\n//# sourceMappingURL=grip-vertical.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst HardDrive = createLucideIcon(\"HardDriveIcon\", [\n [\"line\", { x1: \"22\", x2: \"2\", y1: \"12\", y2: \"12\", key: \"1y58io\" }],\n [\n \"path\",\n {\n d: \"M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z\",\n key: \"oot6mr\"\n }\n ],\n [\"line\", { x1: \"6\", x2: \"6.01\", y1: \"16\", y2: \"16\", key: \"sgf278\" }],\n [\"line\", { x1: \"10\", x2: \"10.01\", y1: \"16\", y2: \"16\", key: \"1l4acy\" }]\n]);\n\nexport { HardDrive as default };\n//# sourceMappingURL=hard-drive.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Hash = createLucideIcon(\"HashIcon\", [\n [\"line\", { x1: \"4\", x2: \"20\", y1: \"9\", y2: \"9\", key: \"4lhtct\" }],\n [\"line\", { x1: \"4\", x2: \"20\", y1: \"15\", y2: \"15\", key: \"vyu0kd\" }],\n [\"line\", { x1: \"10\", x2: \"8\", y1: \"3\", y2: \"21\", key: \"1ggp8o\" }],\n [\"line\", { x1: \"16\", x2: \"14\", y1: \"3\", y2: \"21\", key: \"weycgp\" }]\n]);\n\nexport { Hash as default };\n//# sourceMappingURL=hash.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Heart = createLucideIcon(\"HeartIcon\", [\n [\n \"path\",\n {\n d: \"M19 14c1.49-1.46 3-3.21 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.76 0-3 .5-4.5 2-1.5-1.5-2.74-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.3 1.5 4.05 3 5.5l7 7Z\",\n key: \"c3ymky\"\n }\n ]\n]);\n\nexport { Heart as default };\n//# sourceMappingURL=heart.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst History = createLucideIcon(\"HistoryIcon\", [\n [\"path\", { d: \"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8\", key: \"1357e3\" }],\n [\"path\", { d: \"M3 3v5h5\", key: \"1xhq8a\" }],\n [\"path\", { d: \"M12 7v5l4 2\", key: \"1fdv2h\" }]\n]);\n\nexport { History as default };\n//# sourceMappingURL=history.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst House = createLucideIcon(\"HouseIcon\", [\n [\"path\", { d: \"M15 21v-8a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v8\", key: \"5wwlr5\" }],\n [\n \"path\",\n {\n d: \"M3 10a2 2 0 0 1 .709-1.528l7-5.999a2 2 0 0 1 2.582 0l7 5.999A2 2 0 0 1 21 10v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z\",\n key: \"1d0kgt\"\n }\n ]\n]);\n\nexport { House as default };\n//# sourceMappingURL=house.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Image = createLucideIcon(\"ImageIcon\", [\n [\"rect\", { width: \"18\", height: \"18\", x: \"3\", y: \"3\", rx: \"2\", ry: \"2\", key: \"1m3agn\" }],\n [\"circle\", { cx: \"9\", cy: \"9\", r: \"2\", key: \"af1f0g\" }],\n [\"path\", { d: \"m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21\", key: \"1xmnt7\" }]\n]);\n\nexport { Image as default };\n//# sourceMappingURL=image.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Images = createLucideIcon(\"ImagesIcon\", [\n [\"path\", { d: \"M18 22H4a2 2 0 0 1-2-2V6\", key: \"pblm9e\" }],\n [\"path\", { d: \"m22 13-1.296-1.296a2.41 2.41 0 0 0-3.408 0L11 18\", key: \"nf6bnh\" }],\n [\"circle\", { cx: \"12\", cy: \"8\", r: \"2\", key: \"1822b1\" }],\n [\"rect\", { width: \"16\", height: \"16\", x: \"6\", y: \"2\", rx: \"2\", key: \"12espp\" }]\n]);\n\nexport { Images as default };\n//# sourceMappingURL=images.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Inbox = createLucideIcon(\"InboxIcon\", [\n [\"polyline\", { points: \"22 12 16 12 14 15 10 15 8 12 2 12\", key: \"o97t9d\" }],\n [\n \"path\",\n {\n d: \"M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z\",\n key: \"oot6mr\"\n }\n ]\n]);\n\nexport { Inbox as default };\n//# sourceMappingURL=inbox.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Info = createLucideIcon(\"InfoIcon\", [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"10\", key: \"1mglay\" }],\n [\"path\", { d: \"M12 16v-4\", key: \"1dtifu\" }],\n [\"path\", { d: \"M12 8h.01\", key: \"e9boi3\" }]\n]);\n\nexport { Info as default };\n//# sourceMappingURL=info.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Key = createLucideIcon(\"KeyIcon\", [\n [\"path\", { d: \"m15.5 7.5 2.3 2.3a1 1 0 0 0 1.4 0l2.1-2.1a1 1 0 0 0 0-1.4L19 4\", key: \"g0fldk\" }],\n [\"path\", { d: \"m21 2-9.6 9.6\", key: \"1j0ho8\" }],\n [\"circle\", { cx: \"7.5\", cy: \"15.5\", r: \"5.5\", key: \"yqb3hr\" }]\n]);\n\nexport { Key as default };\n//# sourceMappingURL=key.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Layers = createLucideIcon(\"LayersIcon\", [\n [\n \"path\",\n {\n d: \"m12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83Z\",\n key: \"8b97xw\"\n }\n ],\n [\"path\", { d: \"m22 17.65-9.17 4.16a2 2 0 0 1-1.66 0L2 17.65\", key: \"dd6zsq\" }],\n [\"path\", { d: \"m22 12.65-9.17 4.16a2 2 0 0 1-1.66 0L2 12.65\", key: \"ep9fru\" }]\n]);\n\nexport { Layers as default };\n//# sourceMappingURL=layers.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst LayoutDashboard = createLucideIcon(\"LayoutDashboardIcon\", [\n [\"rect\", { width: \"7\", height: \"9\", x: \"3\", y: \"3\", rx: \"1\", key: \"10lvy0\" }],\n [\"rect\", { width: \"7\", height: \"5\", x: \"14\", y: \"3\", rx: \"1\", key: \"16une8\" }],\n [\"rect\", { width: \"7\", height: \"9\", x: \"14\", y: \"12\", rx: \"1\", key: \"1hutg5\" }],\n [\"rect\", { width: \"7\", height: \"5\", x: \"3\", y: \"16\", rx: \"1\", key: \"ldoo1y\" }]\n]);\n\nexport { LayoutDashboard as default };\n//# sourceMappingURL=layout-dashboard.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst LayoutGrid = createLucideIcon(\"LayoutGridIcon\", [\n [\"rect\", { width: \"7\", height: \"7\", x: \"3\", y: \"3\", rx: \"1\", key: \"1g98yp\" }],\n [\"rect\", { width: \"7\", height: \"7\", x: \"14\", y: \"3\", rx: \"1\", key: \"6d4xhi\" }],\n [\"rect\", { width: \"7\", height: \"7\", x: \"14\", y: \"14\", rx: \"1\", key: \"nxv5o0\" }],\n [\"rect\", { width: \"7\", height: \"7\", x: \"3\", y: \"14\", rx: \"1\", key: \"1bb6yr\" }]\n]);\n\nexport { LayoutGrid as default };\n//# sourceMappingURL=layout-grid.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst LifeBuoy = createLucideIcon(\"LifeBuoyIcon\", [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"10\", key: \"1mglay\" }],\n [\"path\", { d: \"m4.93 4.93 4.24 4.24\", key: \"1ymg45\" }],\n [\"path\", { d: \"m14.83 9.17 4.24-4.24\", key: \"1cb5xl\" }],\n [\"path\", { d: \"m14.83 14.83 4.24 4.24\", key: \"q42g0n\" }],\n [\"path\", { d: \"m9.17 14.83-4.24 4.24\", key: \"bqpfvv\" }],\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"4\", key: \"4exip2\" }]\n]);\n\nexport { LifeBuoy as default };\n//# sourceMappingURL=life-buoy.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Link = createLucideIcon(\"LinkIcon\", [\n [\"path\", { d: \"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\", key: \"1cjeqo\" }],\n [\"path\", { d: \"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\", key: \"19qd67\" }]\n]);\n\nexport { Link as default };\n//# sourceMappingURL=link.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst ListChecks = createLucideIcon(\"ListChecksIcon\", [\n [\"path\", { d: \"m3 17 2 2 4-4\", key: \"1jhpwq\" }],\n [\"path\", { d: \"m3 7 2 2 4-4\", key: \"1obspn\" }],\n [\"path\", { d: \"M13 6h8\", key: \"15sg57\" }],\n [\"path\", { d: \"M13 12h8\", key: \"h98zly\" }],\n [\"path\", { d: \"M13 18h8\", key: \"oe0vm4\" }]\n]);\n\nexport { ListChecks as default };\n//# sourceMappingURL=list-checks.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst List = createLucideIcon(\"ListIcon\", [\n [\"path\", { d: \"M3 12h.01\", key: \"nlz23k\" }],\n [\"path\", { d: \"M3 18h.01\", key: \"1tta3j\" }],\n [\"path\", { d: \"M3 6h.01\", key: \"1rqtza\" }],\n [\"path\", { d: \"M8 12h13\", key: \"1za7za\" }],\n [\"path\", { d: \"M8 18h13\", key: \"1lx6n3\" }],\n [\"path\", { d: \"M8 6h13\", key: \"ik3vkj\" }]\n]);\n\nexport { List as default };\n//# sourceMappingURL=list.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Lock = createLucideIcon(\"LockIcon\", [\n [\"rect\", { width: \"18\", height: \"11\", x: \"3\", y: \"11\", rx: \"2\", ry: \"2\", key: \"1w4ew1\" }],\n [\"path\", { d: \"M7 11V7a5 5 0 0 1 10 0v4\", key: \"fwvmzm\" }]\n]);\n\nexport { Lock as default };\n//# sourceMappingURL=lock.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst LogOut = createLucideIcon(\"LogOutIcon\", [\n [\"path\", { d: \"M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4\", key: \"1uf3rs\" }],\n [\"polyline\", { points: \"16 17 21 12 16 7\", key: \"1gabdz\" }],\n [\"line\", { x1: \"21\", x2: \"9\", y1: \"12\", y2: \"12\", key: \"1uyos4\" }]\n]);\n\nexport { LogOut as default };\n//# sourceMappingURL=log-out.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Mail = createLucideIcon(\"MailIcon\", [\n [\"rect\", { width: \"20\", height: \"16\", x: \"2\", y: \"4\", rx: \"2\", key: \"18n3k1\" }],\n [\"path\", { d: \"m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7\", key: \"1ocrg3\" }]\n]);\n\nexport { Mail as default };\n//# sourceMappingURL=mail.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst MapPin = createLucideIcon(\"MapPinIcon\", [\n [\n \"path\",\n {\n d: \"M20 10c0 4.993-5.539 10.193-7.399 11.799a1 1 0 0 1-1.202 0C9.539 20.193 4 14.993 4 10a8 8 0 0 1 16 0\",\n key: \"1r0f0z\"\n }\n ],\n [\"circle\", { cx: \"12\", cy: \"10\", r: \"3\", key: \"ilqhr7\" }]\n]);\n\nexport { MapPin as default };\n//# sourceMappingURL=map-pin.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Map = createLucideIcon(\"MapIcon\", [\n [\n \"path\",\n {\n d: \"M14.106 5.553a2 2 0 0 0 1.788 0l3.659-1.83A1 1 0 0 1 21 4.619v12.764a1 1 0 0 1-.553.894l-4.553 2.277a2 2 0 0 1-1.788 0l-4.212-2.106a2 2 0 0 0-1.788 0l-3.659 1.83A1 1 0 0 1 3 19.381V6.618a1 1 0 0 1 .553-.894l4.553-2.277a2 2 0 0 1 1.788 0z\",\n key: \"169xi5\"\n }\n ],\n [\"path\", { d: \"M15 5.764v15\", key: \"1pn4in\" }],\n [\"path\", { d: \"M9 3.236v15\", key: \"1uimfh\" }]\n]);\n\nexport { Map as default };\n//# sourceMappingURL=map.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst MessageSquare = createLucideIcon(\"MessageSquareIcon\", [\n [\"path\", { d: \"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\", key: \"1lielz\" }]\n]);\n\nexport { MessageSquare as default };\n//# sourceMappingURL=message-square.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Monitor = createLucideIcon(\"MonitorIcon\", [\n [\"rect\", { width: \"20\", height: \"14\", x: \"2\", y: \"3\", rx: \"2\", key: \"48i651\" }],\n [\"line\", { x1: \"8\", x2: \"16\", y1: \"21\", y2: \"21\", key: \"1svkeh\" }],\n [\"line\", { x1: \"12\", x2: \"12\", y1: \"17\", y2: \"21\", key: \"vw1qmm\" }]\n]);\n\nexport { Monitor as default };\n//# sourceMappingURL=monitor.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Moon = createLucideIcon(\"MoonIcon\", [\n [\"path\", { d: \"M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z\", key: \"a7tn18\" }]\n]);\n\nexport { Moon as default };\n//# sourceMappingURL=moon.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Package = createLucideIcon(\"PackageIcon\", [\n [\n \"path\",\n {\n d: \"M11 21.73a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73z\",\n key: \"1a0edw\"\n }\n ],\n [\"path\", { d: \"M12 22V12\", key: \"d0xqtd\" }],\n [\"path\", { d: \"m3.3 7 7.703 4.734a2 2 0 0 0 1.994 0L20.7 7\", key: \"yx3hmr\" }],\n [\"path\", { d: \"m7.5 4.27 9 5.15\", key: \"1c824w\" }]\n]);\n\nexport { Package as default };\n//# sourceMappingURL=package.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst PanelLeft = createLucideIcon(\"PanelLeftIcon\", [\n [\"rect\", { width: \"18\", height: \"18\", x: \"3\", y: \"3\", rx: \"2\", key: \"afitv7\" }],\n [\"path\", { d: \"M9 3v18\", key: \"fh3hqa\" }]\n]);\n\nexport { PanelLeft as default };\n//# sourceMappingURL=panel-left.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst PanelsTopLeft = createLucideIcon(\"PanelsTopLeftIcon\", [\n [\"rect\", { width: \"18\", height: \"18\", x: \"3\", y: \"3\", rx: \"2\", key: \"afitv7\" }],\n [\"path\", { d: \"M3 9h18\", key: \"1pudct\" }],\n [\"path\", { d: \"M9 21V9\", key: \"1oto5p\" }]\n]);\n\nexport { PanelsTopLeft as default };\n//# sourceMappingURL=panels-top-left.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Paperclip = createLucideIcon(\"PaperclipIcon\", [\n [\n \"path\",\n {\n d: \"m21.44 11.05-9.19 9.19a6 6 0 0 1-8.49-8.49l8.57-8.57A4 4 0 1 1 18 8.84l-8.59 8.57a2 2 0 0 1-2.83-2.83l8.49-8.48\",\n key: \"1u3ebp\"\n }\n ]\n]);\n\nexport { Paperclip as default };\n//# sourceMappingURL=paperclip.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Pencil = createLucideIcon(\"PencilIcon\", [\n [\n \"path\",\n {\n d: \"M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z\",\n key: \"1a8usu\"\n }\n ],\n [\"path\", { d: \"m15 5 4 4\", key: \"1mk7zo\" }]\n]);\n\nexport { Pencil as default };\n//# sourceMappingURL=pencil.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Plus = createLucideIcon(\"PlusIcon\", [\n [\"path\", { d: \"M5 12h14\", key: \"1ays0h\" }],\n [\"path\", { d: \"M12 5v14\", key: \"s699le\" }]\n]);\n\nexport { Plus as default };\n//# sourceMappingURL=plus.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst RefreshCw = createLucideIcon(\"RefreshCwIcon\", [\n [\"path\", { d: \"M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8\", key: \"v9h5vc\" }],\n [\"path\", { d: \"M21 3v5h-5\", key: \"1q7to0\" }],\n [\"path\", { d: \"M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16\", key: \"3uifl3\" }],\n [\"path\", { d: \"M8 16H3v5\", key: \"1cv678\" }]\n]);\n\nexport { RefreshCw as default };\n//# sourceMappingURL=refresh-cw.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst RotateCcw = createLucideIcon(\"RotateCcwIcon\", [\n [\"path\", { d: \"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8\", key: \"1357e3\" }],\n [\"path\", { d: \"M3 3v5h5\", key: \"1xhq8a\" }]\n]);\n\nexport { RotateCcw as default };\n//# sourceMappingURL=rotate-ccw.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Search = createLucideIcon(\"SearchIcon\", [\n [\"circle\", { cx: \"11\", cy: \"11\", r: \"8\", key: \"4ej97u\" }],\n [\"path\", { d: \"m21 21-4.3-4.3\", key: \"1qie3q\" }]\n]);\n\nexport { Search as default };\n//# sourceMappingURL=search.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Send = createLucideIcon(\"SendIcon\", [\n [\n \"path\",\n {\n d: \"M14.536 21.686a.5.5 0 0 0 .937-.024l6.5-19a.496.496 0 0 0-.635-.635l-19 6.5a.5.5 0 0 0-.024.937l7.93 3.18a2 2 0 0 1 1.112 1.11z\",\n key: \"1ffxy3\"\n }\n ],\n [\"path\", { d: \"m21.854 2.147-10.94 10.939\", key: \"12cjpa\" }]\n]);\n\nexport { Send as default };\n//# sourceMappingURL=send.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Server = createLucideIcon(\"ServerIcon\", [\n [\"rect\", { width: \"20\", height: \"8\", x: \"2\", y: \"2\", rx: \"2\", ry: \"2\", key: \"ngkwjq\" }],\n [\"rect\", { width: \"20\", height: \"8\", x: \"2\", y: \"14\", rx: \"2\", ry: \"2\", key: \"iecqi9\" }],\n [\"line\", { x1: \"6\", x2: \"6.01\", y1: \"6\", y2: \"6\", key: \"16zg32\" }],\n [\"line\", { x1: \"6\", x2: \"6.01\", y1: \"18\", y2: \"18\", key: \"nzw8ys\" }]\n]);\n\nexport { Server as default };\n//# sourceMappingURL=server.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Settings = createLucideIcon(\"SettingsIcon\", [\n [\n \"path\",\n {\n d: \"M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z\",\n key: \"1qme2f\"\n }\n ],\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"3\", key: \"1v7zrd\" }]\n]);\n\nexport { Settings as default };\n//# sourceMappingURL=settings.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Shield = createLucideIcon(\"ShieldIcon\", [\n [\n \"path\",\n {\n d: \"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z\",\n key: \"oel41y\"\n }\n ]\n]);\n\nexport { Shield as default };\n//# sourceMappingURL=shield.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst ShoppingBag = createLucideIcon(\"ShoppingBagIcon\", [\n [\"path\", { d: \"M6 2 3 6v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6l-3-4Z\", key: \"hou9p0\" }],\n [\"path\", { d: \"M3 6h18\", key: \"d0wm0j\" }],\n [\"path\", { d: \"M16 10a4 4 0 0 1-8 0\", key: \"1ltviw\" }]\n]);\n\nexport { ShoppingBag as default };\n//# sourceMappingURL=shopping-bag.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst ShoppingCart = createLucideIcon(\"ShoppingCartIcon\", [\n [\"circle\", { cx: \"8\", cy: \"21\", r: \"1\", key: \"jimo8o\" }],\n [\"circle\", { cx: \"19\", cy: \"21\", r: \"1\", key: \"13723u\" }],\n [\n \"path\",\n {\n d: \"M2.05 2.05h2l2.66 12.42a2 2 0 0 0 2 1.58h9.78a2 2 0 0 0 1.95-1.57l1.65-7.43H5.12\",\n key: \"9zh506\"\n }\n ]\n]);\n\nexport { ShoppingCart as default };\n//# sourceMappingURL=shopping-cart.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst SlidersVertical = createLucideIcon(\"SlidersVerticalIcon\", [\n [\"line\", { x1: \"4\", x2: \"4\", y1: \"21\", y2: \"14\", key: \"1p332r\" }],\n [\"line\", { x1: \"4\", x2: \"4\", y1: \"10\", y2: \"3\", key: \"gb41h5\" }],\n [\"line\", { x1: \"12\", x2: \"12\", y1: \"21\", y2: \"12\", key: \"hf2csr\" }],\n [\"line\", { x1: \"12\", x2: \"12\", y1: \"8\", y2: \"3\", key: \"1kfi7u\" }],\n [\"line\", { x1: \"20\", x2: \"20\", y1: \"21\", y2: \"16\", key: \"1lhrwl\" }],\n [\"line\", { x1: \"20\", x2: \"20\", y1: \"12\", y2: \"3\", key: \"16vvfq\" }],\n [\"line\", { x1: \"2\", x2: \"6\", y1: \"14\", y2: \"14\", key: \"1uebub\" }],\n [\"line\", { x1: \"10\", x2: \"14\", y1: \"8\", y2: \"8\", key: \"1yglbp\" }],\n [\"line\", { x1: \"18\", x2: \"22\", y1: \"16\", y2: \"16\", key: \"1jxqpz\" }]\n]);\n\nexport { SlidersVertical as default };\n//# sourceMappingURL=sliders-vertical.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst SquarePen = createLucideIcon(\"SquarePenIcon\", [\n [\"path\", { d: \"M12 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7\", key: \"1m0v6g\" }],\n [\n \"path\",\n {\n d: \"M18.375 2.625a1 1 0 0 1 3 3l-9.013 9.014a2 2 0 0 1-.853.505l-2.873.84a.5.5 0 0 1-.62-.62l.84-2.873a2 2 0 0 1 .506-.852z\",\n key: \"ohrbg2\"\n }\n ]\n]);\n\nexport { SquarePen as default };\n//# sourceMappingURL=square-pen.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Star = createLucideIcon(\"StarIcon\", [\n [\n \"path\",\n {\n d: \"M11.525 2.295a.53.53 0 0 1 .95 0l2.31 4.679a2.123 2.123 0 0 0 1.595 1.16l5.166.756a.53.53 0 0 1 .294.904l-3.736 3.638a2.123 2.123 0 0 0-.611 1.878l.882 5.14a.53.53 0 0 1-.771.56l-4.618-2.428a2.122 2.122 0 0 0-1.973 0L6.396 21.01a.53.53 0 0 1-.77-.56l.881-5.139a2.122 2.122 0 0 0-.611-1.879L2.16 9.795a.53.53 0 0 1 .294-.906l5.165-.755a2.122 2.122 0 0 0 1.597-1.16z\",\n key: \"r04s7s\"\n }\n ]\n]);\n\nexport { Star as default };\n//# sourceMappingURL=star.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Store = createLucideIcon(\"StoreIcon\", [\n [\"path\", { d: \"m2 7 4.41-4.41A2 2 0 0 1 7.83 2h8.34a2 2 0 0 1 1.42.59L22 7\", key: \"ztvudi\" }],\n [\"path\", { d: \"M4 12v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8\", key: \"1b2hhj\" }],\n [\"path\", { d: \"M15 22v-4a2 2 0 0 0-2-2h-2a2 2 0 0 0-2 2v4\", key: \"2ebpfo\" }],\n [\"path\", { d: \"M2 7h20\", key: \"1fcdvo\" }],\n [\n \"path\",\n {\n d: \"M22 7v3a2 2 0 0 1-2 2a2.7 2.7 0 0 1-1.59-.63.7.7 0 0 0-.82 0A2.7 2.7 0 0 1 16 12a2.7 2.7 0 0 1-1.59-.63.7.7 0 0 0-.82 0A2.7 2.7 0 0 1 12 12a2.7 2.7 0 0 1-1.59-.63.7.7 0 0 0-.82 0A2.7 2.7 0 0 1 8 12a2.7 2.7 0 0 1-1.59-.63.7.7 0 0 0-.82 0A2.7 2.7 0 0 1 4 12a2 2 0 0 1-2-2V7\",\n key: \"6c3vgh\"\n }\n ]\n]);\n\nexport { Store as default };\n//# sourceMappingURL=store.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Sun = createLucideIcon(\"SunIcon\", [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"4\", key: \"4exip2\" }],\n [\"path\", { d: \"M12 2v2\", key: \"tus03m\" }],\n [\"path\", { d: \"M12 20v2\", key: \"1lh1kg\" }],\n [\"path\", { d: \"m4.93 4.93 1.41 1.41\", key: \"149t6j\" }],\n [\"path\", { d: \"m17.66 17.66 1.41 1.41\", key: \"ptbguv\" }],\n [\"path\", { d: \"M2 12h2\", key: \"1t8f8n\" }],\n [\"path\", { d: \"M20 12h2\", key: \"1q8mjw\" }],\n [\"path\", { d: \"m6.34 17.66-1.41 1.41\", key: \"1m8zz5\" }],\n [\"path\", { d: \"m19.07 4.93-1.41 1.41\", key: \"1shlcs\" }]\n]);\n\nexport { Sun as default };\n//# sourceMappingURL=sun.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Tag = createLucideIcon(\"TagIcon\", [\n [\n \"path\",\n {\n d: \"M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z\",\n key: \"vktsd0\"\n }\n ],\n [\"circle\", { cx: \"7.5\", cy: \"7.5\", r: \".5\", fill: \"currentColor\", key: \"kqv944\" }]\n]);\n\nexport { Tag as default };\n//# sourceMappingURL=tag.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Tags = createLucideIcon(\"TagsIcon\", [\n [\"path\", { d: \"m15 5 6.3 6.3a2.4 2.4 0 0 1 0 3.4L17 19\", key: \"1cbfv1\" }],\n [\n \"path\",\n {\n d: \"M9.586 5.586A2 2 0 0 0 8.172 5H3a1 1 0 0 0-1 1v5.172a2 2 0 0 0 .586 1.414L8.29 18.29a2.426 2.426 0 0 0 3.42 0l3.58-3.58a2.426 2.426 0 0 0 0-3.42z\",\n key: \"135mg7\"\n }\n ],\n [\"circle\", { cx: \"6.5\", cy: \"9.5\", r: \".5\", fill: \"currentColor\", key: \"5pm5xn\" }]\n]);\n\nexport { Tags as default };\n//# sourceMappingURL=tags.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Terminal = createLucideIcon(\"TerminalIcon\", [\n [\"polyline\", { points: \"4 17 10 11 4 5\", key: \"akl6gq\" }],\n [\"line\", { x1: \"12\", x2: \"20\", y1: \"19\", y2: \"19\", key: \"q2wloq\" }]\n]);\n\nexport { Terminal as default };\n//# sourceMappingURL=terminal.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Trash2 = createLucideIcon(\"Trash2Icon\", [\n [\"path\", { d: \"M3 6h18\", key: \"d0wm0j\" }],\n [\"path\", { d: \"M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6\", key: \"4alrt4\" }],\n [\"path\", { d: \"M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2\", key: \"v07s0e\" }],\n [\"line\", { x1: \"10\", x2: \"10\", y1: \"11\", y2: \"17\", key: \"1uufr5\" }],\n [\"line\", { x1: \"14\", x2: \"14\", y1: \"11\", y2: \"17\", key: \"xtxkd\" }]\n]);\n\nexport { Trash2 as default };\n//# sourceMappingURL=trash-2.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst TrendingUp = createLucideIcon(\"TrendingUpIcon\", [\n [\"polyline\", { points: \"22 7 13.5 15.5 8.5 10.5 2 17\", key: \"126l90\" }],\n [\"polyline\", { points: \"16 7 22 7 22 13\", key: \"kwv8wd\" }]\n]);\n\nexport { TrendingUp as default };\n//# sourceMappingURL=trending-up.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst TriangleAlert = createLucideIcon(\"TriangleAlertIcon\", [\n [\n \"path\",\n {\n d: \"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3\",\n key: \"wmoenq\"\n }\n ],\n [\"path\", { d: \"M12 9v4\", key: \"juzpu7\" }],\n [\"path\", { d: \"M12 17h.01\", key: \"p32p05\" }]\n]);\n\nexport { TriangleAlert as default };\n//# sourceMappingURL=triangle-alert.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Upload = createLucideIcon(\"UploadIcon\", [\n [\"path\", { d: \"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\", key: \"ih7n3h\" }],\n [\"polyline\", { points: \"17 8 12 3 7 8\", key: \"t8dd8p\" }],\n [\"line\", { x1: \"12\", x2: \"12\", y1: \"3\", y2: \"15\", key: \"widbto\" }]\n]);\n\nexport { Upload as default };\n//# sourceMappingURL=upload.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst UserPlus = createLucideIcon(\"UserPlusIcon\", [\n [\"path\", { d: \"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2\", key: \"1yyitq\" }],\n [\"circle\", { cx: \"9\", cy: \"7\", r: \"4\", key: \"nufk8\" }],\n [\"line\", { x1: \"19\", x2: \"19\", y1: \"8\", y2: \"14\", key: \"1bvyxn\" }],\n [\"line\", { x1: \"22\", x2: \"16\", y1: \"11\", y2: \"11\", key: \"1shjgl\" }]\n]);\n\nexport { UserPlus as default };\n//# sourceMappingURL=user-plus.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst User = createLucideIcon(\"UserIcon\", [\n [\"path\", { d: \"M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2\", key: \"975kel\" }],\n [\"circle\", { cx: \"12\", cy: \"7\", r: \"4\", key: \"17ys0d\" }]\n]);\n\nexport { User as default };\n//# sourceMappingURL=user.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Users = createLucideIcon(\"UsersIcon\", [\n [\"path\", { d: \"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2\", key: \"1yyitq\" }],\n [\"circle\", { cx: \"9\", cy: \"7\", r: \"4\", key: \"nufk8\" }],\n [\"path\", { d: \"M22 21v-2a4 4 0 0 0-3-3.87\", key: \"kshegd\" }],\n [\"path\", { d: \"M16 3.13a4 4 0 0 1 0 7.75\", key: \"1da9ce\" }]\n]);\n\nexport { Users as default };\n//# sourceMappingURL=users.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst X = createLucideIcon(\"XIcon\", [\n [\"path\", { d: \"M18 6 6 18\", key: \"1bl5f8\" }],\n [\"path\", { d: \"m6 6 12 12\", key: \"d8bk6v\" }]\n]);\n\nexport { X as default };\n//# sourceMappingURL=x.js.map\n","/**\n * @license lucide-vue-next v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Zap = createLucideIcon(\"ZapIcon\", [\n [\n \"path\",\n {\n d: \"M4 14a1 1 0 0 1-.78-1.63l9.9-10.2a.5.5 0 0 1 .86.46l-1.92 6.02A1 1 0 0 0 13 10h7a1 1 0 0 1 .78 1.63l-9.9 10.2a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14z\",\n key: \"1xq2db\"\n }\n ]\n]);\n\nexport { Zap as default };\n//# sourceMappingURL=zap.js.map\n","/**\n * Глобальный registry AdminClient'а для Pinia stores.\n *\n * Stores не получают client через параметры — это сильно усложняет API\n * (`useAuthStore(client)` каждый раз). Вместо этого client регистрируется\n * один раз при bootstrap'е приложения через `setAdminClient()`, и stores\n * читают его через `getAdminClient()`.\n *\n * Это singleton-pattern — допустим в случае admin-SPA, потому что\n * client всегда один на весь жизненный цикл.\n */\n\nimport type { AdminClient } from '../api/client'\n\nlet _client: AdminClient | null = null\n\nexport function setAdminClient(client: AdminClient): void {\n _client = client\n}\n\nexport function getAdminClient(): AdminClient {\n if (_client === null) {\n throw new Error(\n '[admin] AdminClient is not registered. Call setAdminClient(...) before using stores.',\n )\n }\n return _client\n}\n\nexport function clearAdminClient(): void {\n _client = null\n}\n\nexport function hasAdminClient(): boolean {\n return _client !== null\n}\n","/**\n * Theme store: текущая тема + список доступных + persist через API.\n *\n * Side effect: применяет `<html data-theme=\"...\">` при изменении.\n * SPA рассчитывает на это для CSS-vars overrides.\n */\n\nimport { defineStore } from 'pinia'\nimport { computed, ref } from 'vue'\nimport { getAdminClient } from './registry'\nimport type { AdminBootstrap } from '../types/bootstrap'\n\nexport const useThemeStore = defineStore('admin-theme', () => {\n const current = ref<string>('light')\n const available = ref<string[]>(['light', 'dark'])\n\n const isDark = computed(() => current.value === 'dark')\n\n function hydrate(bootstrap: AdminBootstrap): void {\n current.value = bootstrap.theme\n available.value = bootstrap.availableThemes\n applyHtmlAttr(bootstrap.theme)\n }\n\n /**\n * Локальное переключение без round-trip'а. Используется когда нужно\n * мгновенно применить тему до получения ответа от сервера.\n */\n function applyLocal(theme: string): void {\n if (!available.value.includes(theme)) {\n throw new Error(`Theme \"${theme}\" is not available`)\n }\n current.value = theme\n applyHtmlAttr(theme)\n }\n\n /**\n * POST /system/setTheme — persist в user.theme + cookie.\n * Применяет тему к DOM немедленно (optimistic update).\n */\n async function setTheme(theme: string): Promise<void> {\n if (!available.value.includes(theme)) {\n throw new Error(`Theme \"${theme}\" is not available`)\n }\n\n const previous = current.value\n applyLocal(theme)\n\n try {\n const client = getAdminClient()\n await client.post('/system/setTheme', { theme })\n } catch (err) {\n // Откатываем optimistic update.\n applyLocal(previous)\n throw err\n }\n }\n\n function applyHtmlAttr(theme: string): void {\n if (typeof document !== 'undefined' && document.documentElement) {\n document.documentElement.setAttribute('data-theme', theme)\n }\n }\n\n return {\n current,\n available,\n isDark,\n hydrate,\n applyLocal,\n setTheme,\n }\n})\n","<script setup lang=\"ts\">\n/**\n * Toggle между light/dark поверх @dskripchenko/ui. Использует topbar\n * icon-button-стиль (.admin-topbar__icon-btn) для визуальной согласованности\n * с остальными widget'ами в баре.\n */\nimport { computed } from 'vue'\nimport { Moon, Sun } from 'lucide-vue-next'\nimport { UidIcon } from '@dskripchenko/ui'\nimport { useThemeStore } from '../../../stores/theme'\n\nconst theme = useThemeStore()\n\nconst isDark = computed(() => theme.current === 'dark')\nconst icon = computed(() => (isDark.value ? Sun : Moon))\nconst iconName = computed(() => (isDark.value ? 'sun' : 'moon'))\nconst ariaLabel = computed(() =>\n isDark.value ? 'Переключить на светлую тему' : 'Переключить на тёмную тему',\n)\n\nasync function toggle(): Promise<void> {\n const next = isDark.value ? 'light' : 'dark'\n await theme.setTheme(next)\n}\n</script>\n\n<template>\n <button\n type=\"button\"\n class=\"admin-topbar__icon-btn\"\n :aria-label=\"ariaLabel\"\n :aria-pressed=\"isDark\"\n @click=\"toggle\"\n >\n <UidIcon :icon=\"icon\" :size=\"18\" :data-icon=\"iconName\" />\n </button>\n</template>\n","/**\n * Locale store: текущая локаль + persist + sync с AdminClient.\n *\n * Side effects при смене:\n * - `<html lang=\"...\">` обновляется\n * - AdminClient.setLocale() — все следующие запросы получат правильный\n * X-Admin-Locale header\n * - POST /system/setLocale → persist в user.locale + cookie\n */\n\nimport { defineStore } from 'pinia'\nimport { ref } from 'vue'\nimport { getAdminClient } from './registry'\nimport type { AdminBootstrap } from '../types/bootstrap'\n\nexport const useLocaleStore = defineStore('admin-locale', () => {\n const current = ref<string>('ru')\n const available = ref<string[]>(['ru', 'en'])\n\n function hydrate(bootstrap: AdminBootstrap): void {\n current.value = bootstrap.locale\n available.value = bootstrap.availableLocales\n applySideEffects(bootstrap.locale)\n }\n\n function applyLocal(locale: string): void {\n if (!available.value.includes(locale)) {\n throw new Error(`Locale \"${locale}\" is not available`)\n }\n current.value = locale\n applySideEffects(locale)\n }\n\n async function setLocale(locale: string): Promise<void> {\n if (!available.value.includes(locale)) {\n throw new Error(`Locale \"${locale}\" is not available`)\n }\n\n const previous = current.value\n applyLocal(locale)\n\n try {\n const client = getAdminClient()\n await client.post('/system/setLocale', { locale })\n } catch (err) {\n applyLocal(previous)\n throw err\n }\n }\n\n function applySideEffects(locale: string): void {\n if (typeof document !== 'undefined' && document.documentElement) {\n document.documentElement.setAttribute('lang', locale)\n }\n // Try-catch потому что в test-окружении registry может быть пуст.\n try {\n getAdminClient().setLocale(locale)\n } catch {\n // ignore — клиент ещё не зарегистрирован\n }\n }\n\n return {\n current,\n available,\n hydrate,\n applyLocal,\n setLocale,\n }\n})\n","<script setup lang=\"ts\">\n/**\n * Переключение локали через UidMenu. В topbar показываем компактно\n * (icon + uppercase-код), под ним выпадает список доступных локалей.\n */\nimport { Globe } from 'lucide-vue-next'\nimport { UidIcon, UidMenu, UidMenuItem } from '@dskripchenko/ui'\nimport { useLocaleStore } from '../../../stores/locale'\n\nconst locale = useLocaleStore()\n\nasync function pick(loc: string): Promise<void> {\n if (loc === locale.current) return\n await locale.setLocale(loc)\n}\n</script>\n\n<template>\n <UidMenu>\n <template #trigger>\n <button\n type=\"button\"\n class=\"admin-topbar__icon-btn\"\n style=\"width: auto; padding: 0 8px; gap: 4px; font-size: 12px;\"\n aria-label=\"Сменить локаль\"\n >\n <UidIcon :icon=\"Globe\" :size=\"14\" data-icon=\"globe\" />\n <span>{{ (locale.current ?? '').toUpperCase() }}</span>\n </button>\n </template>\n\n <UidMenuItem\n v-for=\"loc in locale.available\"\n :key=\"loc\"\n @click=\"pick(loc)\"\n >\n {{ loc.toUpperCase() }}\n </UidMenuItem>\n </UidMenu>\n</template>\n","/**\n * Notifications store: список + unread count + read/delete actions.\n *\n * Bell-badge polling реализуется на уровне UI через setInterval +\n * вызов loadUnread() — store сам не polling'ит, чтобы не дублировать\n * SetInterval'ы между tab'ами.\n */\n\nimport { defineStore } from 'pinia'\nimport { computed, ref } from 'vue'\nimport { getAdminClient } from './registry'\nimport type { AdminBootstrap } from '../types/bootstrap'\n\nexport interface NotificationItem {\n id: string\n type: string\n data: Record<string, unknown>\n read_at: string | null\n created_at: string | null\n}\n\nexport type NotificationFilter = 'all' | 'unread' | 'read'\n\nexport const useNotificationsStore = defineStore('admin-notifications', () => {\n const items = ref<NotificationItem[]>([])\n const unreadCount = ref(0)\n const loading = ref(false)\n const lastFilter = ref<NotificationFilter>('all')\n const meta = ref<{ page: number; per_page: number; total: number; last_page: number } | null>(null)\n /**\n * Slide-in drawer state. Bell-кнопка в топбаре toggle'ит этот флаг,\n * NotificationsDrawer (mounted в AdminApp root) реагирует на него.\n */\n const isOpen = ref<boolean>(false)\n\n const hasUnread = computed(() => unreadCount.value > 0)\n\n function openDrawer(): void {\n isOpen.value = true\n }\n function closeDrawer(): void {\n isOpen.value = false\n }\n function toggleDrawer(): void {\n isOpen.value = !isOpen.value\n }\n\n function hydrate(bootstrap: AdminBootstrap): void {\n unreadCount.value = bootstrap.unread_notifications_count\n }\n\n async function load(filter: NotificationFilter = 'all', page = 1): Promise<void> {\n loading.value = true\n try {\n const client = getAdminClient()\n const result = await client.get<{\n data: NotificationItem[]\n meta: { page: number; per_page: number; total: number; last_page: number; unread_count: number }\n }>(`/notifications/list?type=${filter}&page=${page}`)\n items.value = result.data\n unreadCount.value = result.meta.unread_count\n meta.value = {\n page: result.meta.page,\n per_page: result.meta.per_page,\n total: result.meta.total,\n last_page: result.meta.last_page,\n }\n lastFilter.value = filter\n } finally {\n loading.value = false\n }\n }\n\n /**\n * Лёгкий polling-endpoint — только count + последние 20.\n * Для bell-badge.\n */\n async function loadUnread(): Promise<void> {\n const client = getAdminClient()\n const result = await client.get<{ count: number; data: NotificationItem[] }>(\n '/notifications/unread',\n )\n unreadCount.value = result.count\n // Не подменяем items если в данный момент open'нут другой filter.\n if (lastFilter.value === 'unread') {\n items.value = result.data\n }\n }\n\n async function markAsRead(id: string): Promise<void> {\n const client = getAdminClient()\n await client.post('/notifications/markAsRead', { id })\n // Optimistic update в локальном state.\n const item = items.value.find((n) => n.id === id)\n if (item && item.read_at === null) {\n item.read_at = new Date().toISOString()\n unreadCount.value = Math.max(0, unreadCount.value - 1)\n }\n }\n\n async function markAllAsRead(): Promise<void> {\n const client = getAdminClient()\n await client.post('/notifications/markAllAsRead')\n const now = new Date().toISOString()\n for (const item of items.value) {\n if (item.read_at === null) item.read_at = now\n }\n unreadCount.value = 0\n }\n\n async function destroy(id: string): Promise<void> {\n const client = getAdminClient()\n await client.post('/notifications/destroy', { id })\n const index = items.value.findIndex((n) => n.id === id)\n if (index !== -1) {\n const wasUnread = items.value[index].read_at === null\n items.value.splice(index, 1)\n if (wasUnread) {\n unreadCount.value = Math.max(0, unreadCount.value - 1)\n }\n }\n }\n\n return {\n items,\n unreadCount,\n loading,\n meta,\n lastFilter,\n isOpen,\n hasUnread,\n hydrate,\n load,\n loadUnread,\n markAsRead,\n markAllAsRead,\n destroy,\n openDrawer,\n closeDrawer,\n toggleDrawer,\n }\n})\n","<script setup lang=\"ts\">\n/**\n * Bell с unread-badge — toggle'ит slide-in drawer NotificationsDrawer.\n * Сам drawer mounted один раз в AdminApp.vue (Teleport to body).\n */\nimport { computed } from 'vue'\nimport { Bell } from 'lucide-vue-next'\nimport { UidIcon } from '@dskripchenko/ui'\nimport { useNotificationsStore } from '../../../stores/notifications'\n\nconst notifications = useNotificationsStore()\n\nconst display = computed(() => {\n const n = notifications.unreadCount\n if (n <= 0) return null\n return n > 99 ? '99+' : String(n)\n})\n\nfunction onClick(): void {\n notifications.toggleDrawer()\n}\n</script>\n\n<template>\n <button\n type=\"button\"\n class=\"admin-topbar__icon-btn\"\n aria-label=\"Уведомления\"\n aria-haspopup=\"dialog\"\n :aria-expanded=\"notifications.isOpen\"\n @click=\"onClick\"\n >\n <UidIcon :icon=\"Bell\" :size=\"18\" data-icon=\"bell\" />\n <span\n v-if=\"display !== null\"\n class=\"admin-topbar__bell-badge\"\n :title=\"`Непрочитанных: ${notifications.unreadCount}`\"\n >\n {{ display }}\n </span>\n </button>\n</template>\n","/**\n * Кастомные Error-классы для admin API.\n *\n * Все API-ошибки бросаются как ApiError или его подклассы. Потребители\n * могут делать `instanceof ValidationError` для специфичной обработки.\n */\n\nimport type { ErrorEnvelope } from './envelope'\n\nexport class ApiError extends Error {\n public readonly status: number\n public readonly errorKey: string\n public readonly payload: ErrorEnvelope['payload']\n\n constructor(status: number, payload: ErrorEnvelope['payload']) {\n super(payload.message ?? `API error ${status}`)\n this.name = 'ApiError'\n this.status = status\n this.errorKey = payload.errorKey ?? 'unknown'\n this.payload = payload\n }\n}\n\nexport class UnauthenticatedError extends ApiError {\n constructor(payload: ErrorEnvelope['payload']) {\n super(401, payload)\n this.name = 'UnauthenticatedError'\n }\n}\n\nexport class ForbiddenError extends ApiError {\n constructor(payload: ErrorEnvelope['payload']) {\n super(403, payload)\n this.name = 'ForbiddenError'\n }\n}\n\nexport class NotFoundError extends ApiError {\n constructor(payload: ErrorEnvelope['payload']) {\n super(404, payload)\n this.name = 'NotFoundError'\n }\n}\n\nexport class ValidationError extends ApiError {\n /** Field-keyed map of error messages. */\n public readonly fields: Record<string, string[]>\n\n constructor(payload: ErrorEnvelope['payload']) {\n super(422, payload)\n this.name = 'ValidationError'\n this.fields = payload.messages ?? {}\n }\n\n /** Первое сообщение из field'а — удобно для toast. */\n firstFieldMessage(): string | null {\n for (const messages of Object.values(this.fields)) {\n if (messages.length > 0) {\n return messages[0]\n }\n }\n return null\n }\n}\n\n/**\n * Network-failure (не дошли до сервера). Отдельный класс чтобы UI мог\n * показать «Нет соединения» вместо «500 Server Error».\n */\nexport class NetworkError extends Error {\n constructor(message = 'Network error') {\n super(message)\n this.name = 'NetworkError'\n }\n}\n\n/**\n * Превращает HTTP-status + envelope в правильный подкласс ApiError.\n */\nexport function toApiError(status: number, payload: ErrorEnvelope['payload']): ApiError {\n switch (status) {\n case 401: return new UnauthenticatedError(payload)\n case 403: return new ForbiddenError(payload)\n case 404: return new NotFoundError(payload)\n case 422: return new ValidationError(payload)\n default: return new ApiError(status, payload)\n }\n}\n","/**\n * Auth store: текущий user, permissions, login/logout/2FA flow.\n *\n * Wildcard в permissions:\n * - `*` — полный доступ ко всему.\n * - `admin.users.*` — доступ ко всем admin.users.{view,create,update,delete}.\n *\n * 2FA flow:\n * 1. login() с верными creds + 2FA включена → success: false +\n * errorKey: 'two_factor_required' + challenge_token. State переходит в\n * `pendingChallenge`.\n * 2. UI показывает 2FA-форму. twoFactorChallenge(code) или\n * twoFactorRecovery(recovery_code) → success login flow.\n */\n\nimport { defineStore } from 'pinia'\nimport { computed, ref } from 'vue'\nimport { getAdminClient } from './registry'\nimport { ApiError } from '../api/errors'\nimport type { AdminUser, AdminBootstrap } from '../types/bootstrap'\n\nexport interface PendingChallenge {\n challengeToken: string\n remember: boolean\n}\n\nexport interface LoginPayload {\n email: string\n password: string\n remember?: boolean\n}\n\nexport const useAuthStore = defineStore('admin-auth', () => {\n const user = ref<AdminUser | null>(null)\n const permissions = ref<string[]>([])\n const pendingChallenge = ref<PendingChallenge | null>(null)\n\n const isAuthenticated = computed(() => user.value !== null)\n const isChallengePending = computed(() => pendingChallenge.value !== null)\n\n /** Заполнить store из bootstrap-payload'а (стартовая инициализация). */\n function hydrate(bootstrap: AdminBootstrap): void {\n user.value = bootstrap.user\n permissions.value = bootstrap.permissions\n }\n\n /**\n * Проверить permission. Поддерживает wildcards:\n * - `*` — даёт доступ всем.\n * - `admin.users.*` — даёт доступ ко всем admin.users.X.\n */\n function hasPermission(key: string): boolean {\n if (permissions.value.includes('*')) return true\n if (permissions.value.includes(key)) return true\n return permissions.value.some((permission) => {\n if (!permission.endsWith('.*')) return false\n const prefix = permission.slice(0, -1) // 'admin.users.'\n return key.startsWith(prefix)\n })\n }\n\n function hasAnyPermission(keys: string[]): boolean {\n return keys.some(hasPermission)\n }\n\n function hasAllPermissions(keys: string[]): boolean {\n return keys.every(hasPermission)\n }\n\n /**\n * POST /auth/login. При 2FA-required envelope success:false +\n * errorKey:'two_factor_required' конвертируется interceptor'ом в ApiError;\n * мы ловим его, переходим в challenge-mode и возвращаем 'two_factor_required'.\n * На полный success — заполняем user и возвращаем 'authenticated'.\n * На реальную ошибку — throw'ит ApiError выше.\n */\n async function login(payload: LoginPayload): Promise<'authenticated' | 'two_factor_required'> {\n const client = getAdminClient()\n try {\n const result = await client.post<{ user?: AdminUser; permissions?: string[] }>(\n '/auth/login',\n payload,\n )\n if (result?.user) {\n user.value = result.user\n }\n if (Array.isArray(result?.permissions)) {\n permissions.value = result.permissions\n }\n pendingChallenge.value = null\n return 'authenticated'\n } catch (err) {\n if (err instanceof ApiError && err.errorKey === 'two_factor_required') {\n const challengeToken = (err.payload as Record<string, unknown>).challenge_token\n pendingChallenge.value = {\n challengeToken: typeof challengeToken === 'string' ? challengeToken : '',\n remember: payload.remember ?? false,\n }\n return 'two_factor_required'\n }\n throw err\n }\n }\n\n /** POST /auth/twoFactorChallenge. Завершает login. */\n async function twoFactorChallenge(code: string): Promise<void> {\n if (pendingChallenge.value === null) {\n throw new Error('No pending 2FA challenge')\n }\n const client = getAdminClient()\n const result = await client.post<{ user: AdminUser }>('/auth/twoFactorChallenge', {\n challenge_token: pendingChallenge.value.challengeToken,\n code,\n })\n user.value = result.user\n pendingChallenge.value = null\n }\n\n /** POST /auth/twoFactorRecovery. Использует recovery-код вместо TOTP. */\n async function twoFactorRecovery(recoveryCode: string): Promise<{ remaining: number }> {\n if (pendingChallenge.value === null) {\n throw new Error('No pending 2FA challenge')\n }\n const client = getAdminClient()\n const result = await client.post<{\n user: AdminUser\n recovery_codes_remaining: number\n }>('/auth/twoFactorRecovery', {\n challenge_token: pendingChallenge.value.challengeToken,\n recovery_code: recoveryCode,\n })\n user.value = result.user\n pendingChallenge.value = null\n return { remaining: result.recovery_codes_remaining }\n }\n\n /** Сбросить pending challenge — для возврата на login-форму. */\n function cancelChallenge(): void {\n pendingChallenge.value = null\n }\n\n /** POST /auth/logout. Чистит store. */\n async function logout(): Promise<void> {\n const client = getAdminClient()\n try {\n await client.post('/auth/logout')\n } finally {\n user.value = null\n permissions.value = []\n pendingChallenge.value = null\n }\n }\n\n return {\n // state\n user,\n permissions,\n pendingChallenge,\n // getters\n isAuthenticated,\n isChallengePending,\n // actions\n hydrate,\n hasPermission,\n hasAnyPermission,\n hasAllPermissions,\n login,\n twoFactorChallenge,\n twoFactorRecovery,\n cancelChallenge,\n logout,\n }\n})\n","<script setup lang=\"ts\">\n/**\n * UserMenu с avatar + dropdown через UidMenu из @dskripchenko/ui.\n * В trigger'е — UidAvatar (с инициалами либо src, размер sm).\n */\nimport { UidAvatar, UidMenu, UidMenuItem, UidMenuSeparator } from '@dskripchenko/ui'\nimport { useRouter } from 'vue-router'\nimport { useAuthStore } from '../../../stores/auth'\n\nconst auth = useAuthStore()\nconst router = useRouter()\n\nasync function logout(): Promise<void> {\n try {\n await auth.logout()\n } finally {\n await router.push({ name: 'admin.login' })\n }\n}\n\nfunction goProfile(): void {\n void router.push({ name: 'admin.profile' })\n}\n</script>\n\n<template>\n <UidMenu>\n <template #trigger>\n <button\n type=\"button\"\n class=\"admin-topbar__icon-btn admin-user-menu__trigger\"\n aria-label=\"Меню пользователя\"\n aria-haspopup=\"menu\"\n style=\"width: auto; padding: 0 4px; gap: 8px;\"\n >\n <UidAvatar\n :src=\"auth.user?.avatar ?? undefined\"\n :name=\"auth.user?.name ?? '?'\"\n :alt=\"auth.user?.name ?? 'User'\"\n size=\"sm\"\n />\n </button>\n </template>\n\n <UidMenuItem @click=\"goProfile\">Профиль</UidMenuItem>\n <UidMenuSeparator />\n <UidMenuItem variant=\"danger\" @click=\"logout\">Выйти</UidMenuItem>\n </UidMenu>\n</template>\n","<script setup lang=\"ts\">\n/**\n * Admin top bar поверх UID-токенов. Структура из docs/design_handoff_laravel_admin/\n * screens-shell.jsx (Topbar): collapse-toggle / breadcrumbs / spacer /\n * search-pill / bell / theme / locale / avatar.\n *\n * Slots:\n * - actions — host может вставить дополнительные actions перед widget'ами\n * - search — кастомизация ⌘K command-palette pill (по умолчанию — статичный\n * placeholder; host сверху поднимет UidCommand или свой)\n * - breadcrumbs — переопределить хлебные крошки\n */\nimport { computed } from 'vue'\nimport { PanelLeft, Search } from 'lucide-vue-next'\nimport { UidIcon } from '@dskripchenko/ui'\nimport ThemeToggle from './widgets/ThemeToggle.vue'\nimport LocaleSwitcher from './widgets/LocaleSwitcher.vue'\nimport NotificationBell from './widgets/NotificationBell.vue'\nimport UserMenu from './widgets/UserMenu.vue'\n\ninterface Crumb {\n label: string\n to?: string | Record<string, unknown> | null\n}\n\ninterface Props {\n /** Хлебные крошки. Последний элемент — текущая страница (без to). */\n breadcrumbs?: Crumb[]\n /** Показывать кнопку collapse сайдбара (только в shell-layout'е). */\n showCollapseToggle?: boolean\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n breadcrumbs: () => [],\n showCollapseToggle: true,\n})\n\nconst emit = defineEmits<{\n 'toggle-sidebar': []\n}>()\n\nconst lastIdx = computed(() => props.breadcrumbs.length - 1)\n</script>\n\n<template>\n <header class=\"admin-topbar\">\n <button\n v-if=\"showCollapseToggle\"\n type=\"button\"\n class=\"admin-topbar__icon-btn\"\n aria-label=\"Свернуть меню\"\n @click=\"emit('toggle-sidebar')\"\n >\n <UidIcon :icon=\"PanelLeft\" :size=\"18\" data-icon=\"panel-left\" />\n </button>\n\n <div class=\"admin-topbar__breadcrumbs\">\n <slot name=\"breadcrumbs\">\n <template v-for=\"(crumb, idx) in breadcrumbs\" :key=\"idx\">\n <span v-if=\"idx > 0\" class=\"sep\">›</span>\n <component\n :is=\"crumb.to ? 'a' : 'span'\"\n :href=\"typeof crumb.to === 'string' ? crumb.to : undefined\"\n :class=\"idx === lastIdx ? 'cur' : ''\"\n >\n {{ crumb.label }}\n </component>\n </template>\n </slot>\n </div>\n\n <div class=\"admin-topbar__spacer\" />\n\n <slot name=\"search\">\n <div class=\"admin-topbar__search\" role=\"button\" tabindex=\"0\">\n <UidIcon :icon=\"Search\" :size=\"14\" data-icon=\"search\" />\n <span>Поиск везде…</span>\n <kbd>⌘K</kbd>\n </div>\n </slot>\n\n <slot name=\"actions\" />\n <NotificationBell />\n <ThemeToggle />\n <LocaleSwitcher />\n <UserMenu />\n </header>\n</template>\n","/**\n * Menu store: дерево пунктов сайдбара.\n *\n * Источник — /system/menu (backend строит из ResourceRegistry/ScreenRegistry/\n * Settings + plugin-вкладов). Фронт фильтрует по permission'ам залогиненного\n * пользователя через auth-store.\n */\n\nimport { defineStore } from 'pinia'\nimport { computed, ref } from 'vue'\nimport { getAdminClient } from './registry'\nimport { useAuthStore } from './auth'\n\nexport interface MenuItem {\n /** Уникальный идентификатор. */\n key: string\n /** Текст пункта. */\n label: string\n /** Имя icon'а (опционально — host-проект сам резолвит icon-set). */\n icon?: string | null\n /** URL (внутренний router-target) либо null для группы. */\n url?: string | null\n /** Имя router-route (если задано — приоритет над url). */\n routeName?: string | null\n /** Бейдж справа (число unread, ярлык вроде \"new\"). */\n badge?: string | number | null\n /** Группа (header в sidebar). */\n group?: string | null\n /** Сортировочный вес. */\n order?: number\n /** Permission-keys; если заданы — пункт виден только при hasAnyPermission. */\n permissions?: string[]\n /** Вложенные пункты. */\n children?: MenuItem[]\n}\n\nexport interface MenuGroup {\n /** Заголовок группы (null = пункты без группы). */\n group: string | null\n items: MenuItem[]\n}\n\ninterface MenuResponse {\n items: MenuItem[]\n}\n\nexport const useMenuStore = defineStore('admin-menu', () => {\n const items = ref<MenuItem[]>([])\n const loading = ref(false)\n const error = ref<Error | null>(null)\n const isLoaded = ref(false)\n\n /**\n * Видимые пункты — отфильтрованные по permission'ам через auth-store.\n * Поддерживает wildcards (`*`, `admin.users.*`) через auth.hasAnyPermission.\n * Items без permissions считаются открытыми всем.\n */\n const visibleItems = computed<MenuItem[]>(() => {\n const auth = useAuthStore()\n const filter = (it: MenuItem): MenuItem | null => {\n if (Array.isArray(it.permissions) && it.permissions.length > 0) {\n if (!auth.hasAnyPermission(it.permissions)) return null\n }\n const filteredChildren = (it.children ?? [])\n .map(filter)\n .filter((c): c is MenuItem => c !== null)\n return { ...it, children: filteredChildren }\n }\n return items.value.map(filter).filter((i): i is MenuItem => i !== null)\n })\n\n /**\n * Группированный список — для рендера в sidebar по секциям.\n * Сортировка: order по возрастанию, затем label по алфавиту.\n */\n const groupedItems = computed<MenuGroup[]>(() => {\n const groups = new Map<string | null, MenuItem[]>()\n for (const item of visibleItems.value) {\n const groupKey = item.group ?? null\n if (!groups.has(groupKey)) groups.set(groupKey, [])\n groups.get(groupKey)!.push(item)\n }\n const result: MenuGroup[] = []\n for (const [group, list] of groups) {\n list.sort((a, b) => {\n const orderDiff = (a.order ?? 0) - (b.order ?? 0)\n if (orderDiff !== 0) return orderDiff\n return a.label.localeCompare(b.label)\n })\n result.push({ group, items: list })\n }\n return result\n })\n\n /** Загрузить меню с backend'а. Кэшируется до reset()/force=true. */\n async function load(force = false): Promise<MenuItem[]> {\n if (isLoaded.value && !force) return items.value\n loading.value = true\n error.value = null\n try {\n const client = getAdminClient()\n const response = await client.get<MenuResponse>('/system/menu')\n items.value = Array.isArray(response.items) ? response.items : []\n isLoaded.value = true\n return items.value\n } catch (err) {\n error.value = err instanceof Error ? err : new Error(String(err))\n throw err\n } finally {\n loading.value = false\n }\n }\n\n /** Установить items напрямую (например, host-проект построил из manifest'а). */\n function setItems(next: MenuItem[]): void {\n items.value = next\n isLoaded.value = true\n error.value = null\n }\n\n function reset(): void {\n items.value = []\n isLoaded.value = false\n error.value = null\n loading.value = false\n }\n\n return {\n items,\n loading,\n error,\n isLoaded,\n visibleItems,\n groupedItems,\n load,\n setItems,\n reset,\n }\n})\n","<script setup lang=\"ts\">\n/**\n * LAdmin brand mark — \"Terminal Block\".\n * Vue-порт docs/design_handoff_laravel_admin/brand/Logo.tsx.\n *\n * Палитра — zinc-900 фон + teal-400 \">_\" с мигающим курсором.\n * Все внутренние размеры скейлятся от prop `size`, так что mark\n * остаётся чётким при любом px (28 для sidebar, 40 на login и т.д.).\n *\n * При prefers-reduced-motion курсор не анимируется (см. CSS ниже).\n */\nimport { computed } from 'vue'\n\ninterface Props {\n /** Сторона квадрата в px. */\n size?: number\n /** Мигающий курсор. */\n animated?: boolean\n /** color = бренд-палитра, mono = single-tone через currentColor. */\n variant?: 'color' | 'mono'\n title?: string\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n size: 28,\n animated: true,\n variant: 'color',\n title: 'LAdmin',\n})\n\nconst TEAL = '#2dd4bf'\nconst INK = '#18181b'\n\nconst radius = computed(() => Math.round(props.size * 0.25))\nconst fontSize = computed(() => Math.round(props.size * 0.42))\nconst padX = computed(() => Math.round(props.size * 0.18))\nconst cursorW = computed(() => Math.max(2, Math.round(props.size * 0.18)))\nconst cursorH = computed(() => Math.round(props.size * 0.3))\nconst cursorGap = computed(() => Math.max(1, Math.round(props.size * 0.04)))\n\nconst bg = computed(() => (props.variant === 'mono' ? 'currentColor' : INK))\nconst fg = computed(() =>\n props.variant === 'mono' ? 'var(--ladmin-logo-fg, #fff)' : TEAL,\n)\n\nconst wrapStyle = computed(() => ({\n width: `${props.size}px`,\n height: `${props.size}px`,\n padding: `0 ${padX.value}px`,\n borderRadius: `${radius.value}px`,\n background: bg.value,\n color: fg.value,\n fontSize: `${fontSize.value}px`,\n}))\n\nconst cursorStyle = computed(() => ({\n width: `${cursorW.value}px`,\n height: `${cursorH.value}px`,\n marginLeft: `${cursorGap.value}px`,\n background: fg.value,\n}))\n</script>\n\n<template>\n <span\n role=\"img\"\n :aria-label=\"title\"\n class=\"ladmin-logo\"\n :class=\"{ 'ladmin-logo--animated': animated }\"\n :style=\"wrapStyle\"\n >\n <span aria-hidden=\"true\">&gt;_</span>\n <span aria-hidden=\"true\" class=\"ladmin-logo__cursor\" :style=\"cursorStyle\" />\n </span>\n</template>\n\n<style>\n.ladmin-logo {\n display: inline-flex;\n align-items: center;\n justify-content: flex-start;\n font-family: ui-monospace, 'IBM Plex Mono', 'Fira Code', Menlo, monospace;\n font-weight: 700;\n letter-spacing: -0.02em;\n line-height: 1;\n flex: none;\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06);\n}\n.ladmin-logo--animated .ladmin-logo__cursor {\n animation: ladmin-cursor 1.1s steps(1, end) infinite;\n}\n@keyframes ladmin-cursor {\n 50% { opacity: 0; }\n}\n@media (prefers-reduced-motion: reduce) {\n .ladmin-logo--animated .ladmin-logo__cursor { animation: none; }\n}\n</style>\n","/**\n * Резолвер kebab-имени lucide-иконки → Vue-компонент.\n *\n * MenuItem.icon приходит из backend'а строкой (например 'file-text', 'users').\n * Чтобы не тащить весь lucide-vue-next в bundle — держим whitelist\n * популярных имён. Host может расширить через registerIcon(name, comp).\n *\n * Не найденное имя возвращает fallback (Box) — sidebar item никогда не\n * рендерится без иконки.\n */\nimport type { Component } from 'vue'\nimport {\n Activity,\n AlertCircle,\n Archive,\n BarChart3,\n Bell,\n Bookmark,\n Box,\n Briefcase,\n Calendar,\n CheckCircle,\n Clock,\n Code,\n Cog,\n Command,\n Database,\n Download,\n FileText,\n FileClock,\n Files,\n Flag,\n FolderOpen,\n Folder,\n Gauge,\n Globe,\n Grid,\n HardDrive,\n Hash,\n Heart,\n HelpCircle,\n History,\n Home,\n Image,\n Images,\n Inbox,\n Info,\n Key,\n Layers,\n LayoutDashboard,\n Layout,\n LifeBuoy,\n LineChart,\n Link,\n List,\n ListChecks,\n Lock,\n LogOut,\n Mail,\n MapPin,\n Map,\n MessageSquare,\n Monitor,\n Package,\n Paperclip,\n PieChart,\n RefreshCw,\n Search,\n Send,\n Server,\n Settings,\n Shield,\n ShoppingBag,\n ShoppingCart,\n Sliders,\n Star,\n Store,\n Tag,\n Tags,\n Terminal,\n TrendingUp,\n Upload,\n User,\n UserCircle,\n Users,\n XCircle,\n Zap,\n} from 'lucide-vue-next'\n\nconst REGISTRY: Record<string, Component> = {\n 'activity': Activity,\n 'alert-circle': AlertCircle,\n 'archive': Archive,\n 'bar-chart': BarChart3,\n 'bar-chart-3': BarChart3,\n 'bell': Bell,\n 'bookmark': Bookmark,\n 'box': Box,\n 'briefcase': Briefcase,\n 'calendar': Calendar,\n 'check-circle': CheckCircle,\n 'clock': Clock,\n 'code': Code,\n 'cog': Cog,\n 'command': Command,\n 'database': Database,\n 'download': Download,\n 'file': FileText,\n 'file-text': FileText,\n 'file-clock': FileClock,\n 'files': Files,\n 'flag': Flag,\n 'folder': Folder,\n 'folder-open': FolderOpen,\n 'gauge': Gauge,\n 'globe': Globe,\n 'grid': Grid,\n 'hard-drive': HardDrive,\n 'hash': Hash,\n 'health-check': CheckCircle,\n 'heart': Heart,\n 'help-circle': HelpCircle,\n 'history': History,\n 'home': Home,\n 'image': Image,\n 'images': Images,\n 'inbox': Inbox,\n 'info': Info,\n 'key': Key,\n 'layers': Layers,\n 'layout': Layout,\n 'layout-dashboard': LayoutDashboard,\n 'life-buoy': LifeBuoy,\n 'line-chart': LineChart,\n 'link': Link,\n 'list': List,\n 'list-checks': ListChecks,\n 'lock': Lock,\n 'log-out': LogOut,\n 'mail': Mail,\n 'map': Map,\n 'map-pin': MapPin,\n 'media': Image,\n 'message-square': MessageSquare,\n 'monitor': Monitor,\n 'notifications': Bell,\n 'package': Package,\n 'paperclip': Paperclip,\n 'pie-chart': PieChart,\n 'refresh-cw': RefreshCw,\n 'reports': BarChart3,\n 'roles': Shield,\n 'search': Search,\n 'send': Send,\n 'server': Server,\n 'settings': Settings,\n 'shield': Shield,\n 'shopping-bag': ShoppingBag,\n 'shopping-cart': ShoppingCart,\n 'sliders': Sliders,\n 'star': Star,\n 'store': Store,\n 'tag': Tag,\n 'tags': Tags,\n 'terminal': Terminal,\n 'trending-up': TrendingUp,\n 'upload': Upload,\n 'user': User,\n 'user-circle': UserCircle,\n 'users': Users,\n 'x-circle': XCircle,\n 'zap': Zap,\n}\n\n/**\n * Найти иконку по имени. Не найдена — null (вызывающий код решает рендерить\n * fallback или ничего).\n */\nexport function resolveIcon(name: string | null | undefined): Component | null {\n if (!name) return null\n return REGISTRY[name] ?? null\n}\n\n/** Зарегистрировать дополнительную иконку (host-проект). */\nexport function registerIcon(name: string, component: Component): void {\n REGISTRY[name] = component\n}\n","<script setup lang=\"ts\">\n/**\n * Sidebar admin-каркаса поверх UidSidebar/UidSidebarGroup/UidSidebarItem.\n *\n * Источник данных — useMenuStore (groupedItems, отфильтрованные по permission'ам\n * через auth.hasAnyPermission). UidSidebarItem поддерживает вложенный icon-slot\n * + active + badge — маппим прямо из MenuItem.\n *\n * Brand-row сверху + опциональный tenant-block + footer с версией/docs —\n * по эталону docs/design_handoff_laravel_admin/screens-shell.jsx (Sidebar).\n */\nimport { computed, h, type Component } from 'vue'\nimport { useRoute } from 'vue-router'\nimport { Box } from 'lucide-vue-next'\nimport { UidIcon, UidSidebar, UidSidebarGroup, UidSidebarItem } from '@dskripchenko/ui'\nimport { useMenuStore, type MenuItem } from '../../stores/menu'\nimport BrandLogo from './BrandLogo.vue'\nimport { resolveIcon } from './iconRegistry'\n\ninterface Props {\n collapsed?: boolean\n /** Заголовок бренда. */\n brandName?: string\n /**\n * Custom mark (если задан — рендерится вместо BrandLogo). Полезно\n * host-проекту с собственным логотипом.\n */\n brandMark?: string | null\n /** Named-route для click'а по brand-row. */\n homeRouteName?: string\n /** Тенант / workspace — опционально показывается под брендом. */\n tenant?: { label: string; name: string } | null\n /** Версия + ссылка на docs в footer'е. */\n version?: string | null\n docsUrl?: string | null\n}\n\nwithDefaults(defineProps<Props>(), {\n collapsed: false,\n brandName: 'Laravel Admin',\n brandMark: null,\n homeRouteName: 'admin.home',\n tenant: null,\n version: null,\n docsUrl: null,\n})\n\nconst menu = useMenuStore()\nconst route = useRoute()\n\nconst groups = computed(() => menu.groupedItems)\n\nfunction isActive(item: MenuItem): boolean {\n if (item.routeName && route.name === item.routeName) return true\n if (item.url && route.path === item.url) return true\n return false\n}\n\n/**\n * UidSidebarItem ожидает icon-slot. MenuItem.icon — строка (имя lucide-иконки\n * в kebab-case). Резолвим через iconRegistry; если имя не зарегистрировано —\n * fallback на Box, чтобы каждый item всегда имел иконку (иначе collapsed\n * mode превращается в бесполезные пустые квадраты).\n *\n * Host-проект может расширить registry через registerIcon(name, comp).\n */\nfunction iconSlot(name?: string | null): Component {\n const resolved = resolveIcon(name) ?? Box\n return () => h(UidIcon, { icon: resolved, size: 16 })\n}\n\n/** UidSidebarItem.to принимает string | object; routeName маппим через route-object. */\nfunction itemTarget(item: MenuItem): string | Record<string, unknown> | undefined {\n // URL приоритетнее routeName — vue-router бросает \"no match for {name}\" если\n // route'а ещё нет (dynamic-routes добавляются async после manifest.load).\n // URL-based navigation матчится в любой момент через path.\n if (item.url) return item.url\n if (item.routeName) return { name: item.routeName }\n return undefined\n}\n</script>\n\n<template>\n <UidSidebar :collapsed=\"collapsed\">\n <template #header>\n <router-link\n :to=\"{ name: homeRouteName }\"\n class=\"admin-sidebar-brand\"\n :title=\"collapsed ? brandName : undefined\"\n :aria-label=\"brandName\"\n >\n <div v-if=\"brandMark\" class=\"admin-sidebar-brand__mark\">{{ brandMark }}</div>\n <BrandLogo v-else :size=\"28\" />\n <div v-if=\"!collapsed\" class=\"admin-sidebar-brand__name\">{{ brandName }}</div>\n </router-link>\n <div v-if=\"tenant && !collapsed\" class=\"admin-sidebar-tenant\">\n <span>{{ tenant.label }}</span>\n <b>{{ tenant.name }}</b>\n </div>\n </template>\n\n <template #nav>\n <UidSidebarGroup\n v-for=\"(grp, idx) in groups\"\n :key=\"`grp-${idx}`\"\n :title=\"grp.group ?? undefined\"\n >\n <UidSidebarItem\n v-for=\"item in grp.items\"\n :key=\"item.key\"\n :to=\"itemTarget(item)\"\n :active=\"isActive(item)\"\n :badge=\"item.badge ?? undefined\"\n :title=\"collapsed ? item.label : undefined\"\n >\n <template #icon>\n <component :is=\"iconSlot(item.icon)\" />\n </template>\n {{ item.label }}\n </UidSidebarItem>\n </UidSidebarGroup>\n </template>\n\n <template #footer>\n <div class=\"admin-sidebar-foot\">\n <span class=\"admin-sidebar-foot__text\" :title=\"version ?? 'Laravel Admin'\">\n <template v-if=\"!collapsed\">{{ version ?? 'Laravel Admin' }}</template>\n <template v-else>·</template>\n </span>\n <a\n v-if=\"docsUrl && !collapsed\"\n :href=\"docsUrl\"\n class=\"admin-sidebar-foot__text admin-sidebar-foot__link\"\n >\n Docs\n </a>\n </div>\n </template>\n </UidSidebar>\n</template>\n\n<style>\n/*\n * Sidebar header выровнен по AdminTopBar (height: 56px + 1px border).\n * Padding у uid-pattern-sidebar__header обнулён — brand занимает ровно\n * одну строку шапки. Border-bottom UI-kit'а оставляем — он совпадает\n * по Y с border-bottom топбара, образуя единую горизонталь над nav\n * и контентной частью.\n */\n.uid-pattern-sidebar__header:has(.admin-sidebar-brand) {\n padding: 0;\n}\n.admin-sidebar-brand {\n display: flex;\n align-items: center;\n gap: 10px;\n height: 56px;\n padding: 0 16px;\n text-decoration: none;\n color: inherit;\n transition: background var(--uid-duration-fast, 120ms) var(--uid-ease-out, ease);\n}\n.admin-sidebar-brand:hover {\n background: var(--uid-color-surface-hover, rgba(0, 0, 0, 0.04));\n}\n.admin-sidebar-brand:focus-visible {\n outline: 2px solid var(--uid-color-focus-ring, var(--uid-accent));\n outline-offset: -2px;\n}\n.admin-sidebar-brand__mark {\n width: 28px;\n height: 28px;\n border-radius: 7px;\n flex: none;\n background: var(--uid-text-primary);\n color: var(--uid-surface-raised);\n display: grid;\n place-items: center;\n font-family: var(--uid-font-family-display);\n font-weight: var(--uid-font-weight-bold);\n font-size: 14px;\n letter-spacing: -0.02em;\n}\n.admin-sidebar-brand__name {\n font-family: var(--uid-font-family-display);\n font-size: 14px;\n font-weight: var(--uid-font-weight-semibold);\n letter-spacing: -0.01em;\n white-space: nowrap;\n overflow: hidden;\n color: var(--uid-text-primary);\n}\n.admin-sidebar-tenant {\n margin: 8px;\n display: flex;\n align-items: center;\n gap: 8px;\n height: 32px;\n padding: 0 8px;\n border: 1px solid var(--uid-border-subtle);\n border-radius: var(--uid-radius-md);\n font-size: var(--uid-font-size-xs);\n color: var(--uid-text-secondary);\n background: var(--uid-surface-base);\n}\n.admin-sidebar-tenant b { color: var(--uid-text-primary); font-weight: 500; }\n.admin-sidebar-foot {\n /*\n * Высота строго через --admin-foot-height — совпадает с .admin-main-footer\n * (см. AdminShell.vue), чтобы border-top sidebar foot и border-top main\n * footer проходили по одной Y и давали единую горизонталь под экраном.\n */\n height: var(--admin-foot-height, 32px);\n padding: 0 16px;\n border-top: 1px solid var(--uid-border-subtle);\n display: flex;\n align-items: center;\n justify-content: space-between;\n font-size: 11px;\n color: var(--uid-text-tertiary);\n}\n.admin-sidebar-foot__link { cursor: pointer; }\n.admin-sidebar-foot__link:hover { color: var(--uid-text-primary); }\n\n.admin-sidebar__icon {\n width: 16px;\n height: 16px;\n display: inline-block;\n flex: none;\n color: currentColor;\n}\n</style>\n","<script setup lang=\"ts\">\n/**\n * Корневой layout admin-панели поверх UidSidebarLayout из @dskripchenko/ui.\n *\n * Slots:\n * - sidebar — обычно AdminSidebar (default)\n * - header — AdminTopBar (default)\n * - default — main-area (host рендерит <RouterView/>)\n *\n * v-model — boolean флаг сворачивания сайдбара (240→56 px, transition в uid).\n *\n * Impersonation: prop `impersonation` показывает 32-px amber бейдж над shell'ом\n * с кнопкой выхода — стиль из docs/design_handoff_laravel_admin/app.css:159\n * (.imp-banner). На <html> ставим data-impersonating='true' чтобы корректно\n * сместить sticky-элементы вниз.\n */\nimport { computed, onBeforeUnmount, ref, watch } from 'vue'\nimport { UidSidebarLayout } from '@dskripchenko/ui'\nimport AdminTopBar from './AdminTopBar.vue'\nimport AdminSidebar from './AdminSidebar.vue'\n\ninterface ImpersonationData {\n /** Имя того, в кого вошли. */\n asName: string\n}\n\ninterface Props {\n /**\n * v-model:collapsed — состояние сворачивания. Опционально: если host\n * не передаёт, AdminShell использует internal ref'ом, чтобы collapse\n * toggle работал out-of-the-box.\n */\n collapsed?: boolean\n /** Если задано — показывает amber-banner и сдвигает контент. */\n impersonation?: ImpersonationData | null\n}\nconst props = withDefaults(defineProps<Props>(), {\n collapsed: undefined,\n impersonation: null,\n})\n\nconst emit = defineEmits<{\n 'update:collapsed': [value: boolean]\n 'exit-impersonation': []\n}>()\n\n// Internal fallback state — используется когда host не передал v-model.\nconst internalCollapsed = ref<boolean>(false)\nconst isExternallyControlled = computed<boolean>(() => props.collapsed !== undefined)\nconst collapsed = computed<boolean>(\n () => (isExternallyControlled.value ? (props.collapsed as boolean) : internalCollapsed.value),\n)\n\nfunction onCollapseChange(value: boolean): void {\n if (!isExternallyControlled.value) internalCollapsed.value = value\n emit('update:collapsed', value)\n}\n\nfunction exitImpersonation(): void {\n emit('exit-impersonation')\n}\n\n// Маркер на <html> — для shell-classes которые делают paddding-top + sticky-offset.\nconst HTML_ATTR = 'data-admin-impersonating'\n\nwatch(\n () => props.impersonation,\n (val) => {\n if (typeof document === 'undefined') return\n if (val !== null) document.documentElement.setAttribute(HTML_ATTR, 'true')\n else document.documentElement.removeAttribute(HTML_ATTR)\n },\n { immediate: true },\n)\n\nonBeforeUnmount(() => {\n if (typeof document !== 'undefined') {\n document.documentElement.removeAttribute(HTML_ATTR)\n }\n})\n</script>\n\n<template>\n <div class=\"admin-shell-root\">\n <div v-if=\"impersonation\" class=\"admin-impersonation-banner\" role=\"status\">\n <span>\n Вы вошли как <b>{{ impersonation.asName }}</b> · режим имперсонации\n </span>\n <button\n type=\"button\"\n class=\"admin-impersonation-banner__exit\"\n @click=\"exitImpersonation\"\n >\n Выйти из режима\n </button>\n </div>\n <UidSidebarLayout\n :model-value=\"collapsed\"\n class=\"admin-shell\"\n @update:model-value=\"onCollapseChange\"\n >\n <template #sidebar>\n <slot name=\"sidebar\">\n <AdminSidebar :collapsed=\"collapsed\" />\n </slot>\n </template>\n <template #header>\n <slot name=\"topbar\">\n <AdminTopBar @toggle-sidebar=\"onCollapseChange(!collapsed)\" />\n </slot>\n </template>\n <slot />\n <template #footer>\n <slot name=\"footer\">\n <!--\n Default footer-bar: горизонталь снизу контентной части, совпадает\n по Y с footer'ом sidebar'а — общая высота через --admin-foot-height.\n Host может переопределить полностью через slot=footer.\n -->\n <div class=\"admin-main-footer\" />\n </slot>\n </template>\n </UidSidebarLayout>\n </div>\n</template>\n\n<style>\n.admin-shell-root[data-admin-impersonating='true'] {\n /* Sidebar/topbar sticky уже учтут `--admin-page-pad` и offset через CSS-классы. */\n padding-top: 32px;\n}\n:root[data-admin-impersonating='true'] {\n scroll-padding-top: 32px;\n}\n\n/*\n * Full-viewport layout: sidebar и main каждый имеют own scroll контейнер.\n * Window сам не прокручивается (overflow:hidden на корне), вся прокрутка\n * локализована внутри:\n * - sidebar __nav (свой scroll в списке пунктов когда их больше высоты)\n * - main-content (правая контентная часть)\n *\n * Топбар внутри main всегда виден (flex none / position:sticky top:0).\n *\n * Все правила скоупированы в `.admin-shell` чтобы не задеть UidSidebarLayout\n * в других контекстах (storybook UI-kit'а, тесты).\n */\n.admin-shell.uid-layout-sidebar {\n height: 100vh;\n min-height: 0;\n max-height: 100vh;\n overflow: hidden;\n}\n.admin-shell .uid-layout-sidebar__sidebar {\n height: 100vh;\n}\n.admin-shell .uid-pattern-sidebar {\n height: 100%;\n display: flex;\n flex-direction: column;\n}\n.admin-shell .uid-pattern-sidebar__nav {\n flex: 1 1 0;\n min-height: 0;\n overflow-y: auto;\n overscroll-behavior: contain;\n}\n.admin-shell .uid-pattern-sidebar__footer {\n flex: none;\n}\n.admin-shell .uid-layout-sidebar__main {\n height: 100vh;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n min-width: 0;\n}\n.admin-shell .uid-layout-sidebar__main-header {\n flex: none;\n}\n.admin-shell .uid-layout-sidebar__main-content {\n flex: 1 1 0;\n min-height: 0;\n overflow-y: auto;\n overscroll-behavior: contain;\n}\n\n/* impersonation banner добавляет 32px над shell — корректируем высоту. */\n.admin-shell-root[data-admin-impersonating='true'] .admin-shell.uid-layout-sidebar,\n.admin-shell-root[data-admin-impersonating='true'] .admin-shell .uid-layout-sidebar__sidebar,\n.admin-shell-root[data-admin-impersonating='true'] .admin-shell .uid-layout-sidebar__main {\n height: calc(100vh - 32px);\n max-height: calc(100vh - 32px);\n}\n\n/*\n * Main-footer — пустая горизонтальная полоса под content-area. Высоту\n * держит --admin-foot-height (см. styles/admin.css), такую же как у\n * sidebar footer'а — тогда обе нижние линии (border-top main + border-top\n * sidebar) проходят по одной Y, образуя единую горизонталь через весь экран.\n */\n.admin-main-footer {\n height: var(--admin-foot-height, 32px);\n border-top: 1px solid var(--uid-border-subtle);\n background: var(--uid-surface-base);\n flex: none;\n}\n</style>\n","/**\n * useNavigationStore — глобальный pending-counter для top-loading-bar.\n *\n * При router.beforeEach (старт навигации) — вызываем `start()`.\n * При router.afterEach + resource-page завершила data-fetch — вызываем `end()`.\n *\n * Counter (а не bool) защищает от race condition'ов: если несколько\n * параллельных fetch'ей, bar остаётся видимым пока хоть один pending.\n */\n\nimport { defineStore } from 'pinia'\nimport { computed, ref } from 'vue'\n\nexport const useNavigationStore = defineStore('admin-navigation', () => {\n const pending = ref<number>(0)\n const isLoading = computed<boolean>(() => pending.value > 0)\n\n function start(): void {\n pending.value += 1\n }\n\n function end(): void {\n if (pending.value > 0) pending.value -= 1\n }\n\n /** Сбросить counter (на случай зависшего pending в dev). */\n function reset(): void {\n pending.value = 0\n }\n\n return { pending, isLoading, start, end, reset }\n})\n","<script setup lang=\"ts\">\n/**\n * Top loading bar (как у YouTube/GitHub/Vercel).\n *\n * Реактивно отображает useNavigationStore.isLoading. Indeterminate-anim\n * (CSS keyframes) — slide bar слева направо в бесконечном цикле пока\n * pending > 0.\n *\n * Hide-delay 120ms: если pending быстро спадает к 0, bar успевает\n * мигнуть в полный размер вместо instant-cutoff.\n */\nimport { computed, ref, watch } from 'vue'\nimport { useNavigationStore } from '../stores/navigation'\n\nconst nav = useNavigationStore()\n\n// Soft-hide: bar остаётся 120ms после end() для плавности.\nconst visible = ref<boolean>(false)\nlet hideTimer: ReturnType<typeof setTimeout> | null = null\n\nwatch(\n () => nav.isLoading,\n (loading) => {\n if (loading) {\n if (hideTimer !== null) {\n clearTimeout(hideTimer)\n hideTimer = null\n }\n visible.value = true\n } else {\n hideTimer = setTimeout(() => {\n visible.value = false\n hideTimer = null\n }, 120)\n }\n },\n { immediate: true },\n)\n\nconst cls = computed(() => ({\n 'admin-loading-bar': true,\n 'admin-loading-bar--visible': visible.value,\n}))\n</script>\n\n<template>\n <div :class=\"cls\" role=\"progressbar\" aria-busy=\"true\" />\n</template>\n\n<style>\n.admin-loading-bar {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n height: 2px;\n z-index: var(--uid-z-toast, 9999);\n pointer-events: none;\n opacity: 0;\n transition: opacity 120ms ease-out;\n background: transparent;\n}\n\n.admin-loading-bar--visible {\n opacity: 1;\n}\n\n.admin-loading-bar--visible::before {\n content: '';\n position: absolute;\n inset: 0;\n background: var(--uid-accent, var(--uid-color-primary, #14b8a6));\n transform-origin: 0 50%;\n animation: admin-loading-bar-slide 1.4s cubic-bezier(0.4, 0, 0.2, 1) infinite;\n}\n\n@keyframes admin-loading-bar-slide {\n 0% {\n transform: translateX(-100%) scaleX(0.4);\n }\n 50% {\n transform: translateX(0%) scaleX(0.7);\n }\n 100% {\n transform: translateX(100%) scaleX(0.4);\n }\n}\n\n/* Reduced-motion: статичный bar 60% width. */\n@media (prefers-reduced-motion: reduce) {\n .admin-loading-bar--visible::before {\n animation: none;\n width: 60%;\n transform: none;\n }\n}\n</style>\n","<script setup lang=\"ts\">\n/**\n * NotificationsDrawer — slide-in справа панель с уведомлениями.\n *\n * Структура по docs/design_handoff_laravel_admin (Notifications):\n * Header — title + unread badge + \"Прочитать все\" + close\n * Tabs — Все (count) | Непрочитанные (count) | Прочитанные\n * List — items с иконкой, title, time, description, unread-dot\n * Backdrop — закрывает по клику\n *\n * Открывается через notificationsStore.toggleDrawer() из NotificationBell\n * в топбаре. Drawer mounted один раз в AdminApp.vue, стейт открытости —\n * в pinia store (см. stores/notifications.ts).\n */\nimport { computed, onUnmounted, watch } from 'vue'\nimport {\n AlertTriangle,\n Check,\n CheckCircle,\n MessageSquare,\n Trash2,\n UserPlus,\n X,\n type LucideIcon,\n} from 'lucide-vue-next'\nimport { UidIcon } from '@dskripchenko/ui'\nimport {\n useNotificationsStore,\n type NotificationFilter,\n type NotificationItem,\n} from '../../stores/notifications'\n\nconst notifications = useNotificationsStore()\n\nconst isOpen = computed<boolean>(() => notifications.isOpen)\n\nconst tabs: Array<{ key: NotificationFilter; label: string }> = [\n { key: 'all', label: 'Все' },\n { key: 'unread', label: 'Непрочитанные' },\n { key: 'read', label: 'Прочитанные' },\n]\n\nasync function selectTab(key: NotificationFilter): Promise<void> {\n if (notifications.lastFilter === key) return\n await notifications.load(key, 1).catch(() => undefined)\n}\n\nasync function onMarkAll(): Promise<void> {\n await notifications.markAllAsRead().catch(() => undefined)\n}\n\nasync function onItemClick(item: NotificationItem): Promise<void> {\n if (item.read_at === null) {\n await notifications.markAsRead(item.id).catch(() => undefined)\n }\n // Если у уведомления есть ссылка в data — открываем; иначе остаёмся.\n const url = item.data.url\n if (typeof url === 'string' && url.length > 0) {\n if (url.startsWith('http://') || url.startsWith('https://')) {\n window.open(url, '_blank', 'noopener')\n } else {\n // SPA-навигация — закроем drawer и оставим решение router'у через href.\n notifications.closeDrawer()\n window.location.href = url\n }\n }\n}\n\nasync function onDelete(item: NotificationItem, e: MouseEvent): Promise<void> {\n e.stopPropagation()\n await notifications.destroy(item.id).catch(() => undefined)\n}\n\nfunction close(): void {\n notifications.closeDrawer()\n}\n\n/**\n * Иконка по типу уведомления. Backend laravel-notifications использует FQCN\n * в `type` ('App\\\\Notifications\\\\ImportFinished' и т.п.) — пробуем находить\n * по подстроке. Default — bell.\n */\nfunction iconFor(item: NotificationItem): LucideIcon {\n const t = item.type.toLowerCase()\n if (t.includes('import') || t.includes('finished') || t.includes('success')) return CheckCircle\n if (t.includes('comment') || t.includes('message') || t.includes('mention')) return MessageSquare\n if (t.includes('user') || t.includes('member') || t.includes('role')) return UserPlus\n if (t.includes('warning') || t.includes('schedule')) return AlertTriangle\n if (t.includes('delete') || t.includes('failed') || t.includes('error')) return Trash2\n return CheckCircle\n}\n\nfunction variantFor(item: NotificationItem): 'success' | 'info' | 'warning' | 'danger' | 'neutral' {\n const t = item.type.toLowerCase()\n if (t.includes('import') || t.includes('success') || t.includes('finished')) return 'success'\n if (t.includes('warning') || t.includes('schedule')) return 'warning'\n if (t.includes('delete') || t.includes('failed') || t.includes('error')) return 'danger'\n if (t.includes('comment') || t.includes('message')) return 'info'\n return 'neutral'\n}\n\nfunction relativeTime(iso: string | null): string {\n if (!iso) return ''\n const ts = new Date(iso).getTime()\n if (Number.isNaN(ts)) return ''\n const diff = (Date.now() - ts) / 1000\n if (diff < 60) return `${Math.max(1, Math.floor(diff))} сек назад`\n if (diff < 3600) return `${Math.floor(diff / 60)} мин назад`\n if (diff < 86_400) return `${Math.floor(diff / 3600)} ч назад`\n if (diff < 86_400 * 2) return 'вчера'\n if (diff < 86_400 * 7) return `${Math.floor(diff / 86_400)} д назад`\n return new Date(iso).toLocaleDateString('ru-RU')\n}\n\ninterface ItemView {\n title: string\n description: string\n}\nfunction viewOf(item: NotificationItem): ItemView {\n // Backend кладёт payload в `data`; поддерживаем стандартные ключи\n // `title`/`message`/`description` + fallback на data.text.\n const d = item.data\n const title =\n typeof d.title === 'string' ? d.title : typeof d.subject === 'string' ? d.subject : 'Уведомление'\n const description =\n typeof d.description === 'string'\n ? d.description\n : typeof d.message === 'string'\n ? d.message\n : typeof d.text === 'string'\n ? d.text\n : ''\n return { title, description }\n}\n\nconst tabCounts = computed<Record<NotificationFilter, number>>(() => {\n const meta = notifications.meta\n const total = meta?.total ?? notifications.items.length\n const unread = notifications.unreadCount\n const read = Math.max(0, total - unread)\n return { all: total, unread, read }\n})\n\n// Загружаем при первом открытии. И каждый раз — чтобы свежие данные.\nwatch(isOpen, async (open) => {\n if (open) {\n await notifications.load(notifications.lastFilter, 1).catch(() => undefined)\n document.addEventListener('keydown', onKey)\n } else {\n document.removeEventListener('keydown', onKey)\n }\n})\n\nfunction onKey(e: KeyboardEvent): void {\n if (e.key === 'Escape') close()\n}\n\nonUnmounted(() => {\n document.removeEventListener('keydown', onKey)\n})\n</script>\n\n<template>\n <Teleport to=\"body\">\n <Transition name=\"admin-notif-drawer\">\n <div\n v-if=\"isOpen\"\n class=\"admin-notif-drawer\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"admin-notif-drawer-title\"\n >\n <div class=\"admin-notif-drawer__backdrop\" @click=\"close\" />\n <aside class=\"admin-notif-drawer__panel\">\n <header class=\"admin-notif-drawer__hd\">\n <h2 id=\"admin-notif-drawer-title\" class=\"admin-notif-drawer__title\">\n Уведомления\n <span\n v-if=\"notifications.unreadCount > 0\"\n class=\"admin-notif-drawer__unread-badge\"\n >{{ notifications.unreadCount }}</span>\n </h2>\n <div class=\"admin-notif-drawer__hd-actions\">\n <button\n v-if=\"notifications.unreadCount > 0\"\n type=\"button\"\n class=\"admin-notif-drawer__mark-all\"\n @click=\"onMarkAll\"\n >\n <UidIcon :icon=\"Check\" :size=\"14\" />\n Прочитать все\n </button>\n <button\n type=\"button\"\n class=\"admin-notif-drawer__close\"\n aria-label=\"Закрыть\"\n @click=\"close\"\n >\n <UidIcon :icon=\"X\" :size=\"16\" />\n </button>\n </div>\n </header>\n\n <nav class=\"admin-notif-drawer__tabs\" role=\"tablist\">\n <button\n v-for=\"tab in tabs\"\n :key=\"tab.key\"\n type=\"button\"\n role=\"tab\"\n :class=\"[\n 'admin-notif-drawer__tab',\n {\n 'admin-notif-drawer__tab--active': notifications.lastFilter === tab.key,\n },\n ]\"\n :aria-selected=\"notifications.lastFilter === tab.key\"\n @click=\"selectTab(tab.key)\"\n >\n {{ tab.label }}\n <span class=\"admin-notif-drawer__tab-count\">{{ tabCounts[tab.key] }}</span>\n </button>\n </nav>\n\n <div class=\"admin-notif-drawer__body\">\n <div\n v-if=\"notifications.loading && notifications.items.length === 0\"\n class=\"admin-notif-drawer__empty\"\n >\n Загрузка…\n </div>\n <div\n v-else-if=\"notifications.items.length === 0\"\n class=\"admin-notif-drawer__empty\"\n >\n Нет уведомлений\n </div>\n <ol v-else class=\"admin-notif-drawer__list\">\n <li\n v-for=\"item in notifications.items\"\n :key=\"item.id\"\n :class=\"[\n 'admin-notif-drawer__item',\n { 'admin-notif-drawer__item--unread': item.read_at === null },\n ]\"\n @click=\"onItemClick(item)\"\n >\n <span\n class=\"admin-notif-drawer__icon\"\n :data-variant=\"variantFor(item)\"\n aria-hidden=\"true\"\n >\n <UidIcon :icon=\"iconFor(item)\" :size=\"14\" />\n </span>\n <div class=\"admin-notif-drawer__content\">\n <div class=\"admin-notif-drawer__row\">\n <span class=\"admin-notif-drawer__item-title\">{{ viewOf(item).title }}</span>\n <span class=\"admin-notif-drawer__item-time\">\n {{ relativeTime(item.created_at) }}\n </span>\n </div>\n <div\n v-if=\"viewOf(item).description\"\n class=\"admin-notif-drawer__item-description\"\n >\n {{ viewOf(item).description }}\n </div>\n </div>\n <span\n v-if=\"item.read_at === null\"\n class=\"admin-notif-drawer__unread-dot\"\n aria-hidden=\"true\"\n />\n <button\n type=\"button\"\n class=\"admin-notif-drawer__item-delete\"\n aria-label=\"Удалить\"\n @click.stop=\"onDelete(item, $event)\"\n >\n <UidIcon :icon=\"X\" :size=\"12\" />\n </button>\n </li>\n </ol>\n </div>\n </aside>\n </div>\n </Transition>\n </Teleport>\n</template>\n\n<style>\n.admin-notif-drawer {\n position: fixed;\n inset: 0;\n z-index: var(--uid-z-drawer, 400);\n pointer-events: none;\n}\n.admin-notif-drawer__backdrop {\n position: absolute;\n inset: 0;\n /*\n * Полупрозрачный затеняющий слой над основным интерфейсом. Не используем\n * --uid-color-overlay — в @dskripchenko/ui это opaque surface для popover'ов\n * (white в light / dark-grey в dark), и backdrop становится непрозрачным,\n * закрывая контент полностью. Берём жёсткий rgba(0,0,0,0.4) — стандартный\n * dim для модальных слоёв.\n */\n background: rgba(0, 0, 0, 0.4);\n pointer-events: auto;\n}\n.admin-notif-drawer__panel {\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n width: min(480px, 100%);\n display: flex;\n flex-direction: column;\n background: var(--uid-surface-raised);\n border-left: 1px solid var(--uid-border-subtle);\n box-shadow: var(--uid-shadow-lg);\n pointer-events: auto;\n}\n\n/* Header */\n.admin-notif-drawer__hd {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--uid-space-sm);\n padding: var(--uid-space-md);\n border-bottom: 1px solid var(--uid-border-subtle);\n}\n.admin-notif-drawer__title {\n display: inline-flex;\n align-items: center;\n gap: var(--uid-space-xs);\n margin: 0;\n font-family: var(--uid-font-family-display);\n font-size: 16px;\n font-weight: var(--uid-font-weight-semibold);\n color: var(--uid-text-primary);\n}\n.admin-notif-drawer__unread-badge {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 20px;\n padding: 2px 6px;\n border-radius: 10px;\n background: color-mix(in srgb, var(--uid-color-danger, #dc2626) 14%, transparent);\n color: var(--uid-color-danger, #dc2626);\n font-size: 11px;\n font-weight: var(--uid-font-weight-semibold);\n line-height: 1;\n}\n.admin-notif-drawer__hd-actions {\n display: inline-flex;\n align-items: center;\n gap: var(--uid-space-xs);\n}\n.admin-notif-drawer__mark-all {\n display: inline-flex;\n align-items: center;\n gap: var(--uid-space-2xs);\n padding: 6px 10px;\n border: 0;\n background: transparent;\n border-radius: var(--uid-radius-sm);\n color: var(--uid-text-secondary);\n font-size: 13px;\n cursor: pointer;\n}\n.admin-notif-drawer__mark-all:hover {\n background: var(--uid-color-surface-hover, var(--uid-border-subtle));\n color: var(--uid-text-primary);\n}\n.admin-notif-drawer__close {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n border: 0;\n background: transparent;\n border-radius: var(--uid-radius-sm);\n color: var(--uid-text-secondary);\n cursor: pointer;\n}\n.admin-notif-drawer__close:hover {\n background: var(--uid-color-surface-hover, var(--uid-border-subtle));\n color: var(--uid-text-primary);\n}\n\n/* Tabs */\n.admin-notif-drawer__tabs {\n display: flex;\n align-items: center;\n gap: var(--uid-space-md);\n padding: 0 var(--uid-space-md);\n border-bottom: 1px solid var(--uid-border-subtle);\n}\n.admin-notif-drawer__tab {\n display: inline-flex;\n align-items: center;\n gap: var(--uid-space-2xs);\n padding: 12px 0;\n border: 0;\n border-bottom: 2px solid transparent;\n background: transparent;\n color: var(--uid-text-secondary);\n font-size: 13px;\n font-weight: var(--uid-font-weight-medium);\n cursor: pointer;\n}\n.admin-notif-drawer__tab:hover { color: var(--uid-text-primary); }\n.admin-notif-drawer__tab--active {\n color: var(--uid-text-primary);\n border-bottom-color: var(--uid-accent);\n}\n.admin-notif-drawer__tab-count {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 18px;\n padding: 1px 6px;\n border-radius: 9px;\n background: var(--uid-border-subtle);\n color: var(--uid-text-tertiary);\n font-size: 11px;\n font-weight: var(--uid-font-weight-semibold);\n}\n.admin-notif-drawer__tab--active .admin-notif-drawer__tab-count {\n background: color-mix(in srgb, var(--uid-color-danger, #dc2626) 14%, transparent);\n color: var(--uid-color-danger, #dc2626);\n}\n\n/* Body / list */\n.admin-notif-drawer__body {\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n}\n.admin-notif-drawer__empty {\n padding: var(--uid-space-xl);\n text-align: center;\n color: var(--uid-text-tertiary);\n font-size: 13px;\n}\n.admin-notif-drawer__list {\n list-style: none;\n margin: 0;\n padding: 0;\n}\n.admin-notif-drawer__item {\n position: relative;\n display: flex;\n align-items: flex-start;\n gap: var(--uid-space-sm);\n padding: var(--uid-space-md);\n border-bottom: 1px solid var(--uid-border-subtle);\n cursor: pointer;\n transition: background var(--uid-duration-fast, 120ms) var(--uid-ease-out, ease);\n}\n.admin-notif-drawer__item:hover {\n background: var(--uid-color-surface-hover, var(--uid-border-subtle));\n}\n.admin-notif-drawer__item--unread {\n background: color-mix(in srgb, var(--uid-accent) 5%, transparent);\n}\n.admin-notif-drawer__icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex: none;\n width: 32px;\n height: 32px;\n border-radius: 50%;\n}\n.admin-notif-drawer__icon[data-variant='success'] {\n background: color-mix(in srgb, var(--uid-color-success, #10b981) 14%, transparent);\n color: var(--uid-color-success, #10b981);\n}\n.admin-notif-drawer__icon[data-variant='warning'] {\n background: color-mix(in srgb, var(--uid-color-warning, #f59e0b) 14%, transparent);\n color: var(--uid-color-warning, #f59e0b);\n}\n.admin-notif-drawer__icon[data-variant='danger'] {\n background: color-mix(in srgb, var(--uid-color-danger, #dc2626) 14%, transparent);\n color: var(--uid-color-danger, #dc2626);\n}\n.admin-notif-drawer__icon[data-variant='info'] {\n background: color-mix(in srgb, var(--uid-accent) 14%, transparent);\n color: var(--uid-accent);\n}\n.admin-notif-drawer__icon[data-variant='neutral'] {\n background: var(--uid-border-subtle);\n color: var(--uid-text-secondary);\n}\n\n.admin-notif-drawer__content {\n flex: 1;\n min-width: 0;\n}\n.admin-notif-drawer__row {\n display: flex;\n justify-content: space-between;\n align-items: baseline;\n gap: var(--uid-space-sm);\n}\n.admin-notif-drawer__item-title {\n font-size: 13px;\n font-weight: var(--uid-font-weight-semibold);\n color: var(--uid-text-primary);\n}\n.admin-notif-drawer__item-time {\n font-size: 11px;\n color: var(--uid-text-tertiary);\n flex: none;\n}\n.admin-notif-drawer__item-description {\n margin-top: 2px;\n font-size: 13px;\n color: var(--uid-text-secondary);\n line-height: 1.45;\n display: -webkit-box;\n -webkit-line-clamp: 3;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n.admin-notif-drawer__unread-dot {\n position: absolute;\n top: 16px;\n right: 36px;\n width: 8px;\n height: 8px;\n border-radius: 50%;\n background: var(--uid-color-success, #10b981);\n}\n.admin-notif-drawer__item-delete {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 22px;\n border: 0;\n background: transparent;\n border-radius: 50%;\n color: var(--uid-text-tertiary);\n cursor: pointer;\n opacity: 0;\n flex: none;\n align-self: flex-start;\n margin-top: -2px;\n}\n.admin-notif-drawer__item:hover .admin-notif-drawer__item-delete { opacity: 1; }\n.admin-notif-drawer__item-delete:hover {\n background: color-mix(in srgb, var(--uid-color-danger, #dc2626) 14%, transparent);\n color: var(--uid-color-danger, #dc2626);\n}\n\n/* Slide transition */\n.admin-notif-drawer-enter-active,\n.admin-notif-drawer-leave-active {\n transition: opacity 200ms ease-out;\n}\n.admin-notif-drawer-enter-active .admin-notif-drawer__panel,\n.admin-notif-drawer-leave-active .admin-notif-drawer__panel {\n transition: transform 240ms cubic-bezier(0.2, 0.8, 0.2, 1);\n}\n.admin-notif-drawer-enter-from,\n.admin-notif-drawer-leave-to {\n opacity: 0;\n}\n.admin-notif-drawer-enter-from .admin-notif-drawer__panel,\n.admin-notif-drawer-leave-to .admin-notif-drawer__panel {\n transform: translateX(100%);\n}\n</style>\n","/**\n * Manifest store: lazy-load JSON-манифеста админки + кеширование по version.\n *\n * Manifest содержит описание всех Resource'ов, Screen'ов, Settings'ов,\n * Plugin'ов. SPA загружает один раз на старте и переиспользует.\n *\n * ETag-based 304 Not Modified backend-side — фронт ничего особенного не\n * делает (axios + browser handle If-None-Match). Свежий version записывается\n * в lastVersion для cheap-сравнения.\n */\n\nimport { defineStore } from 'pinia'\nimport { computed, ref } from 'vue'\nimport { getAdminClient } from './registry'\n\n/**\n * Узел manifest'а с обязательным `type`. Совместим с LayoutNode/FieldNode/\n * InfolistNode — позволяет передавать массив прямо в renderer без cast'а.\n */\nexport interface ManifestNode extends Record<string, unknown> {\n type: string\n}\n\nexport interface ManifestResourceMeta {\n slug: string\n label: string\n icon?: string\n group?: string | null\n /**\n * Eloquent morph-class либо FQCN модели — нужен AuditTimeline'у как\n * `subject_type` параметр для /audit/timeline endpoint'а.\n */\n subject_type?: string | null\n permissions: Record<string, string>\n fields: ManifestNode[]\n /** Read-only entries для view-page. Default — auto-generated из fields(). */\n infolist?: ManifestNode[]\n columns: ManifestNode[]\n filters: ManifestNode[]\n actions: ManifestNode[]\n searchable: string[]\n with: string[]\n features: Record<string, unknown>\n screens?: Record<string, unknown>\n}\n\nexport interface ManifestScreenMeta {\n slug: string\n name: string\n description: string | null\n permission: string[] | string | null\n}\n\nexport interface ManifestSettingsMeta {\n kind: 'settings'\n slug: string\n label: string\n permissions: Record<string, string>\n fields: ManifestNode[]\n}\n\nexport interface AdminManifest {\n version: string\n locale: string\n resources: ManifestResourceMeta[]\n screens: ManifestScreenMeta[]\n settings: ManifestSettingsMeta[]\n dashboards: unknown[]\n plugins: string[]\n permissions: unknown[]\n}\n\nexport const useManifestStore = defineStore('admin-manifest', () => {\n const manifest = ref<AdminManifest | null>(null)\n const loading = ref(false)\n const error = ref<Error | null>(null)\n /**\n * Boot-resolution gate. true как только начальный flow \"load manifest →\n * replaceManifestRoutes → router.replace(currentFullPath)\" завершён,\n * либо если manifest заведомо не нужен (login flow / skipManifestLoad).\n *\n * AdminApp.vue использует этот флаг чтобы скрыть NotFoundPage пока не\n * закончился initial re-resolve — иначе deep-link reload даёт вспышку\n * 404 между первым match'ем catch-all и последующим router.replace.\n *\n * Проставляется createAdminApp.loadAndApply() в finally — точное место,\n * где route уже re-resolved, а manifest либо загружен, либо упал ошибкой.\n */\n const bootResolved = ref(false)\n\n const isLoaded = computed(() => manifest.value !== null)\n const version = computed(() => manifest.value?.version ?? null)\n const resources = computed(() => manifest.value?.resources ?? [])\n const screens = computed(() => manifest.value?.screens ?? [])\n const settings = computed(() => manifest.value?.settings ?? [])\n const plugins = computed(() => manifest.value?.plugins ?? [])\n\n function getResource(slug: string): ManifestResourceMeta | null {\n return resources.value.find((r) => r.slug === slug) ?? null\n }\n\n function getScreen(slug: string): ManifestScreenMeta | null {\n return screens.value.find((s) => s.slug === slug) ?? null\n }\n\n function getSettings(slug: string): ManifestSettingsMeta | null {\n return settings.value.find((s) => s.slug === slug) ?? null\n }\n\n /**\n * Загрузить manifest. Если уже загружен — возвращает cached.\n * Force=true принудительно обновит с сервера.\n */\n async function load(force = false): Promise<AdminManifest> {\n if (manifest.value !== null && !force) {\n return manifest.value\n }\n\n loading.value = true\n error.value = null\n try {\n const client = getAdminClient()\n const result = await client.get<AdminManifest>('/system/manifest')\n manifest.value = result\n return result\n } catch (err) {\n error.value = err instanceof Error ? err : new Error(String(err))\n throw err\n } finally {\n loading.value = false\n }\n }\n\n function reset(): void {\n manifest.value = null\n error.value = null\n loading.value = false\n bootResolved.value = false\n }\n\n return {\n // state\n manifest,\n loading,\n error,\n bootResolved,\n // getters\n isLoaded,\n version,\n resources,\n screens,\n settings,\n plugins,\n // actions\n getResource,\n getScreen,\n getSettings,\n load,\n reset,\n }\n})\n","/**\n * adminToast — фасад над useToast() из @dskripchenko/ui для admin-flows.\n *\n * Компонент @dskripchenko/ui/composables/useToast хранит массив toast'ов\n * в module-singleton'е (общий стек на всё приложение). Мы оборачиваем\n * методы success/error/info/warning в простые функции с дефолтными\n * длительностями + используется AdminClient ApiError для извлечения\n * понятных сообщений.\n */\nimport { useToast } from '@dskripchenko/ui'\n\ninterface Options {\n title?: string\n /** Длительность в ms (0 = не закрывать автоматически). */\n duration?: number\n}\n\nfunction shorthand(message: string, opts?: Options) {\n return { message, ...(opts ?? {}) }\n}\n\nexport const adminToast = {\n success(message: string, opts?: Options): void {\n useToast().success(shorthand(message, opts))\n },\n error(message: string, opts?: Options): void {\n useToast().error(shorthand(message, { duration: 6000, ...(opts ?? {}) }))\n },\n warning(message: string, opts?: Options): void {\n useToast().warning(shorthand(message, opts))\n },\n info(message: string, opts?: Options): void {\n useToast().info(shorthand(message, opts))\n },\n}\n\n/**\n * fromError — извлекает message из ApiError / Error / unknown и пушит toast.\n */\nexport function toastError(err: unknown, fallback = 'Произошла ошибка'): void {\n const msg =\n err instanceof Error\n ? err.message || fallback\n : typeof err === 'string'\n ? err\n : fallback\n adminToast.error(msg)\n}\n","<script setup lang=\"ts\">\n/**\n * Root компонент SPA admin'а — рендерит router-view, оборачивая его в\n * AdminShell layout (TopBar + Sidebar + content) для аутентифицированных\n * роутов. Auth-роуты (login, 403, 404) и роуты с meta.fullscreen рендерятся\n * без shell.\n *\n * Используется createAdminApp() как root-component. Host'ы редко\n * переопределяют — обычно достаточно настроить отдельные pages через опции.\n */\nimport { computed } from 'vue'\nimport { useRoute } from 'vue-router'\nimport { UidToastProvider } from '@dskripchenko/ui'\nimport AdminShell from './shell/AdminShell.vue'\nimport AdminLoadingBar from './AdminLoadingBar.vue'\nimport NotificationsDrawer from './shell/NotificationsDrawer.vue'\nimport { useManifestStore } from '../stores/manifest'\nimport { useAuthStore } from '../stores/auth'\nimport { adminToast } from '../stores/toast'\n\nconst route = useRoute()\nconst manifest = useManifestStore()\nconst auth = useAuthStore()\n\n/**\n * Impersonation state — backend кладёт в bootstrap.user.impersonator\n * объект `{name, email}`, если активный сеанс — impersonation. Frontend\n * отображает баннер сверху shell'а.\n */\nconst impersonation = computed<{ asName: string } | null>(() => {\n const u = auth.user as Record<string, unknown> | null\n const imp = u?.impersonator as Record<string, unknown> | null | undefined\n if (!imp) return null\n // u.name — кого мы изображаем; imp.name — кто настоящий админ.\n return { asName: String(u?.name ?? '?') }\n})\n\nasync function exitImpersonation(): Promise<void> {\n try {\n const { getAdminClient } = await import('../stores/registry')\n const client = getAdminClient()\n await client.post('/auth/stopImpersonation')\n window.location.reload()\n } catch {\n adminToast.error('Не удалось выйти из режима импертонации.')\n }\n}\n\nconst useShell = computed<boolean>(() => {\n if (route.meta?.fullscreen === true) return false\n if (route.meta?.kind === 'auth') return false\n if (route.name === 'admin.notFound') return false\n return true\n})\n\n/**\n * При reload deep-link страницы (/admin/r/articles/1/edit) Vue Router\n * сначала матчит против static routes (dynamic resource routes ещё не\n * добавлены — manifest async-load в createAdminApp), и фолбэк-резолв\n * попадает в catch-all `admin.notFound`. Через 50-200ms manifest приходит,\n * createAdminApp re-resolve'ит current route → правильная страница.\n *\n * Чтобы избежать вспышки 404 в этот промежуток — скрываем NotFoundPage\n * пока initial manifest+re-resolve не закончился (manifest.bootResolved).\n * Гейт открывается createAdminApp.loadAndApply() в finally — после того,\n * как router.replace(currentFullPath) уже отработал. Это закрывает окно\n * между \"manifest пришёл\" и \"route переключился\", где иначе виден 404.\n */\nconst suppressNotFound = computed<boolean>(\n () => route.name === 'admin.notFound' && !manifest.bootResolved,\n)\n</script>\n\n<template>\n <!-- Top loading-bar: показывается пока nav/data не закончили (см. useNavigationStore). -->\n <AdminLoadingBar />\n\n <AdminShell\n v-if=\"useShell\"\n :impersonation=\"impersonation\"\n @exit-impersonation=\"exitImpersonation\"\n >\n <div class=\"admin-page-host\">\n <router-view v-slot=\"{ Component }\">\n <Transition name=\"admin-page\">\n <component v-if=\"!suppressNotFound\" :is=\"Component\" />\n <div v-else class=\"admin-page-host__suspended\" aria-busy=\"true\" />\n </Transition>\n </router-view>\n </div>\n </AdminShell>\n <router-view v-else v-slot=\"{ Component }\">\n <Transition name=\"admin-page\">\n <component v-if=\"!suppressNotFound\" :is=\"Component\" />\n <div v-else class=\"admin-page-host__suspended\" aria-busy=\"true\" />\n </Transition>\n </router-view>\n\n <!-- Slide-in drawer уведомлений; mounted один раз, открывается через\n notificationsStore.toggleDrawer() (см. NotificationBell). -->\n <NotificationsDrawer />\n\n <!-- Toast-stack для админских уведомлений (success/error/info).\n useToast() из @dskripchenko/ui — push'ит сообщения в общий store. -->\n <UidToastProvider />\n</template>\n\n<style>\n/*\n * Page-host: relative контейнер. Старая страница leaving делается absolute\n * (overlay поверх новой), entering в нормальном flow с slide-from-right.\n *\n * Тайминги (по запросу):\n * - leaving fade-out: 140ms ease-out (быстро уходит).\n * - entering slide-from-right + fade-in: 320ms cubic-bezier easing,\n * с 60ms delay чтобы старая успела \"пропасть до того как новая\n * доберётся до позиции\".\n *\n * overflow:hidden на host — slide справа не вылезает за viewport.\n */\n.admin-page-host {\n position: relative;\n min-height: 200px;\n overflow: hidden;\n}\n\n/* Заглушка-noop пока manifest не resolved — заменяет потенциальный flash\n NotFoundPage при reload deep-link. Top loading-bar показывает что\n что-то происходит. */\n.admin-page-host__suspended {\n min-height: 320px;\n}\n\n/* Leaving page absolute — не двигает layout, остаётся на месте пока fade'ится. */\n.admin-page-leave-active {\n position: absolute;\n inset: 0;\n width: 100%;\n transition: opacity 140ms ease-out;\n}\n\n.admin-page-leave-to {\n opacity: 0;\n}\n\n/* Entering page: slide-in справа + fade-in. Delay 60ms — старая уже почти ушла. */\n.admin-page-enter-active {\n transition:\n opacity 320ms cubic-bezier(0.2, 0.8, 0.2, 1) 60ms,\n transform 320ms cubic-bezier(0.2, 0.8, 0.2, 1) 60ms;\n}\n\n.admin-page-enter-from {\n opacity: 0;\n transform: translateX(28px);\n}\n\n.admin-page-enter-to {\n opacity: 1;\n transform: translateX(0);\n}\n\n@media (prefers-reduced-motion: reduce) {\n .admin-page-enter-active,\n .admin-page-leave-active {\n transition: opacity 80ms ease-out;\n }\n .admin-page-enter-from {\n transform: none;\n }\n}\n</style>\n","/**\n * Dashboard store: edit-mode + working-copy layout + save/load.\n *\n * Backend контракт:\n * GET /api/admin/dashboard/get?key={dashboard_slug} → { layout: WidgetItem[] | null }\n * POST /api/admin/dashboard/save body { key, widgets[] }\n * POST /api/admin/dashboard/reset body { key }\n *\n * WidgetItem — это per-user override:\n * { slug, size, position, hidden, config?, type? }\n *\n * `slug` — backend Widget::slug() (для встроенных) либо user-generated\n * (для виджетов добавленных через Add Widget — host сохраняет config\n * в `config` поле, type — в `type`).\n */\n\nimport { defineStore } from 'pinia'\nimport { computed, ref } from 'vue'\nimport { getAdminClient } from './registry'\n\nexport interface WidgetLayoutItem {\n slug: string\n size?: number\n position?: number\n hidden?: boolean\n /** Тип widget'а (для user-added; для backend — синхронизируется с Widget). */\n type?: string\n /** Title override + per-type конфигурация. */\n config?: Record<string, unknown>\n}\n\nexport const useDashboardStore = defineStore('admin-dashboard', () => {\n /** Текущий dashboard-slug (открытый в DashboardPage). */\n const slug = ref<string | null>(null)\n /** Edit-mode флаг — показывает overlay'и поверх виджетов. */\n const editMode = ref<boolean>(false)\n /** Working-copy layout (то что юзер редактирует, до save). */\n const draft = ref<WidgetLayoutItem[]>([])\n /** Изначальный layout — для cancel/restore. */\n const original = ref<WidgetLayoutItem[]>([])\n /** Loading state для load/save. */\n const saving = ref<boolean>(false)\n const loading = ref<boolean>(false)\n\n const isDirty = computed<boolean>(() => {\n return JSON.stringify(draft.value) !== JSON.stringify(original.value)\n })\n\n /** Открыть dashboard — load persisted layout если есть. */\n async function openDashboard(dashboardSlug: string): Promise<void> {\n slug.value = dashboardSlug\n loading.value = true\n try {\n const client = getAdminClient()\n const result = await client.get<{ layout: WidgetLayoutItem[] | null }>(\n `/dashboard/get?key=${encodeURIComponent(dashboardSlug)}`,\n )\n const items = (result.layout ?? []).map((it, idx) => ({\n ...it,\n position: it.position ?? idx,\n }))\n original.value = items\n draft.value = items.map((it) => ({ ...it }))\n } catch {\n original.value = []\n draft.value = []\n } finally {\n loading.value = false\n }\n }\n\n function enterEditMode(): void {\n editMode.value = true\n }\n\n function cancelEdit(): void {\n draft.value = original.value.map((it) => ({ ...it }))\n editMode.value = false\n }\n\n async function saveLayout(): Promise<void> {\n if (slug.value === null) return\n saving.value = true\n try {\n const client = getAdminClient()\n // Перед save нумеруем position в порядке текущего draft (drag-order).\n const widgets = draft.value.map((it, idx) => ({\n slug: it.slug,\n size: it.size,\n position: idx,\n hidden: it.hidden ?? false,\n type: it.type,\n config: it.config,\n }))\n await client.post('/dashboard/save', { key: slug.value, widgets })\n original.value = draft.value.map((it) => ({ ...it }))\n editMode.value = false\n } finally {\n saving.value = false\n }\n }\n\n async function resetToDefault(): Promise<void> {\n if (slug.value === null) return\n saving.value = true\n try {\n const client = getAdminClient()\n await client.post('/dashboard/reset', { key: slug.value })\n original.value = []\n draft.value = []\n editMode.value = false\n } finally {\n saving.value = false\n }\n }\n\n function addWidget(item: WidgetLayoutItem): void {\n draft.value = [\n ...draft.value,\n { ...item, position: draft.value.length },\n ]\n }\n\n function removeWidget(slugKey: string): void {\n draft.value = draft.value.filter((it) => it.slug !== slugKey)\n }\n\n function updateWidget(slugKey: string, patch: Partial<WidgetLayoutItem>): void {\n draft.value = draft.value.map((it) =>\n it.slug === slugKey ? { ...it, ...patch } : it,\n )\n }\n\n function moveWidget(fromIdx: number, toIdx: number): void {\n if (fromIdx === toIdx) return\n const next = [...draft.value]\n const [moved] = next.splice(fromIdx, 1)\n next.splice(toIdx, 0, moved)\n draft.value = next\n }\n\n function reset(): void {\n slug.value = null\n editMode.value = false\n draft.value = []\n original.value = []\n }\n\n return {\n slug,\n editMode,\n draft,\n original,\n saving,\n loading,\n isDirty,\n openDashboard,\n enterEditMode,\n cancelEdit,\n saveLayout,\n resetToDefault,\n addWidget,\n removeWidget,\n updateWidget,\n moveWidget,\n reset,\n }\n})\n","/**\n * i18n store — простой message-bag + t() helper.\n *\n * Backend кладёт translations bag в `bootstrap.translations` (Record<key, string>).\n * При смене локали (`/system/setLocale`) bootstrap переподнимается либо\n * helper зовёт `loadLocale(locale)`, который POST'ит messages.\n *\n * Формат:\n * t('admin.dashboard.add_widget') // 'Add widget'\n * t('admin.records.count', { n: 42 }) // 'Записей: 42' (interpolation :n)\n *\n * Fallback: если ключ не найден — возвращает сам ключ (помогает быстро\n * увидеть отсутствующие переводы во время разработки).\n */\nimport { defineStore } from 'pinia'\nimport { computed, ref } from 'vue'\nimport type { AdminBootstrap } from '../types/bootstrap'\n\nexport const useI18nStore = defineStore('admin-i18n', () => {\n const messages = ref<Record<string, string>>({})\n const locale = ref<string>('ru')\n\n function hydrate(bootstrap: AdminBootstrap): void {\n // Backend кладёт translations в bootstrap (опционально).\n const t = (bootstrap as unknown as { translations?: Record<string, string> }).translations\n if (t && typeof t === 'object') {\n messages.value = { ...t }\n }\n locale.value = bootstrap.locale ?? 'ru'\n }\n\n function setMessages(next: Record<string, string>): void {\n messages.value = { ...next }\n }\n\n /**\n * Translate. Поддерживает interpolation вида `:name` (Laravel-стиль).\n * Если ключ отсутствует — возвращается сам ключ (visible-fallback).\n */\n function t(key: string, replace: Record<string, string | number> = {}): string {\n let str = messages.value[key] ?? key\n for (const [k, v] of Object.entries(replace)) {\n str = str.replace(new RegExp(`:${k}`, 'g'), String(v))\n }\n return str\n }\n\n const has = (key: string): boolean => key in messages.value\n\n return {\n messages,\n locale,\n hydrate,\n setMessages,\n t,\n has,\n keys: computed(() => Object.keys(messages.value)),\n }\n})\n\n/**\n * Convenience: глобальный t() для не-Vue контекстов (utils, services).\n * В Vue-компонентах предпочтительнее `const { t } = useI18nStore()`.\n */\nexport function tRaw(key: string, replace?: Record<string, string | number>): string {\n return useI18nStore().t(key, replace ?? {})\n}\n","/**\n * Generic factory для component-registry'ов (fields, layouts, widgets,\n * infolist entries и т.п.).\n *\n * Все component-registry в admin'е по сути одинаковы: keyed Map<string, Component>\n * + register/get/has/list/clear/registerBundle. Этот factory вытаскивает паттерн\n * один раз; конкретные модули просто переименовывают экспорты.\n *\n * const reg = createComponentRegistry<Component>()\n * export const registerWidget = reg.register\n * export const getWidget = reg.get\n * // ...\n */\n\nexport interface ComponentRegistry<T> {\n register(type: string, value: T): void\n get(type: string): T | null\n has(type: string): boolean\n list(): string[]\n clear(): void\n registerBundle(bundle: Record<string, T>): void\n}\n\nexport function createComponentRegistry<T>(): ComponentRegistry<T> {\n const store = new Map<string, T>()\n\n return {\n register(type, value) {\n store.set(type, value)\n },\n get(type) {\n return store.get(type) ?? null\n },\n has(type) {\n return store.has(type)\n },\n list() {\n return [...store.keys()]\n },\n clear() {\n store.clear()\n },\n registerBundle(bundle) {\n for (const [type, value] of Object.entries(bundle)) {\n store.set(type, value)\n }\n },\n }\n}\n","/**\n * Реестр dashboard widget-компонентов.\n *\n * Manifest узлы dashboard выглядят так:\n * {\n * slug: 'main',\n * label: 'Главный',\n * widgets: [\n * { type: 'stat', name: 'total', title: 'Всего', value: 1284,\n * span: 3, trend: 12 },\n * { type: 'bar-chart', span: 8, ... },\n * { type: 'recent-table', span: 8, columns: [...], rows: [...] },\n * ]\n * }\n *\n * Host регистрирует кастомные widget'ы через `registerWidget()` /\n * `registerWidgets()` bundle.\n */\n\nimport type { Component } from 'vue'\nimport { createComponentRegistry } from '../createComponentRegistry'\n\nconst widgets = createComponentRegistry<Component>()\n\nexport const registerWidget = widgets.register\nexport const getWidget = widgets.get\nexport const hasWidget = widgets.has\nexport const listWidgets = widgets.list\nexport const clearWidgetRegistry = widgets.clear\nexport const registerWidgets = widgets.registerBundle\n","<script setup lang=\"ts\">\nimport { UidAlert } from '@dskripchenko/ui'\n\ninterface Props {\n type: string\n}\ndefineProps<Props>()\n</script>\n\n<template>\n <UidAlert variant=\"warning\">\n <template #title>Неизвестный widget-тип: {{ type }}</template>\n Зарегистрируйте через <code>registerWidget('{{ type }}', YourComponent)</code>.\n </UidAlert>\n</template>\n","<script setup lang=\"ts\">\n/**\n * Резолвит widget-компонент по `node.type` и forwards остальные props.\n */\nimport { computed } from 'vue'\nimport { getWidget } from './registry'\nimport UnknownWidget from './UnknownWidget.vue'\n\nexport interface WidgetNode extends Record<string, unknown> {\n type: string\n /** Сколько колонок занимает в 12-grid (1..12). */\n span?: number\n}\n\ninterface Props {\n node: WidgetNode\n}\nconst props = defineProps<Props>()\n\nconst component = computed(() => getWidget(props.node.type))\nconst widgetProps = computed(() => {\n const { type: _type, span: _span, ...rest } = props.node\n return rest\n})\n</script>\n\n<template>\n <component :is=\"component\" v-if=\"component\" v-bind=\"widgetProps\" />\n <UnknownWidget v-else :type=\"node.type\" />\n</template>\n","<script setup lang=\"ts\">\n/**\n * Overlay с action-кнопками поверх widget'а в edit-mode:\n * ☰ — drag-handle для пересортировки\n * ⚙ — настройки widget'а\n * × — удалить\n */\nimport { GripVertical, Settings, X } from 'lucide-vue-next'\nimport { UidIcon } from '@dskripchenko/ui'\n\ndefineEmits<{\n configure: []\n remove: []\n}>()\n</script>\n\n<template>\n <div class=\"admin-widget-actions\" role=\"toolbar\" aria-label=\"Действия с виджетом\">\n <button\n type=\"button\"\n class=\"admin-widget-actions__btn admin-widget-actions__drag\"\n aria-label=\"Перетащить\"\n title=\"Перетащить\"\n data-drag-handle=\"true\"\n >\n <UidIcon :icon=\"GripVertical\" :size=\"14\" />\n </button>\n <button\n type=\"button\"\n class=\"admin-widget-actions__btn\"\n aria-label=\"Настройки\"\n title=\"Настройки\"\n @click=\"$emit('configure')\"\n >\n <UidIcon :icon=\"Settings\" :size=\"14\" />\n </button>\n <button\n type=\"button\"\n class=\"admin-widget-actions__btn admin-widget-actions__btn--danger\"\n aria-label=\"Удалить\"\n title=\"Удалить\"\n @click=\"$emit('remove')\"\n >\n <UidIcon :icon=\"X\" :size=\"14\" />\n </button>\n </div>\n</template>\n\n<style>\n.admin-widget-actions {\n position: absolute;\n top: 8px;\n right: 8px;\n display: inline-flex;\n align-items: center;\n gap: 2px;\n padding: 2px;\n background: var(--uid-surface-raised);\n border: 1px solid var(--uid-border-subtle);\n border-radius: var(--uid-radius-md);\n box-shadow: var(--uid-shadow-sm);\n z-index: 5;\n}\n.admin-widget-actions__btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n border: 0;\n background: transparent;\n border-radius: var(--uid-radius-sm);\n color: var(--uid-text-secondary);\n cursor: pointer;\n}\n.admin-widget-actions__btn:hover {\n background: var(--uid-color-surface-hover, var(--uid-border-subtle));\n color: var(--uid-text-primary);\n}\n.admin-widget-actions__btn--danger:hover {\n background: color-mix(in srgb, var(--uid-color-danger, #dc2626) 14%, transparent);\n color: var(--uid-color-danger, #dc2626);\n}\n.admin-widget-actions__drag {\n cursor: grab;\n}\n.admin-widget-actions__drag:active {\n cursor: grabbing;\n}\n</style>\n","<script setup lang=\"ts\">\n/**\n * WidgetConfigDialog — единый dialog для двух use-case'ов:\n *\n * mode='add' — выбор типа из registry + первичная настройка\n * mode='configure'— редактирование существующего widget'а (тип фиксирован)\n *\n * Поля:\n * - title (всегда)\n * - size 1..12 (всегда)\n * - type-specific config (зависит от type):\n * markdown → content\n * stat/stats → label + value\n * gauge → value (0..100)\n * chart/bar-chart/donut-chart → labels + datasets[0].data (CSV)\n * recent-table → resource slug + limit\n * heatmap → нет настраиваемых (рендерится из data, host'ит backend)\n *\n * @add — emit готового WidgetLayoutItem (родитель кладёт в store).\n * @save — emit patch'а для существующего widget'а.\n */\nimport { computed, ref, watch } from 'vue'\nimport { X } from 'lucide-vue-next'\nimport {\n UidButton,\n UidIcon,\n UidInput,\n} from '@dskripchenko/ui'\nimport { listWidgets } from './registry'\nimport type { WidgetLayoutItem } from '../../stores/dashboard'\n\ninterface Props {\n open: boolean\n /** 'add' — выбор типа; 'configure' — редактирование существующего. */\n mode?: 'add' | 'configure'\n /** Initial-state для configure (slug + type + size + config). */\n item?: WidgetLayoutItem | null\n /** Title виджета на момент открытия (для configure-mode из manifest'а). */\n initialTitle?: string\n}\nconst props = withDefaults(defineProps<Props>(), {\n mode: 'add',\n item: null,\n initialTitle: '',\n})\n\nconst emit = defineEmits<{\n close: []\n add: [item: WidgetLayoutItem]\n save: [patch: Partial<WidgetLayoutItem>]\n}>()\n\nconst types = computed<string[]>(() => listWidgets())\nconst selectedType = ref<string>('')\nconst title = ref<string>('')\nconst size = ref<string>('6')\n\nconst markdownContent = ref<string>('# Новая заметка\\n\\nТекст…')\nconst statLabel = ref<string>('LABEL')\nconst statValue = ref<string>('0')\nconst gaugeValue = ref<string>('50')\nconst chartLabels = ref<string>('Янв, Фев, Мар, Апр')\nconst chartValues = ref<string>('10, 20, 15, 30')\nconst recentResource = ref<string>('')\nconst recentLimit = ref<string>('5')\n\nwatch(\n () => props.open,\n (open) => {\n if (!open) return\n if (props.mode === 'configure' && props.item) {\n const cfg = (props.item.config ?? {}) as Record<string, unknown>\n selectedType.value = props.item.type ?? ''\n title.value = (cfg.title as string | undefined) ?? props.initialTitle\n size.value = String(props.item.size ?? 6)\n // Преварительно заполняем type-specific поля.\n markdownContent.value = (cfg.content as string | undefined) ?? markdownContent.value\n const firstStat = (cfg.stats as Array<Record<string, unknown>> | undefined)?.[0]\n if (firstStat) {\n statLabel.value = String(firstStat.label ?? '')\n statValue.value = String(firstStat.value ?? '')\n }\n gaugeValue.value = String((cfg.value as number | undefined) ?? 50)\n // Chart labels/values — flatten из cfg.labels / cfg.datasets[0].data.\n const labels = cfg.labels as string[] | undefined\n const datasets = cfg.datasets as Array<{ data?: number[] }> | undefined\n if (labels && labels.length > 0) chartLabels.value = labels.join(', ')\n if (datasets && datasets[0]?.data) chartValues.value = datasets[0].data.join(', ')\n recentResource.value = (cfg.resource as string | undefined) ?? ''\n recentLimit.value = String(cfg.limit ?? 5)\n } else {\n // Add-mode: чистый state.\n selectedType.value = ''\n title.value = ''\n size.value = '6'\n }\n },\n)\n\nconst canSubmit = computed<boolean>(\n () => selectedType.value !== '' && title.value.trim() !== '',\n)\n\nconst labelOf: Record<string, string> = {\n stat: 'Stat — карточка с числом',\n stats: 'Stats overview — несколько метрик',\n chart: 'Chart — линия / столбцы / донат',\n 'bar-chart': 'Bar chart — гистограмма',\n 'donut-chart': 'Donut — кольцевая диаграмма',\n 'recent-table': 'Recent list — последние записи',\n recent_list: 'Recent list — последние записи',\n 'recent-list': 'Recent list — последние записи',\n heatmap: 'Heatmap — тепловая карта',\n gauge: 'Gauge — шкала со значением',\n markdown: 'Markdown — заметка / текст',\n}\n\ntype ConfigKind =\n | 'markdown'\n | 'stat'\n | 'gauge'\n | 'chart'\n | 'recent'\n | null\n\nfunction configKind(t: string): ConfigKind {\n if (t === 'markdown') return 'markdown'\n if (t === 'stat' || t === 'stats') return 'stat'\n if (t === 'gauge') return 'gauge'\n if (t === 'chart' || t === 'bar-chart' || t === 'donut-chart') return 'chart'\n if (t === 'recent-table' || t === 'recent_list' || t === 'recent-list') return 'recent'\n return null\n}\n\nfunction buildConfig(): Record<string, unknown> {\n const base: Record<string, unknown> = { title: title.value }\n switch (configKind(selectedType.value)) {\n case 'markdown':\n base.content = markdownContent.value\n break\n case 'stat':\n base.stats = [{ label: statLabel.value, value: statValue.value }]\n break\n case 'gauge':\n base.value = Number(gaugeValue.value) || 0\n base.min = 0\n base.max = 100\n break\n case 'chart': {\n const labels = chartLabels.value.split(',').map((s) => s.trim()).filter(Boolean)\n const data = chartValues.value\n .split(',')\n .map((s) => Number(s.trim()))\n .filter((n) => !Number.isNaN(n))\n base.labels = labels\n base.datasets = [{ label: title.value, data }]\n base.type = selectedType.value === 'donut-chart' ? 'doughnut' : 'bar'\n break\n }\n case 'recent':\n base.resource = recentResource.value\n base.limit = Number(recentLimit.value) || 5\n break\n }\n return base\n}\n\nfunction onSubmit(): void {\n if (!canSubmit.value) return\n const sizeNum = Math.max(1, Math.min(12, Number(size.value) || 6))\n const config = buildConfig()\n\n if (props.mode === 'configure' && props.item) {\n emit('save', { size: sizeNum, type: selectedType.value, config })\n } else {\n const slug = `custom.${selectedType.value}.${Date.now()}`\n emit('add', {\n slug,\n type: selectedType.value,\n size: sizeNum,\n config,\n })\n }\n emit('close')\n}\n\nfunction close(): void {\n emit('close')\n}\n</script>\n\n<template>\n <Teleport to=\"body\">\n <Transition name=\"admin-dialog\">\n <div\n v-if=\"open\"\n class=\"admin-dialog-root\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"widget-config-title\"\n >\n <div class=\"admin-dialog-root__backdrop\" @click=\"close\" />\n <div class=\"admin-dialog\">\n <header class=\"admin-dialog__hd\">\n <h2 id=\"widget-config-title\" class=\"admin-dialog__title\">\n {{ mode === 'add' ? 'Добавить виджет' : 'Настроить виджет' }}\n </h2>\n <button\n type=\"button\"\n class=\"admin-dialog__close\"\n aria-label=\"Закрыть\"\n @click=\"close\"\n >\n <UidIcon :icon=\"X\" :size=\"16\" />\n </button>\n </header>\n\n <div class=\"admin-dialog__body\">\n <!-- Type selector — только в add-mode. -->\n <div v-if=\"mode === 'add'\" class=\"admin-dialog__field\">\n <label class=\"admin-dialog__label\">Тип виджета</label>\n <div class=\"admin-dialog__type-grid\">\n <button\n v-for=\"t in types\"\n :key=\"t\"\n type=\"button\"\n :class=\"[\n 'admin-dialog__type-card',\n { 'admin-dialog__type-card--active': selectedType === t },\n ]\"\n @click=\"selectedType = t\"\n >\n <span class=\"admin-dialog__type-name\">{{ t }}</span>\n <span class=\"admin-dialog__type-help\">{{ labelOf[t] ?? '' }}</span>\n </button>\n </div>\n </div>\n <div v-else class=\"admin-dialog__field\">\n <label class=\"admin-dialog__label\">Тип</label>\n <div class=\"admin-dialog__readonly\">{{ selectedType || 'unknown' }}</div>\n </div>\n\n <div class=\"admin-dialog__field\">\n <label class=\"admin-dialog__label\">Заголовок</label>\n <UidInput v-model=\"title\" placeholder=\"Название виджета\" />\n </div>\n\n <div class=\"admin-dialog__field\">\n <label class=\"admin-dialog__label\">Ширина (1..12)</label>\n <UidInput v-model=\"size\" type=\"number\" />\n </div>\n\n <!-- Type-specific config -->\n <template v-if=\"configKind(selectedType) === 'markdown'\">\n <div class=\"admin-dialog__field\">\n <label class=\"admin-dialog__label\">Markdown содержимое</label>\n <textarea\n v-model=\"markdownContent\"\n class=\"admin-dialog__textarea\"\n rows=\"6\"\n />\n </div>\n </template>\n <template v-else-if=\"configKind(selectedType) === 'stat'\">\n <div class=\"admin-dialog__field\">\n <label class=\"admin-dialog__label\">Метка</label>\n <UidInput v-model=\"statLabel\" />\n </div>\n <div class=\"admin-dialog__field\">\n <label class=\"admin-dialog__label\">Значение</label>\n <UidInput v-model=\"statValue\" />\n </div>\n </template>\n <template v-else-if=\"configKind(selectedType) === 'gauge'\">\n <div class=\"admin-dialog__field\">\n <label class=\"admin-dialog__label\">Значение (0..100)</label>\n <UidInput v-model=\"gaugeValue\" type=\"number\" />\n </div>\n </template>\n <template v-else-if=\"configKind(selectedType) === 'chart'\">\n <div class=\"admin-dialog__field\">\n <label class=\"admin-dialog__label\">Метки (через запятую)</label>\n <UidInput v-model=\"chartLabels\" placeholder=\"Янв, Фев, Мар\" />\n </div>\n <div class=\"admin-dialog__field\">\n <label class=\"admin-dialog__label\">Значения (через запятую)</label>\n <UidInput v-model=\"chartValues\" placeholder=\"10, 20, 15\" />\n </div>\n </template>\n <template v-else-if=\"configKind(selectedType) === 'recent'\">\n <div class=\"admin-dialog__field\">\n <label class=\"admin-dialog__label\">Resource slug</label>\n <UidInput v-model=\"recentResource\" placeholder=\"articles\" />\n </div>\n <div class=\"admin-dialog__field\">\n <label class=\"admin-dialog__label\">Limit</label>\n <UidInput v-model=\"recentLimit\" type=\"number\" />\n </div>\n </template>\n </div>\n\n <footer class=\"admin-dialog__ft\">\n <UidButton variant=\"ghost\" @click=\"close\">Отмена</UidButton>\n <UidButton variant=\"primary\" :disabled=\"!canSubmit\" @click=\"onSubmit\">\n {{ mode === 'add' ? 'Добавить' : 'Сохранить' }}\n </UidButton>\n </footer>\n </div>\n </div>\n </Transition>\n </Teleport>\n</template>\n\n<style>\n.admin-dialog__readonly {\n padding: 8px 10px;\n background: var(--uid-surface-base);\n border: 1px solid var(--uid-border-subtle);\n border-radius: var(--uid-radius-md);\n font-family: var(--uid-font-family-mono, ui-monospace, monospace);\n font-size: 13px;\n color: var(--uid-text-secondary);\n}\n</style>\n","<script setup lang=\"ts\">\n/**\n * DashboardPage — 12-col grid из widget'ов с поддержкой edit-mode.\n *\n * Источник widget'ов:\n * - Manifest.dashboards (host-side declared, через DashboardScreen).\n * - Per-user persisted layout (DashboardLayout / dashboard store) —\n * накладывается поверх manifest'ной декларации: переупорядочение,\n * resize, hidden, удаление + user-added widgets через AddWidget.\n *\n * Edit-mode:\n * 1. «Редактировать» в toolbar → editMode=true. На каждом widget'е\n * появляются [☰][⚙][×] (см. WidgetActionsOverlay).\n * 2. Drag-handle ☰ позволяет менять порядок (HTML5 drag).\n * 3. Resize-handle ↘ в правом-нижнем углу — изменяет span (1..12).\n * 4. + Add widget → AddWidgetDialog → store.addWidget.\n * 5. «Сохранить» → POST /dashboard/save с draft. «Отменить» → restore.\n */\nimport { computed, ref } from 'vue'\nimport {\n Calendar,\n ChevronDown,\n Download,\n Pencil,\n Plus,\n RotateCcw,\n} from 'lucide-vue-next'\nimport {\n UidButton,\n UidIcon,\n UidMenu,\n UidMenuItem,\n} from '@dskripchenko/ui'\nimport { useManifestStore } from '../../stores/manifest'\nimport { useI18nStore } from '../../stores/i18n'\nimport { useDashboardStore, type WidgetLayoutItem } from '../../stores/dashboard'\nimport WidgetRenderer, { type WidgetNode } from './WidgetRenderer.vue'\nimport WidgetActionsOverlay from './WidgetActionsOverlay.vue'\nimport WidgetConfigDialog from './WidgetConfigDialog.vue'\n\ninterface DashboardManifest {\n slug: string\n label?: string\n description?: string | null\n widgets: WidgetNode[]\n}\n\ninterface Props {\n slug?: string\n widgets?: WidgetNode[]\n title?: string\n subtitle?: string\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n slug: undefined,\n widgets: undefined,\n title: undefined,\n subtitle: undefined,\n})\n\nconst emit = defineEmits<{\n 'change-period': [value: string]\n 'export': []\n}>()\n\nconst manifest = useManifestStore()\nconst dashboardStore = useDashboardStore()\nconst i18n = useI18nStore()\nconst t = (key: string, fallback: string): string => {\n // Если backend lang-bag прислал нужный ключ — используем; иначе ru-fallback.\n // Это позволяет постепенно мигрировать без breaking changes.\n return i18n.has(key) ? i18n.t(key) : fallback\n}\n\nconst dashboard = computed<DashboardManifest | null>(() => {\n if (!props.slug || !manifest.manifest) return null\n const dashboards = manifest.manifest.dashboards as DashboardManifest[] | undefined\n return dashboards?.find((d) => d.slug === props.slug) ?? null\n})\n\nconst manifestWidgets = computed<WidgetNode[]>(() => {\n if (props.widgets) return props.widgets\n // refreshedWidgets — свежие data после смены period (через /dashboard/widgets).\n // Имеют приоритет над manifest'ным snapshot'ом.\n if (refreshedWidgets.value !== null) return refreshedWidgets.value\n return dashboard.value?.widgets ?? []\n})\n\nconst resolvedTitle = computed(\n () => props.title ?? dashboard.value?.label ?? 'Dashboard',\n)\nconst resolvedSubtitle = computed(\n () => props.subtitle ?? dashboard.value?.description ?? null,\n)\n\n/**\n * Финальный список виджетов с применённым per-user layout'ом:\n * - manifest widgets индексируются по slug;\n * - draft layout (из store) задаёт порядок, size, hidden;\n * - user-added (есть type/config, но нет manifest-исходника) рендерятся как самостоятельные;\n * - manifest widget'ы которых нет в draft — добавляются в конец (новые в коде).\n */\nconst renderedWidgets = computed<Array<{ node: WidgetNode; layoutSlug: string }>>(() => {\n const bySlug = new Map<string, WidgetNode>()\n for (const w of manifestWidgets.value) {\n const slug = String((w as Record<string, unknown>).slug ?? '')\n if (slug) bySlug.set(slug, w)\n }\n\n const draft = dashboardStore.draft\n const out: Array<{ node: WidgetNode; layoutSlug: string }> = []\n\n if (draft.length > 0) {\n for (const item of draft) {\n if (item.hidden) continue\n let node: WidgetNode | null = null\n if (bySlug.has(item.slug)) {\n // Manifest-widget с per-user override size.\n const base = bySlug.get(item.slug) as WidgetNode\n node = {\n ...base,\n size: item.size ?? (base as Record<string, unknown>).size ?? 12,\n } as WidgetNode\n bySlug.delete(item.slug)\n } else if (item.type) {\n // User-added widget — рендерится по type + config.\n const cfg = (item.config ?? {}) as Record<string, unknown>\n node = {\n slug: item.slug,\n type: item.type,\n title: (cfg.title as string | undefined) ?? '',\n size: item.size ?? 6,\n data: cfg,\n } as WidgetNode\n }\n if (node) out.push({ node, layoutSlug: item.slug })\n }\n // Новые manifest-widgets (которых ещё нет в persisted layout'е).\n for (const [slug, w] of bySlug.entries()) {\n out.push({ node: w, layoutSlug: slug })\n }\n } else {\n // Нет draft'а — рендерим manifest как есть.\n for (const w of manifestWidgets.value) {\n out.push({ node: w, layoutSlug: String((w as Record<string, unknown>).slug ?? '') })\n }\n }\n\n return out\n})\n\nfunction spanFor(w: WidgetNode): number {\n const raw = (w as Record<string, unknown>).size ?? (w as Record<string, unknown>).span\n const s = typeof raw === 'number' ? raw : 12\n return Math.max(1, Math.min(12, s))\n}\n\n// === Toolbar period ===\nconst periods = computed(() => [\n { key: '7d', label: t('admin.dashboard.period.7d', 'За 7 дней') },\n { key: '30d', label: t('admin.dashboard.period.30d', 'За 30 дней') },\n { key: '90d', label: t('admin.dashboard.period.90d', 'За 90 дней') },\n { key: 'all', label: t('admin.dashboard.period.all', 'Всё время') },\n])\nconst selectedPeriod = ref<string>('30d')\n/** Свежие widget data полученные через /dashboard/widgets?period=. */\nconst refreshedWidgets = ref<WidgetNode[] | null>(null)\n\nasync function setPeriod(key: string, close: () => void): Promise<void> {\n selectedPeriod.value = key\n emit('change-period', key)\n close()\n await refetchPeriod()\n}\n\nasync function refetchPeriod(): Promise<void> {\n if (!props.slug) return\n try {\n const { getAdminClient } = await import('../../stores/registry')\n const client = getAdminClient()\n const result = await client.get<{ widgets: WidgetNode[]; period: string }>(\n `/dashboard/widgets?key=${encodeURIComponent(props.slug)}&period=${encodeURIComponent(selectedPeriod.value)}`,\n )\n refreshedWidgets.value = result.widgets\n } catch {\n // silent — оставляем manifest-данные.\n }\n}\n\nconst periodLabel = computed(\n () => periods.value.find((p) => p.key === selectedPeriod.value)?.label ?? t('admin.dashboard.period.label', 'Период'),\n)\n\n// === Edit-mode actions ===\nconst dialogMode = ref<'add' | 'configure' | null>(null)\nconst dialogItem = ref<WidgetLayoutItem | null>(null)\nconst dialogInitialTitle = ref<string>('')\nfunction openAdd(): void {\n dialogMode.value = 'add'\n dialogItem.value = null\n dialogInitialTitle.value = ''\n}\nfunction closeDialog(): void {\n dialogMode.value = null\n}\n\nfunction onEnterEdit(): void {\n dashboardStore.enterEditMode()\n}\nfunction onCancelEdit(): void {\n dashboardStore.cancelEdit()\n}\nasync function onSaveLayout(): Promise<void> {\n await dashboardStore.saveLayout().catch(() => undefined)\n}\n\nfunction onRemoveWidget(layoutSlug: string): void {\n // Если widget есть в draft — удаляем, иначе делаем hidden override.\n const inDraft = dashboardStore.draft.some((it) => it.slug === layoutSlug)\n if (inDraft) {\n dashboardStore.removeWidget(layoutSlug)\n } else {\n // Manifest widget — добавляем как hidden override.\n dashboardStore.addWidget({ slug: layoutSlug, hidden: true })\n }\n}\n\nfunction onConfigureWidget(layoutSlug: string): void {\n ensureDraftReflectsRendered()\n const draftItem = dashboardStore.draft.find((it) => it.slug === layoutSlug) ?? null\n // Для manifest-widget'ов (которые ещё не попали в draft) собираем\n // initial-state из renderedWidgets — там уже посчитанный node.\n const rendered = renderedWidgets.value.find((r) => r.layoutSlug === layoutSlug)\n const node = rendered?.node as Record<string, unknown> | undefined\n dialogItem.value = draftItem ?? {\n slug: layoutSlug,\n type: (node?.type as string | undefined) ?? '',\n size: (node?.size as number | undefined) ?? 6,\n config: {},\n }\n dialogInitialTitle.value = (node?.title as string | undefined) ?? ''\n dialogMode.value = 'configure'\n}\n\nfunction onAddWidget(item: WidgetLayoutItem): void {\n dashboardStore.addWidget(item)\n}\n\nfunction onSaveConfig(patch: Partial<WidgetLayoutItem>): void {\n if (!dialogItem.value) return\n const slug = dialogItem.value.slug\n // Если widget ещё не в draft — добавляем; иначе patch.\n const inDraft = dashboardStore.draft.some((it) => it.slug === slug)\n if (inDraft) {\n // merge config с предыдущим (а не replace).\n const existing = dashboardStore.draft.find((it) => it.slug === slug)\n dashboardStore.updateWidget(slug, {\n ...patch,\n config: { ...(existing?.config ?? {}), ...(patch.config ?? {}) },\n })\n } else {\n dashboardStore.addWidget({\n slug,\n type: dialogItem.value.type,\n ...patch,\n })\n }\n}\n\n// === Drag-reorder (нативный HTML5) ===\nconst dragSourceIdx = ref<number | null>(null)\nfunction onDragStart(idx: number, e: DragEvent): void {\n if (!dashboardStore.editMode) return\n if (e.dataTransfer === null) return\n // Разрешаем drag только если он начался с [data-drag-handle] —\n // иначе пользователь не сможет кликать по контенту виджета (selectable\n // text, ссылки, кнопки) без случайного перетаскивания всей карточки.\n const target = e.target as HTMLElement | null\n if (!target?.closest('[data-drag-handle=\"true\"]')) {\n e.preventDefault()\n return\n }\n dragSourceIdx.value = idx\n e.dataTransfer.effectAllowed = 'move'\n e.dataTransfer.setData('text/plain', String(idx))\n}\nfunction onDragOver(e: DragEvent): void {\n if (dashboardStore.editMode && dragSourceIdx.value !== null) {\n e.preventDefault()\n }\n}\nfunction onDrop(toIdx: number, e: DragEvent): void {\n e.preventDefault()\n if (!dashboardStore.editMode || dragSourceIdx.value === null) return\n // Reorder в store. Если widget не в draft — сначала \"поднимаем\" его\n // из manifest'а, чтобы layout сохранил позицию.\n const sourceIdx = dragSourceIdx.value\n ensureDraftReflectsRendered()\n dashboardStore.moveWidget(sourceIdx, toIdx)\n dragSourceIdx.value = null\n}\n\n/**\n * Перед drag/resize гарантируем, что текущий rendered порядок отражён\n * в store.draft (иначе reorder работает на пустом draft'е и теряет\n * manifest widget'ы).\n */\nfunction ensureDraftReflectsRendered(): void {\n if (dashboardStore.draft.length === renderedWidgets.value.length) return\n const items: WidgetLayoutItem[] = renderedWidgets.value.map(({ node, layoutSlug }, idx) => {\n const existing = dashboardStore.draft.find((it) => it.slug === layoutSlug)\n return {\n slug: layoutSlug,\n size: spanFor(node),\n position: idx,\n hidden: existing?.hidden ?? false,\n type: existing?.type ?? (node as Record<string, unknown>).type as string | undefined,\n config: existing?.config,\n }\n })\n dashboardStore.draft = items\n}\n\n// === Resize via mouse ===\nconst resizing = ref<{ slug: string; startX: number; startSpan: number } | null>(null)\nlet resizeContainerWidth = 0\nfunction onResizeStart(e: MouseEvent, layoutSlug: string, currentSpan: number): void {\n if (!dashboardStore.editMode) return\n e.preventDefault()\n e.stopPropagation()\n ensureDraftReflectsRendered()\n resizing.value = { slug: layoutSlug, startX: e.clientX, startSpan: currentSpan }\n const grid = (e.target as HTMLElement).closest('.admin-dashboard__grid') as HTMLElement | null\n resizeContainerWidth = grid?.getBoundingClientRect().width ?? 1200\n window.addEventListener('mousemove', onResizeMove)\n window.addEventListener('mouseup', onResizeEnd)\n}\nfunction onResizeMove(e: MouseEvent): void {\n if (!resizing.value) return\n const colWidth = resizeContainerWidth / 12\n const delta = Math.round((e.clientX - resizing.value.startX) / colWidth)\n const nextSpan = Math.max(1, Math.min(12, resizing.value.startSpan + delta))\n const item = dashboardStore.draft.find((it) => it.slug === resizing.value!.slug)\n if (item && item.size !== nextSpan) {\n dashboardStore.updateWidget(resizing.value.slug, { size: nextSpan })\n }\n}\nfunction onResizeEnd(): void {\n resizing.value = null\n window.removeEventListener('mousemove', onResizeMove)\n window.removeEventListener('mouseup', onResizeEnd)\n}\n\nfunction onExport(): void {\n emit('export')\n}\n</script>\n\n<template>\n <section class=\"admin-page admin-dashboard\">\n <header class=\"admin-page__hd\">\n <div class=\"admin-page__title-wrap\">\n <h1 class=\"admin-page__title\">{{ resolvedTitle }}</h1>\n <div v-if=\"resolvedSubtitle\" class=\"admin-page__count\">\n {{ resolvedSubtitle }}\n </div>\n </div>\n <div class=\"admin-page__actions\">\n <slot name=\"actions\" />\n\n <UidMenu>\n <template #trigger>\n <UidButton variant=\"ghost\" size=\"md\">\n <template #prepend><UidIcon :icon=\"Calendar\" :size=\"14\" /></template>\n {{ periodLabel }}\n <template #append><UidIcon :icon=\"ChevronDown\" :size=\"14\" /></template>\n </UidButton>\n </template>\n <UidMenuItem\n v-for=\"p in periods\"\n :key=\"p.key\"\n @click=\"setPeriod(p.key, () => undefined)\"\n >\n {{ p.label }}\n </UidMenuItem>\n </UidMenu>\n\n <UidButton variant=\"secondary\" size=\"md\" @click=\"onExport\">\n <template #prepend><UidIcon :icon=\"Download\" :size=\"14\" /></template>\n Export\n </UidButton>\n\n <!-- Edit-mode toggle -->\n <template v-if=\"!dashboardStore.editMode\">\n <UidButton variant=\"secondary\" size=\"md\" @click=\"onEnterEdit\">\n <template #prepend><UidIcon :icon=\"Pencil\" :size=\"14\" /></template>\n Редактировать\n </UidButton>\n </template>\n <template v-else>\n <UidButton variant=\"secondary\" size=\"md\" @click=\"openAdd\">\n <template #prepend><UidIcon :icon=\"Plus\" :size=\"14\" /></template>\n Add widget\n </UidButton>\n <UidButton variant=\"ghost\" size=\"md\" @click=\"onCancelEdit\">\n <template #prepend><UidIcon :icon=\"RotateCcw\" :size=\"14\" /></template>\n Отмена\n </UidButton>\n <UidButton\n variant=\"primary\"\n size=\"md\"\n :loading=\"dashboardStore.saving\"\n :disabled=\"dashboardStore.saving\"\n @click=\"onSaveLayout\"\n >\n Сохранить\n </UidButton>\n </template>\n </div>\n </header>\n\n <div\n :class=\"[\n 'admin-dashboard__grid',\n { 'admin-dashboard__grid--editing': dashboardStore.editMode },\n ]\"\n >\n <div\n v-for=\"(item, idx) in renderedWidgets\"\n :key=\"item.layoutSlug\"\n class=\"admin-dashboard__cell\"\n :class=\"{ 'admin-dashboard__cell--editing': dashboardStore.editMode }\"\n :draggable=\"dashboardStore.editMode\"\n :style=\"{ gridColumn: `span ${spanFor(item.node)} / span ${spanFor(item.node)}` }\"\n @dragstart=\"onDragStart(idx, $event)\"\n @dragover=\"onDragOver\"\n @drop=\"onDrop(idx, $event)\"\n >\n <WidgetRenderer :node=\"item.node\" />\n <WidgetActionsOverlay\n v-if=\"dashboardStore.editMode\"\n @configure=\"onConfigureWidget(item.layoutSlug)\"\n @remove=\"onRemoveWidget(item.layoutSlug)\"\n />\n <span\n v-if=\"dashboardStore.editMode\"\n class=\"admin-dashboard__resize\"\n aria-label=\"Изменить размер\"\n @mousedown=\"onResizeStart($event, item.layoutSlug, spanFor(item.node))\"\n />\n </div>\n </div>\n\n <WidgetConfigDialog\n :open=\"dialogMode !== null\"\n :mode=\"dialogMode ?? 'add'\"\n :item=\"dialogItem\"\n :initial-title=\"dialogInitialTitle\"\n @close=\"closeDialog\"\n @add=\"onAddWidget\"\n @save=\"onSaveConfig\"\n />\n </section>\n</template>\n\n<style>\n.admin-dashboard__grid {\n display: grid;\n grid-template-columns: repeat(12, minmax(0, 1fr));\n gap: var(--uid-space-md);\n}\n.admin-dashboard__grid--editing .admin-dashboard__cell {\n outline: 1px dashed transparent;\n transition: outline-color 120ms ease;\n}\n.admin-dashboard__grid--editing .admin-dashboard__cell:hover {\n outline-color: var(--uid-accent);\n}\n.admin-dashboard__cell {\n position: relative;\n min-width: 0;\n}\n/*\n * cursor: default на cell — дёргать карточку можно только за [☰]-handle\n * (см. WidgetActionsOverlay). Это позволяет в edit-mode по-прежнему\n * взаимодействовать с интерактивными элементами внутри виджета.\n */\n.admin-dashboard__resize {\n position: absolute;\n bottom: 4px;\n right: 4px;\n width: 14px;\n height: 14px;\n cursor: nwse-resize;\n background:\n linear-gradient(135deg, transparent 0 50%, var(--uid-text-tertiary) 50% 60%, transparent 60% 70%, var(--uid-text-tertiary) 70% 80%, transparent 80%);\n z-index: 4;\n}\n</style>\n","<script setup lang=\"ts\">\n/**\n * Default home-страница admin'а — показывает первый зарегистрированный\n * Dashboard (host регистрирует через `Admin::screens([DashboardScreen])`),\n * иначе fallback на welcome-карточку со списком Resource'ов.\n *\n * Host может полностью переопределить через\n * `createAdminApp({ pages: { home: MyHome } })`.\n */\nimport { computed, watch } from 'vue'\nimport { useRouter } from 'vue-router'\nimport { UidCard } from '@dskripchenko/ui'\nimport { useManifestStore } from '../stores/manifest'\nimport { useAuthStore } from '../stores/auth'\nimport { useDashboardStore } from '../stores/dashboard'\nimport DashboardPage from './dashboard/DashboardPage.vue'\n\ninterface DashboardManifest {\n slug: string\n label?: string\n description?: string | null\n widgets: unknown[]\n}\n\nconst manifest = useManifestStore()\nconst auth = useAuthStore()\nconst router = useRouter()\n\nconst userName = computed(() => auth.user?.name ?? '')\nconst resources = computed(() => manifest.manifest?.resources ?? [])\n\nconst dashboards = computed<DashboardManifest[]>(\n () => (manifest.manifest?.dashboards ?? []) as DashboardManifest[],\n)\nconst primaryDashboardSlug = computed<string | null>(\n () => dashboards.value[0]?.slug ?? null,\n)\n\n// Загружаем persisted layout из dashboard store на mount/смену slug.\nconst dashboardStore = useDashboardStore()\nwatch(\n primaryDashboardSlug,\n (slug) => {\n if (slug) void dashboardStore.openDashboard(slug)\n },\n { immediate: true },\n)\n</script>\n\n<template>\n <DashboardPage\n v-if=\"primaryDashboardSlug\"\n :slug=\"primaryDashboardSlug\"\n />\n\n <div v-else class=\"admin-home\">\n <UidCard padding=\"lg\" class=\"admin-home__hero\">\n <h1 class=\"admin-home__title\">Добро пожаловать{{ userName ? ', ' + userName : '' }}</h1>\n <p class=\"admin-home__lead\">\n Админ-панель готова. Зарегистрируйте DashboardScreen чтобы увидеть widget-grid здесь,\n либо переходите к ресурсам ниже.\n </p>\n </UidCard>\n\n <section v-if=\"resources.length\" class=\"admin-home__resources\">\n <h2 class=\"admin-home__heading\">Ресурсы</h2>\n <ul class=\"admin-home__grid\">\n <li v-for=\"r in resources\" :key=\"r.slug\">\n <button\n type=\"button\"\n class=\"admin-home__card\"\n @click=\"router.push({ name: `admin.resource.${r.slug}.index` })\"\n >\n <span class=\"admin-home__card-label\">{{ r.label }}</span>\n <span class=\"admin-home__card-slug\">{{ r.slug }}</span>\n </button>\n </li>\n </ul>\n </section>\n </div>\n</template>\n\n<style>\n.admin-home {\n display: flex;\n flex-direction: column;\n gap: var(--uid-space-lg);\n padding: var(--uid-space-md);\n}\n.admin-home__title {\n font-size: var(--uid-font-size-2xl);\n font-weight: var(--uid-font-weight-bold);\n margin: 0 0 var(--uid-space-sm);\n}\n.admin-home__lead {\n color: var(--uid-text-secondary);\n margin: 0;\n}\n.admin-home__heading {\n font-size: var(--uid-font-size-lg);\n font-weight: var(--uid-font-weight-semibold);\n margin: 0 0 var(--uid-space-sm);\n}\n.admin-home__grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));\n gap: var(--uid-space-sm);\n list-style: none;\n padding: 0;\n margin: 0;\n}\n.admin-home__card {\n display: flex;\n flex-direction: column;\n gap: var(--uid-space-2xs);\n padding: var(--uid-space-md);\n border: 1px solid var(--uid-border-subtle);\n border-radius: var(--uid-radius-md);\n background: var(--uid-surface-raised);\n text-align: left;\n cursor: pointer;\n transition: border-color 0.15s ease, transform 0.15s ease;\n}\n.admin-home__card:hover {\n border-color: var(--uid-accent);\n transform: translateY(-1px);\n}\n.admin-home__card-label {\n font-weight: var(--uid-font-weight-medium);\n}\n.admin-home__card-slug {\n font-size: var(--uid-font-size-xs);\n color: var(--uid-text-tertiary);\n}\n</style>\n","<script setup lang=\"ts\">\n/**\n * 403 fallback. Host может переопределить через createAdminApp({ pages: { forbidden } }).\n */\nimport { UidCard, UidButton } from '@dskripchenko/ui'\nimport { useRouter } from 'vue-router'\n\nconst router = useRouter()\n</script>\n\n<template>\n <div class=\"admin-status-page\">\n <UidCard padding=\"lg\" class=\"admin-status-page__card\">\n <h1 class=\"admin-status-page__code\">403</h1>\n <p class=\"admin-status-page__message\">Доступ запрещён.</p>\n <UidButton variant=\"ghost\" @click=\"router.replace({ name: 'admin.home' })\">\n На главную\n </UidButton>\n </UidCard>\n </div>\n</template>\n\n<style>\n.admin-status-page {\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 60vh;\n padding: var(--uid-space-lg);\n}\n.admin-status-page__card {\n text-align: center;\n max-width: 480px;\n}\n.admin-status-page__code {\n font-size: 64px;\n font-weight: var(--uid-font-weight-bold);\n margin: 0 0 var(--uid-space-sm);\n color: var(--uid-text-secondary);\n}\n.admin-status-page__message {\n margin: 0 0 var(--uid-space-md);\n color: var(--uid-text-secondary);\n}\n</style>\n","<script setup lang=\"ts\">\n/**\n * 404 fallback. Host может переопределить через createAdminApp({ pages: { notFound } }).\n */\nimport { UidCard, UidButton } from '@dskripchenko/ui'\nimport { useRouter } from 'vue-router'\n\nconst router = useRouter()\n</script>\n\n<template>\n <div class=\"admin-status-page\">\n <UidCard padding=\"lg\" class=\"admin-status-page__card\">\n <h1 class=\"admin-status-page__code\">404</h1>\n <p class=\"admin-status-page__message\">Страница не найдена.</p>\n <UidButton variant=\"ghost\" @click=\"router.replace({ name: 'admin.home' })\">\n На главную\n </UidButton>\n </UidCard>\n </div>\n</template>\n","<script setup lang=\"ts\">\n/**\n * Default страница для admin.settings.{slug} роутов.\n *\n * Загружает settings-meta из manifest'а и рендерит fields через LayoutRenderer\n * с form-state поверх SettingsApiClient. Host'ы переопределяют через\n * createAdminApp({ pages: { settings: MySettings } }) если нужна более\n * специфичная UX (например, side-tab навигация по Settings-классам).\n */\nimport { computed } from 'vue'\nimport { useRoute } from 'vue-router'\nimport { UidCard } from '@dskripchenko/ui'\nimport { useManifestStore } from '../stores/manifest'\n\nconst route = useRoute()\nconst manifest = useManifestStore()\n\nconst slug = computed(() => String(route.params.slug ?? ''))\nconst meta = computed(() => manifest.manifest?.settings?.find((s) => s.slug === slug.value) ?? null)\n</script>\n\n<template>\n <div class=\"admin-settings-page\">\n <UidCard padding=\"lg\">\n <h1 class=\"admin-settings-page__title\">{{ meta?.label ?? slug }}</h1>\n <p v-if=\"!meta\" class=\"admin-settings-page__hint\">\n Settings «{{ slug }}» не найдено в manifest'е.\n </p>\n <pre v-else class=\"admin-settings-page__debug\">{{ JSON.stringify(meta.fields, null, 2) }}</pre>\n </UidCard>\n </div>\n</template>\n\n<style>\n.admin-settings-page {\n padding: var(--uid-space-md);\n}\n.admin-settings-page__title {\n font-size: var(--uid-font-size-xl);\n font-weight: var(--uid-font-weight-semibold);\n margin: 0 0 var(--uid-space-sm);\n}\n.admin-settings-page__debug {\n background: var(--uid-surface-raised);\n border: 1px solid var(--uid-border-subtle);\n padding: var(--uid-space-sm);\n border-radius: var(--uid-radius-sm);\n font-family: var(--uid-font-mono);\n font-size: var(--uid-font-size-xs);\n overflow: auto;\n max-height: 60vh;\n}\n.admin-settings-page__hint {\n color: var(--uid-text-secondary);\n}\n</style>\n","<script setup lang=\"ts\">\n/**\n * Заглушка для произвольных Screen-роутов из manifest'а.\n * Host'ы переопределяют через createAdminApp({ pages: { screen: MyScreen } })\n * и кастомным компонентом рендерят `route.params.slug` через любой template.\n */\nimport { computed } from 'vue'\nimport { useRoute } from 'vue-router'\nimport { UidCard } from '@dskripchenko/ui'\n\nconst route = useRoute()\nconst slug = computed(() => String(route.params.slug ?? ''))\nconst title = computed(() => String(route.meta?.title ?? slug.value))\n</script>\n\n<template>\n <div class=\"admin-status-page\">\n <UidCard padding=\"lg\" class=\"admin-status-page__card\">\n <h1 class=\"admin-status-page__title\">{{ title }}</h1>\n <p class=\"admin-status-page__hint\">\n Это заглушка для screen «{{ slug }}». Передайте свой компонент через\n <code>createAdminApp({{ '{' }} pages: {{ '{' }} screen: MyScreen {{ '}' }} {{ '}' }})</code>.\n </p>\n </UidCard>\n </div>\n</template>\n\n<style>\n.admin-status-page__title {\n font-size: var(--uid-font-size-xl);\n font-weight: var(--uid-font-weight-semibold);\n margin: 0 0 var(--uid-space-sm);\n}\n.admin-status-page__hint {\n margin: 0;\n color: var(--uid-text-secondary);\n font-size: var(--uid-font-size-sm);\n}\n</style>\n","<script setup lang=\"ts\">\n/**\n * LoginForm — email/password/remember поверх UidInput/UidButton/UidCheckbox/\n * UidAlert. Архитектура auth-card по docs/design_handoff_laravel_admin/\n * screens-secondary.jsx (LoginScreen).\n */\nimport { computed, ref } from 'vue'\nimport { UidAlert, UidButton, UidCheckbox, UidInput } from '@dskripchenko/ui'\nimport { useAuthStore } from '../../stores/auth'\nimport { ApiError, NetworkError, ValidationError } from '../../api/errors'\n\ninterface Props {\n /** URL «Забыли пароль?» — если задан, показывается link справа от remember. */\n forgotUrl?: string | null\n /** Текст SSO-ссылки или null чтобы скрыть. */\n ssoLinkLabel?: string | null\n ssoUrl?: string | null\n}\n\nwithDefaults(defineProps<Props>(), {\n forgotUrl: null,\n ssoLinkLabel: null,\n ssoUrl: null,\n})\n\nconst emit = defineEmits<{\n success: [result: 'authenticated' | 'two_factor_required']\n}>()\n\nconst auth = useAuthStore()\n\nconst email = ref('')\nconst password = ref('')\nconst remember = ref(false)\n\nconst submitting = ref(false)\nconst generalError = ref<string | null>(null)\nconst fieldErrors = ref<Record<string, string[]>>({})\n\nconst emailError = computed<string | undefined>(() => fieldErrors.value.email?.[0])\nconst passwordError = computed<string | undefined>(() => fieldErrors.value.password?.[0])\n\nasync function submit(): Promise<void> {\n if (submitting.value) return\n submitting.value = true\n generalError.value = null\n fieldErrors.value = {}\n\n try {\n const result = await auth.login({\n email: email.value,\n password: password.value,\n remember: remember.value,\n })\n emit('success', result)\n } catch (err) {\n if (err instanceof ValidationError) {\n fieldErrors.value = err.fields\n generalError.value = err.firstFieldMessage()\n } else if (err instanceof NetworkError) {\n generalError.value = 'Нет соединения с сервером'\n } else if (err instanceof ApiError) {\n generalError.value = err.message || 'Не удалось войти'\n } else {\n generalError.value = (err as Error).message\n }\n } finally {\n submitting.value = false\n }\n}\n</script>\n\n<template>\n <form class=\"admin-auth-card__bd\" novalidate @submit.prevent=\"submit\">\n <UidAlert\n v-if=\"generalError\"\n variant=\"danger\"\n class=\"admin-auth-card__alert\"\n role=\"alert\"\n >\n {{ generalError }}\n </UidAlert>\n\n <UidInput\n v-model=\"email\"\n type=\"email\"\n label=\"Email\"\n placeholder=\"you@company.com\"\n autocomplete=\"username\"\n :required=\"true\"\n :disabled=\"submitting\"\n :error=\"emailError\"\n name=\"email\"\n />\n\n <UidInput\n v-model=\"password\"\n type=\"password\"\n label=\"Пароль\"\n autocomplete=\"current-password\"\n :required=\"true\"\n :disabled=\"submitting\"\n :error=\"passwordError\"\n name=\"password\"\n />\n\n <div class=\"admin-auth-card__row\">\n <UidCheckbox v-model=\"remember\" :disabled=\"submitting\">\n Запомнить меня\n </UidCheckbox>\n <a v-if=\"forgotUrl\" :href=\"forgotUrl\" class=\"admin-auth-card__link\">\n Забыли пароль?\n </a>\n </div>\n\n <UidButton\n type=\"submit\"\n variant=\"primary\"\n size=\"lg\"\n :loading=\"submitting\"\n :disabled=\"submitting\"\n >\n {{ submitting ? 'Вход…' : 'Войти' }}\n </UidButton>\n\n <div\n v-if=\"ssoLinkLabel && ssoUrl\"\n style=\"text-align: center; font-size: var(--uid-font-size-xs); color: var(--uid-text-secondary); padding-top: 4px;\"\n >\n или войдите через\n <a :href=\"ssoUrl\" class=\"admin-auth-card__link\">{{ ssoLinkLabel }}</a>\n </div>\n </form>\n</template>\n","<script setup lang=\"ts\">\n/**\n * 2FA-форма: 6-cell mono TOTP-input + alt recovery-code.\n *\n * Эталон — docs/design_handoff_laravel_admin/screens-secondary.jsx (TwoFactor):\n * 6 input'ов 44×52, IBM Plex Mono 22px, при заполнении одного — фокус\n * автопереходит на следующий, paste-event раскладывает 6 цифр сразу.\n */\nimport { computed, nextTick, ref } from 'vue'\nimport { UidAlert, UidButton, UidInput } from '@dskripchenko/ui'\nimport { useAuthStore } from '../../stores/auth'\nimport { ApiError, NetworkError, ValidationError } from '../../api/errors'\n\nconst emit = defineEmits<{\n success: []\n cancel: []\n}>()\n\nconst auth = useAuthStore()\n\nconst mode = ref<'totp' | 'recovery'>('totp')\nconst cells = ref<string[]>(['', '', '', '', '', ''])\nconst recoveryCode = ref('')\nconst cellRefs = ref<HTMLInputElement[]>([])\n\nconst submitting = ref(false)\nconst generalError = ref<string | null>(null)\nconst remaining = ref<number | null>(null)\n\nconst totpCode = computed(() => cells.value.join(''))\nconst isValid = computed(() => {\n if (mode.value === 'totp') return totpCode.value.length === 6\n return recoveryCode.value.trim().length > 0\n})\n\nfunction setCellRef(idx: number, el: Element | null): void {\n if (el instanceof HTMLInputElement) cellRefs.value[idx] = el\n}\n\nfunction onCellInput(idx: number, event: Event): void {\n const target = event.target as HTMLInputElement\n // Только цифры; обрезаем до 1 символа.\n const digit = target.value.replace(/\\D/g, '').slice(-1)\n cells.value[idx] = digit\n target.value = digit\n if (digit && idx < cells.value.length - 1) {\n void nextTick(() => cellRefs.value[idx + 1]?.focus())\n }\n if (totpCode.value.length === cells.value.length) {\n void submit()\n }\n}\n\nfunction onCellKeydown(idx: number, event: KeyboardEvent): void {\n if (event.key === 'Backspace' && !cells.value[idx] && idx > 0) {\n void nextTick(() => cellRefs.value[idx - 1]?.focus())\n } else if (event.key === 'ArrowLeft' && idx > 0) {\n cellRefs.value[idx - 1]?.focus()\n event.preventDefault()\n } else if (event.key === 'ArrowRight' && idx < cells.value.length - 1) {\n cellRefs.value[idx + 1]?.focus()\n event.preventDefault()\n }\n}\n\nfunction onPaste(event: ClipboardEvent): void {\n const pasted = event.clipboardData?.getData('text') ?? ''\n const digits = pasted.replace(/\\D/g, '').slice(0, cells.value.length)\n if (digits.length === 0) return\n event.preventDefault()\n for (let i = 0; i < cells.value.length; i++) {\n cells.value[i] = digits[i] ?? ''\n }\n void nextTick(() => {\n cellRefs.value[Math.min(digits.length, cells.value.length - 1)]?.focus()\n if (digits.length === cells.value.length) void submit()\n })\n}\n\nasync function submit(): Promise<void> {\n if (submitting.value || !isValid.value) return\n submitting.value = true\n generalError.value = null\n\n try {\n if (mode.value === 'totp') {\n await auth.twoFactorChallenge(totpCode.value)\n } else {\n const res = await auth.twoFactorRecovery(recoveryCode.value.trim())\n remaining.value = res.remaining\n }\n emit('success')\n } catch (err) {\n if (err instanceof ValidationError) {\n generalError.value = err.firstFieldMessage() ?? 'Неверный код'\n } else if (err instanceof NetworkError) {\n generalError.value = 'Нет соединения с сервером'\n } else if (err instanceof ApiError) {\n generalError.value = err.message || 'Не удалось проверить код'\n } else {\n generalError.value = (err as Error).message\n }\n } finally {\n submitting.value = false\n }\n}\n\nfunction cancel(): void {\n auth.cancelChallenge()\n emit('cancel')\n}\n\nfunction switchMode(): void {\n mode.value = mode.value === 'totp' ? 'recovery' : 'totp'\n generalError.value = null\n}\n</script>\n\n<template>\n <form class=\"admin-auth-card__bd\" novalidate @submit.prevent=\"submit\">\n <UidAlert\n v-if=\"generalError\"\n variant=\"danger\"\n class=\"admin-auth-card__alert\"\n role=\"alert\"\n >\n {{ generalError }}\n </UidAlert>\n <UidAlert\n v-if=\"remaining !== null\"\n variant=\"info\"\n class=\"admin-auth-card__alert\"\n role=\"status\"\n >\n Использован recovery-код. Осталось: {{ remaining }}\n </UidAlert>\n\n <div v-if=\"mode === 'totp'\" class=\"admin-code-input\" @paste=\"onPaste\">\n <input\n v-for=\"(_, idx) in cells\"\n :key=\"idx\"\n :ref=\"(el) => setCellRef(idx, el as Element | null)\"\n :value=\"cells[idx]\"\n type=\"text\"\n inputmode=\"numeric\"\n autocomplete=\"one-time-code\"\n maxlength=\"1\"\n :disabled=\"submitting\"\n :aria-label=\"`Цифра ${idx + 1}`\"\n @input=\"onCellInput(idx, $event)\"\n @keydown=\"onCellKeydown(idx, $event)\"\n />\n </div>\n\n <UidInput\n v-else\n v-model=\"recoveryCode\"\n type=\"text\"\n label=\"Recovery-код\"\n autocomplete=\"one-time-code\"\n :disabled=\"submitting\"\n name=\"recovery-code\"\n />\n\n <UidButton\n type=\"submit\"\n variant=\"primary\"\n size=\"lg\"\n :loading=\"submitting\"\n :disabled=\"submitting || !isValid\"\n >\n {{ submitting ? 'Проверка…' : 'Подтвердить' }}\n </UidButton>\n\n <div class=\"admin-auth-card__row\">\n <button type=\"button\" class=\"admin-auth-card__link\" @click=\"switchMode\">\n <template v-if=\"mode === 'totp'\">Использовать recovery-код</template>\n <template v-else>Вернуться к коду из приложения</template>\n </button>\n <button type=\"button\" class=\"admin-auth-card__link\" @click=\"cancel\">\n Отмена\n </button>\n </div>\n </form>\n</template>\n","<script setup lang=\"ts\">\n/**\n * LoginPage поверх UID design handoff: centered auth-card 400/440 px на\n * `--uid-surface-base`-фоне с corner-actions (theme + locale toggles).\n *\n * Композиция: LoginForm либо TwoFactorForm в зависимости от\n * auth.isChallengePending. Редирект на main завязан на watch\n * (auth.isAuthenticated) — это переживает unmount форм при смене ветки.\n *\n * `?redirect`-query учитывает только относительные пути (защита от\n * open-redirect).\n */\nimport { onMounted, watch } from 'vue'\nimport { useRouter, useRoute } from 'vue-router'\nimport { UidCard } from '@dskripchenko/ui'\nimport { useAuthStore } from '../../stores/auth'\nimport LoginForm from './LoginForm.vue'\nimport TwoFactorForm from './TwoFactorForm.vue'\nimport ThemeToggle from '../shell/widgets/ThemeToggle.vue'\nimport LocaleSwitcher from '../shell/widgets/LocaleSwitcher.vue'\nimport BrandLogo from '../shell/BrandLogo.vue'\n\ninterface Props {\n brandName?: string\n /**\n * Custom mark (если задан — рендерится вместо BrandLogo). Полезно\n * host'у с собственным брендом.\n */\n brandMark?: string | null\n brandLogo?: string | null\n homeRouteName?: string\n redirectQueryKey?: string\n /** URL «Забыли пароль?» — пробрасывается в LoginForm. */\n forgotUrl?: string | null\n /** SSO-link (label + url) — пробрасывается в LoginForm. */\n ssoLinkLabel?: string | null\n ssoUrl?: string | null\n /** Показывать ли theme/locale toggle'ы в углу. */\n showCornerActions?: boolean\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n brandName: 'Laravel Admin',\n brandMark: null,\n brandLogo: null,\n homeRouteName: 'admin.home',\n redirectQueryKey: 'redirect',\n forgotUrl: null,\n ssoLinkLabel: null,\n ssoUrl: null,\n showCornerActions: true,\n})\n\nconst auth = useAuthStore()\nconst router = useRouter()\nconst route = useRoute()\n\nasync function redirectToHome(): Promise<void> {\n const target = route.query[props.redirectQueryKey]\n if (typeof target === 'string' && target.length > 0 && target.startsWith('/')) {\n await router.push(target)\n return\n }\n await router.push({ name: props.homeRouteName })\n}\n\nwatch(\n () => auth.isAuthenticated,\n (next) => {\n if (next) void redirectToHome()\n },\n)\nonMounted(() => {\n if (auth.isAuthenticated) void redirectToHome()\n})\n</script>\n\n<template>\n <div class=\"admin-auth-page\">\n <div v-if=\"showCornerActions\" class=\"admin-auth-page__corner\">\n <ThemeToggle />\n <LocaleSwitcher />\n </div>\n\n <UidCard\n :class=\"['admin-auth-card', auth.isChallengePending ? 'admin-auth-card--wide' : '']\"\n padding=\"none\"\n >\n <div class=\"admin-auth-card__hd\">\n <div\n :class=\"['admin-auth-card__logo', auth.isChallengePending ? 'admin-auth-card__logo--accent' : '']\"\n >\n <img v-if=\"brandLogo && !auth.isChallengePending\" :src=\"brandLogo\" :alt=\"brandName\" />\n <span v-else-if=\"auth.isChallengePending\" aria-hidden=\"true\">🛡</span>\n <span v-else-if=\"brandMark\">{{ brandMark }}</span>\n <BrandLogo v-else :size=\"40\" />\n </div>\n <div class=\"admin-auth-card__title\">\n <template v-if=\"auth.isChallengePending\">Двухфакторная проверка</template>\n <template v-else>{{ brandName }}</template>\n </div>\n <div class=\"admin-auth-card__sub\">\n <template v-if=\"auth.isChallengePending\">\n Введите 6-значный код из приложения-аутентификатора\n </template>\n <template v-else>Войдите, чтобы продолжить работу</template>\n </div>\n </div>\n\n <TwoFactorForm\n v-if=\"auth.isChallengePending\"\n @success=\"() => undefined\"\n @cancel=\"() => undefined\"\n />\n <LoginForm\n v-else\n :forgot-url=\"forgotUrl\"\n :sso-link-label=\"ssoLinkLabel\"\n :sso-url=\"ssoUrl\"\n @success=\"() => undefined\"\n />\n </UidCard>\n </div>\n</template>\n","<script setup lang=\"ts\">\n/**\n * ForgotPasswordPage — простой email-input + submit.\n * Backend: POST /auth/forgotPassword body {email} → отправляет письмо.\n */\nimport { ref } from 'vue'\nimport { useRouter } from 'vue-router'\nimport { Mail } from 'lucide-vue-next'\nimport { UidButton, UidCard, UidIcon, UidInput } from '@dskripchenko/ui'\nimport { adminToast } from '../../stores/toast'\nimport BrandLogo from '../shell/BrandLogo.vue'\n\ninterface Props {\n brandName?: string\n loginRouteName?: string\n}\nwithDefaults(defineProps<Props>(), {\n brandName: 'Laravel Admin',\n loginRouteName: 'admin.login',\n})\n\nconst router = useRouter()\nconst email = ref<string>('')\nconst submitted = ref<boolean>(false)\nconst busy = ref<boolean>(false)\n\nasync function submit(): Promise<void> {\n if (email.value.trim() === '') {\n adminToast.error('Введите email.')\n return\n }\n busy.value = true\n try {\n const { getAdminClient } = await import('../../stores/registry')\n const client = getAdminClient()\n await client.post('/auth/forgotPassword', { email: email.value.trim() })\n submitted.value = true\n } catch {\n // Backend для безопасности не палит существование email — отображаем\n // success в любом случае.\n submitted.value = true\n } finally {\n busy.value = false\n }\n}\n</script>\n\n<template>\n <div class=\"admin-auth-page\">\n <UidCard padding=\"none\" class=\"admin-auth-card\">\n <div class=\"admin-auth-card__hd\">\n <div class=\"admin-auth-card__logo\">\n <BrandLogo :size=\"40\" />\n </div>\n <div class=\"admin-auth-card__title\">Восстановление пароля</div>\n <div class=\"admin-auth-card__sub\">\n {{ submitted\n ? 'Если такой email зарегистрирован — мы отправили письмо со ссылкой на сброс.'\n : 'Введите email — отправим ссылку для сброса пароля.' }}\n </div>\n </div>\n <div class=\"admin-auth-card__body\">\n <form v-if=\"!submitted\" @submit.prevent=\"submit\">\n <UidInput\n v-model=\"email\"\n type=\"email\"\n placeholder=\"you@example.com\"\n autocomplete=\"email\"\n required\n />\n <UidButton\n type=\"submit\"\n variant=\"primary\"\n class=\"admin-auth-card__submit\"\n :loading=\"busy\"\n >\n <template #prepend><UidIcon :icon=\"Mail\" :size=\"14\" /></template>\n Отправить ссылку\n </UidButton>\n </form>\n <UidButton\n variant=\"ghost\"\n class=\"admin-auth-card__back\"\n @click=\"router.push({ name: loginRouteName })\"\n >\n ← Назад ко входу\n </UidButton>\n </div>\n </UidCard>\n </div>\n</template>\n\n<style>\n.admin-auth-card__submit { width: 100%; margin-top: var(--uid-space-sm); }\n.admin-auth-card__back { width: 100%; margin-top: var(--uid-space-sm); }\n</style>\n","<script setup lang=\"ts\">\n/**\n * ResetPasswordPage — форма сброса пароля по token + email из ссылки в письме.\n * URL: /admin/reset-password?token=...&email=... (параметры из query).\n *\n * Backend: POST /auth/resetPassword {token, email, password, password_confirmation}.\n */\nimport { computed, ref } from 'vue'\nimport { useRouter, useRoute } from 'vue-router'\nimport { Check } from 'lucide-vue-next'\nimport { UidButton, UidCard, UidIcon, UidInput } from '@dskripchenko/ui'\nimport { adminToast } from '../../stores/toast'\nimport BrandLogo from '../shell/BrandLogo.vue'\n\ninterface Props {\n loginRouteName?: string\n}\nconst props = withDefaults(defineProps<Props>(), {\n loginRouteName: 'admin.login',\n})\n\nconst router = useRouter()\nconst route = useRoute()\n\nconst token = computed<string>(() => String(route.query.token ?? ''))\nconst email = ref<string>(String(route.query.email ?? ''))\nconst password = ref<string>('')\nconst confirm = ref<string>('')\nconst busy = ref<boolean>(false)\nconst error = ref<string>('')\n\nasync function submit(): Promise<void> {\n error.value = ''\n if (password.value.length < 8) {\n error.value = 'Пароль должен быть не менее 8 символов.'\n return\n }\n if (password.value !== confirm.value) {\n error.value = 'Пароли не совпадают.'\n return\n }\n busy.value = true\n try {\n const { getAdminClient } = await import('../../stores/registry')\n const client = getAdminClient()\n await client.post('/auth/resetPassword', {\n token: token.value,\n email: email.value,\n password: password.value,\n password_confirmation: confirm.value,\n })\n adminToast.success('Пароль обновлён. Войдите с новым паролем.')\n await router.push({ name: props.loginRouteName })\n } catch {\n error.value = 'Не удалось сбросить пароль. Возможно, ссылка устарела.'\n } finally {\n busy.value = false\n }\n}\n</script>\n\n<template>\n <div class=\"admin-auth-page\">\n <UidCard padding=\"none\" class=\"admin-auth-card\">\n <div class=\"admin-auth-card__hd\">\n <div class=\"admin-auth-card__logo\">\n <BrandLogo :size=\"40\" />\n </div>\n <div class=\"admin-auth-card__title\">Новый пароль</div>\n <div class=\"admin-auth-card__sub\">Задайте новый пароль для своего аккаунта.</div>\n </div>\n <div class=\"admin-auth-card__body\">\n <form @submit.prevent=\"submit\">\n <UidInput v-model=\"email\" type=\"email\" placeholder=\"email\" required />\n <UidInput\n v-model=\"password\"\n type=\"password\"\n placeholder=\"Новый пароль (мин. 8)\"\n autocomplete=\"new-password\"\n required\n />\n <UidInput\n v-model=\"confirm\"\n type=\"password\"\n placeholder=\"Повторите пароль\"\n autocomplete=\"new-password\"\n required\n />\n <p v-if=\"error\" class=\"admin-auth-card__error\">{{ error }}</p>\n <UidButton\n type=\"submit\"\n variant=\"primary\"\n class=\"admin-auth-card__submit\"\n :loading=\"busy\"\n >\n <template #prepend><UidIcon :icon=\"Check\" :size=\"14\" /></template>\n Сохранить пароль\n </UidButton>\n </form>\n </div>\n </UidCard>\n </div>\n</template>\n\n<style>\n.admin-auth-card__error {\n color: var(--uid-color-danger, #dc2626);\n font-size: 13px;\n margin: var(--uid-space-xs) 0 0;\n}\n</style>\n","/**\n * useResourceIndexStore — list-page state для одного Resource'а.\n *\n * Поддерживает:\n * - items + pagination meta из envelope payload\n * - filters (typed Record<string, unknown>) — отправляются как query\n * - sort (key + direction)\n * - selection (Set<row-id>) для bulk-actions; tri-state header-checkbox\n * - loading/error состояния (UI рендерит UidSkeleton/UidErrorState)\n *\n * Один store-instance переиспользуется на разных Resource-страницах через\n * `useResourceIndexStore(slug)` с явным `setSlug` — это даёт чистый reset\n * между resource'ами.\n */\n\nimport { defineStore } from 'pinia'\nimport { computed, ref } from 'vue'\nimport { getAdminClient } from './registry'\n\nexport interface IndexMeta {\n page: number\n per_page: number\n total: number\n last_page: number\n}\n\nexport type SortDirection = 'asc' | 'desc' | null\n\nexport interface IndexParams {\n page?: number\n per_page?: number\n sort?: string | null\n direction?: SortDirection\n search?: string | null\n filters?: Record<string, unknown>\n}\n\ninterface ListResponse {\n data: Array<Record<string, unknown>>\n meta: IndexMeta\n}\n\nconst DEFAULT_META: IndexMeta = { page: 1, per_page: 20, total: 0, last_page: 1 }\n\nexport const useResourceIndexStore = defineStore('admin-resource-index', () => {\n /** Текущий resource-slug (urls/users/posts/etc). */\n const slug = ref<string | null>(null)\n\n const items = ref<Array<Record<string, unknown>>>([])\n const meta = ref<IndexMeta>({ ...DEFAULT_META })\n\n const loading = ref(false)\n /**\n * `slowLoading` = true только если loading длится > SLOW_LOADING_DELAY мс.\n * UI использует это для skeleton — чтобы быстрые ответы (<200мс) не\n * мерцали 'data → skeleton → data'. Если запрос быстрый, skeleton\n * никогда не показывается.\n */\n const slowLoading = ref(false)\n const error = ref<Error | null>(null)\n let slowLoadingTimer: ReturnType<typeof setTimeout> | null = null\n const SLOW_LOADING_DELAY = 200\n\n const search = ref<string>('')\n const filters = ref<Record<string, unknown>>({})\n const sortKey = ref<string | null>(null)\n const sortDirection = ref<SortDirection>(null)\n\n /** Set ID-шников выбранных строк (bulk-actions). */\n const selection = ref<Set<string | number>>(new Set())\n\n const isEmpty = computed(() => !loading.value && error.value === null && items.value.length === 0)\n const selectedCount = computed(() => selection.value.size)\n const hasSelection = computed(() => selection.value.size > 0)\n const hasError = computed(() => error.value !== null)\n\n /** Tri-state: 'all' / 'mixed' / 'none' для header-checkbox. */\n const selectionState = computed<'all' | 'mixed' | 'none'>(() => {\n if (selection.value.size === 0) return 'none'\n if (items.value.length === 0) return 'none'\n const allSelected = items.value.every((row) => selection.value.has(rowId(row)))\n return allSelected ? 'all' : 'mixed'\n })\n\n /** Извлекает ID строки. По умолчанию — поле `id`; host может переопределить. */\n function rowId(row: Record<string, unknown>): string | number {\n return (row.id ?? row.key ?? '') as string | number\n }\n\n /**\n * Сменить ресурс — сброс state'а.\n *\n * `loading=true` ставится сразу, чтобы в окне между setSlug() и load() не\n * рендерилась EmptyState (\"Нет данных\") — это вызывало flicker при\n * navigation между Resource'ами.\n */\n function setSlug(next: string | null): void {\n if (slug.value === next) return\n slug.value = next\n reset()\n loading.value = true\n }\n\n function reset(): void {\n items.value = []\n meta.value = { ...DEFAULT_META }\n loading.value = false\n error.value = null\n search.value = ''\n filters.value = {}\n sortKey.value = null\n sortDirection.value = null\n selection.value = new Set()\n }\n\n function buildParams(override: IndexParams = {}): Record<string, unknown> {\n const params: Record<string, unknown> = {\n page: override.page ?? meta.value.page,\n per_page: override.per_page ?? meta.value.per_page,\n }\n // Free-text: backend ждёт `q`. См. HttpFilterParser::searchTerm.\n const ss = override.search ?? search.value\n if (ss) params.q = ss\n\n // Order: массив {column, direction}. Backend читает `order[]` через input('order').\n // Если direction === null → не добавляем order (3-режимная sort: off).\n const sk = override.sort ?? sortKey.value\n const dir = override.direction ?? sortDirection.value\n if (sk && dir !== null) {\n params.order = [{ column: sk, direction: dir }]\n }\n\n // Filters: map-style {column: value} — HttpFilterParser auto-detect режим 1.\n const f = override.filters ?? filters.value\n const filtersMap: Record<string, unknown> = {}\n for (const [k, v] of Object.entries(f)) {\n if (v === null || v === undefined || v === '') continue\n filtersMap[k] = Array.isArray(v) ? v.join(',') : v\n }\n if (Object.keys(filtersMap).length > 0) params.filters = filtersMap\n\n return params\n }\n\n /** Загрузить страницу. Без аргументов — текущие фильтры/сортировка/page. */\n async function load(override: IndexParams = {}): Promise<void> {\n if (!slug.value) {\n throw new Error('useResourceIndexStore.load() called before setSlug()')\n }\n loading.value = true\n error.value = null\n // Debounced flag для skeleton: true только если запрос длится > 200мс.\n if (slowLoadingTimer !== null) clearTimeout(slowLoadingTimer)\n slowLoadingTimer = setTimeout(() => {\n slowLoading.value = true\n }, SLOW_LOADING_DELAY)\n try {\n const client = getAdminClient()\n const body = buildParams(override)\n // Backend ResourceController.search: POST /{slug}/search.\n // Тело — параметры (фильтры/сортировка/пагинация). Возвращает\n // {data, meta:{page,per_page,total,last_page,...}}.\n const res = await client.post<ListResponse>(`/${slug.value}/search`, body)\n items.value = res.data\n meta.value = res.meta\n } catch (err) {\n error.value = err instanceof Error ? err : new Error(String(err))\n throw err\n } finally {\n loading.value = false\n slowLoading.value = false\n if (slowLoadingTimer !== null) {\n clearTimeout(slowLoadingTimer)\n slowLoadingTimer = null\n }\n }\n }\n\n async function setSearch(value: string): Promise<void> {\n search.value = value\n meta.value.page = 1\n await load()\n }\n\n async function setFilter(key: string, value: unknown): Promise<void> {\n if (value === null || value === undefined || value === '') {\n delete filters.value[key]\n } else {\n filters.value[key] = value\n }\n meta.value.page = 1\n await load()\n }\n\n async function clearFilters(): Promise<void> {\n filters.value = {}\n meta.value.page = 1\n await load()\n }\n\n async function setSort(key: string | null, direction: SortDirection = 'asc'): Promise<void> {\n sortKey.value = key\n sortDirection.value = direction\n await load()\n }\n\n /**\n * 3-режимная sort. Click по same key → asc → desc → off (sort=null).\n * Click по другому key → asc.\n */\n async function toggleSort(key: string): Promise<void> {\n if (sortKey.value === key) {\n if (sortDirection.value === 'asc') {\n sortDirection.value = 'desc'\n } else if (sortDirection.value === 'desc') {\n sortKey.value = null\n sortDirection.value = null\n } else {\n sortDirection.value = 'asc'\n }\n } else {\n sortKey.value = key\n sortDirection.value = 'asc'\n }\n await load()\n }\n\n async function setPage(page: number): Promise<void> {\n meta.value.page = page\n await load()\n }\n\n function toggleRow(id: string | number): void {\n const next = new Set(selection.value)\n if (next.has(id)) next.delete(id)\n else next.add(id)\n selection.value = next\n }\n\n /** Toggle: выделить все на странице если что-то не выбрано, иначе очистить. */\n function toggleAllOnPage(): void {\n if (selectionState.value === 'all') {\n selection.value = new Set()\n return\n }\n const next = new Set(selection.value)\n for (const row of items.value) next.add(rowId(row))\n selection.value = next\n }\n\n function clearSelection(): void {\n selection.value = new Set()\n }\n\n /** Проверить выбор конкретной строки. */\n function isSelected(id: string | number): boolean {\n return selection.value.has(id)\n }\n\n return {\n // state\n slug,\n items,\n meta,\n loading,\n slowLoading,\n error,\n search,\n filters,\n sortKey,\n sortDirection,\n selection,\n // getters\n isEmpty,\n hasError,\n hasSelection,\n selectedCount,\n selectionState,\n // actions\n setSlug,\n reset,\n load,\n setSearch,\n setFilter,\n clearFilters,\n setSort,\n toggleSort,\n setPage,\n toggleRow,\n toggleAllOnPage,\n clearSelection,\n isSelected,\n rowId,\n }\n})\n","/**\n * Formatter cell-значений для ResourceIndexPage.\n *\n * Backend-side TableColumn presets:\n * - text → as-is (string).\n * - date → 'd.m.Y' (default).\n * - datetime → 'd.m.Y H:i:s' (default).\n * - money → '{value} {currency}' с decimals.\n * - boolean → trueLabel / falseLabel из meta.\n * - badge → текст; стилизация на UI рендере (через slot или CSS-class).\n * - bytes → human-readable размер.\n * - text → fallback.\n *\n * `auto-format` для колонок без явного preset'а: если значение похоже на ISO\n * datetime (`*_at` или строка с T...Z) — применяется default datetime формат.\n */\n\nexport type CellPreset = 'text' | 'date' | 'datetime' | 'money' | 'boolean' | 'badge' | 'bytes'\n\nexport interface CellMeta {\n format?: string\n currency?: string\n decimals?: number\n trueLabel?: string | null\n falseLabel?: string | null\n [key: string]: unknown\n}\n\nconst DEFAULT_DATETIME = 'd.m.Y H:i:s'\nconst DEFAULT_DATE = 'd.m.Y'\n\nconst ISO_DATETIME_RE = /^\\d{4}-\\d{2}-\\d{2}[T\\s]\\d{2}:\\d{2}/\n\nexport function formatCell(\n value: unknown,\n preset: string | undefined,\n meta: CellMeta = {},\n): string {\n if (value === null || value === undefined) return ''\n\n // Auto-detection ISO datetime для колонок без preset'а.\n if (!preset && typeof value === 'string' && ISO_DATETIME_RE.test(value)) {\n return formatDateString(value, DEFAULT_DATETIME)\n }\n\n switch (preset) {\n case 'date':\n return formatDateString(String(value), meta.format ?? DEFAULT_DATE)\n case 'datetime':\n return formatDateString(String(value), meta.format ?? DEFAULT_DATETIME)\n case 'money':\n return formatMoney(value, meta.currency ?? 'RUB', meta.decimals ?? 2)\n case 'boolean':\n return formatBoolean(value, meta.trueLabel ?? 'Да', meta.falseLabel ?? 'Нет')\n case 'bytes':\n return formatBytes(value)\n default:\n return String(value)\n }\n}\n\n/**\n * PHP-стиль format strings → JS-Date.\n *\n * Поддерживаемые токены:\n * d → 01-31, m → 01-12, Y → 2026, y → 26\n * H → 00-23, h → 12-hour, i → minutes, s → seconds\n * D → Mon-Sun (3-letter), l → full day name, M → Jan, F → January\n * N → 1-7 (ISO weekday), w → 0-6\n * U → Unix timestamp, c → ISO 8601\n */\nfunction formatDateString(input: string, format: string): string {\n const date = new Date(input)\n if (isNaN(date.getTime())) return input\n\n const pad = (n: number, w = 2): string => String(n).padStart(w, '0')\n\n const tokens: Record<string, string> = {\n d: pad(date.getDate()),\n m: pad(date.getMonth() + 1),\n Y: String(date.getFullYear()),\n y: pad(date.getFullYear() % 100),\n H: pad(date.getHours()),\n h: pad(((date.getHours() + 11) % 12) + 1),\n i: pad(date.getMinutes()),\n s: pad(date.getSeconds()),\n U: String(Math.floor(date.getTime() / 1000)),\n c: date.toISOString(),\n N: String(((date.getDay() + 6) % 7) + 1),\n w: String(date.getDay()),\n }\n\n // Замена с учётом escape '\\\\' (PHP: backslash escapes the next char).\n let out = ''\n for (let i = 0; i < format.length; i++) {\n const ch = format[i]\n if (ch === '\\\\' && i + 1 < format.length) {\n out += format[i + 1]\n i++\n continue\n }\n out += tokens[ch] ?? ch\n }\n return out\n}\n\nfunction formatMoney(value: unknown, currency: string, decimals: number): string {\n const n = typeof value === 'number' ? value : Number(value)\n if (isNaN(n)) return String(value)\n return `${n.toFixed(decimals)} ${currency}`\n}\n\nfunction formatBoolean(value: unknown, trueLabel: string, falseLabel: string): string {\n const truthy = value === true || value === 1 || value === '1' || value === 'true'\n return truthy ? trueLabel : falseLabel\n}\n\nfunction formatBytes(value: unknown): string {\n const n = typeof value === 'number' ? value : Number(value)\n if (isNaN(n)) return String(value)\n if (n < 1024) return `${n} B`\n if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)} KB`\n if (n < 1024 * 1024 * 1024) return `${(n / 1024 / 1024).toFixed(1)} MB`\n return `${(n / 1024 / 1024 / 1024).toFixed(1)} GB`\n}\n","/**\n * FilterEditor — render-функция для редактора одного filter'а.\n *\n * Отдельный модуль (не SFC), потому что компонент чисто render-based —\n * выбирает control под filter.type без шаблона и состояния.\n */\nimport { defineComponent, h, type PropType } from 'vue'\n\nexport interface FilterOption {\n value: string | number\n label: string\n}\n\nexport interface FilterDef {\n name: string\n label: string\n type: string\n icon?: string | null\n options?: FilterOption[] | null\n multiple?: boolean\n default?: unknown\n placeholder?: string\n}\n\nexport const FilterEditor = defineComponent({\n name: 'FilterEditor',\n props: {\n filter: { type: Object as PropType<FilterDef>, required: true },\n draft: { type: null as unknown as PropType<unknown>, required: false, default: null as unknown },\n isChecked: {\n type: Function as PropType<(v: string | number) => boolean>,\n required: true,\n },\n },\n emits: ['toggle-option', 'set-draft'],\n setup(props, { emit }) {\n return () => {\n const f = props.filter\n\n // OptionsFilter (single/multi) — single render как radio, multi — checkbox.\n if (f.type === 'options' && f.options && f.options.length > 0) {\n return h(\n 'div',\n { class: 'admin-toolbar__editor admin-toolbar__editor--options' },\n f.options.map((opt) =>\n h(\n 'label',\n {\n key: String(opt.value),\n class: 'admin-toolbar__list-item admin-toolbar__list-item--checkbox',\n },\n [\n h('input', {\n type: f.multiple ? 'checkbox' : 'radio',\n checked: props.isChecked(opt.value),\n onChange: () => emit('toggle-option', opt.value),\n }),\n h('span', null, opt.label),\n ],\n ),\n ),\n )\n }\n\n // DateRangeFilter — два input type=date.\n if (f.type === 'date_range') {\n const v = (props.draft ?? {}) as { from?: string; to?: string }\n return h('div', { class: 'admin-toolbar__editor admin-toolbar__editor--dates' }, [\n h('input', {\n type: 'date',\n value: v.from ?? '',\n class: 'admin-toolbar__input',\n placeholder: 'От',\n onChange: (e: Event) =>\n emit('set-draft', { ...v, from: (e.target as HTMLInputElement).value }),\n }),\n h('input', {\n type: 'date',\n value: v.to ?? '',\n class: 'admin-toolbar__input',\n placeholder: 'До',\n onChange: (e: Event) =>\n emit('set-draft', { ...v, to: (e.target as HTMLInputElement).value }),\n }),\n ])\n }\n\n // TrashedFilter — tri-state (without / with / only).\n if (f.type === 'trashed') {\n const options = [\n { value: 'without', label: 'Без удалённых' },\n { value: 'with', label: 'С удалёнными' },\n { value: 'only', label: 'Только удалённые' },\n ]\n return h(\n 'div',\n { class: 'admin-toolbar__editor admin-toolbar__editor--options' },\n options.map((opt) =>\n h(\n 'label',\n {\n key: opt.value,\n class: 'admin-toolbar__list-item admin-toolbar__list-item--checkbox',\n },\n [\n h('input', {\n type: 'radio',\n checked: props.draft === opt.value,\n onChange: () => emit('set-draft', opt.value),\n }),\n h('span', null, opt.label),\n ],\n ),\n ),\n )\n }\n\n // SwitcherFilter — yes/no.\n if (f.type === 'switcher') {\n return h('div', { class: 'admin-toolbar__editor' }, [\n h('label', { class: 'admin-toolbar__list-item admin-toolbar__list-item--checkbox' }, [\n h('input', {\n type: 'radio',\n checked: props.draft === true,\n onChange: () => emit('set-draft', true),\n }),\n h('span', null, 'Да'),\n ]),\n h('label', { class: 'admin-toolbar__list-item admin-toolbar__list-item--checkbox' }, [\n h('input', {\n type: 'radio',\n checked: props.draft === false,\n onChange: () => emit('set-draft', false),\n }),\n h('span', null, 'Нет'),\n ]),\n ])\n }\n\n // Default: text input (input / select_from_model / unknown type).\n return h('input', {\n type: 'text',\n value: props.draft ?? '',\n class: 'admin-toolbar__input',\n placeholder: f.placeholder ?? f.label,\n onChange: (e: Event) => emit('set-draft', (e.target as HTMLInputElement).value),\n })\n }\n },\n})\n\nexport default FilterEditor\n","<script setup lang=\"ts\">\n/**\n * AdminFilterToolbar — двухстрочный toolbar над таблицей Resource'а:\n *\n * Row 1 (filter bar): search | active-chips, inactive-buttons | + Filter | Сбросить\n * Row 2 (action bar): Группировать | Колонки | Сохранить\n *\n * Конфигурируется через manifest:\n * - filters[] — Resource->filters() (type/options/multiple/icon/...)\n * - columns[] — Resource->columns() (key/label/groupable/...)\n * - searchable[] — список колонок поиска (placeholder подставляется\n * автоматически: \"Поиск по {label}…\")\n *\n * UI-фолбэк: для каждого filter-type (options / date_range / switcher /\n * input / select_from_model / trashed) рендерим универсальный popover-\n * редактор, чтобы Resource без custom-UI всё равно получил рабочий toolbar.\n */\nimport { computed, ref, watch } from 'vue'\nimport {\n Bookmark,\n Check,\n Columns,\n LayoutGrid,\n Plus,\n RotateCcw,\n Search,\n X,\n} from 'lucide-vue-next'\nimport { UidButton, UidIcon, UidMenu } from '@dskripchenko/ui'\nimport { resolveIcon } from '../shell/iconRegistry'\nimport { FilterEditor, type FilterDef, type FilterOption } from './FilterEditor'\n\ninterface ColumnDef {\n key?: string\n name?: string\n label?: string\n groupable?: boolean\n hidden?: boolean\n}\n\ninterface Props {\n search: string\n searchPlaceholder?: string\n filters: FilterDef[]\n values: Record<string, unknown>\n columns: ColumnDef[]\n /** Group-by column key (если выбран). */\n groupBy?: string | null\n /** Visibility map для column-toggle. true = видна. */\n columnVisibility?: Record<string, boolean>\n /** Показывать ли \"Сохранить\" (saved-views) — host управляет наличием feature. */\n enableSavedViews?: boolean\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n searchPlaceholder: 'Поиск…',\n groupBy: null,\n columnVisibility: () => ({}),\n enableSavedViews: true,\n})\n\nconst emit = defineEmits<{\n 'update:search': [value: string]\n 'apply-filter': [name: string, value: unknown]\n 'reset': []\n 'group-by': [column: string | null]\n 'columns-visibility': [next: Record<string, boolean>]\n 'save-view': [label: string]\n}>()\n\n// === Search local state (commit on Enter / blur) ===\nconst localSearch = ref<string>(props.search)\nwatch(\n () => props.search,\n (v) => {\n localSearch.value = v\n },\n)\nfunction commitSearch(): void {\n if (localSearch.value !== props.search) emit('update:search', localSearch.value)\n}\n\n// === Active / inactive filter partitioning ===\nfunction hasValue(v: unknown): boolean {\n if (v === null || v === undefined || v === '') return false\n if (Array.isArray(v) && v.length === 0) return false\n if (typeof v === 'object' && !Array.isArray(v)) {\n const obj = v as Record<string, unknown>\n return Object.values(obj).some((x) => x !== null && x !== '' && x !== undefined)\n }\n return true\n}\n\nconst activeFilters = computed(() =>\n props.filters.filter((f) => hasValue(props.values[f.name])),\n)\nconst inactiveFilters = computed(() =>\n props.filters.filter((f) => !hasValue(props.values[f.name])),\n)\n\nconst VISIBLE_LIMIT = 4\nconst revealed = ref<Set<string>>(new Set())\nconst inactiveVisible = computed(() =>\n inactiveFilters.value.filter(\n (f, i) => revealed.value.has(f.name) || i < VISIBLE_LIMIT,\n ),\n)\nconst inactiveHidden = computed(() =>\n inactiveFilters.value.filter(\n (f, i) => !revealed.value.has(f.name) && i >= VISIBLE_LIMIT,\n ),\n)\nfunction reveal(name: string): void {\n const next = new Set(revealed.value)\n next.add(name)\n revealed.value = next\n}\n\nconst hasActiveAnything = computed<boolean>(\n () => props.search !== '' || activeFilters.value.length > 0,\n)\n\nfunction clearFilter(name: string): void {\n emit('apply-filter', name, null)\n}\n\n// === Filter chip label formatting ===\nfunction chipText(f: FilterDef): string {\n const v = props.values[f.name]\n if (f.options && f.options.length > 0) {\n const arr = Array.isArray(v) ? v : [v]\n const labels = arr.map(\n (val) => f.options?.find((o) => String(o.value) === String(val))?.label ?? String(val),\n )\n return `${f.label}: ${labels.join(', ')}`\n }\n if (f.type === 'date_range' && v && typeof v === 'object') {\n const r = v as { from?: string; to?: string }\n return `${f.label}: ${r.from ?? ''} – ${r.to ?? ''}`\n }\n if (f.type === 'switcher') {\n return `${f.label}: ${v ? 'да' : 'нет'}`\n }\n return `${f.label}: ${String(v)}`\n}\n\n// === Multi-select working-copy (буфер до Apply) ===\nconst draftValues = ref<Record<string, unknown>>({})\nfunction getDraft(name: string): unknown {\n if (!(name in draftValues.value)) {\n draftValues.value[name] = props.values[name] ?? null\n }\n return draftValues.value[name]\n}\nfunction setDraft(name: string, value: unknown): void {\n draftValues.value = { ...draftValues.value, [name]: value }\n}\nfunction applyDraft(name: string, close: () => void): void {\n emit('apply-filter', name, draftValues.value[name] ?? null)\n close()\n}\nfunction toggleOption(name: string, value: FilterOption['value'], multiple: boolean): void {\n if (!multiple) {\n setDraft(name, value)\n return\n }\n const cur = getDraft(name)\n const arr = Array.isArray(cur) ? [...(cur as Array<string | number>)] : []\n const idx = arr.findIndex((x) => String(x) === String(value))\n if (idx >= 0) arr.splice(idx, 1)\n else arr.push(value)\n setDraft(name, arr)\n}\nfunction isOptionChecked(name: string, value: FilterOption['value']): boolean {\n const cur = getDraft(name)\n if (Array.isArray(cur)) return cur.some((x) => String(x) === String(value))\n return cur !== null && cur !== undefined && String(cur) === String(value)\n}\n\n// === Group-by + Columns + Saved-view ===\nconst groupableColumns = computed<ColumnDef[]>(() =>\n props.columns.filter((c) => c.groupable === true && (c.key ?? c.name)),\n)\nfunction setGroupBy(col: string | null, close: () => void): void {\n emit('group-by', col)\n close()\n}\n\nfunction colKey(c: ColumnDef): string {\n return String(c.key ?? c.name ?? '')\n}\nfunction colLabel(c: ColumnDef): string {\n return String(c.label ?? c.name ?? c.key ?? '')\n}\nfunction isVisible(c: ColumnDef): boolean {\n const k = colKey(c)\n if (k in props.columnVisibility) return props.columnVisibility[k]\n return true\n}\nfunction toggleVisibility(c: ColumnDef): void {\n const k = colKey(c)\n emit('columns-visibility', { ...props.columnVisibility, [k]: !isVisible(c) })\n}\n\nconst newViewLabel = ref<string>('')\nfunction saveView(close: () => void): void {\n if (newViewLabel.value.trim() === '') return\n emit('save-view', newViewLabel.value.trim())\n newViewLabel.value = ''\n close()\n}\n\nfunction iconFor(name: string | null | undefined) {\n return resolveIcon(name) ?? null\n}\n</script>\n\n<template>\n <div class=\"admin-toolbar\">\n <!-- Row 1: search + filters -->\n <div class=\"admin-toolbar__row admin-toolbar__row--filters\">\n <label class=\"admin-toolbar__search\">\n <UidIcon :icon=\"Search\" :size=\"14\" class=\"admin-toolbar__search-icon\" />\n <input\n v-model=\"localSearch\"\n type=\"search\"\n :placeholder=\"searchPlaceholder\"\n class=\"admin-toolbar__search-input\"\n @keydown.enter=\"commitSearch\"\n @blur=\"commitSearch\"\n />\n </label>\n\n <span v-if=\"filters.length > 0\" class=\"admin-toolbar__divider\" />\n\n <!-- Active filter chips: filled style + X для сброса -->\n <UidMenu\n v-for=\"f in activeFilters\"\n :key=\"`active-${f.name}`\"\n >\n <template #trigger>\n <button\n type=\"button\"\n class=\"admin-toolbar__chip admin-toolbar__chip--active\"\n >\n <UidIcon\n v-if=\"iconFor(f.icon) !== null\"\n :icon=\"(iconFor(f.icon) as never)\"\n :size=\"14\"\n />\n <span class=\"admin-toolbar__chip-text\">{{ chipText(f) }}</span>\n <span\n role=\"button\"\n tabindex=\"0\"\n aria-label=\"Сбросить фильтр\"\n class=\"admin-toolbar__chip-x\"\n @click.stop=\"clearFilter(f.name)\"\n @keydown.enter.stop=\"clearFilter(f.name)\"\n >\n <UidIcon :icon=\"X\" :size=\"12\" />\n </span>\n </button>\n </template>\n <div\n class=\"admin-toolbar__popover\"\n @keydown.stop\n >\n <FilterEditor\n :filter=\"f\"\n :draft=\"(getDraft(f.name) as never)\"\n :is-checked=\"(v) => isOptionChecked(f.name, v)\"\n @toggle-option=\"(v) => toggleOption(f.name, v, f.multiple ?? false)\"\n @set-draft=\"(v) => setDraft(f.name, v)\"\n />\n <div class=\"admin-toolbar__popover-actions\">\n <UidButton size=\"sm\" variant=\"ghost\" @click=\"setDraft(f.name, null)\">\n Очистить\n </UidButton>\n <UidButton\n size=\"sm\"\n variant=\"primary\"\n @click=\"applyDraft(f.name, () => undefined)\"\n >\n Применить\n </UidButton>\n </div>\n </div>\n </UidMenu>\n\n <!-- Inactive filter buttons: outlined, открывают popover -->\n <UidMenu\n v-for=\"f in inactiveVisible\"\n :key=\"`inactive-${f.name}`\"\n >\n <template #trigger>\n <button\n type=\"button\"\n class=\"admin-toolbar__chip\"\n >\n <UidIcon\n v-if=\"iconFor(f.icon) !== null\"\n :icon=\"(iconFor(f.icon) as never)\"\n :size=\"14\"\n />\n <span class=\"admin-toolbar__chip-text\">{{ f.label }}</span>\n </button>\n </template>\n <div\n class=\"admin-toolbar__popover\"\n @keydown.stop\n >\n <FilterEditor\n :filter=\"f\"\n :draft=\"(getDraft(f.name) as never)\"\n :is-checked=\"(v) => isOptionChecked(f.name, v)\"\n @toggle-option=\"(v) => toggleOption(f.name, v, f.multiple ?? false)\"\n @set-draft=\"(v) => setDraft(f.name, v)\"\n />\n <div class=\"admin-toolbar__popover-actions\">\n <UidButton size=\"sm\" variant=\"ghost\" @click=\"setDraft(f.name, null)\">\n Очистить\n </UidButton>\n <UidButton\n size=\"sm\"\n variant=\"primary\"\n @click=\"applyDraft(f.name, () => undefined)\"\n >\n Применить\n </UidButton>\n </div>\n </div>\n </UidMenu>\n\n <!-- + Filter dropdown с скрытыми filter'ами -->\n <UidMenu v-if=\"inactiveHidden.length > 0\">\n <template #trigger>\n <button type=\"button\" class=\"admin-toolbar__chip\">\n <UidIcon :icon=\"Plus\" :size=\"14\" />\n <span class=\"admin-toolbar__chip-text\">Filter</span>\n </button>\n </template>\n <div class=\"admin-toolbar__popover admin-toolbar__popover--list\" @keydown.stop>\n <button\n v-for=\"f in inactiveHidden\"\n :key=\"f.name\"\n type=\"button\"\n role=\"menuitem\"\n class=\"admin-toolbar__list-item\"\n @click=\"reveal(f.name)\"\n >\n <UidIcon\n v-if=\"iconFor(f.icon) !== null\"\n :icon=\"(iconFor(f.icon) as never)\"\n :size=\"14\"\n />\n {{ f.label }}\n </button>\n </div>\n </UidMenu>\n\n <span class=\"admin-toolbar__spacer\" />\n\n <UidButton\n v-if=\"hasActiveAnything\"\n variant=\"ghost\"\n size=\"md\"\n @click=\"emit('reset')\"\n >\n <template #prepend><UidIcon :icon=\"RotateCcw\" :size=\"14\" /></template>\n Сбросить\n </UidButton>\n </div>\n\n <!-- Row 2: actions (группировать / колонки / сохранить) -->\n <div\n v-if=\"groupableColumns.length > 0 || columns.length > 0 || enableSavedViews\"\n class=\"admin-toolbar__row admin-toolbar__row--actions\"\n >\n <!-- Группировать -->\n <UidMenu v-if=\"groupableColumns.length > 0\">\n <template #trigger>\n <button type=\"button\" class=\"admin-toolbar__chip\">\n <UidIcon :icon=\"LayoutGrid\" :size=\"14\" />\n <span class=\"admin-toolbar__chip-text\">\n {{ groupBy\n ? `Группа: ${colLabel(columns.find((c) => colKey(c) === groupBy) ?? {})}`\n : 'Группировать' }}\n </span>\n </button>\n </template>\n <div class=\"admin-toolbar__popover admin-toolbar__popover--list\" @keydown.stop>\n <button\n type=\"button\"\n role=\"menuitem\"\n class=\"admin-toolbar__list-item\"\n @click=\"setGroupBy(null, () => undefined)\"\n >\n <UidIcon v-if=\"!groupBy\" :icon=\"Check\" :size=\"14\" />\n <span>Без группировки</span>\n </button>\n <button\n v-for=\"c in groupableColumns\"\n :key=\"colKey(c)\"\n type=\"button\"\n role=\"menuitem\"\n class=\"admin-toolbar__list-item\"\n @click=\"setGroupBy(colKey(c), () => undefined)\"\n >\n <UidIcon v-if=\"groupBy === colKey(c)\" :icon=\"Check\" :size=\"14\" />\n <span>{{ colLabel(c) }}</span>\n </button>\n </div>\n </UidMenu>\n\n <!-- Колонки -->\n <UidMenu v-if=\"columns.length > 0\">\n <template #trigger>\n <button type=\"button\" class=\"admin-toolbar__chip\">\n <UidIcon :icon=\"Columns\" :size=\"14\" />\n <span class=\"admin-toolbar__chip-text\">Колонки</span>\n </button>\n </template>\n <div class=\"admin-toolbar__popover admin-toolbar__popover--list\" @keydown.stop>\n <label\n v-for=\"c in columns.filter((col) => colKey(col) !== '')\"\n :key=\"colKey(c)\"\n class=\"admin-toolbar__list-item admin-toolbar__list-item--checkbox\"\n >\n <input\n type=\"checkbox\"\n :checked=\"isVisible(c)\"\n @change=\"toggleVisibility(c)\"\n />\n <span>{{ colLabel(c) }}</span>\n </label>\n </div>\n </UidMenu>\n\n <!-- Сохранить (saved views) -->\n <UidMenu v-if=\"enableSavedViews\">\n <template #trigger>\n <button type=\"button\" class=\"admin-toolbar__chip\">\n <UidIcon :icon=\"Bookmark\" :size=\"14\" />\n <span class=\"admin-toolbar__chip-text\">Сохранить</span>\n </button>\n </template>\n <div class=\"admin-toolbar__popover\" @keydown.stop>\n <input\n v-model=\"newViewLabel\"\n type=\"text\"\n placeholder=\"Название view\"\n class=\"admin-toolbar__input\"\n @keydown.enter=\"saveView(() => undefined)\"\n />\n <div class=\"admin-toolbar__popover-actions\">\n <UidButton\n size=\"sm\"\n variant=\"primary\"\n :disabled=\"newViewLabel.trim() === ''\"\n @click=\"saveView(() => undefined)\"\n >\n Сохранить view\n </UidButton>\n </div>\n </div>\n </UidMenu>\n </div>\n </div>\n</template>\n\n<style>\n.admin-toolbar {\n display: flex;\n flex-direction: column;\n gap: var(--uid-space-xs);\n padding: var(--uid-space-sm) var(--uid-space-md);\n border: 1px solid var(--uid-border-subtle);\n background: var(--uid-surface-raised);\n border-radius: var(--uid-radius-lg) var(--uid-radius-lg) 0 0;\n border-bottom: 0;\n margin-top: var(--uid-space-md);\n}\n\n.admin-toolbar__row {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--uid-space-xs);\n}\n\n.admin-toolbar__divider {\n width: 1px;\n height: 22px;\n background: var(--uid-border-subtle);\n flex: none;\n margin: 0 var(--uid-space-2xs);\n}\n\n.admin-toolbar__spacer { flex: 1; }\n\n/* Search input */\n.admin-toolbar__search {\n position: relative;\n display: inline-flex;\n align-items: center;\n flex: 1 1 200px;\n max-width: 360px;\n height: 32px;\n padding: 0 var(--uid-space-sm);\n border: 1px solid var(--uid-border-subtle);\n background: var(--uid-surface-base);\n border-radius: var(--uid-radius-md);\n gap: var(--uid-space-2xs);\n}\n.admin-toolbar__search:focus-within {\n border-color: var(--uid-accent);\n outline: 2px solid color-mix(in srgb, var(--uid-accent) 18%, transparent);\n}\n.admin-toolbar__search-icon { color: var(--uid-text-tertiary); flex: none; }\n.admin-toolbar__search-input {\n flex: 1;\n height: 100%;\n border: 0;\n outline: none;\n background: transparent;\n font: inherit;\n font-size: 13px;\n color: var(--uid-text-primary);\n}\n.admin-toolbar__search-input::placeholder { color: var(--uid-text-tertiary); }\n\n/* Chip / button (общая база для active/inactive) */\n.admin-toolbar__chip {\n display: inline-flex;\n align-items: center;\n gap: var(--uid-space-2xs);\n height: 32px;\n padding: 0 var(--uid-space-sm);\n border: 1px solid var(--uid-border-subtle);\n background: var(--uid-surface-base);\n border-radius: var(--uid-radius-md);\n color: var(--uid-text-secondary);\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: background var(--uid-duration-fast, 120ms) var(--uid-ease-out, ease),\n border-color var(--uid-duration-fast, 120ms) var(--uid-ease-out, ease),\n color var(--uid-duration-fast, 120ms) var(--uid-ease-out, ease);\n}\n.admin-toolbar__chip:hover {\n background: var(--uid-color-surface-hover, var(--uid-border-subtle));\n color: var(--uid-text-primary);\n}\n.admin-toolbar__chip--active {\n background: color-mix(in srgb, var(--uid-accent) 12%, transparent);\n border-color: color-mix(in srgb, var(--uid-accent) 35%, transparent);\n color: var(--uid-accent);\n}\n.admin-toolbar__chip--active:hover {\n background: color-mix(in srgb, var(--uid-accent) 18%, transparent);\n color: var(--uid-accent);\n}\n.admin-toolbar__chip-text {\n white-space: nowrap;\n max-width: 240px;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.admin-toolbar__chip-x {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 16px;\n height: 16px;\n border-radius: 50%;\n cursor: pointer;\n margin-left: var(--uid-space-2xs);\n}\n.admin-toolbar__chip-x:hover {\n background: color-mix(in srgb, var(--uid-accent) 25%, transparent);\n}\n\n/* Popover content */\n.admin-toolbar__popover {\n display: flex;\n flex-direction: column;\n gap: var(--uid-space-sm);\n padding: var(--uid-space-sm);\n min-width: 220px;\n max-width: 320px;\n}\n.admin-toolbar__popover--list {\n padding: var(--uid-space-2xs);\n gap: 0;\n}\n.admin-toolbar__popover-actions {\n display: flex;\n justify-content: flex-end;\n gap: var(--uid-space-2xs);\n border-top: 1px solid var(--uid-border-subtle);\n padding-top: var(--uid-space-sm);\n}\n.admin-toolbar__list-item {\n display: flex;\n align-items: center;\n gap: var(--uid-space-2xs);\n padding: var(--uid-space-2xs) var(--uid-space-sm);\n border-radius: var(--uid-radius-sm);\n cursor: pointer;\n background: transparent;\n border: 0;\n font-size: 13px;\n text-align: left;\n color: var(--uid-text-primary);\n}\n.admin-toolbar__list-item:hover { background: var(--uid-color-surface-hover, var(--uid-border-subtle)); }\n.admin-toolbar__list-item--checkbox { cursor: pointer; }\n.admin-toolbar__editor { display: flex; flex-direction: column; gap: var(--uid-space-2xs); }\n.admin-toolbar__editor--dates { gap: var(--uid-space-xs); }\n.admin-toolbar__input {\n height: 32px;\n padding: 0 var(--uid-space-sm);\n border: 1px solid var(--uid-border-subtle);\n background: var(--uid-surface-base);\n border-radius: var(--uid-radius-md);\n color: var(--uid-text-primary);\n font-size: 13px;\n outline: none;\n}\n.admin-toolbar__input:focus {\n border-color: var(--uid-accent);\n outline: 2px solid color-mix(in srgb, var(--uid-accent) 18%, transparent);\n}\n</style>\n","<script setup lang=\"ts\">\n/**\n * InlineEditCell — обёртка над текстом cell'а с double-click → input.\n *\n * Backend контракт: POST /{slug}/inlineUpdate body {id, column, value}.\n * Резолв правил валидации backend делает на стороне TableColumn->editable.\n *\n * Поведение:\n * - Idle: рендерит текст (через slot default).\n * - Edit: input (text) с автофокусом, Enter — save, Esc/Blur — cancel.\n * - Saving: отключённый input, статус.\n */\nimport { nextTick, ref } from 'vue'\nimport { adminToast } from '../../stores/toast'\n\ninterface Props {\n resourceSlug: string\n rowId: string | number\n column: string\n value: unknown\n /** Если false — двойной клик ничего не делает (read-only cell). */\n editable?: boolean\n}\nconst props = withDefaults(defineProps<Props>(), {\n editable: true,\n})\n\nconst emit = defineEmits<{\n saved: [value: unknown]\n}>()\n\nconst editing = ref<boolean>(false)\nconst draft = ref<string>('')\nconst saving = ref<boolean>(false)\nconst inputRef = ref<HTMLInputElement | null>(null)\n\nasync function startEdit(): Promise<void> {\n if (!props.editable || saving.value) return\n draft.value = props.value === null || props.value === undefined ? '' : String(props.value)\n editing.value = true\n await nextTick()\n inputRef.value?.focus()\n inputRef.value?.select()\n}\n\nfunction cancel(): void {\n editing.value = false\n}\n\nasync function commit(): Promise<void> {\n if (!editing.value || saving.value) return\n // Без изменений — просто закрываем.\n if (draft.value === String(props.value ?? '')) {\n editing.value = false\n return\n }\n saving.value = true\n try {\n const { getAdminClient } = await import('../../stores/registry')\n const client = getAdminClient()\n await client.post(`/${props.resourceSlug}/inlineUpdate`, {\n id: props.rowId,\n column: props.column,\n value: draft.value,\n })\n emit('saved', draft.value)\n editing.value = false\n } catch (err) {\n if (typeof console !== 'undefined') console.error('[admin] inline-update failed:', err)\n adminToast.error(`Не удалось обновить «${props.column}».`)\n } finally {\n saving.value = false\n }\n}\n\nfunction onKeydown(e: KeyboardEvent): void {\n if (e.key === 'Enter') {\n e.preventDefault()\n void commit()\n } else if (e.key === 'Escape') {\n e.preventDefault()\n cancel()\n }\n}\n</script>\n\n<template>\n <span\n v-if=\"!editing\"\n :class=\"['admin-inline-edit', { 'admin-inline-edit--editable': editable }]\"\n :title=\"editable ? 'Двойной клик для редактирования' : undefined\"\n @dblclick.stop=\"startEdit\"\n >\n <slot>{{ value }}</slot>\n </span>\n <input\n v-else\n ref=\"inputRef\"\n v-model=\"draft\"\n type=\"text\"\n class=\"admin-inline-edit__input\"\n :disabled=\"saving\"\n @keydown=\"onKeydown\"\n @blur=\"commit\"\n @click.stop\n />\n</template>\n\n<style>\n.admin-inline-edit {\n display: inline-block;\n max-width: 100%;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n vertical-align: middle;\n}\n.admin-inline-edit--editable {\n cursor: text;\n border-radius: 3px;\n transition: background 120ms ease;\n}\n.admin-inline-edit--editable:hover {\n background: color-mix(in srgb, var(--uid-accent) 8%, transparent);\n}\n.admin-inline-edit__input {\n width: 100%;\n height: 26px;\n padding: 0 6px;\n border: 1px solid var(--uid-accent);\n background: var(--uid-surface-base);\n border-radius: var(--uid-radius-sm);\n outline: 2px solid color-mix(in srgb, var(--uid-accent) 18%, transparent);\n font: inherit;\n font-size: 13px;\n color: var(--uid-text-primary);\n}\n</style>\n","<script setup lang=\"ts\">\n/**\n * ResourceIndexPage — list-screen для одного Resource'а из manifest'а.\n * Архитектура по docs/design_handoff_laravel_admin/screens-shell.jsx (Resource List).\n *\n * Композиция:\n * - Page header (title + count + actions cluster)\n * - Filter bar с search + chips\n * - Bulk toolbar (заменяет filter bar при selectedCount > 0)\n * - UidTable с manifest.columns\n * - States: loading (UidSkeleton ×8) / empty (UidEmptyState) / error (UidErrorState)\n * - UidPagination внизу\n *\n * Host рендерит page через router. resource-slug приходит из props (либо\n * из route.params).\n */\nimport { computed, nextTick, onMounted, onUnmounted, ref, watch } from 'vue'\nimport { useRouter } from 'vue-router'\nimport {\n Bookmark,\n ChevronDown,\n Eye,\n GripVertical,\n MoreHorizontal,\n Pencil,\n Plus,\n RotateCcw,\n Trash2,\n Upload,\n} from 'lucide-vue-next'\nimport {\n UidButton,\n UidEmptyState,\n UidErrorState,\n UidIcon,\n UidMenu,\n UidMenuItem,\n UidPagination,\n UidSkeleton,\n UidTable,\n type UidTableColumn,\n} from '@dskripchenko/ui'\nimport { useResourceIndexStore } from '../../stores/resourceIndex'\nimport { useManifestStore } from '../../stores/manifest'\nimport { useNavigationStore } from '../../stores/navigation'\nimport { formatCell, type CellMeta } from './cellFormat'\nimport AdminFilterToolbar from './AdminFilterToolbar.vue'\nimport InlineEditCell from './InlineEditCell.vue'\nimport { adminToast } from '../../stores/toast'\nimport { useI18nStore } from '../../stores/i18n'\n\nconst i18n = useI18nStore()\n/**\n * Локальная обёртка над t() с graceful fallback на ru-string.\n * Это позволяет постепенный sweep: пока bootstrap.translations не наполнен,\n * UI показывает ru-defaults; когда host публикует lang-bag — подменяется\n * на переводы.\n */\nconst tt = (key: string, fallback: string, replace?: Record<string, string | number>): string =>\n i18n.has(key) ? i18n.t(key, replace) : fallback\n\ninterface Props {\n /** Slug ресурса (users/articles/etc). */\n slug: string\n /** Заголовок страницы. Если не задан — берётся из manifest'а. */\n title?: string | null\n /** Подпись под заголовком (например \"Аналитика контента\"). */\n subtitle?: string | null\n /** Текст primary-кнопки «Создать». */\n createLabel?: string\n /** Имя router-route для action «Создать». */\n createRouteName?: string | null\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n title: null,\n subtitle: null,\n createLabel: 'Создать',\n createRouteName: null,\n})\n\nconst emit = defineEmits<{\n /** Bulk-action triggered с текущим Set'ом id. */\n 'bulk-action': [action: string, ids: Array<string | number>]\n /** Click на row — host решает (push edit / open view). */\n 'row-click': [row: Record<string, unknown>]\n /** Header-action: import — host вешает обработчик загрузки CSV/JSON. */\n 'import': []\n /** Header more-menu action — произвольный ключ из additional-items. */\n 'header-action': [action: string]\n}>()\n\nconst index = useResourceIndexStore()\nconst manifest = useManifestStore()\nconst nav = useNavigationStore()\nconst router = useRouter()\n\nconst resourceMeta = computed(() => manifest.getResource(props.slug))\n\nconst displayTitle = computed(\n () => props.title ?? resourceMeta.value?.label ?? props.slug,\n)\n\n/**\n * Auto-derive create route name. Резервный вариант — стандартный pattern\n * из router/builder.ts (`admin.resource.{slug}.create`). Кнопка \"Создать\"\n * рендерится если route действительно зарегистрирован — у read-only\n * Resource'а его не будет (backend не отдаст create permission).\n */\nconst resolvedCreateRouteName = computed<string | null>(() => {\n if (props.createRouteName !== null) {\n return router.hasRoute(props.createRouteName) ? props.createRouteName : null\n }\n const candidate = `admin.resource.${props.slug}.create`\n return router.hasRoute(candidate) ? candidate : null\n})\n\n/**\n * Header actions из manifest.actions — Resource->actions() в backend.\n * Каждый node имеет {key, label, icon?, confirm?, ...}. Рендерятся в\n * more-menu (...). По клику вызываем onCustomAction → POST на\n * /{slug}/action/{key}.\n */\ninterface HeaderAction {\n key: string\n label: string\n confirm?: string\n icon?: string\n}\nconst headerActions = computed<HeaderAction[]>(() => {\n const raw = (resourceMeta.value?.actions ?? []) as Array<Record<string, unknown>>\n return raw\n .map((a) => ({\n key: String(a.key ?? a.name ?? ''),\n label: String(a.label ?? a.name ?? a.key ?? ''),\n confirm: typeof a.confirm === 'string' ? a.confirm : undefined,\n icon: typeof a.icon === 'string' ? a.icon : undefined,\n }))\n .filter((a) => a.key !== '' && a.label !== '')\n})\n\nasync function onCustomAction(action: HeaderAction): Promise<void> {\n if (action.confirm && !window.confirm(action.confirm)) return\n emit('header-action', action.key)\n try {\n nav.start()\n const { getAdminClient } = await import('../../stores/registry')\n const client = getAdminClient()\n // Backend контракт: POST /{slug}/action body {key, ids[], payload?}.\n // Action резолвится через Resource->actions() по name.\n const result = await client.post<{ affected?: number; message?: string }>(\n `/${props.slug}/action`,\n {\n key: action.key,\n ids: [...index.selection],\n },\n )\n await index.load().catch(() => undefined)\n adminToast.success(\n result?.message ?? `Action «${action.label}» применён к ${result?.affected ?? 0} записям.`,\n )\n } catch (err) {\n if (typeof console !== 'undefined') console.error('[admin] header-action failed:', err)\n adminToast.error(`Не удалось выполнить action «${action.label}».`)\n } finally {\n nav.end()\n }\n}\n\n/**\n * Export — POST /{slug}/export?format=csv|json|xlsx|pdf. Backend\n * ExporterRegistry резолвит format. Ответ blob, скачиваем через <a download>.\n *\n * Доступные форматы зависят от установленных composer-пакетов:\n * - csv / json — всегда (без deps)\n * - xlsx — openspout/openspout\n * - pdf — mpdf/mpdf или dompdf/dompdf\n */\nasync function onExport(format: 'csv' | 'json' | 'xlsx' | 'pdf' = 'csv'): Promise<void> {\n emit('header-action', 'export')\n try {\n nav.start()\n const { getAdminClient } = await import('../../stores/registry')\n const client = getAdminClient()\n const blob = await client.post<Blob>(\n `/${props.slug}/export`,\n { format, filters: index.filters, search: index.search },\n { responseType: 'blob' as const },\n )\n const url = URL.createObjectURL(blob as unknown as Blob)\n const a = document.createElement('a')\n a.href = url\n a.download = `${props.slug}-${new Date().toISOString().slice(0, 10)}.${format}`\n document.body.appendChild(a)\n a.click()\n a.remove()\n URL.revokeObjectURL(url)\n } catch (err) {\n if (typeof console !== 'undefined') console.error('[admin] export failed:', err)\n adminToast.error(`Не удалось экспортировать данные в формате ${format.toUpperCase()}.`)\n } finally {\n nav.end()\n }\n}\n\n/**\n * Import — file picker → POST multipart на /{slug}/import. После успеха\n * перезагружаем list. Если backend не поддерживает — alert.\n */\nconst importInput = ref<HTMLInputElement | null>(null)\nfunction onImportClick(): void {\n emit('import')\n importInput.value?.click()\n}\n/**\n * Default import flow поверх Dskripchenko\\LaravelAdmin\\Import\\ImportController:\n * 1. POST /import/upload (file + resource=slug) → uploadId\n * 2. POST /import/preview → auto-mapping (headers ↔ fields)\n * 3. POST /import/start (uploadId + mapping) → processId\n * 4. polling /import/status?processId=… до status === 'done' | 'failed'\n *\n * Auto-mapping автоматически связывает имена колонок CSV/JSON со своими\n * Resource-полями. Host может перехватить @import до этого flow и открыть\n * собственный wizard.\n */\nasync function onImportFileChange(e: Event): Promise<void> {\n const input = e.target as HTMLInputElement\n const file = input.files?.[0]\n if (!file) return\n try {\n nav.start()\n const { getAdminClient } = await import('../../stores/registry')\n const client = getAdminClient()\n\n // 1. Upload\n const uploadForm = new FormData()\n uploadForm.append('file', file)\n uploadForm.append('resource', props.slug)\n const uploaded = await client.post<{ upload_id: string }>(\n '/import/upload',\n uploadForm,\n )\n\n // 2. Preview (для auto-mapping)\n const preview = await client.post<{ mapping: Record<string, string> }>(\n '/import/preview',\n { resource: props.slug, upload_id: uploaded.upload_id },\n )\n\n // 3. Start\n const started = await client.post<{ process_id: string }>(\n '/import/start',\n {\n resource: props.slug,\n upload_id: uploaded.upload_id,\n mapping: preview.mapping,\n },\n )\n\n // 4. Poll status\n const finalStatus = await pollImportStatus(client, started.process_id)\n const imported = finalStatus.imported ?? 0\n const failed = finalStatus.failed ?? 0\n if (failed > 0) {\n adminToast.warning(`Импорт завершён с ошибками: ${imported} записей, ${failed} ошибок.`)\n } else {\n adminToast.success(`Импортировано записей: ${imported}.`)\n }\n await index.load().catch(() => undefined)\n } catch (err) {\n if (typeof console !== 'undefined') console.error('[admin] import failed:', err)\n adminToast.error(\n 'Импорт не удался. Проверьте формат файла и поля ресурса либо обратитесь к администратору.',\n )\n } finally {\n input.value = ''\n nav.end()\n }\n}\n\ninterface ImportStatus {\n status: 'pending' | 'running' | 'done' | 'failed'\n imported?: number\n failed?: number\n}\nasync function pollImportStatus(\n client: { get<T>(url: string): Promise<T> },\n processId: string,\n): Promise<ImportStatus> {\n // Polling каждые 800ms, но не дольше 90 секунд (сырая защита от вечного loop'а).\n const deadline = Date.now() + 90_000\n while (Date.now() < deadline) {\n await new Promise((resolve) => setTimeout(resolve, 800))\n const status = await client.get<ImportStatus>(\n `/import/status?process_id=${encodeURIComponent(processId)}`,\n )\n if (status.status === 'done' || status.status === 'failed') return status\n }\n return { status: 'failed', failed: 1 }\n}\n\nconst ACTIONS_KEY = '__row_actions__'\nconst REORDER_KEY = '__row_reorder__'\n\n/** Resource поддерживает reorder если features.reorderable=true. */\nconst isReorderable = computed<boolean>(() => {\n const features = (resourceMeta.value?.features ?? {}) as Record<string, unknown>\n return features.reorderable === true\n})\n\nconst columns = computed<UidTableColumn[]>(() => {\n const cols = resourceMeta.value?.columns ?? []\n const mapped = cols.map((c) => {\n const col = c as Record<string, unknown>\n return {\n key: String(col.key ?? col.name ?? ''),\n label: String(col.label ?? col.name ?? ''),\n sortable: Boolean(col.sortable),\n align: (col.align as 'left' | 'center' | 'right' | undefined) ?? 'left',\n width: typeof col.width === 'string' ? col.width : undefined,\n }\n })\n .filter((c) => c.key)\n // Применяем visibility-state из toolbar'а (Колонки): если явно false —\n // колонку не рендерим. По умолчанию (отсутствует в map) считаем visible.\n .filter((c) => columnVisibility.value[c.key] !== false)\n // Если Resource reorderable — впереди колонка с drag-handle.\n const head: UidTableColumn[] = isReorderable.value\n ? [{\n key: REORDER_KEY,\n label: '',\n sortable: false,\n align: 'center',\n width: '32px',\n }]\n : []\n // Хвостовая колонка с per-row actions (Просмотр / Редактировать / Удалить).\n // ResourceIndexPage добавляет её всегда — host может скрыть через\n // useShowActions=false (TODO prop).\n return [\n ...head,\n ...mapped,\n {\n key: ACTIONS_KEY,\n label: '',\n sortable: false,\n align: 'right',\n width: '120px',\n },\n ]\n})\n\n// Колоночная meta (preset / format / currency / editable / etc.) из manifest'а.\n// Используется для formatCell (datetime → 'd.m.Y H:i:s', money → '{val} {ccy}')\n// + InlineEditCell проверяет editable.\nfunction columnIsEditable(key: string): boolean {\n const cols = resourceMeta.value?.columns ?? []\n for (const c of cols) {\n const col = c as Record<string, unknown>\n const k = String(col.key ?? col.name ?? '')\n if (k === key) {\n // Backend кладёт editable как объект {rules:...} или null.\n return col.editable !== null && col.editable !== undefined\n }\n }\n return false\n}\nconst columnMeta = computed<Record<string, { preset?: string; meta: CellMeta }>>(() => {\n const cols = resourceMeta.value?.columns ?? []\n const result: Record<string, { preset?: string; meta: CellMeta }> = {}\n for (const c of cols) {\n const col = c as Record<string, unknown>\n const key = String(col.key ?? col.name ?? '')\n if (!key) continue\n result[key] = {\n preset: typeof col.preset === 'string' ? col.preset : undefined,\n meta: (col.meta as CellMeta) ?? {},\n }\n }\n return result\n})\n\nfunction renderCell(key: string, slotProps: unknown): string {\n // UidTable scoped-slot передаёт {row: actualRow}.\n const row = (slotProps as { row?: Record<string, unknown> } | undefined)?.row\n const value = row?.[key]\n const m = columnMeta.value[key]\n return formatCell(value, m?.preset, m?.meta ?? {})\n}\n\nfunction rowFromSlot(slotProps: unknown): Record<string, unknown> | undefined {\n return (slotProps as { row?: Record<string, unknown> } | undefined)?.row\n}\n\n/**\n * Показывать ли filter-toolbar:\n * - если есть данные → всегда (search + фильтры внутри);\n * - если данных нет, но есть активный search/filter → ДА (чтобы пользователь\n * мог сбросить и снова увидеть items);\n * - если данных нет и фильтры/поиск пустые → НЕТ (initial empty state).\n */\nconst hasActiveFilters = computed<boolean>(\n () => index.search !== '' || Object.keys(index.filters).length > 0,\n)\nconst showFilterBar = computed<boolean>(\n () => !index.isEmpty || hasActiveFilters.value,\n)\n\n// Filter / column / view state — toolbar делегирует это сюда.\nconst manifestFilters = computed(\n () => (resourceMeta.value?.filters ?? []) as unknown as Array<Record<string, unknown>>,\n)\nconst manifestColumns = computed(\n () => (resourceMeta.value?.columns ?? []) as unknown as Array<Record<string, unknown>>,\n)\nconst searchPlaceholder = computed(() => {\n const label = (resourceMeta.value?.label ?? props.slug).toLowerCase()\n return `Поиск по ${label}…`\n})\n\nconst groupByCol = ref<string | null>(null)\nconst columnVisibility = ref<Record<string, boolean>>({})\n\nasync function onFilterApply(name: string, value: unknown): Promise<void> {\n await index.setFilter(name, value)\n}\nasync function onSearchUpdate(v: string): Promise<void> {\n await index.setSearch(v)\n}\nasync function onResetFilters(): Promise<void> {\n index.search = ''\n await index.clearFilters()\n}\nasync function onGroupBy(col: string | null): Promise<void> {\n groupByCol.value = col\n // Backend может или не может поддерживать group-by — пробрасываем\n // в search payload как `group_by`. Если не поддерживается — просто\n // игнорируется. Cast через unknown-bridge т.к. IndexParams strict.\n await index.load({ group_by: col } as unknown as Parameters<typeof index.load>[0])\n}\nfunction onColumnsVisibility(next: Record<string, boolean>): void {\n columnVisibility.value = next\n}\n/**\n * Saved views: state + load + apply/delete. Backend — SavedViewsController,\n * URL pattern /{slug}_views/{action}. Active view хранится локально и\n * подсвечивается в scope-dropdown'е.\n */\ninterface SavedViewItem {\n id: number\n name: string\n state: Record<string, unknown>\n is_default: boolean\n owned: boolean\n}\nconst savedViews = ref<SavedViewItem[]>([])\nconst activeViewId = ref<number | null>(null)\n\nasync function loadSavedViews(): Promise<void> {\n try {\n const { getAdminClient } = await import('../../stores/registry')\n const client = getAdminClient()\n const result = await client.get<{ data: SavedViewItem[] }>(`/${props.slug}_views/list`)\n savedViews.value = result.data ?? []\n } catch {\n // Тихо — endpoint опционален. Возможно ресурс без permission или backend\n // не зарегистрировал views.\n savedViews.value = []\n }\n}\n\nasync function onApplyView(view: SavedViewItem): Promise<void> {\n activeViewId.value = view.id\n const s = view.state as {\n search?: string\n filters?: Record<string, unknown>\n sort?: { key?: string | null; direction?: 'asc' | 'desc' | null }\n group_by?: string | null\n columns?: Record<string, boolean>\n }\n index.search = s.search ?? ''\n index.filters = { ...(s.filters ?? {}) }\n index.sortKey = s.sort?.key ?? null\n index.sortDirection = s.sort?.direction ?? null\n groupByCol.value = s.group_by ?? null\n columnVisibility.value = { ...(s.columns ?? {}) }\n index.meta.page = 1\n await loadWithProgress()\n}\n\nasync function onResetView(): Promise<void> {\n activeViewId.value = null\n index.search = ''\n index.filters = {}\n index.sortKey = null\n index.sortDirection = null\n groupByCol.value = null\n columnVisibility.value = {}\n index.meta.page = 1\n await loadWithProgress()\n}\n\nasync function onDeleteView(view: SavedViewItem, e?: MouseEvent): Promise<void> {\n e?.stopPropagation()\n if (!view.owned) return\n if (!window.confirm(`Удалить view «${view.name}»?`)) return\n try {\n nav.start()\n const { getAdminClient } = await import('../../stores/registry')\n const client = getAdminClient()\n await client.post(`/${props.slug}_views/delete`, { id: view.id })\n if (activeViewId.value === view.id) activeViewId.value = null\n await loadSavedViews()\n } catch (err) {\n if (typeof console !== 'undefined') console.error('[admin] delete-view failed:', err)\n } finally {\n nav.end()\n }\n}\n\nasync function onSaveView(label: string): Promise<void> {\n try {\n nav.start()\n const { getAdminClient } = await import('../../stores/registry')\n const client = getAdminClient()\n // Backend: ResourceCompiler регистрирует controller key `{slug}_views`,\n // SavedViewsController::create — POST /{slug}_views/create.\n // Validation: {name: required string, state: required array, is_default?}\n const result = await client.post<{ view: SavedViewItem }>(\n `/${props.slug}_views/create`,\n {\n name: label,\n state: {\n search: index.search,\n filters: index.filters,\n sort: { key: index.sortKey, direction: index.sortDirection },\n group_by: groupByCol.value,\n columns: columnVisibility.value,\n },\n },\n )\n // Сразу актуализируем локальный список и помечаем view активным.\n if (result?.view) {\n activeViewId.value = result.view.id\n }\n await loadSavedViews()\n adminToast.success(tt('admin.resource.view_saved', 'Представление сохранено.'))\n } catch (err) {\n if (typeof console !== 'undefined') console.error('[admin] save-view failed:', err)\n adminToast.error(\n 'Не удалось сохранить view. Возможно, недостаточно прав либо ресурс не зарегистрирован.',\n )\n } finally {\n nav.end()\n }\n}\n\nconst totalLabel = computed(() => {\n const t = index.meta.total\n if (t === 0) return ''\n return `${index.items.length} из ${t} ${pluralRecords(t)}`\n})\n\n/**\n * Русская плюрализация для \"записей\". Backend локаль RU; для других локалей\n * host может пропатчить через slot `subtitle`.\n */\nfunction pluralRecords(n: number): string {\n const mod10 = n % 10\n const mod100 = n % 100\n if (mod10 === 1 && mod100 !== 11) return 'запись'\n if (mod10 >= 2 && mod10 <= 4 && (mod100 < 10 || mod100 >= 20)) return 'записи'\n return 'записей'\n}\n\n/**\n * Live-status: timestamp последнего успешного load + \"tick\" каждые 30s,\n * чтобы текст \"обновлено 1 мин назад\" реально обновлялся без re-load.\n *\n * lastLoadedAt = null до первой удачи; после успешного store.load() ставим\n * Date.now(). Используем watch на index.loading: переход true → false без\n * error = успех.\n */\nconst lastLoadedAt = ref<number | null>(null)\nconst tick = ref<number>(0)\nlet tickTimer: ReturnType<typeof setInterval> | null = null\n\nwatch(\n () => index.loading,\n (isLoading, wasLoading) => {\n if (wasLoading && !isLoading && index.error === null) {\n lastLoadedAt.value = Date.now()\n }\n },\n)\n\nonMounted(() => {\n tickTimer = setInterval(() => {\n tick.value += 1\n }, 30_000)\n})\nonUnmounted(() => {\n if (tickTimer !== null) clearInterval(tickTimer)\n})\n\nconst liveStatus = computed<string | null>(() => {\n // tick — dependency для re-compute. Без него computed замёрзнет на initial value.\n void tick.value\n if (lastLoadedAt.value === null) return null\n const diffSec = Math.floor((Date.now() - lastLoadedAt.value) / 1000)\n if (diffSec < 5) return 'обновлено только что'\n if (diffSec < 60) return `обновлено ${diffSec} сек назад`\n const min = Math.floor(diffSec / 60)\n if (min < 60) return `обновлено ${min} мин назад`\n const hr = Math.floor(min / 60)\n if (hr < 24) return `обновлено ${hr} ч назад`\n return 'обновлено более суток назад'\n})\n\nconst scopeLabel = computed<string>(() => {\n // Активный view → его имя; иначе \"Все {ресурс в lowercase}\".\n if (activeViewId.value !== null) {\n const v = savedViews.value.find((x) => x.id === activeViewId.value)\n if (v) return v.name\n }\n const label = resourceMeta.value?.label ?? props.slug\n return `Все ${label.toLowerCase()}`\n})\n\n/**\n * Обёртка над index.load — увеличивает navigation pending counter\n * (top loading-bar) на время запроса. router.beforeEach уже инкрементирует\n * counter при start navigation; этот wrap держит bar до конца data-fetch'а.\n */\nasync function loadWithProgress(): Promise<void> {\n nav.start()\n try {\n await index.load()\n } catch {\n // silent; ошибка отображается в hasError state\n } finally {\n nav.end()\n }\n}\n\n/**\n * Mount-init: setSlug + load data.\n *\n * При SPA navigation от router.push первичный data-fetch также делается\n * в router.beforeResolve (см. createAdminApp.ts) — он держит navigation\n * в pending пока данные не пришли. Здесь load всё равно вызываем как\n * resilient fallback (direct page mount, page reload, test).\n */\nonMounted(async () => {\n index.setSlug(props.slug)\n if (manifest.manifest === null) {\n await manifest.load().catch(() => undefined)\n }\n void loadSavedViews()\n await loadWithProgress()\n})\n\nwatch(\n () => props.slug,\n async (next, prev) => {\n if (next === prev) return\n index.setSlug(next)\n activeViewId.value = null\n void loadSavedViews()\n await loadWithProgress()\n },\n)\n\nasync function onSortKeyUpdate(key: string | null): Promise<void> {\n // UidTable управляет своим 3-режимным cycle; здесь только применяем итог.\n // sortDirection приходит отдельным событием — apply через setSort одним\n // вызовом (после nextTick — Vue batches событий).\n await nextTick()\n await index.setSort(key, index.sortDirection)\n}\n\nasync function onSortDirUpdate(dir: 'asc' | 'desc' | null): Promise<void> {\n await nextTick()\n await index.setSort(index.sortKey, dir)\n}\n\nfunction onSelectionUpdate(next: Set<string | number>): void {\n index.selection = next\n}\n\nasync function onPageChange(page: number): Promise<void> {\n await index.setPage(page)\n}\n\nfunction rowId(row: Record<string, unknown>): string | number | null {\n const v = row?.id ?? row?.key\n return typeof v === 'string' || typeof v === 'number' ? v : null\n}\n\nfunction onRowClick(row: Record<string, unknown>): void {\n emit('row-click', row)\n // По умолчанию click по строке открывает view-screen записи.\n // Host может перехватить через @row-click и сделать e.preventDefault.\n const id = rowId(row)\n if (id !== null) {\n void router.push({ name: `admin.resource.${props.slug}.view`, params: { id: String(id) } })\n }\n}\n\nfunction onView(row: Record<string, unknown>, e?: MouseEvent): void {\n e?.stopPropagation()\n const id = rowId(row)\n if (id !== null) {\n void router.push({ name: `admin.resource.${props.slug}.view`, params: { id: String(id) } })\n }\n}\n\nfunction onEdit(row: Record<string, unknown>, e?: MouseEvent): void {\n e?.stopPropagation()\n const id = rowId(row)\n if (id !== null) {\n void router.push({ name: `admin.resource.${props.slug}.edit`, params: { id: String(id) } })\n }\n}\n\nasync function onDelete(row: Record<string, unknown>, e?: MouseEvent): Promise<void> {\n e?.stopPropagation()\n const id = rowId(row)\n if (id === null) return\n if (!window.confirm(tt('admin.resource.delete_confirm', 'Удалить запись?'))) return\n try {\n nav.start()\n const { getAdminClient } = await import('../../stores/registry')\n const client = getAdminClient()\n await client.post(`/${props.slug}/delete`, { id })\n await index.load().catch(() => undefined)\n adminToast.success(tt('admin.resource.deleted', 'Запись удалена.'))\n } catch (err) {\n if (typeof console !== 'undefined') console.error('[admin] delete failed:', err)\n adminToast.error(tt('admin.resource.delete_failed', 'Не удалось удалить запись.'))\n } finally {\n nav.end()\n }\n}\n\n/** Soft-deleted rows имеют непустой `deleted_at`. */\nfunction isTrashed(row: Record<string, unknown>): boolean {\n return row.deleted_at !== null && row.deleted_at !== undefined\n}\n\nasync function onRestore(row: Record<string, unknown>, e?: MouseEvent): Promise<void> {\n e?.stopPropagation()\n const id = rowId(row)\n if (id === null) return\n try {\n nav.start()\n const { getAdminClient } = await import('../../stores/registry')\n const client = getAdminClient()\n await client.post(`/${props.slug}/restore`, { id })\n await index.load().catch(() => undefined)\n adminToast.success(tt('admin.resource.restored', 'Запись восстановлена.'))\n } catch (err) {\n if (typeof console !== 'undefined') console.error('[admin] restore failed:', err)\n adminToast.error(tt('admin.resource.restore_failed', 'Не удалось восстановить запись.'))\n } finally {\n nav.end()\n }\n}\n\n// === Row reorder (HTML5 drag + visual indicator) ===\nconst dragRowIdx = ref<number | null>(null)\nconst dragOverRowIdx = ref<number | null>(null)\nconst dragOverSide = ref<'before' | 'after'>('before')\n\nfunction onRowDragStart(idx: number, e: DragEvent): void {\n if (!isReorderable.value || !e.dataTransfer) return\n const t = e.target as HTMLElement | null\n if (!t?.closest('[data-row-drag-handle=\"true\"]')) {\n e.preventDefault()\n return\n }\n dragRowIdx.value = idx\n e.dataTransfer.effectAllowed = 'move'\n e.dataTransfer.setData('text/plain', String(idx))\n}\nfunction onRowDragOver(idx: number, e: DragEvent): void {\n if (!isReorderable.value || dragRowIdx.value === null) return\n e.preventDefault()\n // Определяем сторону по mid-Y current cell'а — drop-line будет либо\n // выше, либо ниже текущей строки.\n const target = e.currentTarget as HTMLElement | null\n if (target) {\n const rect = target.getBoundingClientRect()\n dragOverSide.value = e.clientY < rect.top + rect.height / 2 ? 'before' : 'after'\n }\n dragOverRowIdx.value = idx\n}\nfunction onRowDragEnd(): void {\n dragRowIdx.value = null\n dragOverRowIdx.value = null\n}\nasync function onRowDrop(toIdx: number, e: DragEvent): Promise<void> {\n e.preventDefault()\n if (!isReorderable.value || dragRowIdx.value === null) return\n const fromIdx = dragRowIdx.value\n // adjusted = вставка после строки (insertion-index в уже-удалённом array).\n const adjusted = dragOverSide.value === 'after' ? toIdx + 1 : toIdx\n const finalIdx = adjusted > fromIdx ? adjusted - 1 : adjusted\n dragRowIdx.value = null\n dragOverRowIdx.value = null\n if (fromIdx === finalIdx) return\n // Локальный reorder для мгновенного отклика.\n const items = [...index.items]\n const [moved] = items.splice(fromIdx, 1)\n items.splice(finalIdx, 0, moved)\n index.items = items\n // Backend persistence: POST /{slug}/reorder body {ids: [orderedIds]}.\n try {\n nav.start()\n const { getAdminClient } = await import('../../stores/registry')\n const client = getAdminClient()\n const ids = items.map((r) => index.rowId(r))\n await client.post(`/${props.slug}/reorder`, { ids })\n adminToast.success(tt('admin.resource.reorder_saved', 'Порядок сохранён.'))\n } catch (err) {\n if (typeof console !== 'undefined') console.error('[admin] reorder failed:', err)\n adminToast.error(tt('admin.resource.reorder_failed', 'Не удалось сохранить порядок.'))\n await index.load().catch(() => undefined)\n } finally {\n nav.end()\n }\n}\n\nasync function onForceDelete(row: Record<string, unknown>, e?: MouseEvent): Promise<void> {\n e?.stopPropagation()\n const id = rowId(row)\n if (id === null) return\n if (!window.confirm(tt('admin.resource.force_delete_confirm', 'Удалить запись НАВСЕГДА? Действие необратимо.'))) return\n try {\n nav.start()\n const { getAdminClient } = await import('../../stores/registry')\n const client = getAdminClient()\n await client.post(`/${props.slug}/forceDelete`, { id })\n await index.load().catch(() => undefined)\n adminToast.success(tt('admin.resource.force_deleted', 'Запись удалена навсегда.'))\n } catch (err) {\n if (typeof console !== 'undefined') console.error('[admin] force-delete failed:', err)\n adminToast.error(tt('admin.resource.force_delete_failed', 'Не удалось удалить запись навсегда.'))\n } finally {\n nav.end()\n }\n}\n\nfunction bulkAction(action: string): void {\n emit('bulk-action', action, [...index.selection])\n}\n\nasync function retryLoad(): Promise<void> {\n await index.load().catch(() => undefined)\n}\n</script>\n\n<template>\n <section class=\"admin-page admin-resource-index\">\n <!-- Header — следует docs/design_handoff_laravel_admin/screens-resource.jsx\n (Resource Index): title-row с live-status, под ним counter,\n справа — scope dropdown / more-menu / Import / Создать. -->\n <header class=\"admin-page__hd\">\n <div class=\"admin-page__title-wrap\">\n <div class=\"admin-page__title-row\">\n <h1 class=\"admin-page__title\">{{ displayTitle }}</h1>\n <span v-if=\"liveStatus\" class=\"admin-page__live\" role=\"status\">\n <span class=\"admin-page__live-dot\" aria-hidden=\"true\" />\n {{ liveStatus }}\n </span>\n </div>\n <div v-if=\"subtitle || totalLabel\" class=\"admin-page__count\">\n <template v-if=\"subtitle\">{{ subtitle }}</template>\n <template v-if=\"subtitle && totalLabel\"> · </template>\n <template v-if=\"totalLabel\">{{ totalLabel }}</template>\n </div>\n </div>\n <div class=\"admin-page__actions\">\n <slot name=\"actions\" />\n <UidMenu>\n <template #trigger>\n <UidButton variant=\"ghost\" size=\"md\" class=\"admin-page__scope\">\n <template #prepend><UidIcon :icon=\"Bookmark\" :size=\"14\" /></template>\n {{ scopeLabel }}\n <template #append><UidIcon :icon=\"ChevronDown\" :size=\"14\" /></template>\n </UidButton>\n </template>\n <UidMenuItem @click=\"onResetView\">\n Все {{ (resourceMeta?.label ?? slug).toLowerCase() }}\n </UidMenuItem>\n <UidMenuItem\n v-for=\"v in savedViews\"\n :key=\"v.id\"\n @click=\"onApplyView(v)\"\n >\n <span class=\"admin-page__view-row\">\n <span class=\"admin-page__view-name\">\n {{ v.name }}\n <span v-if=\"v.is_default\" class=\"admin-page__view-badge\">default</span>\n </span>\n <button\n v-if=\"v.owned\"\n type=\"button\"\n class=\"admin-page__view-delete\"\n aria-label=\"Удалить view\"\n @click.stop=\"onDeleteView(v, $event)\"\n >\n <UidIcon :icon=\"Trash2\" :size=\"12\" />\n </button>\n </span>\n </UidMenuItem>\n </UidMenu>\n <UidMenu>\n <template #trigger>\n <UidButton variant=\"ghost\" size=\"md\" aria-label=\"Действия\" class=\"admin-page__more\">\n <UidIcon :icon=\"MoreHorizontal\" :size=\"16\" />\n </UidButton>\n </template>\n <UidMenuItem @click=\"retryLoad\">Обновить</UidMenuItem>\n <UidMenuItem @click=\"onExport('csv')\">Экспорт CSV</UidMenuItem>\n <UidMenuItem @click=\"onExport('json')\">Экспорт JSON</UidMenuItem>\n <UidMenuItem @click=\"onExport('xlsx')\">Экспорт XLSX</UidMenuItem>\n <UidMenuItem @click=\"onExport('pdf')\">Экспорт PDF</UidMenuItem>\n <!-- Кастомные действия от backend Resource->actions(). -->\n <UidMenuItem\n v-for=\"action in headerActions\"\n :key=\"action.key\"\n @click=\"onCustomAction(action)\"\n >\n {{ action.label }}\n </UidMenuItem>\n <slot name=\"header-menu\" />\n </UidMenu>\n <UidButton variant=\"secondary\" size=\"md\" @click=\"onImportClick\">\n <template #prepend><UidIcon :icon=\"Upload\" :size=\"14\" /></template>\n Import\n </UidButton>\n <input\n ref=\"importInput\"\n type=\"file\"\n class=\"admin-page__import-input\"\n accept=\".csv,.json,.xlsx,.xls,application/json,text/csv\"\n @change=\"onImportFileChange\"\n />\n <UidButton\n v-if=\"resolvedCreateRouteName\"\n variant=\"primary\"\n size=\"md\"\n @click=\"$router.push({ name: resolvedCreateRouteName })\"\n >\n <template #prepend><UidIcon :icon=\"Plus\" :size=\"14\" /></template>\n {{ createLabel }}\n </UidButton>\n </div>\n </header>\n\n <!-- Bulk toolbar (selection > 0) ИЛИ filter bar -->\n <div v-if=\"index.hasSelection\" class=\"admin-bulk-toolbar\" role=\"toolbar\">\n <span class=\"admin-bulk-toolbar__count\">\n Выбрано <b>{{ index.selectedCount }}</b>\n </span>\n <span class=\"admin-bulk-toolbar__divider\" />\n <UidButton size=\"sm\" variant=\"ghost\" @click=\"bulkAction('publish')\">Опубликовать</UidButton>\n <UidButton size=\"sm\" variant=\"ghost\" @click=\"bulkAction('archive')\">Архивировать</UidButton>\n <UidButton size=\"sm\" variant=\"ghost\" @click=\"bulkAction('export')\">Экспорт</UidButton>\n <UidButton size=\"sm\" variant=\"danger\" @click=\"bulkAction('delete')\">Удалить</UidButton>\n <span class=\"admin-bulk-toolbar__spacer\" />\n <UidButton size=\"sm\" variant=\"ghost\" @click=\"index.clearSelection\">\n Снять выделение\n </UidButton>\n </div>\n\n <AdminFilterToolbar\n v-else-if=\"showFilterBar\"\n :search=\"index.search\"\n :search-placeholder=\"searchPlaceholder\"\n :filters=\"(manifestFilters as never)\"\n :values=\"index.filters\"\n :columns=\"(manifestColumns as never)\"\n :group-by=\"groupByCol\"\n :column-visibility=\"columnVisibility\"\n @update:search=\"onSearchUpdate\"\n @apply-filter=\"onFilterApply\"\n @reset=\"onResetFilters\"\n @group-by=\"onGroupBy\"\n @columns-visibility=\"onColumnsVisibility\"\n @save-view=\"onSaveView\"\n >\n <template #extra>\n <slot name=\"filters\" :filters=\"index.filters\" :set-filter=\"index.setFilter\" />\n </template>\n </AdminFilterToolbar>\n\n <!-- States -->\n <!-- Initial-loading стейт (между setSlug и первым успехом load).\n Показываем placeholder вместо UidTable — иначе сама таблица\n рендерит \"Нет данных\" empty state, что создаёт flicker\n \"Нет данных → реальные строки\" при navigation. -->\n <div\n v-if=\"index.loading && index.items.length === 0\"\n class=\"admin-resource-index__loading\"\n >\n <UidSkeleton\n v-if=\"index.slowLoading\"\n v-for=\"i in 8\"\n :key=\"i\"\n height=\"40px\"\n />\n </div>\n <UidErrorState\n v-else-if=\"index.hasError\"\n title=\"Не удалось загрузить данные\"\n :description=\"index.error?.message ?? 'Попробуйте обновить страницу.'\"\n class=\"admin-resource-index__state\"\n >\n <template #actions>\n <UidButton variant=\"primary\" @click=\"retryLoad\">Обновить</UidButton>\n </template>\n </UidErrorState>\n <UidEmptyState\n v-else-if=\"index.isEmpty\"\n title=\"Пока пусто\"\n description=\"Создайте первую запись или измените фильтры.\"\n class=\"admin-resource-index__state\"\n >\n <template #actions>\n <UidButton\n v-if=\"createRouteName\"\n variant=\"primary\"\n @click=\"$router.push({ name: createRouteName })\"\n >\n {{ createLabel }}\n </UidButton>\n </template>\n </UidEmptyState>\n\n <!-- Таблица — UidTable native selection (UidTable.selectable + selection prop). -->\n <div v-else class=\"admin-resource-index__table\">\n <UidTable\n :columns=\"columns\"\n :data=\"index.items\"\n :sort-key=\"index.sortKey\"\n :sort-direction=\"index.sortDirection\"\n selectable\n :selection=\"index.selection\"\n :row-key=\"(row) => index.rowId(row)\"\n @update:sort-key=\"onSortKeyUpdate\"\n @update:sort-direction=\"onSortDirUpdate\"\n @update:selection=\"onSelectionUpdate\"\n @row-click=\"onRowClick\"\n >\n <template\n v-for=\"col in columns\"\n #[col.key]=\"slotProps\"\n :key=\"col.key\"\n >\n <!-- Колонка drag-handle для reorderable resource'а -->\n <span\n v-if=\"col.key === REORDER_KEY\"\n :class=\"[\n 'admin-resource-index__row-drag',\n {\n 'admin-resource-index__row-drag--drop-before':\n dragOverRowIdx !== null\n && dragOverRowIdx === index.items.indexOf((rowFromSlot(slotProps) ?? {}) as Record<string, unknown>)\n && dragOverSide === 'before',\n 'admin-resource-index__row-drag--drop-after':\n dragOverRowIdx !== null\n && dragOverRowIdx === index.items.indexOf((rowFromSlot(slotProps) ?? {}) as Record<string, unknown>)\n && dragOverSide === 'after',\n 'admin-resource-index__row-drag--ghost':\n dragRowIdx !== null\n && dragRowIdx === index.items.indexOf((rowFromSlot(slotProps) ?? {}) as Record<string, unknown>),\n },\n ]\"\n data-row-drag-handle=\"true\"\n :draggable=\"isReorderable\"\n title=\"Перетащить\"\n @dragstart=\"(e: DragEvent) => onRowDragStart(\n index.items.indexOf((rowFromSlot(slotProps) ?? {}) as Record<string, unknown>),\n e,\n )\"\n @dragover=\"(e: DragEvent) => onRowDragOver(\n index.items.indexOf((rowFromSlot(slotProps) ?? {}) as Record<string, unknown>),\n e,\n )\"\n @dragend=\"onRowDragEnd\"\n @drop=\"(e: DragEvent) => onRowDrop(\n index.items.indexOf((rowFromSlot(slotProps) ?? {}) as Record<string, unknown>),\n e,\n )\"\n >\n <UidIcon :icon=\"GripVertical\" :size=\"14\" />\n </span>\n\n <!-- Колонка row-actions (View / Edit / Delete) — рендерим всегда последней. -->\n <div\n v-else-if=\"col.key === ACTIONS_KEY\"\n class=\"admin-resource-index__row-actions\"\n >\n <button\n type=\"button\"\n class=\"admin-resource-index__row-action\"\n title=\"Просмотр\"\n @click.stop=\"onView(rowFromSlot(slotProps) ?? {}, $event)\"\n >\n <UidIcon :icon=\"Eye\" :size=\"16\" />\n </button>\n <template v-if=\"!isTrashed(rowFromSlot(slotProps) ?? {})\">\n <button\n type=\"button\"\n class=\"admin-resource-index__row-action\"\n title=\"Редактировать\"\n @click.stop=\"onEdit(rowFromSlot(slotProps) ?? {}, $event)\"\n >\n <UidIcon :icon=\"Pencil\" :size=\"16\" />\n </button>\n <button\n type=\"button\"\n class=\"admin-resource-index__row-action admin-resource-index__row-action--danger\"\n title=\"Удалить\"\n @click.stop=\"onDelete(rowFromSlot(slotProps) ?? {}, $event)\"\n >\n <UidIcon :icon=\"Trash2\" :size=\"16\" />\n </button>\n </template>\n <template v-else>\n <button\n type=\"button\"\n class=\"admin-resource-index__row-action\"\n title=\"Восстановить\"\n @click.stop=\"onRestore(rowFromSlot(slotProps) ?? {}, $event)\"\n >\n <UidIcon :icon=\"RotateCcw\" :size=\"16\" />\n </button>\n <button\n type=\"button\"\n class=\"admin-resource-index__row-action admin-resource-index__row-action--danger\"\n title=\"Удалить навсегда\"\n @click.stop=\"onForceDelete(rowFromSlot(slotProps) ?? {}, $event)\"\n >\n <UidIcon :icon=\"Trash2\" :size=\"16\" />\n </button>\n </template>\n </div>\n <slot\n v-else\n :name=\"`cell-${col.key}`\"\n :row=\"rowFromSlot(slotProps)\"\n >\n <!--\n Default cell renderer: значение в одну строку с ellipsis при\n переполнении. max-width задаёт «адекватную» ширину колонки\n через CSS-var --admin-cell-max-width (по умолчанию 320px).\n Полный текст доступен через native browser tooltip (title=).\n Для editable-колонок double-click открывает inline editor.\n -->\n <InlineEditCell\n v-if=\"columnIsEditable(col.key)\"\n :resource-slug=\"slug\"\n :row-id=\"(rowId(rowFromSlot(slotProps) ?? {}) ?? '') as string | number\"\n :column=\"col.key\"\n :value=\"(rowFromSlot(slotProps) ?? {})[col.key]\"\n :editable=\"true\"\n @saved=\"(v) => {\n const r = rowFromSlot(slotProps)\n if (r) r[col.key] = v\n }\"\n >\n <span class=\"admin-cell-truncate\">{{ renderCell(col.key, slotProps) }}</span>\n </InlineEditCell>\n <span\n v-else\n class=\"admin-cell-truncate\"\n :title=\"renderCell(col.key, slotProps)\"\n >{{ renderCell(col.key, slotProps) }}</span>\n </slot>\n </template>\n </UidTable>\n </div>\n\n <!-- Pagination -->\n <footer\n v-if=\"!index.loading && !index.hasError && !index.isEmpty\"\n class=\"admin-resource-index__footer\"\n >\n <UidPagination\n :model-value=\"index.meta.page\"\n :total=\"index.meta.total\"\n :per-page=\"index.meta.per_page\"\n @update:model-value=\"onPageChange\"\n />\n </footer>\n </section>\n</template>\n\n<style>\n.admin-resource-index__loading {\n display: flex;\n flex-direction: column;\n gap: var(--uid-space-sm);\n margin-top: var(--uid-space-md);\n /* min-height предотвращает layout-collapse при первом mount'е,\n когда slowLoading ещё false (быстрый запрос — placeholder пустой). */\n min-height: 320px;\n}\n\n/* Drag-handle для reorderable resource'а — первая колонка. */\n.admin-resource-index__row-drag {\n position: relative;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n cursor: grab;\n color: var(--uid-text-tertiary);\n border-radius: var(--uid-radius-sm);\n}\n.admin-resource-index__row-drag:hover {\n background: var(--uid-color-surface-hover, var(--uid-border-subtle));\n color: var(--uid-text-primary);\n}\n.admin-resource-index__row-drag:active { cursor: grabbing; }\n/* Полупрозрачная исходная строка во время drag (приём из Notion/Linear). */\n.admin-resource-index__row-drag--ghost { opacity: 0.4; }\n/* Линия-индикатор drop'а — extends на всю ширину строки через ::before\n (положение absolute относительно td.admin-resource-index__row-drag,\n left:-9999 чтобы перекрыть ширину таблицы). */\n.admin-resource-index__row-drag--drop-before::before,\n.admin-resource-index__row-drag--drop-after::before {\n content: '';\n position: absolute;\n left: 0;\n right: -9999px;\n height: 2px;\n background: var(--uid-accent);\n pointer-events: none;\n z-index: 5;\n}\n.admin-resource-index__row-drag--drop-before::before { top: -1px; }\n.admin-resource-index__row-drag--drop-after::before { bottom: -1px; }\n\n/* Row actions: View / Edit / Delete иконки в последней колонке таблицы. */\n.admin-resource-index__row-actions {\n display: flex;\n align-items: center;\n justify-content: flex-end;\n gap: var(--uid-space-2xs);\n}\n.admin-resource-index__row-action {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n padding: 0;\n border: 1px solid transparent;\n border-radius: var(--uid-radius-sm);\n background: transparent;\n color: var(--uid-text-secondary);\n cursor: pointer;\n transition: background var(--uid-duration-fast) var(--uid-ease-out),\n color var(--uid-duration-fast) var(--uid-ease-out),\n border-color var(--uid-duration-fast) var(--uid-ease-out);\n}\n.admin-resource-index__row-action:hover {\n background: var(--uid-color-surface-hover);\n color: var(--uid-text-primary);\n border-color: var(--uid-border-subtle);\n}\n.admin-resource-index__row-action--danger:hover {\n color: var(--uid-color-danger, #dc2626);\n}\n.admin-resource-index__state {\n margin-top: var(--uid-space-xl);\n}\n.admin-resource-index__table {\n /* table визуально приклеена к filter-bar / bulk-toolbar сверху —\n убираем gap, скругляем только нижние углы у table-wrap'а. */\n margin-top: 0;\n}\n.admin-resource-index__table .uid-table-wrap {\n border: 1px solid var(--uid-border-subtle);\n border-top: 0;\n border-radius: 0 0 var(--uid-radius-lg) var(--uid-radius-lg);\n}\n\n/*\n * Compact-mode table: уменьшаем padding td/th под --admin-row-h:32px и\n * font-size 13px. Оригинальный UidTable ставит padding:12px — для compact\n * это много. Переопределяем точечно внутри admin-resource-index'а чтобы\n * не задеть UidTable в других контекстах (storybook, custom widgets).\n */\n.admin-resource-index__table .uid-table__td,\n.admin-resource-index__table .uid-table__th {\n padding: 6px var(--uid-space-md);\n font-size: var(--admin-row-fs, 13px);\n height: var(--admin-row-h, 32px);\n line-height: 1.3;\n}\n\n/*\n * Cell truncate — 1 строка с ellipsis, max-width адекватный (320px по\n * умолчанию). Long-words переносятся внутри ограничения макс. до 3 строк\n * (line-clamp) на случай когда host переопределит white-space через slot.\n *\n * Tooltip с полным значением — нативный browser-tooltip через title=\n * атрибут (см. ResourceIndexPage.vue cell renderer).\n */\n.admin-cell-truncate {\n display: inline-block;\n max-width: var(--admin-cell-max-width, 320px);\n vertical-align: middle;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.admin-cell-truncate--multi {\n display: -webkit-box;\n white-space: normal;\n -webkit-line-clamp: 3;\n -webkit-box-orient: vertical;\n word-break: break-word;\n}\n.admin-resource-index__footer {\n display: flex;\n justify-content: flex-end;\n padding: var(--uid-space-md) 0;\n}\n\n/* Filter bar */\n.admin-filter-bar {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--uid-space-sm);\n padding: var(--uid-space-sm) var(--uid-space-md);\n border: 1px solid var(--uid-border-subtle);\n background: var(--uid-surface-raised);\n border-radius: var(--uid-radius-lg) var(--uid-radius-lg) 0 0;\n border-bottom: 0;\n margin-top: var(--uid-space-md);\n}\n.admin-filter-bar__search {\n flex: 1;\n min-width: 200px;\n max-width: 320px;\n height: 28px;\n padding: 0 var(--uid-space-sm);\n border: 1px solid var(--uid-border-subtle);\n background: var(--uid-surface-base);\n border-radius: var(--uid-radius-md);\n color: var(--uid-text-primary);\n font-size: 13px;\n outline: none;\n}\n.admin-filter-bar__search:focus {\n border-color: var(--uid-accent);\n outline: 2px solid color-mix(in srgb, var(--uid-accent) 18%, transparent);\n}\n.admin-filter-bar__spacer { flex: 1; }\n\n/* Bulk toolbar — dark zinc-900 surface, заменяет filter bar */\n.admin-bulk-toolbar {\n display: flex;\n align-items: center;\n gap: var(--uid-space-sm);\n padding: var(--uid-space-sm) var(--uid-space-md);\n background: var(--uid-color-zinc-900, #18181b);\n color: var(--uid-color-zinc-100, #f4f4f5);\n border-radius: var(--uid-radius-lg) var(--uid-radius-lg) 0 0;\n border: 1px solid var(--uid-color-zinc-900, #18181b);\n border-bottom: 0;\n margin-top: var(--uid-space-md);\n}\n.admin-bulk-toolbar__count { font-size: 13px; }\n.admin-bulk-toolbar__count b { font-weight: var(--uid-font-weight-semibold); }\n.admin-bulk-toolbar__divider {\n width: 1px;\n height: 20px;\n background: rgba(255, 255, 255, 0.15);\n}\n.admin-bulk-toolbar__spacer { flex: 1; }\n.admin-bulk-toolbar .uid-button {\n background: transparent;\n border-color: rgba(255, 255, 255, 0.15);\n color: var(--uid-color-zinc-100, #f4f4f5);\n}\n.admin-bulk-toolbar .uid-button:hover:not([disabled]) {\n background: rgba(255, 255, 255, 0.08);\n}\n.admin-bulk-toolbar .uid-button--danger {\n color: var(--uid-color-rose-400, #fb7185);\n}\n\n/* Selected row tint */\n.admin-resource-index__row--selected {\n background: color-mix(in srgb, var(--uid-accent) 8%, transparent);\n}\n</style>\n","/**\n * useResourceFormStore — state для Resource Create/Edit/View screens.\n *\n * Управляет:\n * - mode ('create' | 'edit' | 'view')\n * - record (raw из API), state (working copy в form-state, но мы держим\n * reference на initial для unsaved-changes detection)\n * - errors (field-keyed) — устанавливаются при ValidationError\n * - loading/saving/deleting — для disable submit / show spinner\n * - dirty (computed) — есть ли несохранённые изменения\n *\n * Endpoints (laravel-admin contract):\n * GET /{slug}/read — fetch one (id в query)\n * POST /{slug}/create\n * POST /{slug}/update\n * POST /{slug}/delete\n */\n\nimport { defineStore } from 'pinia'\nimport { computed, ref } from 'vue'\nimport { getAdminClient } from './registry'\nimport { ApiError, ValidationError } from '../api/errors'\n\nexport type FormMode = 'create' | 'edit' | 'view'\n\ninterface ReadResponse {\n // backend ResourceController::read возвращает payload {record}.\n record: Record<string, unknown>\n}\n\ninterface SaveResponse {\n // backend create/update возвращает payload {record, redirect_url, message}.\n record?: Record<string, unknown>\n id?: string | number\n redirect_url?: string\n message?: string\n}\n\nexport const useResourceFormStore = defineStore('admin-resource-form', () => {\n const slug = ref<string | null>(null)\n const mode = ref<FormMode>('create')\n const recordId = ref<string | number | null>(null)\n\n /** Текущее состояние формы — мутируется через setField. */\n const state = ref<Record<string, unknown>>({})\n /** Snapshot изначальных значений (после load) — для dirty-detection. */\n const initial = ref<Record<string, unknown>>({})\n\n /** Field-keyed errors. Очищаются при successful save. */\n const errors = ref<Record<string, string[]>>({})\n\n const loading = ref(false)\n const saving = ref(false)\n const deleting = ref(false)\n const error = ref<Error | null>(null)\n\n const isCreate = computed(() => mode.value === 'create')\n const isEdit = computed(() => mode.value === 'edit')\n const isView = computed(() => mode.value === 'view')\n const hasError = computed(() => error.value !== null)\n\n /** Dirty: state отличается от initial хотя бы по одному ключу. */\n const isDirty = computed(() => {\n const a = state.value\n const b = initial.value\n const keys = new Set([...Object.keys(a), ...Object.keys(b)])\n for (const k of keys) {\n if (!Object.is(a[k], b[k])) {\n // Простое сравнение скаляров; объекты/массивы сравниваем JSON-сериализацией.\n if (typeof a[k] === 'object' || typeof b[k] === 'object') {\n if (JSON.stringify(a[k]) !== JSON.stringify(b[k])) return true\n } else {\n return true\n }\n }\n }\n return false\n })\n\n /** In-place мутация reactive-объекта — сохраняет identity для provide/inject. */\n function replaceObject(target: Record<string, unknown>, next: Record<string, unknown>): void {\n for (const k of Object.keys(target)) delete target[k]\n Object.assign(target, next)\n }\n\n function reset(): void {\n replaceObject(state.value, {})\n replaceObject(initial.value, {})\n errors.value = {}\n loading.value = false\n saving.value = false\n deleting.value = false\n error.value = null\n recordId.value = null\n }\n\n /** Подготовить store для create-mode на ресурсе. */\n function prepareCreate(resourceSlug: string, defaults: Record<string, unknown> = {}): void {\n slug.value = resourceSlug\n mode.value = 'create'\n recordId.value = null\n replaceObject(state.value, defaults)\n replaceObject(initial.value, defaults)\n errors.value = {}\n error.value = null\n }\n\n /** Загрузить запись для edit либо view-режима. */\n async function load(\n resourceSlug: string,\n id: string | number,\n targetMode: 'edit' | 'view' = 'edit',\n ): Promise<void> {\n slug.value = resourceSlug\n mode.value = targetMode\n recordId.value = id\n loading.value = true\n error.value = null\n errors.value = {}\n\n try {\n const client = getAdminClient()\n const res = await client.get<ReadResponse>(`/${resourceSlug}/read`, {\n params: { id },\n })\n replaceObject(state.value, res.record)\n replaceObject(initial.value, res.record)\n } catch (err) {\n error.value = err instanceof Error ? err : new Error(String(err))\n throw err\n } finally {\n loading.value = false\n }\n }\n\n /** Установить значение поля (через FormState composable обычно). */\n function setField(name: string, value: unknown): void {\n state.value[name] = value\n if (errors.value[name]) {\n // Очищаем ошибку конкретного поля при изменении (стандартный UX).\n const next = { ...errors.value }\n delete next[name]\n errors.value = next\n }\n }\n\n function setErrors(next: Record<string, string[]>): void {\n errors.value = { ...next }\n }\n\n function clearErrors(): void {\n errors.value = {}\n }\n\n /**\n * Сохранить. На create — POST /create; на edit — POST /update с id.\n * Возвращает new id (для post-create редиректа).\n */\n async function save(): Promise<string | number> {\n if (!slug.value) throw new Error('useResourceFormStore.save() before slug set')\n if (saving.value) throw new Error('Already saving')\n\n saving.value = true\n error.value = null\n errors.value = {}\n\n try {\n const client = getAdminClient()\n const url =\n mode.value === 'create'\n ? `/${slug.value}/create`\n : `/${slug.value}/update`\n\n const payload =\n mode.value === 'create'\n ? state.value\n : { id: recordId.value, ...state.value }\n\n const res = await client.post<SaveResponse>(url, payload)\n // Backend отдаёт `record: {id, ...}`. Старый формат `{id}` тоже поддерживаем.\n const newId = (res.record?.id ?? res.id) as string | number | undefined\n if (newId === undefined) {\n throw new Error('save: backend response does not contain record.id')\n }\n recordId.value = newId\n // После успешного save обновим initial = state, чтобы dirty=false.\n replaceObject(initial.value, { ...state.value })\n mode.value = 'edit'\n return newId\n } catch (err) {\n if (err instanceof ValidationError) {\n errors.value = { ...err.fields }\n } else if (err instanceof ApiError) {\n error.value = err\n } else if (err instanceof Error) {\n error.value = err\n }\n throw err\n } finally {\n saving.value = false\n }\n }\n\n /** Удалить текущую запись (только в edit-mode). */\n async function destroy(): Promise<void> {\n if (!slug.value || recordId.value === null) {\n throw new Error('Nothing to delete')\n }\n if (deleting.value) throw new Error('Already deleting')\n\n deleting.value = true\n error.value = null\n try {\n const client = getAdminClient()\n await client.post(`/${slug.value}/delete`, { id: recordId.value })\n } catch (err) {\n if (err instanceof Error) error.value = err\n throw err\n } finally {\n deleting.value = false\n }\n }\n\n return {\n // state\n slug,\n mode,\n recordId,\n state,\n initial,\n errors,\n loading,\n saving,\n deleting,\n error,\n // getters\n isCreate,\n isEdit,\n isView,\n isDirty,\n hasError,\n // actions\n reset,\n prepareCreate,\n load,\n setField,\n setErrors,\n clearErrors,\n save,\n destroy,\n }\n})\n","/**\n * Реестр Vue-компонентов для JSON-driven рендеринга.\n *\n * Содержит две Map'ы — для `field`-типов (input'ы, контролы) и для\n * `layout`-типов (контейнеры). LayoutRenderer и FieldRenderer резолвят тип\n * через эти реестры; host-проект может зарегистрировать кастомные компоненты\n * через `registerField()` / `registerLayout()`.\n *\n * Singleton — один регистр на admin-instance. Тестовый сценарий —\n * `clearRegistry()` + `registerField()` в `beforeEach`.\n */\n\nimport type { Component } from 'vue'\nimport { createComponentRegistry } from '../createComponentRegistry'\n\nconst fields = createComponentRegistry<Component>()\nconst layouts = createComponentRegistry<Component>()\n\nexport const registerField = fields.register\nexport const getField = fields.get\nexport const hasField = fields.has\nexport const listFields = fields.list\n\nexport const registerLayout = layouts.register\nexport const getLayout = layouts.get\nexport const hasLayout = layouts.has\nexport const listLayouts = layouts.list\n\n/** Очистить оба реестра. Используется в тестах. */\nexport function clearRegistry(): void {\n fields.clear()\n layouts.clear()\n}\n\n/**\n * Зарегистрировать сразу несколько компонентов.\n *\n * registerComponents({\n * fields: { text: TextField, select: SelectField },\n * layouts: { rows: RowsLayout, tabs: TabsLayout },\n * })\n */\nexport interface ComponentBundle {\n fields?: Record<string, Component>\n layouts?: Record<string, Component>\n}\n\nexport function registerComponents(bundle: ComponentBundle): void {\n if (bundle.fields) fields.registerBundle(bundle.fields)\n if (bundle.layouts) layouts.registerBundle(bundle.layouts)\n}\n","<script setup lang=\"ts\">\n/**\n * Fallback на missing field-registration. Видимый dev-warn вместо silent fail —\n * host-проект сразу замечает unregistered field-type.\n */\nimport { UidAlert } from '@dskripchenko/ui'\n\ninterface Props {\n type: string\n name?: string\n}\ndefineProps<Props>()\n</script>\n\n<template>\n <UidAlert variant=\"warning\">\n <template #title>Неизвестный тип поля: {{ type }}</template>\n <template v-if=\"name\">\n <code>{{ name }}</code> — зарегистрируйте field-компонент через\n <code>registerField('{{ type }}', YourComponent)</code>.\n </template>\n </UidAlert>\n</template>\n","<script setup lang=\"ts\">\n/**\n * FieldRenderer резолвит конкретный field-компонент по `node.type` из реестра\n * и forwards остальные props через v-bind.\n *\n * Узлы манифеста имеют форму:\n * { type: 'text', name: 'title', label: 'Заголовок', required: true, ... }\n *\n * Field хранит value через provide/inject form-state — узлу не передаётся\n * `modelValue` напрямую. Это позволяет строить произвольно-глубокие layout'ы\n * без явного proppin'га state'а.\n */\nimport { computed } from 'vue'\nimport { getField } from './registry'\nimport UnknownField from '../fields/UnknownField.vue'\n\nexport interface FieldNode extends Record<string, unknown> {\n type: string\n name: string\n}\n\ninterface Props {\n node: FieldNode\n}\n\nconst props = defineProps<Props>()\nconst component = computed(() => getField(props.node.type))\nconst fieldProps = computed(() => {\n // Backend Field::toArray() кладёт type-specific опции в `attributes`\n // (suggestions, options, multiple, currency и т.п.). Разворачиваем их\n // на верхний уровень — Field-компоненты ожидают props без обёртки.\n const { type: _type, attributes, ...rest } = props.node\n const attrs = (attributes as Record<string, unknown> | undefined) ?? {}\n return { ...rest, ...attrs }\n})\n</script>\n\n<template>\n <component :is=\"component\" v-if=\"component\" v-bind=\"fieldProps\" />\n <UnknownField v-else :type=\"node.type\" :name=\"node.name\" />\n</template>\n","<script setup lang=\"ts\">\n/**\n * Универсальный рекурсивный renderer manifest-узлов.\n *\n * Узел вида `{ kind: 'field', type: 'text', name: 'title', ... }` рендерится\n * через FieldRenderer. Узел вида `{ kind: 'layout', type: 'rows', items: [...] }`\n * — через зарегистрированный layout-компонент с children-списком.\n *\n * Для совместимости со старыми JSON'ами без `kind` — если type есть в\n * field-registry, считаем field; если в layout-registry — считаем layout;\n * иначе — UnknownField fallback.\n */\nimport { computed } from 'vue'\nimport { getField, getLayout } from './registry'\nimport FieldRenderer, { type FieldNode } from './FieldRenderer.vue'\nimport UnknownField from '../fields/UnknownField.vue'\n\nexport interface LayoutNode extends Record<string, unknown> {\n type: string\n kind?: 'field' | 'layout'\n items?: LayoutNode[]\n}\n\ninterface Props {\n node: LayoutNode\n}\nconst props = defineProps<Props>()\n\ntype Resolved =\n | { kind: 'field' }\n | { kind: 'layout'; component: ReturnType<typeof getLayout> }\n | { kind: 'unknown' }\n\nconst resolved = computed<Resolved>(() => {\n // Явный hint через `kind` всегда приоритетнее.\n if (props.node.kind === 'field') {\n return { kind: 'field' }\n }\n if (props.node.kind === 'layout') {\n const component = getLayout(props.node.type)\n return component ? { kind: 'layout', component } : { kind: 'unknown' }\n }\n // Auto-detect.\n const layoutComponent = getLayout(props.node.type)\n if (layoutComponent) return { kind: 'layout', component: layoutComponent }\n if (getField(props.node.type)) return { kind: 'field' }\n return { kind: 'unknown' }\n})\n\nconst layoutProps = computed(() => {\n const { type: _type, kind: _kind, ...rest } = props.node\n return rest\n})\n\nconst fieldNode = computed<FieldNode>(() => props.node as unknown as FieldNode)\n</script>\n\n<template>\n <component\n :is=\"resolved.component\"\n v-if=\"resolved.kind === 'layout' && resolved.component\"\n v-bind=\"layoutProps\"\n />\n <FieldRenderer v-else-if=\"resolved.kind === 'field'\" :node=\"fieldNode\" />\n <UnknownField v-else :type=\"node.type\" :name=\"(node.name as string | undefined)\" />\n</template>\n","<script setup lang=\"ts\">\n/**\n * ResourceFormPage — unified create/edit page для Resource'а.\n *\n * Архитектура по docs/design_handoff_laravel_admin/screens-shell.jsx\n * (Resource Form):\n * - Header: back-breadcrumb + title + status-badge + actions\n * (Preview / Удалить / Сохранить-primary)\n * - Body: layout из manifest.fields (LayoutRenderer + provideFormState)\n * - Sticky save-bar внизу с unsaved-changes hint\n *\n * Mode определяется наличием `id`-prop'а: id=null → create, иначе → edit.\n *\n * Form-state предоставляется через provideFormState из useResourceFormStore.state.\n * FieldRenderer'ы внутри форм автоматически подхватывают через useFormState.\n */\nimport { computed, onMounted, watch } from 'vue'\nimport { useRouter } from 'vue-router'\nimport {\n UidAlert,\n UidBadge,\n UidButton,\n UidCard,\n UidSkeleton,\n} from '@dskripchenko/ui'\nimport { useResourceFormStore } from '../../stores/resourceForm'\nimport { useManifestStore } from '../../stores/manifest'\nimport { provideFormState } from '../render/formState'\nimport LayoutRenderer from '../render/LayoutRenderer.vue'\nimport type { LayoutNode } from '../render/LayoutRenderer.vue'\n\ninterface Props {\n /** Slug ресурса (articles/users/etc). */\n slug: string\n /** ID записи. null/undefined → create-mode; число/строка → edit. */\n id?: string | number | null\n /**\n * Override имени router-route для back-redirect после save/delete.\n * По умолчанию выводится из slug: `admin.resource.{slug}.index`.\n */\n indexRouteName?: string | null\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n id: null,\n indexRouteName: null,\n})\n\nconst form = useResourceFormStore()\nconst manifest = useManifestStore()\nconst router = useRouter()\n\n// provideFormState ОБЯЗАН вызываться в setup() — связываем со store.state.\n// Сам form-context форвардит setField → store.setField (с auto-clear errors).\nconst ctx = provideFormState(form.state, form.errors)\n\n// Watcher: при изменениях через ctx.setField (обёртка которой) — синхронизируем\n// в store, чтобы isDirty работало. Поскольку state.value === ctx.state (тот же\n// reactive object — provideFormState не делает копию), мутации видны напрямую\n// в store. setField'у в ctx достаточно.\nwatch(\n () => form.errors,\n (next) => {\n // При обновлении store.errors — выкидываем в form-context.\n ctx.setErrors({ ...next })\n },\n)\n\nconst resourceMeta = computed(() => manifest.getResource(props.slug))\n\nconst layoutNodes = computed<LayoutNode[]>(\n () => resourceMeta.value?.fields ?? [],\n)\n\nconst titleLabel = computed(() => {\n if (form.isCreate) return `Создать: ${resourceMeta.value?.label ?? props.slug}`\n return `${resourceMeta.value?.label ?? props.slug}: запись #${props.id}`\n})\n\nconst statusValue = computed<string | null>(() => {\n const v = form.state.status\n return typeof v === 'string' ? v : null\n})\n\nconst statusBadgeVariant = computed<'success' | 'warning' | 'danger' | 'default'>(() => {\n switch (statusValue.value) {\n case 'published': return 'success'\n case 'review':\n case 'draft': return 'warning'\n case 'archived': return 'danger'\n default: return 'default'\n }\n})\n\nonMounted(async () => {\n if (manifest.manifest === null) {\n await manifest.load().catch(() => undefined)\n }\n if (props.id !== null && props.id !== undefined) {\n await form.load(props.slug, props.id, 'edit').catch(() => undefined)\n } else {\n form.prepareCreate(props.slug)\n }\n})\n\nwatch(\n () => [props.slug, props.id] as const,\n async ([nextSlug, nextId]) => {\n if (nextId !== null && nextId !== undefined) {\n await form.load(nextSlug, nextId, 'edit').catch(() => undefined)\n } else {\n form.prepareCreate(nextSlug)\n }\n },\n)\n\nasync function onSave(): Promise<void> {\n try {\n const newId = await form.save()\n if (form.isCreate) {\n // create → редирект на edit с новым id (host route'ит).\n void router.push({\n name: `admin.resource.${props.slug}.edit`,\n params: { id: newId },\n }).catch(() => undefined)\n }\n } catch {\n // ValidationError уже превратился в form.errors через store; остальные\n // ошибки попали в form.error и отрисуются как UidAlert ниже.\n }\n}\n\n/**\n * Auto-derive index route name из slug (`admin.resource.{slug}.index`),\n * если host не передал indexRouteName явно. Это нужно чтобы back/cancel\n * вели на список ресурса, а не на главную админки.\n */\nconst resolvedIndexRouteName = computed<string>(\n () => props.indexRouteName ?? `admin.resource.${props.slug}.index`,\n)\n\nasync function onDelete(): Promise<void> {\n if (!confirm('Удалить запись?')) return\n await form.destroy().catch(() => undefined)\n if (!form.hasError) {\n void router.push({ name: resolvedIndexRouteName.value }).catch(() => undefined)\n }\n}\n\nfunction onCancel(): void {\n if (form.isDirty && !confirm('Несохранённые изменения будут потеряны. Продолжить?')) {\n return\n }\n void router.push({ name: resolvedIndexRouteName.value }).catch(() => undefined)\n}\n</script>\n\n<template>\n <section class=\"admin-page admin-resource-form\">\n <header class=\"admin-page__hd\">\n <div class=\"admin-page__title-wrap\">\n <a class=\"admin-resource-form__back\" @click=\"onCancel\">← Назад</a>\n <h1 class=\"admin-page__title\">{{ titleLabel }}</h1>\n <UidBadge v-if=\"statusValue\" :variant=\"statusBadgeVariant\">\n {{ statusValue }}\n </UidBadge>\n </div>\n <div class=\"admin-page__actions\">\n <UidButton\n variant=\"ghost\"\n :disabled=\"form.saving || form.deleting\"\n @click=\"onCancel\"\n >\n Отмена\n </UidButton>\n <UidButton\n v-if=\"form.isEdit\"\n variant=\"danger\"\n :disabled=\"form.saving || form.deleting\"\n :loading=\"form.deleting\"\n @click=\"onDelete\"\n >\n Удалить\n </UidButton>\n <UidButton\n variant=\"primary\"\n :disabled=\"form.saving || form.loading\"\n :loading=\"form.saving\"\n @click=\"onSave\"\n >\n {{ form.isCreate ? 'Создать' : 'Сохранить' }}\n </UidButton>\n </div>\n </header>\n\n <UidAlert\n v-if=\"form.hasError\"\n variant=\"danger\"\n class=\"admin-resource-form__alert\"\n role=\"alert\"\n >\n {{ form.error?.message ?? 'Не удалось сохранить запись' }}\n </UidAlert>\n\n <!-- Loading state — UidSkeleton imitates form-rows -->\n <div v-if=\"form.loading\" class=\"admin-resource-form__loading\">\n <UidSkeleton v-for=\"i in 6\" :key=\"i\" height=\"40px\" />\n </div>\n\n <!-- Body: layout из manifest -->\n <UidCard v-else padding=\"md\" class=\"admin-resource-form__body\">\n <LayoutRenderer\n v-for=\"(node, idx) in layoutNodes\"\n :key=\"idx\"\n :node=\"node\"\n />\n </UidCard>\n\n <!-- Sticky save-bar — показывается при unsaved-changes -->\n <div v-if=\"form.isDirty && !form.loading\" class=\"admin-resource-form__savebar\">\n <span class=\"admin-resource-form__savebar-hint\">\n Есть несохранённые изменения\n </span>\n <UidButton variant=\"ghost\" size=\"sm\" @click=\"onCancel\">Отмена</UidButton>\n <UidButton\n variant=\"primary\"\n size=\"sm\"\n :loading=\"form.saving\"\n :disabled=\"form.saving\"\n @click=\"onSave\"\n >\n Сохранить\n </UidButton>\n </div>\n </section>\n</template>\n\n<style>\n.admin-resource-form__back {\n font-size: var(--uid-font-size-xs);\n color: var(--uid-text-secondary);\n cursor: pointer;\n text-decoration: none;\n display: inline-block;\n margin-bottom: 4px;\n}\n.admin-resource-form__back:hover { color: var(--uid-text-primary); }\n\n.admin-resource-form__alert {\n margin-bottom: var(--uid-space-md);\n}\n.admin-resource-form__loading {\n display: flex;\n flex-direction: column;\n gap: var(--uid-space-sm);\n}\n.admin-resource-form__body { margin-bottom: var(--uid-space-2xl); }\n\n.admin-resource-form__savebar {\n position: sticky;\n bottom: 0;\n display: flex;\n align-items: center;\n gap: var(--uid-space-sm);\n padding: var(--uid-space-sm) var(--uid-space-md);\n background: var(--uid-surface-raised);\n border-top: 1px solid var(--uid-border-default);\n border-radius: var(--uid-radius-md);\n box-shadow: var(--uid-shadow-md);\n margin-top: var(--uid-space-md);\n}\n.admin-resource-form__savebar-hint {\n flex: 1;\n font-size: 13px;\n color: var(--uid-warning);\n}\n</style>\n","/**\n * Реестр infolist-entry-компонентов.\n *\n * Аналог field-registry, но для read-only display'я. Узлы манифеста имеют\n * форму:\n * { type: 'text', name: 'title', label: 'Заголовок', value?: '...' }\n * либо без явного `value` — тогда entry извлекает `record[name]` из\n * provide'нутого `record`.\n *\n * Host регистрирует кастомные entry через `registerInfolistEntry()` /\n * `registerInfolistEntries()` bundle.\n */\n\nimport type { Component } from 'vue'\nimport { createComponentRegistry } from '../createComponentRegistry'\n\nconst entries = createComponentRegistry<Component>()\n\nexport const registerInfolistEntry = entries.register\nexport const getInfolistEntry = entries.get\nexport const hasInfolistEntry = entries.has\nexport const listInfolistEntries = entries.list\nexport const clearInfolistRegistry = entries.clear\nexport const registerInfolistEntries = entries.registerBundle\n","<script setup lang=\"ts\">\nimport { UidAlert } from '@dskripchenko/ui'\n\ninterface Props {\n type: string\n name?: string\n}\ndefineProps<Props>()\n</script>\n\n<template>\n <UidAlert variant=\"warning\">\n <template #title>Неизвестный тип infolist-entry: {{ type }}</template>\n Зарегистрируйте через <code>registerInfolistEntry('{{ type }}', YourComponent)</code>.\n </UidAlert>\n</template>\n","<script setup lang=\"ts\">\n/**\n * InfolistRenderer — read-only аналог LayoutRenderer для view-страниц.\n *\n * Узлы:\n * { type: 'text', name: 'title', label: 'Заголовок' } — entry (leaf)\n * { type: 'rows', items: [ ... ] } — layout (recurse)\n * { type: 'section', title: 'X', items: [ ... ] } — layout\n * { type: 'columns', items: [ ... ] } — layout\n *\n * Внимание: layout-узлы рендерятся СВОИМ внутренним wrapper'ом, а не\n * registered uid-layouts из render/registry, потому что те делегируют детей\n * в LayoutRenderer (field-registry → useFormState ОБЯЗАТЕЛЕН). Здесь record-\n * read-only режим — детей рендерим через сам InfolistRenderer.\n */\nimport { computed } from 'vue'\nimport { getInfolistEntry } from './registry'\nimport UnknownEntry from './UnknownEntry.vue'\n\nexport interface InfolistNode extends Record<string, unknown> {\n type: string\n /** Hint: 'entry' либо 'layout'. */\n kind?: 'entry' | 'layout'\n items?: InfolistNode[]\n}\n\ninterface Props {\n node: InfolistNode\n}\nconst props = defineProps<Props>()\n\nconst KNOWN_LAYOUTS = new Set(['rows', 'columns', 'section', 'block', 'tabs'])\n\ntype Resolved =\n | { kind: 'entry'; component: NonNullable<ReturnType<typeof getInfolistEntry>> }\n | { kind: 'layout'; layoutType: string }\n | { kind: 'unknown' }\n\nconst resolved = computed<Resolved>(() => {\n if (props.node.kind === 'entry') {\n const c = getInfolistEntry(props.node.type)\n return c ? { kind: 'entry', component: c } : { kind: 'unknown' }\n }\n if (props.node.kind === 'layout') {\n return KNOWN_LAYOUTS.has(props.node.type)\n ? { kind: 'layout', layoutType: props.node.type }\n : { kind: 'unknown' }\n }\n // Auto-detect: layouts по имени, entries по registry.\n if (KNOWN_LAYOUTS.has(props.node.type)) {\n return { kind: 'layout', layoutType: props.node.type }\n }\n const entry = getInfolistEntry(props.node.type)\n if (entry) return { kind: 'entry', component: entry }\n return { kind: 'unknown' }\n})\n\nconst entryProps = computed(() => {\n const { type: _t, kind: _k, items: _i, attributes, ...rest } = props.node\n // Backend кладёт preset/format/etc в `attributes` под-объект (см.\n // Infolist\\Entry::toArray). Flat'имся для удобства Vue v-bind:\n // attributes.preset → preset prop, attributes.format → meta.format.\n const attrs = (attributes as Record<string, unknown> | undefined) ?? {}\n const { preset, format, currency, decimals, trueLabel, falseLabel, ...rest2 } = attrs\n const meta: Record<string, unknown> = {}\n if (format !== undefined) meta.format = format\n if (currency !== undefined) meta.currency = currency\n if (decimals !== undefined) meta.decimals = decimals\n if (trueLabel !== undefined) meta.trueLabel = trueLabel\n if (falseLabel !== undefined) meta.falseLabel = falseLabel\n return { ...rest, ...rest2, preset, meta }\n})\n\nconst items = computed<InfolistNode[]>(\n () => (props.node.items ?? []) as InfolistNode[],\n)\n\nconst sectionTitle = computed(() => (props.node.title as string | undefined) ?? null)\nconst sectionDescription = computed(\n () => (props.node.description as string | undefined) ?? null,\n)\nconst tabsActive = computed<number>(() => {\n const a = props.node.active\n return typeof a === 'number' ? a : 0\n})\n\ninterface InfolistTab {\n key?: string\n label: string\n items: InfolistNode[]\n}\nconst tabsList = computed<InfolistTab[]>(() => {\n return (props.node.items ?? []) as unknown as InfolistTab[]\n})\n</script>\n\n<template>\n <!-- Entry -->\n <component\n :is=\"resolved.component\"\n v-if=\"resolved.kind === 'entry'\"\n v-bind=\"entryProps\"\n />\n\n <!-- Layout: rows -->\n <div\n v-else-if=\"resolved.kind === 'layout' && resolved.layoutType === 'rows'\"\n class=\"admin-infolist-rows\"\n >\n <InfolistRenderer\n v-for=\"(child, idx) in items\"\n :key=\"idx\"\n :node=\"child\"\n />\n </div>\n\n <!-- Layout: columns (12-grid с per-item span) -->\n <div\n v-else-if=\"resolved.kind === 'layout' && resolved.layoutType === 'columns'\"\n class=\"admin-infolist-cols\"\n >\n <div\n v-for=\"(child, idx) in items\"\n :key=\"idx\"\n class=\"admin-infolist-cols__item\"\n :style=\"{\n gridColumn: `span ${\n typeof (child as Record<string, unknown>).span === 'number'\n ? (child as Record<string, unknown>).span\n : Math.max(1, Math.floor(12 / items.length))\n }`,\n }\"\n >\n <InfolistRenderer :node=\"child\" />\n </div>\n </div>\n\n <!-- Layout: section / block -->\n <section\n v-else-if=\"resolved.kind === 'layout' && (resolved.layoutType === 'section' || resolved.layoutType === 'block')\"\n class=\"admin-infolist-section\"\n >\n <header v-if=\"sectionTitle || sectionDescription\" class=\"admin-infolist-section__hd\">\n <h3 v-if=\"sectionTitle\" class=\"admin-infolist-section__title\">{{ sectionTitle }}</h3>\n <p v-if=\"sectionDescription\" class=\"admin-infolist-section__description\">\n {{ sectionDescription }}\n </p>\n </header>\n <div class=\"admin-infolist-section__body\">\n <InfolistRenderer\n v-for=\"(child, idx) in items\"\n :key=\"idx\"\n :node=\"child\"\n />\n </div>\n </section>\n\n <!-- Layout: tabs (минимальные — без переключения, показываем active по prop'у) -->\n <div\n v-else-if=\"resolved.kind === 'layout' && resolved.layoutType === 'tabs'\"\n class=\"admin-infolist-tabs\"\n >\n <ul class=\"admin-infolist-tabs__list\" role=\"tablist\">\n <li\n v-for=\"(tab, idx) in tabsList\"\n :key=\"tab.key ?? idx\"\n :class=\"[\n 'admin-infolist-tabs__tab',\n { 'admin-infolist-tabs__tab--active': idx === tabsActive },\n ]\"\n >\n {{ tab.label }}\n </li>\n </ul>\n <div class=\"admin-infolist-tabs__panel\">\n <InfolistRenderer\n v-for=\"(child, idx) in tabsList[tabsActive]?.items ?? []\"\n :key=\"idx\"\n :node=\"child\"\n />\n </div>\n </div>\n\n <UnknownEntry v-else :type=\"node.type\" :name=\"(node.name as string | undefined)\" />\n</template>\n\n<style>\n.admin-infolist-rows {\n display: flex;\n flex-direction: column;\n gap: var(--uid-space-sm);\n}\n.admin-infolist-cols {\n display: grid;\n grid-template-columns: repeat(12, minmax(0, 1fr));\n gap: var(--uid-space-md);\n}\n.admin-infolist-section {\n margin-bottom: var(--uid-space-md);\n padding: var(--uid-space-md);\n border: 1px solid var(--uid-border-subtle);\n border-radius: var(--uid-radius-lg);\n background: var(--uid-surface-raised);\n}\n.admin-infolist-section__hd { margin-bottom: var(--uid-space-sm); }\n.admin-infolist-section__title {\n margin: 0;\n font-size: var(--uid-font-size-sm);\n font-weight: var(--uid-font-weight-semibold);\n}\n.admin-infolist-section__description {\n margin: var(--uid-space-2xs) 0 0;\n font-size: var(--uid-font-size-xs);\n color: var(--uid-text-tertiary);\n}\n.admin-infolist-section__body {\n display: flex;\n flex-direction: column;\n gap: var(--uid-space-sm);\n}\n.admin-infolist-tabs__list {\n list-style: none;\n margin: 0 0 var(--uid-space-sm);\n padding: 0;\n display: flex;\n gap: var(--uid-space-xs);\n border-bottom: 1px solid var(--uid-border-subtle);\n}\n.admin-infolist-tabs__tab {\n padding: var(--uid-space-sm) var(--uid-space-sm);\n font-size: 13px;\n color: var(--uid-text-secondary);\n border-bottom: 2px solid transparent;\n}\n.admin-infolist-tabs__tab--active {\n color: var(--uid-text-primary);\n border-bottom-color: var(--uid-accent);\n font-weight: var(--uid-font-weight-medium);\n}\n</style>\n","/**\n * Composable для read-only record-контекста, передаваемого Infolist'ом.\n *\n * Контейнер (ResourceViewPage) вызывает `provideRecord(record)`, entry-\n * компоненты — `useRecord()` для чтения значения.\n */\n\nimport { inject, provide, type InjectionKey } from 'vue'\n\nconst RecordKey: InjectionKey<Record<string, unknown>> = Symbol('admin.infolist-record')\n\nexport function provideRecord(record: Record<string, unknown>): void {\n provide(RecordKey, record)\n}\n\nexport function useRecord(): Record<string, unknown> {\n const r = inject(RecordKey)\n if (!r) {\n throw new Error('useRecord() called outside of provideRecord() scope')\n }\n return r\n}\n\nexport function tryUseRecord(): Record<string, unknown> | null {\n return inject(RecordKey, null) as Record<string, unknown> | null\n}\n","<script setup lang=\"ts\">\n/**\n * AuditTimeline — список изменений конкретной записи.\n *\n * Грузит GET /audit/timeline?subject_type={…}&subject_id={…} (см. backend\n * AuditController::timeline) и рендерит вертикальный timeline по дизайну\n * docs/design_handoff_laravel_admin (Resource View → История изменений).\n *\n * subjectType — Eloquent morph-class модели (например 'App\\\\Models\\\\Article'\n * или 'article' если используется map). Если не задан — компонент молча\n * не рендерит timeline (host не включил аудит).\n */\nimport { computed, onMounted, ref, watch } from 'vue'\nimport {\n Edit,\n Plus,\n Tag,\n Trash2,\n type LucideIcon,\n} from 'lucide-vue-next'\nimport { UidAvatar, UidIcon, UidSkeleton } from '@dskripchenko/ui'\n\ninterface AuditActor {\n id: number | string\n type: string\n name: string | null\n}\ninterface AuditEntry {\n id: number\n event: string\n created_at: string\n actor: AuditActor | null\n summary: string\n diff: Array<{ field: string; before: unknown; after: unknown }> | null\n}\n\ninterface Props {\n /**\n * Eloquent morph-class либо FQCN модели. Может быть пустой строкой /\n * null — компонент в этом случае не делает запрос и показывает\n * пустой state. Это нужно чтобы блок «История изменений» был всегда\n * виден на view-странице даже когда у Resource не задан model-class.\n */\n subjectType: string | null\n subjectId: string | number\n}\nconst props = defineProps<Props>()\n\nconst items = ref<AuditEntry[]>([])\nconst loading = ref<boolean>(false)\nconst error = ref<Error | null>(null)\n\nasync function load(): Promise<void> {\n // Без subject_type делать запрос бессмысленно — backend ожидает required\n // строку. Просто показываем пустой state.\n if (!props.subjectType || props.subjectType === '') {\n items.value = []\n loading.value = false\n error.value = null\n return\n }\n loading.value = true\n error.value = null\n try {\n const { getAdminClient } = await import('../../stores/registry')\n const client = getAdminClient()\n const result = await client.get<{ data: AuditEntry[] }>(\n `/audit/timeline?subject_type=${encodeURIComponent(props.subjectType)}&subject_id=${encodeURIComponent(String(props.subjectId))}`,\n )\n items.value = result.data ?? []\n } catch (err) {\n error.value = err instanceof Error ? err : new Error(String(err))\n items.value = []\n } finally {\n loading.value = false\n }\n}\n\nonMounted(load)\nwatch(() => [props.subjectType, props.subjectId] as const, load)\n\nconst hasItems = computed<boolean>(() => items.value.length > 0)\n\nfunction eventIcon(event: string): LucideIcon {\n if (event === 'created') return Plus\n if (event === 'deleted' || event === 'destroyed') return Trash2\n if (event.includes('tag') || event.includes('label')) return Tag\n return Edit\n}\n\nfunction eventLabel(event: string): string {\n const map: Record<string, string> = {\n created: 'создал',\n updated: 'отредактировал',\n deleted: 'удалил',\n destroyed: 'удалил',\n restored: 'восстановил',\n published: 'опубликовал',\n }\n return map[event] ?? event\n}\n\nfunction relativeTime(iso: string): string {\n const ts = new Date(iso).getTime()\n if (Number.isNaN(ts)) return ''\n const diff = (Date.now() - ts) / 1000\n if (diff < 60) return `${Math.max(1, Math.floor(diff))} сек назад`\n if (diff < 3600) return `${Math.floor(diff / 60)} мин назад`\n if (diff < 86_400) return `${Math.floor(diff / 3600)} ч назад`\n if (diff < 86_400 * 30) return `${Math.floor(diff / 86_400)} д назад`\n return new Date(iso).toLocaleDateString('ru-RU')\n}\n\nfunction diffSummary(entry: AuditEntry): string {\n if (entry.summary) return entry.summary\n if (!entry.diff || entry.diff.length === 0) return ''\n if (entry.diff.length === 1) {\n const d = entry.diff[0]\n return `Поле ${d.field}: ${formatVal(d.before)} → ${formatVal(d.after)}`\n }\n const fields = entry.diff.slice(0, 4).map((d) => d.field).join(', ')\n return `Изменены ${entry.diff.length} поля: ${fields}`\n}\n\nfunction formatVal(v: unknown): string {\n if (v === null || v === undefined) return '∅'\n if (typeof v === 'string') return v.length > 20 ? `${v.slice(0, 20)}…` : v\n return String(v)\n}\n</script>\n\n<template>\n <section class=\"admin-audit-timeline\">\n <h2 class=\"admin-audit-timeline__title\">История изменений</h2>\n\n <div v-if=\"loading\" class=\"admin-audit-timeline__loading\">\n <UidSkeleton v-for=\"i in 3\" :key=\"i\" height=\"48px\" />\n </div>\n\n <div v-else-if=\"error\" class=\"admin-audit-timeline__error\">\n Не удалось загрузить историю: {{ error.message }}\n </div>\n\n <div v-else-if=\"!hasItems\" class=\"admin-audit-timeline__empty\">\n Записей в истории пока нет.\n </div>\n\n <ol v-else class=\"admin-audit-timeline__list\">\n <li\n v-for=\"entry in items\"\n :key=\"entry.id\"\n class=\"admin-audit-timeline__item\"\n >\n <span class=\"admin-audit-timeline__icon\" aria-hidden=\"true\">\n <UidIcon :icon=\"eventIcon(entry.event)\" :size=\"14\" />\n </span>\n <div class=\"admin-audit-timeline__body\">\n <div class=\"admin-audit-timeline__row\">\n <UidAvatar\n :name=\"entry.actor?.name ?? '?'\"\n :alt=\"entry.actor?.name ?? 'Неизвестный'\"\n size=\"xs\"\n />\n <span class=\"admin-audit-timeline__actor\">\n {{ entry.actor?.name ?? 'Система' }}\n </span>\n <span class=\"admin-audit-timeline__verb\">\n {{ eventLabel(entry.event) }}\n </span>\n <span class=\"admin-audit-timeline__when\">\n {{ relativeTime(entry.created_at) }}\n </span>\n </div>\n <div v-if=\"diffSummary(entry)\" class=\"admin-audit-timeline__detail\">\n {{ diffSummary(entry) }}\n </div>\n </div>\n </li>\n </ol>\n </section>\n</template>\n\n<style>\n.admin-audit-timeline {\n display: flex;\n flex-direction: column;\n gap: var(--uid-space-sm);\n}\n.admin-audit-timeline__title {\n margin: 0;\n font-family: var(--uid-font-family-display);\n font-size: var(--uid-font-size-lg, 16px);\n font-weight: var(--uid-font-weight-semibold);\n color: var(--uid-text-primary);\n}\n.admin-audit-timeline__list {\n list-style: none;\n margin: 0;\n padding: 0;\n display: flex;\n flex-direction: column;\n gap: var(--uid-space-md);\n position: relative;\n}\n.admin-audit-timeline__list::before {\n content: '';\n position: absolute;\n left: 11px;\n top: 12px;\n bottom: 12px;\n width: 2px;\n background: var(--uid-border-subtle);\n}\n.admin-audit-timeline__item {\n position: relative;\n display: flex;\n gap: var(--uid-space-sm);\n padding-left: 2px;\n}\n.admin-audit-timeline__icon {\n position: relative;\n z-index: 1;\n flex: none;\n width: 24px;\n height: 24px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border-radius: 50%;\n background: var(--uid-surface-base);\n border: 1px solid var(--uid-border-subtle);\n color: var(--uid-text-secondary);\n}\n.admin-audit-timeline__body {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 2px;\n padding-top: 2px;\n}\n.admin-audit-timeline__row {\n display: flex;\n align-items: center;\n gap: var(--uid-space-2xs);\n flex-wrap: wrap;\n}\n.admin-audit-timeline__actor {\n font-size: 13px;\n font-weight: var(--uid-font-weight-semibold);\n color: var(--uid-text-primary);\n}\n.admin-audit-timeline__verb {\n font-size: 13px;\n color: var(--uid-text-secondary);\n}\n.admin-audit-timeline__when {\n margin-left: auto;\n font-size: 12px;\n color: var(--uid-text-tertiary);\n}\n.admin-audit-timeline__detail {\n font-size: 12px;\n color: var(--uid-text-tertiary);\n}\n.admin-audit-timeline__empty,\n.admin-audit-timeline__error {\n font-size: 13px;\n color: var(--uid-text-tertiary);\n}\n.admin-audit-timeline__error { color: var(--uid-color-danger, #dc2626); }\n.admin-audit-timeline__loading {\n display: flex;\n flex-direction: column;\n gap: var(--uid-space-xs);\n}\n</style>\n","<script setup lang=\"ts\">\n/**\n * ResourceViewPage — read-only зеркало form-страницы по дизайну\n * docs/design_handoff_laravel_admin (Resource View):\n *\n * ← Articles Edit … (more menu)\n * {Title}\n * ● Status badge · A-{id}\n *\n * ┌──────────────────────────────┬─────────────────┐\n * │ Card \"Основные данные\" │ Card \"Метрики\" │\n * │ Infolist (manifest.infolist) │ <slot=sidebar> │\n * ├──────────────────────────────┤ │\n * │ Card \"История изменений\" │ │\n * │ AuditTimeline │ │\n * └──────────────────────────────┴─────────────────┘\n */\nimport { computed, onMounted, watch } from 'vue'\nimport { useRouter } from 'vue-router'\nimport { ArrowLeft, MoreHorizontal, Pencil, Trash2 } from 'lucide-vue-next'\nimport {\n UidAlert,\n UidButton,\n UidCard,\n UidIcon,\n UidMenu,\n UidMenuItem,\n UidSkeleton,\n} from '@dskripchenko/ui'\nimport { useResourceFormStore } from '../../stores/resourceForm'\nimport { useManifestStore } from '../../stores/manifest'\nimport InfolistRenderer from '../infolist/InfolistRenderer.vue'\nimport type { InfolistNode } from '../infolist/InfolistRenderer.vue'\nimport { provideRecord } from '../infolist/recordContext'\nimport AuditTimeline from './AuditTimeline.vue'\n\ninterface Props {\n slug: string\n id: string | number\n /** Имя router-route для перехода в edit. */\n editRouteName?: string\n /**\n * Override имени router-route для back-link / возврата после delete.\n * По умолчанию выводится из slug: `admin.resource.{slug}.index`. Если\n * у host'а собственное имя — передаётся явно.\n */\n indexRouteName?: string | null\n /**\n * Override Eloquent morph-class. По умолчанию резолвится из\n * `manifest.resources[slug].subject_type` (Resource::meta()).\n */\n auditSubjectType?: string | null\n /** Поле в record, по которому считать status badge. По умолчанию `status`. */\n statusField?: string\n /** Префикс UID-метки рядом со статусом. Например 'A-' даёт 'A-1284'. */\n uidPrefix?: string\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n editRouteName: undefined,\n indexRouteName: null,\n auditSubjectType: null,\n statusField: 'status',\n uidPrefix: '#',\n})\n\nconst form = useResourceFormStore()\nconst manifest = useManifestStore()\nconst router = useRouter()\n\nprovideRecord(form.state)\n\nconst resourceMeta = computed(() => manifest.getResource(props.slug))\nconst layoutNodes = computed<InfolistNode[]>(\n () => (resourceMeta.value?.infolist ?? resourceMeta.value?.fields ?? []) as InfolistNode[],\n)\n\n/**\n * subject_type для AuditTimeline. Берём в порядке приоритета:\n * 1. props.auditSubjectType (host явно задал) — даже null допустим как\n * explicit \"не показывать\".\n * 2. manifest.resources[slug].subject_type — backend Resource::meta()\n * кладёт morph-alias / FQCN модели.\n *\n * Если оба пусты — timeline не рендерится (Resource без модели либо\n * morph-class не известен фронту).\n */\nconst resolvedSubjectType = computed<string | null>(() => {\n if (props.auditSubjectType !== null) return props.auditSubjectType\n return (resourceMeta.value?.subject_type as string | null | undefined) ?? null\n})\n\n/**\n * Default metrics: created_at / updated_at / created_by из record.\n * Показываем всегда если у записи есть хоть одно из этих полей —\n * стандартные timestamps Eloquent есть у большинства моделей.\n */\ninterface MetricRow {\n label: string\n value: string\n}\nconst defaultMetrics = computed<MetricRow[]>(() => {\n const r = form.state as Record<string, unknown>\n const rows: MetricRow[] = []\n const fmt = (iso: unknown): string | null => {\n if (typeof iso !== 'string' || iso === '') return null\n const ts = new Date(iso)\n if (Number.isNaN(ts.getTime())) return null\n return ts.toLocaleString('ru-RU', {\n day: '2-digit',\n month: '2-digit',\n year: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n })\n }\n const created = fmt(r.created_at)\n if (created) rows.push({ label: 'Создано', value: created })\n const updated = fmt(r.updated_at)\n if (updated && updated !== created) rows.push({ label: 'Обновлено', value: updated })\n const author =\n typeof r.created_by_name === 'string' && r.created_by_name !== ''\n ? r.created_by_name\n : typeof r.author === 'string'\n ? r.author\n : null\n if (author) rows.push({ label: 'Автор', value: author })\n return rows\n})\nconst recordTitle = computed<string>(() => {\n // Запись может иметь поле `title` / `name` / `label` — пробуем по очереди.\n // Иначе fallback на \"{ResourceLabel}: запись #{id}\".\n const r = form.state as Record<string, unknown>\n const t = r.title ?? r.name ?? r.label\n if (typeof t === 'string' && t.length > 0) return t\n return `${resourceMeta.value?.label ?? props.slug}: запись #${props.id}`\n})\nconst indexLabel = computed<string>(\n () => resourceMeta.value?.label ?? props.slug,\n)\nconst uidLabel = computed<string>(() => `${props.uidPrefix}${props.id}`)\n\nconst statusValue = computed<string | null>(() => {\n const r = form.state as Record<string, unknown>\n const v = r[props.statusField]\n return typeof v === 'string' && v.length > 0 ? v : null\n})\n\n/**\n * Маппинг status-значения → визуальный variant. Расширяемо через CSS:\n * `.admin-status-badge[data-status=\"custom\"] { ... }`.\n */\nconst STATUS_VARIANT: Record<string, string> = {\n published: 'success',\n active: 'success',\n enabled: 'success',\n draft: 'neutral',\n pending: 'warning',\n review: 'warning',\n archived: 'muted',\n disabled: 'muted',\n inactive: 'muted',\n deleted: 'danger',\n failed: 'danger',\n error: 'danger',\n}\nfunction statusVariant(s: string): string {\n return STATUS_VARIANT[s.toLowerCase()] ?? 'neutral'\n}\n\n/**\n * Header more-actions — показываем те же `actions[]` из manifest'а что\n * и в index page; здесь они применяются к одной записи (id). Реальный\n * endpoint POST `/{slug}/action/{key}` с body {ids:[id]}.\n */\ninterface HeaderAction {\n key: string\n label: string\n confirm?: string\n}\nconst headerActions = computed<HeaderAction[]>(() => {\n const raw = (resourceMeta.value?.actions ?? []) as Array<Record<string, unknown>>\n return raw\n .map((a) => ({\n key: String(a.key ?? a.name ?? ''),\n label: String(a.label ?? a.name ?? a.key ?? ''),\n confirm: typeof a.confirm === 'string' ? a.confirm : undefined,\n }))\n .filter((a) => a.key !== '' && a.label !== '')\n})\n\nasync function onCustomAction(action: HeaderAction): Promise<void> {\n if (action.confirm && !window.confirm(action.confirm)) return\n try {\n const { getAdminClient } = await import('../../stores/registry')\n const client = getAdminClient()\n await client.post(`/${props.slug}/action/${action.key}`, { ids: [props.id] })\n await form.load(props.slug, props.id, 'view').catch(() => undefined)\n } catch (err) {\n if (typeof console !== 'undefined') console.error('[admin] action failed:', err)\n }\n}\n\nonMounted(async () => {\n if (manifest.manifest === null) {\n await manifest.load().catch(() => undefined)\n }\n await form.load(props.slug, props.id, 'view').catch(() => undefined)\n})\n\nwatch(\n () => [props.slug, props.id] as const,\n async ([s, id]) => {\n await form.load(s, id, 'view').catch(() => undefined)\n },\n)\n\n/**\n * Имя index-роута для back-link и redirect после delete. Default —\n * `admin.resource.{slug}.index` (зарегистрирован buildResourceRoutes).\n * Host может override через prop indexRouteName.\n */\nconst resolvedIndexRouteName = computed<string>(\n () => props.indexRouteName ?? `admin.resource.${props.slug}.index`,\n)\n\nfunction onBack(): void {\n router.push({ name: resolvedIndexRouteName.value }).catch(() => {\n // Fallback на path-based push если route не найден.\n void router.push(`/r/${props.slug}`)\n })\n}\n\nfunction onEdit(): void {\n if (!props.editRouteName) {\n router\n .push(`/r/${props.slug}/${props.id}/edit`)\n .catch(() => undefined)\n return\n }\n router\n .push({ name: props.editRouteName, params: { id: props.id } })\n .catch(() => undefined)\n}\n\nasync function onDelete(): Promise<void> {\n if (!confirm('Удалить запись?')) return\n await form.destroy().catch(() => undefined)\n if (!form.hasError) {\n router.push({ name: resolvedIndexRouteName.value }).catch(() => undefined)\n }\n}\n</script>\n\n<template>\n <section class=\"admin-page admin-resource-view\">\n <header class=\"admin-resource-view__hd\">\n <div class=\"admin-resource-view__hd-left\">\n <button type=\"button\" class=\"admin-resource-view__back\" @click=\"onBack\">\n <UidIcon :icon=\"ArrowLeft\" :size=\"14\" />\n {{ indexLabel }}\n </button>\n <h1 class=\"admin-page__title\">{{ recordTitle }}</h1>\n <div class=\"admin-resource-view__meta\">\n <span\n v-if=\"statusValue\"\n class=\"admin-status-badge\"\n :data-variant=\"statusVariant(statusValue)\"\n :data-status=\"statusValue\"\n >\n <span class=\"admin-status-badge__dot\" aria-hidden=\"true\" />\n {{ statusValue }}\n </span>\n <span class=\"admin-resource-view__uid\">{{ uidLabel }}</span>\n </div>\n </div>\n <div class=\"admin-resource-view__hd-right\">\n <UidButton variant=\"secondary\" size=\"md\" @click=\"onEdit\">\n <template #prepend><UidIcon :icon=\"Pencil\" :size=\"14\" /></template>\n Редактировать\n </UidButton>\n <UidMenu>\n <template #trigger>\n <UidButton variant=\"ghost\" size=\"md\" aria-label=\"Действия\" class=\"admin-page__more\">\n <UidIcon :icon=\"MoreHorizontal\" :size=\"16\" />\n </UidButton>\n </template>\n <UidMenuItem\n v-for=\"a in headerActions\"\n :key=\"a.key\"\n @click=\"onCustomAction(a)\"\n >\n {{ a.label }}\n </UidMenuItem>\n <UidMenuItem variant=\"danger\" @click=\"onDelete\">\n <template #icon><UidIcon :icon=\"Trash2\" :size=\"14\" /></template>\n Удалить\n </UidMenuItem>\n </UidMenu>\n </div>\n </header>\n\n <UidAlert\n v-if=\"form.hasError\"\n variant=\"danger\"\n class=\"admin-resource-view__alert\"\n role=\"alert\"\n >\n {{ form.error?.message ?? 'Не удалось загрузить запись' }}\n </UidAlert>\n\n <div v-if=\"form.loading\" class=\"admin-resource-view__loading\">\n <UidSkeleton v-for=\"i in 8\" :key=\"i\" height=\"24px\" />\n </div>\n\n <div v-else class=\"admin-resource-view__grid\">\n <div class=\"admin-resource-view__main\">\n <UidCard padding=\"md\" class=\"admin-resource-view__card\">\n <h2 class=\"admin-resource-view__card-title\">Основные данные</h2>\n <InfolistRenderer\n v-for=\"(node, idx) in layoutNodes\"\n :key=\"idx\"\n :node=\"node\"\n />\n </UidCard>\n\n <UidCard\n padding=\"md\"\n class=\"admin-resource-view__card\"\n >\n <AuditTimeline\n :subject-type=\"resolvedSubjectType\"\n :subject-id=\"id\"\n />\n </UidCard>\n </div>\n\n <aside class=\"admin-resource-view__aside\">\n <!--\n Default «Метрики» card — created_at / updated_at / автор из record.\n Host может полностью переопределить через slot=sidebar.\n -->\n <UidCard\n v-if=\"defaultMetrics.length > 0\"\n padding=\"md\"\n class=\"admin-resource-view__card\"\n >\n <h2 class=\"admin-resource-view__card-title\">Метрики</h2>\n <dl class=\"admin-resource-view__metrics\">\n <template v-for=\"row in defaultMetrics\" :key=\"row.label\">\n <dt class=\"admin-resource-view__metric-label\">{{ row.label }}</dt>\n <dd class=\"admin-resource-view__metric-value\">{{ row.value }}</dd>\n </template>\n </dl>\n </UidCard>\n\n <slot name=\"sidebar\" :record=\"form.state\" :resource=\"resourceMeta\" />\n </aside>\n </div>\n </section>\n</template>\n\n<style>\n.admin-resource-view__alert {\n margin-bottom: var(--uid-space-md);\n}\n.admin-resource-view__loading {\n display: flex;\n flex-direction: column;\n gap: var(--uid-space-sm);\n}\n\n/* Header */\n.admin-resource-view__hd {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: var(--uid-space-md);\n margin-bottom: var(--uid-space-md);\n}\n.admin-resource-view__hd-left {\n display: flex;\n flex-direction: column;\n gap: var(--uid-space-2xs);\n min-width: 0;\n}\n.admin-resource-view__hd-right {\n display: flex;\n align-items: center;\n gap: var(--uid-space-sm);\n flex: none;\n}\n.admin-resource-view__back {\n display: inline-flex;\n align-items: center;\n gap: var(--uid-space-2xs);\n padding: 0;\n margin: 0;\n font-size: 13px;\n color: var(--uid-text-tertiary);\n background: transparent;\n border: 0;\n cursor: pointer;\n align-self: flex-start;\n}\n.admin-resource-view__back:hover {\n color: var(--uid-text-primary);\n}\n.admin-resource-view__meta {\n display: flex;\n align-items: center;\n gap: var(--uid-space-sm);\n margin-top: var(--uid-space-2xs);\n}\n.admin-resource-view__uid {\n font-family: var(--uid-font-family-mono, ui-monospace, monospace);\n font-size: 12px;\n color: var(--uid-text-tertiary);\n letter-spacing: 0.02em;\n}\n\n/* Status badge */\n.admin-status-badge {\n display: inline-flex;\n align-items: center;\n gap: var(--uid-space-2xs);\n padding: 2px 8px 2px 6px;\n border-radius: var(--uid-radius-sm);\n font-size: 12px;\n font-weight: var(--uid-font-weight-medium);\n text-transform: capitalize;\n}\n.admin-status-badge__dot {\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: currentColor;\n flex: none;\n}\n.admin-status-badge[data-variant='success'] {\n background: color-mix(in srgb, var(--uid-color-success, #10b981) 15%, transparent);\n color: var(--uid-color-success, #10b981);\n}\n.admin-status-badge[data-variant='warning'] {\n background: color-mix(in srgb, var(--uid-color-warning, #f59e0b) 15%, transparent);\n color: var(--uid-color-warning, #f59e0b);\n}\n.admin-status-badge[data-variant='danger'] {\n background: color-mix(in srgb, var(--uid-color-danger, #dc2626) 15%, transparent);\n color: var(--uid-color-danger, #dc2626);\n}\n.admin-status-badge[data-variant='neutral'],\n.admin-status-badge[data-variant='muted'] {\n background: var(--uid-border-subtle);\n color: var(--uid-text-secondary);\n}\n\n/* Two-column grid */\n.admin-resource-view__grid {\n display: grid;\n grid-template-columns: minmax(0, 1fr) 320px;\n gap: var(--uid-space-md);\n align-items: start;\n}\n@media (max-width: 1024px) {\n .admin-resource-view__grid {\n grid-template-columns: 1fr;\n }\n}\n.admin-resource-view__main {\n display: flex;\n flex-direction: column;\n gap: var(--uid-space-md);\n min-width: 0;\n}\n.admin-resource-view__aside {\n display: flex;\n flex-direction: column;\n gap: var(--uid-space-md);\n}\n.admin-resource-view__card {\n display: flex;\n flex-direction: column;\n gap: var(--uid-space-md);\n}\n.admin-resource-view__card-title {\n margin: 0;\n font-family: var(--uid-font-family-display);\n font-size: var(--uid-font-size-lg, 16px);\n font-weight: var(--uid-font-weight-semibold);\n color: var(--uid-text-primary);\n}\n\n/* Metrics list — label/value pair stacked vertically. */\n.admin-resource-view__metrics {\n display: flex;\n flex-direction: column;\n gap: var(--uid-space-md);\n margin: 0;\n padding: 0;\n}\n.admin-resource-view__metric-label {\n font-size: 11px;\n letter-spacing: 0.06em;\n text-transform: uppercase;\n font-weight: var(--uid-font-weight-medium);\n color: var(--uid-text-tertiary);\n margin: 0;\n}\n.admin-resource-view__metric-value {\n font-size: 14px;\n color: var(--uid-text-primary);\n margin: 4px 0 0;\n font-variant-numeric: tabular-nums;\n}\n</style>\n","<script setup lang=\"ts\">\n/**\n * ProfilePage — профильный экран по эталону handoff'а (screens-secondary.jsx\n * → Profile). Layout 200px nav / 1fr cards.\n *\n * Slot model: каждая section экспонирует свою карточку. По умолчанию\n * library рендерит общие \"Основное\" + \"Безопасность\" (на existing-данных\n * auth.user). Host подмешивает свои \"API токены\" и \"Сессии\" через slot'ы.\n */\nimport { computed, ref, watch } from 'vue'\nimport {\n UidAvatar,\n UidBadge,\n UidButton,\n UidCard,\n UidInput,\n UidSelect,\n} from '@dskripchenko/ui'\nimport { useAuthStore } from '../../stores/auth'\nimport { useThemeStore } from '../../stores/theme'\nimport { useLocaleStore } from '../../stores/locale'\n\ninterface Props {\n /** Заголовок страницы (по умолчанию «Profile»). */\n title?: string\n /** Подзаголовок (по умолчанию из handoff'а). */\n subtitle?: string\n /** Какая section активна. */\n section?: 'general' | 'security' | 'tokens' | 'sessions' | string\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n title: 'Profile',\n subtitle: 'Личные данные, безопасность, токены',\n section: 'general',\n})\n\nconst emit = defineEmits<{\n 'update:section': [value: string]\n /** Host реагирует — например запросом /me/uploadAvatar. */\n 'avatar-replace': []\n /** 2FA disable triggered — host показывает confirmation modal. */\n 'two-factor-disable': []\n /** 2FA recovery-codes regenerate. */\n 'two-factor-regenerate': []\n /** Save profile fields. */\n save: [payload: { name: string; email: string; locale: string; theme: string }]\n}>()\n\nconst auth = useAuthStore()\nconst theme = useThemeStore()\nconst locale = useLocaleStore()\n\nconst navItems = [\n { id: 'general', label: 'Основное', icon: 'user' },\n { id: 'security', label: 'Безопасность', icon: 'shield' },\n { id: 'tokens', label: 'API токены', icon: 'key' },\n { id: 'sessions', label: 'Сессии', icon: 'monitor' },\n]\n\nconst localSection = ref(props.section)\nfunction selectSection(id: string): void {\n localSection.value = id\n emit('update:section', id)\n}\n\n// Form-state для general-tab.\nconst profile = ref({\n name: auth.user?.name ?? '',\n email: auth.user?.email ?? '',\n locale: locale.current,\n theme: theme.current,\n})\n\nconst localeOptions = computed(() =>\n locale.available.map((l) => ({ value: l, label: l.toUpperCase() })),\n)\nconst themeOptions = computed(() =>\n theme.available.map((t) => ({ value: t, label: t === 'dark' ? 'Тёмная' : t === 'light' ? 'Светлая' : t })),\n)\n\n// Locale / theme применяются мгновенно при изменении select'а — не требуют\n// клика \"Сохранить\". Это стандартный admin-UX (как в GitHub/Vercel/Linear).\nwatch(\n () => profile.value.locale,\n (next, prev) => {\n if (next === prev || !next) return\n void locale.setLocale(next).catch(() => undefined)\n },\n)\n\nwatch(\n () => profile.value.theme,\n (next, prev) => {\n if (next === prev || !next) return\n void theme.setTheme(next).catch(() => undefined)\n },\n)\n\nfunction onSave(): void {\n emit('save', { ...profile.value })\n}\n\nfunction onAvatarReplace(): void {\n emit('avatar-replace')\n}\n\nfunction on2FADisable(): void {\n emit('two-factor-disable')\n}\n\nfunction on2FARegenerate(): void {\n emit('two-factor-regenerate')\n}\n\nconst has2FA = computed(() => Boolean(auth.user?.twoFactorEnabled))\n</script>\n\n<template>\n <section class=\"admin-page admin-profile\">\n <header class=\"admin-page__hd\">\n <div class=\"admin-page__title-wrap\">\n <h1 class=\"admin-page__title\">{{ title }}</h1>\n <div class=\"admin-page__count\">{{ subtitle }}</div>\n </div>\n </header>\n\n <div class=\"admin-profile__layout\">\n <nav class=\"admin-profile__nav\" aria-label=\"Profile sections\">\n <button\n v-for=\"item in navItems\"\n :key=\"item.id\"\n type=\"button\"\n :class=\"[\n 'admin-profile__nav-item',\n { 'admin-profile__nav-item--active': localSection === item.id },\n ]\"\n @click=\"selectSection(item.id)\"\n >\n <span class=\"admin-profile__nav-icon\" :data-icon=\"item.icon\" />\n <span>{{ item.label }}</span>\n </button>\n </nav>\n\n <div class=\"admin-profile__content\">\n <!-- General -->\n <UidCard v-if=\"localSection === 'general'\" padding=\"md\">\n <header class=\"admin-profile__card-hd\">\n <h3 class=\"admin-profile__card-title\">Профиль</h3>\n </header>\n\n <div class=\"admin-profile__hero\">\n <UidAvatar\n :src=\"auth.user?.avatar ?? undefined\"\n :name=\"auth.user?.name ?? '?'\"\n size=\"lg\"\n />\n <div class=\"admin-profile__hero-text\">\n <div class=\"admin-profile__hero-name\">{{ auth.user?.name ?? '—' }}</div>\n <div class=\"admin-profile__hero-meta\">\n {{ auth.user?.email ?? '—' }}\n </div>\n </div>\n <div style=\"flex:1\" />\n <UidButton variant=\"ghost\" size=\"sm\" @click=\"onAvatarReplace\">\n Заменить\n </UidButton>\n </div>\n\n <div class=\"admin-profile__form\">\n <UidInput\n v-model=\"profile.name\"\n label=\"Имя\"\n name=\"name\"\n />\n <UidInput\n v-model=\"profile.email\"\n label=\"Email\"\n type=\"email\"\n name=\"email\"\n />\n <UidSelect\n v-model=\"profile.locale\"\n :options=\"localeOptions\"\n label=\"Язык\"\n />\n <UidSelect\n v-model=\"profile.theme\"\n :options=\"themeOptions\"\n label=\"Тема\"\n />\n </div>\n\n <footer class=\"admin-profile__card-ft\">\n <UidButton variant=\"primary\" @click=\"onSave\">Сохранить</UidButton>\n </footer>\n </UidCard>\n\n <!-- Security -->\n <UidCard v-else-if=\"localSection === 'security'\" padding=\"md\">\n <header class=\"admin-profile__card-hd\">\n <h3 class=\"admin-profile__card-title\">Двухфакторная аутентификация</h3>\n <UidBadge :variant=\"has2FA ? 'success' : 'default'\">\n {{ has2FA ? 'Включена' : 'Отключена' }}\n </UidBadge>\n </header>\n\n <p v-if=\"has2FA\" class=\"admin-profile__hint\">\n 2FA включена. У вас остались recovery-коды на случай потери устройства.\n </p>\n <p v-else class=\"admin-profile__hint\">\n Включите 2FA для дополнительной защиты аккаунта.\n </p>\n\n <footer class=\"admin-profile__card-ft\">\n <template v-if=\"has2FA\">\n <UidButton variant=\"ghost\" size=\"sm\" @click=\"on2FARegenerate\">\n Перегенерировать коды\n </UidButton>\n <UidButton variant=\"danger\" size=\"sm\" @click=\"on2FADisable\">\n Отключить 2FA\n </UidButton>\n </template>\n <template v-else>\n <slot name=\"enable-2fa\">\n <UidButton variant=\"primary\" disabled>\n Включить 2FA (host customize)\n </UidButton>\n </slot>\n </template>\n </footer>\n </UidCard>\n\n <!-- Tokens / Sessions / другое — host рендерит через slot -->\n <slot v-else :name=\"localSection\" :section=\"localSection\">\n <UidCard padding=\"md\">\n <p class=\"admin-profile__hint\">\n Section «{{ localSection }}» не реализована библиотекой —\n host-проект подключает её через slot {{ localSection }}.\n </p>\n </UidCard>\n </slot>\n </div>\n </div>\n </section>\n</template>\n\n<style>\n.admin-profile__layout {\n display: grid;\n grid-template-columns: 200px 1fr;\n gap: var(--uid-space-lg);\n align-items: start;\n}\n.admin-profile__nav {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n.admin-profile__nav-item {\n appearance: none;\n border: 0;\n background: transparent;\n text-align: left;\n display: flex;\n align-items: center;\n gap: var(--uid-space-sm);\n padding: var(--uid-space-sm) var(--uid-space-sm);\n border-radius: var(--uid-radius-md);\n font-size: 13px;\n color: var(--uid-text-secondary);\n cursor: pointer;\n}\n.admin-profile__nav-item:hover {\n background: var(--uid-surface-hover);\n color: var(--uid-text-primary);\n}\n.admin-profile__nav-item--active {\n background: var(--uid-surface-base);\n color: var(--uid-text-primary);\n font-weight: var(--uid-font-weight-medium);\n}\n.admin-profile__nav-icon {\n width: 14px;\n height: 14px;\n flex: none;\n}\n.admin-profile__content {\n display: flex;\n flex-direction: column;\n gap: var(--uid-space-md);\n}\n\n.admin-profile__card-hd {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: var(--uid-space-md);\n}\n.admin-profile__card-title {\n margin: 0;\n font-size: var(--uid-font-size-sm);\n font-weight: var(--uid-font-weight-semibold);\n}\n.admin-profile__card-ft {\n margin-top: var(--uid-space-md);\n display: flex;\n gap: var(--uid-space-sm);\n}\n.admin-profile__hint {\n margin: 0;\n font-size: var(--uid-font-size-sm);\n color: var(--uid-text-secondary);\n}\n\n.admin-profile__hero {\n display: flex;\n align-items: center;\n gap: var(--uid-space-md);\n margin-bottom: var(--uid-space-md);\n}\n.admin-profile__hero-text { display: flex; flex-direction: column; gap: 4px; }\n.admin-profile__hero-name {\n font-weight: var(--uid-font-weight-semibold);\n color: var(--uid-text-primary);\n}\n.admin-profile__hero-meta {\n font-size: var(--uid-font-size-xs);\n color: var(--uid-text-tertiary);\n}\n\n.admin-profile__form {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: var(--uid-space-md);\n}\n@media (max-width: 720px) {\n .admin-profile__form { grid-template-columns: 1fr; }\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { UidStat } from '@dskripchenko/ui'\nimport type { StatTone } from '@dskripchenko/ui'\n\ntype SemanticTone = 'neutral' | 'positive' | 'negative' | 'warning' | 'info'\n\ninterface Props {\n title?: string\n value?: number | string\n prefix?: string\n suffix?: string\n trend?: number\n precision?: number\n tone?: SemanticTone\n loading?: boolean\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n title: '',\n value: 0,\n prefix: '',\n suffix: '',\n trend: undefined,\n precision: 0,\n tone: 'neutral',\n loading: false,\n})\n\nconst TONE_MAP: Record<SemanticTone, StatTone> = {\n neutral: 'primary',\n positive: 'success',\n negative: 'danger',\n warning: 'warning',\n info: 'info',\n}\n\nconst uidTone = computed<StatTone>(() => TONE_MAP[props.tone])\n</script>\n\n<template>\n <UidStat\n :title=\"title\"\n :value=\"value\"\n :prefix=\"prefix\"\n :suffix=\"suffix\"\n :trend=\"trend\"\n :precision=\"precision\"\n :tone=\"uidTone\"\n :loading=\"loading\"\n />\n</template>\n","<script setup lang=\"ts\">\n/**\n * BarChartWidget — простой SVG-bar chart без внешних зависимостей.\n *\n * Manifest:\n * { type: 'bar-chart', title: '30 дней',\n * data: [{ label: '01', value: 12 }, ...],\n * accent: 'var(--uid-accent)' }\n */\nimport { computed } from 'vue'\nimport { UidCard } from '@dskripchenko/ui'\n\ninterface Datum {\n label: string\n value: number\n}\n\ninterface Props {\n title?: string\n description?: string\n data: Datum[]\n accent?: string\n height?: number\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n title: '',\n description: '',\n accent: 'var(--uid-accent)',\n height: 200,\n})\n\nconst maxValue = computed(() => Math.max(1, ...props.data.map((d) => d.value)))\n\nconst bars = computed(() => {\n const n = Math.max(1, props.data.length)\n const barWidth = 100 / n\n return props.data.map((d, i) => ({\n label: d.label,\n value: d.value,\n x: i * barWidth + barWidth * 0.1,\n width: barWidth * 0.8,\n heightPct: (d.value / maxValue.value) * 100,\n }))\n})\n</script>\n\n<template>\n <UidCard padding=\"md\" class=\"admin-widget\">\n <header v-if=\"title || description\" class=\"admin-widget__hd\">\n <h3 v-if=\"title\" class=\"admin-widget__title\">{{ title }}</h3>\n <p v-if=\"description\" class=\"admin-widget__desc\">{{ description }}</p>\n </header>\n <svg\n class=\"admin-widget-bar-chart\"\n :viewBox=\"`0 0 100 ${height}`\"\n preserveAspectRatio=\"none\"\n :height=\"height\"\n width=\"100%\"\n role=\"img\"\n :aria-label=\"title || 'Bar chart'\"\n >\n <rect\n v-for=\"(bar, idx) in bars\"\n :key=\"idx\"\n :x=\"bar.x\"\n :y=\"height - (bar.heightPct / 100) * height\"\n :width=\"bar.width\"\n :height=\"(bar.heightPct / 100) * height\"\n :fill=\"accent\"\n rx=\"1\"\n :data-label=\"bar.label\"\n :data-value=\"bar.value\"\n >\n <title>{{ bar.label }}: {{ bar.value }}</title>\n </rect>\n </svg>\n </UidCard>\n</template>\n\n<style>\n.admin-widget__hd { margin-bottom: var(--uid-space-sm); }\n.admin-widget__title {\n margin: 0;\n font-size: var(--uid-font-size-sm);\n font-weight: var(--uid-font-weight-semibold);\n color: var(--uid-text-primary);\n}\n.admin-widget__desc {\n margin: var(--uid-space-2xs) 0 0;\n font-size: var(--uid-font-size-xs);\n color: var(--uid-text-tertiary);\n}\n.admin-widget-bar-chart {\n display: block;\n width: 100%;\n}\n</style>\n","<script setup lang=\"ts\">\n/**\n * DonutChartWidget — SVG donut + legend.\n *\n * Manifest:\n * { type: 'donut-chart', title: 'Status',\n * data: [{ label: 'Published', value: 156, color: '...' }, ...] }\n */\nimport { computed } from 'vue'\nimport { UidCard } from '@dskripchenko/ui'\n\ninterface Slice {\n label: string\n value: number\n color?: string\n}\n\ninterface Props {\n title?: string\n data: Slice[]\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n title: '',\n})\n\nconst PALETTE = [\n 'var(--uid-color-teal-500, #14b8a6)',\n 'var(--uid-color-zinc-700, #3f3f46)',\n 'var(--uid-color-amber-400, #fbbf24)',\n 'var(--uid-color-rose-400, #fb7185)',\n 'var(--uid-color-blue-400, #60a5fa)',\n]\n\nconst total = computed(() => props.data.reduce((s, x) => s + x.value, 0) || 1)\n\nconst slices = computed(() => {\n let cumulative = 0\n return props.data.map((s, idx) => {\n const startAngle = (cumulative / total.value) * 2 * Math.PI\n cumulative += s.value\n const endAngle = (cumulative / total.value) * 2 * Math.PI\n\n const r = 50\n const cx = 60\n const cy = 60\n\n const x1 = cx + r * Math.cos(startAngle - Math.PI / 2)\n const y1 = cy + r * Math.sin(startAngle - Math.PI / 2)\n const x2 = cx + r * Math.cos(endAngle - Math.PI / 2)\n const y2 = cy + r * Math.sin(endAngle - Math.PI / 2)\n\n const largeArc = endAngle - startAngle > Math.PI ? 1 : 0\n\n const path = props.data.length === 1\n ? `M ${cx - r} ${cy} a ${r} ${r} 0 1 0 ${r * 2} 0 a ${r} ${r} 0 1 0 ${-r * 2} 0`\n : `M ${cx} ${cy} L ${x1} ${y1} A ${r} ${r} 0 ${largeArc} 1 ${x2} ${y2} Z`\n\n return {\n ...s,\n path,\n color: s.color ?? PALETTE[idx % PALETTE.length],\n pct: ((s.value / total.value) * 100).toFixed(1),\n }\n })\n})\n</script>\n\n<template>\n <UidCard padding=\"md\" class=\"admin-widget admin-donut-widget\">\n <header v-if=\"title\" class=\"admin-widget__hd\">\n <h3 class=\"admin-widget__title\">{{ title }}</h3>\n </header>\n <div class=\"admin-donut-widget__row\">\n <svg viewBox=\"0 0 120 120\" class=\"admin-donut-widget__svg\" role=\"img\" :aria-label=\"title\">\n <path\n v-for=\"(s, idx) in slices\"\n :key=\"idx\"\n :d=\"s.path\"\n :fill=\"s.color\"\n >\n <title>{{ s.label }}: {{ s.value }} ({{ s.pct }}%)</title>\n </path>\n <circle cx=\"60\" cy=\"60\" r=\"30\" fill=\"var(--uid-surface-raised)\" />\n </svg>\n <ul class=\"admin-donut-widget__legend\">\n <li v-for=\"(s, idx) in slices\" :key=\"idx\">\n <span class=\"admin-donut-widget__dot\" :style=\"{ background: s.color }\" />\n <span class=\"admin-donut-widget__label\">{{ s.label }}</span>\n <span class=\"admin-donut-widget__value\">{{ s.pct }}%</span>\n </li>\n </ul>\n </div>\n </UidCard>\n</template>\n\n<style>\n.admin-donut-widget__row {\n display: flex;\n align-items: center;\n gap: var(--uid-space-md);\n}\n.admin-donut-widget__svg {\n width: 120px;\n height: 120px;\n flex: none;\n}\n.admin-donut-widget__legend {\n list-style: none;\n margin: 0;\n padding: 0;\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: var(--uid-space-xs);\n}\n.admin-donut-widget__legend li {\n display: flex;\n align-items: center;\n gap: var(--uid-space-sm);\n font-size: var(--uid-font-size-xs);\n}\n.admin-donut-widget__dot {\n width: 10px;\n height: 10px;\n border-radius: var(--uid-radius-full);\n flex: none;\n}\n.admin-donut-widget__label { flex: 1; color: var(--uid-text-primary); }\n.admin-donut-widget__value {\n color: var(--uid-text-tertiary);\n font-variant-numeric: tabular-nums;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { UidCard, UidTable, type UidTableColumn } from '@dskripchenko/ui'\n\ninterface Props {\n title?: string\n columns: UidTableColumn[]\n rows: Record<string, unknown>[]\n emptyText?: string\n}\n\nwithDefaults(defineProps<Props>(), {\n title: '',\n emptyText: 'Нет данных',\n})\n</script>\n\n<template>\n <UidCard padding=\"md\" class=\"admin-widget\">\n <header v-if=\"title\" class=\"admin-widget__hd\">\n <h3 class=\"admin-widget__title\">{{ title }}</h3>\n </header>\n <UidTable :columns=\"columns\" :data=\"rows\" :empty-text=\"emptyText\" />\n </UidCard>\n</template>\n","<script setup lang=\"ts\">\nimport { UidCard, UidHeatmap } from '@dskripchenko/ui'\n\ninterface HeatmapPoint {\n date: string\n value: number\n}\n\ninterface Props {\n title?: string\n data: HeatmapPoint[]\n levels?: number\n color?: string\n gap?: number\n}\n\nwithDefaults(defineProps<Props>(), {\n title: '',\n levels: 5,\n color: undefined,\n gap: 2,\n})\n</script>\n\n<template>\n <UidCard padding=\"md\" class=\"admin-widget\">\n <header v-if=\"title\" class=\"admin-widget__hd\">\n <h3 class=\"admin-widget__title\">{{ title }}</h3>\n </header>\n <UidHeatmap :data=\"data\" :levels=\"levels\" :color=\"color\" :gap=\"gap\" />\n </UidCard>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { UidCard, UidGauge } from '@dskripchenko/ui'\nimport type { GaugeTone, GaugeRange } from '@dskripchenko/ui'\n\ntype SemanticTone = 'neutral' | 'positive' | 'warning' | 'negative'\n\ninterface Props {\n title?: string\n value?: number\n min?: number\n max?: number\n size?: number\n ranges?: GaugeRange[]\n tone?: SemanticTone\n color?: string\n label?: string\n suffix?: string\n precision?: number\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n title: '',\n value: 0,\n min: 0,\n max: 100,\n size: 160,\n ranges: () => [],\n tone: 'neutral',\n color: undefined,\n label: '',\n suffix: '',\n precision: 0,\n})\n\nconst TONE_MAP: Record<SemanticTone, GaugeTone> = {\n neutral: 'primary',\n positive: 'success',\n warning: 'warning',\n negative: 'danger',\n}\n\nconst uidTone = computed<GaugeTone>(() => TONE_MAP[props.tone])\n</script>\n\n<template>\n <UidCard padding=\"md\" class=\"admin-widget\">\n <header v-if=\"title\" class=\"admin-widget__hd\">\n <h3 class=\"admin-widget__title\">{{ title }}</h3>\n </header>\n <div style=\"display:flex; justify-content:center;\">\n <UidGauge\n :value=\"value\"\n :min=\"min\"\n :max=\"max\"\n :size=\"size\"\n :ranges=\"ranges\"\n :tone=\"uidTone\"\n :color=\"color\"\n :label=\"label\"\n :suffix=\"suffix\"\n :precision=\"precision\"\n />\n </div>\n </UidCard>\n</template>\n","<script setup lang=\"ts\">\n/**\n * Markdown widget — простой preformatted-блок. Для production хост может\n * подкинуть свой widget с marked/MDX через registerWidget('markdown', ...).\n *\n * Тут — fallback с базовым форматированием через line-break preserve.\n */\nimport { UidCard } from '@dskripchenko/ui'\n\ninterface Props {\n title?: string\n content: string\n}\n\nwithDefaults(defineProps<Props>(), { title: '' })\n</script>\n\n<template>\n <UidCard padding=\"md\" class=\"admin-widget\">\n <header v-if=\"title\" class=\"admin-widget__hd\">\n <h3 class=\"admin-widget__title\">{{ title }}</h3>\n </header>\n <div class=\"admin-markdown-widget\">{{ content }}</div>\n </UidCard>\n</template>\n\n<style>\n.admin-markdown-widget {\n font-size: var(--uid-font-size-sm);\n color: var(--uid-text-secondary);\n white-space: pre-wrap;\n line-height: var(--uid-line-height-normal);\n}\n</style>\n","<script setup lang=\"ts\">\n/**\n * ChartWidget — диспетчер по `data.type` (bar / line / pie / doughnut / area).\n *\n * Backend ChartWidget::data() отдаёт `{type, labels, datasets, ...}`. Эта\n * frontend-обёртка трансформирует структуру в plain Datum/Slice массивы\n * и делегирует рисование специализированным компонентам (Bar/Donut/...).\n */\nimport { computed } from 'vue'\nimport BarChartWidget from './BarChartWidget.vue'\nimport DonutChartWidget from './DonutChartWidget.vue'\nimport UnknownWidget from './UnknownWidget.vue'\n\ninterface ChartDataset {\n label: string\n data: number[]\n color?: string\n}\ninterface ChartData {\n type?: string\n labels?: string[]\n datasets?: ChartDataset[]\n}\n\ninterface Props {\n type?: string\n title?: string\n size?: number\n data?: ChartData\n}\nconst props = defineProps<Props>()\n\nconst chartType = computed<string>(() => props.data?.type ?? 'bar')\n\n/**\n * Палитра по умолчанию для donut/pie. Берём из --uid-* токенов, fallback —\n * статические цвета. Backend может прислать `color` в dataset — тогда\n * предпочтение ему.\n */\nconst DEFAULT_PALETTE = [\n '#10b981', // teal-500\n '#f59e0b', // amber-500\n '#9ca3af', // gray-400\n '#3b82f6', // blue-500\n '#dc2626', // red-600\n '#a855f7', // purple-500\n '#ec4899', // pink-500\n]\n\n/**\n * Bar/line/area-чарты ожидают список {label, value}.\n * Берём первый dataset (multi-dataset stacked будет реализован в следующей\n * итерации).\n */\nconst barData = computed(() => {\n const ds = props.data?.datasets?.[0]\n if (!ds) return []\n return ds.data.map((v, i) => ({\n label: props.data?.labels?.[i] ?? String(i + 1),\n value: v,\n }))\n})\n\nconst barAccent = computed<string | undefined>(\n () => props.data?.datasets?.[0]?.color,\n)\n\n/** Donut/pie — каждый item получает свою долю общего total. */\nconst donutData = computed(() => {\n const ds = props.data?.datasets?.[0]\n if (!ds) return []\n return ds.data.map((v, i) => ({\n label: props.data?.labels?.[i] ?? String(i + 1),\n value: v,\n color: ds.color ?? DEFAULT_PALETTE[i % DEFAULT_PALETTE.length],\n }))\n})\n</script>\n\n<template>\n <DonutChartWidget\n v-if=\"chartType === 'doughnut' || chartType === 'pie'\"\n :title=\"title\"\n :data=\"donutData\"\n />\n <BarChartWidget\n v-else-if=\"chartType === 'bar' || chartType === 'line' || chartType === 'area'\"\n :title=\"title\"\n :data=\"barData\"\n :accent=\"barAccent\"\n />\n <UnknownWidget v-else :type=\"`chart:${chartType}`\" />\n</template>\n","/**\n * Default-bundle с минимальным набором builtin widget-типов.\n */\n\nimport { registerWidgets } from './registry'\nimport StatWidget from './StatWidget.vue'\nimport BarChartWidget from './BarChartWidget.vue'\nimport DonutChartWidget from './DonutChartWidget.vue'\nimport ChartWidget from './ChartWidget.vue'\nimport RecentTableWidget from './RecentTableWidget.vue'\nimport HeatmapWidget from './HeatmapWidget.vue'\nimport GaugeWidget from './GaugeWidget.vue'\nimport MarkdownWidget from './MarkdownWidget.vue'\n\n/**\n * Регистрирует встроенные widget-компоненты + backend-aliases. Имена\n * слева совпадают с тем что отдают backend Widget::widgetType()\n * (`stats`/`chart`/`recent_list` и т.д.); справа — frontend Vue-компонент.\n */\nexport function registerBuiltinWidgets(): void {\n registerWidgets({\n // Stat / Stats overview\n stat: StatWidget,\n stats: StatWidget,\n // Charts: универсальный диспетчер по data.type → bar/donut/...\n chart: ChartWidget,\n 'bar-chart': BarChartWidget,\n 'donut-chart': DonutChartWidget,\n // Recent list (таблица последних записей)\n 'recent-table': RecentTableWidget,\n recent_list: RecentTableWidget,\n 'recent-list': RecentTableWidget,\n // Heatmap / Gauge / Markdown\n heatmap: HeatmapWidget,\n gauge: GaugeWidget,\n markdown: MarkdownWidget,\n })\n}\n","/**\n * Контракт ответов laravel-api: каждое тело — `{success, payload}`.\n *\n * Success: `{success: true, payload: {...}}`\n * Error: `{success: false, payload: {errorKey, message, ...}}`\n *\n * Helper'ы здесь — для type-narrowing'а в потребителях.\n */\n\nexport interface SuccessEnvelope<T = unknown> {\n success: true\n payload: T\n}\n\nexport interface ErrorEnvelope {\n success: false\n payload: {\n errorKey: string\n message: string\n messages?: Record<string, string[]>\n [key: string]: unknown\n }\n}\n\nexport type ApiEnvelope<T = unknown> = SuccessEnvelope<T> | ErrorEnvelope\n\nexport function isSuccess<T>(env: ApiEnvelope<T>): env is SuccessEnvelope<T> {\n return env.success === true\n}\n\nexport function isError(env: ApiEnvelope): env is ErrorEnvelope {\n return env.success === false\n}\n","/**\n * Axios-клиент для admin API.\n *\n * Особенности:\n * - baseURL берётся из bootstrap.apiUrl (либо передаётся явно).\n * - X-XSRF-TOKEN добавляется автоматически из cookie (Laravel Sanctum/web).\n * - X-CSRF-TOKEN — fallback из meta[name=csrf-token] (Blade-injection).\n * - X-Admin-Locale выставляется при наличии текущей локали.\n * - Response interceptor разворачивает envelope и бросает ApiError.\n * - 401 → onUnauthenticated callback (редирект на login на стороне consumer'а).\n */\n\nimport axios, { AxiosError, type AxiosInstance, type AxiosRequestConfig } from 'axios'\nimport { isSuccess, type ApiEnvelope, type ErrorEnvelope } from './envelope'\nimport { NetworkError, toApiError, UnauthenticatedError } from './errors'\n\nexport interface ClientOptions {\n baseURL: string\n csrfToken?: string\n locale?: string\n /** Вызывается при 401. Обычно — push на /admin/login. */\n onUnauthenticated?: () => void\n}\n\nexport interface AdminClient {\n /** Низкоуровневый axios — для специфичных случаев. */\n raw: AxiosInstance\n get<T = unknown>(url: string, config?: AxiosRequestConfig): Promise<T>\n post<T = unknown>(url: string, data?: unknown, config?: AxiosRequestConfig): Promise<T>\n put<T = unknown>(url: string, data?: unknown, config?: AxiosRequestConfig): Promise<T>\n patch<T = unknown>(url: string, data?: unknown, config?: AxiosRequestConfig): Promise<T>\n delete<T = unknown>(url: string, config?: AxiosRequestConfig): Promise<T>\n setLocale(locale: string): void\n}\n\nexport function createAdminClient(opts: ClientOptions): AdminClient {\n const instance = axios.create({\n baseURL: opts.baseURL,\n withCredentials: true,\n headers: {\n Accept: 'application/json',\n 'X-Requested-With': 'XMLHttpRequest',\n },\n })\n\n if (opts.csrfToken) {\n instance.defaults.headers.common['X-CSRF-TOKEN'] = opts.csrfToken\n }\n if (opts.locale) {\n instance.defaults.headers.common['X-Admin-Locale'] = opts.locale\n }\n\n // Подцепляем XSRF из cookie на каждый запрос — браузер сам обновит\n // его после первого 419, но axios reads на вызове.\n instance.interceptors.request.use((config) => {\n const xsrf = readCookie('XSRF-TOKEN')\n if (xsrf) {\n config.headers.set('X-XSRF-TOKEN', decodeURIComponent(xsrf))\n }\n return config\n })\n\n // Response interceptor — разворачиваем envelope, бросаем правильную ошибку.\n instance.interceptors.response.use(\n (response) => {\n const env = response.data as ApiEnvelope\n if (env && typeof env === 'object' && 'success' in env) {\n if (isSuccess(env)) {\n // payload подменяет data — теперь callers получают чистый payload.\n response.data = env.payload\n return response\n }\n // success: false → throw как ApiError\n throw toApiError(response.status, env.payload)\n }\n // Не envelope (например, бинарный stream) — пропускаем как есть.\n return response\n },\n (error: AxiosError<ErrorEnvelope>) => {\n if (error.response) {\n const status = error.response.status\n const payload =\n error.response.data?.payload ?? {\n errorKey: 'unknown',\n message: error.message,\n }\n const apiError = toApiError(status, payload)\n if (apiError instanceof UnauthenticatedError) {\n opts.onUnauthenticated?.()\n }\n return Promise.reject(apiError)\n }\n // network failure / timeout\n return Promise.reject(new NetworkError(error.message))\n },\n )\n\n const wrap = <T>(method: 'get' | 'delete', url: string, config?: AxiosRequestConfig): Promise<T> =>\n instance[method]<unknown, { data: T }>(url, config).then((r) => r.data)\n\n const wrapBody = <T>(\n method: 'post' | 'put' | 'patch',\n url: string,\n data?: unknown,\n config?: AxiosRequestConfig,\n ): Promise<T> => instance[method]<unknown, { data: T }>(url, data, config).then((r) => r.data)\n\n return {\n raw: instance,\n get: <T>(url: string, config?: AxiosRequestConfig) => wrap<T>('get', url, config),\n delete: <T>(url: string, config?: AxiosRequestConfig) => wrap<T>('delete', url, config),\n post: <T>(url: string, data?: unknown, config?: AxiosRequestConfig) =>\n wrapBody<T>('post', url, data, config),\n put: <T>(url: string, data?: unknown, config?: AxiosRequestConfig) =>\n wrapBody<T>('put', url, data, config),\n patch: <T>(url: string, data?: unknown, config?: AxiosRequestConfig) =>\n wrapBody<T>('patch', url, data, config),\n setLocale: (locale: string): void => {\n instance.defaults.headers.common['X-Admin-Locale'] = locale\n },\n }\n}\n\n/** Читает cookie из document.cookie. Returns null если нет. */\nfunction readCookie(name: string): string | null {\n if (typeof document === 'undefined') return null\n const match = document.cookie.match(new RegExp('(^|; )' + escapeRegex(name) + '=([^;]*)'))\n return match ? match[2] : null\n}\n\nfunction escapeRegex(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n}\n","/**\n * buildRoutesFromManifest — превращает AdminManifest в массив RouteRecordRaw.\n *\n * Маппинг:\n * - resource{slug} → /r/{slug} (index)\n * /r/{slug}/create (create)\n * /r/{slug}/:id/edit (edit)\n * /r/{slug}/:id (view, опционально)\n * - screen{slug} → /screens/{slug}\n * - settings{slug} → /settings/{slug}\n * - dashboard{slug} → /dashboard/{slug}\n *\n * Component'ы передаются через resolver — host-проект решает, что отрисовать.\n * Это позволяет library не тащить рендереры внутрь себя жёстко.\n */\n\nimport type { RouteRecordRaw } from 'vue-router'\nimport type { Component } from 'vue'\nimport type {\n AdminManifest,\n ManifestResourceMeta,\n ManifestScreenMeta,\n ManifestSettingsMeta,\n} from '../stores/manifest'\n\n/** Vue Component либо async-loader (для code-splitting). */\nexport type AdminRouteComponent = Component | (() => Promise<Component>)\n\nexport interface RouteMeta {\n /** Требует залогиненного пользователя. */\n requiresAuth?: boolean\n /** Permissions, нужные для входа. ANY-логика (хотя бы одно совпадение). */\n permissions?: string[]\n /** Заголовок страницы (рендерим в <title> через router.afterEach). */\n title?: string\n /** Тип админ-роута — для UI breadcrumbs/active-state. */\n kind?: 'resource' | 'screen' | 'settings' | 'dashboard' | 'system' | 'auth'\n /** Slug сущности из манифеста — для извлечения мета внутри компонента. */\n slug?: string\n}\n\ndeclare module 'vue-router' {\n // eslint-disable-next-line @typescript-eslint/no-empty-object-type\n interface RouteMeta extends Record<string, unknown> {}\n}\n\n/**\n * Resolver компонентов для динамических роутов.\n *\n * Host-проект передаёт конкретные Vue-компоненты для каждой роли.\n * Library не зависит от конкретных view'ов.\n */\nexport interface RouteComponentResolver {\n resourceIndex: AdminRouteComponent\n resourceCreate: AdminRouteComponent\n resourceEdit: AdminRouteComponent\n resourceView: AdminRouteComponent\n screen: AdminRouteComponent\n settings: AdminRouteComponent\n dashboard: AdminRouteComponent\n}\n\n/**\n * Извлекает permissions из meta'ы ресурса / скрина / settings'а.\n *\n * resource.permissions = { view: 'admin.users.view', ... } → ['admin.users.view']\n * (для index используется view; для create/edit — соответственно).\n */\nfunction pickResourcePermission(\n resource: ManifestResourceMeta,\n ability: 'view' | 'create' | 'update',\n): string[] {\n const perm = resource.permissions?.[ability]\n return typeof perm === 'string' && perm.length > 0 ? [perm] : []\n}\n\nfunction pickSettingsPermission(s: ManifestSettingsMeta, ability: 'view' | 'update'): string[] {\n const perm = s.permissions?.[ability]\n return typeof perm === 'string' && perm.length > 0 ? [perm] : []\n}\n\nfunction pickScreenPermission(s: ManifestScreenMeta): string[] {\n if (Array.isArray(s.permission)) return s.permission\n if (typeof s.permission === 'string' && s.permission.length > 0) return [s.permission]\n return []\n}\n\nfunction buildResourceRoutes(\n resource: ManifestResourceMeta,\n components: RouteComponentResolver,\n): RouteRecordRaw[] {\n const slug = resource.slug\n const base = `/r/${slug}`\n\n return [\n {\n path: base,\n name: `admin.resource.${slug}.index`,\n component: components.resourceIndex,\n meta: {\n requiresAuth: true,\n kind: 'resource',\n slug,\n title: resource.label,\n permissions: pickResourcePermission(resource, 'view'),\n },\n // slug передаётся в page-component'ы как prop. Конкретный slug запекаем в\n // function-mode, чтобы page видел его одинаково и через named-route, и через\n // path-routing (без params).\n props: { slug },\n },\n {\n path: `${base}/create`,\n name: `admin.resource.${slug}.create`,\n component: components.resourceCreate,\n meta: {\n requiresAuth: true,\n kind: 'resource',\n slug,\n title: `${resource.label}: создать`,\n permissions: pickResourcePermission(resource, 'create'),\n },\n props: { slug },\n },\n {\n path: `${base}/:id/edit`,\n name: `admin.resource.${slug}.edit`,\n component: components.resourceEdit,\n meta: {\n requiresAuth: true,\n kind: 'resource',\n slug,\n title: `${resource.label}: редактирование`,\n permissions: pickResourcePermission(resource, 'update'),\n },\n // slug запекаем, id из route-params.\n props: (route) => ({ slug, id: route.params.id }),\n },\n {\n path: `${base}/:id`,\n name: `admin.resource.${slug}.view`,\n component: components.resourceView,\n meta: {\n requiresAuth: true,\n kind: 'resource',\n slug,\n title: resource.label,\n permissions: pickResourcePermission(resource, 'view'),\n },\n props: (route) => ({ slug, id: route.params.id }),\n },\n ]\n}\n\nfunction buildScreenRoute(\n screen: ManifestScreenMeta,\n components: RouteComponentResolver,\n): RouteRecordRaw {\n return {\n path: `/screens/${screen.slug}`,\n name: `admin.screen.${screen.slug}`,\n component: components.screen,\n meta: {\n requiresAuth: true,\n kind: 'screen',\n slug: screen.slug,\n title: screen.name,\n permissions: pickScreenPermission(screen),\n },\n }\n}\n\nfunction buildSettingsRoute(\n settings: ManifestSettingsMeta,\n components: RouteComponentResolver,\n): RouteRecordRaw {\n return {\n path: `/settings/${settings.slug}`,\n name: `admin.settings.${settings.slug}`,\n component: components.settings,\n meta: {\n requiresAuth: true,\n kind: 'settings',\n slug: settings.slug,\n title: settings.label,\n permissions: pickSettingsPermission(settings, 'view'),\n },\n }\n}\n\ninterface DashboardMeta {\n slug?: string\n label?: string\n permission?: string | string[] | null\n}\n\nfunction buildDashboardRoute(\n dashboard: DashboardMeta,\n components: RouteComponentResolver,\n): RouteRecordRaw | null {\n if (typeof dashboard.slug !== 'string' || dashboard.slug.length === 0) return null\n const permission = dashboard.permission\n const permissions = Array.isArray(permission)\n ? permission\n : typeof permission === 'string' && permission.length > 0\n ? [permission]\n : []\n return {\n path: `/dashboard/${dashboard.slug}`,\n name: `admin.dashboard.${dashboard.slug}`,\n component: components.dashboard,\n meta: {\n requiresAuth: true,\n kind: 'dashboard',\n slug: dashboard.slug,\n title: dashboard.label ?? 'Dashboard',\n permissions,\n },\n }\n}\n\nexport function buildRoutesFromManifest(\n manifest: AdminManifest | null,\n components: RouteComponentResolver,\n): RouteRecordRaw[] {\n if (manifest === null) return []\n\n const routes: RouteRecordRaw[] = []\n\n for (const resource of manifest.resources) {\n routes.push(...buildResourceRoutes(resource, components))\n }\n for (const screen of manifest.screens) {\n routes.push(buildScreenRoute(screen, components))\n }\n for (const s of manifest.settings) {\n routes.push(buildSettingsRoute(s, components))\n }\n for (const d of manifest.dashboards as DashboardMeta[]) {\n const route = buildDashboardRoute(d, components)\n if (route) routes.push(route)\n }\n\n return routes\n}\n","/**\n * Router-guards: auth + permissions.\n *\n * Логика:\n * 1. Если route.meta.requiresAuth и пользователь не залогинен → /login\n * с ?redirect=...\n * 2. Если у user'а есть pendingChallenge (2FA) — все защищённые роуты\n * редиректят на /login (challenge-form там).\n * 3. Если route.meta.permissions заданы — проверяем hasAnyPermission().\n * Нет ни одного → /forbidden (или роут с name='admin.forbidden').\n *\n * Guards используют useAuthStore — но НЕ берут client напрямую: всё через\n * permissions/isAuthenticated/pendingChallenge state. Stores должны быть\n * захайдрейчены до setup'а router'а.\n */\n\nimport type { RouteLocationNormalized, RouteLocationRaw } from 'vue-router'\nimport { useAuthStore } from '../stores/auth'\n\n/** Тип возвращаемого значения guard'а — true (passthrough) либо redirect-target. */\ntype GuardResult = boolean | RouteLocationRaw\n\n/**\n * Простая 3-арг функция (то что router.beforeEach принимает).\n * Не используем NavigationGuardWithThis<undefined>, т.к. она требует\n * `this: undefined` что неудобно для прямого вызова в тестах.\n */\ntype SimpleGuard = (\n to: RouteLocationNormalized,\n from: RouteLocationNormalized,\n next?: unknown,\n) => GuardResult\n\nexport interface AuthGuardOptions {\n /** Имя login-роута. По умолчанию 'admin.login'. */\n loginRouteName?: string\n /** Имя роута 403-страницы. По умолчанию 'admin.forbidden'. */\n forbiddenRouteName?: string\n /**\n * Имя query-параметра для возврата на исходную страницу после login.\n * По умолчанию 'redirect'.\n */\n redirectQueryKey?: string\n}\n\n/**\n * Создаёт beforeEach guard. Pinia должна быть activeInstance к моменту\n * вызова guard'а (router.beforeEach срабатывает на каждой навигации,\n * включая первую — Pinia уже должна быть установлена).\n */\nexport function createAuthGuard(opts: AuthGuardOptions = {}): SimpleGuard {\n const loginRouteName = opts.loginRouteName ?? 'admin.login'\n const forbiddenRouteName = opts.forbiddenRouteName ?? 'admin.forbidden'\n const redirectQueryKey = opts.redirectQueryKey ?? 'redirect'\n\n return (to: RouteLocationNormalized) => {\n // Login-роут всегда доступен.\n if (to.name === loginRouteName) {\n return true\n }\n\n const auth = useAuthStore()\n const requiresAuth = to.meta?.requiresAuth === true\n\n if (requiresAuth && !auth.isAuthenticated) {\n return {\n name: loginRouteName,\n query: { [redirectQueryKey]: to.fullPath },\n }\n }\n\n // Залогиненный, но в процессе 2FA — нельзя ходить никуда кроме login.\n if (auth.isChallengePending) {\n return {\n name: loginRouteName,\n query: { [redirectQueryKey]: to.fullPath },\n }\n }\n\n // Permission-check. ANY-логика (хотя бы одно permission совпало).\n const permissionsMeta = to.meta?.permissions\n if (Array.isArray(permissionsMeta) && permissionsMeta.length > 0) {\n const allowed = auth.hasAnyPermission(permissionsMeta as string[])\n if (!allowed) {\n return { name: forbiddenRouteName }\n }\n }\n\n return true\n }\n}\n\nexport interface TitleGuardOptions {\n /** Шаблон заголовка. {title} — meta.title, {brand} — название бренда. */\n template?: string\n /** Имя бренда. */\n brand?: string\n /** Default title если в meta нет. */\n fallback?: string\n}\n\n/**\n * Создаёт afterEach hook, обновляющий document.title.\n *\n * Шаблон по умолчанию: '{title} · {brand}' если оба, иначе один из.\n */\nexport function createTitleGuard(\n opts: TitleGuardOptions = {},\n): (to: RouteLocationNormalized, from?: RouteLocationNormalized, failure?: unknown) => void {\n const template = opts.template\n const brand = opts.brand ?? ''\n const fallback = opts.fallback ?? ''\n\n return (to) => {\n if (typeof document === 'undefined') return\n const t = (to.meta?.title as string | undefined) ?? fallback\n let title: string\n if (template) {\n title = template.replace('{title}', t).replace('{brand}', brand)\n } else if (t && brand) {\n title = `${t} · ${brand}`\n } else {\n title = t || brand\n }\n document.title = title\n }\n}\n","/**\n * createAdminRouter — фабрика admin-router'а.\n *\n * Использование:\n *\n * const router = createAdminRouter({\n * base: '/admin',\n * components: { ... },\n * brand: 'My App',\n * })\n * await router.replaceManifestRoutes(manifestStore.manifest)\n * app.use(router)\n *\n * Library намеренно не делает createWebHistory выбор за host'а — host передаёт\n * объект history (createWebHistory / createWebHashHistory).\n */\n\nimport {\n createRouter,\n createWebHistory,\n type Router,\n type RouteRecordRaw,\n type RouterHistory,\n} from 'vue-router'\nimport type { AdminManifest } from '../stores/manifest'\nimport { buildRoutesFromManifest, type RouteComponentResolver, type AdminRouteComponent } from './builder'\nimport { createAuthGuard, createTitleGuard, type AuthGuardOptions, type TitleGuardOptions } from './guards'\n\nexport interface AdminRouterOptions {\n /** Base URL admin-панели. По умолчанию '/admin'. */\n base?: string\n /** History-implementation. По умолчанию createWebHistory(base). */\n history?: RouterHistory\n /** Component resolver для resource/screen/settings/dashboard роутов. */\n components: RouteComponentResolver & {\n /** Login. */\n login: AdminRouteComponent\n /** Главная (либо overview-dashboard). */\n home: AdminRouteComponent\n /** 403 forbidden. */\n forbidden: AdminRouteComponent\n /** 404 not found. */\n notFound: AdminRouteComponent\n /** Страница профиля. */\n profile?: AdminRouteComponent\n /** Страница уведомлений. */\n notifications?: AdminRouteComponent\n /** Forgot password. */\n forgotPassword?: AdminRouteComponent\n /** Reset password (по token + email из query). */\n resetPassword?: AdminRouteComponent\n }\n /** Дополнительные руты сверху динамики. */\n extraRoutes?: RouteRecordRaw[]\n /** Опции auth-guard. */\n authGuard?: AuthGuardOptions\n /** Опции title-guard. */\n titleGuard?: TitleGuardOptions\n}\n\n/**\n * Расширенный Router с возможностью пере-построить динамические роуты.\n */\nexport interface AdminRouter extends Router {\n /**\n * Пере-собрать динамические роуты из manifest'а.\n * Удаляет старые admin.resource.* / admin.screen.* / admin.settings.* / admin.dashboard.*\n * и заменяет на актуальные. Полезно при перезагрузке manifest'а.\n */\n replaceManifestRoutes(manifest: AdminManifest | null): void\n}\n\n/**\n * Префиксы dynamic-роутов которые подменяются при replaceManifestRoutes.\n */\nconst DYNAMIC_NAME_PREFIXES = [\n 'admin.resource.',\n 'admin.screen.',\n 'admin.settings.',\n 'admin.dashboard.',\n]\n\nfunction isDynamicRouteName(name: unknown): boolean {\n if (typeof name !== 'string') return false\n return DYNAMIC_NAME_PREFIXES.some((p) => name.startsWith(p))\n}\n\nexport function createAdminRouter(opts: AdminRouterOptions): AdminRouter {\n const base = opts.base ?? '/admin'\n const history = opts.history ?? createWebHistory(base)\n\n const staticRoutes: RouteRecordRaw[] = [\n {\n path: '/login',\n name: 'admin.login',\n component: opts.components.login,\n meta: { kind: 'auth', title: 'Вход' },\n },\n {\n path: '/',\n name: 'admin.home',\n component: opts.components.home,\n meta: { requiresAuth: true, kind: 'system', title: 'Главная' },\n },\n {\n path: '/forbidden',\n name: 'admin.forbidden',\n component: opts.components.forbidden,\n meta: { requiresAuth: true, kind: 'system', title: '403 — доступ запрещён' },\n },\n ]\n\n if (opts.components.profile) {\n staticRoutes.push({\n path: '/profile',\n name: 'admin.profile',\n component: opts.components.profile,\n meta: { requiresAuth: true, kind: 'system', title: 'Профиль' },\n })\n }\n\n if (opts.components.notifications) {\n staticRoutes.push({\n path: '/notifications',\n name: 'admin.notifications',\n component: opts.components.notifications,\n meta: { requiresAuth: true, kind: 'system', title: 'Уведомления' },\n })\n }\n\n if (opts.components.forgotPassword) {\n staticRoutes.push({\n path: '/forgot-password',\n name: 'admin.forgotPassword',\n component: opts.components.forgotPassword,\n meta: { kind: 'auth', title: 'Восстановление пароля' },\n })\n }\n if (opts.components.resetPassword) {\n staticRoutes.push({\n path: '/reset-password',\n name: 'admin.resetPassword',\n component: opts.components.resetPassword,\n meta: { kind: 'auth', title: 'Новый пароль' },\n })\n }\n\n // Catch-all 404 кладём в конец — vue-router matches in order и динамика\n // может быть добавлена позже через addRoute.\n const notFoundRoute: RouteRecordRaw = {\n path: '/:pathMatch(.*)*',\n name: 'admin.notFound',\n component: opts.components.notFound,\n meta: { kind: 'system', title: '404' },\n }\n\n const router = createRouter({\n history,\n routes: [...staticRoutes, ...(opts.extraRoutes ?? []), notFoundRoute],\n }) as AdminRouter\n\n router.beforeEach(createAuthGuard(opts.authGuard))\n router.afterEach(createTitleGuard(opts.titleGuard))\n\n router.replaceManifestRoutes = (manifest: AdminManifest | null): void => {\n // Удаляем все старые динамические роуты по name.\n const allRoutes = router.getRoutes()\n for (const route of allRoutes) {\n if (isDynamicRouteName(route.name)) {\n router.removeRoute(route.name as string)\n }\n }\n\n // Удаляем catch-all чтобы потом добавить его обратно последним.\n if (router.hasRoute('admin.notFound')) {\n router.removeRoute('admin.notFound')\n }\n\n const dynamic = buildRoutesFromManifest(manifest, opts.components)\n for (const route of dynamic) {\n router.addRoute(route)\n }\n router.addRoute(notFoundRoute)\n }\n\n return router\n}\n\nexport { buildRoutesFromManifest } from './builder'\nexport type { RouteComponentResolver, RouteMeta, AdminRouteComponent } from './builder'\nexport { createAuthGuard, createTitleGuard } from './guards'\nexport type { AuthGuardOptions, TitleGuardOptions } from './guards'\n","<script setup lang=\"ts\">\n/**\n * TextField — wrapper над UidInput из @dskripchenko/ui. Двусторонняя связь\n * с form-state через provideFormState/useFormState. Тип input'а (text/email/\n * url/password/tel/search) пробрасывается как `type`.\n */\nimport { computed } from 'vue'\nimport { UidInput } from '@dskripchenko/ui'\nimport { useFormState } from '../render/formState'\n\ninterface Props {\n name: string\n label?: string | null\n help?: string | null\n required?: boolean\n placeholder?: string | null\n inputType?: 'text' | 'email' | 'url' | 'password' | 'tel' | 'search'\n disabled?: boolean\n readonly?: boolean\n autocomplete?: string | null\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n label: null,\n help: null,\n placeholder: null,\n inputType: 'text',\n required: false,\n disabled: false,\n readonly: false,\n autocomplete: null,\n})\n\nconst form = useFormState()\nconst value = computed<string>(() => (form.getField(props.name) as string | null | undefined) ?? '')\nconst errorMsg = computed<string | undefined>(() => form.errors[props.name]?.[0])\n\nfunction onUpdate(next: string): void {\n form.setField(props.name, next)\n}\n</script>\n\n<template>\n <UidInput\n :model-value=\"value\"\n :type=\"inputType\"\n :label=\"label ?? undefined\"\n :hint=\"help ?? undefined\"\n :error=\"errorMsg\"\n :placeholder=\"placeholder ?? undefined\"\n :required=\"required\"\n :disabled=\"disabled\"\n :readonly=\"readonly\"\n :name=\"name\"\n :autocomplete=\"autocomplete ?? undefined\"\n @update:model-value=\"onUpdate\"\n />\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { UidTextarea, UidFormField } from '@dskripchenko/ui'\nimport { useFormState } from '../render/formState'\n\ninterface Props {\n name: string\n label?: string | null\n help?: string | null\n required?: boolean\n placeholder?: string | null\n rows?: number\n disabled?: boolean\n readonly?: boolean\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n label: null,\n help: null,\n placeholder: null,\n rows: 4,\n required: false,\n disabled: false,\n readonly: false,\n})\n\nconst form = useFormState()\nconst value = computed<string>(() => (form.getField(props.name) as string | null | undefined) ?? '')\nconst errorMsg = computed<string | undefined>(() => form.errors[props.name]?.[0])\n\nfunction onUpdate(next: string): void {\n form.setField(props.name, next)\n}\n</script>\n\n<template>\n <UidFormField\n :label=\"label ?? undefined\"\n :hint=\"help ?? undefined\"\n :error=\"errorMsg\"\n :required=\"required\"\n :disabled=\"disabled\"\n >\n <UidTextarea\n :model-value=\"value\"\n :rows=\"rows\"\n :placeholder=\"placeholder ?? undefined\"\n :disabled=\"disabled\"\n :readonly=\"readonly\"\n :name=\"name\"\n @update:model-value=\"onUpdate\"\n />\n </UidFormField>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { UidNumberInput, UidFormField } from '@dskripchenko/ui'\nimport { useFormState } from '../render/formState'\n\ninterface Props {\n name: string\n label?: string | null\n help?: string | null\n required?: boolean\n placeholder?: string | null\n min?: number | null\n max?: number | null\n step?: number | null\n disabled?: boolean\n readonly?: boolean\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n label: null,\n help: null,\n placeholder: null,\n min: null,\n max: null,\n step: null,\n required: false,\n disabled: false,\n readonly: false,\n})\n\nconst form = useFormState()\nconst value = computed<number | null>(() => {\n const v = form.getField(props.name)\n if (v === null || v === undefined || v === '') return null\n return typeof v === 'number' ? v : Number(v)\n})\nconst errorMsg = computed<string | undefined>(() => form.errors[props.name]?.[0])\n\nfunction onUpdate(next: number | null): void {\n form.setField(props.name, next)\n}\n</script>\n\n<template>\n <UidFormField\n :label=\"label ?? undefined\"\n :hint=\"help ?? undefined\"\n :error=\"errorMsg\"\n :required=\"required\"\n :disabled=\"disabled\"\n >\n <UidNumberInput\n :model-value=\"value\"\n :min=\"min ?? undefined\"\n :max=\"max ?? undefined\"\n :step=\"step ?? undefined\"\n :placeholder=\"placeholder ?? undefined\"\n :disabled=\"disabled\"\n :readonly=\"readonly\"\n :name=\"name\"\n @update:model-value=\"onUpdate\"\n />\n </UidFormField>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { UidSelect, UidFormField } from '@dskripchenko/ui'\nimport { useFormState } from '../render/formState'\n\nexport interface SelectOption {\n value: string | number\n label: string\n disabled?: boolean\n}\n\ninterface Props {\n name: string\n options: SelectOption[]\n label?: string | null\n help?: string | null\n required?: boolean\n placeholder?: string | null\n disabled?: boolean\n searchable?: boolean\n clearable?: boolean\n size?: 'sm' | 'md' | 'lg'\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n label: null,\n help: null,\n placeholder: null,\n required: false,\n disabled: false,\n searchable: false,\n clearable: false,\n size: 'md',\n})\n\nconst form = useFormState()\nconst value = computed<string | number | null>(() => {\n const v = form.getField(props.name)\n if (v === null || v === undefined || v === '') return null\n return v as string | number\n})\nconst errorMsg = computed<string | undefined>(() => form.errors[props.name]?.[0])\n\nfunction onUpdate(next: string | number | null): void {\n form.setField(props.name, next)\n}\n</script>\n\n<template>\n <UidFormField\n :label=\"label ?? undefined\"\n :hint=\"help ?? undefined\"\n :error=\"errorMsg\"\n :required=\"required\"\n :disabled=\"disabled\"\n >\n <UidSelect\n :model-value=\"value\"\n :options=\"options\"\n :placeholder=\"placeholder ?? undefined\"\n :disabled=\"disabled\"\n :searchable=\"searchable\"\n :clearable=\"clearable\"\n :size=\"size\"\n @update:model-value=\"onUpdate\"\n />\n </UidFormField>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { UidCheckbox, UidFormField } from '@dskripchenko/ui'\nimport { useFormState } from '../render/formState'\n\ninterface Props {\n name: string\n label?: string | null\n help?: string | null\n required?: boolean\n inlineLabel?: string | null\n disabled?: boolean\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n label: null,\n help: null,\n inlineLabel: null,\n required: false,\n disabled: false,\n})\n\nconst form = useFormState()\nconst checked = computed<boolean>(() => Boolean(form.getField(props.name)))\nconst errorMsg = computed<string | undefined>(() => form.errors[props.name]?.[0])\n\nfunction onUpdate(next: boolean): void {\n form.setField(props.name, next)\n}\n</script>\n\n<template>\n <UidFormField\n :label=\"label ?? undefined\"\n :hint=\"help ?? undefined\"\n :error=\"errorMsg\"\n :required=\"required\"\n :disabled=\"disabled\"\n >\n <UidCheckbox\n :model-value=\"checked\"\n :disabled=\"disabled\"\n :name=\"name\"\n @update:model-value=\"onUpdate\"\n >\n <template v-if=\"inlineLabel\">{{ inlineLabel }}</template>\n </UidCheckbox>\n </UidFormField>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { UidDatePicker, UidFormField } from '@dskripchenko/ui'\nimport { useFormState } from '../render/formState'\n\ninterface Props {\n name: string\n label?: string | null\n help?: string | null\n required?: boolean\n /**\n * Тип input'а: 'date' (default), 'datetime-local', 'time'.\n * UidDatePicker внутри обрабатывает формат через свои props; для совместимости\n * со старым API оставляем prop.\n */\n inputType?: 'date' | 'datetime-local' | 'time'\n min?: string | null\n max?: string | null\n disabled?: boolean\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n label: null,\n help: null,\n inputType: 'date',\n min: null,\n max: null,\n required: false,\n disabled: false,\n})\n\nconst form = useFormState()\nconst value = computed<string | null>(() => {\n const v = form.getField(props.name)\n return v === null || v === undefined || v === '' ? null : String(v)\n})\nconst errorMsg = computed<string | undefined>(() => form.errors[props.name]?.[0])\n\nfunction onUpdate(next: string | null): void {\n form.setField(props.name, next)\n}\n</script>\n\n<template>\n <UidFormField\n :label=\"label ?? undefined\"\n :hint=\"help ?? undefined\"\n :error=\"errorMsg\"\n :required=\"required\"\n :disabled=\"disabled\"\n >\n <UidDatePicker\n :model-value=\"value\"\n :min=\"min ?? undefined\"\n :max=\"max ?? undefined\"\n :disabled=\"disabled\"\n :name=\"name\"\n @update:model-value=\"onUpdate\"\n />\n </UidFormField>\n</template>\n","<script setup lang=\"ts\">\n/**\n * TagsField — input для list<string> с chip'ами и free-form вводом.\n *\n * Backend Field-класс — Dskripchenko\\LaravelAdmin\\Field\\TagsInput с\n * fieldType()='tags'. Frontend builtin-registry маппит 'tags' сюда.\n *\n * Особенности:\n * - Free input: Enter / separator (`,` или ';') добавляют новый chip,\n * даже если такого нет в suggestions — это критично для wildcard'ов\n * ('admin.content.*') и других произвольных ключей.\n * - Suggestions: backend кладёт `attributes.suggestions: string[]`. При\n * наличии — рендерим dropdown с фильтром по введённому query.\n * - Backspace на пустом input удаляет последний chip.\n * - Click на chip × удаляет.\n */\nimport { computed, nextTick, ref, watch } from 'vue'\nimport { X } from 'lucide-vue-next'\nimport { UidIcon } from '@dskripchenko/ui'\nimport { useFormState } from '../render/formState'\n\ninterface SuggestionGroup {\n label: string\n items: string[]\n}\n\ninterface Props {\n name: string\n label?: string | null\n help?: string | null\n required?: boolean\n placeholder?: string | null\n /** Плоский список подсказок (compat-вариант). */\n suggestions?: string[]\n /**\n * Группированные подсказки. Когда заданы — dropdown рендерится с\n * заголовками групп. Имеет приоритет над `suggestions`.\n */\n suggestionsByGroup?: SuggestionGroup[]\n /** Лимит количества тегов. */\n maxItems?: number\n /**\n * Дополнительный разделитель (помимо Enter). Например `,` или `;`.\n * При вводе одного из этих символов value до него превращается в chip.\n */\n separator?: string\n disabled?: boolean\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n label: null,\n help: null,\n placeholder: 'Введите ключ и нажмите Enter…',\n required: false,\n suggestions: () => [],\n suggestionsByGroup: () => [],\n maxItems: 0,\n separator: ',',\n disabled: false,\n})\n\nconst form = useFormState()\n\nconst tags = computed<string[]>(() => {\n const v = form.getField(props.name)\n if (Array.isArray(v)) return v.map((x) => String(x))\n if (typeof v === 'string' && v !== '') return v.split(',').map((s) => s.trim()).filter(Boolean)\n return []\n})\n\nconst errorMsg = computed<string | undefined>(() => form.errors[props.name]?.[0])\n\nconst query = ref<string>('')\nconst focused = ref<boolean>(false)\nconst inputRef = ref<HTMLInputElement | null>(null)\nconst containerRef = ref<HTMLElement | null>(null)\n\nfunction setTags(next: string[]): void {\n // Дедуплицируем + лимит.\n const seen = new Set<string>()\n const out: string[] = []\n for (const t of next) {\n const trimmed = t.trim()\n if (trimmed === '' || seen.has(trimmed)) continue\n seen.add(trimmed)\n out.push(trimmed)\n if (props.maxItems > 0 && out.length >= props.maxItems) break\n }\n form.setField(props.name, out)\n}\n\nfunction addTag(value: string): void {\n const v = value.trim()\n if (v === '') return\n if (tags.value.includes(v)) {\n query.value = ''\n return\n }\n setTags([...tags.value, v])\n query.value = ''\n}\n\nfunction removeTag(idx: number): void {\n const next = [...tags.value]\n next.splice(idx, 1)\n setTags(next)\n}\n\nfunction onKeydown(e: KeyboardEvent): void {\n if (e.key === 'Enter') {\n e.preventDefault()\n if (activeIdx.value >= 0 && filteredFlat.value[activeIdx.value]) {\n addTag(filteredFlat.value[activeIdx.value])\n } else if (query.value.trim() !== '') {\n addTag(query.value)\n }\n } else if (e.key === 'Backspace' && query.value === '' && tags.value.length > 0) {\n removeTag(tags.value.length - 1)\n } else if (e.key === 'ArrowDown') {\n e.preventDefault()\n activeIdx.value = Math.min(activeIdx.value + 1, filteredFlat.value.length - 1)\n } else if (e.key === 'ArrowUp') {\n e.preventDefault()\n activeIdx.value = Math.max(activeIdx.value - 1, -1)\n } else if (e.key === 'Escape') {\n focused.value = false\n inputRef.value?.blur()\n }\n}\n\nfunction onInput(e: Event): void {\n const v = (e.target as HTMLInputElement).value\n // Обработка separator-символа: если есть — обрезаем до него и коммитим.\n if (props.separator && v.includes(props.separator)) {\n const parts = v.split(props.separator)\n const completed = parts.slice(0, -1).map((p) => p.trim()).filter(Boolean)\n completed.forEach(addTag)\n query.value = parts[parts.length - 1] ?? ''\n return\n }\n query.value = v\n}\n\nconst activeIdx = ref<number>(-1)\n\n/**\n * Если backend передал suggestionsByGroup — рендерим с заголовками групп,\n * иначе — flat list. Формируем единый отфильтрованный массив для индексной\n * навигации стрелками (activeIdx указывает на index в `filteredFlat`).\n */\nconst grouped = computed<boolean>(\n () => Array.isArray(props.suggestionsByGroup) && props.suggestionsByGroup.length > 0,\n)\n\nconst filteredGroups = computed<SuggestionGroup[]>(() => {\n const q = query.value.trim().toLowerCase()\n const used = new Set(tags.value)\n if (!grouped.value) return []\n return props.suggestionsByGroup\n .map((g) => ({\n label: g.label,\n items: g.items.filter(\n (s) => !used.has(s) && (q === '' || s.toLowerCase().includes(q)),\n ),\n }))\n .filter((g) => g.items.length > 0)\n})\n\nconst filteredFlat = computed<string[]>(() => {\n if (grouped.value) {\n return filteredGroups.value.flatMap((g) => g.items)\n }\n const q = query.value.trim().toLowerCase()\n const used = new Set(tags.value)\n return props.suggestions\n .filter((s) => !used.has(s))\n .filter((s) => q === '' || s.toLowerCase().includes(q))\n .slice(0, 200)\n})\n\n/** Сколько групп выше текущего item'а (для shift при index лookup). */\nfunction isItemActive(globalIdx: number): boolean {\n return globalIdx === activeIdx.value\n}\n\nwatch(query, () => {\n activeIdx.value = -1\n})\n\nfunction onContainerClick(): void {\n if (!props.disabled) inputRef.value?.focus()\n}\n\nfunction onSelectSuggestion(s: string): void {\n addTag(s)\n nextTick(() => inputRef.value?.focus())\n}\n\nfunction onBlur(): void {\n // delay чтобы успел сработать click по dropdown'у\n window.setTimeout(() => {\n focused.value = false\n if (query.value.trim() !== '') {\n addTag(query.value)\n }\n }, 120)\n}\n</script>\n\n<template>\n <div :class=\"['admin-field', { 'admin-field--invalid': errorMsg !== undefined }]\">\n <label v-if=\"label\" class=\"admin-field__label\">\n <span>{{ label }}</span>\n <span v-if=\"required\" class=\"admin-field__required\" aria-hidden=\"true\">*</span>\n </label>\n <div\n ref=\"containerRef\"\n :class=\"[\n 'admin-field__control admin-tags',\n {\n 'admin-tags--focused': focused,\n 'admin-tags--disabled': disabled,\n },\n ]\"\n @click=\"onContainerClick\"\n >\n <span\n v-for=\"(tag, idx) in tags\"\n :key=\"`${tag}-${idx}`\"\n class=\"admin-tags__chip\"\n >\n <span class=\"admin-tags__chip-text\">{{ tag }}</span>\n <button\n v-if=\"!disabled\"\n type=\"button\"\n class=\"admin-tags__chip-remove\"\n aria-label=\"Удалить\"\n @click.stop=\"removeTag(idx)\"\n >\n <UidIcon :icon=\"X\" :size=\"10\" />\n </button>\n </span>\n <input\n ref=\"inputRef\"\n :value=\"query\"\n :placeholder=\"tags.length === 0 ? (placeholder ?? '') : ''\"\n :disabled=\"disabled\"\n class=\"admin-tags__input\"\n type=\"text\"\n @input=\"onInput\"\n @keydown=\"onKeydown\"\n @focus=\"focused = true\"\n @blur=\"onBlur\"\n />\n\n <div\n v-if=\"focused && filteredFlat.length > 0\"\n class=\"admin-tags__dropdown\"\n role=\"listbox\"\n >\n <!-- Grouped рендер: заголовок группы + items внутри -->\n <template v-if=\"grouped\">\n <template\n v-for=\"(g, gi) in filteredGroups\"\n :key=\"`g-${gi}-${g.label}`\"\n >\n <div class=\"admin-tags__group-label\">{{ g.label }}</div>\n <button\n v-for=\"s in g.items\"\n :key=\"s\"\n type=\"button\"\n role=\"option\"\n :class=\"[\n 'admin-tags__option',\n {\n 'admin-tags__option--active': isItemActive(\n filteredFlat.indexOf(s),\n ),\n },\n ]\"\n :aria-selected=\"isItemActive(filteredFlat.indexOf(s))\"\n @mousedown.prevent=\"onSelectSuggestion(s)\"\n @mouseenter=\"activeIdx = filteredFlat.indexOf(s)\"\n >\n {{ s }}\n </button>\n </template>\n </template>\n\n <!-- Flat рендер (без групп) — обратная совместимость -->\n <template v-else>\n <button\n v-for=\"(s, idx) in filteredFlat\"\n :key=\"s\"\n type=\"button\"\n role=\"option\"\n :class=\"['admin-tags__option', { 'admin-tags__option--active': idx === activeIdx }]\"\n :aria-selected=\"idx === activeIdx\"\n @mousedown.prevent=\"onSelectSuggestion(s)\"\n @mouseenter=\"activeIdx = idx\"\n >\n {{ s }}\n </button>\n </template>\n </div>\n </div>\n <p v-if=\"errorMsg\" class=\"admin-field__error\">{{ errorMsg }}</p>\n <p v-else-if=\"help\" class=\"admin-field__help\">{{ help }}</p>\n </div>\n</template>\n\n<style>\n.admin-tags {\n position: relative;\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 4px;\n min-height: 36px;\n padding: 4px 8px;\n border: 1px solid var(--uid-border-subtle);\n background: var(--uid-surface-base);\n border-radius: var(--uid-radius-md);\n cursor: text;\n}\n.admin-tags--focused {\n border-color: var(--uid-accent);\n outline: 2px solid color-mix(in srgb, var(--uid-accent) 18%, transparent);\n}\n.admin-tags--disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n.admin-tags__chip {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 2px 6px 2px 8px;\n background: color-mix(in srgb, var(--uid-accent) 14%, transparent);\n color: var(--uid-accent);\n border-radius: var(--uid-radius-sm);\n font-size: 12px;\n font-weight: 500;\n font-family: var(--uid-font-family-mono, ui-monospace, monospace);\n}\n.admin-tags__chip-remove {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 16px;\n height: 16px;\n border: 0;\n background: transparent;\n color: inherit;\n border-radius: 50%;\n cursor: pointer;\n}\n.admin-tags__chip-remove:hover {\n background: color-mix(in srgb, var(--uid-accent) 28%, transparent);\n}\n.admin-tags__input {\n flex: 1;\n min-width: 80px;\n height: 24px;\n padding: 0 4px;\n border: 0;\n background: transparent;\n outline: none;\n font: inherit;\n font-size: 13px;\n color: var(--uid-text-primary);\n}\n.admin-tags__dropdown {\n position: absolute;\n top: calc(100% + 4px);\n left: 0;\n right: 0;\n z-index: 10;\n margin: 0;\n padding: 4px;\n display: flex;\n flex-direction: column;\n background: var(--uid-surface-raised);\n border: 1px solid var(--uid-border-subtle);\n border-radius: var(--uid-radius-md);\n box-shadow: var(--uid-shadow-md);\n max-height: 320px;\n overflow-y: auto;\n}\n.admin-tags__group-label {\n padding: 8px 10px 4px;\n font-size: 11px;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n color: var(--uid-text-tertiary);\n font-weight: var(--uid-font-weight-semibold);\n position: sticky;\n top: 0;\n background: var(--uid-surface-raised);\n z-index: 1;\n}\n.admin-tags__group-label:first-child { padding-top: 4px; }\n.admin-tags__option {\n display: block;\n width: 100%;\n text-align: left;\n padding: 6px 10px;\n border: 0;\n background: transparent;\n border-radius: var(--uid-radius-sm);\n font-size: 13px;\n cursor: pointer;\n color: var(--uid-text-primary);\n font-family: var(--uid-font-family-mono, ui-monospace, monospace);\n}\n.admin-tags__option:hover,\n.admin-tags__option--active {\n background: var(--uid-color-surface-hover, var(--uid-border-subtle));\n}\n</style>\n","<script setup lang=\"ts\">\n/**\n * TranslatableField — input с табами по локалям для translatable-моделей.\n *\n * Backend laravel-translatable хранит переводы в pivot-таблице. Для admin\n * Resource сериализует значение поля как `{ru: '...', en: '...'}`. Этот\n * компонент рендерит таб'ы по локалям и редактирует каждое значение\n * отдельно.\n *\n * Локали:\n * - resource manifest имеет `meta.locale` + `bootstrap.availableLocales`;\n * - prop `locales` явно перебивает (для случаев когда модель ограничена\n * подмножеством локалей).\n *\n * Backend payload — Object keyed by locale. Form-state сохраняет тот же\n * shape; bridge `TranslatableFieldBridge::extract()` извлекает на стороне\n * ResourceController при save.\n */\nimport { computed, ref } from 'vue'\nimport { UidInput } from '@dskripchenko/ui'\nimport { useFormState } from '../render/formState'\nimport { useLocaleStore } from '../../stores/locale'\n\ninterface Props {\n name: string\n label?: string | null\n help?: string | null\n required?: boolean\n placeholder?: string | null\n /** Override доступных локалей. Default — locale.available. */\n locales?: string[]\n /** Использовать textarea вместо input (для длинных полей body/description). */\n multiline?: boolean\n rows?: number\n disabled?: boolean\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n label: null,\n help: null,\n placeholder: null,\n required: false,\n locales: undefined,\n multiline: false,\n rows: 3,\n disabled: false,\n})\n\nconst form = useFormState()\nconst localeStore = useLocaleStore()\n\nconst availableLocales = computed<string[]>(\n () => props.locales ?? localeStore.available ?? [localeStore.current ?? 'ru'],\n)\nconst activeLocale = ref<string>(localeStore.current ?? availableLocales.value[0] ?? 'ru')\n\nconst value = computed<Record<string, string>>(() => {\n const v = form.getField(props.name)\n if (v && typeof v === 'object' && !Array.isArray(v)) {\n return v as Record<string, string>\n }\n // Если поле пришло как plain-string (legacy non-translatable), оборачиваем.\n if (typeof v === 'string') return { [activeLocale.value]: v }\n return {}\n})\n\nfunction update(locale: string, next: string): void {\n const current = { ...value.value }\n current[locale] = next\n form.setField(props.name, current)\n}\n\nconst errorMsg = computed<string | undefined>(() => {\n // Backend может возвращать ошибки per-locale (`field.ru` / `field.en`).\n const errors = form.errors[props.name]\n if (errors?.[0]) return errors[0]\n for (const loc of availableLocales.value) {\n const e = form.errors[`${props.name}.${loc}`]?.[0]\n if (e) return `[${loc}] ${e}`\n }\n return undefined\n})\n\nfunction isFilled(locale: string): boolean {\n const v = value.value[locale]\n return typeof v === 'string' && v.trim() !== ''\n}\n</script>\n\n<template>\n <div :class=\"['admin-field', { 'admin-field--invalid': errorMsg !== undefined }]\">\n <label v-if=\"label\" class=\"admin-field__label\">\n <span>{{ label }}</span>\n <span v-if=\"required\" class=\"admin-field__required\" aria-hidden=\"true\">*</span>\n </label>\n <div class=\"admin-translatable\">\n <div class=\"admin-translatable__tabs\" role=\"tablist\">\n <button\n v-for=\"loc in availableLocales\"\n :key=\"loc\"\n type=\"button\"\n role=\"tab\"\n :class=\"[\n 'admin-translatable__tab',\n {\n 'admin-translatable__tab--active': activeLocale === loc,\n 'admin-translatable__tab--filled': isFilled(loc),\n },\n ]\"\n :aria-selected=\"activeLocale === loc\"\n @click=\"activeLocale = loc\"\n >\n {{ loc.toUpperCase() }}\n <span v-if=\"isFilled(loc)\" class=\"admin-translatable__dot\" aria-hidden=\"true\" />\n </button>\n </div>\n <div class=\"admin-translatable__panel\">\n <UidInput\n v-if=\"!multiline\"\n :model-value=\"value[activeLocale] ?? ''\"\n :placeholder=\"placeholder ?? ''\"\n :disabled=\"disabled\"\n @update:model-value=\"(v) => update(activeLocale, v as string)\"\n />\n <textarea\n v-else\n :value=\"value[activeLocale] ?? ''\"\n :placeholder=\"placeholder ?? ''\"\n :rows=\"rows\"\n :disabled=\"disabled\"\n class=\"admin-translatable__textarea\"\n @input=\"(e) => update(activeLocale, (e.target as HTMLTextAreaElement).value)\"\n />\n </div>\n </div>\n <p v-if=\"errorMsg\" class=\"admin-field__error\">{{ errorMsg }}</p>\n <p v-else-if=\"help\" class=\"admin-field__help\">{{ help }}</p>\n </div>\n</template>\n\n<style>\n.admin-translatable { display: flex; flex-direction: column; gap: 6px; }\n.admin-translatable__tabs {\n display: inline-flex;\n align-items: center;\n gap: 2px;\n align-self: flex-start;\n padding: 2px;\n background: var(--uid-surface-base);\n border: 1px solid var(--uid-border-subtle);\n border-radius: var(--uid-radius-md);\n}\n.admin-translatable__tab {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 4px 10px;\n border: 0;\n background: transparent;\n border-radius: var(--uid-radius-sm);\n font-size: 11px;\n font-weight: 600;\n color: var(--uid-text-secondary);\n cursor: pointer;\n letter-spacing: 0.04em;\n}\n.admin-translatable__tab:hover { color: var(--uid-text-primary); }\n.admin-translatable__tab--active {\n background: var(--uid-surface-raised);\n color: var(--uid-text-primary);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);\n}\n.admin-translatable__dot {\n width: 5px;\n height: 5px;\n border-radius: 50%;\n background: var(--uid-color-success, #10b981);\n}\n.admin-translatable__textarea {\n width: 100%;\n padding: 8px 10px;\n border: 1px solid var(--uid-border-subtle);\n background: var(--uid-surface-base);\n border-radius: var(--uid-radius-md);\n color: var(--uid-text-primary);\n font: inherit;\n font-size: 13px;\n resize: vertical;\n}\n.admin-translatable__textarea:focus {\n outline: 2px solid color-mix(in srgb, var(--uid-accent) 18%, transparent);\n border-color: var(--uid-accent);\n}\n</style>\n","<script setup lang=\"ts\">\n/**\n * Rows-layout — UidStack column.\n */\nimport { UidStack } from '@dskripchenko/ui'\nimport LayoutRenderer from '../render/LayoutRenderer.vue'\nimport type { LayoutNode } from '../render/LayoutRenderer.vue'\n\ninterface Props {\n items: LayoutNode[]\n /** CSS-зазор между элементами (token либо px), по умолчанию --uid-space-md. */\n gap?: string\n}\nwithDefaults(defineProps<Props>(), { gap: 'var(--uid-space-md)' })\n</script>\n\n<template>\n <UidStack direction=\"column\" :gap=\"gap\" align=\"stretch\">\n <LayoutRenderer v-for=\"(child, idx) in items\" :key=\"idx\" :node=\"child\" />\n </UidStack>\n</template>\n","<script setup lang=\"ts\">\n/**\n * Columns: 12-колоночный grid поверх UidGrid из @dskripchenko/ui.\n * Каждый item.span (1..cols) задаёт ширину; default равные доли.\n */\nimport { computed } from 'vue'\nimport { UidGrid } from '@dskripchenko/ui'\nimport LayoutRenderer from '../render/LayoutRenderer.vue'\nimport type { LayoutNode } from '../render/LayoutRenderer.vue'\n\ninterface Props {\n items: LayoutNode[]\n /** Зазор между ячейками (CSS, token или px). */\n gap?: string\n /** Сколько колонок в гриде (default 12). */\n cols?: number\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n gap: 'var(--uid-space-md)',\n cols: 12,\n})\n\nconst defaultSpan = computed(() => {\n if (props.items.length === 0) return props.cols\n return Math.max(1, Math.floor(props.cols / props.items.length))\n})\n\nfunction spanFor(item: LayoutNode): number {\n const s = (item as Record<string, unknown>).span\n if (typeof s === 'number' && s > 0) return Math.min(s, props.cols)\n return defaultSpan.value\n}\n</script>\n\n<template>\n <UidGrid :cols=\"cols\" :gap=\"gap\">\n <div\n v-for=\"(child, idx) in items\"\n :key=\"idx\"\n class=\"admin-columns__item\"\n :style=\"{ gridColumn: `span ${spanFor(child)} / span ${spanFor(child)}` }\"\n >\n <LayoutRenderer :node=\"child\" />\n </div>\n </UidGrid>\n</template>\n","<script setup lang=\"ts\">\n/**\n * Section/Block layout — UidCard с заголовком + опциональным описанием.\n */\nimport { UidCard } from '@dskripchenko/ui'\nimport LayoutRenderer from '../render/LayoutRenderer.vue'\nimport type { LayoutNode } from '../render/LayoutRenderer.vue'\n\ninterface Props {\n items: LayoutNode[]\n title?: string | null\n description?: string | null\n}\n\nwithDefaults(defineProps<Props>(), {\n title: null,\n description: null,\n})\n</script>\n\n<template>\n <UidCard padding=\"md\" class=\"admin-section\">\n <header v-if=\"title || description\" class=\"admin-section__header\">\n <h3 v-if=\"title\" class=\"admin-section__title\">{{ title }}</h3>\n <p v-if=\"description\" class=\"admin-section__description\">{{ description }}</p>\n </header>\n <div class=\"admin-section__body\">\n <LayoutRenderer v-for=\"(child, idx) in items\" :key=\"idx\" :node=\"child\" />\n </div>\n </UidCard>\n</template>\n\n<style>\n.admin-section { margin-bottom: var(--uid-space-md); }\n.admin-section__header { margin-bottom: var(--uid-space-sm); }\n.admin-section__title {\n margin: 0;\n font-size: var(--uid-font-size-sm);\n font-weight: var(--uid-font-weight-semibold);\n color: var(--uid-text-primary);\n}\n.admin-section__description {\n margin: var(--uid-space-2xs) 0 0;\n font-size: var(--uid-font-size-xs);\n color: var(--uid-text-tertiary);\n}\n.admin-section__body {\n display: flex;\n flex-direction: column;\n gap: var(--uid-space-sm);\n}\n</style>\n","<script setup lang=\"ts\">\n/**\n * TabsLayout поверх UidTabs/UidTab/UidTabPanel.\n * Активная вкладка двусторонне связана через v-model:active.\n */\nimport { ref } from 'vue'\nimport { UidTabs, UidTab, UidTabPanel } from '@dskripchenko/ui'\nimport LayoutRenderer from '../render/LayoutRenderer.vue'\nimport type { LayoutNode } from '../render/LayoutRenderer.vue'\n\nexport interface TabNode {\n /** Уникальный ключ вкладки. Если не задан — берётся индекс. */\n key?: string\n /** Текст вкладки. */\n label: string\n icon?: string | null\n items: LayoutNode[]\n}\n\ninterface Props {\n items: TabNode[]\n /** Активная вкладка (key либо индекс при отсутствии key). */\n active?: string | number\n}\n\nconst props = withDefaults(defineProps<Props>(), { active: 0 })\nconst emit = defineEmits<{ 'update:active': [value: string | number] }>()\n\nfunction tabKey(tab: TabNode, idx: number): string | number {\n return tab.key ?? idx\n}\n\nconst localActive = ref<string | number>(props.active ?? tabKey(props.items[0] ?? { label: '' }, 0))\n\nfunction onUpdate(value: string | number): void {\n localActive.value = value\n emit('update:active', value)\n}\n</script>\n\n<template>\n <UidTabs :model-value=\"localActive\" @update:model-value=\"onUpdate\">\n <template #list>\n <UidTab\n v-for=\"(tab, idx) in items\"\n :key=\"tabKey(tab, idx)\"\n :value=\"tabKey(tab, idx)\"\n >\n {{ tab.label }}\n </UidTab>\n </template>\n\n <UidTabPanel\n v-for=\"(tab, idx) in items\"\n :key=\"`panel-${tabKey(tab, idx)}`\"\n :value=\"tabKey(tab, idx)\"\n >\n <LayoutRenderer\n v-for=\"(child, cidx) in tab.items\"\n :key=\"cidx\"\n :node=\"child\"\n />\n </UidTabPanel>\n </UidTabs>\n</template>\n","/**\n * Default-bundle с минимальным набором builtin-компонентов.\n *\n * Использование:\n *\n * import { registerBuiltinComponents } from '@dskripchenko/laravel-admin'\n * registerBuiltinComponents()\n */\n\nimport { registerComponents } from './registry'\nimport TextField from '../fields/TextField.vue'\nimport TextAreaField from '../fields/TextAreaField.vue'\nimport NumberField from '../fields/NumberField.vue'\nimport SelectField from '../fields/SelectField.vue'\nimport CheckboxField from '../fields/CheckboxField.vue'\nimport DateField from '../fields/DateField.vue'\nimport TagsField from '../fields/TagsField.vue'\nimport TranslatableField from '../fields/TranslatableField.vue'\nimport RowsLayout from '../layouts/RowsLayout.vue'\nimport ColumnsLayout from '../layouts/ColumnsLayout.vue'\nimport SectionLayout from '../layouts/SectionLayout.vue'\nimport TabsLayout from '../layouts/TabsLayout.vue'\n\nexport function registerBuiltinComponents(): void {\n registerComponents({\n fields: {\n // Backend Field-классы из dskripchenko/laravel-admin отдают эти fieldType()\n // строки. Соответствие см. core/src/Field/{Input,TextArea,Select,...}.php.\n input: TextField,\n text: TextField,\n email: TextField,\n url: TextField,\n password: TextField,\n tel: TextField,\n search: TextField,\n slug: TextField,\n hidden: TextField,\n label: TextField,\n textarea: TextAreaField,\n // Fallback для wysiwyg/markdown/code — обычный TextAreaField.\n // Реальный rich-editor host подключает через subpath:\n // import { QuillField } from '@dskripchenko/laravel-admin/quill'\n // registerField('wysiwyg', QuillField)\n wysiwyg: TextAreaField,\n markdown: TextAreaField,\n code: TextAreaField,\n number: NumberField,\n slider: NumberField,\n rating: NumberField,\n select: SelectField,\n combobox: SelectField,\n radio: SelectField,\n tags: TagsField,\n // Translatable: backend Field\\TranslatableInput → fieldType()='translatable'.\n // Хранит value как Record<locale, string>; UI показывает табы по локалям.\n translatable: TranslatableField,\n 'translatable-text': TranslatableField,\n 'morph-switcher': SelectField,\n relation: SelectField,\n cascader: SelectField,\n 'tree-select': SelectField,\n checkbox: CheckboxField,\n switch: CheckboxField,\n switcher: CheckboxField,\n boolean: CheckboxField,\n date: DateField,\n datetime: DateField,\n datepicker: DateField,\n 'date-range': DateField,\n time: DateField,\n 'time-picker': DateField,\n 'color-picker': TextField,\n },\n layouts: {\n rows: RowsLayout,\n columns: ColumnsLayout,\n section: SectionLayout,\n block: SectionLayout,\n tabs: TabsLayout,\n accordion: SectionLayout,\n group: RowsLayout,\n step: SectionLayout,\n wizard: SectionLayout,\n },\n })\n}\n","<script setup lang=\"ts\">\n/**\n * TextEntry — строковое read-only значение со встроенным label.\n *\n * Render-режим:\n * - если label задан → row с label сверху и value снизу (admin-form display).\n * - если label пустой → inline span (для обёрток типа BadgeEntry).\n *\n * Auto-formatting через formatCell (см. resource/cellFormat.ts) — преобразует\n * ISO datetime в d.m.Y H:i:s и т.д., если preset указан.\n */\nimport { computed } from 'vue'\nimport { tryUseRecord } from './recordContext'\nimport { formatCell } from '../resource/cellFormat'\n\ninterface Props {\n name?: string\n label?: string\n value?: string | number | null\n /** Заместитель пустого значения. */\n placeholder?: string\n /** Применить mono-font (например для ID/UUID). */\n mono?: boolean\n /** Preset форматтер: datetime/date/money/boolean/bytes. */\n preset?: string\n meta?: Record<string, unknown>\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n name: '',\n label: '',\n value: undefined,\n placeholder: '—',\n mono: false,\n preset: undefined,\n meta: () => ({}),\n})\n\nconst record = tryUseRecord()\nconst display = computed<string>(() => {\n let v: unknown = props.value\n if (v === undefined && record && props.name) {\n v = record[props.name]\n }\n if (v === null || v === undefined || v === '') return props.placeholder\n const formatted = formatCell(v, props.preset, props.meta as Record<string, unknown>)\n return formatted === '' ? props.placeholder : formatted\n})\n\nconst hasLabel = computed<boolean>(() => Boolean(props.label))\n</script>\n\n<template>\n <div v-if=\"hasLabel\" class=\"admin-infolist-entry\">\n <span class=\"admin-infolist-entry__label\">{{ label }}</span>\n <span :class=\"['admin-infolist-entry__value', mono ? 'admin-infolist-entry__value--mono' : '']\">\n {{ display }}\n </span>\n </div>\n <span\n v-else\n :class=\"['admin-infolist-text', mono ? 'admin-infolist-text--mono' : '']\"\n >\n {{ display }}\n </span>\n</template>\n\n<style>\n.admin-infolist-entry {\n display: flex;\n flex-direction: column;\n gap: var(--uid-space-2xs);\n padding: var(--uid-space-sm) 0;\n}\n.admin-infolist-entry + .admin-infolist-entry {\n border-top: 1px solid var(--uid-border-subtle);\n}\n.admin-infolist-entry__label {\n font-size: var(--uid-font-size-xs);\n color: var(--uid-text-tertiary);\n text-transform: uppercase;\n letter-spacing: 0.04em;\n font-weight: var(--uid-font-weight-medium);\n}\n.admin-infolist-entry__value {\n font-size: var(--uid-font-size-sm);\n color: var(--uid-text-primary);\n word-break: break-word;\n white-space: pre-wrap;\n}\n.admin-infolist-entry__value--mono {\n font-family: var(--uid-font-family-mono);\n font-size: var(--uid-font-size-xs);\n}\n\n.admin-infolist-text {\n font-size: var(--uid-font-size-sm);\n color: var(--uid-text-primary);\n}\n.admin-infolist-text--mono {\n font-family: var(--uid-font-family-mono);\n font-size: var(--uid-font-size-xs);\n}\n</style>\n","<script setup lang=\"ts\">\n/**\n * BadgeEntry — строковое значение в виде UidBadge с variant'ом по value-mapping.\n *\n * Manifest:\n * { type: 'badge', name: 'status', label: 'Status',\n * map: { published: 'success', draft: 'warning', archived: 'danger' } }\n */\nimport { computed } from 'vue'\nimport { UidBadge } from '@dskripchenko/ui'\nimport { tryUseRecord } from './recordContext'\n\ntype BadgeVariant = 'default' | 'success' | 'warning' | 'danger' | 'info'\n\ninterface Props {\n name?: string\n label?: string\n value?: string | null\n /** map value → variant. Если не задан — default. */\n map?: Record<string, BadgeVariant>\n /** Принудительный variant. */\n variant?: BadgeVariant\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n name: '',\n label: '',\n value: undefined,\n map: () => ({}),\n variant: undefined,\n})\n\nconst record = tryUseRecord()\nconst value = computed<string>(() => {\n let v: unknown = props.value\n if (v === undefined && record && props.name) {\n v = record[props.name]\n }\n return v === null || v === undefined ? '' : String(v)\n})\nconst resolvedVariant = computed<BadgeVariant>(() => {\n if (props.variant) return props.variant\n return props.map[value.value] ?? 'default'\n})\n</script>\n\n<template>\n <UidBadge v-if=\"value\" :variant=\"resolvedVariant\">\n {{ value }}\n </UidBadge>\n <span v-else class=\"admin-infolist-text\">—</span>\n</template>\n","<script setup lang=\"ts\">\n/**\n * IconEntry — boolean-флаг как иконка (true → check, false → x).\n * Опционально labels: '{ true: \"Опубликовано\", false: \"Черновик\" }'.\n */\nimport { computed } from 'vue'\nimport { tryUseRecord } from './recordContext'\n\ninterface Props {\n name?: string\n label?: string\n value?: boolean | null\n /** Имя icon'и для true (lucide-key, например 'check-circle-2'). */\n trueIcon?: string\n /** Имя icon'и для false. */\n falseIcon?: string\n /** Текстовые подписи. */\n trueLabel?: string\n falseLabel?: string\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n name: '',\n label: '',\n value: undefined,\n trueIcon: 'check-circle-2',\n falseIcon: 'circle',\n trueLabel: '',\n falseLabel: '',\n})\n\nconst record = tryUseRecord()\nconst flag = computed<boolean>(() => {\n let v: unknown = props.value\n if (v === undefined && record && props.name) {\n v = record[props.name]\n }\n return Boolean(v)\n})\nconst displayLabel = computed(() => (flag.value ? props.trueLabel : props.falseLabel))\nconst iconName = computed(() => (flag.value ? props.trueIcon : props.falseIcon))\n</script>\n\n<template>\n <span :class=\"['admin-infolist-icon', flag ? 'admin-infolist-icon--on' : 'admin-infolist-icon--off']\">\n <span class=\"admin-infolist-icon__glyph\" :data-icon=\"iconName\" />\n <span v-if=\"displayLabel\">{{ displayLabel }}</span>\n </span>\n</template>\n\n<style>\n.admin-infolist-icon {\n display: inline-flex;\n align-items: center;\n gap: var(--uid-space-xs);\n font-size: var(--uid-font-size-sm);\n}\n.admin-infolist-icon--on { color: var(--uid-success); }\n.admin-infolist-icon--off { color: var(--uid-text-tertiary); }\n.admin-infolist-icon__glyph {\n display: inline-block;\n width: 14px;\n height: 14px;\n}\n</style>\n","<script setup lang=\"ts\">\n/**\n * KeyValueEntry — словарь {key: value} как UidDescriptionList.\n * Source: prop.value (Record) либо record[name].\n */\nimport { computed } from 'vue'\nimport { UidDescriptionList, UidDescriptionItem } from '@dskripchenko/ui'\nimport { tryUseRecord } from './recordContext'\n\ninterface Props {\n name?: string\n label?: string\n value?: Record<string, unknown>\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n name: '',\n label: '',\n value: undefined,\n})\n\nconst record = tryUseRecord()\nconst items = computed<Array<[string, unknown]>>(() => {\n let v: unknown = props.value\n if (v === undefined && record && props.name) {\n v = record[props.name]\n }\n if (v === null || v === undefined) return []\n if (typeof v !== 'object') return []\n return Object.entries(v as Record<string, unknown>)\n})\n\nfunction formatValue(v: unknown): string {\n if (v === null || v === undefined) return '—'\n if (typeof v === 'object') return JSON.stringify(v)\n return String(v)\n}\n</script>\n\n<template>\n <UidDescriptionList v-if=\"items.length > 0\" direction=\"vertical\" :columns=\"1\">\n <UidDescriptionItem\n v-for=\"[k, v] in items\"\n :key=\"k\"\n :label=\"k\"\n >\n {{ formatValue(v) }}\n </UidDescriptionItem>\n </UidDescriptionList>\n <span v-else class=\"admin-infolist-text\">—</span>\n</template>\n","/**\n * Default-bundle с минимальным набором builtin infolist-entry'ев.\n *\n * View-страница (ResourceViewPage) использует те же type-strings что и\n * form-page (ResourceFormPage) — backend Field::fieldType() возвращает\n * одинаковое имя в обоих контекстах. Поэтому infolist-mapping должен\n * покрывать те же типы что registerBuiltinComponents — fallback на\n * TextEntry для всех stdread-only представлений.\n */\n\nimport { registerInfolistEntries } from './registry'\nimport TextEntry from './TextEntry.vue'\nimport BadgeEntry from './BadgeEntry.vue'\nimport IconEntry from './IconEntry.vue'\nimport KeyValueEntry from './KeyValueEntry.vue'\n\nexport function registerBuiltinInfolistEntries(): void {\n registerInfolistEntries({\n // Дефолтные типы infolist (BadgeEntry::make() и т.п.).\n text: TextEntry,\n badge: BadgeEntry,\n icon: IconEntry,\n keyvalue: KeyValueEntry,\n 'key-value': KeyValueEntry,\n // Маппинг от backend Field::fieldType() → TextEntry для view-режима.\n // Host'ы могут перебить registerInfolistEntry('wysiwyg', WysiwygEntry).\n input: TextEntry,\n email: TextEntry,\n url: TextEntry,\n password: TextEntry,\n tel: TextEntry,\n search: TextEntry,\n slug: TextEntry,\n hidden: TextEntry,\n label: TextEntry,\n textarea: TextEntry,\n wysiwyg: TextEntry,\n markdown: TextEntry,\n code: TextEntry,\n number: TextEntry,\n slider: TextEntry,\n rating: TextEntry,\n select: TextEntry,\n combobox: TextEntry,\n radio: TextEntry,\n tags: TextEntry,\n 'morph-switcher': TextEntry,\n relation: TextEntry,\n cascader: TextEntry,\n 'tree-select': TextEntry,\n checkbox: TextEntry,\n switch: TextEntry,\n switcher: TextEntry,\n boolean: TextEntry,\n date: TextEntry,\n datetime: TextEntry,\n datepicker: TextEntry,\n 'date-range': TextEntry,\n time: TextEntry,\n 'time-picker': TextEntry,\n 'color-picker': TextEntry,\n })\n}\n","/**\n * createAdminApp — фабрика-helper для host-проектов.\n *\n * Собирает Vue-app со всем нужным: Pinia, Router, AdminClient, hydrated\n * stores, built-in fields/layouts/widgets/infolist, default страницы.\n * Возвращает объект где `app` готов к `.mount('#admin-app')`.\n *\n * Минимальный пример (host's resources/js/admin.js):\n *\n * import { createAdminApp } from '@dskripchenko/laravel-admin'\n * import '@dskripchenko/laravel-admin/style.css'\n *\n * const { app } = createAdminApp(window.__ADMIN_BOOTSTRAP__)\n * app.mount('#admin-app')\n *\n * Расширенное использование с переопределением страниц:\n *\n * const { app } = createAdminApp(window.__ADMIN_BOOTSTRAP__, {\n * pages: { home: MyDashboard },\n * onAppCreated: (app) => app.use(SomePlugin),\n * })\n */\n\nimport { createApp, watch, type App, type Component } from 'vue'\nimport { createPinia } from 'pinia'\nimport { createWebHistory } from 'vue-router'\n\nimport AdminApp from './components/AdminApp.vue'\nimport HomePage from './components/HomePage.vue'\nimport ForbiddenPage from './components/ForbiddenPage.vue'\nimport NotFoundPage from './components/NotFoundPage.vue'\nimport SettingsPage from './components/SettingsPage.vue'\nimport UnknownScreenPage from './components/UnknownScreenPage.vue'\nimport { LoginPage } from './components/auth'\nimport ForgotPasswordPage from './components/auth/ForgotPasswordPage.vue'\nimport ResetPasswordPage from './components/auth/ResetPasswordPage.vue'\nimport {\n ResourceIndexPage,\n ResourceFormPage,\n ResourceViewPage,\n} from './components/resource'\nimport { ProfilePage } from './components/profile'\nimport { DashboardPage } from './components/dashboard'\n\nimport { createAdminClient, type AdminClient } from './api/client'\nimport { setAdminClient } from './stores'\nimport { useAuthStore } from './stores/auth'\nimport { useLocaleStore } from './stores/locale'\nimport { useI18nStore } from './stores/i18n'\nimport { useThemeStore } from './stores/theme'\nimport { useNotificationsStore } from './stores/notifications'\nimport { useManifestStore } from './stores/manifest'\nimport { useMenuStore } from './stores/menu'\nimport { useNavigationStore } from './stores/navigation'\n\nimport { createAdminRouter, type AdminRouter, type AdminRouterOptions } from './router'\nimport { registerBuiltinComponents } from './components/render/builtin'\nimport { registerBuiltinWidgets } from './components/dashboard/builtin'\nimport { registerBuiltinInfolistEntries } from './components/infolist/builtin'\n\nimport type { AdminBootstrap } from './types/bootstrap'\n\nexport interface CreateAdminAppPages {\n /** Login page. По умолчанию core'овский LoginPage. */\n login?: Component\n /** Главная (после login). По умолчанию HomePage. */\n home?: Component\n /** 403. По умолчанию ForbiddenPage. */\n forbidden?: Component\n /** 404. По умолчанию NotFoundPage. */\n notFound?: Component\n /** Профиль. По умолчанию ProfilePage. */\n profile?: Component\n /** Auth: forgot/reset password. По умолчанию core'овские. */\n forgotPassword?: Component\n resetPassword?: Component\n /** Resource index/form/view. По умолчанию core'овские. */\n resourceIndex?: Component\n resourceCreate?: Component\n resourceEdit?: Component\n resourceView?: Component\n /** Dashboard страница (для роутов admin.dashboard.*). */\n dashboard?: Component\n /** Settings page (для admin.settings.*). */\n settings?: Component\n /** Custom Screen page (для admin.screen.*). */\n screen?: Component\n}\n\nexport interface CreateAdminAppOptions {\n /**\n * Базовый URL admin-панели. По умолчанию берётся из bootstrap.baseUrl\n * (если он pathname вида '/admin'), иначе '/admin'.\n */\n base?: string\n /** Override отдельных страниц. */\n pages?: CreateAdminAppPages\n /** Дополнительные опции router'а (extraRoutes, history, guards). */\n router?: Partial<Omit<AdminRouterOptions, 'components'>>\n /** Hook для до-настройки app перед mount (app.use(plugin), app.provide(...)). */\n onAppCreated?: (app: App) => void\n /**\n * Не вызывать manifestStore.load() автоматически. По умолчанию false —\n * createAdminApp сам подгружает manifest и выстраивает динамические роуты.\n */\n skipManifestLoad?: boolean\n}\n\nexport interface AdminAppHandle {\n app: App\n router: AdminRouter\n client: AdminClient\n}\n\n/**\n * Создать Vue admin-app, готовый к `.mount('#admin-app')`.\n *\n * Шаги внутри:\n * 1. Pinia + AdminClient (axios через bootstrap.csrf/apiUrl).\n * 2. Hydrate auth/locale/theme/notifications stores из bootstrap.\n * 3. Регистрация built-in fields/layouts/widgets/infolist entries.\n * 4. Router со static-routes (login/home/profile/forbidden/notFound) +\n * async manifest load → replaceManifestRoutes для resource/screen/\n * settings/dashboard.\n * 5. Возврат `{ app, router, client }`. Host вызывает `app.mount(...)`.\n */\nexport function createAdminApp(\n bootstrap: AdminBootstrap,\n options: CreateAdminAppOptions = {},\n): AdminAppHandle {\n const pages = options.pages ?? {}\n const base = options.base ?? deriveBase(bootstrap.baseUrl) ?? '/admin'\n\n // 1. AdminClient\n const client = createAdminClient({\n baseURL: bootstrap.apiUrl,\n csrfToken: bootstrap.csrf,\n })\n setAdminClient(client)\n\n // 2. Vue app + Pinia\n const app = createApp(AdminApp)\n const pinia = createPinia()\n app.use(pinia)\n\n // 3. Pinia stores hydrate\n useAuthStore().hydrate(bootstrap)\n useLocaleStore().hydrate(bootstrap)\n useThemeStore().hydrate(bootstrap)\n useNotificationsStore().hydrate(bootstrap)\n useI18nStore().hydrate(bootstrap)\n\n // 4. Builtin field/layout/widget/infolist registries\n registerBuiltinComponents()\n registerBuiltinWidgets()\n registerBuiltinInfolistEntries()\n\n // 5. Router\n const router = createAdminRouter({\n base,\n history: options.router?.history ?? createWebHistory(base),\n components: {\n login: pages.login ?? LoginPage,\n home: pages.home ?? HomePage,\n forbidden: pages.forbidden ?? ForbiddenPage,\n notFound: pages.notFound ?? NotFoundPage,\n profile: pages.profile ?? ProfilePage,\n forgotPassword: pages.forgotPassword ?? ForgotPasswordPage,\n resetPassword: pages.resetPassword ?? ResetPasswordPage,\n resourceIndex: pages.resourceIndex ?? ResourceIndexPage,\n resourceCreate: pages.resourceCreate ?? ResourceFormPage,\n resourceEdit: pages.resourceEdit ?? ResourceFormPage,\n resourceView: pages.resourceView ?? ResourceViewPage,\n dashboard: pages.dashboard ?? DashboardPage,\n settings: pages.settings ?? SettingsPage,\n screen: pages.screen ?? UnknownScreenPage,\n },\n extraRoutes: options.router?.extraRoutes,\n authGuard: options.router?.authGuard,\n titleGuard: options.router?.titleGuard,\n })\n app.use(router)\n\n // 5.1 Top loading-bar hooks: pending++ при старте навигации, pending--\n // при её завершении.\n const navStore = useNavigationStore()\n router.beforeEach((to, from, next) => {\n if (to.fullPath !== from.fullPath) navStore.start()\n next()\n })\n router.afterEach(() => {\n navStore.end()\n })\n router.onError(() => {\n navStore.end()\n })\n\n // 5.2 Pre-fetch resource data ДО mount страницы. Это держит navigation в\n // pending'е — старая страница остаётся в DOM пока новая загружает данные.\n // После resolve hook'а Vue Router монтирует новую страницу с уже\n // наполненным store'ом, что устраняет flash \"пустая страница →\n // данные приехали\" (без необходимости в Suspense).\n router.beforeResolve(async (to, _from, next) => {\n // Только resource.index роуты предзагружают свой dataset.\n const name = typeof to.name === 'string' ? to.name : null\n if (name && name.startsWith('admin.resource.') && name.endsWith('.index')) {\n const slug = (to.params.slug as string | undefined) ?? (to.meta.slug as string | undefined)\n if (slug) {\n try {\n // Lazy-import чтобы избежать circular в createAdminApp init.\n const { useResourceIndexStore } = await import('./stores/resourceIndex')\n const indexStore = useResourceIndexStore()\n if (indexStore.slug !== slug || indexStore.items.length === 0) {\n indexStore.setSlug(slug)\n await indexStore.load().catch(() => undefined)\n }\n } catch {\n // silent — page mount упадёт в свой error-state.\n }\n }\n }\n next()\n })\n\n // 6. Manifest async-load + dynamic routes (только если authenticated;\n // при появлении user после login — manifest подгружается автоматически).\n if (!options.skipManifestLoad) {\n const manifestStore = useManifestStore()\n const authStore = useAuthStore()\n\n const menuStore = useMenuStore()\n\n const loadAndApply = async (): Promise<void> => {\n // Параллельно с manifest'ом тянем sidebar-меню (от backend menu endpoint).\n void menuStore.load().catch(() => undefined)\n\n try {\n const manifest = await manifestStore.load()\n router.replaceManifestRoutes(manifest)\n // Если текущий route был разрешён в catch-all notFound (deep-link\n // на /r/articles/123/edit при первом mount, когда динамические\n // роуты ещё не были добавлены) — перерезолвим его теперь, когда\n // routes есть. Дожидаемся router.replace ДО того как выставим\n // bootResolved — иначе AdminApp на одном кадре увидит\n // (manifest !== null, route.name === 'admin.notFound') и сверкнёт 404.\n const current = router.currentRoute.value\n if (current.name === 'admin.notFound' && current.fullPath !== '/') {\n await router.replace(current.fullPath).catch(() => undefined)\n }\n } catch (error) {\n // Silent fail — host может перехватить через onAppCreated →\n // app.config.errorHandler. Manifest перезагрузится при следующем\n // появлении user (watch ниже).\n if (typeof console !== 'undefined') {\n console.error('[laravel-admin] manifest load failed:', error)\n }\n } finally {\n // Открываем гейт NotFoundPage. После этой точки реальный 404\n // (несуществующий URL) уже корректно отрисуется без вспышки.\n manifestStore.bootResolved = true\n }\n }\n\n if (authStore.isAuthenticated) {\n // Inline-bootstrap уже принёс user'а — грузим сразу.\n void loadAndApply()\n } else {\n // Login flow — manifest не нужен прямо сейчас; гейт открыт сразу,\n // чтобы LoginPage / NotFoundPage отрисовались штатно.\n manifestStore.bootResolved = true\n }\n // Если user'а ещё нет (login flow) либо появится позже —\n // подписываемся и грузим когда появится. immediate: false чтобы не\n // дублировать вызов при isAuthenticated=true выше.\n watch(\n () => authStore.user,\n (newUser, oldUser) => {\n if (newUser && !oldUser) {\n // Новый login → требуется свежий manifest, гейт сбрасываем.\n manifestStore.bootResolved = false\n void loadAndApply()\n }\n },\n )\n } else {\n // Host явно отключил manifest — гейт открыт сразу.\n useManifestStore().bootResolved = true\n }\n\n // 7. host hook\n options.onAppCreated?.(app)\n\n return { app, router, client }\n}\n\n/**\n * Извлечь base path из bootstrap.baseUrl ('http://app.test/admin' → '/admin').\n */\nfunction deriveBase(baseUrl: string | undefined): string | null {\n if (!baseUrl) return null\n try {\n const url = new URL(baseUrl)\n return url.pathname || '/admin'\n } catch {\n return baseUrl.startsWith('/') ? baseUrl : null\n }\n}\n","/**\n * Загрузка bootstrap-payload'а в SPA.\n *\n * Поддерживает обе стратегии:\n * - 'inline' — читает window.__ADMIN_BOOTSTRAP__ (инжект через\n * shell.blade при strategy=inline).\n * - 'xhr' — fetch'ит /api/admin/system/bootstrap.\n *\n * Если оба способа не дали результата — throw'ит. SPA должна это поймать\n * и показать full-screen error.\n */\n\nimport type { AdminBootstrap } from '../types/bootstrap'\nimport type { AdminClient } from './client'\nimport { NetworkError } from './errors'\n\nexport interface LoadBootstrapOptions {\n /** Если задан client — fallback на xhr через него. */\n client?: AdminClient\n /** Override URL для xhr. Default: '/system/bootstrap'. */\n xhrUrl?: string\n}\n\n/**\n * Возвращает bootstrap или null если не загрузился.\n *\n * Порядок:\n * 1. window.__ADMIN_BOOTSTRAP__ (inline-strategy).\n * 2. xhr fetch если передан client.\n * 3. null — caller решает что делать (показать error-screen).\n */\nexport async function loadBootstrap(\n opts: LoadBootstrapOptions = {},\n): Promise<AdminBootstrap | null> {\n const inline = readInlineBootstrap()\n if (inline) {\n return inline\n }\n\n if (opts.client) {\n try {\n const url = opts.xhrUrl ?? '/system/bootstrap'\n return await opts.client.get<AdminBootstrap>(url)\n } catch (err) {\n if (err instanceof NetworkError) {\n // Network failure — caller должен показать offline-screen.\n return null\n }\n throw err\n }\n }\n\n return null\n}\n\n/**\n * Прочитать bootstrap из window — только в браузерном контексте.\n */\nexport function readInlineBootstrap(): AdminBootstrap | null {\n if (typeof window === 'undefined') return null\n return window.__ADMIN_BOOTSTRAP__ ?? null\n}\n\n/**\n * Прочитать CSRF-token из meta-tag (Blade-injection через `csrf_token()`).\n *\n * Используется как fallback если bootstrap.csrf отсутствует.\n */\nexport function readCsrfFromMeta(): string | null {\n if (typeof document === 'undefined') return null\n const meta = document.querySelector('meta[name=\"csrf-token\"]')\n return meta?.getAttribute('content') ?? null\n}\n","<script setup lang=\"ts\">\n/**\n * NotificationsDrawer — UidDrawer (right, 400px) с tabs (Все/Непрочитанные/\n * Прочитанные) и списком notification-items.\n *\n * Эталон handoff'а (screens-secondary.jsx → NotificationDrawer):\n * - Header: «Уведомления (3)» + actions (Прочитать все)\n * - Tabs: counts, активный tab подсвечен accent\n * - Item: kind-coloured icon (info/success/warning/error) +\n * title (bold если unread) + body + relative timestamp;\n * unread items имеют tinted background + dot слева\n * - Click на item → переход на data.url + auto markAsRead\n * - Hover показывает кнопку '×' (destroy)\n */\nimport { computed, watch } from 'vue'\nimport { UidButton, UidDrawer, UidTabs, UidTab, UidTabPanel } from '@dskripchenko/ui'\nimport { useNotificationsStore, type NotificationFilter, type NotificationItem } from '../../stores/notifications'\n\ninterface Props {\n /** v-model:open. */\n open: boolean\n}\n\nconst props = defineProps<Props>()\nconst emit = defineEmits<{\n 'update:open': [value: boolean]\n /** Click on notification item — host обрабатывает navigation на data.url. */\n 'select-item': [item: NotificationItem]\n}>()\n\nconst notifications = useNotificationsStore()\n\nfunction setOpen(v: boolean): void {\n emit('update:open', v)\n}\n\n// Загружаем при открытии.\nwatch(\n () => props.open,\n async (next) => {\n if (next) {\n await notifications.load(notifications.lastFilter ?? 'all', 1).catch(() => undefined)\n }\n },\n { immediate: true },\n)\n\nconst activeFilter = computed<NotificationFilter>(() => notifications.lastFilter ?? 'all')\n\nasync function setFilter(filter: NotificationFilter | string | number): Promise<void> {\n await notifications\n .load(filter as NotificationFilter, 1)\n .catch(() => undefined)\n}\n\nasync function markAllRead(): Promise<void> {\n await notifications.markAllAsRead().catch(() => undefined)\n}\n\nasync function onItemClick(item: NotificationItem): Promise<void> {\n emit('select-item', item)\n if (!item.read_at) {\n await notifications.markAsRead(item.id).catch(() => undefined)\n }\n}\n\nasync function onDestroy(item: NotificationItem, event: Event): Promise<void> {\n event.stopPropagation()\n await notifications.destroy(item.id).catch(() => undefined)\n}\n\nfunction itemKind(item: NotificationItem): 'info' | 'success' | 'warning' | 'danger' {\n const lvl = item.data.level\n if (lvl === 'success' || lvl === 'warning' || lvl === 'danger') return lvl\n return 'info'\n}\n\nfunction itemTitle(item: NotificationItem): string {\n return (item.data.title as string | undefined) ?? '—'\n}\n\nfunction itemBody(item: NotificationItem): string {\n return (item.data.body as string | undefined) ?? ''\n}\n\nfunction relTime(iso: string | null): string {\n if (!iso) return ''\n const dt = new Date(iso)\n const diff = Math.max(0, Date.now() - dt.getTime())\n const mins = Math.floor(diff / 60000)\n if (mins < 1) return 'только что'\n if (mins < 60) return `${mins} мин назад`\n const hours = Math.floor(mins / 60)\n if (hours < 24) return `${hours} ч назад`\n const days = Math.floor(hours / 24)\n if (days < 7) return `${days} д назад`\n return dt.toLocaleDateString('ru-RU')\n}\n</script>\n\n<template>\n <UidDrawer\n :model-value=\"open\"\n side=\"right\"\n width=\"400px\"\n title=\"Уведомления\"\n @update:model-value=\"setOpen\"\n >\n <template #header>\n <div class=\"admin-notifs__hd\">\n <h2 class=\"admin-notifs__title\">\n Уведомления\n <span v-if=\"notifications.unreadCount > 0\" class=\"admin-notifs__count\">\n ({{ notifications.unreadCount }})\n </span>\n </h2>\n <UidButton\n v-if=\"notifications.unreadCount > 0\"\n variant=\"ghost\"\n size=\"sm\"\n @click=\"markAllRead\"\n >\n Прочитать все\n </UidButton>\n </div>\n </template>\n\n <UidTabs :model-value=\"activeFilter\" @update:model-value=\"setFilter\">\n <template #list>\n <UidTab value=\"all\">Все</UidTab>\n <UidTab value=\"unread\">\n Непрочитанные<template v-if=\"notifications.unreadCount > 0\">\n ({{ notifications.unreadCount }})\n </template>\n </UidTab>\n <UidTab value=\"read\">Прочитанные</UidTab>\n </template>\n\n <UidTabPanel v-for=\"filter in (['all','unread','read'] as const)\" :key=\"filter\" :value=\"filter\">\n <ul class=\"admin-notifs__list\">\n <li v-if=\"notifications.loading\" class=\"admin-notifs__empty\">\n Загрузка…\n </li>\n <li v-else-if=\"notifications.items.length === 0\" class=\"admin-notifs__empty\">\n Нет уведомлений\n </li>\n <li\n v-for=\"item in notifications.items\"\n :key=\"item.id\"\n :class=\"[\n 'admin-notifs__item',\n `admin-notifs__item--${itemKind(item)}`,\n { 'admin-notifs__item--unread': !item.read_at },\n ]\"\n @click=\"onItemClick(item)\"\n >\n <span class=\"admin-notifs__icon\" :data-kind=\"itemKind(item)\" />\n <div class=\"admin-notifs__body\">\n <div class=\"admin-notifs__row1\">\n <strong v-if=\"!item.read_at\" class=\"admin-notifs__title-strong\">\n {{ itemTitle(item) }}\n </strong>\n <span v-else class=\"admin-notifs__title-soft\">{{ itemTitle(item) }}</span>\n <span class=\"admin-notifs__time\">{{ relTime(item.created_at) }}</span>\n </div>\n <p v-if=\"itemBody(item)\" class=\"admin-notifs__text\">{{ itemBody(item) }}</p>\n </div>\n <button\n type=\"button\"\n class=\"admin-notifs__close\"\n :aria-label=\"'Удалить'\"\n @click=\"onDestroy(item, $event)\"\n >\n ×\n </button>\n </li>\n </ul>\n </UidTabPanel>\n </UidTabs>\n </UidDrawer>\n</template>\n\n<style>\n.admin-notifs__hd {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--uid-space-sm);\n}\n.admin-notifs__title {\n margin: 0;\n font-size: var(--uid-font-size-md);\n font-weight: var(--uid-font-weight-semibold);\n}\n.admin-notifs__count {\n color: var(--uid-text-tertiary);\n font-weight: var(--uid-font-weight-regular);\n font-size: var(--uid-font-size-sm);\n}\n\n.admin-notifs__list {\n list-style: none;\n margin: 0;\n padding: 0;\n}\n.admin-notifs__empty {\n padding: var(--uid-space-xl) var(--uid-space-md);\n text-align: center;\n color: var(--uid-text-tertiary);\n font-size: var(--uid-font-size-sm);\n}\n.admin-notifs__item {\n position: relative;\n display: flex;\n gap: var(--uid-space-sm);\n padding: var(--uid-space-sm) var(--uid-space-md);\n cursor: pointer;\n border-bottom: 1px solid var(--uid-border-subtle);\n}\n.admin-notifs__item:hover { background: var(--uid-surface-hover); }\n.admin-notifs__item--unread {\n background: color-mix(in srgb, var(--uid-accent) 6%, transparent);\n}\n.admin-notifs__item--unread:hover {\n background: color-mix(in srgb, var(--uid-accent) 10%, transparent);\n}\n\n.admin-notifs__icon {\n width: 28px;\n height: 28px;\n border-radius: var(--uid-radius-md);\n flex: none;\n margin-top: 2px;\n}\n.admin-notifs__icon[data-kind='info'] {\n background: color-mix(in srgb, var(--uid-info) 14%, transparent);\n}\n.admin-notifs__icon[data-kind='success'] {\n background: color-mix(in srgb, var(--uid-success) 14%, transparent);\n}\n.admin-notifs__icon[data-kind='warning'] {\n background: color-mix(in srgb, var(--uid-warning) 14%, transparent);\n}\n.admin-notifs__icon[data-kind='danger'] {\n background: color-mix(in srgb, var(--uid-danger) 14%, transparent);\n}\n\n.admin-notifs__body { flex: 1; min-width: 0; }\n.admin-notifs__row1 {\n display: flex;\n align-items: baseline;\n gap: var(--uid-space-sm);\n margin-bottom: 2px;\n}\n.admin-notifs__title-strong {\n font-size: var(--uid-font-size-sm);\n font-weight: var(--uid-font-weight-semibold);\n color: var(--uid-text-primary);\n flex: 1;\n min-width: 0;\n}\n.admin-notifs__title-soft {\n font-size: var(--uid-font-size-sm);\n color: var(--uid-text-primary);\n flex: 1;\n min-width: 0;\n}\n.admin-notifs__time {\n font-size: 11px;\n color: var(--uid-text-tertiary);\n flex: none;\n font-variant-numeric: tabular-nums;\n}\n.admin-notifs__text {\n margin: 0;\n font-size: var(--uid-font-size-xs);\n color: var(--uid-text-secondary);\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n.admin-notifs__close {\n position: absolute;\n top: 6px;\n right: 8px;\n appearance: none;\n border: 0;\n background: transparent;\n color: var(--uid-text-tertiary);\n cursor: pointer;\n font-size: 18px;\n width: 22px;\n height: 22px;\n border-radius: var(--uid-radius-sm);\n opacity: 0;\n transition: opacity var(--uid-duration-fast, 100ms);\n}\n.admin-notifs__item:hover .admin-notifs__close { opacity: 1; }\n.admin-notifs__close:hover {\n background: var(--uid-surface-hover);\n color: var(--uid-text-primary);\n}\n</style>\n","<script setup lang=\"ts\">\n/**\n * ImportWizardPage — 4-step wizard для импорта данных в Resource.\n *\n * Эталон: docs/design_handoff_laravel_admin/screens-secondary.jsx (ImportWizard).\n *\n * Шаги:\n * 1. Загрузка файла — UidFileUpload (CSV/TSV/XLSX)\n * 2. Сопоставление колонок — header'ы файла → field-name'ы ресурса\n * 3. Предпросмотр — таблица первых N строк с warning'ами\n * 4. Импорт — progress-bar + KPI (created/updated/errors)\n *\n * Library предоставляет каркас + state. Конкретные API-вызовы (analyze\n * uploaded file → headers/sample, mapping submit → preview, run import →\n * progress events) — host реализует через emit'ы.\n */\nimport { computed, ref } from 'vue'\nimport {\n UidAlert,\n UidButton,\n UidCard,\n UidFileUpload,\n UidProgress,\n UidSelect,\n UidStat,\n UidStepper,\n UidTable,\n type UidTableColumn,\n} from '@dskripchenko/ui'\n\ninterface ColumnHeader {\n key: string\n label: string\n sample?: string\n}\n\ninterface Mapping {\n /** Header из файла. */\n source: string\n /** Field-name в ресурсе либо null = пропустить. */\n target: string | null\n}\n\ninterface PreviewRow extends Record<string, unknown> {\n __warning?: string | null\n}\n\ninterface ImportProgress {\n created: number\n updated: number\n errors: number\n total: number\n}\n\ninterface Props {\n /** Заголовок страницы. */\n title?: string\n /** Опции для select'а target field'а на step 2. */\n fieldOptions: Array<{ value: string; label: string }>\n /** Headers + sample из uploaded file (host передаёт после step 1). */\n headers?: ColumnHeader[]\n /** Preview rows с warning'ами (host передаёт после step 2 submit). */\n preview?: PreviewRow[]\n /** Preview-table columns (host передаёт). */\n previewColumns?: UidTableColumn[]\n /** Финальная сводка импорта. */\n progress?: ImportProgress | null\n /** Внешне controlled-mode current step (опц.). */\n step?: number\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n title: 'Импорт',\n headers: () => [],\n preview: () => [],\n previewColumns: () => [],\n progress: null,\n step: undefined,\n})\n\nconst emit = defineEmits<{\n /** Файл загружен — host анализирует, отдаёт headers через v-bind. */\n 'file-uploaded': [file: File]\n /** Mapping submit — host генерирует preview. */\n 'mapping-submit': [mapping: Mapping[]]\n /** Run import — host выполняет с реальной записью. */\n 'run-import': []\n /** Cancel wizard. */\n cancel: []\n}>()\n\nconst STEPS = [\n { label: 'Загрузка', description: 'CSV / TSV / XLSX' },\n { label: 'Сопоставление', description: 'Колонки файла → поля' },\n { label: 'Предпросмотр', description: 'Проверка первых строк' },\n { label: 'Импорт', description: 'Запуск + сводка' },\n]\n\nconst internalStep = ref(0)\nconst currentStep = computed(() => props.step ?? internalStep.value)\n\nfunction setStep(idx: number): void {\n if (props.step !== undefined) return // controlled mode — host сам сдвигает\n if (idx < 0 || idx >= STEPS.length) return\n internalStep.value = idx\n}\n\n// Step 1: file upload\nconst uploadedFiles = ref<Array<{ file: File; id: string }>>([])\nfunction onUpload(files: Array<{ file: File; id: string }>): void {\n uploadedFiles.value = files\n if (files.length > 0) {\n emit('file-uploaded', files[0].file)\n }\n}\n\n// Step 2: mapping\nconst mapping = ref<Record<string, string | null>>({})\n\nfunction setTarget(source: string, value: string | number | null): void {\n mapping.value[source] = value === null || value === '' ? null : String(value)\n}\n\nfunction buildMapping(): Mapping[] {\n return props.headers.map((h) => ({\n source: h.key,\n target: mapping.value[h.key] ?? null,\n }))\n}\n\nfunction onMappingSubmit(): void {\n emit('mapping-submit', buildMapping())\n setStep(2)\n}\n\n// Step 3 → 4\nfunction onConfirmRun(): void {\n emit('run-import')\n setStep(3)\n}\n\n// Кнопки навигации\nconst canGoBack = computed(() => currentStep.value > 0)\nconst canGoNext = computed(() => {\n switch (currentStep.value) {\n case 0: return uploadedFiles.value.length > 0\n case 1: return Object.values(mapping.value).some((v) => v !== null)\n case 2: return true\n default: return false\n }\n})\n\nconst fileOptions = computed<Array<{ value: string; label: string }>>(() => {\n return [\n { value: '', label: 'Не импортировать' },\n ...props.fieldOptions,\n ]\n})\n\nfunction onCancel(): void {\n emit('cancel')\n}\n</script>\n\n<template>\n <section class=\"admin-page admin-import-wizard\">\n <header class=\"admin-page__hd\">\n <div class=\"admin-page__title-wrap\">\n <h1 class=\"admin-page__title\">{{ title }}</h1>\n </div>\n <div class=\"admin-page__actions\">\n <UidButton variant=\"ghost\" @click=\"onCancel\">Отмена</UidButton>\n </div>\n </header>\n\n <UidStepper :steps=\"STEPS\" :current=\"currentStep\" />\n\n <!-- Step 1: Upload -->\n <UidCard v-if=\"currentStep === 0\" padding=\"md\" class=\"admin-import-wizard__card\">\n <header class=\"admin-import-wizard__card-hd\">\n <h3>1. Загрузите файл</h3>\n <p>CSV / TSV / XLSX, до 50 MB</p>\n </header>\n <UidFileUpload\n :model-value=\"uploadedFiles\"\n accept=\".csv,.tsv,.xlsx\"\n :max-size=\"50 * 1024 * 1024\"\n :max-files=\"1\"\n primary-text=\"Перетащите файл сюда или\"\n secondary-text=\"нажмите чтобы выбрать\"\n @update:model-value=\"onUpload\"\n />\n </UidCard>\n\n <!-- Step 2: Mapping -->\n <UidCard v-else-if=\"currentStep === 1\" padding=\"md\" class=\"admin-import-wizard__card\">\n <header class=\"admin-import-wizard__card-hd\">\n <h3>2. Сопоставьте колонки</h3>\n <p>Выберите поле ресурса для каждой колонки файла</p>\n </header>\n\n <div v-if=\"headers.length === 0\" class=\"admin-import-wizard__empty\">\n Нет данных — host ещё не отдал headers. Загрузите файл сначала.\n </div>\n\n <div v-else class=\"admin-import-wizard__mapping\">\n <div v-for=\"h in headers\" :key=\"h.key\" class=\"admin-import-wizard__map-row\">\n <div class=\"admin-import-wizard__map-source\">\n <strong>{{ h.label }}</strong>\n <span v-if=\"h.sample\" class=\"admin-import-wizard__map-sample\">\n «{{ h.sample }}»\n </span>\n </div>\n <span class=\"admin-import-wizard__map-arrow\">→</span>\n <UidSelect\n :model-value=\"mapping[h.key] ?? ''\"\n :options=\"fileOptions\"\n placeholder=\"Не импортировать\"\n @update:model-value=\"(v) => setTarget(h.key, v)\"\n />\n </div>\n </div>\n </UidCard>\n\n <!-- Step 3: Preview -->\n <UidCard v-else-if=\"currentStep === 2\" padding=\"md\" class=\"admin-import-wizard__card\">\n <header class=\"admin-import-wizard__card-hd\">\n <h3>3. Предпросмотр</h3>\n <p>Первые {{ preview.length }} строк перед импортом</p>\n </header>\n\n <UidAlert\n v-if=\"preview.some((r) => r.__warning)\"\n variant=\"warning\"\n style=\"margin-bottom: var(--uid-space-md);\"\n >\n Часть строк имеет предупреждения — проверьте перед импортом.\n </UidAlert>\n\n <UidTable\n v-if=\"previewColumns.length > 0\"\n :columns=\"previewColumns\"\n :data=\"preview\"\n />\n <div v-else class=\"admin-import-wizard__empty\">\n Host не передал previewColumns/preview.\n </div>\n </UidCard>\n\n <!-- Step 4: Run + Summary -->\n <UidCard v-else padding=\"md\" class=\"admin-import-wizard__card\">\n <header class=\"admin-import-wizard__card-hd\">\n <h3>4. Импорт</h3>\n </header>\n\n <div v-if=\"!progress\" class=\"admin-import-wizard__empty\">\n Запускается импорт…\n </div>\n <template v-else>\n <UidProgress\n v-if=\"progress.total > 0\"\n :model-value=\"progress.created + progress.updated + progress.errors\"\n :max=\"progress.total\"\n />\n <div class=\"admin-import-wizard__kpi\">\n <UidStat title=\"Создано\" :value=\"progress.created\" tone=\"success\" />\n <UidStat title=\"Обновлено\" :value=\"progress.updated\" tone=\"info\" />\n <UidStat title=\"Ошибки\" :value=\"progress.errors\" tone=\"danger\" />\n </div>\n </template>\n </UidCard>\n\n <!-- Navigation buttons -->\n <footer class=\"admin-import-wizard__nav\">\n <UidButton\n v-if=\"canGoBack\"\n variant=\"ghost\"\n @click=\"setStep(currentStep - 1)\"\n >\n Назад\n </UidButton>\n <span style=\"flex:1\" />\n <UidButton\n v-if=\"currentStep === 0\"\n variant=\"primary\"\n :disabled=\"!canGoNext\"\n @click=\"setStep(1)\"\n >\n Далее\n </UidButton>\n <UidButton\n v-else-if=\"currentStep === 1\"\n variant=\"primary\"\n :disabled=\"!canGoNext\"\n @click=\"onMappingSubmit\"\n >\n Подтвердить mapping\n </UidButton>\n <UidButton\n v-else-if=\"currentStep === 2\"\n variant=\"primary\"\n @click=\"onConfirmRun\"\n >\n Запустить импорт\n </UidButton>\n </footer>\n </section>\n</template>\n\n<style>\n.admin-import-wizard {\n max-width: 1100px;\n margin: 0 auto;\n}\n.admin-import-wizard__card {\n margin-top: var(--uid-space-md);\n}\n.admin-import-wizard__card-hd {\n margin-bottom: var(--uid-space-md);\n}\n.admin-import-wizard__card-hd h3 {\n margin: 0 0 var(--uid-space-2xs);\n font-size: var(--uid-font-size-md);\n font-weight: var(--uid-font-weight-semibold);\n}\n.admin-import-wizard__card-hd p {\n margin: 0;\n font-size: var(--uid-font-size-xs);\n color: var(--uid-text-tertiary);\n}\n.admin-import-wizard__empty {\n padding: var(--uid-space-md);\n text-align: center;\n color: var(--uid-text-tertiary);\n font-size: var(--uid-font-size-sm);\n}\n.admin-import-wizard__mapping {\n display: flex;\n flex-direction: column;\n gap: var(--uid-space-sm);\n}\n.admin-import-wizard__map-row {\n display: grid;\n grid-template-columns: 1fr auto 1fr;\n gap: var(--uid-space-md);\n align-items: center;\n}\n.admin-import-wizard__map-source {\n display: flex;\n align-items: center;\n gap: var(--uid-space-sm);\n}\n.admin-import-wizard__map-sample {\n color: var(--uid-text-tertiary);\n font-size: var(--uid-font-size-xs);\n font-style: italic;\n}\n.admin-import-wizard__map-arrow {\n color: var(--uid-text-tertiary);\n font-size: var(--uid-font-size-md);\n}\n.admin-import-wizard__kpi {\n display: grid;\n grid-template-columns: repeat(3, minmax(0, 1fr));\n gap: var(--uid-space-md);\n margin-top: var(--uid-space-md);\n}\n.admin-import-wizard__nav {\n display: flex;\n align-items: center;\n gap: var(--uid-space-sm);\n margin-top: var(--uid-space-md);\n}\n</style>\n","<script setup lang=\"ts\">\n/**\n * FieldGalleryPage — каталог field-компонентов.\n *\n * Эталон: docs/design_handoff_laravel_admin/screens-secondary.jsx (FieldGallery).\n *\n * 3-col grid из demo-cards. Каждая card:\n * - Group label (например \"Текстовые\")\n * - Тип поля (json type-key)\n * - Демо-компонент с sample-данными\n * - Краткое описание\n *\n * Используется как:\n * 1. Тестовая площадка для devs (визуально все Uid* fields на одной странице)\n * 2. Docs / referencer для host'ов\n *\n * Все секции рендерятся через FieldRenderer + provideFormState с локальной\n * state-mock'ой.\n */\nimport { reactive } from 'vue'\nimport { UidCard } from '@dskripchenko/ui'\nimport FieldRenderer, { type FieldNode } from '../render/FieldRenderer.vue'\nimport { provideFormState } from '../render/formState'\n\ninterface Demo {\n type: string\n group: string\n title: string\n description: string\n /** Demo node для FieldRenderer'а. */\n node: FieldNode\n /** Initial state для form-context. */\n initial: Record<string, unknown>\n}\n\nconst DEMOS: Demo[] = [\n // Текстовые\n {\n type: 'text',\n group: 'Текстовые',\n title: 'Input',\n description: 'Простой текстовый input. type=email/url/password/tel доступны через inputType.',\n node: { type: 'text', name: 'demo_text', label: 'Заголовок статьи', placeholder: 'Например: Введение в Laravel' },\n initial: { demo_text: 'Hello World' },\n },\n {\n type: 'textarea',\n group: 'Текстовые',\n title: 'Textarea',\n description: 'Многострочный input с настраиваемым числом rows.',\n node: { type: 'textarea', name: 'demo_textarea', label: 'Описание', rows: 4 },\n initial: { demo_textarea: 'Multi-line text...' },\n },\n {\n type: 'number',\n group: 'Текстовые',\n title: 'NumberInput',\n description: 'Числовой input. Empty/NaN автоматически конвертируются в null.',\n node: { type: 'number', name: 'demo_number', label: 'Цена', min: 0, max: 1000 },\n initial: { demo_number: 42 },\n },\n // Выбор\n {\n type: 'select',\n group: 'Выбор',\n title: 'Select',\n description: 'Single-select с options. Поддерживает searchable + clearable.',\n node: {\n type: 'select',\n name: 'demo_select',\n label: 'Категория',\n options: [\n { value: 'frontend', label: 'Frontend' },\n { value: 'backend', label: 'Backend' },\n { value: 'devops', label: 'DevOps' },\n ],\n },\n initial: { demo_select: 'backend' },\n },\n {\n type: 'checkbox',\n group: 'Выбор',\n title: 'Checkbox',\n description: 'Boolean toggle. inlineLabel рядом с боксом.',\n node: { type: 'checkbox', name: 'demo_checkbox', label: 'Опубликовать', inlineLabel: 'Сделать доступным всем' },\n initial: { demo_checkbox: true },\n },\n // Дата/время\n {\n type: 'date',\n group: 'Дата/время',\n title: 'DatePicker',\n description: 'date / datetime-local / time через inputType.',\n node: { type: 'date', name: 'demo_date', label: 'Дата публикации', inputType: 'date' },\n initial: { demo_date: '2026-05-01' },\n },\n]\n\n// Группируем для рендера.\nconst groupedDemos = DEMOS.reduce<Record<string, Demo[]>>((acc, d) => {\n if (!acc[d.group]) acc[d.group] = []\n acc[d.group].push(d)\n return acc\n}, {})\n\n// provideFormState на корневом уровне — все demo'и шарят один form-context\n// (имена не пересекаются благодаря demo_ префиксу).\nconst allInitial = reactive<Record<string, unknown>>(\n DEMOS.reduce<Record<string, unknown>>((acc, d) => Object.assign(acc, d.initial), {}),\n)\nprovideFormState(allInitial)\n</script>\n\n<template>\n <section class=\"admin-page admin-field-gallery\">\n <header class=\"admin-page__hd\">\n <div class=\"admin-page__title-wrap\">\n <h1 class=\"admin-page__title\">Field Gallery</h1>\n <div class=\"admin-page__count\">\n Каталог встроенных field-компонентов library + примеры использования\n </div>\n </div>\n </header>\n\n <section v-for=\"(items, group) in groupedDemos\" :key=\"group\" class=\"admin-gallery__group\">\n <h2 class=\"admin-gallery__group-title\">{{ group }}</h2>\n <div class=\"admin-gallery__grid\">\n <UidCard\n v-for=\"demo in items\"\n :key=\"demo.type + demo.title\"\n padding=\"md\"\n class=\"admin-gallery__card\"\n >\n <header class=\"admin-gallery__card-hd\">\n <h3 class=\"admin-gallery__card-title\">{{ demo.title }}</h3>\n <code class=\"admin-gallery__card-type\">type: {{ demo.type }}</code>\n </header>\n <p class=\"admin-gallery__card-desc\">{{ demo.description }}</p>\n <div class=\"admin-gallery__card-demo\">\n <FieldRenderer :node=\"demo.node\" />\n </div>\n </UidCard>\n </div>\n </section>\n </section>\n</template>\n\n<style>\n.admin-gallery__group {\n margin-bottom: var(--uid-space-2xl);\n}\n.admin-gallery__group-title {\n margin: 0 0 var(--uid-space-md);\n font-size: var(--uid-font-size-lg);\n font-weight: var(--uid-font-weight-semibold);\n color: var(--uid-text-primary);\n}\n.admin-gallery__grid {\n display: grid;\n grid-template-columns: repeat(3, minmax(0, 1fr));\n gap: var(--uid-space-md);\n}\n@media (max-width: 960px) {\n .admin-gallery__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }\n}\n@media (max-width: 640px) {\n .admin-gallery__grid { grid-template-columns: 1fr; }\n}\n.admin-gallery__card {\n display: flex;\n flex-direction: column;\n}\n.admin-gallery__card-hd {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--uid-space-sm);\n margin-bottom: var(--uid-space-xs);\n}\n.admin-gallery__card-title {\n margin: 0;\n font-size: var(--uid-font-size-sm);\n font-weight: var(--uid-font-weight-semibold);\n}\n.admin-gallery__card-type {\n font-family: var(--uid-font-family-mono);\n font-size: 11px;\n color: var(--uid-text-tertiary);\n background: var(--uid-surface-base);\n padding: 1px 6px;\n border-radius: var(--uid-radius-sm);\n border: 1px solid var(--uid-border-subtle);\n}\n.admin-gallery__card-desc {\n margin: 0 0 var(--uid-space-md);\n font-size: var(--uid-font-size-xs);\n color: var(--uid-text-tertiary);\n line-height: var(--uid-line-height-normal);\n}\n.admin-gallery__card-demo {\n flex: 1;\n display: flex;\n flex-direction: column;\n justify-content: flex-end;\n}\n</style>\n"],"names":["toKebabCase","string","defaultAttributes","Icon","size","strokeWidth","absoluteStrokeWidth","color","iconNode","name","classes","props","slots","h","child","createLucideIcon","iconName","Activity","Archive","ArrowLeft","Bell","Bookmark","Box","Briefcase","Calendar","ChartColumn","ChartLine","ChartPie","Check","ChevronDown","CircleAlert","CircleCheckBig","CircleHelp","CircleUser","CircleX","Clock","Code","Cog","Columns2","Command","Database","Download","Ellipsis","Eye","FileClock","FileText","Files","Flag","FolderOpen","Folder","Gauge","Globe","Grid3x3","GripVertical","HardDrive","Hash","Heart","History","House","Image","Images","Inbox","Info","Key","Layers","LayoutDashboard","LayoutGrid","LifeBuoy","Link","ListChecks","List","Lock","LogOut","Mail","MapPin","Map","MessageSquare","Monitor","Moon","Package","PanelLeft","PanelsTopLeft","Paperclip","Pencil","Plus","RefreshCw","RotateCcw","Search","Send","Server","Settings","Shield","ShoppingBag","ShoppingCart","SlidersVertical","SquarePen","Star","Store","Sun","Tag","Tags","Terminal","Trash2","TrendingUp","TriangleAlert","Upload","UserPlus","User","Users","X","Zap","_client","setAdminClient","client","getAdminClient","clearAdminClient","hasAdminClient","useThemeStore","defineStore","current","ref","available","isDark","computed","hydrate","bootstrap","applyHtmlAttr","applyLocal","theme","setTheme","previous","err","icon","ariaLabel","toggle","next","_createElementBlock","_createVNode","_unref","UidIcon","useLocaleStore","applySideEffects","locale","setLocale","pick","loc","_createBlock","UidMenu","_createElementVNode","_hoisted_1","_toDisplayString","_openBlock","_Fragment","_renderList","UidMenuItem","$event","_createTextVNode","useNotificationsStore","items","unreadCount","loading","lastFilter","meta","isOpen","hasUnread","openDrawer","closeDrawer","toggleDrawer","load","filter","page","result","loadUnread","markAsRead","id","item","n","markAllAsRead","now","destroy","index","wasUnread","notifications","display","onClick","_hoisted_2","ApiError","status","payload","UnauthenticatedError","ForbiddenError","NotFoundError","ValidationError","messages","NetworkError","message","toApiError","useAuthStore","user","permissions","pendingChallenge","isAuthenticated","isChallengePending","hasPermission","key","permission","prefix","hasAnyPermission","keys","hasAllPermissions","login","challengeToken","twoFactorChallenge","code","twoFactorRecovery","recoveryCode","cancelChallenge","logout","auth","router","useRouter","goProfile","UidAvatar","_cache","UidMenuSeparator","__props","emit","__emit","lastIdx","_renderSlot","_ctx","crumb","idx","_hoisted_3","_resolveDynamicComponent","_normalizeClass","_hoisted_4","NotificationBell","ThemeToggle","LocaleSwitcher","UserMenu","useMenuStore","error","isLoaded","visibleItems","it","filteredChildren","c","i","groupedItems","groups","groupKey","group","list","a","b","orderDiff","force","response","setItems","reset","TEAL","INK","radius","fontSize","padX","cursorW","cursorH","cursorGap","bg","fg","wrapStyle","cursorStyle","REGISTRY","AlertCircle","BarChart3","CheckCircle","Grid","HelpCircle","Home","Layout","LineChart","PieChart","Sliders","UserCircle","XCircle","resolveIcon","menu","route","useRoute","isActive","iconSlot","resolved","itemTarget","UidSidebar","_component_router_link","BrandLogo","grp","UidSidebarGroup","UidSidebarItem","_hoisted_6","HTML_ATTR","internalCollapsed","isExternallyControlled","collapsed","onCollapseChange","value","exitImpersonation","watch","val","onBeforeUnmount","UidSidebarLayout","AdminSidebar","AdminTopBar","useNavigationStore","pending","isLoading","start","end","nav","visible","hideTimer","cls","tabs","selectTab","onMarkAll","onItemClick","url","onDelete","e","close","iconFor","t","AlertTriangle","variantFor","relativeTime","iso","ts","diff","viewOf","d","title","description","tabCounts","total","unread","read","open","onKey","onUnmounted","_Teleport","_Transition","_hoisted_5","_hoisted_7","tab","_hoisted_9","_hoisted_10","_hoisted_11","_hoisted_12","_hoisted_13","_hoisted_16","_hoisted_17","_hoisted_18","_hoisted_19","_hoisted_20","_hoisted_21","_withModifiers","useManifestStore","manifest","bootResolved","version","resources","screens","settings","plugins","getResource","slug","r","getScreen","s","getSettings","shorthand","opts","adminToast","useToast","impersonation","u","registry","useShell","suppressNotFound","AdminLoadingBar","AdminShell","_component_router_view","_withCtx","Component","NotificationsDrawer","UidToastProvider","useDashboardStore","editMode","draft","original","saving","isDirty","openDashboard","dashboardSlug","enterEditMode","cancelEdit","saveLayout","widgets","resetToDefault","addWidget","removeWidget","slugKey","updateWidget","patch","moveWidget","fromIdx","toIdx","moved","useI18nStore","setMessages","replace","str","k","v","createComponentRegistry","store","type","bundle","registerWidget","getWidget","hasWidget","listWidgets","clearWidgetRegistry","registerWidgets","UidAlert","component","widgetProps","_type","_span","rest","_normalizeProps","_mergeProps","UnknownWidget","$emit","types","selectedType","markdownContent","statLabel","statValue","gaugeValue","chartLabels","chartValues","recentResource","recentLimit","cfg","firstStat","labels","datasets","canSubmit","labelOf","configKind","buildConfig","base","data","onSubmit","sizeNum","config","UidInput","_hoisted_14","_hoisted_15","_hoisted_22","_hoisted_23","UidButton","dashboardStore","i18n","fallback","dashboard","manifestWidgets","refreshedWidgets","resolvedTitle","resolvedSubtitle","renderedWidgets","bySlug","w","out","node","spanFor","raw","periods","selectedPeriod","setPeriod","refetchPeriod","periodLabel","p","dialogMode","dialogItem","dialogInitialTitle","openAdd","closeDialog","onEnterEdit","onCancelEdit","onSaveLayout","onRemoveWidget","layoutSlug","onConfigureWidget","ensureDraftReflectsRendered","draftItem","onAddWidget","onSaveConfig","existing","dragSourceIdx","onDragStart","onDragOver","onDrop","sourceIdx","resizing","resizeContainerWidth","onResizeStart","currentSpan","onResizeMove","onResizeEnd","colWidth","delta","nextSpan","onExport","_normalizeStyle","WidgetRenderer","WidgetActionsOverlay","WidgetConfigDialog","userName","dashboards","primaryDashboardSlug","DashboardPage","UidCard","email","password","remember","submitting","generalError","fieldErrors","emailError","passwordError","submit","UidCheckbox","mode","cells","cellRefs","remaining","totpCode","isValid","setCellRef","el","onCellInput","event","target","digit","nextTick","onCellKeydown","onPaste","digits","res","cancel","switchMode","_","redirectToHome","onMounted","_hoisted_8","TwoFactorForm","LoginForm","submitted","busy","token","confirm","DEFAULT_META","useResourceIndexStore","slowLoading","slowLoadingTimer","SLOW_LOADING_DELAY","search","filters","sortKey","sortDirection","selection","isEmpty","selectedCount","hasSelection","hasError","selectionState","row","rowId","setSlug","buildParams","override","params","ss","sk","dir","f","filtersMap","body","setSearch","setFilter","clearFilters","setSort","direction","toggleSort","setPage","toggleRow","toggleAllOnPage","clearSelection","isSelected","DEFAULT_DATETIME","DEFAULT_DATE","ISO_DATETIME_RE","formatCell","preset","formatDateString","formatMoney","formatBoolean","formatBytes","input","format","date","pad","tokens","ch","currency","decimals","trueLabel","falseLabel","FilterEditor","defineComponent","opt","options","VISIBLE_LIMIT","localSearch","commitSearch","hasValue","activeFilters","inactiveFilters","revealed","inactiveVisible","inactiveHidden","reveal","hasActiveAnything","clearFilter","chipText","o","draftValues","getDraft","setDraft","applyDraft","toggleOption","multiple","cur","arr","x","isOptionChecked","groupableColumns","setGroupBy","col","colKey","colLabel","isVisible","toggleVisibility","newViewLabel","saveView","_withKeys","Columns","editing","inputRef","startEdit","commit","onKeydown","ACTIONS_KEY","REORDER_KEY","tt","resourceMeta","displayTitle","resolvedCreateRouteName","candidate","headerActions","onCustomAction","action","blob","importInput","onImportClick","onImportFileChange","file","uploadForm","uploaded","preview","started","finalStatus","pollImportStatus","imported","failed","processId","deadline","resolve","isReorderable","columns","mapped","columnVisibility","columnIsEditable","cols","columnMeta","renderCell","slotProps","m","rowFromSlot","hasActiveFilters","showFilterBar","manifestFilters","manifestColumns","searchPlaceholder","groupByCol","onFilterApply","onSearchUpdate","onResetFilters","onGroupBy","onColumnsVisibility","savedViews","activeViewId","loadSavedViews","onApplyView","view","loadWithProgress","onResetView","onDeleteView","onSaveView","label","totalLabel","pluralRecords","mod10","mod100","lastLoadedAt","tick","tickTimer","wasLoading","liveStatus","diffSec","min","hr","scopeLabel","prev","onSortKeyUpdate","onSortDirUpdate","onSelectionUpdate","onPageChange","onRowClick","onView","onEdit","isTrashed","onRestore","dragRowIdx","dragOverRowIdx","dragOverSide","onRowDragStart","onRowDragOver","rect","onRowDragEnd","onRowDrop","adjusted","finalIdx","ids","onForceDelete","bulkAction","retryLoad","MoreHorizontal","$router","AdminFilterToolbar","UidSkeleton","UidErrorState","UidEmptyState","UidTable","InlineEditCell","_hoisted_24","_hoisted_25","_hoisted_26","UidPagination","useResourceFormStore","recordId","state","initial","errors","deleting","isCreate","isEdit","isView","replaceObject","prepareCreate","resourceSlug","defaults","targetMode","setField","setErrors","clearErrors","save","newId","fields","layouts","registerField","getField","hasField","listFields","registerLayout","getLayout","hasLayout","listLayouts","clearRegistry","registerComponents","fieldProps","attributes","UnknownField","layoutComponent","layoutProps","_kind","fieldNode","FieldRenderer","form","ctx","provideFormState","layoutNodes","titleLabel","statusValue","statusBadgeVariant","nextSlug","nextId","onSave","resolvedIndexRouteName","onCancel","UidBadge","LayoutRenderer","entries","registerInfolistEntry","getInfolistEntry","hasInfolistEntry","listInfolistEntries","clearInfolistRegistry","registerInfolistEntries","KNOWN_LAYOUTS","entry","entryProps","_t","_k","_i","attrs","rest2","sectionTitle","sectionDescription","tabsActive","tabsList","_component_InfolistRenderer","UnknownEntry","RecordKey","provideRecord","record","provide","useRecord","inject","tryUseRecord","hasItems","eventIcon","Edit","eventLabel","diffSummary","formatVal","resolvedSubjectType","defaultMetrics","rows","fmt","created","updated","author","recordTitle","indexLabel","uidLabel","STATUS_VARIANT","statusVariant","onBack","InfolistRenderer","AuditTimeline","navItems","localSection","selectSection","profile","localeOptions","l","themeOptions","onAvatarReplace","on2FADisable","on2FARegenerate","has2FA","UidSelect","TONE_MAP","uidTone","UidStat","maxValue","bars","barWidth","bar","PALETTE","slices","cumulative","startAngle","endAngle","cx","cy","x1","y1","x2","y2","largeArc","path","UidHeatmap","UidGauge","chartType","DEFAULT_PALETTE","barData","ds","barAccent","donutData","DonutChartWidget","BarChartWidget","registerBuiltinWidgets","StatWidget","ChartWidget","RecentTableWidget","HeatmapWidget","GaugeWidget","MarkdownWidget","isSuccess","env","isError","createAdminClient","instance","axios","xsrf","readCookie","apiError","wrap","method","wrapBody","match","escapeRegex","pickResourcePermission","resource","ability","perm","pickSettingsPermission","pickScreenPermission","buildResourceRoutes","components","buildScreenRoute","screen","buildSettingsRoute","buildDashboardRoute","buildRoutesFromManifest","routes","createAuthGuard","loginRouteName","forbiddenRouteName","redirectQueryKey","to","permissionsMeta","createTitleGuard","template","brand","DYNAMIC_NAME_PREFIXES","isDynamicRouteName","createAdminRouter","history","createWebHistory","staticRoutes","notFoundRoute","createRouter","allRoutes","dynamic","useFormState","errorMsg","onUpdate","UidFormField","UidTextarea","UidNumberInput","checked","UidDatePicker","tags","query","focused","containerRef","setTags","seen","trimmed","addTag","removeTag","activeIdx","filteredFlat","onInput","parts","grouped","filteredGroups","q","used","g","isItemActive","globalIdx","onContainerClick","onSelectSuggestion","onBlur","tag","gi","localeStore","availableLocales","activeLocale","update","isFilled","UidStack","defaultSpan","UidGrid","tabKey","localActive","UidTabs","UidTab","UidTabPanel","cidx","registerBuiltinComponents","TextField","TextAreaField","NumberField","SelectField","TagsField","TranslatableField","CheckboxField","DateField","RowsLayout","ColumnsLayout","SectionLayout","TabsLayout","formatted","hasLabel","resolvedVariant","flag","displayLabel","formatValue","UidDescriptionList","UidDescriptionItem","registerBuiltinInfolistEntries","TextEntry","BadgeEntry","IconEntry","KeyValueEntry","createAdminApp","pages","deriveBase","app","createApp","AdminApp","pinia","createPinia","LoginPage","HomePage","ForbiddenPage","NotFoundPage","ProfilePage","ForgotPasswordPage","ResetPasswordPage","ResourceIndexPage","ResourceFormPage","ResourceViewPage","SettingsPage","UnknownScreenPage","navStore","from","_from","resourceIndex","indexStore","manifestStore","authStore","menuStore","loadAndApply","newUser","oldUser","baseUrl","loadBootstrap","inline","readInlineBootstrap","readCsrfFromMeta","setOpen","activeFilter","markAllRead","onDestroy","itemKind","lvl","itemTitle","itemBody","relTime","dt","mins","hours","days","UidDrawer","STEPS","internalStep","currentStep","setStep","uploadedFiles","onUpload","files","mapping","setTarget","source","buildMapping","onMappingSubmit","onConfirmRun","canGoBack","canGoNext","fileOptions","UidStepper","UidFileUpload","UidProgress","DEMOS","groupedDemos","acc","allInitial","reactive","demo"],"mappings":"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","x_google_ignoreList":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97]}