@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
package/dist/module.d.mts CHANGED
@@ -1,15 +1,21 @@
1
1
  import * as nuxt_schema from 'nuxt/schema';
2
2
  export * from '../dist/runtime/components/DataTable/types.js';
3
3
  export * from '../dist/runtime/types/storage.js';
4
+ export * from '../dist/runtime/types/dashboard.js';
4
5
  export { SidebarNavItem, SidebarNavSection } from '../dist/runtime/types/nav.js';
5
6
  export { PlatformAuth } from '../dist/runtime/composables/usePlatformAuth.js';
6
7
  export { PlatformTenant } from '../dist/runtime/composables/usePlatformTenant.js';
7
8
  export { PlatformTalkback } from '../dist/runtime/composables/usePlatformTalkback.js';
8
9
  export { TalkbackChannel, TalkbackChannelOptions, TalkbackMaybeRef } from '../dist/runtime/composables/useTalkbackChannels.js';
9
10
  export { MediaLibraryClient } from '../dist/runtime/composables/useMediaLibrary.js';
11
+ export { SavedViewsStore, StoredSavedView } from '../dist/runtime/composables/useSavedViews.js';
12
+ export { WidgetCategory, WidgetCategoryGroup, WidgetConfigField, WidgetDefinition, WidgetPreviewShape, WidgetRegistry } from '../dist/runtime/lib/widgetRegistry.js';
13
+ export { StickyListView } from '../dist/runtime/composables/useStickyListView.js';
14
+ export { DetailSheetBinding } from '../dist/runtime/composables/useDetailSheet.js';
10
15
  export { FloatingPanelDock, FloatingPanelMode, FloatingPanelOptions } from '../dist/runtime/composables/useFloatingPanel.js';
11
16
  export { IsoOption } from '../dist/runtime/lib/isoLists.js';
12
17
  export { Translate, TranslateNamed, Translator } from '../dist/runtime/lib/i18nBridge.js';
18
+ export { FieldSpan, FormContextRow, SectionOffset, SpanSource } from '../dist/runtime/lib/formLayout.js';
13
19
 
14
20
  declare const _default: nuxt_schema.NuxtModule<nuxt_schema.ModuleOptions, nuxt_schema.ModuleOptions, false>;
15
21
 
package/dist/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "studio-shared",
3
3
  "configKey": "studioShared",
4
- "version": "0.3.2",
4
+ "version": "0.4.0",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.2",
7
7
  "unbuild": "unknown"
