qdadm 0.13.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 (82) hide show
  1. package/CHANGELOG.md +270 -0
  2. package/LICENSE +21 -0
  3. package/README.md +166 -0
  4. package/package.json +48 -0
  5. package/src/assets/logo.svg +6 -0
  6. package/src/components/BoolCell.vue +28 -0
  7. package/src/components/dialogs/BulkStatusDialog.vue +43 -0
  8. package/src/components/dialogs/MultiStepDialog.vue +321 -0
  9. package/src/components/dialogs/SimpleDialog.vue +108 -0
  10. package/src/components/dialogs/UnsavedChangesDialog.vue +87 -0
  11. package/src/components/display/CardsGrid.vue +155 -0
  12. package/src/components/display/CopyableId.vue +92 -0
  13. package/src/components/display/EmptyState.vue +114 -0
  14. package/src/components/display/IntensityBar.vue +171 -0
  15. package/src/components/display/RichCardsGrid.vue +220 -0
  16. package/src/components/editors/JsonEditorFoldable.vue +467 -0
  17. package/src/components/editors/JsonStructuredField.vue +218 -0
  18. package/src/components/editors/JsonViewer.vue +91 -0
  19. package/src/components/editors/KeyValueEditor.vue +314 -0
  20. package/src/components/editors/LanguageEditor.vue +245 -0
  21. package/src/components/editors/ScopeEditor.vue +341 -0
  22. package/src/components/editors/VanillaJsonEditor.vue +185 -0
  23. package/src/components/forms/FormActions.vue +104 -0
  24. package/src/components/forms/FormField.vue +64 -0
  25. package/src/components/forms/FormTab.vue +217 -0
  26. package/src/components/forms/FormTabs.vue +108 -0
  27. package/src/components/index.js +44 -0
  28. package/src/components/layout/AppLayout.vue +430 -0
  29. package/src/components/layout/Breadcrumb.vue +106 -0
  30. package/src/components/layout/PageHeader.vue +75 -0
  31. package/src/components/layout/PageLayout.vue +93 -0
  32. package/src/components/lists/ActionButtons.vue +41 -0
  33. package/src/components/lists/ActionColumn.vue +37 -0
  34. package/src/components/lists/FilterBar.vue +53 -0
  35. package/src/components/lists/ListPage.vue +319 -0
  36. package/src/composables/index.js +19 -0
  37. package/src/composables/useApp.js +43 -0
  38. package/src/composables/useAuth.js +49 -0
  39. package/src/composables/useBareForm.js +143 -0
  40. package/src/composables/useBreadcrumb.js +221 -0
  41. package/src/composables/useDirtyState.js +103 -0
  42. package/src/composables/useEntityTitle.js +121 -0
  43. package/src/composables/useForm.js +254 -0
  44. package/src/composables/useGuardStore.js +37 -0
  45. package/src/composables/useJsonSyntax.js +101 -0
  46. package/src/composables/useListPageBuilder.js +1176 -0
  47. package/src/composables/useNavigation.js +89 -0
  48. package/src/composables/usePageBuilder.js +334 -0
  49. package/src/composables/useStatus.js +146 -0
  50. package/src/composables/useSubEditor.js +165 -0
  51. package/src/composables/useTabSync.js +110 -0
  52. package/src/composables/useUnsavedChangesGuard.js +122 -0
  53. package/src/entity/EntityManager.js +540 -0
  54. package/src/entity/index.js +11 -0
  55. package/src/entity/storage/ApiStorage.js +146 -0
  56. package/src/entity/storage/LocalStorage.js +220 -0
  57. package/src/entity/storage/MemoryStorage.js +201 -0
  58. package/src/entity/storage/index.js +10 -0
  59. package/src/index.js +29 -0
  60. package/src/kernel/Kernel.js +234 -0
  61. package/src/kernel/index.js +7 -0
  62. package/src/module/index.js +16 -0
  63. package/src/module/moduleRegistry.js +222 -0
  64. package/src/orchestrator/Orchestrator.js +141 -0
  65. package/src/orchestrator/index.js +8 -0
  66. package/src/orchestrator/useOrchestrator.js +61 -0
  67. package/src/plugin.js +142 -0
  68. package/src/styles/_alerts.css +48 -0
  69. package/src/styles/_code.css +33 -0
  70. package/src/styles/_dialogs.css +17 -0
  71. package/src/styles/_markdown.css +82 -0
  72. package/src/styles/_show-pages.css +84 -0
  73. package/src/styles/index.css +16 -0
  74. package/src/styles/main.css +845 -0
  75. package/src/styles/theme/components.css +286 -0
  76. package/src/styles/theme/index.css +10 -0
  77. package/src/styles/theme/tokens.css +125 -0
  78. package/src/styles/theme/utilities.css +172 -0
  79. package/src/utils/debugInjector.js +261 -0
  80. package/src/utils/formatters.js +165 -0
  81. package/src/utils/index.js +35 -0
  82. package/src/utils/transformers.js +105 -0
