@revenexx/studio-shared 0.3.2 → 0.4.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 (166) hide show
  1. package/dist/module.d.mts +6 -0
  2. package/dist/module.json +1 -1
  3. package/dist/module.mjs +12 -1
  4. package/dist/runtime/components/Dashboard/DashboardConfirmDialog.d.vue.ts +16 -0
  5. package/dist/runtime/components/Dashboard/DashboardConfirmDialog.vue +39 -0
  6. package/dist/runtime/components/Dashboard/DashboardConfirmDialog.vue.d.ts +16 -0
  7. package/dist/runtime/components/Dashboard/DashboardControls.d.vue.ts +58 -0
  8. package/dist/runtime/components/Dashboard/DashboardControls.vue +209 -0
  9. package/dist/runtime/components/Dashboard/DashboardControls.vue.d.ts +58 -0
  10. package/dist/runtime/components/Dashboard/DashboardGrid.d.vue.ts +17 -0
  11. package/dist/runtime/components/Dashboard/DashboardGrid.vue +87 -0
  12. package/dist/runtime/components/Dashboard/DashboardGrid.vue.d.ts +17 -0
  13. package/dist/runtime/components/Dashboard/DashboardNameDialog.d.vue.ts +19 -0
  14. package/dist/runtime/components/Dashboard/DashboardNameDialog.vue +61 -0
  15. package/dist/runtime/components/Dashboard/DashboardNameDialog.vue.d.ts +19 -0
  16. package/dist/runtime/components/Dashboard/DashboardPickerDialog.d.vue.ts +15 -0
  17. package/dist/runtime/components/Dashboard/DashboardPickerDialog.vue +100 -0
  18. package/dist/runtime/components/Dashboard/DashboardPickerDialog.vue.d.ts +15 -0
  19. package/dist/runtime/components/Dashboard/DashboardShareDialog.d.vue.ts +28 -0
  20. package/dist/runtime/components/Dashboard/DashboardShareDialog.vue +155 -0
  21. package/dist/runtime/components/Dashboard/DashboardShareDialog.vue.d.ts +28 -0
  22. package/dist/runtime/components/Dashboard/DashboardTopBar.d.vue.ts +64 -0
  23. package/dist/runtime/components/Dashboard/DashboardTopBar.vue +79 -0
  24. package/dist/runtime/components/Dashboard/DashboardTopBar.vue.d.ts +64 -0
  25. package/dist/runtime/components/Dashboard/DashboardWidgetConfigDialog.d.vue.ts +44 -0
  26. package/dist/runtime/components/Dashboard/DashboardWidgetConfigDialog.vue +153 -0
  27. package/dist/runtime/components/Dashboard/DashboardWidgetConfigDialog.vue.d.ts +44 -0
  28. package/dist/runtime/components/Dashboard/DashboardWidgetFrame.d.vue.ts +28 -0
  29. package/dist/runtime/components/Dashboard/DashboardWidgetFrame.vue +80 -0
  30. package/dist/runtime/components/Dashboard/DashboardWidgetFrame.vue.d.ts +28 -0
  31. package/dist/runtime/components/Dashboard/DashboardWidgetHost.d.vue.ts +7 -0
  32. package/dist/runtime/components/Dashboard/DashboardWidgetHost.vue +30 -0
  33. package/dist/runtime/components/Dashboard/DashboardWidgetHost.vue.d.ts +7 -0
  34. package/dist/runtime/components/Dashboard/DashboardWidgetIcon.d.vue.ts +9 -0
  35. package/dist/runtime/components/Dashboard/DashboardWidgetIcon.vue +13 -0
  36. package/dist/runtime/components/Dashboard/DashboardWidgetIcon.vue.d.ts +9 -0
  37. package/dist/runtime/components/Dashboard/DashboardWidgetLibrary.d.vue.ts +24 -0
  38. package/dist/runtime/components/Dashboard/DashboardWidgetLibrary.vue +140 -0
  39. package/dist/runtime/components/Dashboard/DashboardWidgetLibrary.vue.d.ts +24 -0
  40. package/dist/runtime/components/Dashboard/DashboardWidgetPreview.d.vue.ts +23 -0
  41. package/dist/runtime/components/Dashboard/DashboardWidgetPreview.vue +124 -0
  42. package/dist/runtime/components/Dashboard/DashboardWidgetPreview.vue.d.ts +23 -0
  43. package/dist/runtime/components/DataTable/ColumnsMenu.d.vue.ts +2 -1
  44. package/dist/runtime/components/DataTable/ColumnsMenu.vue.d.ts +2 -1
  45. package/dist/runtime/components/DataTable/DataTable.d.vue.ts +105 -28
  46. package/dist/runtime/components/DataTable/DataTable.vue +403 -38
  47. package/dist/runtime/components/DataTable/DataTable.vue.d.ts +105 -28
  48. package/dist/runtime/components/DataTable/FacetChips.d.vue.ts +17 -0
  49. package/dist/runtime/components/DataTable/FacetChips.vue +72 -0
  50. package/dist/runtime/components/DataTable/FacetChips.vue.d.ts +17 -0
  51. package/dist/runtime/components/DataTable/FacetPanel.d.vue.ts +21 -0
  52. package/dist/runtime/components/DataTable/FacetPanel.vue +359 -0
  53. package/dist/runtime/components/DataTable/FacetPanel.vue.d.ts +21 -0
  54. package/dist/runtime/components/DataTable/FilterMenu.d.vue.ts +6 -5
  55. package/dist/runtime/components/DataTable/FilterMenu.vue.d.ts +6 -5
  56. package/dist/runtime/components/DataTable/SavedViewsMenu.d.vue.ts +6 -1
  57. package/dist/runtime/components/DataTable/SavedViewsMenu.vue +83 -63
  58. package/dist/runtime/components/DataTable/SavedViewsMenu.vue.d.ts +6 -1
  59. package/dist/runtime/components/DataTable/SortMenu.d.vue.ts +9 -3
  60. package/dist/runtime/components/DataTable/SortMenu.vue +40 -12
  61. package/dist/runtime/components/DataTable/SortMenu.vue.d.ts +9 -3
  62. package/dist/runtime/components/DataTable/ViewModeSwitch.d.vue.ts +4 -2
  63. package/dist/runtime/components/DataTable/ViewModeSwitch.vue.d.ts +4 -2
  64. package/dist/runtime/components/Form/FieldCell.d.vue.ts +32 -0
  65. package/dist/runtime/components/Form/FieldCell.vue +46 -0
  66. package/dist/runtime/components/Form/FieldCell.vue.d.ts +32 -0
  67. package/dist/runtime/components/Form/FieldGrid.d.vue.ts +13 -0
  68. package/dist/runtime/components/Form/FieldGrid.vue +11 -0
  69. package/dist/runtime/components/Form/FieldGrid.vue.d.ts +13 -0
  70. package/dist/runtime/components/Form/FormContextCard.d.vue.ts +33 -0
  71. package/dist/runtime/components/Form/FormContextCard.vue +56 -0
  72. package/dist/runtime/components/Form/FormContextCard.vue.d.ts +33 -0
  73. package/dist/runtime/components/Form/FormLayout.d.vue.ts +47 -0
  74. package/dist/runtime/components/Form/FormLayout.vue +169 -0
  75. package/dist/runtime/components/Form/FormLayout.vue.d.ts +47 -0
  76. package/dist/runtime/components/Form/FormSection.d.vue.ts +25 -0
  77. package/dist/runtime/components/Form/FormSection.vue +48 -0
  78. package/dist/runtime/components/Form/FormSection.vue.d.ts +25 -0
  79. package/dist/runtime/components/Form/SaveBar.d.vue.ts +44 -0
  80. package/dist/runtime/components/Form/SaveBar.vue +71 -0
  81. package/dist/runtime/components/Form/SaveBar.vue.d.ts +44 -0
  82. package/dist/runtime/components/Media/MediaFolderTree.d.vue.ts +2 -1
  83. package/dist/runtime/components/Media/MediaFolderTree.vue.d.ts +2 -1
  84. package/dist/runtime/components/Media/MediaPickerDialog.d.vue.ts +4 -3
  85. package/dist/runtime/components/Media/MediaPickerDialog.vue.d.ts +4 -3
  86. package/dist/runtime/components/Media/MediaUploader.d.vue.ts +4 -3
  87. package/dist/runtime/components/Media/MediaUploader.vue.d.ts +4 -3
  88. package/dist/runtime/components/Shared/AppIcon.d.vue.ts +21 -0
  89. package/dist/runtime/components/Shared/AppIcon.vue +47 -0
  90. package/dist/runtime/components/Shared/AppIcon.vue.d.ts +21 -0
  91. package/dist/runtime/components/Shared/BuildLogsFlyout.d.vue.ts +2 -1
  92. package/dist/runtime/components/Shared/BuildLogsFlyout.vue.d.ts +2 -1
  93. package/dist/runtime/components/Shared/DetailSheet.d.vue.ts +60 -0
  94. package/dist/runtime/components/Shared/DetailSheet.vue +207 -0
  95. package/dist/runtime/components/Shared/DetailSheet.vue.d.ts +60 -0
  96. package/dist/runtime/components/Shared/FloatingPanel.d.vue.ts +7 -6
  97. package/dist/runtime/components/Shared/FloatingPanel.vue.d.ts +7 -6
  98. package/dist/runtime/components/Shared/GitDeploymentSettings.d.vue.ts +2 -1
  99. package/dist/runtime/components/Shared/GitDeploymentSettings.vue.d.ts +2 -1
  100. package/dist/runtime/components/Shared/KpiTile.d.vue.ts +2 -1
  101. package/dist/runtime/components/Shared/KpiTile.vue.d.ts +2 -1
  102. package/dist/runtime/components/Shared/ListSurface.d.vue.ts +3 -2
  103. package/dist/runtime/components/Shared/ListSurface.vue.d.ts +3 -2
  104. package/dist/runtime/components/Shared/PageHeader.d.vue.ts +7 -6
  105. package/dist/runtime/components/Shared/PageHeader.vue.d.ts +7 -6
  106. package/dist/runtime/components/Shared/RecordLayout.d.vue.ts +8 -7
  107. package/dist/runtime/components/Shared/RecordLayout.vue.d.ts +8 -7
  108. package/dist/runtime/components/Shared/RecordRailCard.d.vue.ts +3 -2
  109. package/dist/runtime/components/Shared/RecordRailCard.vue.d.ts +3 -2
  110. package/dist/runtime/components/Shared/SidebarNav.d.vue.ts +3 -2
  111. package/dist/runtime/components/Shared/SidebarNav.vue.d.ts +3 -2
  112. package/dist/runtime/components/Shared/SidebarNavLink.d.vue.ts +2 -1
  113. package/dist/runtime/components/Shared/SidebarNavLink.vue.d.ts +2 -1
  114. package/dist/runtime/components/Shared/SortHeader.d.vue.ts +3 -2
  115. package/dist/runtime/components/Shared/SortHeader.vue +6 -2
  116. package/dist/runtime/components/Shared/SortHeader.vue.d.ts +3 -2
  117. package/dist/runtime/components/Shared/StateCard.d.vue.ts +6 -5
  118. package/dist/runtime/components/Shared/StateCard.vue.d.ts +6 -5
  119. package/dist/runtime/components/Shared/StudioCard.d.vue.ts +5 -4
  120. package/dist/runtime/components/Shared/StudioCard.vue.d.ts +5 -4
  121. package/dist/runtime/components/Shared/TabBar.d.vue.ts +9 -10
  122. package/dist/runtime/components/Shared/TabBar.vue +26 -7
  123. package/dist/runtime/components/Shared/TabBar.vue.d.ts +9 -10
  124. package/dist/runtime/components/Shared/ViewTab.d.vue.ts +2 -1
  125. package/dist/runtime/components/Shared/ViewTab.vue.d.ts +2 -1
  126. package/dist/runtime/components/Shared/Wizard.d.vue.ts +10 -7
  127. package/dist/runtime/components/Shared/Wizard.vue.d.ts +10 -7
  128. package/dist/runtime/composables/useDashboards.d.ts +27 -0
  129. package/dist/runtime/composables/useDashboards.js +143 -0
  130. package/dist/runtime/composables/useDetailSheet.d.ts +20 -0
  131. package/dist/runtime/composables/useDetailSheet.js +50 -0
  132. package/dist/runtime/composables/usePlatformTenant.d.ts +6 -0
  133. package/dist/runtime/composables/useSavedViews.d.ts +44 -0
  134. package/dist/runtime/composables/useSavedViews.js +44 -0
  135. package/dist/runtime/composables/useStickyListView.d.ts +60 -0
  136. package/dist/runtime/composables/useStickyListView.js +32 -0
  137. package/dist/runtime/lib/activeTenant.d.ts +58 -0
  138. package/dist/runtime/lib/activeTenant.js +45 -0
  139. package/dist/runtime/lib/appIcon.d.ts +48 -0
  140. package/dist/runtime/lib/appIcon.js +27 -0
  141. package/dist/runtime/lib/canonicalJson.d.ts +43 -0
  142. package/dist/runtime/lib/canonicalJson.js +38 -0
  143. package/dist/runtime/lib/dashboardIcons.d.ts +4 -0
  144. package/dist/runtime/lib/dashboardIcons.js +50 -0
  145. package/dist/runtime/lib/detailSheet.d.ts +43 -0
  146. package/dist/runtime/lib/detailSheet.js +34 -0
  147. package/dist/runtime/lib/facets.d.ts +200 -0
  148. package/dist/runtime/lib/facets.js +171 -0
  149. package/dist/runtime/lib/formLayout.d.ts +94 -0
  150. package/dist/runtime/lib/formLayout.js +70 -0
  151. package/dist/runtime/lib/formLayoutContext.d.ts +26 -0
  152. package/dist/runtime/lib/formLayoutContext.js +1 -0
  153. package/dist/runtime/lib/gridTracks.d.ts +55 -0
  154. package/dist/runtime/lib/gridTracks.js +29 -0
  155. package/dist/runtime/lib/rowMove.d.ts +38 -0
  156. package/dist/runtime/lib/rowMove.js +20 -0
  157. package/dist/runtime/lib/solarIconMap.d.ts +15 -0
  158. package/dist/runtime/lib/solarIconMap.js +280 -0
  159. package/dist/runtime/lib/solarIcons.d.ts +37 -0
  160. package/dist/runtime/lib/solarIcons.js +25 -0
  161. package/dist/runtime/lib/widgetRegistry.d.ts +124 -0
  162. package/dist/runtime/lib/widgetRegistry.js +66 -0
  163. package/dist/runtime/types/dashboard.d.ts +95 -0
  164. package/dist/runtime/types/dashboard.js +2 -0
  165. package/dist/types.d.mts +12 -0
  166. package/package.json +3 -2