package/dist/module.mjs CHANGED
@@ -20,7 +20,7 @@ const module$1 = defineNuxtModule({
20
20
  nuxt.options.vite = nuxt.options.vite || {};
21
21
  nuxt.options.vite.resolve = nuxt.options.vite.resolve || {};
22
22
  const dedupe = nuxt.options.vite.resolve.dedupe ??= [];
23
- for (const pkg of ["@revenexx/studio-shared", "@revenexx/talkback-js", "centrifuge"]) {
23
+ for (const pkg of ["@revenexx/studio-shared", "@revenexx/talkback-js", "centrifuge", "vue-sonner"]) {
24
24
  if (!dedupe.includes(pkg)) dedupe.push(pkg);
25
25
  }
26
26
  nuxt.options.runtimeConfig.public.talkbackHost ??= "";
@@ -36,6 +36,14 @@ const module$1 = defineNuxtModule({
36
36
  // Collapsible list-rail state (persisted per surface) behind the
37
37
  // DataTable toolbar's rail handle.
38
38
  { name: "useListRail", from: join(runtime, "composables/useListRail"), priority: -1 },
39
+ // Where the DataTable toolbar's saved views are kept. The default is
40
+ // localStorage, which is what a host without a cockpit backend has; the
41
+ // cockpit overrides it with an account-backed store (PE-608).
42
+ { name: "useSavedViews", from: join(runtime, "composables/useSavedViews"), priority: -1 },
43
+ // The narrowing a list was left in, kept across a page change (PE-608).
44
+ { name: "useStickyListView", from: join(runtime, "composables/useStickyListView"), priority: -1 },
45
+ // Which record a list's DetailSheet shows, kept in `?<key>=<id>` (PE-691).
46
+ { name: "useDetailSheet", from: join(runtime, "composables/useDetailSheet"), priority: -1 },
39
47
  // A panel that docks to either side of a canvas, floats anywhere on it,
40
48
  // or collapses to a pill — and is dragged between those by its header.
41
49
  // Lifted out of the integration studio's workflow editor so a second
@@ -53,6 +61,9 @@ const module$1 = defineNuxtModule({
53
61
  "useTalkbackStream",
54
62
  "useTalkbackPresence"
55
63
  ].map((name) => ({ name, from: join(runtime, "composables/useTalkbackChannels") })));
64
+ addImports([
65
+ { name: "useDashboards", from: join(runtime, "composables/useDashboards") }
66
+ ]);
56
67
  addImports([
57
68
  { name: "useT", from: join(runtime, "composables/useT") },
58
69
  { name: "useUiLocale", from: join(runtime, "composables/useT") }
@@ -0,0 +1,16 @@
1
+ type __VLS_Props = {
2
+ open: boolean;
3
+ title: string;
4
+ description?: string;
5
+ confirmLabel: string;
6
+ destructive?: boolean;
7
+ };
8
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
9
+ "update:open": (value: boolean) => any;
10
+ confirm: () => any;
11
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
12
+ "onUpdate:open"?: ((value: boolean) => any) | undefined;
13
+ onConfirm?: (() => any) | undefined;
14
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
15
+ declare const _default: typeof __VLS_export;
16
+ export default _default;
@@ -0,0 +1,39 @@
1
+ <script setup>
2
+ import { AlertDialog, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, Button } from "@revenexx/studio";
3
+ defineProps({
4
+ open: { type: Boolean, required: true },
5
+ title: { type: String, required: true },
6
+ description: { type: String, required: false },
7
+ confirmLabel: { type: String, required: true },
8
+ destructive: { type: Boolean, required: false }
9
+ });
10
+ const emit = defineEmits(["update:open", "confirm"]);
11
+ const t = useT();
12
+ </script>
13
+
14
+ <template>
15
+ <AlertDialog :open="open" @update:open="(o) => {
16
+ if (!o) emit('update:open', false);
17
+ }">
18
+ <AlertDialogContent>
19
+ <AlertDialogHeader>
20
+ <AlertDialogTitle>{{ title }}</AlertDialogTitle>
21
+ <AlertDialogDescription v-if="description">{{ description }}</AlertDialogDescription>
22
+ </AlertDialogHeader>
23
+ <AlertDialogFooter>
24
+ <Button variant="outline" size="sm" class="h-7 text-sm" @click="emit('update:open', false)">
25
+ {{ t("dashboard.dialog.action.cancel") }}
26
+ </Button>
27
+ <Button
28
+ size="sm"
29
+ class="h-7 text-sm"
30
+ :class="destructive ? 'bg-rose-600 text-white hover:bg-rose-700' : ''"
31
+ @click="emit('confirm');
32
+ emit('update:open', false)"
33
+ >
34
+ {{ confirmLabel }}
35
+ </Button>
36
+ </AlertDialogFooter>
37
+ </AlertDialogContent>
38
+ </AlertDialog>
39
+ </template>
@@ -0,0 +1,16 @@
1
+ type __VLS_Props = {
2
+ open: boolean;
3
+ title: string;
4
+ description?: string;
5
+ confirmLabel: string;
6
+ destructive?: boolean;
7
+ };
8
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
9
+ "update:open": (value: boolean) => any;
10
+ confirm: () => any;
11
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
12
+ "onUpdate:open"?: ((value: boolean) => any) | undefined;
13
+ onConfirm?: (() => any) | undefined;
14
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
15
+ declare const _default: typeof __VLS_export;
16
+ export default _default;
@@ -0,0 +1,58 @@
1
+ import type { Dashboard } from '../../types/dashboard.js';
2
+ type __VLS_Props = {
3
+ dashboards: Dashboard[];
4
+ current: Dashboard | null;
5
+ editing: boolean;
6
+ dirty: boolean;
7
+ saving: boolean;
8
+ /** House-header sizing: `h-7` studio buttons instead of the greeting bar's pills. */
9
+ compact?: boolean;
10
+ };
11
+ declare var __VLS_180: {
12
+ pillClass: "group cursor-pointer rounded-lg border border-gray-400/10 outline-1 outline-white/30 transition-colors hover:border-primary/50 disabled:cursor-not-allowed disabled:opacity-55 disabled:hover:border-gray-400/10";
13
+ paneClass: "flex items-center gap-1.5 rounded-lg bg-white px-2.5 py-1.5 text-sm font-medium text-[#0B0522] transition-colors group-hover:bg-muted/60 group-disabled:group-hover:bg-white";
14
+ compact: boolean;
15
+ };
16
+ type __VLS_Slots = {} & {
17
+ scope?: (props: typeof __VLS_180) => any;
18
+ };
19
+ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {
20
+ PILL: string;
21
+ PILL_PANE: string;
22
+ }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
23
+ edit: () => any;
24
+ select: (id: string) => any;
25
+ save: () => any;
26
+ discard: () => any;
27
+ addWidget: () => any;
28
+ rename: () => any;
29
+ share: () => any;
30
+ browse: () => any;
31
+ create: () => any;
32
+ duplicate: () => any;
33
+ remove: () => any;
34
+ setDefault: () => any;
35
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
36
+ onEdit?: (() => any) | undefined;
37
+ onSelect?: ((id: string) => any) | undefined;
38
+ onSave?: (() => any) | undefined;
39
+ onDiscard?: (() => any) | undefined;
40
+ onAddWidget?: (() => any) | undefined;
41
+ onRename?: (() => any) | undefined;
42
+ onShare?: (() => any) | undefined;
43
+ onBrowse?: (() => any) | undefined;
44
+ onCreate?: (() => any) | undefined;
45
+ onDuplicate?: (() => any) | undefined;
46
+ onRemove?: (() => any) | undefined;
47
+ onSetDefault?: (() => any) | undefined;
48
+ }>, {
49
+ compact: boolean;
50
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
51
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
52
+ declare const _default: typeof __VLS_export;
53
+ export default _default;
54
+ type __VLS_WithSlots<T, S> = T & {
55
+ new (): {
56
+ $slots: S;
57
+ };
58
+ };
@@ -0,0 +1,209 @@
1
+ <script setup>
2
+ import {
3
+ Button,
4
+ DropdownMenu,
5
+ DropdownMenuContent,
6
+ DropdownMenuGroup,
7
+ DropdownMenuItem,
8
+ DropdownMenuLabel,
9
+ DropdownMenuSeparator,
10
+ DropdownMenuTrigger
11
+ } from "@revenexx/studio";
12
+ import { AddSquare, AltArrowDown as ChevronsUpDown, Copy, Diskette, Global, Magnifier, Pen, Restart, Star, TrashBinMinimalistic } from "#solar-icons";
13
+ import { computed } from "vue";
14
+ const props = defineProps({
15
+ dashboards: { type: Array, required: true },
16
+ current: { type: [Object, null], required: true },
17
+ editing: { type: Boolean, required: true },
18
+ dirty: { type: Boolean, required: true },
19
+ saving: { type: Boolean, required: true },
20
+ compact: { type: Boolean, required: false, default: false }
21
+ });
22
+ const emit = defineEmits(["select", "edit", "save", "discard", "addWidget", "rename", "share", "browse", "create", "duplicate", "remove", "setDefault"]);
23
+ const t = useT();
24
+ const MENU_LIMIT = 5;
25
+ const PILL = "group cursor-pointer rounded-lg border border-gray-400/10 outline-1 outline-white/30 transition-colors hover:border-primary/50 disabled:cursor-not-allowed disabled:opacity-55 disabled:hover:border-gray-400/10";
26
+ const PILL_PANE = "flex items-center gap-1.5 rounded-lg bg-white px-2.5 py-1.5 text-sm font-medium text-[#0B0522] transition-colors group-hover:bg-muted/60 group-disabled:group-hover:bg-white";
27
+ const PILL_PANE_PRIMARY = "flex items-center gap-1.5 rounded-lg bg-primary px-2.5 py-1.5 text-sm font-medium text-white transition-colors group-hover:bg-primary/90";
28
+ defineExpose({ PILL, PILL_PANE });
29
+ const mine = computed(() => props.dashboards.filter((d) => d.isOwner));
30
+ const shared = computed(() => props.dashboards.filter((d) => !d.isOwner));
31
+ function shortlist(list) {
32
+ const currentFirst = [...list].sort((a, b) => {
33
+ if (a.id === props.current?.id) return -1;
34
+ if (b.id === props.current?.id) return 1;
35
+ return 0;
36
+ });
37
+ return currentFirst.slice(0, MENU_LIMIT);
38
+ }
39
+ const mineShown = computed(() => shortlist(mine.value));
40
+ const sharedShown = computed(() => shortlist(shared.value));
41
+ const hiddenCount = computed(
42
+ () => mine.value.length - mineShown.value.length + (shared.value.length - sharedShown.value.length)
43
+ );
44
+ const actions = computed(() => {
45
+ if (props.editing) {
46
+ return [
47
+ { key: "rename", icon: Pen, label: t("dashboard.header.action.rename"), run: () => emit("rename") },
48
+ { key: "add", icon: AddSquare, label: t("dashboard.header.action.add_widget"), run: () => emit("addWidget") },
49
+ { key: "discard", icon: Restart, label: t("dashboard.header.action.discard"), disabled: props.saving, run: () => emit("discard") },
50
+ {
51
+ key: "save",
52
+ icon: Diskette,
53
+ label: props.saving ? t("dashboard.header.action.saving") : t("dashboard.header.action.save"),
54
+ disabled: props.saving || !props.dirty,
55
+ primary: true,
56
+ run: () => emit("save")
57
+ }
58
+ ];
59
+ }
60
+ if (props.current?.canEdit) {
61
+ return [{ key: "edit", icon: Pen, label: t("dashboard.header.action.edit"), run: () => emit("edit") }];
62
+ }
63
+ if (props.current) {
64
+ return [{ key: "duplicate", icon: Copy, label: t("dashboard.header.action.duplicate_to_edit"), run: () => emit("duplicate") }];
65
+ }
66
+ return [];
67
+ });
68
+ const triggerLabel = computed(() => props.current && !props.current.isOwner ? t("dashboard.header.trigger.shared") : t("dashboard.header.trigger.mine"));
69
+ </script>
70
+
71
+ <template>
72
+ <div class="relative flex shrink-0 flex-wrap items-center gap-2">
73
+ <!-- Dashboard picker. Same DropdownMenu as the profile menu in the topbar,
74
+ so hover, spacing and colours are shared rather than reproduced. -->
75
+ <!-- Hidden in edit mode: switching dashboards mid-edit was guarded by a
76
+ discard prompt, and not offering the switch is a better answer than
77
+ asking about it. -->
78
+ <DropdownMenu v-if="!editing">
79
+ <DropdownMenuTrigger as-child>
80
+ <Button v-if="compact" variant="outline" size="sm" class="h-7 gap-1.5 text-sm">
81
+ <span class="text-muted-foreground">{{ triggerLabel }}:</span>
82
+ <span class="max-w-[12rem] truncate font-medium">{{ current?.name ?? t("dashboard.page.title_fallback") }}</span>
83
+ <ChevronsUpDown weight="Bold" :size="12" class="shrink-0 text-muted-foreground" />
84
+ </Button>
85
+ <button
86
+ v-else
87
+ type="button"
88
+ class="group cursor-pointer rounded-lg border border-gray-400/10 outline-1 outline-white/30 transition-colors hover:border-primary/50"
89
+ >
90
+ <div class="flex items-center gap-2 rounded-lg bg-white px-2.5 py-1.5 transition-colors group-hover:bg-muted/60">
91
+ <span class="shrink-0 text-sm text-muted-foreground">{{ triggerLabel }}:</span>
92
+ <span class="max-w-[14rem] truncate text-sm font-medium text-[#0B0522]">
93
+ {{ current?.name ?? t("dashboard.page.title_fallback") }}
94
+ </span>
95
+ <ChevronsUpDown weight="Bold" :size="12" class="shrink-0 text-muted-foreground" />
96
+ </div>
97
+ </button>
98
+ </DropdownMenuTrigger>
99
+
100
+ <DropdownMenuContent align="end" class="w-64">
101
+ <DropdownMenuLabel class="text-xs font-normal text-muted-foreground">
102
+ {{ t("dashboard.header.group.mine") }}
103
+ </DropdownMenuLabel>
104
+ <DropdownMenuGroup>
105
+ <DropdownMenuItem
106
+ v-for="dashboard in mineShown"
107
+ :key="dashboard.id"
108
+ :class="dashboard.id === current?.id ? 'font-medium' : ''"
109
+ @select="emit('select', dashboard.id)"
110
+ >
111
+ <span class="flex-1 truncate">{{ dashboard.name }}</span>
112
+ <span
113
+ v-if="dashboard.isDefault"
114
+ class="flex shrink-0 items-center gap-1 rounded bg-amber-50 px-1.5 py-0.5 text-[10px] font-medium uppercase tracking-wide text-amber-700"
115
+ >
116
+ {{ t("dashboard.header.menu.default_badge") }}
117
+ </span>
118
+ </DropdownMenuItem>
119
+ </DropdownMenuGroup>
120
+
121
+ <template v-if="shared.length">
122
+ <DropdownMenuSeparator />
123
+ <DropdownMenuLabel class="text-xs font-normal text-muted-foreground">
124
+ {{ t("dashboard.header.group.shared") }}
125
+ </DropdownMenuLabel>
126
+ <DropdownMenuGroup>
127
+ <DropdownMenuItem
128
+ v-for="dashboard in sharedShown"
129
+ :key="dashboard.id"
130
+ :class="dashboard.id === current?.id ? 'font-medium' : ''"
131
+ @select="emit('select', dashboard.id)"
132
+ >
133
+ <span class="flex-1 truncate">{{ dashboard.name }}</span>
134
+ <span
135
+ v-if="dashboard.isDefault"
136
+ class="flex shrink-0 items-center gap-1 rounded bg-amber-50 px-1.5 py-0.5 text-[10px] font-medium uppercase tracking-wide text-amber-700"
137
+ >
138
+ {{ t("dashboard.header.menu.default_badge") }}
139
+ </span>
140
+ </DropdownMenuItem>
141
+ </DropdownMenuGroup>
142
+ </template>
143
+
144
+ <DropdownMenuSeparator />
145
+ <DropdownMenuGroup>
146
+ <DropdownMenuItem v-if="hiddenCount > 0" @select="emit('browse')">
147
+ <Magnifier :size="14" />
148
+ {{ t("dashboard.header.menu.browse") }}
149
+ </DropdownMenuItem>
150
+ <DropdownMenuItem @select="emit('create')">
151
+ <AddSquare :size="14" />
152
+ {{ t("dashboard.header.menu.new") }}
153
+ </DropdownMenuItem>
154
+ </DropdownMenuGroup>
155
+
156
+ <DropdownMenuSeparator />
157
+ <DropdownMenuGroup>
158
+ <DropdownMenuItem @select="emit('duplicate')">
159
+ <Copy :size="14" />
160
+ {{ t("dashboard.header.menu.duplicate") }}
161
+ </DropdownMenuItem>
162
+ <DropdownMenuItem v-if="current?.isOwner" @select="emit('share')">
163
+ <Global :size="14" />
164
+ {{ t("dashboard.header.menu.share") }}
165
+ </DropdownMenuItem>
166
+ <DropdownMenuItem v-if="current && !current.isDefault" @select="emit('setDefault')">
167
+ <Star :size="14" />
168
+ {{ t("dashboard.header.menu.set_default") }}
169
+ </DropdownMenuItem>
170
+ <DropdownMenuItem
171
+ v-if="current?.isOwner"
172
+ class="text-destructive focus:text-destructive"
173
+ @select="emit('remove')"
174
+ >
175
+ <TrashBinMinimalistic :size="14" />
176
+ {{ t("dashboard.header.menu.delete") }}
177
+ </DropdownMenuItem>
178
+ </DropdownMenuGroup>
179
+ </DropdownMenuContent>
180
+ </DropdownMenu>
181
+
182
+ <!-- What this surface scopes its widgets by: a period on the home screen,
183
+ a market in a studio. The row owns the position and the pill styling;
184
+ the surface owns the control. -->
185
+ <slot name="scope" :pill-class="PILL" :pane-class="PILL_PANE" :compact="compact" />
186
+
187
+ <span v-if="editing && dirty" class="text-xs text-muted-foreground">{{ t("dashboard.header.unsaved") }}</span>
188
+
189
+ <template v-for="action in actions" :key="action.key">
190
+ <Button
191
+ v-if="compact"
192
+ :variant="action.primary ? 'default' : 'outline'"
193
+ size="sm"
194
+ class="h-7 text-sm"
195
+ :disabled="action.disabled"
196
+ @click="action.run()"
197
+ >
198
+ <component :is="action.icon" :size="13" :class="action.primary ? '' : 'text-muted-foreground'" />
199
+ {{ action.label }}
200
+ </Button>
201
+ <button v-else type="button" :class="PILL" :disabled="action.disabled" @click="action.run()">
202
+ <span :class="action.primary ? PILL_PANE_PRIMARY : PILL_PANE">
203
+ <component :is="action.icon" :size="13" :class="action.primary ? '' : 'text-muted-foreground'" />
204
+ {{ action.label }}
205
+ </span>
206
+ </button>
207
+ </template>
208
+ </div>
209
+ </template>
@@ -0,0 +1,58 @@
1
+ import type { Dashboard } from '../../types/dashboard.js';
2
+ type __VLS_Props = {
3
+ dashboards: Dashboard[];
4
+ current: Dashboard | null;
5
+ editing: boolean;
6
+ dirty: boolean;
7
+ saving: boolean;
8
+ /** House-header sizing: `h-7` studio buttons instead of the greeting bar's pills. */
9
+ compact?: boolean;
10
+ };
11
+ declare var __VLS_180: {
12
+ pillClass: "group cursor-pointer rounded-lg border border-gray-400/10 outline-1 outline-white/30 transition-colors hover:border-primary/50 disabled:cursor-not-allowed disabled:opacity-55 disabled:hover:border-gray-400/10";
13
+ paneClass: "flex items-center gap-1.5 rounded-lg bg-white px-2.5 py-1.5 text-sm font-medium text-[#0B0522] transition-colors group-hover:bg-muted/60 group-disabled:group-hover:bg-white";
14
+ compact: boolean;
15
+ };
16
+ type __VLS_Slots = {} & {
17
+ scope?: (props: typeof __VLS_180) => any;
18
+ };
19
+ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {
20
+ PILL: string;
21
+ PILL_PANE: string;
22
+ }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
23
+ edit: () => any;
24
+ select: (id: string) => any;
25
+ save: () => any;
26
+ discard: () => any;
27
+ addWidget: () => any;
28
+ rename: () => any;
29
+ share: () => any;
30
+ browse: () => any;
31
+ create: () => any;
32
+ duplicate: () => any;
33
+ remove: () => any;
34
+ setDefault: () => any;
35
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
36
+ onEdit?: (() => any) | undefined;
37
+ onSelect?: ((id: string) => any) | undefined;
38
+ onSave?: (() => any) | undefined;
39
+ onDiscard?: (() => any) | undefined;
40
+ onAddWidget?: (() => any) | undefined;
41
+ onRename?: (() => any) | undefined;
42
+ onShare?: (() => any) | undefined;
43
+ onBrowse?: (() => any) | undefined;
44
+ onCreate?: (() => any) | undefined;
45
+ onDuplicate?: (() => any) | undefined;
46
+ onRemove?: (() => any) | undefined;
47
+ onSetDefault?: (() => any) | undefined;
48
+ }>, {
49
+ compact: boolean;
50
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
51
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
52
+ declare const _default: typeof __VLS_export;
53
+ export default _default;
54
+ type __VLS_WithSlots<T, S> = T & {
55
+ new (): {
56
+ $slots: S;
57
+ };
58
+ };
@@ -0,0 +1,17 @@
1
+ import type { DashboardLayoutItem, DashboardWidget } from '../../types/dashboard.js';
2
+ type __VLS_Props = {
3
+ layout: DashboardLayoutItem[];
4
+ widgets: DashboardWidget[];
5
+ editing?: boolean;
6
+ };
7
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
8
+ remove: (widgetId: string) => any;
9
+ configure: (widgetId: string) => any;
10
+ "update:layout": (layout: DashboardLayoutItem[]) => any;
11
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
12
+ onRemove?: ((widgetId: string) => any) | undefined;
13
+ onConfigure?: ((widgetId: string) => any) | undefined;
14
+ "onUpdate:layout"?: ((layout: DashboardLayoutItem[]) => any) | undefined;
15
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
16
+ declare const _default: typeof __VLS_export;
17
+ export default _default;
@@ -0,0 +1,87 @@
1
+ <script setup>
2
+ import { GridItem, GridLayout } from "grid-layout-plus";
3
+ import { computed, ref, watch } from "vue";
4
+ import WidgetFrame from "./DashboardWidgetFrame.vue";
5
+ import WidgetHost from "./DashboardWidgetHost.vue";
6
+ import { useWidgetRegistry } from "../../lib/widgetRegistry";
7
+ const props = defineProps({
8
+ layout: { type: Array, required: true },
9
+ widgets: { type: Array, required: true },
10
+ editing: { type: Boolean, required: false }
11
+ });
12
+ const emit = defineEmits(["update:layout", "configure", "remove"]);
13
+ const registry = useWidgetRegistry();
14
+ const internalLayout = ref(props.layout.map((item) => ({ ...item })));
15
+ function normalize(items) {
16
+ return JSON.stringify(items.map(({ i, x, y, w, h }) => ({ i, x, y, w, h })));
17
+ }
18
+ function idsOf(items) {
19
+ return items.map((item) => item.i).sort().join("|");
20
+ }
21
+ watch(() => props.layout, (next) => {
22
+ const membershipChanged = idsOf(next) !== idsOf(internalLayout.value);
23
+ if (props.editing && !membershipChanged) return;
24
+ if (membershipChanged || normalize(next) !== normalize(internalLayout.value)) {
25
+ internalLayout.value = next.map((item) => ({ ...item }));
26
+ }
27
+ }, { deep: true });
28
+ watch(() => props.editing, () => {
29
+ internalLayout.value = props.layout.map((item) => ({ ...item }));
30
+ });
31
+ function onLayoutUpdated(next) {
32
+ if (!props.editing) return;
33
+ emit("update:layout", next.map(({ i, x, y, w, h }) => ({ i, x, y, w, h })));
34
+ }
35
+ function widgetFor(id) {
36
+ return props.widgets.find((w) => w.id === id);
37
+ }
38
+ const placedLayout = computed(() => internalLayout.value.filter((item) => !!widgetFor(item.i)));
39
+ </script>
40
+
41
+ <template>
42
+ <!-- `-mx-3 -mt-3`: grid-layout-plus insets every item by `margin` on all four
43
+ sides, so without this the widgets sit one gutter inside the page padding
44
+ and one inside the header. Cancelling it on three sides keeps the gaps
45
+ between widgets and drops the duplicated outer one. -->
46
+ <GridLayout
47
+ v-model:layout="internalLayout"
48
+ class="relative z-0 -mx-3 -mt-3"
49
+ :col-num="12"
50
+ :row-height="20"
51
+ :margin="[12, 12]"
52
+ :is-draggable="!!editing"
53
+ :is-resizable="!!editing"
54
+ :responsive="false"
55
+ :vertical-compact="true"
56
+ :use-css-transforms="true"
57
+ drag-allow-from=".widget-drag-handle"
58
+ @layout-updated="onLayoutUpdated"
59
+ >
60
+ <GridItem
61
+ v-for="item in placedLayout"
62
+ :key="item.i"
63
+ :i="item.i"
64
+ :x="item.x"
65
+ :y="item.y"
66
+ :w="item.w"
67
+ :h="item.h"
68
+ :min-w="registry.get(widgetFor(item.i).type)?.minSize?.w ?? 2"
69
+ :min-h="registry.get(widgetFor(item.i).type)?.minSize?.h ?? 3"
70
+ >
71
+ <WidgetFrame
72
+ :definition="registry.get(widgetFor(item.i).type)"
73
+ :title="widgetFor(item.i).title"
74
+ :editing="editing"
75
+ :configurable="!!registry.get(widgetFor(item.i).type)?.configFields?.length"
76
+ @configure="emit('configure', item.i)"
77
+ @remove="emit('remove', item.i)"
78
+ >
79
+ <WidgetHost :widget="widgetFor(item.i)" />
80
+ </WidgetFrame>
81
+ </GridItem>
82
+ </GridLayout>
83
+ </template>
84
+
85
+ <style scoped>
86
+ :deep(.vgl-item--placeholder){background:rgba(124,58,237,.16);border:2px dashed rgba(124,58,237,.55);border-radius:.5rem;box-shadow:inset 0 0 0 9999px rgba(124,58,237,.04);opacity:1}:deep(.vgl-item--dragging){cursor:grabbing;z-index:40}:deep(.vgl-item--dragging)>*{border-radius:.5rem;box-shadow:0 12px 32px -8px rgba(11,5,34,.25);transform:scale(1.01);transition:transform .12s ease,box-shadow .12s ease}:deep(.vgl-item--resizing)>*{border-radius:.5rem;box-shadow:0 8px 24px -8px rgba(11,5,34,.2)}:deep(.vgl-item__resizer){opacity:.55;z-index:30}:deep(.vgl-item:hover .vgl-item__resizer){opacity:1}
87
+ </style>
@@ -0,0 +1,17 @@
1
+ import type { DashboardLayoutItem, DashboardWidget } from '../../types/dashboard.js';
2
+ type __VLS_Props = {
3
+ layout: DashboardLayoutItem[];
4
+ widgets: DashboardWidget[];
5
+ editing?: boolean;
6
+ };
7
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
8
+ remove: (widgetId: string) => any;
9
+ configure: (widgetId: string) => any;
10
+ "update:layout": (layout: DashboardLayoutItem[]) => any;
11
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
12
+ onRemove?: ((widgetId: string) => any) | undefined;
13
+ onConfigure?: ((widgetId: string) => any) | undefined;
14
+ "onUpdate:layout"?: ((layout: DashboardLayoutItem[]) => any) | undefined;
15
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
16
+ declare const _default: typeof __VLS_export;
17
+ export default _default;
@@ -0,0 +1,19 @@
1
+ type __VLS_Props = {
2
+ open: boolean;
3
+ title: string;
4
+ description?: string;
5
+ label: string;
6
+ placeholder?: string;
7
+ confirmLabel: string;
8
+ /** Pre-filled value — a rename starts from the current name. */
9
+ initial?: string;
10
+ };
11
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
12
+ "update:open": (value: boolean) => any;
13
+ submit: (name: string) => any;
14
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
15
+ "onUpdate:open"?: ((value: boolean) => any) | undefined;
16
+ onSubmit?: ((name: string) => any) | undefined;
17
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
18
+ declare const _default: typeof __VLS_export;
19
+ export default _default;