@@ -0,0 +1,222 @@
1
+ /**
2
+ * Module Registry - Auto-discovery and registration system
3
+ *
4
+ * Each module can provide an init.js that registers:
5
+ * - Routes
6
+ * - Navigation items
7
+ * - Route families (for active state detection)
8
+ *
9
+ * Usage in module (modules/agents/init.js):
10
+ *
11
+ * export function init(registry) {
12
+ * registry.addRoutes('agents', [
13
+ * { path: '', name: 'agents', component: () => import('./pages/AgentList.vue') },
14
+ * { path: 'create', name: 'agent-create', component: () => import('./pages/AgentForm.vue') },
15
+ * { path: ':id/edit', name: 'agent-edit', component: () => import('./pages/AgentForm.vue') }
16
+ * ])
17
+ *
18
+ * registry.addNavItem({
19
+ * section: 'Simulation',
20
+ * route: 'agents',
21
+ * icon: 'pi pi-user',
22
+ * label: 'Agents'
23
+ * })
24
+ *
25
+ * registry.addRouteFamily('agents', ['agent-'])
26
+ * }
27
+ */
28
+
29
+ // Storage
30
+ const routes = []
31
+ const navItems = []
32
+ const routeFamilies = {}
33
+ const navSections = new Map()
34
+ const entityConfigs = new Map() // Entity declarations from modules
35
+
36
+ // Configurable section order (set via setSectionOrder or bootstrap)
37
+ let sectionOrder = []
38
+
39
+ /**
40
+ * Registry API passed to module init functions
41
+ */
42
+ const registry = {
43
+ /**
44
+ * Add routes for this module
45
+ * @param {string} prefix - Path prefix for all routes (e.g., 'agents')
46
+ * @param {Array} moduleRoutes - Route definitions with relative paths
47
+ * @param {object} options - { entity?: string } - Entity name for permission checking
48
+ */
49
+ addRoutes(prefix, moduleRoutes, options = {}) {
50
+ const prefixedRoutes = moduleRoutes.map(route => ({
51
+ ...route,
52
+ path: route.path ? `${prefix}/${route.path}` : prefix,
53
+ meta: {
54
+ ...route.meta,
55
+ ...(options.entity && { entity: options.entity })
56
+ }
57
+ }))
58
+ routes.push(...prefixedRoutes)
59
+ },
60
+
61
+ /**
62
+ * Add a navigation item to a section
63
+ * @param {object} item - { section, route, icon, label, exact? }
64
+ */
65
+ addNavItem(item) {
66
+ const { section, ...navItem } = item
67
+ if (!navSections.has(section)) {
68
+ navSections.set(section, [])
69
+ }
70
+ navSections.get(section).push(navItem)
71
+ navItems.push(item)
72
+ },
73
+
74
+ /**
75
+ * Add route family mapping (for active state detection)
76
+ * @param {string} parent - Parent route name (e.g., 'agents')
77
+ * @param {Array<string>} prefixes - Child route prefixes (e.g., ['agent-'])
78
+ */
79
+ addRouteFamily(parent, prefixes) {
80
+ if (!routeFamilies[parent]) {
81
+ routeFamilies[parent] = []
82
+ }
83
+ routeFamilies[parent].push(...prefixes)
84
+ },
85
+
86
+ /**
87
+ * Declare an entity managed by this module
88
+ * @param {string} name - Entity name (e.g., 'users')
89
+ * @param {object|EntityManager} config - Entity config or manager instance
90
+ * - If EntityManager instance: used directly
91
+ * - If object: { endpoint, idField, storage?, ... } passed to factory
92
+ *
93
+ * Usage:
94
+ * registry.addEntity('users', { endpoint: '/users' })
95
+ * registry.addEntity('users', new CustomUsersManager())
96
+ */
97
+ addEntity(name, config) {
98
+ entityConfigs.set(name, config)
99
+ }
100
+ }
101
+
102
+ /**
103
+ * Set section order for navigation menu
104
+ * Called from bootstrap config
105
+ * @param {Array<string>} order - Section titles in order
106
+ */
107
+ export function setSectionOrder(order) {
108
+ sectionOrder = order || []
109
+ }
110
+
111
+ /**
112
+ * Initialize modules from a glob import result
113
+ * The consuming app calls this with its own import.meta.glob
114
+ *
115
+ * Usage in app:
116
+ * const moduleInits = import.meta.glob('./modules/* /init.js', { eager: true })
117
+ * initModules(moduleInits)
118
+ *
119
+ * @param {object} moduleInits - Result of import.meta.glob
120
+ * @param {object} options - { coreNavItems: [] } - Core items not in modules
121
+ */
122
+ export function initModules(moduleInits, options = {}) {
123
+ // Add core nav items (pages that aren't in modules)
124
+ if (options.coreNavItems) {
125
+ for (const item of options.coreNavItems) {
126
+ registry.addNavItem(item)
127
+ }
128
+ }
129
+
130
+ // Initialize all discovered modules
131
+ for (const path in moduleInits) {
132
+ const module = moduleInits[path]
133
+ if (typeof module.init === 'function') {
134
+ module.init(registry)
135
+ }
136
+ }
137
+ }
138
+
139
+ /**
140
+ * Get all registered routes
141
+ */
142
+ export function getRoutes() {
143
+ return routes
144
+ }
145
+
146
+ /**
147
+ * Get navigation sections in order
148
+ */
149
+ export function getNavSections() {
150
+ const sections = []
151
+
152
+ // First add sections in the configured order
153
+ for (const title of sectionOrder) {
154
+ if (navSections.has(title)) {
155
+ sections.push({
156
+ title,
157
+ items: navSections.get(title)
158
+ })
159
+ }
160
+ }
161
+
162
+ // Add any sections not in the predefined order
163
+ for (const [title, items] of navSections) {
164
+ if (!sectionOrder.includes(title)) {
165
+ sections.push({ title, items })
166
+ }
167
+ }
168
+
169
+ return sections
170
+ }
171
+
172
+ /**
173
+ * Get route families mapping
174
+ */
175
+ export function getRouteFamilies() {
176
+ return routeFamilies
177
+ }
178
+
179
+ /**
180
+ * Get entity configurations declared by modules
181
+ * @returns {Map<string, object>}
182
+ */
183
+ export function getEntityConfigs() {
184
+ return entityConfigs
185
+ }
186
+
187
+ /**
188
+ * Get a specific entity configuration
189
+ * @param {string} name - Entity name
190
+ * @returns {object|undefined}
191
+ */
192
+ export function getEntityConfig(name) {
193
+ return entityConfigs.get(name)
194
+ }
195
+
196
+ /**
197
+ * Check if a route belongs to a family
198
+ */
199
+ export function isRouteInFamily(currentRoute, parentRoute) {
200
+ if (currentRoute === parentRoute) return true
201
+
202
+ const prefixes = routeFamilies[parentRoute]
203
+ if (prefixes && currentRoute) {
204
+ return prefixes.some(prefix => currentRoute.startsWith(prefix))
205
+ }
206
+ return false
207
+ }
208
+
209
+ /**
210
+ * Reset registry (for testing)
211
+ */
212
+ export function resetRegistry() {
213
+ routes.length = 0
214
+ navItems.length = 0
215
+ Object.keys(routeFamilies).forEach(key => delete routeFamilies[key])
216
+ navSections.clear()
217
+ entityConfigs.clear()
218
+ sectionOrder = []
219
+ }
220
+
221
+ // Export registry for direct access if needed
222
+ export { registry }
@@ -0,0 +1,141 @@
1
+ /**
2
+ * Orchestrator - Manager of EntityManagers
3
+ *
4
+ * Central registry that creates and distributes EntityManagers.
5
+ * Uses a factory function provided by the consuming application.
6
+ * Entity configs can be declared by modules via registry.addEntity().
7
+ *
8
+ * Usage:
9
+ * ```js
10
+ * // Dashboard provides a factory that receives (name, config)
11
+ * const entityFactory = (entityName, entityConfig) => {
12
+ * // entityConfig comes from registry.addEntity() or is undefined
13
+ * if (entityConfig instanceof EntityManager) {
14
+ * return entityConfig // Module provided a custom manager
15
+ * }
16
+ * return new EntityManager({
17
+ * name: entityName,
18
+ * storage: new ApiStorage({
19
+ * endpoint: entityConfig?.endpoint || `/${entityName}`,
20
+ * client
21
+ * })
22
+ * })
23
+ * }
24
+ *
25
+ * const orchestrator = new Orchestrator({ entityFactory })
26
+ *
27
+ * // Get managers (created lazily)
28
+ * const usersManager = orchestrator.get('users')
29
+ * ```
30
+ */
31
+ import { getEntityConfig } from '../module/moduleRegistry.js'
32
+
33
+ export class Orchestrator {
34
+ constructor(options = {}) {
35
+ const {
36
+ entityFactory = null,
37
+ // Optional: pre-registered managers (for special cases)
38
+ managers = {}
39
+ } = options
40
+
41
+ this._entityFactory = entityFactory
42
+ this._managers = new Map()
43
+
44
+ // Register pre-provided managers
45
+ for (const [name, manager] of Object.entries(managers)) {
46
+ this.register(name, manager)
47
+ }
48
+ }
49
+
50
+ /**
51
+ * Set the entity factory
52
+ * @param {function} factory - (entityName, entityConfig) => EntityManager
53
+ */
54
+ setFactory(factory) {
55
+ this._entityFactory = factory
56
+ }
57
+
58
+ /**
59
+ * Register an EntityManager manually
60
+ * Use this for special managers that don't follow the factory pattern
61
+ *
62
+ * @param {string} name - Entity name
63
+ * @param {EntityManager} manager - Manager instance
64
+ */
65
+ register(name, manager) {
66
+ this._managers.set(name, manager)
67
+ if (manager.onRegister) {
68
+ manager.onRegister(this)
69
+ }
70
+ }
71
+
72
+ /**
73
+ * Check if a manager exists (registered or can be created)
74
+ * @param {string} name - Entity name
75
+ * @returns {boolean}
76
+ */
77
+ has(name) {
78
+ return this._managers.has(name) || !!this._entityFactory
79
+ }
80
+
81
+ /**
82
+ * Get an EntityManager by name
83
+ * Creates it via factory if not already registered
84
+ *
85
+ * @param {string} name - Entity name
86
+ * @returns {EntityManager}
87
+ */
88
+ get(name) {
89
+ // Return existing manager
90
+ if (this._managers.has(name)) {
91
+ return this._managers.get(name)
92
+ }
93
+
94
+ // Get entity config from module registry (if declared)
95
+ const entityConfig = getEntityConfig(name)
96
+
97
+ // If config is already an EntityManager, use it directly
98
+ if (entityConfig && typeof entityConfig.get === 'function') {
99
+ this.register(name, entityConfig)
100
+ return entityConfig
101
+ }
102
+
103
+ // Create via factory
104
+ if (this._entityFactory) {
105
+ const manager = this._entityFactory(name, entityConfig)
106
+ if (manager) {
107
+ this.register(name, manager)
108
+ return manager
109
+ }
110
+ }
111
+
112
+ throw new Error(`[Orchestrator] No manager for entity "${name}" and no factory provided`)
113
+ }
114
+
115
+ /**
116
+ * Get all registered manager names
117
+ * @returns {string[]}
118
+ */
119
+ getRegisteredNames() {
120
+ return Array.from(this._managers.keys())
121
+ }
122
+
123
+ /**
124
+ * Dispose all managers
125
+ */
126
+ dispose() {
127
+ for (const [, manager] of this._managers) {
128
+ if (manager.onDispose) {
129
+ manager.onDispose()
130
+ }
131
+ }
132
+ this._managers.clear()
133
+ }
134
+ }
135
+
136
+ /**
137
+ * Factory function to create an Orchestrator
138
+ */
139
+ export function createOrchestrator(options) {
140
+ return new Orchestrator(options)
141
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Orchestrator Module
3
+ *
4
+ * Manager of EntityManagers - central registry for entity access.
5
+ */
6
+
7
+ export { Orchestrator, createOrchestrator } from './Orchestrator.js'
8
+ export { useOrchestrator, useEntity } from './useOrchestrator.js'
@@ -0,0 +1,61 @@
1
+ /**
2
+ * useOrchestrator - Composable to access the Orchestrator
3
+ *
4
+ * Usage:
5
+ * ```js
6
+ * const { orchestrator, getManager } = useOrchestrator()
7
+ *
8
+ * // Get a specific manager
9
+ * const usersManager = getManager('users')
10
+ *
11
+ * // Use it
12
+ * const { items } = await usersManager.list({ page: 1 })
13
+ * ```
14
+ */
15
+ import { inject } from 'vue'
16
+
17
+ export function useOrchestrator() {
18
+ const orchestrator = inject('qdadmOrchestrator')
19
+
20
+ if (!orchestrator) {
21
+ throw new Error('[qdadm] Orchestrator not provided. Make sure to use createQdadm() with entityFactory.')
22
+ }
23
+
24
+ /**
25
+ * Get an EntityManager by name
26
+ * @param {string} name - Entity name
27
+ * @returns {EntityManager}
28
+ */
29
+ function getManager(name) {
30
+ return orchestrator.get(name)
31
+ }
32
+
33
+ /**
34
+ * Check if a manager exists
35
+ * @param {string} name - Entity name
36
+ * @returns {boolean}
37
+ */
38
+ function hasManager(name) {
39
+ return orchestrator.has(name)
40
+ }
41
+
42
+ return {
43
+ orchestrator,
44
+ getManager,
45
+ hasManager
46
+ }
47
+ }
48
+
49
+ /**
50
+ * useEntity - Shorthand composable to get a specific EntityManager
51
+ *
52
+ * Usage:
53
+ * ```js
54
+ * const users = useEntity('users')
55
+ * const { items } = await users.list()
56
+ * ```
57
+ */
58
+ export function useEntity(name) {
59
+ const { getManager } = useOrchestrator()
60
+ return getManager(name)
61
+ }
package/src/plugin.js ADDED
@@ -0,0 +1,142 @@
1
+ /**
2
+ * qdadm Vue Plugin
3
+ *
4
+ * Creates and configures the qdadm framework for Vue applications.
5
+ */
6
+
7
+ import { Orchestrator } from './orchestrator/Orchestrator.js'
8
+
9
+ /**
10
+ * Creates the qdadm plugin with the given configuration
11
+ *
12
+ * @param {object} options - Configuration options
13
+ * @param {function} options.entityFactory - Factory function: (entityName, entityConfig) => EntityManager
14
+ * @param {object} options.managers - Pre-registered managers to override defaults (e.g., { users: myUsersManager })
15
+ * @param {object} options.orchestrator - Or provide a pre-configured Orchestrator instance
16
+ * @param {object} options.authAdapter - Optional: Auth adapter for login/logout
17
+ * @param {object} options.router - Required: Vue Router instance
18
+ * @param {object} options.toast - Required: Toast notification service
19
+ * @param {object} options.app - Optional: App branding configuration
20
+ * @param {object} options.modules - Optional: Module system configuration
21
+ * @param {object} options.features - Optional: Feature toggles (auth, poweredBy)
22
+ * @param {object} options.builtinModules - Optional: Builtin modules configuration
23
+ * @param {object} options.endpoints - Optional: API endpoints configuration
24
+ * @returns {object} Vue plugin
25
+ */
26
+ export function createQdadm(options) {
27
+ return {
28
+ install(app) {
29
+ // Validation des contrats requis
30
+ if (!options.entityFactory && !options.orchestrator && !options.managers) {
31
+ throw new Error('[qdadm] entityFactory, orchestrator, or managers required')
32
+ }
33
+ if (!options.router) {
34
+ throw new Error('[qdadm] router required')
35
+ }
36
+ if (!options.toast) {
37
+ throw new Error('[qdadm] toast required')
38
+ }
39
+
40
+ // Create or use provided Orchestrator
41
+ let orchestrator = options.orchestrator
42
+ if (!orchestrator) {
43
+ orchestrator = new Orchestrator({
44
+ entityFactory: options.entityFactory,
45
+ managers: options.managers || {}
46
+ })
47
+ } else if (options.managers) {
48
+ // Register additional managers on existing orchestrator
49
+ for (const [name, manager] of Object.entries(options.managers)) {
50
+ orchestrator.register(name, manager)
51
+ }
52
+ }
53
+
54
+ // Features config avec défauts
55
+ const features = {
56
+ auth: true,
57
+ poweredBy: true,
58
+ ...options.features
59
+ }
60
+
61
+ // App config avec défauts
62
+ const appConfig = {
63
+ name: 'Admin',
64
+ shortName: 'Admin',
65
+ logo: null,
66
+ logoSmall: null,
67
+ favicon: null,
68
+ version: null,
69
+ theme: {
70
+ primary: '#3B82F6',
71
+ surface: '#1E293B',
72
+ ...options.app?.theme
73
+ },
74
+ ...options.app
75
+ }
76
+
77
+ // Endpoints config
78
+ const endpoints = {
79
+ users: '/users',
80
+ roles: '/roles',
81
+ ...options.endpoints
82
+ }
83
+
84
+ // Builtin modules config
85
+ const builtinModules = {
86
+ users: features.auth,
87
+ roles: features.auth,
88
+ ...options.builtinModules
89
+ }
90
+
91
+ // Validation conditionnelle
92
+ if (features.auth && !options.authAdapter) {
93
+ throw new Error('[qdadm] authAdapter required when features.auth is true')
94
+ }
95
+
96
+ // Provide all dependencies
97
+ app.provide('qdadmOrchestrator', orchestrator)
98
+ app.provide('qdadmRouter', options.router)
99
+ app.provide('qdadmToast', options.toast)
100
+ app.provide('qdadmFeatures', features)
101
+ app.provide('qdadmApp', appConfig)
102
+ app.provide('qdadmEndpoints', endpoints)
103
+ app.provide('qdadmBuiltinModules', builtinModules)
104
+
105
+ if (options.authAdapter) {
106
+ app.provide('authAdapter', options.authAdapter)
107
+ }
108
+
109
+ if (options.modules?.sectionOrder) {
110
+ app.provide('qdadmSectionOrder', options.modules.sectionOrder)
111
+ }
112
+
113
+ // Add route guard for entity permissions
114
+ options.router.beforeEach((to, from, next) => {
115
+ const entity = to.meta?.entity
116
+ if (entity) {
117
+ const manager = orchestrator.get(entity)
118
+ if (manager && !manager.canRead()) {
119
+ // Redirect to home or show forbidden
120
+ console.warn(`[qdadm] Access denied to ${to.path} (entity: ${entity})`)
121
+ return next({ path: '/' })
122
+ }
123
+ }
124
+ next()
125
+ })
126
+
127
+ // Appliquer le thème via CSS variables
128
+ if (appConfig.theme) {
129
+ document.documentElement.style.setProperty('--qdadm-primary', appConfig.theme.primary)
130
+ document.documentElement.style.setProperty('--qdadm-surface', appConfig.theme.surface)
131
+ }
132
+
133
+ // Appliquer le favicon
134
+ if (appConfig.favicon) {
135
+ const link = document.querySelector("link[rel~='icon']") || document.createElement('link')
136
+ link.rel = 'icon'
137
+ link.href = appConfig.favicon
138
+ document.head.appendChild(link)
139
+ }
140
+ }
141
+ }
142
+ }
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Alert and Notice Boxes
3
+ * Warning, info, and system notice styles
4
+ */
5
+
6
+ /* Warning banner (yellow) - for system notices */
7
+ .alert-warning {
8
+ background: var(--p-yellow-50);
9
+ padding: 1rem;
10
+ margin-bottom: 1rem;
11
+ border-radius: 0.5rem;
12
+ border: 1px solid var(--p-yellow-200);
13
+ }
14
+
15
+ .alert-warning-icon {
16
+ color: var(--p-yellow-600);
17
+ }
18
+
19
+ .alert-warning-text {
20
+ margin-left: 0.5rem;
21
+ color: var(--p-yellow-700);
22
+ }
23
+
24
+ /* Info banner (orange) - for important notices */
25
+ .alert-info {
26
+ color: var(--p-orange-600);
27
+ margin-bottom: 1rem;
28
+ }
29
+
30
+ /* Key info panel - for displaying read-only metadata */
31
+ .key-info-panel {
32
+ background: var(--p-surface-50);
33
+ padding: 1rem;
34
+ margin-bottom: 1rem;
35
+ border-radius: 0.5rem;
36
+ }
37
+
38
+ .key-info-grid {
39
+ display: flex;
40
+ flex-wrap: wrap;
41
+ gap: 2rem;
42
+ align-items: center;
43
+ }
44
+
45
+ .key-info-item small {
46
+ color: var(--p-surface-500);
47
+ display: block;
48
+ }
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Code and Key Display
3
+ * Monospace text, code boxes, and key displays
4
+ */
5
+
6
+ /* Code box - for displaying keys, code, or technical values */
7
+ .code-box {
8
+ word-break: break-all;
9
+ font-family: monospace;
10
+ background: var(--p-surface-100);
11
+ padding: 1rem;
12
+ border-radius: 0.25rem;
13
+ }
14
+
15
+ /* Small code display */
16
+ .code-box--sm {
17
+ padding: 0.5rem;
18
+ font-size: 0.875rem;
19
+ }
20
+
21
+ /* Tag with small font for compact display */
22
+ .tag-sm {
23
+ font-size: 0.7rem;
24
+ }
25
+
26
+ .tag-xs {
27
+ font-size: 0.75rem;
28
+ }
29
+
30
+ /* Constrained width for tag previews */
31
+ .tags-constrained {
32
+ max-width: 300px;
33
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Dialog Content Styles
3
+ * Styles for modal dialog content
4
+ */
5
+
6
+ /* Dialog content spacing */
7
+ .dialog-content {
8
+ margin-bottom: 1rem;
9
+ }
10
+
11
+ /* Dialog section title */
12
+ .dialog-section-title {
13
+ font-size: 0.875rem;
14
+ font-weight: 600;
15
+ margin-bottom: 0.5rem;
16
+ color: var(--p-surface-600);
17
+ }