@revenexx/studio-shared 0.1.2 → 0.3.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 (120) hide show
  1. package/README.md +22 -12
  2. package/dist/module.d.mts +15 -0
  3. package/dist/module.json +9 -0
  4. package/dist/module.mjs +58 -0
  5. package/dist/runtime/components/DataTable/ColumnsMenu.d.vue.ts +12 -0
  6. package/{components → dist/runtime/components}/DataTable/ColumnsMenu.vue +13 -19
  7. package/dist/runtime/components/DataTable/ColumnsMenu.vue.d.ts +12 -0
  8. package/dist/runtime/components/DataTable/DataTable.d.vue.ts +87 -0
  9. package/dist/runtime/components/DataTable/DataTable.vue +510 -0
  10. package/dist/runtime/components/DataTable/DataTable.vue.d.ts +87 -0
  11. package/dist/runtime/components/DataTable/FilterMenu.d.vue.ts +21 -0
  12. package/dist/runtime/components/DataTable/FilterMenu.vue +46 -0
  13. package/dist/runtime/components/DataTable/FilterMenu.vue.d.ts +21 -0
  14. package/dist/runtime/components/DataTable/SavedViewsMenu.d.vue.ts +6 -0
  15. package/dist/runtime/components/DataTable/SavedViewsMenu.vue +189 -0
  16. package/dist/runtime/components/DataTable/SavedViewsMenu.vue.d.ts +6 -0
  17. package/dist/runtime/components/DataTable/SortMenu.d.vue.ts +13 -0
  18. package/dist/runtime/components/DataTable/SortMenu.vue +47 -0
  19. package/dist/runtime/components/DataTable/SortMenu.vue.d.ts +13 -0
  20. package/dist/runtime/components/DataTable/ViewModeSwitch.d.vue.ts +20 -0
  21. package/dist/runtime/components/DataTable/ViewModeSwitch.vue +26 -0
  22. package/dist/runtime/components/DataTable/ViewModeSwitch.vue.d.ts +20 -0
  23. package/dist/runtime/components/DataTable/types.d.ts +104 -0
  24. package/dist/runtime/components/DataTable/types.js +0 -0
  25. package/dist/runtime/components/Media/MediaFolderTree.d.vue.ts +17 -0
  26. package/dist/runtime/components/Media/MediaFolderTree.vue +65 -0
  27. package/dist/runtime/components/Media/MediaFolderTree.vue.d.ts +17 -0
  28. package/dist/runtime/components/Media/MediaPickerDialog.d.vue.ts +18 -0
  29. package/dist/runtime/components/Media/MediaPickerDialog.vue +163 -0
  30. package/dist/runtime/components/Media/MediaPickerDialog.vue.d.ts +18 -0
  31. package/dist/runtime/components/Media/MediaUploader.d.vue.ts +29 -0
  32. package/dist/runtime/components/Media/MediaUploader.vue +161 -0
  33. package/dist/runtime/components/Media/MediaUploader.vue.d.ts +29 -0
  34. package/dist/runtime/components/Shared/BuildLogsFlyout.d.vue.ts +30 -0
  35. package/{components → dist/runtime/components}/Shared/BuildLogsFlyout.vue +37 -54
  36. package/dist/runtime/components/Shared/BuildLogsFlyout.vue.d.ts +30 -0
  37. package/dist/runtime/components/Shared/GitDeploymentSettings.d.vue.ts +17 -0
  38. package/dist/runtime/components/Shared/GitDeploymentSettings.vue +75 -0
  39. package/dist/runtime/components/Shared/GitDeploymentSettings.vue.d.ts +17 -0
  40. package/dist/runtime/components/Shared/KpiTile.d.vue.ts +13 -0
  41. package/{components → dist/runtime/components}/Shared/KpiTile.vue +11 -19
  42. package/dist/runtime/components/Shared/KpiTile.vue.d.ts +13 -0
  43. package/dist/runtime/components/Shared/ListSurface.d.vue.ts +38 -0
  44. package/dist/runtime/components/Shared/ListSurface.vue +27 -0
  45. package/dist/runtime/components/Shared/ListSurface.vue.d.ts +38 -0
  46. package/dist/runtime/components/Shared/PageHeader.d.vue.ts +23 -0
  47. package/{components → dist/runtime/components}/Shared/PageHeader.vue +6 -8
  48. package/dist/runtime/components/Shared/PageHeader.vue.d.ts +23 -0
  49. package/dist/runtime/components/Shared/RecordLayout.d.vue.ts +52 -0
  50. package/dist/runtime/components/Shared/RecordLayout.vue +63 -0
  51. package/dist/runtime/components/Shared/RecordLayout.vue.d.ts +52 -0
  52. package/dist/runtime/components/Shared/RecordRailCard.d.vue.ts +26 -0
  53. package/dist/runtime/components/Shared/RecordRailCard.vue +20 -0
  54. package/dist/runtime/components/Shared/RecordRailCard.vue.d.ts +26 -0
  55. package/dist/runtime/components/Shared/SidebarNav.d.vue.ts +41 -0
  56. package/dist/runtime/components/Shared/SidebarNav.vue +48 -0
  57. package/dist/runtime/components/Shared/SidebarNav.vue.d.ts +41 -0
  58. package/dist/runtime/components/Shared/SidebarNavLink.d.vue.ts +15 -0
  59. package/dist/runtime/components/Shared/SidebarNavLink.vue +49 -0
  60. package/dist/runtime/components/Shared/SidebarNavLink.vue.d.ts +15 -0
  61. package/dist/runtime/components/Shared/SortHeader.d.vue.ts +23 -0
  62. package/dist/runtime/components/Shared/SortHeader.vue +35 -0
  63. package/dist/runtime/components/Shared/SortHeader.vue.d.ts +23 -0
  64. package/dist/runtime/components/Shared/StateCard.d.vue.ts +32 -0
  65. package/{components → dist/runtime/components}/Shared/StateCard.vue +21 -36
  66. package/dist/runtime/components/Shared/StateCard.vue.d.ts +32 -0
  67. package/dist/runtime/components/Shared/StudioCard.d.vue.ts +15 -0
  68. package/dist/runtime/components/Shared/StudioCard.vue +19 -0
  69. package/dist/runtime/components/Shared/StudioCard.vue.d.ts +15 -0
  70. package/dist/runtime/components/Shared/TabBar.d.vue.ts +23 -0
  71. package/{components → dist/runtime/components}/Shared/TabBar.vue +7 -16
  72. package/dist/runtime/components/Shared/TabBar.vue.d.ts +23 -0
  73. package/dist/runtime/components/Shared/ViewTab.d.vue.ts +7 -0
  74. package/{components → dist/runtime/components}/Shared/ViewTab.vue +7 -9
  75. package/dist/runtime/components/Shared/ViewTab.vue.d.ts +7 -0
  76. package/dist/runtime/components/Shared/Wizard.d.vue.ts +47 -0
  77. package/dist/runtime/components/Shared/Wizard.vue +66 -0
  78. package/dist/runtime/components/Shared/Wizard.vue.d.ts +47 -0
  79. package/dist/runtime/composables/useListRail.d.ts +9 -0
  80. package/dist/runtime/composables/useListRail.js +19 -0
  81. package/dist/runtime/composables/useMediaLibrary.d.ts +41 -0
  82. package/dist/runtime/composables/useMediaLibrary.js +36 -0
  83. package/dist/runtime/composables/usePlatformAuth.d.ts +35 -0
  84. package/dist/runtime/composables/usePlatformAuth.js +17 -0
  85. package/dist/runtime/composables/usePlatformTalkback.d.ts +29 -0
  86. package/dist/runtime/composables/usePlatformTalkback.js +54 -0
  87. package/dist/runtime/composables/usePlatformTenant.d.ts +14 -0
  88. package/dist/runtime/composables/usePlatformTenant.js +18 -0
  89. package/dist/runtime/composables/useT.d.ts +11 -0
  90. package/dist/runtime/composables/useT.js +8 -0
  91. package/dist/runtime/composables/useTalkbackChannels.d.ts +78 -0
  92. package/dist/runtime/composables/useTalkbackChannels.js +52 -0
  93. package/dist/runtime/lib/formatBridge.d.ts +50 -0
  94. package/dist/runtime/lib/formatBridge.js +54 -0
  95. package/dist/runtime/lib/i18nBridge.d.ts +31 -0
  96. package/dist/runtime/lib/i18nBridge.js +17 -0
  97. package/dist/runtime/lib/isoLists.d.ts +61 -0
  98. package/dist/runtime/lib/isoLists.js +62 -0
  99. package/dist/runtime/lib/sidebarNav.d.ts +34 -0
  100. package/dist/runtime/lib/sidebarNav.js +22 -0
  101. package/dist/runtime/lib/talkback.d.ts +59 -0
  102. package/dist/runtime/lib/talkback.js +49 -0
  103. package/dist/runtime/types/nav.d.ts +37 -0
  104. package/dist/runtime/types/nav.js +0 -0
  105. package/dist/runtime/types/storage.d.ts +67 -0
  106. package/dist/runtime/types/storage.js +0 -0
  107. package/dist/types.d.mts +27 -0
  108. package/package.json +41 -13
  109. package/components/DataTable/DataTable.vue +0 -518
  110. package/components/DataTable/FilterMenu.vue +0 -40
  111. package/components/DataTable/types.ts +0 -82
  112. package/components/Shared/GitDeploymentSettings.vue +0 -87
  113. package/components/Shared/SidebarNav.vue +0 -100
  114. package/components/Shared/SortHeader.vue +0 -50
  115. package/components/Shared/StudioCard.vue +0 -24
  116. package/components/Shared/Wizard.vue +0 -80
  117. package/composables/usePlatformAuth.ts +0 -35
  118. package/composables/usePlatformTenant.ts +0 -35
  119. package/index.ts +0 -16
  120. package/nuxt.config.ts +0 -23