@@ -16,8 +16,9 @@ type __VLS_Slots = {} & {
16
16
  } & {
17
17
  default?: (props: typeof __VLS_3) => any;
18
18
  };
19
- declare const __VLS_component: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
20
- declare const _default: __VLS_WithSlots<typeof __VLS_component, __VLS_Slots>;
19
+ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
20
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
21
+ declare const _default: typeof __VLS_export;
21
22
  export default _default;
22
23
  type __VLS_WithSlots<T, S> = T & {
23
24
  new (): {
@@ -16,8 +16,9 @@ type __VLS_Slots = {} & {
16
16
  } & {
17
17
  default?: (props: typeof __VLS_3) => any;
18
18
  };
19
- declare const __VLS_component: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
20
- declare const _default: __VLS_WithSlots<typeof __VLS_component, __VLS_Slots>;
19
+ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
20
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
21
+ declare const _default: typeof __VLS_export;
21
22
  export default _default;
22
23
  type __VLS_WithSlots<T, S> = T & {
23
24
  new (): {
@@ -14,7 +14,9 @@
14
14
  import type { Component } from 'vue';
15
15
  import type { SidebarNavSection } from '../../types/nav.js';
16
16
  export type { SidebarNavItem, SidebarNavSection } from '../../types/nav.js';
17
- declare const _default: __VLS_WithSlots<import("vue").DefineComponent<{
17
+ declare const _default: typeof __VLS_export;
18
+ export default _default;
19
+ declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<{
18
20
  title: string;
19
21
  icon?: Component;
20
22
  sections: SidebarNavSection[];
@@ -33,7 +35,6 @@ declare const _default: __VLS_WithSlots<import("vue").DefineComponent<{
33
35
  } & {
34
36
  notice?: (props: {}) => any;
35
37
  }>;
36
- export default _default;
37
38
  type __VLS_WithSlots<T, S> = T & {
38
39
  new (): {
39
40
  $slots: S;
@@ -14,7 +14,9 @@
14
14
  import type { Component } from 'vue';
15
15
  import type { SidebarNavSection } from '../../types/nav.js';
16
16
  export type { SidebarNavItem, SidebarNavSection } from '../../types/nav.js';
17
- declare const _default: __VLS_WithSlots<import("vue").DefineComponent<{
17
+ declare const _default: typeof __VLS_export;
18
+ export default _default;
19
+ declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<{
18
20
  title: string;
19
21
  icon?: Component;
20
22
  sections: SidebarNavSection[];
@@ -33,7 +35,6 @@ declare const _default: __VLS_WithSlots<import("vue").DefineComponent<{
33
35
  } & {
34
36
  notice?: (props: {}) => any;
35
37
  }>;
36
- export default _default;
37
38
  type __VLS_WithSlots<T, S> = T & {
38
39
  new (): {
39
40
  $slots: S;
@@ -11,5 +11,6 @@ import type { SidebarNavItem } from '../../types/nav.js';
11
11
  type __VLS_Props = {
12
12
  item: SidebarNavItem;
13
13
  };
14
- declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
14
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
15
+ declare const _default: typeof __VLS_export;
15
16
  export default _default;
@@ -11,5 +11,6 @@ import type { SidebarNavItem } from '../../types/nav.js';
11
11
  type __VLS_Props = {
12
12
  item: SidebarNavItem;
13
13
  };
14
- declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
14
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
15
+ declare const _default: typeof __VLS_export;
15
16
  export default _default;
@@ -9,12 +9,13 @@ declare var __VLS_1: {};
9
9
  type __VLS_Slots = {} & {
10
10
  default?: (props: typeof __VLS_1) => any;
11
11
  };
12
- declare const __VLS_component: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
12
+ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
13
13
  toggle: (column: string) => any;
14
14
  }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
15
15
  onToggle?: ((column: string) => any) | undefined;
16
16
  }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
17
- declare const _default: __VLS_WithSlots<typeof __VLS_component, __VLS_Slots>;
17
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
18
+ declare const _default: typeof __VLS_export;
18
19
  export default _default;
19
20
  type __VLS_WithSlots<T, S> = T & {
20
21
  new (): {
@@ -18,11 +18,15 @@ const sortIcon = computed(() => {
18
18
  <template>
19
19
  <button
20
20
  type="button"
21
- class="group inline-flex cursor-pointer items-center gap-1.5 -m-1 p-1 rounded-md text-left transition-colors hover:text-primary"
21
+ class="group inline-flex min-w-0 max-w-full cursor-pointer items-center gap-1.5 -m-1 p-1 rounded-md text-left transition-colors hover:text-primary"
22
22
  :class="alignRight ? 'flex-row-reverse w-full justify-end' : ''"
23
23
  @click="emit('toggle', column)"
24
24
  >
25
- <slot />
25
+ <!-- The label truncates. Without this the button is as wide as its words
26
+ and a heading longer than its column simply prints over the next one —
27
+ "SortierungGeändert" on a category list, with no hint that two columns
28
+ are involved. The cell carries the full text as its `title`. -->
29
+ <span class="min-w-0 truncate"><slot /></span>
26
30
  <component
27
31
  :is="sortIcon"
28
32
  weight="Linear"
@@ -9,12 +9,13 @@ declare var __VLS_1: {};
9
9
  type __VLS_Slots = {} & {
10
10
  default?: (props: typeof __VLS_1) => any;
11
11
  };
12
- declare const __VLS_component: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
12
+ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
13
13
  toggle: (column: string) => any;
14
14
  }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
15
15
  onToggle?: ((column: string) => any) | undefined;
16
16
  }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
17
- declare const _default: __VLS_WithSlots<typeof __VLS_component, __VLS_Slots>;
17
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
18
+ declare const _default: typeof __VLS_export;
18
19
  export default _default;
19
20
  type __VLS_WithSlots<T, S> = T & {
20
21
  new (): {
@@ -14,16 +14,17 @@ type __VLS_Props = {
14
14
  title: string;
15
15
  description?: string;
16
16
  };
17
- declare var __VLS_22: {}, __VLS_28: {};
17
+ declare var __VLS_31: {}, __VLS_39: {};
18
18
  type __VLS_Slots = {} & {
19
- description?: (props: typeof __VLS_22) => any;
19
+ description?: (props: typeof __VLS_31) => any;
20
20
  } & {
21
- actions?: (props: typeof __VLS_28) => any;
21
+ actions?: (props: typeof __VLS_39) => any;
22
22
  };
23
- declare const __VLS_component: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
23
+ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
24
24
  variant: Variant;
25
25
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
26
- declare const _default: __VLS_WithSlots<typeof __VLS_component, __VLS_Slots>;
26
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
27
+ declare const _default: typeof __VLS_export;
27
28
  export default _default;
28
29
  type __VLS_WithSlots<T, S> = T & {
29
30
  new (): {
@@ -14,16 +14,17 @@ type __VLS_Props = {
14
14
  title: string;
15
15
  description?: string;
16
16
  };
17
- declare var __VLS_22: {}, __VLS_28: {};
17
+ declare var __VLS_31: {}, __VLS_39: {};
18
18
  type __VLS_Slots = {} & {
19
- description?: (props: typeof __VLS_22) => any;
19
+ description?: (props: typeof __VLS_31) => any;
20
20
  } & {
21
- actions?: (props: typeof __VLS_28) => any;
21
+ actions?: (props: typeof __VLS_39) => any;
22
22
  };
23
- declare const __VLS_component: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
23
+ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
24
24
  variant: Variant;
25
25
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
26
- declare const _default: __VLS_WithSlots<typeof __VLS_component, __VLS_Slots>;
26
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
27
+ declare const _default: typeof __VLS_export;
27
28
  export default _default;
28
29
  type __VLS_WithSlots<T, S> = T & {
29
30
  new (): {
@@ -1,12 +1,13 @@
1
1
  type __VLS_Props = {
2
2
  to?: string;
3
3
  };
4
- declare var __VLS_6: {};
4
+ declare var __VLS_8: {};
5
5
  type __VLS_Slots = {} & {
6
- default?: (props: typeof __VLS_6) => any;
6
+ default?: (props: typeof __VLS_8) => any;
7
7
  };
8
- declare const __VLS_component: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
9
- declare const _default: __VLS_WithSlots<typeof __VLS_component, __VLS_Slots>;
8
+ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
9
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
10
+ declare const _default: typeof __VLS_export;
10
11
  export default _default;
11
12
  type __VLS_WithSlots<T, S> = T & {
12
13
  new (): {
@@ -1,12 +1,13 @@
1
1
  type __VLS_Props = {
2
2
  to?: string;
3
3
  };
4
- declare var __VLS_6: {};
4
+ declare var __VLS_8: {};
5
5
  type __VLS_Slots = {} & {
6
- default?: (props: typeof __VLS_6) => any;
6
+ default?: (props: typeof __VLS_8) => any;
7
7
  };
8
- declare const __VLS_component: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
9
- declare const _default: __VLS_WithSlots<typeof __VLS_component, __VLS_Slots>;
8
+ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
9
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
10
+ declare const _default: typeof __VLS_export;
10
11
  export default _default;
11
12
  type __VLS_WithSlots<T, S> = T & {
12
13
  new (): {
@@ -1,11 +1,3 @@
1
- /**
2
- * Underline tab bar — the standard cockpit detail-page tabs. A full-width
3
- * hairline sits behind the row; the active/hover indicator is a 2px bar that
4
- * spans exactly the label width (inset-x-3 = the px-3 padding), sitting on the
5
- * baseline over the hairline. Active = primary; hover = soft primary. Tabs
6
- * scroll horizontally on overflow. To bleed the line to the panel edges, pass
7
- * e.g. `class="-mx-4 px-4"` from a padded page.
8
- */
9
1
  export interface TabItem {
10
2
  key: string;
11
3
  label: string;
@@ -14,10 +6,17 @@ export interface TabItem {
14
6
  type __VLS_Props = {
15
7
  tabs: TabItem[];
16
8
  modelValue: string;
9
+ /** Pin to the page header. Off for a bar inside a panel. */
10
+ sticky?: boolean;
11
+ /** Accessible name of the tab list. */
12
+ label?: string;
17
13
  };
18
- declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
14
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
19
15
  "update:modelValue": (key: string) => any;
20
16
  }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
21
17
  "onUpdate:modelValue"?: ((key: string) => any) | undefined;
22
- }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
18
+ }>, {
19
+ sticky: boolean;
20
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
21
+ declare const _default: typeof __VLS_export;
23
22
  export default _default;
@@ -1,9 +1,23 @@
1
1
  <script setup>
2
- defineProps({
2
+ import { ref } from "vue";
3
+ const props = defineProps({
3
4
  tabs: { type: Array, required: true },
4
- modelValue: { type: String, required: true }
5
+ modelValue: { type: String, required: true },
6
+ sticky: { type: Boolean, required: false, default: true },
7
+ label: { type: String, required: false }
5
8
  });
6
- defineEmits(["update:modelValue"]);
9
+ const emit = defineEmits(["update:modelValue"]);
10
+ const buttons = ref([]);
11
+ function onKeydown(event, index) {
12
+ const last = props.tabs.length - 1;
13
+ const next = event.key === "ArrowRight" ? index === last ? 0 : index + 1 : event.key === "ArrowLeft" ? index === 0 ? last : index - 1 : event.key === "Home" ? 0 : event.key === "End" ? last : -1;
14
+ if (next < 0) return;
15
+ event.preventDefault();
16
+ const tab = props.tabs[next];
17
+ if (!tab) return;
18
+ emit("update:modelValue", tab.key);
19
+ buttons.value[next]?.focus();
20
+ }
7
21
  </script>
8
22
 
9
23
  <template>
@@ -11,17 +25,22 @@ defineEmits(["update:modelValue"]);
11
25
  pt-4 pb-3 + text-xl line + 1px border) so header and tabs stay glued as
12
26
  one unit while the panel scrolls. Glassy frosted bg (blur + low opacity)
13
27
  lets content scroll through. -->
14
- <div class="sticky top-[57px] z-10 bg-white/40 backdrop-blur-xl">
28
+ <div :class="sticky ? 'sticky top-[57px] z-10 bg-white/40 backdrop-blur-xl' : 'relative'">
15
29
  <!-- Pull the row out by the tab padding so the first/last label sits flush
16
30
  with the surrounding content (headline) edges. -->
17
- <div class="relative z-10 -mx-2.5 flex gap-1 overflow-x-auto">
31
+ <div class="relative z-10 -mx-2.5 flex gap-1 overflow-x-auto" role="tablist" :aria-label="label">
18
32
  <button
19
- v-for="t in tabs"
33
+ v-for="(t, index) in tabs"
20
34
  :key="t.key"
35
+ ref="buttons"
21
36
  type="button"
37
+ role="tab"
38
+ :aria-selected="modelValue === t.key"
39
+ :tabindex="modelValue === t.key || !tabs.some((x) => x.key === modelValue) && index === 0 ? 0 : -1"
22
40
  class="group relative shrink-0 cursor-pointer whitespace-nowrap px-2.5 py-2 text-sm font-medium transition-colors"
23
41
  :class="modelValue === t.key ? 'text-[#0B0522] hover:text-primary' : 'text-[#0B0522]/80 hover:text-primary'"
24
- @click="$emit('update:modelValue', t.key)"
42
+ @click="emit('update:modelValue', t.key)"
43
+ @keydown="onKeydown($event, index)"
25
44
  >
26
45
  {{ t.label }}
27
46
  <span
@@ -1,11 +1,3 @@
1
- /**
2
- * Underline tab bar — the standard cockpit detail-page tabs. A full-width
3
- * hairline sits behind the row; the active/hover indicator is a 2px bar that
4
- * spans exactly the label width (inset-x-3 = the px-3 padding), sitting on the
5
- * baseline over the hairline. Active = primary; hover = soft primary. Tabs
6
- * scroll horizontally on overflow. To bleed the line to the panel edges, pass
7
- * e.g. `class="-mx-4 px-4"` from a padded page.
8
- */
9
1
  export interface TabItem {
10
2
  key: string;
11
3
  label: string;
@@ -14,10 +6,17 @@ export interface TabItem {
14
6
  type __VLS_Props = {
15
7
  tabs: TabItem[];
16
8
  modelValue: string;
9
+ /** Pin to the page header. Off for a bar inside a panel. */
10
+ sticky?: boolean;
11
+ /** Accessible name of the tab list. */
12
+ label?: string;
17
13
  };
18
- declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
14
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
19
15
  "update:modelValue": (key: string) => any;
20
16
  }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
21
17
  "onUpdate:modelValue"?: ((key: string) => any) | undefined;
22
- }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
18
+ }>, {
19
+ sticky: boolean;
20
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
21
+ declare const _default: typeof __VLS_export;
23
22
  export default _default;
@@ -3,5 +3,6 @@ type __VLS_Props = {
3
3
  icon?: unknown;
4
4
  label: string;
5
5
  };
6
- declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
6
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
7
+ declare const _default: typeof __VLS_export;
7
8
  export default _default;
@@ -3,5 +3,6 @@ type __VLS_Props = {
3
3
  icon?: unknown;
4
4
  label: string;
5
5
  };
6
- declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
6
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
7
+ declare const _default: typeof __VLS_export;
7
8
  export default _default;
@@ -10,16 +10,18 @@ type __VLS_Props = {
10
10
  canAdvance?: boolean;
11
11
  busy?: boolean;
12
12
  };
13
+ declare function back(): void;
14
+ declare function next(): void;
13
15
  declare var __VLS_1: {
14
16
  step: any;
15
17
  index: any;
16
18
  }, __VLS_3: {
17
- back: any;
18
- next: any;
19
+ back: typeof back;
20
+ next: typeof next;
19
21
  isFirst: any;
20
22
  isLast: any;
21
- canAdvance: any;
22
- busy: any;
23
+ canAdvance: boolean;
24
+ busy: boolean;
23
25
  index: any;
24
26
  };
25
27
  type __VLS_Slots = {} & {
@@ -27,7 +29,7 @@ type __VLS_Slots = {} & {
27
29
  } & {
28
30
  footer?: (props: typeof __VLS_3) => any;
29
31
  };
30
- declare const __VLS_component: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
32
+ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
31
33
  "update:modelValue": (args_0: number) => any;
32
34
  finish: () => any;
33
35
  }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
@@ -35,10 +37,11 @@ declare const __VLS_component: import("vue").DefineComponent<__VLS_Props, {}, {}
35
37
  onFinish?: (() => any) | undefined;
36
38
  }>, {
37
39
  modelValue: number;
38
- canAdvance: boolean;
39
40
  busy: boolean;
41
+ canAdvance: boolean;
40
42
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
41
- declare const _default: __VLS_WithSlots<typeof __VLS_component, __VLS_Slots>;
43
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
44
+ declare const _default: typeof __VLS_export;
42
45
  export default _default;
43
46
  type __VLS_WithSlots<T, S> = T & {
44
47
  new (): {
@@ -10,16 +10,18 @@ type __VLS_Props = {
10
10
  canAdvance?: boolean;
11
11
  busy?: boolean;
12
12
  };
13
+ declare function back(): void;
14
+ declare function next(): void;
13
15
  declare var __VLS_1: {
14
16
  step: any;
15
17
  index: any;
16
18
  }, __VLS_3: {
17
- back: any;
18
- next: any;
19
+ back: typeof back;
20
+ next: typeof next;
19
21
  isFirst: any;
20
22
  isLast: any;
21
- canAdvance: any;
22
- busy: any;
23
+ canAdvance: boolean;
24
+ busy: boolean;
23
25
  index: any;
24
26
  };
25
27
  type __VLS_Slots = {} & {
@@ -27,7 +29,7 @@ type __VLS_Slots = {} & {
27
29
  } & {
28
30
  footer?: (props: typeof __VLS_3) => any;
29
31
  };
30
- declare const __VLS_component: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
32
+ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
31
33
  "update:modelValue": (args_0: number) => any;
32
34
  finish: () => any;
33
35
  }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
@@ -35,10 +37,11 @@ declare const __VLS_component: import("vue").DefineComponent<__VLS_Props, {}, {}
35
37
  onFinish?: (() => any) | undefined;
36
38
  }>, {
37
39
  modelValue: number;
38
- canAdvance: boolean;
39
40
  busy: boolean;
41
+ canAdvance: boolean;
40
42
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
41
- declare const _default: __VLS_WithSlots<typeof __VLS_component, __VLS_Slots>;
43
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
44
+ declare const _default: typeof __VLS_export;
42
45
  export default _default;
43
46
  type __VLS_WithSlots<T, S> = T & {
44
47
  new (): {
@@ -0,0 +1,27 @@
1
+ import type { ComputedRef } from 'vue';
2
+ import type { Dashboard, DashboardScope, DashboardWritePayload } from '../types/dashboard.js';
3
+ export declare class DashboardApiError extends Error {
4
+ status: number;
5
+ constructor(status: number, message: string);
6
+ }
7
+ export interface UseDashboardsOptions {
8
+ /** Where the dashboard routes live. The cockpit serves them from Nitro. */
9
+ base?: string;
10
+ }
11
+ export declare function useDashboards(scope: DashboardScope, options?: UseDashboardsOptions): {
12
+ scope: DashboardScope;
13
+ dashboards: ComputedRef<Dashboard[]>;
14
+ defaultId: ComputedRef<string | null>;
15
+ loading: ComputedRef<boolean>;
16
+ saving: ComputedRef<boolean>;
17
+ error: ComputedRef<string | null>;
18
+ load: (force?: boolean) => Promise<Dashboard[]>;
19
+ resolve: (slug: string | null) => Dashboard | null;
20
+ create: (payload: DashboardWritePayload & {
21
+ name: string;
22
+ }) => Promise<Dashboard>;
23
+ save: (id: string, payload: DashboardWritePayload) => Promise<Dashboard>;
24
+ remove: (id: string) => Promise<void>;
25
+ duplicate: (id: string) => Promise<Dashboard>;
26
+ setDefault: (id: string | null) => Promise<void>;
27
+ };
@@ -0,0 +1,143 @@
1
+ import { computed, ref } from "vue";
2
+ export class DashboardApiError extends Error {
3
+ constructor(status, message) {
4
+ super(message);
5
+ this.status = status;
6
+ this.name = "DashboardApiError";
7
+ }
8
+ }
9
+ export function useDashboards(scope, options = {}) {
10
+ const base = options.base ?? "/api/cockpit";
11
+ const auth = usePlatformAuth();
12
+ const tenant = usePlatformTenant();
13
+ const key = (name) => `studio.dashboards.${scope}.${name}`;
14
+ const dashboards = useState(key("list"), () => []);
15
+ const defaultId = useState(key("defaultId"), () => null);
16
+ const loaded = useState(key("loaded"), () => false);
17
+ const loading = useState(key("loading"), () => false);
18
+ const saving = useState(key("saving"), () => false);
19
+ const error = useState(key("error"), () => null);
20
+ const inFlight = ref(null);
21
+ async function headers() {
22
+ const token = await auth.getToken();
23
+ if (!token) throw new DashboardApiError(401, "Not signed in.");
24
+ if (!tenant.slug.value) await tenant.load();
25
+ const slug = tenant.slug.value;
26
+ if (!slug) throw new DashboardApiError(400, "No active tenant.");
27
+ return { Authorization: `Bearer ${token}`, "X-Revenexx-Tenant": slug };
28
+ }
29
+ function fail(err) {
30
+ const e = err;
31
+ const status = e.status ?? e.statusCode ?? e.response?.status ?? 0;
32
+ const message = e.data?.statusMessage ?? e.data?.message ?? e.statusMessage ?? e.message ?? "The dashboard service did not answer.";
33
+ throw new DashboardApiError(status, message);
34
+ }
35
+ async function call(path, init = {}) {
36
+ try {
37
+ return await $fetch(`${base}${path}`, {
38
+ method: init.method ?? "GET",
39
+ headers: await headers(),
40
+ query: init.query,
41
+ body: init.body
42
+ });
43
+ } catch (err) {
44
+ if (err instanceof DashboardApiError) throw err;
45
+ fail(err);
46
+ }
47
+ }
48
+ function replace(updated) {
49
+ const idx = dashboards.value.findIndex((d) => d.id === updated.id);
50
+ dashboards.value = idx === -1 ? [...dashboards.value, updated] : dashboards.value.map((d) => d.id === updated.id ? updated : d);
51
+ }
52
+ async function run(force) {
53
+ loading.value = true;
54
+ error.value = null;
55
+ try {
56
+ const res = await call("/dashboards", { query: { scope } });
57
+ dashboards.value = res.dashboards;
58
+ defaultId.value = res.defaultDashboardId;
59
+ loaded.value = true;
60
+ } catch (err) {
61
+ error.value = err.message;
62
+ if (force) throw err;
63
+ } finally {
64
+ loading.value = false;
65
+ }
66
+ return dashboards.value;
67
+ }
68
+ async function load(force = false) {
69
+ if (inFlight.value) return inFlight.value;
70
+ if (loaded.value && !force) return dashboards.value;
71
+ inFlight.value = run(force);
72
+ try {
73
+ return await inFlight.value;
74
+ } finally {
75
+ inFlight.value = null;
76
+ }
77
+ }
78
+ async function create(payload) {
79
+ saving.value = true;
80
+ try {
81
+ const created = await call("/dashboards", { method: "POST", body: { ...payload, scope } });
82
+ replace(created);
83
+ return created;
84
+ } finally {
85
+ saving.value = false;
86
+ }
87
+ }
88
+ async function save(id, payload) {
89
+ const current = dashboards.value.find((d) => d.id === id);
90
+ saving.value = true;
91
+ try {
92
+ const updated = await call(`/dashboards/${id}`, {
93
+ method: "PATCH",
94
+ // The version travels with every write: a stale one is a 409 rather
95
+ // than a silent overwrite of the other tab's edit.
96
+ body: { ...payload, version: payload.version ?? current?.version }
97
+ });
98
+ replace(updated);
99
+ return updated;
100
+ } finally {
101
+ saving.value = false;
102
+ }
103
+ }
104
+ async function remove(id) {
105
+ await call(`/dashboards/${id}`, { method: "DELETE" });
106
+ dashboards.value = dashboards.value.filter((d) => d.id !== id);
107
+ if (defaultId.value === id) defaultId.value = null;
108
+ }
109
+ async function duplicate(id) {
110
+ const copy = await call(`/dashboards/${id}/duplicate`, { method: "POST" });
111
+ replace(copy);
112
+ return copy;
113
+ }
114
+ async function setDefault(id) {
115
+ await call(`/dashboards/${id ?? "none"}/default`, { method: "PUT", body: { scope } });
116
+ defaultId.value = id;
117
+ dashboards.value = dashboards.value.map((d) => ({ ...d, isDefault: d.id === id }));
118
+ }
119
+ function resolve(slug) {
120
+ const list = dashboards.value;
121
+ if (!list.length) return null;
122
+ if (slug) {
123
+ const named = list.find((d) => d.slug === slug);
124
+ if (named) return named;
125
+ }
126
+ return list.find((d) => d.id === defaultId.value) ?? list[0] ?? null;
127
+ }
128
+ return {
129
+ scope,
130
+ dashboards: computed(() => dashboards.value),
131
+ defaultId: computed(() => defaultId.value),
132
+ loading: computed(() => loading.value),
133
+ saving: computed(() => saving.value),
134
+ error: computed(() => error.value),
135
+ load,
136
+ resolve,
137
+ create,
138
+ save,
139
+ remove,
140
+ duplicate,
141
+ setDefault
142
+ };
143
+ }