@adminforth/dashboard 1.5.0 → 1.7.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 (58) hide show
  1. package/custom/api/dashboardApi.ts +137 -1
  2. package/custom/model/dashboard.types.ts +32 -22
  3. package/custom/package.json +1 -0
  4. package/custom/pnpm-lock.yaml +31 -0
  5. package/custom/runtime/DashboardRuntime.vue +9 -15
  6. package/custom/runtime/YamlConfigEditor.vue +109 -0
  7. package/custom/skills/adminforth-dashboard/SKILL.md +66 -10
  8. package/custom/widgets/KpiCardWidget.vue +172 -9
  9. package/custom/widgets/chart/ChartWidget.vue +5 -5
  10. package/custom/widgets/registry.ts +4 -4
  11. package/dist/custom/api/dashboardApi.d.ts +46 -1
  12. package/dist/custom/api/dashboardApi.js +90 -0
  13. package/dist/custom/api/dashboardApi.ts +137 -1
  14. package/dist/custom/model/dashboard.types.d.ts +30 -14
  15. package/dist/custom/model/dashboard.types.js +2 -2
  16. package/dist/custom/model/dashboard.types.ts +32 -22
  17. package/dist/custom/package.json +1 -0
  18. package/dist/custom/pnpm-lock.yaml +31 -0
  19. package/dist/custom/queries/useDashboardConfig.d.ts +106 -104
  20. package/dist/custom/queries/useWidgetData.d.ts +106 -104
  21. package/dist/custom/runtime/DashboardRuntime.vue +9 -15
  22. package/dist/custom/runtime/YamlConfigEditor.vue +109 -0
  23. package/dist/custom/skills/adminforth-dashboard/SKILL.md +66 -10
  24. package/dist/custom/widgets/KpiCardWidget.vue +172 -9
  25. package/dist/custom/widgets/chart/ChartWidget.vue +5 -5
  26. package/dist/custom/widgets/registry.js +4 -4
  27. package/dist/custom/widgets/registry.ts +4 -4
  28. package/dist/endpoint/widgets.js +99 -14
  29. package/dist/schema/api.d.ts +11426 -1634
  30. package/dist/schema/api.js +118 -21
  31. package/dist/schema/widget.d.ts +425 -1980
  32. package/dist/schema/widget.js +13 -374
  33. package/dist/schema/widgets/charts.d.ts +1689 -0
  34. package/dist/schema/widgets/charts.js +92 -0
  35. package/dist/schema/widgets/common.d.ts +275 -0
  36. package/dist/schema/widgets/common.js +171 -0
  37. package/dist/schema/widgets/gauge-card.d.ts +172 -0
  38. package/dist/schema/widgets/gauge-card.js +28 -0
  39. package/dist/schema/widgets/kpi-card.d.ts +212 -0
  40. package/dist/schema/widgets/kpi-card.js +43 -0
  41. package/dist/schema/widgets/pivot-table.d.ts +196 -0
  42. package/dist/schema/widgets/pivot-table.js +17 -0
  43. package/dist/schema/widgets/table.d.ts +130 -0
  44. package/dist/schema/widgets/table.js +12 -0
  45. package/dist/services/widgetDataService.js +96 -2
  46. package/endpoint/widgets.ts +173 -26
  47. package/package.json +1 -1
  48. package/schema/api.ts +148 -22
  49. package/schema/widget.ts +43 -425
  50. package/schema/widgets/charts.ts +113 -0
  51. package/schema/widgets/common.ts +194 -0
  52. package/schema/widgets/gauge-card.ts +34 -0
  53. package/schema/widgets/kpi-card.ts +49 -0
  54. package/schema/widgets/pivot-table.ts +24 -0
  55. package/schema/widgets/table.ts +18 -0
  56. package/services/widgetDataService.ts +129 -3
  57. package/shims-vue.d.ts +11 -0
  58. package/tsconfig.json +3 -1