@@ -0,0 +1,21 @@
1
+ type __VLS_Props = {
2
+ /** Popover width class (a wide panel of inputs needs more than the default). */
3
+ width?: string;
4
+ /** Tint the trigger while at least one filter is set. */
5
+ active?: boolean;
6
+ };
7
+ declare var __VLS_34: {};
8
+ type __VLS_Slots = {} & {
9
+ default?: (props: typeof __VLS_34) => any;
10
+ };
11
+ declare const __VLS_component: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
12
+ active: boolean;
13
+ width: string;
14
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
15
+ declare const _default: __VLS_WithSlots<typeof __VLS_component, __VLS_Slots>;
16
+ export default _default;
17
+ type __VLS_WithSlots<T, S> = T & {
18
+ new (): {
19
+ $slots: S;
20
+ };
21
+ };
@@ -0,0 +1,6 @@
1
+ import type { DataTableSavedViews } from './types.js';
2
+ type __VLS_Props = {
3
+ config: DataTableSavedViews;
4
+ };
5
+ 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
+ export default _default;
@@ -0,0 +1,189 @@
1
+ <script setup>
2
+ import { AltArrowDown, Bookmark, TrashBinMinimalistic } from "#solar-icons";
3
+ import {
4
+ Button,
5
+ Dialog,
6
+ DialogContent,
7
+ DialogDescription,
8
+ DialogFooter,
9
+ DialogHeader,
10
+ DialogTitle,
11
+ DropdownMenu,
12
+ DropdownMenuContent,
13
+ DropdownMenuItem,
14
+ DropdownMenuSeparator,
15
+ DropdownMenuTrigger,
16
+ Input
17
+ } from "@revenexx/studio";
18
+ const props = defineProps({
19
+ config: { type: Object, required: true }
20
+ });
21
+ const t = useT();
22
+ const views = ref([]);
23
+ function read() {
24
+ try {
25
+ if (typeof window === "undefined") return [];
26
+ const raw = window.localStorage.getItem(props.config.storageKey);
27
+ if (!raw) return [];
28
+ const parsed = JSON.parse(raw);
29
+ if (!Array.isArray(parsed)) return [];
30
+ return parsed.filter((v) => !!v && typeof v === "object" && typeof v.name === "string");
31
+ } catch {
32
+ return [];
33
+ }
34
+ }
35
+ function persist() {
36
+ try {
37
+ if (typeof window === "undefined") return;
38
+ window.localStorage.setItem(props.config.storageKey, JSON.stringify(views.value));
39
+ } catch {
40
+ }
41
+ }
42
+ onMounted(() => {
43
+ views.value = read();
44
+ });
45
+ watch(() => props.config.storageKey, () => {
46
+ views.value = read();
47
+ });
48
+ const allLabel = computed(() => props.config.allLabel ?? t("shared.datatable.savedviews.all.default"));
49
+ function same(a, b) {
50
+ return JSON.stringify(a) === JSON.stringify(b);
51
+ }
52
+ const isDefault = computed(() => same(props.config.snapshot(), props.config.defaultSnapshot()));
53
+ function isActive(v) {
54
+ return same(v.snapshot, props.config.snapshot());
55
+ }
56
+ const activeLabel = computed(() => {
57
+ const hit = views.value.find(isActive);
58
+ if (hit) return hit.name;
59
+ return isDefault.value ? allLabel.value : t("shared.datatable.savedviews.custom");
60
+ });
61
+ function applyDefault() {
62
+ props.config.apply(props.config.defaultSnapshot());
63
+ }
64
+ function applyView(v) {
65
+ props.config.apply(v.snapshot);
66
+ }
67
+ const saveOpen = ref(false);
68
+ const saveName = ref("");
69
+ function openSave() {
70
+ saveName.value = "";
71
+ saveOpen.value = true;
72
+ }
73
+ function save() {
74
+ const name = saveName.value.trim();
75
+ if (!name) return;
76
+ const entry = { name, snapshot: props.config.snapshot() };
77
+ const idx = views.value.findIndex((v) => v.name === name);
78
+ if (idx >= 0) views.value.splice(idx, 1, entry);
79
+ else views.value.push(entry);
80
+ persist();
81
+ saveOpen.value = false;
82
+ }
83
+ const deleteTarget = ref(null);
84
+ function remove() {
85
+ if (!deleteTarget.value) return;
86
+ views.value = views.value.filter((v) => v.name !== deleteTarget.value.name);
87
+ persist();
88
+ deleteTarget.value = null;
89
+ }
90
+ </script>
91
+
92
+ <template>
93
+ <DropdownMenu>
94
+ <DropdownMenuTrigger as-child>
95
+ <Button
96
+ variant="outline"
97
+ size="sm"
98
+ class="h-7 max-w-48 gap-1.5 text-sm"
99
+ :class="isDefault ? '' : 'border-primary/30 text-primary'"
100
+ :aria-label="t('shared.datatable.savedviews.aria')"
101
+ >
102
+ <Bookmark :size="13" />
103
+ <span class="truncate">{{ activeLabel }}</span>
104
+ <AltArrowDown :size="12" class="opacity-60" />
105
+ </Button>
106
+ </DropdownMenuTrigger>
107
+ <DropdownMenuContent align="end" class="w-56">
108
+ <DropdownMenuItem class="gap-2" @select="applyDefault">
109
+ <span class="flex-1 truncate">{{ allLabel }}</span>
110
+ <span v-if="isDefault" class="text-xs text-primary">{{ t("shared.datatable.savedviews.active.badge") }}</span>
111
+ </DropdownMenuItem>
112
+ <template v-if="views.length">
113
+ <DropdownMenuSeparator />
114
+ <DropdownMenuItem
115
+ v-for="v in views"
116
+ :key="v.name"
117
+ class="gap-2"
118
+ @select="applyView(v)"
119
+ >
120
+ <span class="flex-1 truncate">{{ v.name }}</span>
121
+ <span
122
+ role="button"
123
+ class="text-muted-foreground transition-colors hover:text-rose-600"
124
+ :aria-label="t('shared.datatable.savedviews.delete.aria', { name: v.name })"
125
+ @click.stop="deleteTarget = v"
126
+ @pointerdown.stop.prevent
127
+ >
128
+ <TrashBinMinimalistic :size="13" />
129
+ </span>
130
+ </DropdownMenuItem>
131
+ </template>
132
+ <DropdownMenuSeparator />
133
+ <DropdownMenuItem @select="openSave">
134
+ {{ t("shared.datatable.savedviews.action.savecurrent") }}
135
+ </DropdownMenuItem>
136
+ </DropdownMenuContent>
137
+ </DropdownMenu>
138
+
139
+ <!-- Save the current filters + sort under a name -->
140
+ <Dialog :open="saveOpen" @update:open="(v2) => {
141
+ if (!v2) saveOpen = false;
142
+ }">
143
+ <DialogContent>
144
+ <DialogHeader>
145
+ <DialogTitle>{{ t("shared.datatable.savedviews.savedialog.title") }}</DialogTitle>
146
+ <DialogDescription>{{ t("shared.datatable.savedviews.savedialog.description") }}</DialogDescription>
147
+ </DialogHeader>
148
+ <div class="space-y-1">
149
+ <label for="saved-view-name" class="text-sm font-medium">{{ t("shared.datatable.savedviews.savedialog.field.name.label") }}</label>
150
+ <Input
151
+ id="saved-view-name"
152
+ v-model="saveName"
153
+ :placeholder="t('shared.datatable.savedviews.savedialog.field.name.placeholder')"
154
+ @keydown.enter="save"
155
+ />
156
+ </div>
157
+ <DialogFooter>
158
+ <Button variant="outline" @click="saveOpen = false">
159
+ {{ t("shared.datatable.savedviews.savedialog.action.cancel") }}
160
+ </Button>
161
+ <Button :disabled="!saveName.trim()" @click="save">
162
+ {{ t("shared.datatable.savedviews.savedialog.action.save") }}
163
+ </Button>
164
+ </DialogFooter>
165
+ </DialogContent>
166
+ </Dialog>
167
+
168
+ <!-- Delete a saved view -->
169
+ <Dialog :open="deleteTarget !== null" @update:open="(v2) => {
170
+ if (!v2) deleteTarget = null;
171
+ }">
172
+ <DialogContent>
173
+ <DialogHeader>
174
+ <DialogTitle>{{ t("shared.datatable.savedviews.deletedialog.title") }}</DialogTitle>
175
+ <DialogDescription>
176
+ {{ t("shared.datatable.savedviews.deletedialog.description", { name: deleteTarget?.name ?? "" }) }}
177
+ </DialogDescription>
178
+ </DialogHeader>
179
+ <DialogFooter>
180
+ <Button variant="outline" @click="deleteTarget = null">
181
+ {{ t("shared.datatable.savedviews.deletedialog.action.cancel") }}
182
+ </Button>
183
+ <Button variant="outline" class="border-rose-500/30 text-rose-700 hover:bg-rose-500/10" @click="remove">
184
+ {{ t("shared.datatable.savedviews.deletedialog.action.delete") }}
185
+ </Button>
186
+ </DialogFooter>
187
+ </DialogContent>
188
+ </Dialog>
189
+ </template>
@@ -0,0 +1,6 @@
1
+ import type { DataTableSavedViews } from './types.js';
2
+ type __VLS_Props = {
3
+ config: DataTableSavedViews;
4
+ };
5
+ 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
+ export default _default;
@@ -0,0 +1,13 @@
1
+ import type { DataTableColumn, SortState } from './types.js';
2
+ type __VLS_Props = {
3
+ columns: DataTableColumn[];
4
+ };
5
+ type __VLS_PublicProps = __VLS_Props & {
6
+ modelValue: SortState;
7
+ };
8
+ declare const _default: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
9
+ "update:modelValue": (value: SortState) => any;
10
+ }, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
11
+ "onUpdate:modelValue"?: ((value: SortState) => any) | undefined;
12
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
13
+ export default _default;
@@ -0,0 +1,47 @@
1
+ <script setup>
2
+ import { AltArrowDown, SortVertical } from "#solar-icons";
3
+ import {
4
+ Button,
5
+ DropdownMenu,
6
+ DropdownMenuContent,
7
+ DropdownMenuItem,
8
+ DropdownMenuTrigger
9
+ } from "@revenexx/studio";
10
+ const props = defineProps({
11
+ columns: { type: Array, required: true }
12
+ });
13
+ const sort = defineModel({ type: Object, ...{ required: true } });
14
+ const t = useT();
15
+ const label = computed(() => {
16
+ const col = props.columns.find((c) => c.key === sort.value.column);
17
+ if (!col || !sort.value.direction) return t("shared.datatable.sortmenu.label.default");
18
+ return `${col.label} ${sort.value.direction === "asc" ? "\u2191" : "\u2193"}`;
19
+ });
20
+ function pick(key, direction) {
21
+ sort.value = { column: key, direction };
22
+ }
23
+ </script>
24
+
25
+ <template>
26
+ <DropdownMenu>
27
+ <DropdownMenuTrigger as-child>
28
+ <Button variant="outline" size="sm" class="h-7 gap-1.5 text-sm" :aria-label="t('shared.datatable.sortmenu.aria')">
29
+ <SortVertical :size="14" />
30
+ {{ label }}
31
+ <AltArrowDown :size="12" class="opacity-60" />
32
+ </Button>
33
+ </DropdownMenuTrigger>
34
+ <DropdownMenuContent align="start" class="w-52">
35
+ <template v-for="col in columns" :key="col.key">
36
+ <DropdownMenuItem class="gap-2" @select="pick(col.key, 'asc')">
37
+ <span class="flex-1 truncate">{{ col.label }} ↑</span>
38
+ <span v-if="sort.column === col.key && sort.direction === 'asc'" class="text-xs text-primary">{{ t("shared.datatable.sortmenu.active.badge") }}</span>
39
+ </DropdownMenuItem>
40
+ <DropdownMenuItem class="gap-2" @select="pick(col.key, 'desc')">
41
+ <span class="flex-1 truncate">{{ col.label }} ↓</span>
42
+ <span v-if="sort.column === col.key && sort.direction === 'desc'" class="text-xs text-primary">{{ t("shared.datatable.sortmenu.active.badge") }}</span>
43
+ </DropdownMenuItem>
44
+ </template>
45
+ </DropdownMenuContent>
46
+ </DropdownMenu>
47
+ </template>
@@ -0,0 +1,13 @@
1
+ import type { DataTableColumn, SortState } from './types.js';
2
+ type __VLS_Props = {
3
+ columns: DataTableColumn[];
4
+ };
5
+ type __VLS_PublicProps = __VLS_Props & {
6
+ modelValue: SortState;
7
+ };
8
+ declare const _default: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
9
+ "update:modelValue": (value: SortState) => any;
10
+ }, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
11
+ "onUpdate:modelValue"?: ((value: SortState) => any) | undefined;
12
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
13
+ export default _default;
@@ -0,0 +1,20 @@
1
+ /**
2
+ * List | Gallery (| …) switch for the DataTable toolbar.
3
+ *
4
+ * A gallery is a view mode of a table, not a different kind of page: the
5
+ * toolbar, the footer and the data pipeline stay put, only the body swaps
6
+ * for the `#view` slot.
7
+ */
8
+ import type { DataTableViewMode } from './types.js';
9
+ type __VLS_Props = {
10
+ modes: DataTableViewMode[];
11
+ };
12
+ type __VLS_PublicProps = __VLS_Props & {
13
+ modelValue: string;
14
+ };
15
+ declare const _default: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
16
+ "update:modelValue": (value: string) => any;
17
+ }, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
18
+ "onUpdate:modelValue"?: ((value: string) => any) | undefined;
19
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
20
+ export default _default;
@@ -0,0 +1,26 @@
1
+ <script setup>
2
+ defineProps({
3
+ modes: { type: Array, required: true }
4
+ });
5
+ const mode = defineModel({ type: String, ...{ required: true } });
6
+ </script>
7
+
8
+ <template>
9
+ <div class="inline-flex shrink-0 overflow-hidden rounded-md border border-black/[0.06]">
10
+ <button
11
+ v-for="(m, i) in modes"
12
+ :key="m.value"
13
+ type="button"
14
+ class="inline-flex items-center gap-1.5 px-2.5 py-1 text-sm transition-colors"
15
+ :class="[
16
+ i > 0 ? 'border-l border-black/[0.06]' : '',
17
+ mode === m.value ? 'bg-primary/10 font-medium text-[#0B0522]' : 'text-muted-foreground hover:bg-muted/60'
18
+ ]"
19
+ :aria-pressed="mode === m.value"
20
+ @click="mode = m.value"
21
+ >
22
+ <component :is="m.icon" v-if="m.icon" :size="13" />
23
+ {{ m.label }}
24
+ </button>
25
+ </div>
26
+ </template>
@@ -0,0 +1,20 @@
1
+ /**
2
+ * List | Gallery (| …) switch for the DataTable toolbar.
3
+ *
4
+ * A gallery is a view mode of a table, not a different kind of page: the
5
+ * toolbar, the footer and the data pipeline stay put, only the body swaps
6
+ * for the `#view` slot.
7
+ */
8
+ import type { DataTableViewMode } from './types.js';
9
+ type __VLS_Props = {
10
+ modes: DataTableViewMode[];
11
+ };
12
+ type __VLS_PublicProps = __VLS_Props & {
13
+ modelValue: string;
14
+ };
15
+ declare const _default: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
16
+ "update:modelValue": (value: string) => any;
17
+ }, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
18
+ "onUpdate:modelValue"?: ((value: string) => any) | undefined;
19
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
20
+ export default _default;
@@ -0,0 +1,104 @@
1
+ import type { Component } from 'vue';
2
+ export type Comparable = string | number | boolean | Date | null | undefined;
3
+ export interface DataTableColumn<T = unknown> {
4
+ /** Stable key — matches the slot name `cell-<key>` and is used in the
5
+ * sort state. */
6
+ key: string;
7
+ /** Header label. */
8
+ label: string;
9
+ /** CSS grid track. Defaults to `minmax(0,1fr)` for text columns; pass
10
+ * a fixed value like `120px` or `minmax(0,140px)` for compact ones. */
11
+ width?: string;
12
+ /** Enable sort affordance on this column. */
13
+ sortable?: boolean;
14
+ /** Returns the sort key for the row. Falls back to `row[key]` if it
15
+ * looks like a primitive. ISO date strings sort correctly as-is. */
16
+ sortGetter?: (row: T) => Comparable;
17
+ /** Returns the string a text-search query is matched against. Falls
18
+ * back to the stringified sortGetter result. */
19
+ searchGetter?: (row: T) => string;
20
+ /** Initial visibility (default `true`). */
21
+ visible?: boolean;
22
+ /** Hide-able via the column menu (default `true`). */
23
+ toggleable?: boolean;
24
+ /** Right-align cell content (numeric columns). */
25
+ alignRight?: boolean;
26
+ /** Optional icon component for the header. */
27
+ icon?: Component;
28
+ /** Marks the identifying column. When set (and no `#cell-<key>` slot is
29
+ * given) the DataTable renders the value as the bold record anchor —
30
+ * `font-semibold text-[#0B0522]`, truncated — optionally led by a tinted
31
+ * icon tile (see `cellIcon`). One per table. (datatable-ux) */
32
+ primary?: boolean;
33
+ /** Leading tinted icon tile for the cell (typically the `primary` column).
34
+ * A static icon component, rendered as the `bg-primary/10` rounded tile the
35
+ * scanning rules call for. (For a per-row icon use a `#cell-<key>` slot —
36
+ * `cellIcon` must NOT be a getter: Solar icons are functional components, so
37
+ * the table can't tell a getter from an icon and would crash invoking it.) */
38
+ cellIcon?: Component;
39
+ }
40
+ /** A built-in filter dimension rendered under the generic "Filter" dropdown as
41
+ * a labelled sub-menu (datatable-ux). Static mode only: the DataTable filters
42
+ * `data` in-memory and shows a count per option. Pass one, or an array of
43
+ * several dimensions — each becomes its own sub-menu. */
44
+ export interface DataTableFilter<T = unknown> {
45
+ /** Stable id for this dimension (defaults to `label`). */
46
+ key?: string;
47
+ /** Sub-menu title, e.g. "Status" (default `Status`). */
48
+ label?: string;
49
+ /** The row's value for this dimension (e.g. `r => r.status`). */
50
+ getter: (row: T) => string | null | undefined;
51
+ /** The selectable values + their labels. */
52
+ options: {
53
+ value: string;
54
+ label: string;
55
+ }[];
56
+ /** Label for the reset/"all" entry (default `All`). */
57
+ allLabel?: string;
58
+ }
59
+ /** A named snapshot of a list surface's filter + sort state. */
60
+ export interface DataTableSavedView<S = unknown> {
61
+ name: string;
62
+ snapshot: S;
63
+ }
64
+ /**
65
+ * Saved-view wiring for the DataTable toolbar. The table owns the control,
66
+ * the storage and the save/delete dialogs; the surface only says how to read
67
+ * and write its own filter state.
68
+ */
69
+ export interface DataTableSavedViews<S = unknown> {
70
+ /** `localStorage` key — one bucket per list surface. */
71
+ storageKey: string;
72
+ /** Label of the reset entry (default `All`). */
73
+ allLabel?: string;
74
+ /** The surface's current filter + sort state. */
75
+ snapshot: () => S;
76
+ /** The unfiltered baseline the reset entry restores. */
77
+ defaultSnapshot: () => S;
78
+ /** Put a snapshot back onto the surface. */
79
+ apply: (snapshot: S) => void;
80
+ }
81
+ /** One entry of the toolbar's view-mode switch (List | Gallery | …). */
82
+ export interface DataTableViewMode {
83
+ /** `list` renders the table; any other value renders the `#view` slot. */
84
+ value: string;
85
+ label: string;
86
+ icon?: Component;
87
+ }
88
+ /** Collapsible left-rail affordance in the toolbar. */
89
+ export interface DataTableRail {
90
+ /** Button label (default `Filters`). */
91
+ label?: string;
92
+ }
93
+ export type SortDirection = 'asc' | 'desc' | null;
94
+ export interface SortState {
95
+ column: string | null;
96
+ direction: SortDirection;
97
+ }
98
+ export interface DataTableState {
99
+ search: string;
100
+ sort: SortState;
101
+ page: number;
102
+ pageSize: number;
103
+ }
104
+ export type RowKey<T> = keyof T | ((row: T) => string | number);
File without changes
@@ -0,0 +1,17 @@
1
+ import type { StorageFolderNode } from '../../types/storage.js';
2
+ /**
3
+ * Recursive folder tree for the media browser sidebar. Emits `select` with a
4
+ * folder id (or null for the synthetic root). Self-renders for children.
5
+ */
6
+ type __VLS_Props = {
7
+ nodes: StorageFolderNode[];
8
+ currentId: string | null;
9
+ /** Internal: nesting depth for indentation. */
10
+ depth?: number;
11
+ };
12
+ declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
13
+ select: (id: string | null) => any;
14
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
15
+ onSelect?: ((id: string | null) => any) | undefined;
16
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
17
+ export default _default;
@@ -0,0 +1,65 @@
1
+ <script setup>
2
+ import { Folder as FolderIcon, FolderOpen, AltArrowRight } from "#solar-icons";
3
+ const props = defineProps({
4
+ nodes: { type: Array, required: true },
5
+ currentId: { type: [String, null], required: true },
6
+ depth: { type: Number, required: false }
7
+ });
8
+ const emit = defineEmits(["select"]);
9
+ const expanded = ref(/* @__PURE__ */ new Set());
10
+ function toggle(id) {
11
+ const next = new Set(expanded.value);
12
+ if (next.has(id)) next.delete(id);
13
+ else next.add(id);
14
+ expanded.value = next;
15
+ }
16
+ const depth = computed(() => props.depth ?? 0);
17
+ const t = useT();
18
+ </script>
19
+
20
+ <template>
21
+ <div class="flex flex-col">
22
+ <div
23
+ v-for="node in nodes"
24
+ :key="node.id"
25
+ >
26
+ <div
27
+ class="group flex items-center gap-1 rounded-md pr-2 py-1 text-sm transition-colors cursor-pointer"
28
+ :class="currentId === node.id ? 'bg-primary/10 text-[#0B0522] font-medium' : 'text-foreground/80 hover:bg-primary/5'"
29
+ :style="{ paddingLeft: `${depth * 12 + 4}px` }"
30
+ @click="emit('select', node.id)"
31
+ >
32
+ <button
33
+ type="button"
34
+ class="shrink-0 rounded p-0.5 text-foreground/40 hover:text-foreground/80"
35
+ :class="{ invisible: node.children.length === 0 }"
36
+ @click.stop="toggle(node.id)"
37
+ >
38
+ <AltArrowRight
39
+ :size="12"
40
+ class="transition-transform"
41
+ :class="{ 'rotate-90': expanded.has(node.id) }"
42
+ />
43
+ </button>
44
+ <component
45
+ :is="currentId === node.id ? FolderOpen : FolderIcon"
46
+ :size="14"
47
+ class="shrink-0 text-foreground/50"
48
+ />
49
+ <span class="flex-1 truncate">{{ node.name }}</span>
50
+ <span
51
+ v-if="node.is_system"
52
+ class="rounded bg-muted px-1 text-[10px] font-medium text-muted-foreground"
53
+ >{{ t("shared.media.foldertree.badge.system") }}</span>
54
+ </div>
55
+
56
+ <MediaFolderTree
57
+ v-if="node.children.length && expanded.has(node.id)"
58
+ :nodes="node.children"
59
+ :current-id="currentId"
60
+ :depth="depth + 1"
61
+ @select="(id) => emit('select', id)"
62
+ />
63
+ </div>
64
+ </div>
65
+ </template>
@@ -0,0 +1,17 @@
1
+ import type { StorageFolderNode } from '../../types/storage.js';
2
+ /**
3
+ * Recursive folder tree for the media browser sidebar. Emits `select` with a
4
+ * folder id (or null for the synthetic root). Self-renders for children.
5
+ */
6
+ type __VLS_Props = {
7
+ nodes: StorageFolderNode[];
8
+ currentId: string | null;
9
+ /** Internal: nesting depth for indentation. */
10
+ depth?: number;
11
+ };
12
+ declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
13
+ select: (id: string | null) => any;
14
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
15
+ onSelect?: ((id: string | null) => any) | undefined;
16
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
17
+ export default _default;
@@ -0,0 +1,18 @@
1
+ import type { StorageAsset } from '../../types/storage.js';
2
+ type __VLS_Props = {
3
+ open: boolean;
4
+ multiple?: boolean;
5
+ /** Restrict the grid to these asset kinds (e.g. ['image']). */
6
+ kinds?: string[];
7
+ };
8
+ declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
9
+ select: (assets: StorageAsset[]) => any;
10
+ "update:open": (value: boolean) => any;
11
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
12
+ onSelect?: ((assets: StorageAsset[]) => any) | undefined;
13
+ "onUpdate:open"?: ((value: boolean) => any) | undefined;
14
+ }>, {
15
+ multiple: boolean;
16
+ kinds: string[];
17
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
18
+ export default _default;