@halo-dev/ui-shared 1.0.1 → 2.22.1

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.
@@ -0,0 +1,1783 @@
1
+ import { Attachment, Backup, DetailedUser, Extension, GetThumbnailByUriSizeEnum, ListedComment, ListedPost, ListedReply, ListedSinglePage, Plugin, Theme } from "@halo-dev/api-client";
2
+ import * as pinia0 from "pinia";
3
+ import * as vue0 from "vue";
4
+ import { Component, Raw, Ref } from "vue";
5
+ import * as mitt0 from "mitt";
6
+ import { RouteLocationRaw, RouteRecordName, RouteRecordRaw } from "vue-router";
7
+ import { AnyExtension } from "@halo-dev/richtext-editor";
8
+ import _dayjs from "dayjs";
9
+
10
+ //#region src/events/index.d.ts
11
+ type Events = {
12
+ /**
13
+ * Emitted when a plugin's configuration map is updated.
14
+ */
15
+ "core:plugin:configMap:updated": {
16
+ pluginName: string;
17
+ group: string;
18
+ };
19
+ };
20
+ declare const events: mitt0.Emitter<Events>;
21
+ //#endregion
22
+ //#region src/plugin/types/attachment-selector.d.ts
23
+ /**
24
+ * Represents a simplified attachment object with essential properties.
25
+ * Used for lightweight attachment representations without full API client dependencies.
26
+ */
27
+ interface AttachmentSimple {
28
+ /**
29
+ * The URL of the attachment.
30
+ */
31
+ url: string;
32
+ /**
33
+ * The MIME type of the attachment (e.g., 'image/png', 'video/mp4').
34
+ */
35
+ mediaType?: string;
36
+ /**
37
+ * Alternative text for the attachment, used for accessibility.
38
+ */
39
+ alt?: string;
40
+ /**
41
+ * Caption or description for the attachment.
42
+ */
43
+ caption?: string;
44
+ }
45
+ /**
46
+ * Union type representing different forms of attachment references.
47
+ *
48
+ * @remarks
49
+ * This flexible type allows working with attachments in various formats:
50
+ * - Full `Attachment` object from the API client
51
+ * - Simplified `AttachmentSimple` object with basic properties
52
+ * - String URL directly referencing the attachment
53
+ */
54
+ type AttachmentLike = Attachment | AttachmentSimple | string;
55
+ /**
56
+ * Defines a custom attachment selector provider that plugins can register.
57
+ *
58
+ * @remarks
59
+ * Attachment selector providers allow plugins to create custom UI components
60
+ * for selecting attachments from different sources (e.g., local upload,
61
+ * external services, galleries, etc.).
62
+ */
63
+ interface AttachmentSelectProvider {
64
+ /**
65
+ * Unique identifier for this attachment selector provider.
66
+ * Should follow a namespaced pattern to avoid conflicts (e.g., 'plugin-name:selector-id').
67
+ */
68
+ id: string;
69
+ /**
70
+ * Display label for the attachment selector.
71
+ * This label will be shown in the UI where users can choose between different selectors.
72
+ */
73
+ label: string;
74
+ /**
75
+ * The Vue component that implements the attachment selection interface.
76
+ * Can be either a component definition or a component name string.
77
+ *
78
+ * @remarks
79
+ * The component should emit selected attachments through the provided callback
80
+ * or emit events that the parent component can handle.
81
+ */
82
+ component: Component | string;
83
+ /**
84
+ * Optional callback function invoked when attachments are selected.
85
+ *
86
+ * @param attachments - Array of selected attachments in various formats.
87
+ *
88
+ * @remarks
89
+ * This callback is triggered after the user confirms their selection.
90
+ * It allows the provider to handle post-selection logic like validation,
91
+ * transformation, or triggering additional actions.
92
+ */
93
+ callback?: (attachments: AttachmentLike[]) => void;
94
+ }
95
+ //#endregion
96
+ //#region src/plugin/types/backup.d.ts
97
+ /**
98
+ * Defines a custom tab for the backup management page.
99
+ *
100
+ * @remarks
101
+ * Backup tabs allow plugins to extend the backup interface with custom
102
+ * functionality such as cloud backup providers, automated backup schedules,
103
+ * or specialized restore operations.
104
+ */
105
+ interface BackupTab {
106
+ /**
107
+ * Unique identifier for the backup tab.
108
+ * Should follow a namespaced pattern to avoid conflicts (e.g., 'plugin-name:tab-id').
109
+ */
110
+ id: string;
111
+ /**
112
+ * Display label for the tab.
113
+ * This text will be shown in the tab navigation.
114
+ */
115
+ label: string;
116
+ /**
117
+ * The Vue component that renders the tab content.
118
+ * Must be wrapped with `markRaw` to prevent Vue from making it reactive.
119
+ */
120
+ component: Raw<Component>;
121
+ /**
122
+ * Optional array of permission identifiers required to view this tab.
123
+ * The tab will only be visible to users with at least one of these permissions.
124
+ */
125
+ permissions?: string[];
126
+ }
127
+ //#endregion
128
+ //#region src/plugin/types/comment.d.ts
129
+ /**
130
+ * Represents the result of resolving a comment subject reference.
131
+ * Contains display information and navigation details for the commented content.
132
+ */
133
+ interface CommentSubjectRefResult {
134
+ /**
135
+ * Short label or type identifier for the subject (e.g., 'Post', 'Page', 'Custom').
136
+ */
137
+ label: string;
138
+ /**
139
+ * The title or name of the content being commented on.
140
+ */
141
+ title: string;
142
+ /**
143
+ * Internal route location to navigate to the subject.
144
+ * Used for navigating within the Halo console.
145
+ */
146
+ route?: RouteLocationRaw;
147
+ /**
148
+ * External URL to the subject if it's hosted outside the console.
149
+ * Typically used for public-facing content.
150
+ */
151
+ externalUrl?: string;
152
+ }
153
+ /**
154
+ * Defines a provider that resolves comment subject references.
155
+ *
156
+ * @remarks
157
+ * Comment subject reference providers allow plugins to make their custom content types
158
+ * commentable. The provider resolves extension references into human-readable information
159
+ * that can be displayed in the comment management interface.
160
+ */
161
+ type CommentSubjectRefProvider = {
162
+ /**
163
+ * The kind of the extension that this provider handles.
164
+ * Must match the `kind` field in the extension's metadata.
165
+ */
166
+ kind: string;
167
+ /**
168
+ * The API group of the extension that this provider handles.
169
+ * Must match the `group` field in the extension's metadata.
170
+ */
171
+ group: string;
172
+ /**
173
+ * Resolves an extension reference into displayable comment subject information.
174
+ *
175
+ * @param subject - The extension object representing the commented content.
176
+ * @returns The resolved subject information including label, title, and navigation details.
177
+ */
178
+ resolve: (subject: Extension) => CommentSubjectRefResult;
179
+ };
180
+ /**
181
+ * Defines a custom comment editor provider.
182
+ *
183
+ * @remarks
184
+ * Allows plugins to replace the default comment editor with a custom implementation.
185
+ * Useful for providing rich-text editing, markdown support, or specialized input methods.
186
+ */
187
+ interface CommentEditorProvider {
188
+ /**
189
+ * The Vue component that implements the custom comment editor.
190
+ * Must be wrapped with `markRaw` to prevent Vue from making it reactive.
191
+ *
192
+ * @remarks
193
+ * The component should emit appropriate events for content changes and
194
+ * integrate with the parent form for submission handling.
195
+ */
196
+ component: Raw<Component>;
197
+ }
198
+ /**
199
+ * Defines a custom comment content renderer.
200
+ *
201
+ * @remarks
202
+ * Allows plugins to customize how comment content is displayed in comment lists.
203
+ * Useful when comments are stored in a custom format that requires special rendering.
204
+ */
205
+ interface CommentContentProvider {
206
+ /**
207
+ * The Vue component that renders the comment content.
208
+ * Must be wrapped with `markRaw` to prevent Vue from making it reactive.
209
+ *
210
+ * @remarks
211
+ * The component receives the comment content as props and should handle
212
+ * rendering, sanitization, and any interactive features.
213
+ */
214
+ component: Raw<Component>;
215
+ }
216
+ //#endregion
217
+ //#region src/plugin/types/dashboard-widget.d.ts
218
+ /**
219
+ * Defines responsive layout configurations for dashboard widgets across different screen sizes.
220
+ *
221
+ * @remarks
222
+ * Each breakpoint can have a different layout arrangement. If a breakpoint is not specified,
223
+ * it will fall back to the next larger breakpoint's layout.
224
+ */
225
+ interface DashboardResponsiveLayout {
226
+ /**
227
+ * Layout for large screens (typically ≥ 1200px).
228
+ */
229
+ lg?: DashboardWidget[];
230
+ /**
231
+ * Layout for medium screens (typically ≥ 996px).
232
+ */
233
+ md?: DashboardWidget[];
234
+ /**
235
+ * Layout for small screens (typically ≥ 768px).
236
+ */
237
+ sm?: DashboardWidget[];
238
+ /**
239
+ * Layout for extra small screens (typically ≥ 480px).
240
+ */
241
+ xs?: DashboardWidget[];
242
+ /**
243
+ * Layout for double extra small screens (typically < 480px).
244
+ */
245
+ xxs?: DashboardWidget[];
246
+ }
247
+ /**
248
+ * Represents an instance of a dashboard widget with its position, size, and configuration.
249
+ *
250
+ * @remarks
251
+ * Dashboard widgets are arranged in a grid layout system. The grid typically has 12 columns,
252
+ * and widgets can span multiple rows and columns.
253
+ */
254
+ interface DashboardWidget {
255
+ /**
256
+ * The x-coordinate (column position) in the grid, starting from 0.
257
+ */
258
+ x: number;
259
+ /**
260
+ * The y-coordinate (row position) in the grid, starting from 0.
261
+ */
262
+ y: number;
263
+ /**
264
+ * The width of the widget in grid columns.
265
+ */
266
+ w: number;
267
+ /**
268
+ * The height of the widget in grid rows.
269
+ */
270
+ h: number;
271
+ /**
272
+ * Unique identifier for this widget instance in the layout.
273
+ * Can be a number or string.
274
+ */
275
+ i: number | string;
276
+ /**
277
+ * Minimum width constraint in grid columns.
278
+ */
279
+ minW?: number;
280
+ /**
281
+ * Minimum height constraint in grid rows.
282
+ */
283
+ minH?: number;
284
+ /**
285
+ * Maximum width constraint in grid columns.
286
+ */
287
+ maxW?: number;
288
+ /**
289
+ * Maximum height constraint in grid rows.
290
+ */
291
+ maxH?: number;
292
+ /**
293
+ * Reference to the widget definition ID that this instance represents.
294
+ */
295
+ id: string;
296
+ /**
297
+ * User-specific configuration for this widget instance.
298
+ * The structure depends on the widget's definition schema.
299
+ */
300
+ config?: Record<string, unknown>;
301
+ /**
302
+ * Optional array of permission identifiers required to view this widget instance.
303
+ */
304
+ permissions?: string[];
305
+ }
306
+ /**
307
+ * Defines a dashboard widget type that can be added to the dashboard.
308
+ *
309
+ * @remarks
310
+ * Widget definitions serve as templates from which users can create widget instances.
311
+ * Each definition specifies the component, default configuration, and size constraints.
312
+ *
313
+ * @example
314
+ * ```typescript
315
+ * const widgetDef: DashboardWidgetDefinition = {
316
+ * id: 'plugin-name:widget-id',
317
+ * component: markRaw(MyWidgetComponent),
318
+ * group: 'statistics',
319
+ * defaultSize: { w: 4, h: 2, minW: 2, minH: 1 },
320
+ * defaultConfig: { refreshInterval: 60000 },
321
+ * configFormKitSchema: [
322
+ * { $formkit: 'number', name: 'refreshInterval', label: 'Refresh Interval (ms)' }
323
+ * ]
324
+ * };
325
+ * ```
326
+ */
327
+ interface DashboardWidgetDefinition {
328
+ /**
329
+ * Unique identifier for the widget definition.
330
+ * Should follow a namespaced pattern (e.g., 'plugin-name:widget-id').
331
+ */
332
+ id: string;
333
+ /**
334
+ * The Vue component that renders the widget.
335
+ * Must be wrapped with `markRaw` to prevent Vue from making it reactive.
336
+ */
337
+ component: Raw<Component>;
338
+ /**
339
+ * Category or group for organizing widgets in the selection interface.
340
+ * Common groups include 'statistics', 'content', 'system', etc.
341
+ */
342
+ group: string;
343
+ /**
344
+ * FormKit schema for the widget's configuration form.
345
+ * Can be an array, a function returning an array, or a function returning a Promise.
346
+ *
347
+ * @remarks
348
+ * Defines the editable settings that users can configure for widget instances.
349
+ * The schema uses FormKit's schema format.
350
+ */
351
+ configFormKitSchema?: Record<string, unknown>[] | (() => Promise<Record<string, unknown>[]>) | (() => Record<string, unknown>[]);
352
+ /**
353
+ * Default configuration values for new widget instances.
354
+ * These values will be used when a user first adds the widget to their dashboard.
355
+ */
356
+ defaultConfig?: Record<string, unknown>;
357
+ /**
358
+ * Default size and constraints for the widget.
359
+ *
360
+ * @remarks
361
+ * Specifies the initial dimensions and any size limitations when the widget is added.
362
+ */
363
+ defaultSize: {
364
+ /**
365
+ * Default width in grid columns.
366
+ */
367
+ w: number;
368
+ /**
369
+ * Default height in grid rows.
370
+ */
371
+ h: number;
372
+ /**
373
+ * Minimum width constraint in grid columns.
374
+ */
375
+ minW?: number;
376
+ /**
377
+ * Minimum height constraint in grid rows.
378
+ */
379
+ minH?: number;
380
+ /**
381
+ * Maximum width constraint in grid columns.
382
+ */
383
+ maxW?: number;
384
+ /**
385
+ * Maximum height constraint in grid rows.
386
+ */
387
+ maxH?: number;
388
+ };
389
+ /**
390
+ * Optional array of permission identifiers required to add or view this widget.
391
+ */
392
+ permissions?: string[];
393
+ }
394
+ /**
395
+ * Base interface for dashboard widget quick action items.
396
+ */
397
+ interface DashboardWidgetQuickActionBaseItem {
398
+ /**
399
+ * Unique identifier for the quick action.
400
+ */
401
+ id: string;
402
+ /**
403
+ * Optional array of permission identifiers required to see this action.
404
+ */
405
+ permissions?: string[];
406
+ }
407
+ /**
408
+ * A quick action item that uses a custom component for rendering.
409
+ * Provides maximum flexibility for complex action UI.
410
+ */
411
+ interface DashboardWidgetQuickActionComponentItem extends DashboardWidgetQuickActionBaseItem {
412
+ /**
413
+ * Custom Vue component for rendering the quick action.
414
+ * When provided, standard properties (icon, title, action) are optional.
415
+ */
416
+ component: Raw<Component>;
417
+ /**
418
+ * Optional icon component displayed alongside the action.
419
+ */
420
+ icon?: Raw<Component>;
421
+ /**
422
+ * Optional title text for the action.
423
+ */
424
+ title?: string;
425
+ /**
426
+ * Optional click handler for the action.
427
+ */
428
+ action?: () => void;
429
+ }
430
+ /**
431
+ * A standard quick action item with icon, title, and action handler.
432
+ * Uses the default rendering style for consistency.
433
+ */
434
+ interface DashboardWidgetQuickActionStandardItem extends DashboardWidgetQuickActionBaseItem {
435
+ /**
436
+ * Cannot provide a custom component for standard items.
437
+ */
438
+ component?: never;
439
+ /**
440
+ * Icon component displayed with the action (required for standard items).
441
+ */
442
+ icon: Raw<Component>;
443
+ /**
444
+ * Display title for the action (required for standard items).
445
+ */
446
+ title: string;
447
+ /**
448
+ * Click handler invoked when the action is triggered (required for standard items).
449
+ */
450
+ action: () => void;
451
+ }
452
+ /**
453
+ * A quick action item that navigates to a route when triggered.
454
+ */
455
+ interface DashboardWidgetQuickActionRouteItem extends DashboardWidgetQuickActionBaseItem {
456
+ /**
457
+ * Cannot provide a custom component for route items.
458
+ */
459
+ component?: never;
460
+ /**
461
+ * Cannot provide an action handler for route items.
462
+ */
463
+ action?: never;
464
+ /**
465
+ * Icon component displayed with the action (required for route items).
466
+ */
467
+ icon: Raw<Component>;
468
+ /**
469
+ * Display title for the action (required for route items).
470
+ */
471
+ title: string;
472
+ /**
473
+ * Route to navigate to when the action is triggered (required for route items).
474
+ */
475
+ route: RouteLocationRaw;
476
+ }
477
+ /**
478
+ * Represents a quick action button that can be added to dashboard widgets.
479
+ *
480
+ * @remarks
481
+ * Quick actions provide shortcuts to common operations directly from the dashboard.
482
+ * They can either use a custom component for full control or follow the standard
483
+ * pattern with an icon, title, and action handler.
484
+ */
485
+ type DashboardWidgetQuickActionItem = DashboardWidgetQuickActionComponentItem | DashboardWidgetQuickActionStandardItem | DashboardWidgetQuickActionRouteItem;
486
+ //#endregion
487
+ //#region src/plugin/types/editor-provider.d.ts
488
+ /**
489
+ * Defines a custom content editor provider.
490
+ *
491
+ * @remarks
492
+ * Editor providers allow plugins to register alternative content editors beyond
493
+ * the default editor. This enables support for different content formats, editing
494
+ * experiences, and specialized workflows (e.g., Markdown, rich-text, code, visual builders).
495
+ *
496
+ * @example
497
+ * ```typescript
498
+ * const markdownEditor: EditorProvider = {
499
+ * name: 'markdown-editor',
500
+ * displayName: 'Markdown Editor',
501
+ * logo: '/path/to/markdown-logo.svg',
502
+ * component: MarkdownEditorComponent,
503
+ * rawType: 'markdown'
504
+ * };
505
+ * ```
506
+ */
507
+ interface EditorProvider {
508
+ /**
509
+ * Unique identifier for the editor provider.
510
+ * Should use kebab-case naming (e.g., 'markdown-editor', 'wysiwyg-editor').
511
+ */
512
+ name: string;
513
+ /**
514
+ * Human-readable display name shown in the editor selection UI.
515
+ */
516
+ displayName: string;
517
+ /**
518
+ * Optional URL or path to the editor's logo image.
519
+ * Displayed in the editor selection interface for visual identification.
520
+ */
521
+ logo?: string;
522
+ /**
523
+ * The Vue component that implements the editor interface.
524
+ *
525
+ * @remarks
526
+ * The component should handle content editing, emit appropriate events for
527
+ * content changes, and integrate with the parent form for validation and submission.
528
+ */
529
+ component: Component;
530
+ /**
531
+ * The content format or MIME type that this editor produces.
532
+ *
533
+ * @remarks
534
+ * This identifier is stored with the content to indicate which editor should be
535
+ * used when reopening for editing. Common values include:
536
+ * - 'markdown' for Markdown content
537
+ * - 'html' for HTML content
538
+ * - 'json' for structured JSON data
539
+ * - Custom identifiers for proprietary formats
540
+ */
541
+ rawType: string;
542
+ }
543
+ //#endregion
544
+ //#region src/plugin/types/list-entity-field.d.ts
545
+ /**
546
+ * Defines a custom field (column) that can be added to entity list views.
547
+ *
548
+ * @remarks
549
+ * Entity field items allow plugins to add custom columns or metadata displays
550
+ * to list views such as posts, pages, comments, etc. Fields can be positioned
551
+ * at the start or end of the list and can include custom rendering logic.
552
+ *
553
+ * @example
554
+ * ```typescript
555
+ * const customField: EntityFieldItem = {
556
+ * priority: 10,
557
+ * position: 'end',
558
+ * component: markRaw(CustomFieldComponent),
559
+ * props: { format: 'short' },
560
+ * permissions: ['plugin:my-plugin:view']
561
+ * };
562
+ * ```
563
+ */
564
+ interface EntityFieldItem {
565
+ /**
566
+ * Priority for ordering multiple custom fields.
567
+ * Higher priority fields are displayed first within their position group.
568
+ */
569
+ priority: number;
570
+ /**
571
+ * The position where this field should be inserted in the list.
572
+ * - 'start': Before the default fields
573
+ * - 'end': After the default fields
574
+ */
575
+ position: "start" | "end";
576
+ /**
577
+ * The Vue component that renders the field content.
578
+ * Must be wrapped with `markRaw` to prevent Vue from making it reactive.
579
+ *
580
+ * @remarks
581
+ * The component typically receives the entity object as a prop and should
582
+ * render the custom field information in a list-friendly format.
583
+ */
584
+ component: Raw<Component>;
585
+ /**
586
+ * Optional props to pass to the component.
587
+ * These can be used to configure the field's behavior or appearance.
588
+ */
589
+ props?: Record<string, unknown>;
590
+ /**
591
+ * Optional array of permission identifiers required to view this field.
592
+ * The field will only be visible to users with at least one of these permissions.
593
+ */
594
+ permissions?: string[];
595
+ /**
596
+ * Whether the field should be hidden by default.
597
+ * Can be used to implement toggleable columns or conditional visibility.
598
+ */
599
+ hidden?: boolean;
600
+ }
601
+ //#endregion
602
+ //#region src/plugin/types/list-operation.d.ts
603
+ /**
604
+ * Defines a custom operation (action button or menu item) for entity list items.
605
+ *
606
+ * @remarks
607
+ * Operation items allow plugins to add custom actions to list rows across various
608
+ * entity types (posts, pages, comments, etc.). Operations can be standalone buttons
609
+ * or nested within dropdown menus, and can include permission checks and conditional visibility.
610
+ *
611
+ * @typeParam T - The type of entity this operation applies to (e.g., ListedPost, Plugin, Theme).
612
+ *
613
+ * @example
614
+ * ```typescript
615
+ * const exportOperation: OperationItem<ListedPost> = {
616
+ * priority: 20,
617
+ * component: markRaw(VButton),
618
+ * label: 'Export',
619
+ * action: (post) => {
620
+ * console.log('Exporting post:', post.metadata.name);
621
+ * },
622
+ * permissions: ['plugin:export:use']
623
+ * };
624
+ *
625
+ * // Operation with children (dropdown menu)
626
+ * const shareOperation: OperationItem<ListedPost> = {
627
+ * priority: 15,
628
+ * component: markRaw(VDropdown),
629
+ * label: 'Share',
630
+ * children: [
631
+ * {
632
+ * priority: 10,
633
+ * component: markRaw(VButton),
634
+ * label: 'Share to Twitter',
635
+ * action: (post) => { // ... }
636
+ * },
637
+ * {
638
+ * priority: 20,
639
+ * component: markRaw(VButton),
640
+ * label: 'Copy Link',
641
+ * action: (post) => { // ... }
642
+ * }
643
+ * ]
644
+ * };
645
+ * ```
646
+ */
647
+ interface OperationItem<T> {
648
+ /**
649
+ * Priority for ordering multiple operations.
650
+ * Higher priority operations are displayed first (leftmost or at the top).
651
+ */
652
+ priority: number;
653
+ /**
654
+ * The Vue component that renders the operation.
655
+ * Must be wrapped with `markRaw` to prevent Vue from making it reactive.
656
+ *
657
+ * @remarks
658
+ * Common components include buttons, dropdown menus, or custom action components.
659
+ * The component receives props and should handle the visual representation and
660
+ * interaction of the operation.
661
+ */
662
+ component: Raw<Component>;
663
+ /**
664
+ * Optional props to pass to the component.
665
+ * Can be used to configure appearance, behavior, or additional data.
666
+ */
667
+ props?: Record<string, unknown>;
668
+ /**
669
+ * Optional action handler invoked when the operation is triggered.
670
+ *
671
+ * @param item - The entity instance that this operation was triggered on.
672
+ *
673
+ * @remarks
674
+ * This is typically used for operations that need to perform actions on the entity,
675
+ * such as exporting, sharing, or custom processing. The handler can be async.
676
+ */
677
+ action?: (item?: T) => void;
678
+ /**
679
+ * Optional display label for the operation.
680
+ * Used for button text, menu items, or tooltips.
681
+ */
682
+ label?: string;
683
+ /**
684
+ * Whether the operation should be hidden by default.
685
+ * Can be used to implement conditional visibility based on entity state or user context.
686
+ */
687
+ hidden?: boolean;
688
+ /**
689
+ * Optional array of permission identifiers required to see this operation.
690
+ * The operation will only be visible to users with at least one of these permissions.
691
+ */
692
+ permissions?: string[];
693
+ /**
694
+ * Optional nested operations for creating hierarchical menus.
695
+ *
696
+ * @remarks
697
+ * When provided, this operation becomes a dropdown menu or submenu containing
698
+ * the child operations. Useful for grouping related actions together.
699
+ */
700
+ children?: OperationItem<T>[];
701
+ }
702
+ //#endregion
703
+ //#region src/plugin/types/plugin-installation-tab.d.ts
704
+ /**
705
+ * Defines a custom tab for the plugin installation page.
706
+ *
707
+ * @remarks
708
+ * Plugin installation tabs allow plugins to provide alternative installation methods
709
+ * or additional functionality during the plugin installation process. Examples include
710
+ * installing from a URL, importing from a marketplace, or batch installation features.
711
+ *
712
+ * @example
713
+ * ```typescript
714
+ * const remoteInstallTab: PluginInstallationTab = {
715
+ * id: 'remote-install',
716
+ * label: 'Install from URL',
717
+ * component: markRaw(RemoteInstallComponent),
718
+ * priority: 10,
719
+ * permissions: ['plugin:install:remote']
720
+ * };
721
+ * ```
722
+ */
723
+ interface PluginInstallationTab {
724
+ /**
725
+ * Unique identifier for the installation tab.
726
+ * Should follow a namespaced pattern to avoid conflicts (e.g., 'plugin-name:tab-id').
727
+ */
728
+ id: string;
729
+ /**
730
+ * Display label for the tab.
731
+ * This text will be shown in the tab navigation.
732
+ */
733
+ label: string;
734
+ /**
735
+ * The Vue component that renders the tab content.
736
+ * Must be wrapped with `markRaw` to prevent Vue from making it reactive.
737
+ *
738
+ * @remarks
739
+ * The component should implement the installation interface and handle
740
+ * the complete installation workflow, including validation and error handling.
741
+ */
742
+ component: Raw<Component>;
743
+ /**
744
+ * Optional props to pass to the component.
745
+ * Can be used to configure the installation behavior or provide additional context.
746
+ */
747
+ props?: Record<string, unknown>;
748
+ /**
749
+ * Optional array of permission identifiers required to view this tab.
750
+ * The tab will only be visible to users with at least one of these permissions.
751
+ */
752
+ permissions?: string[];
753
+ /**
754
+ * Priority for ordering multiple installation tabs.
755
+ * Higher priority tabs appear first (leftmost) in the tab navigation.
756
+ */
757
+ priority: number;
758
+ }
759
+ //#endregion
760
+ //#region src/plugin/types/plugin-tab.d.ts
761
+ /**
762
+ * Defines a custom tab for a plugin's own detail/settings page.
763
+ *
764
+ * @remarks
765
+ * Plugin tabs allow plugins to organize their settings, configuration, and
766
+ * management interfaces into multiple sections. This is useful for plugins
767
+ * with extensive configuration options or multiple functional areas.
768
+ *
769
+ * @example
770
+ * ```typescript
771
+ * const settingsTab: PluginTab = {
772
+ * id: 'settings',
773
+ * label: 'Settings',
774
+ * component: markRaw(SettingsComponent),
775
+ * permissions: ['plugin:my-plugin:manage']
776
+ * };
777
+ * ```
778
+ */
779
+ interface PluginTab {
780
+ /**
781
+ * Unique identifier for the plugin tab.
782
+ * Should follow a namespaced pattern to avoid conflicts (e.g., 'plugin-name:tab-id').
783
+ */
784
+ id: string;
785
+ /**
786
+ * Display label for the tab.
787
+ * This text will be shown in the tab navigation.
788
+ */
789
+ label: string;
790
+ /**
791
+ * The Vue component that renders the tab content.
792
+ * Must be wrapped with `markRaw` to prevent Vue from making it reactive.
793
+ *
794
+ * @remarks
795
+ * The component should implement the tab's functionality, which might include
796
+ * configuration forms, status displays, or management interfaces.
797
+ */
798
+ component: Raw<Component>;
799
+ /**
800
+ * Optional array of permission identifiers required to view this tab.
801
+ * The tab will only be visible to users with at least one of these permissions.
802
+ */
803
+ permissions?: string[];
804
+ }
805
+ //#endregion
806
+ //#region src/plugin/types/theme-list-tab.d.ts
807
+ /**
808
+ * Defines a custom tab for the theme list page.
809
+ *
810
+ * @remarks
811
+ * Theme list tabs allow plugins to extend the theme management interface with
812
+ * custom functionality such as theme marketplaces, remote theme browsers,
813
+ * theme backup/restore tools, or advanced theme customization interfaces.
814
+ *
815
+ * @example
816
+ * ```typescript
817
+ * const themeMarketplaceTab: ThemeListTab = {
818
+ * id: 'marketplace',
819
+ * label: 'Theme Marketplace',
820
+ * component: markRaw(MarketplaceComponent),
821
+ * priority: 20,
822
+ * permissions: ['plugin:theme-marketplace:view']
823
+ * };
824
+ * ```
825
+ */
826
+ interface ThemeListTab {
827
+ /**
828
+ * Unique identifier for the theme list tab.
829
+ * Should follow a namespaced pattern to avoid conflicts (e.g., 'plugin-name:tab-id').
830
+ */
831
+ id: string;
832
+ /**
833
+ * Display label for the tab.
834
+ * This text will be shown in the tab navigation.
835
+ */
836
+ label: string;
837
+ /**
838
+ * The Vue component that renders the tab content.
839
+ * Must be wrapped with `markRaw` to prevent Vue from making it reactive.
840
+ *
841
+ * @remarks
842
+ * The component should implement the theme-related functionality and integrate
843
+ * appropriately with the theme management system.
844
+ */
845
+ component: Raw<Component>;
846
+ /**
847
+ * Optional props to pass to the component.
848
+ * Can be used to configure behavior or provide additional context.
849
+ */
850
+ props?: Record<string, unknown>;
851
+ /**
852
+ * Optional array of permission identifiers required to view this tab.
853
+ * The tab will only be visible to users with at least one of these permissions.
854
+ */
855
+ permissions?: string[];
856
+ /**
857
+ * Priority for ordering multiple theme list tabs.
858
+ * Higher priority tabs appear first (leftmost) in the tab navigation.
859
+ */
860
+ priority: number;
861
+ }
862
+ //#endregion
863
+ //#region src/plugin/types/user-tab.d.ts
864
+ /**
865
+ * Defines a custom tab for the user detail page in the console.
866
+ *
867
+ * @remarks
868
+ * User tabs allow plugins to extend user management interfaces with custom
869
+ * functionality such as activity logs, custom user metadata, integration
870
+ * settings, or additional user management tools.
871
+ *
872
+ * @example
873
+ * ```typescript
874
+ * const activityTab: UserTab = {
875
+ * id: 'activity-log',
876
+ * label: 'Activity Log',
877
+ * component: markRaw(ActivityLogComponent),
878
+ * priority: 10,
879
+ * permissions: ['system:users:view-activity']
880
+ * };
881
+ * ```
882
+ */
883
+ interface UserTab {
884
+ /**
885
+ * Unique identifier for the user tab.
886
+ * Should follow a namespaced pattern to avoid conflicts (e.g., 'plugin-name:tab-id').
887
+ */
888
+ id: string;
889
+ /**
890
+ * Display label for the tab.
891
+ * This text will be shown in the tab navigation.
892
+ */
893
+ label: string;
894
+ /**
895
+ * The Vue component that renders the tab content.
896
+ * Must be wrapped with `markRaw` to prevent Vue from making it reactive.
897
+ *
898
+ * @remarks
899
+ * The component typically receives the user object as a prop and should
900
+ * implement user-related functionality or display user-specific information.
901
+ */
902
+ component: Raw<Component>;
903
+ /**
904
+ * Optional array of permission identifiers required to view this tab.
905
+ * The tab will only be visible to users with at least one of these permissions.
906
+ */
907
+ permissions?: string[];
908
+ /**
909
+ * Priority for ordering multiple user tabs.
910
+ * Higher priority tabs appear first (leftmost) in the tab navigation.
911
+ */
912
+ priority: number;
913
+ }
914
+ /**
915
+ * Defines a custom tab for the user profile page in the user center.
916
+ *
917
+ * @remarks
918
+ * User profile tabs allow plugins to extend the user-facing profile interface
919
+ * with custom sections such as social connections, preferences, achievements,
920
+ * subscription management, or personalization settings.
921
+ *
922
+ * @example
923
+ * ```typescript
924
+ * const preferencesTab: UserProfileTab = {
925
+ * id: 'preferences',
926
+ * label: 'Preferences',
927
+ * component: markRaw(PreferencesComponent),
928
+ * priority: 15
929
+ * };
930
+ * ```
931
+ */
932
+ interface UserProfileTab {
933
+ /**
934
+ * Unique identifier for the user profile tab.
935
+ * Should follow a namespaced pattern to avoid conflicts (e.g., 'plugin-name:tab-id').
936
+ */
937
+ id: string;
938
+ /**
939
+ * Display label for the tab.
940
+ * This text will be shown in the tab navigation.
941
+ */
942
+ label: string;
943
+ /**
944
+ * The Vue component that renders the tab content.
945
+ * Must be wrapped with `markRaw` to prevent Vue from making it reactive.
946
+ *
947
+ * @remarks
948
+ * The component should provide user-facing functionality that allows users
949
+ * to view or modify their own profile information or settings.
950
+ */
951
+ component: Raw<Component>;
952
+ /**
953
+ * Optional array of permission identifiers required to view this tab.
954
+ * The tab will only be visible to users with at least one of these permissions.
955
+ */
956
+ permissions?: string[];
957
+ /**
958
+ * Priority for ordering multiple user profile tabs.
959
+ * Higher priority tabs appear first (leftmost) in the tab navigation.
960
+ */
961
+ priority: number;
962
+ }
963
+ //#endregion
964
+ //#region src/plugin/types/ui-plugin-module.d.ts
965
+ /**
966
+ * Represents a route record that will be appended to a parent route.
967
+ * Used to extend existing routes with additional child routes.
968
+ */
969
+ interface RouteRecordAppend {
970
+ /**
971
+ * The name of the parent route to which this route will be appended.
972
+ */
973
+ parentName: NonNullable<RouteRecordName>;
974
+ /**
975
+ * The route definition to be appended as a child route.
976
+ */
977
+ route: RouteRecordRaw;
978
+ }
979
+ /**
980
+ * Defines extension points that plugins can hook into to extend Halo's functionality.
981
+ * Extension points follow a naming convention: `<feature>:<action>:<operation>`.
982
+ *
983
+ * @remarks
984
+ * Extension points are the primary mechanism for plugins to integrate with the Halo console and uc.
985
+ * Each extension point represents a specific place where plugins can inject custom functionality.
986
+ */
987
+ interface ExtensionPoint {
988
+ /**
989
+ * Creates custom attachment selector providers.
990
+ * Allows plugins to provide alternative attachment selection interfaces.
991
+ *
992
+ * @returns An array of attachment select providers or a promise resolving to them.
993
+ * @see https://docs.halo.run/developer-guide/plugin/extension-points/ui/attachment-selector-create
994
+ */
995
+ "attachment:selector:create"?: () => AttachmentSelectProvider[] | Promise<AttachmentSelectProvider[]>;
996
+ /**
997
+ * Creates custom editor providers.
998
+ * Allows plugins to register custom content editors.
999
+ *
1000
+ * @returns An array of editor providers or a promise resolving to them.
1001
+ * @see https://docs.halo.run/developer-guide/plugin/extension-points/ui/editor-create
1002
+ */
1003
+ "editor:create"?: () => EditorProvider[] | Promise<EditorProvider[]>;
1004
+ /**
1005
+ * Creates tabs for the plugin's own settings page.
1006
+ * Used to add configuration tabs within a plugin's detail view.
1007
+ *
1008
+ * @returns An array of plugin tabs or a promise resolving to them.
1009
+ * @see https://docs.halo.run/developer-guide/plugin/extension-points/ui/plugin-self-tabs-create
1010
+ */
1011
+ "plugin:self:tabs:create"?: () => PluginTab[] | Promise<PluginTab[]>;
1012
+ /**
1013
+ * Creates extensions for the default rich-text editor.
1014
+ * Allows plugins to extend the editor with custom nodes, marks, or functionality.
1015
+ *
1016
+ * @returns An array of editor extensions or a promise resolving to them.
1017
+ * @see https://docs.halo.run/developer-guide/plugin/extension-points/ui/default-editor-extension-create
1018
+ */
1019
+ "default:editor:extension:create"?: () => AnyExtension[] | Promise<AnyExtension[]>;
1020
+ /**
1021
+ * Creates comment subject reference providers.
1022
+ * Allows plugins to define custom content types that can receive comments.
1023
+ *
1024
+ * @returns An array of comment subject reference providers.
1025
+ * @see https://docs.halo.run/developer-guide/plugin/extension-points/ui/comment-subject-ref-create
1026
+ */
1027
+ "comment:subject-ref:create"?: () => CommentSubjectRefProvider[];
1028
+ /**
1029
+ * Replaces the default comment editor.
1030
+ * Allows plugins to provide a custom comment editing interface.
1031
+ *
1032
+ * @returns A comment editor provider or a promise resolving to it.
1033
+ */
1034
+ "comment:editor:replace"?: () => CommentEditorProvider | Promise<CommentEditorProvider>;
1035
+ /**
1036
+ * Replaces the default comment list item content display.
1037
+ * Allows plugins to customize how comment content is rendered in lists.
1038
+ *
1039
+ * @returns A comment content provider or a promise resolving to it.
1040
+ */
1041
+ "comment:list-item:content:replace"?: () => CommentContentProvider | Promise<CommentContentProvider>;
1042
+ /**
1043
+ * Creates tabs for the backup management page.
1044
+ * Allows plugins to add custom backup-related functionality.
1045
+ *
1046
+ * @returns An array of backup tabs or a promise resolving to them.
1047
+ * @see https://docs.halo.run/developer-guide/plugin/extension-points/ui/backup-tabs-create
1048
+ */
1049
+ "backup:tabs:create"?: () => BackupTab[] | Promise<BackupTab[]>;
1050
+ /**
1051
+ * Creates tabs for the plugin installation page.
1052
+ * Allows plugins to add custom installation methods or configurations.
1053
+ *
1054
+ * @returns An array of plugin installation tabs or a promise resolving to them.
1055
+ * @see https://docs.halo.run/developer-guide/plugin/extension-points/ui/plugin-installation-tabs-create
1056
+ */
1057
+ "plugin:installation:tabs:create"?: () => PluginInstallationTab[] | Promise<PluginInstallationTab[]>;
1058
+ /**
1059
+ * Creates custom operations for post list items.
1060
+ * Allows plugins to add action buttons or menu items to post list rows.
1061
+ *
1062
+ * @param post - A reactive reference to the post object.
1063
+ * @returns An array of operation items for the post.
1064
+ * @see https://docs.halo.run/developer-guide/plugin/extension-points/ui/post-list-item-operation-create
1065
+ */
1066
+ "post:list-item:operation:create"?: (post: Ref<ListedPost>) => OperationItem<ListedPost>[];
1067
+ /**
1068
+ * Creates custom operations for single page list items.
1069
+ * Allows plugins to add action buttons or menu items to single page list rows.
1070
+ *
1071
+ * @param singlePage - A reactive reference to the single page object.
1072
+ * @returns An array of operation items for the single page.
1073
+ * @see https://docs.halo.run/developer-guide/plugin/extension-points/ui/single-page-list-item-operation-create
1074
+ */
1075
+ "single-page:list-item:operation:create"?: (singlePage: Ref<ListedSinglePage>) => OperationItem<ListedSinglePage>[];
1076
+ /**
1077
+ * Creates custom operations for comment list items.
1078
+ * Allows plugins to add action buttons or menu items to comment list rows.
1079
+ *
1080
+ * @param comment - A reactive reference to the comment object.
1081
+ * @returns An array of operation items for the comment.
1082
+ * @see https://docs.halo.run/developer-guide/plugin/extension-points/ui/comment-list-item-operation-create
1083
+ */
1084
+ "comment:list-item:operation:create"?: (comment: Ref<ListedComment>) => OperationItem<ListedComment>[];
1085
+ /**
1086
+ * Creates custom operations for reply list items.
1087
+ * Allows plugins to add action buttons or menu items to reply list rows.
1088
+ *
1089
+ * @param reply - A reactive reference to the reply object.
1090
+ * @returns An array of operation items for the reply.
1091
+ * @see https://docs.halo.run/developer-guide/plugin/extension-points/ui/reply-list-item-operation-create
1092
+ */
1093
+ "reply:list-item:operation:create"?: (reply: Ref<ListedReply>) => OperationItem<ListedReply>[];
1094
+ /**
1095
+ * Creates custom operations for plugin list items.
1096
+ * Allows plugins to add action buttons or menu items to plugin list rows.
1097
+ *
1098
+ * @param plugin - A reactive reference to the plugin object.
1099
+ * @returns An array of operation items for the plugin.
1100
+ * @see https://docs.halo.run/developer-guide/plugin/extension-points/ui/plugin-list-item-operation-create
1101
+ */
1102
+ "plugin:list-item:operation:create"?: (plugin: Ref<Plugin>) => OperationItem<Plugin>[];
1103
+ /**
1104
+ * Creates custom operations for backup list items.
1105
+ * Allows plugins to add action buttons or menu items to backup list rows.
1106
+ *
1107
+ * @param backup - A reactive reference to the backup object.
1108
+ * @returns An array of operation items for the backup.
1109
+ * @see https://docs.halo.run/developer-guide/plugin/extension-points/ui/backup-list-item-operation-create
1110
+ */
1111
+ "backup:list-item:operation:create"?: (backup: Ref<Backup>) => OperationItem<Backup>[];
1112
+ /**
1113
+ * Creates custom operations for attachment list items.
1114
+ * Allows plugins to add action buttons or menu items to attachment list rows.
1115
+ *
1116
+ * @param attachment - A reactive reference to the attachment object.
1117
+ * @returns An array of operation items for the attachment.
1118
+ * @see https://docs.halo.run/developer-guide/plugin/extension-points/ui/attachment-list-item-operation-create
1119
+ */
1120
+ "attachment:list-item:operation:create"?: (attachment: Ref<Attachment>) => OperationItem<Attachment>[];
1121
+ /**
1122
+ * Creates custom fields for plugin list items.
1123
+ * Allows plugins to add custom columns or metadata fields to the plugin list display.
1124
+ *
1125
+ * @param plugin - A reactive reference to the plugin object.
1126
+ * @returns An array of entity field items for the plugin.
1127
+ * @see https://docs.halo.run/developer-guide/plugin/extension-points/ui/plugin-list-item-field-create
1128
+ */
1129
+ "plugin:list-item:field:create"?: (plugin: Ref<Plugin>) => EntityFieldItem[];
1130
+ /**
1131
+ * Creates custom fields for post list items.
1132
+ * Allows plugins to add custom columns or metadata fields to the post list display.
1133
+ *
1134
+ * @param post - A reactive reference to the post object.
1135
+ * @returns An array of entity field items for the post.
1136
+ * @see https://docs.halo.run/developer-guide/plugin/extension-points/ui/post-list-item-field-create
1137
+ */
1138
+ "post:list-item:field:create"?: (post: Ref<ListedPost>) => EntityFieldItem[];
1139
+ /**
1140
+ * Creates custom fields for single page list items.
1141
+ * Allows plugins to add custom columns or metadata fields to the single page list display.
1142
+ *
1143
+ * @param singlePage - A reactive reference to the single page object.
1144
+ * @returns An array of entity field items for the single page.
1145
+ * @see https://docs.halo.run/developer-guide/plugin/extension-points/ui/single-page-list-item-field-create
1146
+ */
1147
+ "single-page:list-item:field:create"?: (singlePage: Ref<ListedSinglePage>) => EntityFieldItem[];
1148
+ /**
1149
+ * Creates tabs for the theme list page.
1150
+ * Allows plugins to add custom theme management or configuration sections.
1151
+ *
1152
+ * @returns An array of theme list tabs or a promise resolving to them.
1153
+ * @see https://docs.halo.run/developer-guide/plugin/extension-points/ui/theme-list-tabs-create
1154
+ */
1155
+ "theme:list:tabs:create"?: () => ThemeListTab[] | Promise<ThemeListTab[]>;
1156
+ /**
1157
+ * Creates custom operations for theme list items.
1158
+ * Allows plugins to add action buttons or menu items to theme list rows.
1159
+ *
1160
+ * @param theme - A reactive reference to the theme object.
1161
+ * @returns An array of operation items for the theme.
1162
+ * @see https://docs.halo.run/developer-guide/plugin/extension-points/ui/theme-list-item-operation-create
1163
+ */
1164
+ "theme:list-item:operation:create"?: (theme: Ref<Theme>) => OperationItem<Theme>[];
1165
+ /**
1166
+ * Creates tabs for the user detail page in the console.
1167
+ * Allows plugins to add custom user management sections.
1168
+ *
1169
+ * @returns An array of user tabs or a promise resolving to them.
1170
+ * @see https://docs.halo.run/developer-guide/plugin/extension-points/ui/user-detail-tabs-create
1171
+ */
1172
+ "user:detail:tabs:create"?: () => UserTab[] | Promise<UserTab[]>;
1173
+ /**
1174
+ * Creates tabs for the user profile page in the user center.
1175
+ * Allows plugins to extend user profile settings and information.
1176
+ *
1177
+ * @returns An array of user profile tabs or a promise resolving to them.
1178
+ * @see https://docs.halo.run/developer-guide/plugin/extension-points/ui/uc-user-profile-tabs-create
1179
+ */
1180
+ "uc:user:profile:tabs:create"?: () => UserProfileTab[] | Promise<UserProfileTab[]>;
1181
+ /**
1182
+ * Creates custom dashboard widgets for the console.
1183
+ * Allows plugins to add informational or interactive widgets to the main dashboard.
1184
+ *
1185
+ * @returns An array of dashboard widget definitions or a promise resolving to them.
1186
+ * @see https://docs.halo.run/developer-guide/plugin/extension-points/ui/dashboard-widgets#consoledashboardwidgets
1187
+ */
1188
+ "console:dashboard:widgets:create"?: () => DashboardWidgetDefinition[] | Promise<DashboardWidgetDefinition[]>;
1189
+ /**
1190
+ * Creates quick action items for internal dashboard widgets.
1191
+ * Allows plugins to add quick access buttons or shortcuts to dashboard widgets.
1192
+ *
1193
+ * @returns An array of dashboard widget quick action items or a promise resolving to them.
1194
+ * @see https://docs.halo.run/developer-guide/plugin/extension-points/ui/dashboard-widgets#consoledashboardwidgetsinternalquick-actionitem
1195
+ */
1196
+ "console:dashboard:widgets:internal:quick-action:item:create"?: () => DashboardWidgetQuickActionItem[] | Promise<DashboardWidgetQuickActionItem[]>;
1197
+ }
1198
+ /**
1199
+ * Defines the structure of a UI plugin module for the Halo console and user center.
1200
+ *
1201
+ * @see https://docs.halo.run/developer-guide/plugin/basics/ui/entry
1202
+ */
1203
+ interface PluginModule {
1204
+ /**
1205
+ * Components that will be globally registered when the plugin is activated.
1206
+ * These components can be used throughout the Halo console without explicit imports.
1207
+ *
1208
+ * @remarks
1209
+ * The key is the component name (in kebab-case is recommended),
1210
+ * and the value is the Vue component definition.
1211
+ */
1212
+ components?: Record<string, Component>;
1213
+ /**
1214
+ * Console routes that will be registered when the plugin is activated.
1215
+ * Can be either standalone routes or routes that append to existing parent routes.
1216
+ *
1217
+ * @remarks
1218
+ * - Use `RouteRecordRaw[]` for standalone routes
1219
+ * - Use `RouteRecordAppend[]` to append routes to existing parent routes
1220
+ * @see https://docs.halo.run/developer-guide/plugin/api-reference/ui/route
1221
+ */
1222
+ routes?: RouteRecordRaw[] | RouteRecordAppend[];
1223
+ /**
1224
+ * User center routes that will be registered when the plugin is activated.
1225
+ * These routes are specifically for the user-facing area (UC).
1226
+ *
1227
+ * @remarks
1228
+ * - Use `RouteRecordRaw[]` for standalone routes
1229
+ * - Use `RouteRecordAppend[]` to append routes to existing parent routes
1230
+ * @see https://docs.halo.run/developer-guide/plugin/api-reference/ui/route
1231
+ */
1232
+ ucRoutes?: RouteRecordRaw[] | RouteRecordAppend[];
1233
+ /**
1234
+ * Extension points that the plugin hooks into.
1235
+ * This is where plugins register their custom functionality to extend Halo.
1236
+ *
1237
+ * @remarks
1238
+ * Each extension point can provide custom functionality that integrates
1239
+ * with specific parts of the Halo console.
1240
+ * @see https://docs.halo.run/developer-guide/plugin/extension-points/ui
1241
+ */
1242
+ extensionPoints?: ExtensionPoint;
1243
+ }
1244
+ //#endregion
1245
+ //#region src/plugin/types/ui-plugin-entry.d.ts
1246
+ /**
1247
+ * Helper function to define a Halo UI plugin module with type safety.
1248
+ *
1249
+ * @param plugin - The plugin module definition containing components, routes, and extension points.
1250
+ * @returns The same plugin module, properly typed for Halo's plugin system.
1251
+ *
1252
+ * @remarks
1253
+ * This function is a type-safe wrapper that provides IDE support and type checking
1254
+ * for plugin definitions. It doesn't perform any runtime transformations, but ensures
1255
+ * that the plugin structure conforms to the expected interface.
1256
+ *
1257
+ * @example
1258
+ * ```typescript
1259
+ * import { definePlugin } from "@halo-dev/ui-shared";
1260
+ * import { markRaw } from "vue";
1261
+ *
1262
+ * export default definePlugin({
1263
+ * components: {
1264
+ * "my-widget": MyWidgetComponent
1265
+ * },
1266
+ * routes: [
1267
+ * {
1268
+ * path: "/my-plugin",
1269
+ * name: "MyPlugin",
1270
+ * component: MyPluginView
1271
+ * }
1272
+ * ],
1273
+ * extensionPoints: {
1274
+ * "post:list-item:operation:create": (post) => [
1275
+ * {
1276
+ * priority: 10,
1277
+ * component: markRaw(VButton),
1278
+ * label: "Custom Action",
1279
+ * action: () => {
1280
+ * console.log("Action triggered");
1281
+ * }
1282
+ * }
1283
+ * ]
1284
+ * }
1285
+ * });
1286
+ * ```
1287
+ */
1288
+ declare function definePlugin(plugin: PluginModule): PluginModule;
1289
+ //#endregion
1290
+ //#region src/stores/types/slug.d.ts
1291
+ type ModeType = "UUID" | "shortUUID" | "timestamp" | "generateByTitle";
1292
+ declare enum FormType {
1293
+ TAG = "Tag",
1294
+ CATEGORY = "Category",
1295
+ POST = "Post",
1296
+ SINGLE_PAGE = "SinglePage",
1297
+ }
1298
+ //#endregion
1299
+ //#region src/stores/types/actuator.d.ts
1300
+ interface GlobalInfo {
1301
+ externalUrl: string;
1302
+ timeZone: string;
1303
+ locale: string;
1304
+ allowComments: boolean;
1305
+ allowAnonymousComments: boolean;
1306
+ allowRegistration: boolean;
1307
+ favicon?: string;
1308
+ postSlugGenerationStrategy: ModeType;
1309
+ mustVerifyEmailOnRegistration: boolean;
1310
+ siteTitle: string;
1311
+ }
1312
+ interface Info {
1313
+ git?: Git;
1314
+ build?: Build;
1315
+ java: Java;
1316
+ os: Os;
1317
+ database: Database;
1318
+ }
1319
+ interface Database {
1320
+ name: string;
1321
+ version: string;
1322
+ }
1323
+ interface Commit {
1324
+ id: string;
1325
+ time: Date;
1326
+ }
1327
+ interface Git {
1328
+ branch: string;
1329
+ commit: Commit;
1330
+ }
1331
+ interface Build {
1332
+ artifact: string;
1333
+ name: string;
1334
+ time: Date;
1335
+ version: string;
1336
+ group: string;
1337
+ }
1338
+ interface Vendor {
1339
+ name: string;
1340
+ version: string;
1341
+ }
1342
+ interface Runtime {
1343
+ name: string;
1344
+ version: string;
1345
+ }
1346
+ interface Jvm {
1347
+ name: string;
1348
+ vendor: string;
1349
+ version: string;
1350
+ }
1351
+ interface Java {
1352
+ version: string;
1353
+ vendor: Vendor;
1354
+ runtime: Runtime;
1355
+ jvm: Jvm;
1356
+ }
1357
+ interface Os {
1358
+ name: string;
1359
+ version: string;
1360
+ arch: string;
1361
+ }
1362
+ interface Tag {
1363
+ key: string;
1364
+ value: string;
1365
+ }
1366
+ interface StartupStep {
1367
+ name: string;
1368
+ id: number;
1369
+ tags: Tag[];
1370
+ parentId?: number;
1371
+ }
1372
+ interface Event {
1373
+ endTime: Date;
1374
+ duration: string;
1375
+ startTime: Date;
1376
+ startupStep: StartupStep;
1377
+ }
1378
+ interface Timeline {
1379
+ startTime: Date;
1380
+ events: Event[];
1381
+ }
1382
+ interface Startup {
1383
+ springBootVersion: string;
1384
+ timeline: Timeline;
1385
+ }
1386
+ //#endregion
1387
+ //#region src/stores/index.d.ts
1388
+ /**
1389
+ * Collection of Pinia stores for shared application state.
1390
+ *
1391
+ * @remarks
1392
+ * These stores provide centralized state management for common data
1393
+ * that needs to be accessed across multiple components and plugins.
1394
+ */
1395
+ declare const stores: {
1396
+ /**
1397
+ * Store for managing the current authenticated user's information.
1398
+ *
1399
+ * @remarks
1400
+ * This store provides access to the current user's details and authentication state.
1401
+ * It includes helper methods to fetch the latest user information from the server.
1402
+ *
1403
+ * @example
1404
+ * ```typescript
1405
+ * import { stores } from "@halo-dev/ui-shared";
1406
+ *
1407
+ * const userStore = stores.currentUser();
1408
+ *
1409
+ * // Fetch current user info
1410
+ * await userStore.fetchCurrentUser();
1411
+ *
1412
+ * // Access user data
1413
+ * console.log(userStore.currentUser?.user.metadata.name);
1414
+ * console.log(userStore.isAnonymous); // Check if user is anonymous
1415
+ * ```
1416
+ */
1417
+ currentUser: pinia0.StoreDefinition<"currentUser", Pick<{
1418
+ currentUser: vue0.Ref<DetailedUser | undefined, DetailedUser | undefined>;
1419
+ isAnonymous: vue0.Ref<boolean, boolean>;
1420
+ fetchCurrentUser: () => Promise<void>;
1421
+ }, "currentUser" | "isAnonymous">, Pick<{
1422
+ currentUser: vue0.Ref<DetailedUser | undefined, DetailedUser | undefined>;
1423
+ isAnonymous: vue0.Ref<boolean, boolean>;
1424
+ fetchCurrentUser: () => Promise<void>;
1425
+ }, never>, Pick<{
1426
+ currentUser: vue0.Ref<DetailedUser | undefined, DetailedUser | undefined>;
1427
+ isAnonymous: vue0.Ref<boolean, boolean>;
1428
+ fetchCurrentUser: () => Promise<void>;
1429
+ }, "fetchCurrentUser">>;
1430
+ /**
1431
+ * Store for managing global system information and configuration.
1432
+ *
1433
+ * @remarks
1434
+ * This store provides access to global system settings, configuration,
1435
+ * and metadata that are shared across the entire application.
1436
+ *
1437
+ * @example
1438
+ * ```typescript
1439
+ * import { stores } from "@halo-dev/ui-shared";
1440
+ *
1441
+ * const globalInfoStore = stores.globalInfo();
1442
+ *
1443
+ * // Fetch global info
1444
+ * await globalInfoStore.fetchGlobalInfo();
1445
+ *
1446
+ * // Access global settings
1447
+ * console.log(globalInfoStore.globalInfo?.externalUrl);
1448
+ * console.log(globalInfoStore.globalInfo?.siteTitle);
1449
+ * console.log(globalInfoStore.globalInfo?.allowRegistration);
1450
+ * ```
1451
+ */
1452
+ globalInfo: pinia0.StoreDefinition<"global-info", Pick<{
1453
+ globalInfo: vue0.Ref<GlobalInfo | undefined, GlobalInfo | undefined>;
1454
+ fetchGlobalInfo: () => Promise<void>;
1455
+ }, "globalInfo">, Pick<{
1456
+ globalInfo: vue0.Ref<GlobalInfo | undefined, GlobalInfo | undefined>;
1457
+ fetchGlobalInfo: () => Promise<void>;
1458
+ }, never>, Pick<{
1459
+ globalInfo: vue0.Ref<GlobalInfo | undefined, GlobalInfo | undefined>;
1460
+ fetchGlobalInfo: () => Promise<void>;
1461
+ }, "fetchGlobalInfo">>;
1462
+ };
1463
+ //#endregion
1464
+ //#region src/types/menus.d.ts
1465
+ type CoreMenuGroupId = "dashboard" | "content" | "interface" | "system" | "tool";
1466
+ interface MenuGroupType {
1467
+ id: CoreMenuGroupId | string;
1468
+ name?: string;
1469
+ priority: number;
1470
+ items?: MenuItemType[];
1471
+ }
1472
+ interface MenuItemType {
1473
+ name: string;
1474
+ path: string;
1475
+ mobile?: boolean;
1476
+ icon?: Component;
1477
+ meta?: Record<string, unknown>;
1478
+ children?: MenuItemType[];
1479
+ }
1480
+ //#endregion
1481
+ //#region src/utils/attachment.d.ts
1482
+ /**
1483
+ * Mapping of thumbnail size enums to their corresponding widths in pixels
1484
+ *
1485
+ * @remarks
1486
+ * - XL: 1600px - Extra large thumbnails
1487
+ * - L: 1200px - Large thumbnails
1488
+ * - M: 800px - Medium thumbnails
1489
+ * - S: 400px - Small thumbnails
1490
+ */
1491
+ declare const THUMBNAIL_WIDTH_MAP: Record<GetThumbnailByUriSizeEnum, number>;
1492
+ declare class AttachmentUtils {
1493
+ /**
1494
+ * Generates a thumbnail URL for the given image URL with the specified size
1495
+ *
1496
+ * @param url - The original image URL (can be absolute, relative, or external)
1497
+ * @param size - The desired thumbnail size (XL, L, M, or S)
1498
+ * @returns The thumbnail URL with width parameter, or original URL if size is invalid
1499
+ *
1500
+ * @remarks
1501
+ * This method handles three scenarios:
1502
+ * 1. If URL starts with current origin: Appends `?width={size}` query parameter
1503
+ * 2. If URL is a relative path (starts with "/"): Appends `?width={size}` query parameter
1504
+ * 3. If URL is external: Routes through Halo's thumbnail API endpoint
1505
+ *
1506
+ * @example
1507
+ * ```ts
1508
+ * import { utils } from "@halo-dev/ui-shared"
1509
+ *
1510
+ * // Local image
1511
+ * utils.attachment.getThumbnailUrl("/uploads/image.jpg", "M");
1512
+ * // Returns: "/uploads/image.jpg?width=800"
1513
+ *
1514
+ * // Same origin image
1515
+ * utils.attachment.getThumbnailUrl("https://example.com/image.jpg", "S");
1516
+ * // Returns: "https://example.com/image.jpg?width=400" (if current origin is example.com)
1517
+ *
1518
+ * // External image
1519
+ * utils.attachment.getThumbnailUrl("https://external.com/image.jpg", "L");
1520
+ * // Returns: "/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fexternal.com%2Fimage.jpg&width=1200"
1521
+ * ```
1522
+ */
1523
+ getThumbnailUrl(url: string, size: GetThumbnailByUriSizeEnum): string;
1524
+ /**
1525
+ * Extracts the URL from an attachment-like object
1526
+ *
1527
+ * @param attachment - The attachment object (can be a string URL, Attachment object, or AttachmentSimple)
1528
+ * @returns The URL string extracted from the attachment
1529
+ * @throws {Error} When the attachment type is invalid or unrecognized
1530
+ *
1531
+ * @remarks
1532
+ * This method handles three types of attachments:
1533
+ * 1. String: Returns the string directly as URL
1534
+ * 2. Attachment object (with "spec"): Returns the permalink from status
1535
+ * 3. AttachmentSimple (with "url"): Returns the url property
1536
+ *
1537
+ * @example
1538
+ * ```ts
1539
+ * import { utils } from "@halo-dev/ui-shared"
1540
+ *
1541
+ * // String URL
1542
+ * utils.attachment.getUrl("https://example.com/image.jpg");
1543
+ * // Returns: "https://example.com/image.jpg"
1544
+ *
1545
+ * // Attachment object
1546
+ * utils.attachment.getUrl(attachmentObject);
1547
+ * // Returns: attachmentObject.status?.permalink
1548
+ *
1549
+ * // AttachmentSimple object
1550
+ * utils.attachment.getUrl({ url: "https://example.com/image.jpg" });
1551
+ * // Returns: "https://example.com/image.jpg"
1552
+ * ```
1553
+ */
1554
+ getUrl(attachment: AttachmentLike): string | undefined;
1555
+ /**
1556
+ * Converts an attachment-like object to a simplified attachment format
1557
+ *
1558
+ * @param attachment - The attachment object to convert (can be a string URL, Attachment object, or AttachmentSimple)
1559
+ * @returns A simplified attachment object with url, alt, and mediaType properties, or undefined
1560
+ * @throws {Error} When the attachment type is invalid or unrecognized
1561
+ *
1562
+ * @remarks
1563
+ * This method normalizes different attachment formats into a consistent AttachmentSimple structure:
1564
+ * 1. String: Converts to object with only url property
1565
+ * 2. Attachment object (with "spec"): Extracts permalink, displayName, and mediaType
1566
+ * 3. AttachmentSimple (with "url"): Returns as-is since it's already in the correct format
1567
+ *
1568
+ * @example
1569
+ * ```ts
1570
+ * import { utils } from "@halo-dev/ui-shared"
1571
+ *
1572
+ * // String URL
1573
+ * utils.attachment.convertToSimple("https://example.com/image.jpg");
1574
+ * // Returns: { url: "https://example.com/image.jpg" }
1575
+ *
1576
+ * // Attachment object
1577
+ * utils.attachment.convertToSimple(attachmentObject);
1578
+ * // Returns: {
1579
+ * // url: attachmentObject.status?.permalink || "",
1580
+ * // alt: attachmentObject.spec.displayName,
1581
+ * // mediaType: attachmentObject.spec.mediaType
1582
+ * // }
1583
+ *
1584
+ * // AttachmentSimple object
1585
+ * utils.attachment.convertToSimple({ url: "https://example.com/image.jpg", alt: "Image" });
1586
+ * // Returns: { url: "https://example.com/image.jpg", alt: "Image" }
1587
+ * ```
1588
+ */
1589
+ convertToSimple(attachment: AttachmentLike): AttachmentSimple | undefined;
1590
+ }
1591
+ //#endregion
1592
+ //#region src/utils/date.d.ts
1593
+ declare class DateUtils {
1594
+ readonly dayjs: typeof _dayjs;
1595
+ constructor();
1596
+ /**
1597
+ * Formats a date to a string according to the specified format
1598
+ *
1599
+ * @param date - The date to format (string, Date object, or null/undefined)
1600
+ * @param format - The format string (defaults to "YYYY-MM-DD HH:mm")
1601
+ * @returns The formatted date string, or empty string if date is null/undefined
1602
+ *
1603
+ * @example
1604
+ * ```ts
1605
+ * import { utils } from "@halo-dev/ui-shared"
1606
+ * utils.date.format(new Date()); // "2025-10-22 14:30"
1607
+ * utils.date.format("2025-10-22", "YYYY/MM/DD"); // "2025/10/22"
1608
+ * ```
1609
+ */
1610
+ format(date: string | Date | undefined | null, format?: string): string;
1611
+ /**
1612
+ * Converts a date to ISO 8601 format string
1613
+ *
1614
+ * @param date - The date to convert (string, Date object, or null/undefined)
1615
+ * @returns The ISO 8601 formatted date string, or empty string if date is null/undefined
1616
+ *
1617
+ * @example
1618
+ * ```ts
1619
+ * import { utils } from "@halo-dev/ui-shared"
1620
+ * utils.date.toISOString(new Date("2025-10-22")); // "2025-10-22T00:00:00.000Z"
1621
+ * ```
1622
+ */
1623
+ toISOString(date: string | Date | undefined | null): string;
1624
+ /**
1625
+ * Converts a date to HTML5 datetime-local input format
1626
+ *
1627
+ * @param date - The date to convert (string, Date object, or null/undefined)
1628
+ * @returns The datetime-local formatted string (YYYY-MM-DDTHH:mm), or empty string if date is null/undefined
1629
+ *
1630
+ * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/datetime-local#the_y10k_problem_often_client-side
1631
+ *
1632
+ * @example
1633
+ * ```ts
1634
+ * import { utils } from "@halo-dev/ui-shared"
1635
+ * utils.date.toDatetimeLocal(new Date("2025-10-22 14:30")); // "2025-10-22T14:30"
1636
+ * ```
1637
+ */
1638
+ toDatetimeLocal(date: string | Date | undefined | null): string;
1639
+ /**
1640
+ * Gets the relative time from now to the specified date
1641
+ *
1642
+ * @param date - The target date (string, Date object, or null/undefined)
1643
+ * @returns A human-readable relative time string (e.g., "in 2 hours", "3 days ago"), or undefined if date is null/undefined
1644
+ *
1645
+ * @example
1646
+ * ```ts
1647
+ * import { utils } from "@halo-dev/ui-shared"
1648
+ * // Assuming now is 2025-10-22
1649
+ * utils.date.timeAgo("2025-10-23"); // "in a day"
1650
+ * utils.date.timeAgo("2025-10-21"); // "a day ago"
1651
+ * utils.date.timeAgo("2025-11-22"); // "in a month"
1652
+ * ```
1653
+ */
1654
+ timeAgo(date: string | Date | undefined | null): string | undefined;
1655
+ /**
1656
+ * Sets the locale for date formatting
1657
+ *
1658
+ * @param locale - The locale code (e.g., "en", "zh", "en-US", "zh-CN", "zh-TW")
1659
+ *
1660
+ * @remarks
1661
+ * Supported locales:
1662
+ * - "en" or "en-US" → English
1663
+ * - "zh" or "zh-CN" → Simplified Chinese
1664
+ * - "zh-TW" → Traditional Chinese
1665
+ *
1666
+ * Defaults to English if the locale is not supported.
1667
+ *
1668
+ * @example
1669
+ * ```ts
1670
+ * import { utils } from "@halo-dev/ui-shared"
1671
+ * utils.date.setLocale("zh-CN");
1672
+ * utils.date.timeAgo("2025-10-21"); // "1 天前"
1673
+ * utils.date.setLocale("en");
1674
+ * utils.date.timeAgo("2025-10-21"); // "a day ago"
1675
+ * ```
1676
+ */
1677
+ setLocale(locale: string): void;
1678
+ }
1679
+ // See https://github.com/iamkun/dayjs/issues/364
1680
+ declare module "dayjs" {
1681
+ interface Dayjs {
1682
+ fromNow(withoutSuffix?: boolean): string;
1683
+ from(compared: _dayjs.ConfigType, withoutSuffix?: boolean): string;
1684
+ toNow(withoutSuffix?: boolean): string;
1685
+ to(compared: _dayjs.ConfigType, withoutSuffix?: boolean): string;
1686
+ }
1687
+ }
1688
+ declare module "dayjs" {
1689
+ interface Dayjs {
1690
+ tz(timezone?: string, keepLocalTime?: boolean): _dayjs.Dayjs;
1691
+ offsetName(type?: "short" | "long"): string | undefined;
1692
+ }
1693
+ interface DayjsTimezone {
1694
+ (date?: _dayjs.ConfigType, timezone?: string): _dayjs.Dayjs;
1695
+ (date: _dayjs.ConfigType, format: string, timezone?: string): _dayjs.Dayjs;
1696
+ guess(): string;
1697
+ setDefault(timezone?: string): void;
1698
+ }
1699
+ }
1700
+ declare module "dayjs" {
1701
+ interface Dayjs {
1702
+ utc(keepLocalTime?: boolean): _dayjs.Dayjs;
1703
+ local(): _dayjs.Dayjs;
1704
+ isUTC(): boolean;
1705
+ utcOffset(offset: number | string, keepLocalTime?: boolean): _dayjs.Dayjs;
1706
+ }
1707
+ function utc(config?: _dayjs.ConfigType, format?: string, strict?: boolean): _dayjs.Dayjs;
1708
+ }
1709
+ //#endregion
1710
+ //#region src/utils/id.d.ts
1711
+ /**
1712
+ * Utilities for generating unique identifiers that remain sortable over time.
1713
+ *
1714
+ * Relies on the `uuid` package for RFC 4122 compliant UUID generation.
1715
+ */
1716
+ declare class IdUtils {
1717
+ /**
1718
+ * Generates a RFC 4122 version 7 UUID string using the `uuid` package.
1719
+ *
1720
+ * UUID v7 keeps the order of creation roughly aligned with chronological order,
1721
+ * making it a good fit for persistence stores or log entries that benefit from
1722
+ * monotonic sorting.
1723
+ *
1724
+ * @returns A lowercase UUIDv7 string such as "018f1c2e-4fcb-7d04-9f21-1a2b3c4d5e6f".
1725
+ */
1726
+ uuid(): string;
1727
+ }
1728
+ //#endregion
1729
+ //#region src/utils/permission.d.ts
1730
+ /**
1731
+ * Utility class for checking user permissions.
1732
+ */
1733
+ declare class PermissionUtils {
1734
+ private userPermissions?;
1735
+ /**
1736
+ * Creates a new PermissionUtils instance.
1737
+ * @param userPermissions - Array of permissions that the user has
1738
+ */
1739
+ constructor(userPermissions?: Array<string>);
1740
+ /**
1741
+ * Checks if the user has the required permissions.
1742
+ *
1743
+ * @param permissions - Array of permissions to check against user's permissions
1744
+ * @param any - If true, returns true when ANY of the required permissions match.
1745
+ * If false, returns true only when ALL required permissions match.
1746
+ * Defaults to true.
1747
+ * @returns true if the permission check passes, false otherwise
1748
+ *
1749
+ * @throws Error if user permissions are not set
1750
+ *
1751
+ * @example
1752
+ * ```ts
1753
+ * import { utils } from "@halo-dev/ui-shared"
1754
+ *
1755
+ * // Check if user has any of the permissions
1756
+ * utils.permission.has(['core:posts:manage'], true);
1757
+ *
1758
+ * // Check if user has all of the permissions
1759
+ * utils.permission.has(['core:posts:view', 'core:attachments:view'], false);
1760
+ * ```
1761
+ */
1762
+ has(permissions: Array<string>, any?: boolean): boolean;
1763
+ /**
1764
+ * Retrieves the current user permissions.
1765
+ * @returns Array of user permissions or undefined if not set
1766
+ */
1767
+ getUserPermissions(): Array<string> | undefined;
1768
+ /**
1769
+ * Updates the user permissions.
1770
+ * @param userPermissions - Array of permissions to set for the user
1771
+ */
1772
+ setUserPermissions(userPermissions: Array<string>): void;
1773
+ }
1774
+ //#endregion
1775
+ //#region src/utils/index.d.ts
1776
+ declare const utils: {
1777
+ date: DateUtils;
1778
+ attachment: AttachmentUtils;
1779
+ permission: PermissionUtils;
1780
+ id: IdUtils;
1781
+ };
1782
+ //#endregion
1783
+ export { AttachmentLike, AttachmentSelectProvider, AttachmentSimple, BackupTab, Build, CommentContentProvider, CommentEditorProvider, CommentSubjectRefProvider, CommentSubjectRefResult, Commit, CoreMenuGroupId, DashboardResponsiveLayout, DashboardWidget, DashboardWidgetDefinition, DashboardWidgetQuickActionItem, Database, EditorProvider, EntityFieldItem, Event, ExtensionPoint, FormType, Git, GlobalInfo, Info, Java, Jvm, MenuGroupType, MenuItemType, ModeType, OperationItem, Os, PluginInstallationTab, PluginModule, PluginTab, RouteRecordAppend, Runtime, Startup, StartupStep, THUMBNAIL_WIDTH_MAP, Tag, ThemeListTab, Timeline, UserProfileTab, UserTab, Vendor, definePlugin, events, stores, utils };