@@ -50,6 +50,12 @@ export declare function useWidgetData(slug: Ref<string>, widgetId: Ref<string>,
50
50
  calc: string;
51
51
  as: string;
52
52
  })[] | undefined;
53
+ sparkline?: {
54
+ field: string;
55
+ grain: import("../model/dashboard.types.js").TimeGrain;
56
+ as: string;
57
+ fill_missing?: Record<string, import("../model/dashboard.types.js").JsonValue> | undefined;
58
+ } | undefined;
53
59
  filters?: any;
54
60
  group_by?: (string | {
55
61
  field: string;
@@ -63,16 +69,6 @@ export declare function useWidgetData(slug: Ref<string>, widgetId: Ref<string>,
63
69
  }[] | undefined;
64
70
  limit?: number | undefined;
65
71
  offset?: number | undefined;
66
- time_series?: {
67
- field: string;
68
- grain: import("../model/dashboard.types.js").TimeGrain;
69
- timezone?: string | undefined;
70
- } | undefined;
71
- period?: {
72
- field: string;
73
- gte?: any;
74
- lt?: any;
75
- } | undefined;
76
72
  bucket?: {
77
73
  field: string;
78
74
  buckets: {
@@ -154,6 +150,12 @@ export declare function useWidgetData(slug: Ref<string>, widgetId: Ref<string>,
154
150
  calc: string;
155
151
  as: string;
156
152
  })[] | undefined;
153
+ sparkline?: {
154
+ field: string;
155
+ grain: import("../model/dashboard.types.js").TimeGrain;
156
+ as: string;
157
+ fill_missing?: Record<string, import("../model/dashboard.types.js").JsonValue> | undefined;
158
+ } | undefined;
157
159
  filters?: any;
158
160
  group_by?: (string | {
159
161
  field: string;
@@ -167,16 +169,6 @@ export declare function useWidgetData(slug: Ref<string>, widgetId: Ref<string>,
167
169
  }[] | undefined;
168
170
  limit?: number | undefined;
169
171
  offset?: number | undefined;
170
- time_series?: {
171
- field: string;
172
- grain: import("../model/dashboard.types.js").TimeGrain;
173
- timezone?: string | undefined;
174
- } | undefined;
175
- period?: {
176
- field: string;
177
- gte?: any;
178
- lt?: any;
179
- } | undefined;
180
172
  bucket?: {
181
173
  field: string;
182
174
  buckets: {
@@ -231,8 +223,29 @@ export declare function useWidgetData(slug: Ref<string>, widgetId: Ref<string>,
231
223
  text?: string | undefined;
232
224
  field?: string | undefined;
233
225
  } | undefined;
234
- comparison?: any;
235
- sparkline?: any;
226
+ comparison?: {
227
+ field: string;
228
+ format?: import("../model/dashboard.types.js").ValueFormat | undefined;
229
+ positive_is_good?: boolean | undefined;
230
+ compact?: {
231
+ show?: boolean | undefined;
232
+ template?: string | undefined;
233
+ } | undefined;
234
+ tooltip?: {
235
+ label?: string | undefined;
236
+ template?: string | undefined;
237
+ } | undefined;
238
+ } | undefined;
239
+ sparkline?: {
240
+ type?: "line" | undefined;
241
+ field: string;
242
+ x: string;
243
+ show_axes?: boolean | undefined;
244
+ show_labels?: boolean | undefined;
245
+ fill?: {
246
+ type?: "gradient" | "solid" | undefined;
247
+ } | undefined;
248
+ } | undefined;
236
249
  };
237
250
  query: {
238
251
  resource: string;
@@ -249,6 +262,12 @@ export declare function useWidgetData(slug: Ref<string>, widgetId: Ref<string>,
249
262
  calc: string;
250
263
  as: string;
251
264
  })[] | undefined;
265
+ sparkline?: {
266
+ field: string;
267
+ grain: import("../model/dashboard.types.js").TimeGrain;
268
+ as: string;
269
+ fill_missing?: Record<string, import("../model/dashboard.types.js").JsonValue> | undefined;
270
+ } | undefined;
252
271
  filters?: any;
253
272
  group_by?: (string | {
254
273
  field: string;
@@ -262,16 +281,6 @@ export declare function useWidgetData(slug: Ref<string>, widgetId: Ref<string>,
262
281
  }[] | undefined;
263
282
  limit?: number | undefined;
264
283
  offset?: number | undefined;
265
- time_series?: {
266
- field: string;
267
- grain: import("../model/dashboard.types.js").TimeGrain;
268
- timezone?: string | undefined;
269
- } | undefined;
270
- period?: {
271
- field: string;
272
- gte?: any;
273
- lt?: any;
274
- } | undefined;
275
284
  bucket?: {
276
285
  field: string;
277
286
  buckets: {
@@ -334,6 +343,12 @@ export declare function useWidgetData(slug: Ref<string>, widgetId: Ref<string>,
334
343
  calc: string;
335
344
  as: string;
336
345
  })[] | undefined;
346
+ sparkline?: {
347
+ field: string;
348
+ grain: import("../model/dashboard.types.js").TimeGrain;
349
+ as: string;
350
+ fill_missing?: Record<string, import("../model/dashboard.types.js").JsonValue> | undefined;
351
+ } | undefined;
337
352
  filters?: any;
338
353
  group_by?: (string | {
339
354
  field: string;
@@ -347,16 +362,6 @@ export declare function useWidgetData(slug: Ref<string>, widgetId: Ref<string>,
347
362
  }[] | undefined;
348
363
  limit?: number | undefined;
349
364
  offset?: number | undefined;
350
- time_series?: {
351
- field: string;
352
- grain: import("../model/dashboard.types.js").TimeGrain;
353
- timezone?: string | undefined;
354
- } | undefined;
355
- period?: {
356
- field: string;
357
- gte?: any;
358
- lt?: any;
359
- } | undefined;
360
365
  bucket?: {
361
366
  field: string;
362
367
  buckets: {
@@ -416,6 +421,12 @@ export declare function useWidgetData(slug: Ref<string>, widgetId: Ref<string>,
416
421
  calc: string;
417
422
  as: string;
418
423
  })[] | undefined;
424
+ sparkline?: {
425
+ field: string;
426
+ grain: import("../model/dashboard.types.js").TimeGrain;
427
+ as: string;
428
+ fill_missing?: Record<string, import("../model/dashboard.types.js").JsonValue> | undefined;
429
+ } | undefined;
419
430
  filters?: any;
420
431
  group_by?: (string | {
421
432
  field: string;
@@ -429,16 +440,6 @@ export declare function useWidgetData(slug: Ref<string>, widgetId: Ref<string>,
429
440
  }[] | undefined;
430
441
  limit?: number | undefined;
431
442
  offset?: number | undefined;
432
- time_series?: {
433
- field: string;
434
- grain: import("../model/dashboard.types.js").TimeGrain;
435
- timezone?: string | undefined;
436
- } | undefined;
437
- period?: {
438
- field: string;
439
- gte?: any;
440
- lt?: any;
441
- } | undefined;
442
443
  bucket?: {
443
444
  field: string;
444
445
  buckets: {
@@ -504,6 +505,12 @@ export declare function useWidgetData(slug: Ref<string>, widgetId: Ref<string>,
504
505
  calc: string;
505
506
  as: string;
506
507
  })[] | undefined;
508
+ sparkline?: {
509
+ field: string;
510
+ grain: import("../model/dashboard.types.js").TimeGrain;
511
+ as: string;
512
+ fill_missing?: Record<string, import("../model/dashboard.types.js").JsonValue> | undefined;
513
+ } | undefined;
507
514
  filters?: any;
508
515
  group_by?: (string | {
509
516
  field: string;
@@ -517,16 +524,6 @@ export declare function useWidgetData(slug: Ref<string>, widgetId: Ref<string>,
517
524
  }[] | undefined;
518
525
  limit?: number | undefined;
519
526
  offset?: number | undefined;
520
- time_series?: {
521
- field: string;
522
- grain: import("../model/dashboard.types.js").TimeGrain;
523
- timezone?: string | undefined;
524
- } | undefined;
525
- period?: {
526
- field: string;
527
- gte?: any;
528
- lt?: any;
529
- } | undefined;
530
527
  bucket?: {
531
528
  field: string;
532
529
  buckets: {
@@ -608,6 +605,12 @@ export declare function useWidgetData(slug: Ref<string>, widgetId: Ref<string>,
608
605
  calc: string;
609
606
  as: string;
610
607
  })[] | undefined;
608
+ sparkline?: {
609
+ field: string;
610
+ grain: import("../model/dashboard.types.js").TimeGrain;
611
+ as: string;
612
+ fill_missing?: Record<string, import("../model/dashboard.types.js").JsonValue> | undefined;
613
+ } | undefined;
611
614
  filters?: any;
612
615
  group_by?: (string | {
613
616
  field: string;
@@ -621,16 +624,6 @@ export declare function useWidgetData(slug: Ref<string>, widgetId: Ref<string>,
621
624
  }[] | undefined;
622
625
  limit?: number | undefined;
623
626
  offset?: number | undefined;
624
- time_series?: {
625
- field: string;
626
- grain: import("../model/dashboard.types.js").TimeGrain;
627
- timezone?: string | undefined;
628
- } | undefined;
629
- period?: {
630
- field: string;
631
- gte?: any;
632
- lt?: any;
633
- } | undefined;
634
627
  bucket?: {
635
628
  field: string;
636
629
  buckets: {
@@ -685,8 +678,29 @@ export declare function useWidgetData(slug: Ref<string>, widgetId: Ref<string>,
685
678
  text?: string | undefined;
686
679
  field?: string | undefined;
687
680
  } | undefined;
688
- comparison?: any;
689
- sparkline?: any;
681
+ comparison?: {
682
+ field: string;
683
+ format?: import("../model/dashboard.types.js").ValueFormat | undefined;
684
+ positive_is_good?: boolean | undefined;
685
+ compact?: {
686
+ show?: boolean | undefined;
687
+ template?: string | undefined;
688
+ } | undefined;
689
+ tooltip?: {
690
+ label?: string | undefined;
691
+ template?: string | undefined;
692
+ } | undefined;
693
+ } | undefined;
694
+ sparkline?: {
695
+ type?: "line" | undefined;
696
+ field: string;
697
+ x: string;
698
+ show_axes?: boolean | undefined;
699
+ show_labels?: boolean | undefined;
700
+ fill?: {
701
+ type?: "gradient" | "solid" | undefined;
702
+ } | undefined;
703
+ } | undefined;
690
704
  };
691
705
  query: {
692
706
  resource: string;
@@ -703,6 +717,12 @@ export declare function useWidgetData(slug: Ref<string>, widgetId: Ref<string>,
703
717
  calc: string;
704
718
  as: string;
705
719
  })[] | undefined;
720
+ sparkline?: {
721
+ field: string;
722
+ grain: import("../model/dashboard.types.js").TimeGrain;
723
+ as: string;
724
+ fill_missing?: Record<string, import("../model/dashboard.types.js").JsonValue> | undefined;
725
+ } | undefined;
706
726
  filters?: any;
707
727
  group_by?: (string | {
708
728
  field: string;
@@ -716,16 +736,6 @@ export declare function useWidgetData(slug: Ref<string>, widgetId: Ref<string>,
716
736
  }[] | undefined;
717
737
  limit?: number | undefined;
718
738
  offset?: number | undefined;
719
- time_series?: {
720
- field: string;
721
- grain: import("../model/dashboard.types.js").TimeGrain;
722
- timezone?: string | undefined;
723
- } | undefined;
724
- period?: {
725
- field: string;
726
- gte?: any;
727
- lt?: any;
728
- } | undefined;
729
739
  bucket?: {
730
740
  field: string;
731
741
  buckets: {
@@ -788,6 +798,12 @@ export declare function useWidgetData(slug: Ref<string>, widgetId: Ref<string>,
788
798
  calc: string;
789
799
  as: string;
790
800
  })[] | undefined;
801
+ sparkline?: {
802
+ field: string;
803
+ grain: import("../model/dashboard.types.js").TimeGrain;
804
+ as: string;
805
+ fill_missing?: Record<string, import("../model/dashboard.types.js").JsonValue> | undefined;
806
+ } | undefined;
791
807
  filters?: any;
792
808
  group_by?: (string | {
793
809
  field: string;
@@ -801,16 +817,6 @@ export declare function useWidgetData(slug: Ref<string>, widgetId: Ref<string>,
801
817
  }[] | undefined;
802
818
  limit?: number | undefined;
803
819
  offset?: number | undefined;
804
- time_series?: {
805
- field: string;
806
- grain: import("../model/dashboard.types.js").TimeGrain;
807
- timezone?: string | undefined;
808
- } | undefined;
809
- period?: {
810
- field: string;
811
- gte?: any;
812
- lt?: any;
813
- } | undefined;
814
820
  bucket?: {
815
821
  field: string;
816
822
  buckets: {
@@ -870,6 +876,12 @@ export declare function useWidgetData(slug: Ref<string>, widgetId: Ref<string>,
870
876
  calc: string;
871
877
  as: string;
872
878
  })[] | undefined;
879
+ sparkline?: {
880
+ field: string;
881
+ grain: import("../model/dashboard.types.js").TimeGrain;
882
+ as: string;
883
+ fill_missing?: Record<string, import("../model/dashboard.types.js").JsonValue> | undefined;
884
+ } | undefined;
873
885
  filters?: any;
874
886
  group_by?: (string | {
875
887
  field: string;
@@ -883,16 +895,6 @@ export declare function useWidgetData(slug: Ref<string>, widgetId: Ref<string>,
883
895
  }[] | undefined;
884
896
  limit?: number | undefined;
885
897
  offset?: number | undefined;
886
- time_series?: {
887
- field: string;
888
- grain: import("../model/dashboard.types.js").TimeGrain;
889
- timezone?: string | undefined;
890
- } | undefined;
891
- period?: {
892
- field: string;
893
- gte?: any;
894
- lt?: any;
895
- } | undefined;
896
898
  bucket?: {
897
899
  field: string;
898
900
  buckets: {
@@ -54,7 +54,7 @@
54
54
  class="fixed inset-0 z-50 flex items-center justify-center bg-black/35 p-4"
55
55
  @click.self="closeGroupConfigEditor"
56
56
  >
57
- <section class="w-full max-w-2xl rounded-lg border border-lightListBorder bg-lightDropdownOptionsBackground p-4 shadow-xl dark:border-darkListBorder dark:bg-darkDropdownOptionsBackground">
57
+ <section class="w-full max-w-5xl rounded-lg border border-lightListBorder bg-lightDropdownOptionsBackground p-4 shadow-xl dark:border-darkListBorder dark:bg-darkDropdownOptionsBackground">
58
58
  <header class="mb-3 flex items-center justify-between gap-3">
59
59
  <h2 class="m-0 text-base font-bold text-lightNavbarText dark:text-darkNavbarText">
60
60
  Group JSON
@@ -81,12 +81,9 @@
81
81
  </button>
82
82
  </header>
83
83
 
84
- <textarea
84
+ <YamlConfigEditor
85
85
  v-model="groupConfigCode"
86
- class="min-h-[500px] w-full resize-y rounded-lg border border-lightListBorder bg-lightListTable p-3 font-mono text-sm text-lightNavbarText outline-none focus:border-lightPrimaryButtonBackground dark:border-darkListBorder dark:bg-darkListTable dark:text-darkNavbarText dark:focus:border-darkPrimaryButtonBackground"
87
- spellcheck="false"
88
- @keydown.ctrl.enter.prevent="saveGroupConfig"
89
- @keydown.meta.enter.prevent="saveGroupConfig"
86
+ @save="saveGroupConfig"
90
87
  />
91
88
 
92
89
  <div
@@ -120,7 +117,7 @@
120
117
  class="fixed inset-0 z-50 flex items-center justify-center bg-black/35 p-4"
121
118
  @click.self="closeWidgetConfigEditor"
122
119
  >
123
- <section class="w-full max-w-2xl rounded-lg border border-lightListBorder bg-lightDropdownOptionsBackground p-4 shadow-xl dark:border-darkListBorder dark:bg-darkDropdownOptionsBackground">
120
+ <section class="w-full max-w-5xl rounded-lg border border-lightListBorder bg-lightDropdownOptionsBackground p-4 shadow-xl dark:border-darkListBorder dark:bg-darkDropdownOptionsBackground">
124
121
  <header class="mb-3 flex items-center justify-between gap-3">
125
122
  <h2 class="m-0 text-base font-bold text-lightNavbarText dark:text-darkNavbarText">
126
123
  Widget JSON
@@ -147,12 +144,9 @@
147
144
  </button>
148
145
  </header>
149
146
 
150
- <textarea
147
+ <YamlConfigEditor
151
148
  v-model="widgetConfigCode"
152
- class="min-h-[500px] w-full resize-y rounded-lg border border-lightListBorder bg-lightListTable p-3 font-mono text-sm text-lightNavbarText outline-none focus:border-lightPrimaryButtonBackground dark:border-darkListBorder dark:bg-darkListTable dark:text-darkNavbarText dark:focus:border-darkPrimaryButtonBackground"
153
- spellcheck="false"
154
- @keydown.ctrl.enter.prevent="saveWidgetConfig"
155
- @keydown.meta.enter.prevent="saveWidgetConfig"
149
+ @save="saveWidgetConfig"
156
150
  />
157
151
 
158
152
  <div
@@ -203,12 +197,12 @@ import { computed, ref, watch } from 'vue'
203
197
  import { parse as parseYaml, stringify as stringifyYaml } from 'yaml'
204
198
  import { Button } from '@/afcl'
205
199
  import DashboardGroup from './DashboardGroup.vue'
200
+ import YamlConfigEditor from './YamlConfigEditor.vue'
206
201
  import { DashboardApiError, dashboardApi, type DashboardResponse } from '../api/dashboardApi.js'
207
202
  import type {
208
203
  DashboardConfig,
209
204
  DashboardGroupConfig,
210
205
  EditableDashboardGroupConfig,
211
- EditableDashboardWidgetConfig,
212
206
  DashboardGroupMoveDirection,
213
207
  DashboardWidgetConfig,
214
208
  DashboardWidgetMoveDirection,
@@ -414,13 +408,13 @@ async function saveWidgetConfig() {
414
408
  try {
415
409
  widgetConfigError.value = ''
416
410
  widgetConfigFieldErrors.value = []
417
- const widgetConfig = parseYaml(widgetConfigCode.value) as EditableDashboardWidgetConfig
411
+ const widgetConfig = parseYaml(widgetConfigCode.value) as DashboardWidgetConfig
418
412
 
419
413
  applyDashboardResponse(
420
414
  await dashboardApi.setWidgetConfig(
421
415
  props.dashboardSlug,
422
416
  editingWidgetId.value,
423
- widgetConfig,
417
+ serializeDashboardWidgetConfigForEditor(widgetConfig),
424
418
  ),
425
419
  )
426
420
  closeWidgetConfigEditor()
@@ -0,0 +1,109 @@
1
+ <template>
2
+ <div
3
+ ref="editorEl"
4
+ class="min-h-[500px] w-full overflow-hidden rounded-lg border border-lightListBorder bg-lightListTable text-sm dark:border-darkListBorder dark:bg-darkListTable"
5
+ />
6
+ </template>
7
+
8
+ <script setup lang="ts">
9
+ import 'monaco-editor/min/vs/editor/editor.main.css'
10
+ import EditorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker'
11
+ import { nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue'
12
+ import type * as Monaco from 'monaco-editor'
13
+
14
+ declare global {
15
+ interface Window {
16
+ MonacoEnvironment?: {
17
+ getWorker: () => Worker
18
+ }
19
+ }
20
+ }
21
+
22
+ if (typeof window !== 'undefined' && !window.MonacoEnvironment) {
23
+ window.MonacoEnvironment = {
24
+ getWorker: () => new EditorWorker(),
25
+ }
26
+ }
27
+
28
+ const props = defineProps<{
29
+ modelValue: string
30
+ }>()
31
+
32
+ const emit = defineEmits<{
33
+ 'update:modelValue': [value: string]
34
+ save: []
35
+ }>()
36
+
37
+ const editorEl = ref<HTMLElement | null>(null)
38
+ let monaco: typeof Monaco | null = null
39
+ let editor: Monaco.editor.IStandaloneCodeEditor | null = null
40
+ let resizeObserver: ResizeObserver | null = null
41
+ let applyingExternalValue = false
42
+
43
+ watch(
44
+ () => props.modelValue,
45
+ (value) => {
46
+ if (!editor || value === editor.getValue()) {
47
+ return
48
+ }
49
+
50
+ applyingExternalValue = true
51
+ editor.setValue(value)
52
+ applyingExternalValue = false
53
+ },
54
+ )
55
+
56
+ onMounted(async () => {
57
+ const [loadedMonaco] = await Promise.all([
58
+ import('monaco-editor'),
59
+ import('monaco-editor/esm/vs/basic-languages/yaml/yaml.contribution'),
60
+ ])
61
+
62
+ monaco = loadedMonaco
63
+ await nextTick()
64
+
65
+ if (!editorEl.value) {
66
+ return
67
+ }
68
+
69
+ editor = monaco.editor.create(editorEl.value, {
70
+ value: props.modelValue,
71
+ language: 'yaml',
72
+ automaticLayout: true,
73
+ minimap: { enabled: false },
74
+ fontSize: 13,
75
+ lineNumbersMinChars: 3,
76
+ padding: { top: 12, bottom: 12 },
77
+ scrollBeyondLastLine: false,
78
+ tabSize: 2,
79
+ insertSpaces: true,
80
+ wordWrap: 'on',
81
+ wrappingIndent: 'same',
82
+ theme: document.documentElement.classList.contains('dark') ? 'vs-dark' : 'vs',
83
+ })
84
+
85
+ editor.onDidChangeModelContent(() => {
86
+ if (!editor || applyingExternalValue) {
87
+ return
88
+ }
89
+
90
+ emit('update:modelValue', editor.getValue())
91
+ })
92
+
93
+ editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.Enter, () => {
94
+ emit('save')
95
+ })
96
+
97
+ resizeObserver = new ResizeObserver(() => {
98
+ editor?.layout()
99
+ })
100
+ resizeObserver.observe(editorEl.value)
101
+ })
102
+
103
+ onBeforeUnmount(() => {
104
+ resizeObserver?.disconnect()
105
+ resizeObserver = null
106
+ editor?.dispose()
107
+ editor = null
108
+ })
109
+ </script>