@dskripchenko/laravel-admin 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (163) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +226 -0
  3. package/dist/.gitkeep +0 -0
  4. package/dist/api/bootstrap.d.ts +38 -0
  5. package/dist/api/bootstrap.test.d.ts +1 -0
  6. package/dist/api/client.d.ts +30 -0
  7. package/dist/api/client.test.d.ts +1 -0
  8. package/dist/api/envelope.d.ts +24 -0
  9. package/dist/api/envelope.test.d.ts +1 -0
  10. package/dist/api/errors.d.ts +40 -0
  11. package/dist/api/errors.test.d.ts +1 -0
  12. package/dist/components/AdminApp.vue.d.ts +2 -0
  13. package/dist/components/ForbiddenPage.vue.d.ts +2 -0
  14. package/dist/components/HomePage.vue.d.ts +2 -0
  15. package/dist/components/NotFoundPage.vue.d.ts +2 -0
  16. package/dist/components/SettingsPage.vue.d.ts +2 -0
  17. package/dist/components/UnknownScreenPage.vue.d.ts +2 -0
  18. package/dist/components/auth/LoginForm.test.d.ts +1 -0
  19. package/dist/components/auth/LoginForm.vue.d.ts +17 -0
  20. package/dist/components/auth/LoginPage.test.d.ts +1 -0
  21. package/dist/components/auth/LoginPage.vue.d.ts +26 -0
  22. package/dist/components/auth/TwoFactorForm.test.d.ts +1 -0
  23. package/dist/components/auth/TwoFactorForm.vue.d.ts +8 -0
  24. package/dist/components/auth/index.d.ts +6 -0
  25. package/dist/components/createComponentRegistry.d.ts +22 -0
  26. package/dist/components/dashboard/BarChartWidget.vue.d.ts +18 -0
  27. package/dist/components/dashboard/DashboardPage.test.d.ts +1 -0
  28. package/dist/components/dashboard/DashboardPage.vue.d.ts +28 -0
  29. package/dist/components/dashboard/DonutChartWidget.vue.d.ts +13 -0
  30. package/dist/components/dashboard/GaugeWidget.vue.d.ts +29 -0
  31. package/dist/components/dashboard/HeatmapWidget.vue.d.ts +18 -0
  32. package/dist/components/dashboard/MarkdownWidget.vue.d.ts +8 -0
  33. package/dist/components/dashboard/RecentTableWidget.vue.d.ts +12 -0
  34. package/dist/components/dashboard/StatWidget.vue.d.ts +22 -0
  35. package/dist/components/dashboard/UnknownWidget.vue.d.ts +5 -0
  36. package/dist/components/dashboard/WidgetRenderer.vue.d.ts +10 -0
  37. package/dist/components/dashboard/builtin.d.ts +4 -0
  38. package/dist/components/dashboard/index.d.ts +16 -0
  39. package/dist/components/dashboard/registry.d.ts +25 -0
  40. package/dist/components/dashboard/registry.test.d.ts +1 -0
  41. package/dist/components/fields/CheckboxField.vue.d.ts +16 -0
  42. package/dist/components/fields/DateField.vue.d.ts +25 -0
  43. package/dist/components/fields/NumberField.vue.d.ts +24 -0
  44. package/dist/components/fields/SelectField.vue.d.ts +28 -0
  45. package/dist/components/fields/TextAreaField.vue.d.ts +20 -0
  46. package/dist/components/fields/TextField.vue.d.ts +22 -0
  47. package/dist/components/fields/UnknownField.vue.d.ts +6 -0
  48. package/dist/components/fields/fields.test.d.ts +1 -0
  49. package/dist/components/fields/wysiwyg/quill/QuillField.vue.d.ts +26 -0
  50. package/dist/components/fields/wysiwyg/quill/index.d.ts +12 -0
  51. package/dist/components/fields/wysiwyg/tinymce/TinymceField.vue.d.ts +31 -0
  52. package/dist/components/fields/wysiwyg/tinymce/index.d.ts +12 -0
  53. package/dist/components/gallery/FieldGalleryPage.test.d.ts +1 -0
  54. package/dist/components/gallery/FieldGalleryPage.vue.d.ts +2 -0
  55. package/dist/components/gallery/index.d.ts +1 -0
  56. package/dist/components/import/ImportWizardPage.test.d.ts +1 -0
  57. package/dist/components/import/ImportWizardPage.vue.d.ts +59 -0
  58. package/dist/components/import/index.d.ts +1 -0
  59. package/dist/components/infolist/BadgeEntry.vue.d.ts +18 -0
  60. package/dist/components/infolist/IconEntry.vue.d.ts +22 -0
  61. package/dist/components/infolist/InfolistRenderer.test.d.ts +1 -0
  62. package/dist/components/infolist/InfolistRenderer.vue.d.ts +11 -0
  63. package/dist/components/infolist/KeyValueEntry.vue.d.ts +11 -0
  64. package/dist/components/infolist/TextEntry.vue.d.ts +17 -0
  65. package/dist/components/infolist/UnknownEntry.vue.d.ts +6 -0
  66. package/dist/components/infolist/builtin.d.ts +4 -0
  67. package/dist/components/infolist/index.d.ts +13 -0
  68. package/dist/components/infolist/recordContext.d.ts +9 -0
  69. package/dist/components/infolist/registry.d.ts +19 -0
  70. package/dist/components/infolist/registry.test.d.ts +1 -0
  71. package/dist/components/layouts/ColumnsLayout.vue.d.ts +13 -0
  72. package/dist/components/layouts/RowsLayout.vue.d.ts +10 -0
  73. package/dist/components/layouts/SectionLayout.vue.d.ts +11 -0
  74. package/dist/components/layouts/TabsLayout.vue.d.ts +22 -0
  75. package/dist/components/notifications/NotificationsDrawer.test.d.ts +1 -0
  76. package/dist/components/notifications/NotificationsDrawer.vue.d.ts +13 -0
  77. package/dist/components/notifications/index.d.ts +1 -0
  78. package/dist/components/profile/ProfilePage.test.d.ts +1 -0
  79. package/dist/components/profile/ProfilePage.vue.d.ts +50 -0
  80. package/dist/components/profile/index.d.ts +1 -0
  81. package/dist/components/render/FieldRenderer.test.d.ts +1 -0
  82. package/dist/components/render/FieldRenderer.vue.d.ts +9 -0
  83. package/dist/components/render/LayoutRenderer.test.d.ts +1 -0
  84. package/dist/components/render/LayoutRenderer.vue.d.ts +10 -0
  85. package/dist/components/render/builtin.d.ts +9 -0
  86. package/dist/components/render/formState.d.ts +36 -0
  87. package/dist/components/render/formState.test.d.ts +1 -0
  88. package/dist/components/render/index.d.ts +23 -0
  89. package/dist/components/render/registry.d.ts +35 -0
  90. package/dist/components/render/registry.test.d.ts +1 -0
  91. package/dist/components/resource/ResourceFormPage.test.d.ts +1 -0
  92. package/dist/components/resource/ResourceFormPage.vue.d.ts +13 -0
  93. package/dist/components/resource/ResourceIndexPage.test.d.ts +1 -0
  94. package/dist/components/resource/ResourceIndexPage.vue.d.ts +44 -0
  95. package/dist/components/resource/ResourceViewPage.test.d.ts +1 -0
  96. package/dist/components/resource/ResourceViewPage.vue.d.ts +13 -0
  97. package/dist/components/resource/index.d.ts +6 -0
  98. package/dist/components/shell/AdminShell.vue.d.ts +35 -0
  99. package/dist/components/shell/AdminSidebar.test.d.ts +1 -0
  100. package/dist/components/shell/AdminSidebar.vue.d.ts +27 -0
  101. package/dist/components/shell/AdminTopBar.test.d.ts +1 -0
  102. package/dist/components/shell/AdminTopBar.vue.d.ts +33 -0
  103. package/dist/components/shell/index.d.ts +18 -0
  104. package/dist/components/shell/widgets/LocaleSwitcher.test.d.ts +1 -0
  105. package/dist/components/shell/widgets/LocaleSwitcher.vue.d.ts +2 -0
  106. package/dist/components/shell/widgets/NotificationBell.vue.d.ts +2 -0
  107. package/dist/components/shell/widgets/ThemeToggle.test.d.ts +1 -0
  108. package/dist/components/shell/widgets/ThemeToggle.vue.d.ts +2 -0
  109. package/dist/components/shell/widgets/UserMenu.test.d.ts +1 -0
  110. package/dist/components/shell/widgets/UserMenu.vue.d.ts +2 -0
  111. package/dist/createAdminApp.d.ts +85 -0
  112. package/dist/createAdminApp.test.d.ts +1 -0
  113. package/dist/formState-DGNcH1XQ.js +40 -0
  114. package/dist/formState-DGNcH1XQ.js.map +1 -0
  115. package/dist/formState-GlJBphEn.cjs +2 -0
  116. package/dist/formState-GlJBphEn.cjs.map +1 -0
  117. package/dist/index.cjs +2 -0
  118. package/dist/index.cjs.map +1 -0
  119. package/dist/index.d.ts +62 -0
  120. package/dist/index.mjs +4345 -0
  121. package/dist/index.mjs.map +1 -0
  122. package/dist/quill.cjs +2 -0
  123. package/dist/quill.cjs.map +1 -0
  124. package/dist/quill.mjs +71 -0
  125. package/dist/quill.mjs.map +1 -0
  126. package/dist/router/builder.d.ts +52 -0
  127. package/dist/router/builder.test.d.ts +1 -0
  128. package/dist/router/guards.d.ts +56 -0
  129. package/dist/router/guards.test.d.ts +1 -0
  130. package/dist/router/index.d.ts +63 -0
  131. package/dist/router/index.test.d.ts +1 -0
  132. package/dist/stores/auth.d.ts +142 -0
  133. package/dist/stores/auth.test.d.ts +1 -0
  134. package/dist/stores/index.d.ts +21 -0
  135. package/dist/stores/locale.d.ts +29 -0
  136. package/dist/stores/locale.test.d.ts +1 -0
  137. package/dist/stores/manifest.d.ts +515 -0
  138. package/dist/stores/manifest.test.d.ts +1 -0
  139. package/dist/stores/menu.d.ts +215 -0
  140. package/dist/stores/menu.test.d.ts +1 -0
  141. package/dist/stores/notifications.d.ts +137 -0
  142. package/dist/stores/notifications.test.d.ts +1 -0
  143. package/dist/stores/registry.d.ts +16 -0
  144. package/dist/stores/registry.test.d.ts +1 -0
  145. package/dist/stores/resourceForm.d.ts +91 -0
  146. package/dist/stores/resourceForm.test.d.ts +1 -0
  147. package/dist/stores/resourceIndex.d.ts +149 -0
  148. package/dist/stores/resourceIndex.test.d.ts +1 -0
  149. package/dist/stores/theme.d.ts +29 -0
  150. package/dist/stores/theme.test.d.ts +1 -0
  151. package/dist/style.css +1 -0
  152. package/dist/tinymce.cjs +2 -0
  153. package/dist/tinymce.cjs.map +1 -0
  154. package/dist/tinymce.mjs +80 -0
  155. package/dist/tinymce.mjs.map +1 -0
  156. package/dist/types/bootstrap.d.ts +50 -0
  157. package/package.json +162 -0
  158. package/resources/fonts/InterDisplay-Bold.woff2 +0 -0
  159. package/resources/fonts/InterDisplay-ExtraBold.woff2 +0 -0
  160. package/resources/fonts/InterDisplay-SemiBold.woff2 +0 -0
  161. package/resources/fonts/InterVariable-Italic.woff2 +0 -0
  162. package/resources/fonts/InterVariable.woff2 +0 -0
  163. package/resources/fonts/fonts.css +69 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Denis Skripchenko
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,226 @@
1
+ # dskripchenko/laravel-admin
2
+
3
+ Конструктор админок для Laravel: Resource-first CRUD, Vue 3 SPA, JSON-API транспорт. Подключается в любой существующий Laravel-проект без вмешательства в его routes/auth.
4
+
5
+ > **Статус:** in development. Архитектура зафиксирована, идёт реализация. См. `docs/ARCHITECTURE.md`.
6
+
7
+ ## Tldr
8
+
9
+ ```php
10
+ class UserResource extends Resource
11
+ {
12
+ public static string $model = \App\Models\User::class;
13
+ public static string $icon = 'user';
14
+
15
+ public function fields(): array
16
+ {
17
+ return [
18
+ Field\Input::make('name')->required(),
19
+ Field\Input::make('email')->type('email')->required()->unique(),
20
+ Field\Switch::make('is_active'),
21
+ ];
22
+ }
23
+
24
+ public function columns(): array
25
+ {
26
+ return [
27
+ TC::make('id')->sort(),
28
+ TC::make('name')->sort()->search(),
29
+ TC::make('email')->copyable(),
30
+ TC::make('is_active')->as('badge'),
31
+ ];
32
+ }
33
+ }
34
+ ```
35
+
36
+ ```php
37
+ // AppServiceProvider
38
+ Admin::resources([UserResource::class]);
39
+ ```
40
+
41
+ Готово: SPA с list/create/edit/view/audit/permissions.
42
+
43
+ ## Требования
44
+
45
+ - PHP `^8.5`
46
+ - Laravel `^12`
47
+ - Redis или Memcached (для tag-aware кэша переводов; иначе soft-fallback)
48
+ - Vue 3.4+, TypeScript, Vite (для frontend-сборки)
49
+
50
+ ## Установка
51
+
52
+ ```bash
53
+ composer require dskripchenko/laravel-admin
54
+ php artisan admin:install
55
+ php artisan migrate
56
+ php artisan admin:user "Admin" admin@example.com secret
57
+ npm install
58
+ npm run admin:build
59
+ ```
60
+
61
+ После этого админка доступна на `/admin`.
62
+
63
+ ## Frontend SPA (`@dskripchenko/laravel-admin` npm-пакет)
64
+
65
+ Для host-проектов которые хотят встроить SPA в свой Vite-bundle вместо Blade-shell'а либо построить кастомный admin-фронт поверх готовых блоков.
66
+
67
+ ### Установка
68
+
69
+ ```bash
70
+ npm install @dskripchenko/laravel-admin @dskripchenko/ui vue@^3.4 vue-router@^4.3 pinia axios
71
+ ```
72
+
73
+ ### Минимальный entry
74
+
75
+ ```ts
76
+ // resources/admin-spa/main.ts
77
+ import { createApp } from 'vue'
78
+ import { createPinia } from 'pinia'
79
+
80
+ // (1) UI-кит: токены + темы + reset + global + Uid*-стили
81
+ import '@dskripchenko/ui/styles/all.css'
82
+ // (2) admin-каркас (impersonation banner, polling-dot, page utilities)
83
+ import '@dskripchenko/laravel-admin/style.css'
84
+
85
+ import {
86
+ createAdminClient,
87
+ setAdminClient,
88
+ loadBootstrap,
89
+ createAdminRouter,
90
+ registerBuiltinComponents,
91
+ registerBuiltinInfolistEntries,
92
+ registerBuiltinWidgets,
93
+ AdminShell,
94
+ ResourceIndexPage,
95
+ ResourceFormPage,
96
+ ResourceViewPage,
97
+ DashboardPage,
98
+ } from '@dskripchenko/laravel-admin'
99
+
100
+ // 1. HTTP-клиент с envelope/CSRF/error handling
101
+ const client = createAdminClient({
102
+ baseURL: '/api/admin',
103
+ onUnauthenticated: () => router.push({ name: 'admin.login' }),
104
+ })
105
+ setAdminClient(client)
106
+
107
+ // 2. Bootstrap (inline через <script> либо xhr через /system/bootstrap)
108
+ const bootstrap = await loadBootstrap({ client })
109
+
110
+ // 3. Pinia + hydrate stores
111
+ const pinia = createPinia()
112
+ const app = createApp(AdminShell)
113
+ app.use(pinia)
114
+
115
+ // 4. Регистрация builtin-компонентов в JSON-renderer'ы
116
+ registerBuiltinComponents() // Field/Layout (text/textarea/number/select/...)
117
+ registerBuiltinInfolistEntries() // Read-only display (text/badge/icon/keyvalue)
118
+ registerBuiltinWidgets() // Dashboard widgets (stat/charts/heatmap/gauge)
119
+
120
+ // 5. Router с динамическими роутами из manifest'а
121
+ const router = createAdminRouter({
122
+ base: '/admin',
123
+ components: {
124
+ login: () => import('./pages/Login.vue'),
125
+ home: () => import('./pages/Home.vue'),
126
+ forbidden: () => import('./pages/403.vue'),
127
+ notFound: () => import('./pages/404.vue'),
128
+ resourceIndex: ResourceIndexPage,
129
+ resourceCreate: ResourceFormPage,
130
+ resourceEdit: ResourceFormPage,
131
+ screen: () => import('./pages/Screen.vue'),
132
+ settings: () => import('./pages/Settings.vue'),
133
+ dashboard: DashboardPage,
134
+ },
135
+ })
136
+ app.use(router)
137
+ app.mount('#admin')
138
+ ```
139
+
140
+ ### Готовые компоненты-страницы
141
+
142
+ - `LoginPage` + `LoginForm` + `TwoFactorForm` — auth + TOTP/recovery
143
+ - `ResourceIndexPage` — список с filter-bar / bulk toolbar / pagination
144
+ - `ResourceFormPage` — create/edit unified с sticky save-bar
145
+ - `ResourceViewPage` — read-only display через Infolist
146
+ - `DashboardPage` — 12-col widget grid
147
+ - `ProfilePage` — sidebar nav + cards
148
+ - `ImportWizardPage` — 4-step wizard
149
+ - `NotificationsDrawer` — UidDrawer right с tabs
150
+ - `FieldGalleryPage` — каталог field-типов (docs/playground)
151
+
152
+ ### Расширение через registry
153
+
154
+ ```ts
155
+ import { registerField, registerWidget, registerInfolistEntry } from '@dskripchenko/laravel-admin'
156
+ import MyCustomField from './fields/MyCustomField.vue'
157
+
158
+ registerField('my-custom', MyCustomField)
159
+ // теперь manifest узел { type: 'my-custom', name: 'x', ... } рендерится через MyCustomField
160
+ ```
161
+
162
+ ### Шрифты (опционально)
163
+
164
+ UID design system предполагает Inter Variable + Inter Display. Library не bundle'ит шрифты в style.css (Vite lib-mode инлайнит base64 → 1.4 MB). Варианты:
165
+
166
+ - `npm i @fontsource-variable/inter @fontsource/inter-display` + `import` (рекомендуется)
167
+ - Google Fonts CDN
168
+ - Self-hosted — копировать `node_modules/@dskripchenko/laravel-admin/resources/fonts/*.woff2` в `public/fonts/` + подключить `fonts.css`
169
+
170
+ ### Скрипты разработки
171
+
172
+ ```bash
173
+ npm run lint # eslint flat config + vue-eslint-parser
174
+ npm run typecheck # vue-tsc --noEmit
175
+ npm test # vitest (jsdom)
176
+ npm run build # vite build + vue-tsc --emitDeclarationOnly
177
+ npm run build:analyze # с rollup-plugin-visualizer → dist/stats.html
178
+ npm run size # size-limit budgets (ESM/CJS gzipped + CSS)
179
+ npm run preflight # lint + typecheck + test + build (CI gate)
180
+ ```
181
+
182
+ ## Документация
183
+
184
+ - [ARCHITECTURE.md](docs/ARCHITECTURE.md) — архитектура и решения.
185
+ - [docs/sister-packs/](docs/sister-packs/) — спецификации опциональных расширений.
186
+ - [docs/design_handoff_laravel_admin/](docs/design_handoff_laravel_admin/) — UID design handoff (эталон вёрстки SPA).
187
+
188
+ ## Sister-packs
189
+
190
+ | Пакет | Назначение |
191
+ |---|---|
192
+ | `dskripchenko/laravel-admin-starter` | Готовые системные Resource'ы |
193
+ | `dskripchenko/laravel-admin-tinymce` / `*-quill` | Альтернативные WYSIWYG |
194
+ | `dskripchenko/laravel-admin-search` | Глобальный поиск |
195
+ | `dskripchenko/laravel-admin-media` | Медиа-библиотека |
196
+ | `dskripchenko/laravel-admin-health` | Health-checks |
197
+ | `dskripchenko/laravel-admin-pulse` | Лёгкая телеметрия |
198
+ | `dskripchenko/laravel-admin-jobs` | Failed jobs viewer |
199
+
200
+ ## Структура репозитория (dev)
201
+
202
+ На время разработки до первого релиза проект ведётся как **монорепо**:
203
+
204
+ ```
205
+ laravel-admin/
206
+ ├── src/ # основной пакет dskripchenko/laravel-admin
207
+ ├── resources/ts/ # SPA-бандл @dskripchenko/laravel-admin
208
+ ├── packages/ # sister-packs, локально
209
+ │ ├── starter/
210
+ │ ├── tinymce/
211
+ │ ├── quill/
212
+ │ ├── search/
213
+ │ ├── media/
214
+ │ ├── health/
215
+ │ ├── pulse/
216
+ │ └── jobs/
217
+ └── docs/
218
+ ```
219
+
220
+ - Composer: корневой `composer.json` содержит `repositories: [{ type: path, url: packages/* }]` — sister-packs резолвятся локально через симлинки. Это позволяет менять core и sister-packs одновременно без публикации dev-версий.
221
+ - NPM: workspaces для `packages/tinymce` и `packages/quill` (только им нужны npm-зависимости). `npm install` из корня устанавливает зависимости всем сразу.
222
+ - **Перед первым стабильным релизом** sister-packs выносятся в отдельные репозитории на github.com/dskripchenko и публикуются на packagist/npm независимо. На этот момент `repositories` в корневом `composer.json` удаляются, sister-packs ставятся обычным `composer require`.
223
+
224
+ ## License
225
+
226
+ MIT. См. [LICENSE](LICENSE).
package/dist/.gitkeep ADDED
File without changes
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Загрузка bootstrap-payload'а в SPA.
3
+ *
4
+ * Поддерживает обе стратегии:
5
+ * - 'inline' — читает window.__ADMIN_BOOTSTRAP__ (инжект через
6
+ * shell.blade при strategy=inline).
7
+ * - 'xhr' — fetch'ит /api/admin/system/bootstrap.
8
+ *
9
+ * Если оба способа не дали результата — throw'ит. SPA должна это поймать
10
+ * и показать full-screen error.
11
+ */
12
+ import type { AdminBootstrap } from '../types/bootstrap';
13
+ import type { AdminClient } from './client';
14
+ export interface LoadBootstrapOptions {
15
+ /** Если задан client — fallback на xhr через него. */
16
+ client?: AdminClient;
17
+ /** Override URL для xhr. Default: '/system/bootstrap'. */
18
+ xhrUrl?: string;
19
+ }
20
+ /**
21
+ * Возвращает bootstrap или null если не загрузился.
22
+ *
23
+ * Порядок:
24
+ * 1. window.__ADMIN_BOOTSTRAP__ (inline-strategy).
25
+ * 2. xhr fetch если передан client.
26
+ * 3. null — caller решает что делать (показать error-screen).
27
+ */
28
+ export declare function loadBootstrap(opts?: LoadBootstrapOptions): Promise<AdminBootstrap | null>;
29
+ /**
30
+ * Прочитать bootstrap из window — только в браузерном контексте.
31
+ */
32
+ export declare function readInlineBootstrap(): AdminBootstrap | null;
33
+ /**
34
+ * Прочитать CSRF-token из meta-tag (Blade-injection через `csrf_token()`).
35
+ *
36
+ * Используется как fallback если bootstrap.csrf отсутствует.
37
+ */
38
+ export declare function readCsrfFromMeta(): string | null;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Axios-клиент для admin API.
3
+ *
4
+ * Особенности:
5
+ * - baseURL берётся из bootstrap.apiUrl (либо передаётся явно).
6
+ * - X-XSRF-TOKEN добавляется автоматически из cookie (Laravel Sanctum/web).
7
+ * - X-CSRF-TOKEN — fallback из meta[name=csrf-token] (Blade-injection).
8
+ * - X-Admin-Locale выставляется при наличии текущей локали.
9
+ * - Response interceptor разворачивает envelope и бросает ApiError.
10
+ * - 401 → onUnauthenticated callback (редирект на login на стороне consumer'а).
11
+ */
12
+ import { type AxiosInstance, type AxiosRequestConfig } from 'axios';
13
+ export interface ClientOptions {
14
+ baseURL: string;
15
+ csrfToken?: string;
16
+ locale?: string;
17
+ /** Вызывается при 401. Обычно — push на /admin/login. */
18
+ onUnauthenticated?: () => void;
19
+ }
20
+ export interface AdminClient {
21
+ /** Низкоуровневый axios — для специфичных случаев. */
22
+ raw: AxiosInstance;
23
+ get<T = unknown>(url: string, config?: AxiosRequestConfig): Promise<T>;
24
+ post<T = unknown>(url: string, data?: unknown, config?: AxiosRequestConfig): Promise<T>;
25
+ put<T = unknown>(url: string, data?: unknown, config?: AxiosRequestConfig): Promise<T>;
26
+ patch<T = unknown>(url: string, data?: unknown, config?: AxiosRequestConfig): Promise<T>;
27
+ delete<T = unknown>(url: string, config?: AxiosRequestConfig): Promise<T>;
28
+ setLocale(locale: string): void;
29
+ }
30
+ export declare function createAdminClient(opts: ClientOptions): AdminClient;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Контракт ответов laravel-api: каждое тело — `{success, payload}`.
3
+ *
4
+ * Success: `{success: true, payload: {...}}`
5
+ * Error: `{success: false, payload: {errorKey, message, ...}}`
6
+ *
7
+ * Helper'ы здесь — для type-narrowing'а в потребителях.
8
+ */
9
+ export interface SuccessEnvelope<T = unknown> {
10
+ success: true;
11
+ payload: T;
12
+ }
13
+ export interface ErrorEnvelope {
14
+ success: false;
15
+ payload: {
16
+ errorKey: string;
17
+ message: string;
18
+ messages?: Record<string, string[]>;
19
+ [key: string]: unknown;
20
+ };
21
+ }
22
+ export type ApiEnvelope<T = unknown> = SuccessEnvelope<T> | ErrorEnvelope;
23
+ export declare function isSuccess<T>(env: ApiEnvelope<T>): env is SuccessEnvelope<T>;
24
+ export declare function isError(env: ApiEnvelope): env is ErrorEnvelope;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Кастомные Error-классы для admin API.
3
+ *
4
+ * Все API-ошибки бросаются как ApiError или его подклассы. Потребители
5
+ * могут делать `instanceof ValidationError` для специфичной обработки.
6
+ */
7
+ import type { ErrorEnvelope } from './envelope';
8
+ export declare class ApiError extends Error {
9
+ readonly status: number;
10
+ readonly errorKey: string;
11
+ readonly payload: ErrorEnvelope['payload'];
12
+ constructor(status: number, payload: ErrorEnvelope['payload']);
13
+ }
14
+ export declare class UnauthenticatedError extends ApiError {
15
+ constructor(payload: ErrorEnvelope['payload']);
16
+ }
17
+ export declare class ForbiddenError extends ApiError {
18
+ constructor(payload: ErrorEnvelope['payload']);
19
+ }
20
+ export declare class NotFoundError extends ApiError {
21
+ constructor(payload: ErrorEnvelope['payload']);
22
+ }
23
+ export declare class ValidationError extends ApiError {
24
+ /** Field-keyed map of error messages. */
25
+ readonly fields: Record<string, string[]>;
26
+ constructor(payload: ErrorEnvelope['payload']);
27
+ /** Первое сообщение из field'а — удобно для toast. */
28
+ firstFieldMessage(): string | null;
29
+ }
30
+ /**
31
+ * Network-failure (не дошли до сервера). Отдельный класс чтобы UI мог
32
+ * показать «Нет соединения» вместо «500 Server Error».
33
+ */
34
+ export declare class NetworkError extends Error {
35
+ constructor(message?: string);
36
+ }
37
+ /**
38
+ * Превращает HTTP-status + envelope в правильный подкласс ApiError.
39
+ */
40
+ export declare function toApiError(status: number, payload: ErrorEnvelope['payload']): ApiError;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,2 @@
1
+ declare const _default: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
2
+ export default _default;
@@ -0,0 +1,2 @@
1
+ declare const _default: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
2
+ export default _default;
@@ -0,0 +1,2 @@
1
+ declare const _default: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
2
+ export default _default;
@@ -0,0 +1,2 @@
1
+ declare const _default: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
2
+ export default _default;
@@ -0,0 +1,2 @@
1
+ declare const _default: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
2
+ export default _default;
@@ -0,0 +1,2 @@
1
+ declare const _default: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
2
+ export default _default;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,17 @@
1
+ interface Props {
2
+ /** URL «Забыли пароль?» — если задан, показывается link справа от remember. */
3
+ forgotUrl?: string | null;
4
+ /** Текст SSO-ссылки или null чтобы скрыть. */
5
+ ssoLinkLabel?: string | null;
6
+ ssoUrl?: string | null;
7
+ }
8
+ declare const _default: import("vue").DefineComponent<Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
9
+ success: (result: "authenticated" | "two_factor_required") => any;
10
+ }, string, import("vue").PublicProps, Readonly<Props> & Readonly<{
11
+ onSuccess?: ((result: "authenticated" | "two_factor_required") => any) | undefined;
12
+ }>, {
13
+ forgotUrl: string | null;
14
+ ssoLinkLabel: string | null;
15
+ ssoUrl: string | null;
16
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
17
+ export default _default;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,26 @@
1
+ interface Props {
2
+ brandName?: string;
3
+ brandMark?: string;
4
+ brandLogo?: string | null;
5
+ homeRouteName?: string;
6
+ redirectQueryKey?: string;
7
+ /** URL «Забыли пароль?» — пробрасывается в LoginForm. */
8
+ forgotUrl?: string | null;
9
+ /** SSO-link (label + url) — пробрасывается в LoginForm. */
10
+ ssoLinkLabel?: string | null;
11
+ ssoUrl?: string | null;
12
+ /** Показывать ли theme/locale toggle'ы в углу. */
13
+ showCornerActions?: boolean;
14
+ }
15
+ declare const _default: import("vue").DefineComponent<Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<Props> & Readonly<{}>, {
16
+ brandName: string;
17
+ brandMark: string;
18
+ forgotUrl: string | null;
19
+ ssoLinkLabel: string | null;
20
+ ssoUrl: string | null;
21
+ brandLogo: string | null;
22
+ homeRouteName: string;
23
+ redirectQueryKey: string;
24
+ showCornerActions: boolean;
25
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
26
+ export default _default;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,8 @@
1
+ declare const _default: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
2
+ success: () => any;
3
+ cancel: () => any;
4
+ }, string, import("vue").PublicProps, Readonly<{}> & Readonly<{
5
+ onSuccess?: (() => any) | undefined;
6
+ onCancel?: (() => any) | undefined;
7
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
8
+ export default _default;
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Public exports auth-страниц.
3
+ */
4
+ export { default as LoginPage } from './LoginPage.vue';
5
+ export { default as LoginForm } from './LoginForm.vue';
6
+ export { default as TwoFactorForm } from './TwoFactorForm.vue';
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Generic factory для component-registry'ов (fields, layouts, widgets,
3
+ * infolist entries и т.п.).
4
+ *
5
+ * Все component-registry в admin'е по сути одинаковы: keyed Map<string, Component>
6
+ * + register/get/has/list/clear/registerBundle. Этот factory вытаскивает паттерн
7
+ * один раз; конкретные модули просто переименовывают экспорты.
8
+ *
9
+ * const reg = createComponentRegistry<Component>()
10
+ * export const registerWidget = reg.register
11
+ * export const getWidget = reg.get
12
+ * // ...
13
+ */
14
+ export interface ComponentRegistry<T> {
15
+ register(type: string, value: T): void;
16
+ get(type: string): T | null;
17
+ has(type: string): boolean;
18
+ list(): string[];
19
+ clear(): void;
20
+ registerBundle(bundle: Record<string, T>): void;
21
+ }
22
+ export declare function createComponentRegistry<T>(): ComponentRegistry<T>;
@@ -0,0 +1,18 @@
1
+ interface Datum {
2
+ label: string;
3
+ value: number;
4
+ }
5
+ interface Props {
6
+ title?: string;
7
+ description?: string;
8
+ data: Datum[];
9
+ accent?: string;
10
+ height?: number;
11
+ }
12
+ declare const _default: import("vue").DefineComponent<Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<Props> & Readonly<{}>, {
13
+ title: string;
14
+ description: string;
15
+ height: number;
16
+ accent: string;
17
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
18
+ export default _default;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,28 @@
1
+ import { type WidgetNode } from './WidgetRenderer.vue';
2
+ interface Props {
3
+ /** Slug dashboard'а в manifest.dashboards. */
4
+ slug?: string;
5
+ /** Прямой override widget'ов (если slug не задан или не нашёлся). */
6
+ widgets?: WidgetNode[];
7
+ /** Заголовок страницы. */
8
+ title?: string;
9
+ /** Подзаголовок (description). */
10
+ subtitle?: string;
11
+ }
12
+ declare var __VLS_1: {};
13
+ type __VLS_Slots = {} & {
14
+ actions?: (props: typeof __VLS_1) => any;
15
+ };
16
+ declare const __VLS_component: import("vue").DefineComponent<Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<Props> & Readonly<{}>, {
17
+ title: string;
18
+ slug: string;
19
+ subtitle: string;
20
+ widgets: WidgetNode[];
21
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
22
+ declare const _default: __VLS_WithSlots<typeof __VLS_component, __VLS_Slots>;
23
+ export default _default;
24
+ type __VLS_WithSlots<T, S> = T & {
25
+ new (): {
26
+ $slots: S;
27
+ };
28
+ };
@@ -0,0 +1,13 @@
1
+ interface Slice {
2
+ label: string;
3
+ value: number;
4
+ color?: string;
5
+ }
6
+ interface Props {
7
+ title?: string;
8
+ data: Slice[];
9
+ }
10
+ declare const _default: import("vue").DefineComponent<Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<Props> & Readonly<{}>, {
11
+ title: string;
12
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
13
+ export default _default;
@@ -0,0 +1,29 @@
1
+ import type { GaugeRange } from '@dskripchenko/ui';
2
+ type SemanticTone = 'neutral' | 'positive' | 'warning' | 'negative';
3
+ interface Props {
4
+ title?: string;
5
+ value?: number;
6
+ min?: number;
7
+ max?: number;
8
+ size?: number;
9
+ ranges?: GaugeRange[];
10
+ tone?: SemanticTone;
11
+ color?: string;
12
+ label?: string;
13
+ suffix?: string;
14
+ precision?: number;
15
+ }
16
+ declare const _default: import("vue").DefineComponent<Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<Props> & Readonly<{}>, {
17
+ value: number;
18
+ label: string;
19
+ title: string;
20
+ color: string;
21
+ size: number;
22
+ suffix: string;
23
+ precision: number;
24
+ tone: SemanticTone;
25
+ min: number;
26
+ max: number;
27
+ ranges: GaugeRange[];
28
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
29
+ export default _default;
@@ -0,0 +1,18 @@
1
+ interface HeatmapPoint {
2
+ date: string;
3
+ value: number;
4
+ }
5
+ interface Props {
6
+ title?: string;
7
+ data: HeatmapPoint[];
8
+ levels?: number;
9
+ color?: string;
10
+ gap?: number;
11
+ }
12
+ declare const _default: import("vue").DefineComponent<Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<Props> & Readonly<{}>, {
13
+ title: string;
14
+ color: string;
15
+ levels: number;
16
+ gap: number;
17
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
18
+ export default _default;
@@ -0,0 +1,8 @@
1
+ interface Props {
2
+ title?: string;
3
+ content: string;
4
+ }
5
+ declare const _default: import("vue").DefineComponent<Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<Props> & Readonly<{}>, {
6
+ title: string;
7
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
8
+ export default _default;