@revenexx/studio-shared 0.3.3 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/module.d.mts +7 -3
- package/dist/module.json +2 -2
- package/dist/module.mjs +10 -4
- package/dist/runtime/components/Dashboard/DashboardConfirmDialog.d.vue.ts +2 -1
- package/dist/runtime/components/Dashboard/DashboardConfirmDialog.vue +1 -1
- package/dist/runtime/components/Dashboard/DashboardConfirmDialog.vue.d.ts +2 -1
- package/dist/runtime/components/Dashboard/DashboardControls.d.vue.ts +8 -7
- package/dist/runtime/components/Dashboard/DashboardControls.vue.d.ts +8 -7
- package/dist/runtime/components/Dashboard/DashboardGrid.d.vue.ts +2 -1
- package/dist/runtime/components/Dashboard/DashboardGrid.vue +45 -1
- package/dist/runtime/components/Dashboard/DashboardGrid.vue.d.ts +2 -1
- package/dist/runtime/components/Dashboard/DashboardNameDialog.d.vue.ts +2 -1
- package/dist/runtime/components/Dashboard/DashboardNameDialog.vue +1 -1
- package/dist/runtime/components/Dashboard/DashboardNameDialog.vue.d.ts +2 -1
- package/dist/runtime/components/Dashboard/DashboardPickerDialog.d.vue.ts +2 -1
- package/dist/runtime/components/Dashboard/DashboardPickerDialog.vue +1 -1
- package/dist/runtime/components/Dashboard/DashboardPickerDialog.vue.d.ts +2 -1
- package/dist/runtime/components/Dashboard/DashboardShareDialog.d.vue.ts +2 -1
- package/dist/runtime/components/Dashboard/DashboardShareDialog.vue +1 -1
- package/dist/runtime/components/Dashboard/DashboardShareDialog.vue.d.ts +2 -1
- package/dist/runtime/components/Dashboard/DashboardTopBar.d.vue.ts +9 -4
- package/dist/runtime/components/Dashboard/DashboardTopBar.vue.d.ts +9 -4
- package/dist/runtime/components/Dashboard/DashboardWidgetConfigDialog.d.vue.ts +8 -6
- package/dist/runtime/components/Dashboard/DashboardWidgetConfigDialog.vue +1 -1
- package/dist/runtime/components/Dashboard/DashboardWidgetConfigDialog.vue.d.ts +8 -6
- package/dist/runtime/components/Dashboard/DashboardWidgetFrame.d.vue.ts +5 -4
- package/dist/runtime/components/Dashboard/DashboardWidgetFrame.vue +14 -3
- package/dist/runtime/components/Dashboard/DashboardWidgetFrame.vue.d.ts +5 -4
- package/dist/runtime/components/Dashboard/DashboardWidgetHost.d.vue.ts +2 -1
- package/dist/runtime/components/Dashboard/DashboardWidgetHost.vue.d.ts +2 -1
- package/dist/runtime/components/Dashboard/DashboardWidgetIcon.d.vue.ts +2 -1
- package/dist/runtime/components/Dashboard/DashboardWidgetIcon.vue.d.ts +2 -1
- package/dist/runtime/components/Dashboard/DashboardWidgetLibrary.d.vue.ts +2 -1
- package/dist/runtime/components/Dashboard/DashboardWidgetLibrary.vue.d.ts +2 -1
- package/dist/runtime/components/Dashboard/DashboardWidgetPreview.d.vue.ts +2 -1
- package/dist/runtime/components/Dashboard/DashboardWidgetPreview.vue.d.ts +2 -1
- package/dist/runtime/components/DataTable/ColumnsMenu.d.vue.ts +2 -1
- package/dist/runtime/components/DataTable/ColumnsMenu.vue.d.ts +2 -1
- package/dist/runtime/components/DataTable/DataTable.d.vue.ts +120 -37
- package/dist/runtime/components/DataTable/DataTable.vue +493 -53
- package/dist/runtime/components/DataTable/DataTable.vue.d.ts +120 -37
- package/dist/runtime/components/DataTable/FacetChips.d.vue.ts +2 -1
- package/dist/runtime/components/DataTable/FacetChips.vue.d.ts +2 -1
- package/dist/runtime/components/DataTable/FacetPanel.d.vue.ts +6 -5
- package/dist/runtime/components/DataTable/FacetPanel.vue +57 -8
- package/dist/runtime/components/DataTable/FacetPanel.vue.d.ts +6 -5
- package/dist/runtime/components/DataTable/FilterMenu.d.vue.ts +6 -5
- package/dist/runtime/components/DataTable/FilterMenu.vue +5 -5
- package/dist/runtime/components/DataTable/FilterMenu.vue.d.ts +6 -5
- package/dist/runtime/components/DataTable/SavedViewsMenu.d.vue.ts +2 -1
- package/dist/runtime/components/DataTable/SavedViewsMenu.vue +61 -12
- package/dist/runtime/components/DataTable/SavedViewsMenu.vue.d.ts +2 -1
- package/dist/runtime/components/DataTable/SortMenu.d.vue.ts +4 -2
- package/dist/runtime/components/DataTable/SortMenu.vue +4 -1
- package/dist/runtime/components/DataTable/SortMenu.vue.d.ts +4 -2
- package/dist/runtime/components/DataTable/ToolbarLabelTrigger.d.vue.ts +23 -0
- package/dist/runtime/components/DataTable/ToolbarLabelTrigger.vue +29 -0
- package/dist/runtime/components/DataTable/ToolbarLabelTrigger.vue.d.ts +23 -0
- package/dist/runtime/components/DataTable/ViewModeSwitch.d.vue.ts +4 -2
- package/dist/runtime/components/DataTable/ViewModeSwitch.vue.d.ts +4 -2
- package/dist/runtime/components/DataTable/types.d.ts +17 -0
- package/dist/runtime/components/Form/FieldCell.d.vue.ts +32 -0
- package/dist/runtime/components/Form/FieldCell.vue +46 -0
- package/dist/runtime/components/Form/FieldCell.vue.d.ts +32 -0
- package/dist/runtime/components/Form/FieldGrid.d.vue.ts +13 -0
- package/dist/runtime/components/Form/FieldGrid.vue +11 -0
- package/dist/runtime/components/Form/FieldGrid.vue.d.ts +13 -0
- package/dist/runtime/components/Form/FormContextCard.d.vue.ts +33 -0
- package/dist/runtime/components/Form/FormContextCard.vue +56 -0
- package/dist/runtime/components/Form/FormContextCard.vue.d.ts +33 -0
- package/dist/runtime/components/Form/FormLayout.d.vue.ts +47 -0
- package/dist/runtime/components/Form/FormLayout.vue +169 -0
- package/dist/runtime/components/Form/FormLayout.vue.d.ts +47 -0
- package/dist/runtime/components/Form/FormSection.d.vue.ts +25 -0
- package/dist/runtime/components/Form/FormSection.vue +48 -0
- package/dist/runtime/components/Form/FormSection.vue.d.ts +25 -0
- package/dist/runtime/components/Form/SaveBar.d.vue.ts +44 -0
- package/dist/runtime/components/Form/SaveBar.vue +71 -0
- package/dist/runtime/components/Form/SaveBar.vue.d.ts +44 -0
- package/dist/runtime/components/Media/MediaFolderTree.d.vue.ts +6 -5
- package/dist/runtime/components/Media/MediaFolderTree.vue +1 -2
- package/dist/runtime/components/Media/MediaFolderTree.vue.d.ts +6 -5
- package/dist/runtime/components/Media/MediaPickerDialog.d.vue.ts +13 -1
- package/dist/runtime/components/Media/MediaPickerDialog.vue +206 -54
- package/dist/runtime/components/Media/MediaPickerDialog.vue.d.ts +13 -1
- package/dist/runtime/components/Media/MediaUploader.d.vue.ts +2 -1
- package/dist/runtime/components/Media/MediaUploader.vue +1 -1
- package/dist/runtime/components/Media/MediaUploader.vue.d.ts +2 -1
- package/dist/runtime/components/Shared/AppIcon.d.vue.ts +21 -0
- package/dist/runtime/components/Shared/AppIcon.vue +47 -0
- package/dist/runtime/components/Shared/AppIcon.vue.d.ts +21 -0
- package/dist/runtime/components/Shared/BuildLogsFlyout.d.vue.ts +2 -1
- package/dist/runtime/components/Shared/BuildLogsFlyout.vue.d.ts +2 -1
- package/dist/runtime/components/Shared/CardSizeToggle.d.vue.ts +11 -0
- package/dist/runtime/components/Shared/CardSizeToggle.vue +19 -0
- package/dist/runtime/components/Shared/CardSizeToggle.vue.d.ts +11 -0
- package/dist/runtime/components/Shared/DetailSheet.d.vue.ts +60 -0
- package/dist/runtime/components/Shared/DetailSheet.vue +211 -0
- package/dist/runtime/components/Shared/DetailSheet.vue.d.ts +60 -0
- package/dist/runtime/components/Shared/EmptyNote.d.vue.ts +19 -0
- package/dist/runtime/components/Shared/EmptyNote.vue +25 -0
- package/dist/runtime/components/Shared/EmptyNote.vue.d.ts +19 -0
- package/dist/runtime/components/Shared/FloatingPanel.d.vue.ts +7 -6
- package/dist/runtime/components/Shared/FloatingPanel.vue.d.ts +7 -6
- package/dist/runtime/components/Shared/GitDeploymentSettings.d.vue.ts +2 -1
- package/dist/runtime/components/Shared/GitDeploymentSettings.vue.d.ts +2 -1
- package/dist/runtime/components/Shared/KpiTile.d.vue.ts +8 -1
- package/dist/runtime/components/Shared/KpiTile.vue +10 -9
- package/dist/runtime/components/Shared/KpiTile.vue.d.ts +8 -1
- package/dist/runtime/components/Shared/ListSurface.d.vue.ts +3 -2
- package/dist/runtime/components/Shared/ListSurface.vue.d.ts +3 -2
- package/dist/runtime/components/Shared/PageHeader.d.vue.ts +7 -6
- package/dist/runtime/components/Shared/PageHeader.vue +15 -4
- package/dist/runtime/components/Shared/PageHeader.vue.d.ts +7 -6
- package/dist/runtime/components/Shared/RecordLayout.d.vue.ts +8 -7
- package/dist/runtime/components/Shared/RecordLayout.vue +1 -2
- package/dist/runtime/components/Shared/RecordLayout.vue.d.ts +8 -7
- package/dist/runtime/components/Shared/RecordRailCard.d.vue.ts +3 -2
- package/dist/runtime/components/Shared/RecordRailCard.vue +3 -3
- package/dist/runtime/components/Shared/RecordRailCard.vue.d.ts +3 -2
- package/dist/runtime/components/Shared/SelectionBar.d.vue.ts +22 -0
- package/dist/runtime/components/Shared/SelectionBar.vue +40 -0
- package/dist/runtime/components/Shared/SelectionBar.vue.d.ts +22 -0
- package/dist/runtime/components/Shared/SidebarNav.d.vue.ts +39 -4
- package/dist/runtime/components/Shared/SidebarNav.vue +71 -25
- package/dist/runtime/components/Shared/SidebarNav.vue.d.ts +39 -4
- package/dist/runtime/components/Shared/SidebarNavAreas.d.vue.ts +7 -0
- package/dist/runtime/components/Shared/SidebarNavAreas.vue +291 -0
- package/dist/runtime/components/Shared/SidebarNavAreas.vue.d.ts +7 -0
- package/dist/runtime/components/Shared/SidebarNavLink.d.vue.ts +3 -10
- package/dist/runtime/components/Shared/SidebarNavLink.vue +31 -5
- package/dist/runtime/components/Shared/SidebarNavLink.vue.d.ts +3 -10
- package/dist/runtime/components/Shared/SortHeader.d.vue.ts +3 -2
- package/dist/runtime/components/Shared/SortHeader.vue +6 -2
- package/dist/runtime/components/Shared/SortHeader.vue.d.ts +3 -2
- package/dist/runtime/components/Shared/StateCard.d.vue.ts +6 -5
- package/dist/runtime/components/Shared/StateCard.vue +1 -1
- package/dist/runtime/components/Shared/StateCard.vue.d.ts +6 -5
- package/dist/runtime/components/Shared/StudioCard.d.vue.ts +5 -4
- package/dist/runtime/components/Shared/StudioCard.vue.d.ts +5 -4
- package/dist/runtime/components/Shared/TabBar.d.vue.ts +4 -21
- package/dist/runtime/components/Shared/TabBar.vue +30 -13
- package/dist/runtime/components/Shared/TabBar.vue.d.ts +4 -21
- package/dist/runtime/components/Shared/ViewTab.d.vue.ts +2 -1
- package/dist/runtime/components/Shared/ViewTab.vue.d.ts +2 -1
- package/dist/runtime/components/Shared/Wizard.d.vue.ts +20 -7
- package/dist/runtime/components/Shared/Wizard.vue +9 -5
- package/dist/runtime/components/Shared/Wizard.vue.d.ts +20 -7
- package/dist/runtime/composables/useDetailSheet.d.ts +20 -0
- package/dist/runtime/composables/useDetailSheet.js +50 -0
- package/dist/runtime/composables/useMediaLibrary.d.ts +12 -0
- package/dist/runtime/composables/usePlatformTenant.d.ts +6 -0
- package/dist/runtime/composables/useSavedViews.d.ts +11 -1
- package/dist/runtime/composables/useSavedViews.js +4 -4
- package/dist/runtime/composables/useWidgetFigures.d.ts +12 -0
- package/dist/runtime/composables/useWidgetFigures.js +24 -0
- package/dist/runtime/composables/useWidgetHeader.d.ts +15 -0
- package/dist/runtime/composables/useWidgetHeader.js +15 -0
- package/dist/runtime/lib/activeTenant.d.ts +58 -0
- package/dist/runtime/lib/activeTenant.js +45 -0
- package/dist/runtime/lib/appIcon.d.ts +48 -0
- package/dist/runtime/lib/appIcon.js +27 -0
- package/dist/runtime/lib/auditEnvelope.d.ts +43 -0
- package/dist/runtime/lib/auditEnvelope.js +55 -0
- package/dist/runtime/lib/cardSize.d.ts +13 -0
- package/dist/runtime/lib/cardSize.js +20 -0
- package/dist/runtime/lib/dashboardIcons.js +2 -0
- package/dist/runtime/lib/dataTableFilters.d.ts +22 -0
- package/dist/runtime/lib/dataTableFilters.js +5 -0
- package/dist/runtime/lib/detailSheet.d.ts +43 -0
- package/dist/runtime/lib/detailSheet.js +34 -0
- package/dist/runtime/lib/facets.d.ts +13 -0
- package/dist/runtime/lib/formLayout.d.ts +164 -0
- package/dist/runtime/lib/formLayout.js +117 -0
- package/dist/runtime/lib/formLayoutContext.d.ts +26 -0
- package/dist/runtime/lib/formLayoutContext.js +1 -0
- package/dist/runtime/lib/gridTracks.d.ts +14 -1
- package/dist/runtime/lib/gridTracks.js +13 -2
- package/dist/runtime/lib/isoLists.d.ts +37 -2
- package/dist/runtime/lib/isoLists.js +54 -1
- package/dist/runtime/lib/notice.d.ts +14 -0
- package/dist/runtime/lib/notice.js +19 -0
- package/dist/runtime/lib/pageSize.d.ts +15 -0
- package/dist/runtime/lib/pageSize.js +26 -0
- package/dist/runtime/lib/rowMove.d.ts +38 -0
- package/dist/runtime/lib/rowMove.js +20 -0
- package/dist/runtime/lib/sidebarAreas.d.ts +46 -0
- package/dist/runtime/lib/sidebarAreas.js +25 -0
- package/dist/runtime/lib/sidebarNav.d.ts +21 -2
- package/dist/runtime/lib/sidebarNav.js +23 -4
- package/dist/runtime/lib/solarIconMap.d.ts +16 -0
- package/dist/runtime/lib/solarIconMap.js +326 -0
- package/dist/runtime/lib/solarIcons.d.ts +37 -0
- package/dist/runtime/lib/solarIcons.js +25 -0
- package/dist/runtime/lib/swipeToClose.d.ts +25 -0
- package/dist/runtime/lib/swipeToClose.js +118 -0
- package/dist/runtime/lib/tableExport.d.ts +31 -0
- package/dist/runtime/lib/tableExport.js +143 -0
- package/dist/runtime/lib/talkback.d.ts +5 -0
- package/dist/runtime/lib/talkback.js +8 -0
- package/dist/runtime/lib/talkbackTokenBatch.d.ts +35 -0
- package/dist/runtime/lib/talkbackTokenBatch.js +101 -0
- package/dist/runtime/types/nav.d.ts +9 -0
- package/dist/types.d.mts +8 -0
- package/package.json +4 -3
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
-
import { Button, Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from "@revenexx/studio";
|
|
3
|
-
import { CloudUpload, FileText } from "#solar-icons";
|
|
2
|
+
import { Button, Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, Input, SegmentedToggle, SegmentedToggleItem, Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@revenexx/studio";
|
|
3
|
+
import { CloudUpload, FileText, Gallery, ListCheck, Magnifer } from "#solar-icons";
|
|
4
4
|
import MediaFolderTree from "./MediaFolderTree.vue";
|
|
5
5
|
import MediaUploader from "./MediaUploader.vue";
|
|
6
6
|
const props = defineProps({
|
|
7
7
|
open: { type: Boolean, required: true },
|
|
8
8
|
multiple: { type: Boolean, required: false, default: false },
|
|
9
|
-
kinds: { type: Array, required: false, default: void 0 }
|
|
9
|
+
kinds: { type: Array, required: false, default: void 0 },
|
|
10
|
+
catalogue: { type: [Object, null], required: false, default: null }
|
|
10
11
|
});
|
|
11
|
-
const emit = defineEmits(["update:open", "select"]);
|
|
12
|
+
const emit = defineEmits(["update:open", "select", "uploaded"]);
|
|
13
|
+
const lib = useMediaLibrary();
|
|
12
14
|
const {
|
|
13
15
|
assets,
|
|
14
16
|
folderTree,
|
|
@@ -23,15 +25,76 @@ const {
|
|
|
23
25
|
loadMore,
|
|
24
26
|
thumbnailUrl,
|
|
25
27
|
isProcessing
|
|
26
|
-
} =
|
|
28
|
+
} = lib;
|
|
27
29
|
const t = useT();
|
|
28
30
|
const selected = ref([]);
|
|
29
31
|
const uploadOpen = ref(false);
|
|
30
32
|
const failedThumbs = ref(/* @__PURE__ */ new Set());
|
|
31
|
-
const
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
const canSearch = computed(() => !!lib.search && !!lib.loadAssets);
|
|
34
|
+
const query = ref("");
|
|
35
|
+
const KIND_CHIPS = [
|
|
36
|
+
{ value: "image", key: "images" },
|
|
37
|
+
{ value: "video", key: "videos" },
|
|
38
|
+
{ value: "pdf", key: "pdfs" },
|
|
39
|
+
{ value: "document", key: "documents" }
|
|
40
|
+
];
|
|
41
|
+
const chips = computed(() => KIND_CHIPS.filter((c) => !props.kinds?.length || props.kinds.includes(c.value)));
|
|
42
|
+
const kindChip = ref(null);
|
|
43
|
+
const sort = ref("-created_at");
|
|
44
|
+
let searchTimer = null;
|
|
45
|
+
function reload() {
|
|
46
|
+
if (!lib.loadAssets) return;
|
|
47
|
+
if (lib.search) lib.search.value = query.value.trim();
|
|
48
|
+
if (lib.kind) lib.kind.value = kindChip.value;
|
|
49
|
+
if (lib.sortKey) lib.sortKey.value = sort.value;
|
|
50
|
+
void lib.loadAssets();
|
|
51
|
+
}
|
|
52
|
+
watch(query, () => {
|
|
53
|
+
if (searchTimer) clearTimeout(searchTimer);
|
|
54
|
+
searchTimer = setTimeout(reload, 300);
|
|
55
|
+
});
|
|
56
|
+
watch([kindChip, sort], reload);
|
|
57
|
+
const scope = ref("assets");
|
|
58
|
+
const hasCatalogue = computed(() => !!props.catalogue);
|
|
59
|
+
const entryOf = (a) => props.catalogue?.[a.id] ?? null;
|
|
60
|
+
const visibleAssets = computed(() => {
|
|
61
|
+
let list = props.kinds?.length ? assets.value.filter((a) => props.kinds.includes(a.kind)) : assets.value;
|
|
62
|
+
if (hasCatalogue.value && scope.value === "assets") list = list.filter((a) => !!entryOf(a));
|
|
63
|
+
return list;
|
|
64
|
+
});
|
|
65
|
+
const titleOf = (a) => entryOf(a)?.title || a.display_name || a.original_name;
|
|
66
|
+
function factsOf(a) {
|
|
67
|
+
const ext = /\.([a-z0-9]{2,5})$/i.exec(a.original_name ?? "")?.[1]?.toUpperCase() ?? (a.mime_type?.split("/")[1] ?? "").toUpperCase();
|
|
68
|
+
const kb = a.size_bytes != null ? a.size_bytes >= 1048576 ? `${(a.size_bytes / 1048576).toFixed(1).replace(".", ",")} MB` : `${Math.max(1, Math.round(a.size_bytes / 1024))} KB` : "";
|
|
69
|
+
const dims = a.width && a.height ? `${a.width} \xD7 ${a.height}` : "";
|
|
70
|
+
return [ext, kb, dims].filter(Boolean).join(" \xB7 ");
|
|
71
|
+
}
|
|
72
|
+
const VIEW_KEY = "rx.media.picker.view";
|
|
73
|
+
function storedView() {
|
|
74
|
+
try {
|
|
75
|
+
return import.meta.client && localStorage.getItem(VIEW_KEY) === "list" ? "list" : "gallery";
|
|
76
|
+
} catch {
|
|
77
|
+
return "gallery";
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
const view = ref(storedView());
|
|
81
|
+
watch(view, (v) => {
|
|
82
|
+
try {
|
|
83
|
+
localStorage.setItem(VIEW_KEY, v);
|
|
84
|
+
} catch {
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
const sentinel = ref(null);
|
|
88
|
+
let observer = null;
|
|
89
|
+
watch(sentinel, (el) => {
|
|
90
|
+
observer?.disconnect();
|
|
91
|
+
if (!el || typeof IntersectionObserver === "undefined") return;
|
|
92
|
+
observer = new IntersectionObserver((entries) => {
|
|
93
|
+
if (entries.some((e) => e.isIntersecting) && hasMore.value && !loadingAssets.value) void loadMore();
|
|
94
|
+
}, { rootMargin: "200px" });
|
|
95
|
+
observer.observe(el);
|
|
96
|
+
});
|
|
97
|
+
onBeforeUnmount(() => observer?.disconnect());
|
|
35
98
|
function isSelected(asset) {
|
|
36
99
|
return selected.value.some((a) => a.id === asset.id);
|
|
37
100
|
}
|
|
@@ -52,31 +115,46 @@ function confirm() {
|
|
|
52
115
|
emit("select", selected.value);
|
|
53
116
|
emit("update:open", false);
|
|
54
117
|
}
|
|
118
|
+
let beforeUpload = /* @__PURE__ */ new Set();
|
|
119
|
+
function startUpload() {
|
|
120
|
+
beforeUpload = new Set(assets.value.map((a) => a.id));
|
|
121
|
+
uploadOpen.value = true;
|
|
122
|
+
}
|
|
55
123
|
function onUploaded() {
|
|
56
124
|
uploadOpen.value = false;
|
|
125
|
+
const fresh = assets.value.filter((a) => !beforeUpload.has(a.id));
|
|
126
|
+
if (fresh.length) emit("uploaded", fresh);
|
|
57
127
|
}
|
|
58
128
|
watch(() => props.open, (open) => {
|
|
59
129
|
if (open) {
|
|
60
130
|
selected.value = [];
|
|
131
|
+
query.value = "";
|
|
132
|
+
kindChip.value = null;
|
|
133
|
+
sort.value = "-created_at";
|
|
134
|
+
scope.value = "assets";
|
|
135
|
+
lib.resetFilters?.();
|
|
61
136
|
void init();
|
|
137
|
+
} else {
|
|
138
|
+
lib.resetFilters?.();
|
|
62
139
|
}
|
|
63
140
|
});
|
|
64
141
|
</script>
|
|
65
142
|
|
|
66
143
|
<template>
|
|
67
144
|
<Dialog :open="open" @update:open="(v) => emit('update:open', v)">
|
|
68
|
-
<DialogContent class="max-w-
|
|
145
|
+
<DialogContent class="sm:max-w-5xl">
|
|
69
146
|
<DialogHeader>
|
|
70
147
|
<DialogTitle>{{ multiple ? t("shared.media.picker.title.multiple") : t("shared.media.picker.title.single") }}</DialogTitle>
|
|
148
|
+
<DialogDescription>{{ multiple ? t("shared.media.picker.description.multiple") : t("shared.media.picker.description.single") }}</DialogDescription>
|
|
71
149
|
</DialogHeader>
|
|
72
150
|
|
|
73
|
-
<div class="flex
|
|
151
|
+
<div class="flex h-[30rem] gap-4">
|
|
74
152
|
<!-- Folder sidebar -->
|
|
75
153
|
<div class="w-56 shrink-0 overflow-y-auto border-r border-black/[0.06] pr-2">
|
|
76
154
|
<button
|
|
77
155
|
type="button"
|
|
78
|
-
class="w-full
|
|
79
|
-
:class="currentView === 'all' ? 'bg-primary/10 text-[#0B0522]
|
|
156
|
+
class="w-full rounded-md px-2 py-1 text-left text-sm transition-colors"
|
|
157
|
+
:class="currentView === 'all' ? 'bg-primary/10 font-medium text-[#0B0522]' : 'text-foreground/80 hover:bg-primary/5'"
|
|
80
158
|
@click="showAllMedia"
|
|
81
159
|
>
|
|
82
160
|
{{ t("shared.media.picker.action.allmedia") }}
|
|
@@ -88,53 +166,127 @@ watch(() => props.open, (open) => {
|
|
|
88
166
|
/>
|
|
89
167
|
</div>
|
|
90
168
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
<div class="flex items-center
|
|
94
|
-
<
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
169
|
+
<div class="flex min-w-0 flex-1 flex-col">
|
|
170
|
+
<!-- Toolbar: search, kinds, sort, scope, view, upload -->
|
|
171
|
+
<div class="mb-2 flex flex-wrap items-center gap-2">
|
|
172
|
+
<div v-if="canSearch" class="relative min-w-48 flex-1">
|
|
173
|
+
<Magnifer :size="14" class="pointer-events-none absolute left-2.5 top-1/2 -translate-y-1/2 text-muted-foreground" />
|
|
174
|
+
<Input v-model="query" type="search" class="h-8 pl-8 text-sm" :placeholder="t('shared.media.picker.search')" :aria-label="t('shared.media.picker.search')" />
|
|
175
|
+
</div>
|
|
176
|
+
<Select v-if="canSearch && lib.sortKey" v-model="sort">
|
|
177
|
+
<SelectTrigger class="h-8 w-36 text-sm" :aria-label="t('shared.media.picker.sort.label')"><SelectValue /></SelectTrigger>
|
|
178
|
+
<SelectContent>
|
|
179
|
+
<SelectItem value="-created_at">{{ t("shared.media.picker.sort.newest") }}</SelectItem>
|
|
180
|
+
<SelectItem value="original_name">{{ t("shared.media.picker.sort.name") }}</SelectItem>
|
|
181
|
+
</SelectContent>
|
|
182
|
+
</Select>
|
|
183
|
+
<SegmentedToggle v-model="view" variant="inset" :aria-label="t('shared.media.picker.view.label')">
|
|
184
|
+
<SegmentedToggleItem value="gallery" :aria-label="t('shared.media.picker.view.gallery')"><Gallery :size="14" /></SegmentedToggleItem>
|
|
185
|
+
<SegmentedToggleItem value="list" :aria-label="t('shared.media.picker.view.list')"><ListCheck :size="14" /></SegmentedToggleItem>
|
|
186
|
+
</SegmentedToggle>
|
|
187
|
+
<Button variant="outline" size="sm" class="h-8 text-sm" @click="startUpload">
|
|
98
188
|
<CloudUpload :size="14" /> {{ t("shared.media.picker.action.upload") }}
|
|
99
189
|
</Button>
|
|
100
190
|
</div>
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
class="
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
:
|
|
120
|
-
|
|
121
|
-
class="h-full w-full object-cover"
|
|
122
|
-
:class="{ 'opacity-50': isProcessing(asset) }"
|
|
123
|
-
@error="markFailed(thumbnailUrl(asset))"
|
|
191
|
+
<div class="mb-2 flex flex-wrap items-center gap-1.5">
|
|
192
|
+
<template v-if="hasCatalogue">
|
|
193
|
+
<button
|
|
194
|
+
v-for="s in ['assets', 'files']"
|
|
195
|
+
:key="s"
|
|
196
|
+
type="button"
|
|
197
|
+
class="rounded-full border px-2.5 py-0.5 text-xs transition-colors"
|
|
198
|
+
:class="scope === s ? 'border-primary bg-primary/10 text-[#0B0522]' : 'border-black/[0.08] text-muted-foreground hover:border-primary/40'"
|
|
199
|
+
@click="scope = s"
|
|
200
|
+
>
|
|
201
|
+
{{ t(`shared.media.picker.scope.${s}`) }}
|
|
202
|
+
</button>
|
|
203
|
+
<span class="mx-1 h-4 w-px bg-black/[0.08]" />
|
|
204
|
+
</template>
|
|
205
|
+
<template v-if="canSearch && lib.kind && chips.length > 1">
|
|
206
|
+
<button
|
|
207
|
+
type="button"
|
|
208
|
+
class="rounded-full border px-2.5 py-0.5 text-xs transition-colors"
|
|
209
|
+
:class="kindChip === null ? 'border-primary bg-primary/10 text-[#0B0522]' : 'border-black/[0.08] text-muted-foreground hover:border-primary/40'"
|
|
210
|
+
@click="kindChip = null"
|
|
124
211
|
>
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
212
|
+
{{ t("shared.media.picker.kind.all") }}
|
|
213
|
+
</button>
|
|
214
|
+
<button
|
|
215
|
+
v-for="c in chips"
|
|
216
|
+
:key="c.value"
|
|
217
|
+
type="button"
|
|
218
|
+
class="rounded-full border px-2.5 py-0.5 text-xs transition-colors"
|
|
219
|
+
:class="kindChip === c.value ? 'border-primary bg-primary/10 text-[#0B0522]' : 'border-black/[0.08] text-muted-foreground hover:border-primary/40'"
|
|
220
|
+
@click="kindChip = kindChip === c.value ? null : c.value"
|
|
221
|
+
>
|
|
222
|
+
{{ t(`shared.media.picker.kind.${c.key}`) }}
|
|
223
|
+
</button>
|
|
224
|
+
</template>
|
|
225
|
+
<span class="ml-auto text-xs text-muted-foreground">{{ t("shared.media.picker.count", visibleAssets.length) }}</span>
|
|
132
226
|
</div>
|
|
133
227
|
|
|
134
|
-
<div
|
|
135
|
-
<
|
|
136
|
-
{{ t("shared.media.picker.
|
|
137
|
-
</
|
|
228
|
+
<div class="min-h-0 flex-1 overflow-y-auto">
|
|
229
|
+
<div v-if="loadingAssets && !visibleAssets.length" class="py-12 text-center text-sm text-muted-foreground">
|
|
230
|
+
{{ t("shared.media.picker.loading") }}
|
|
231
|
+
</div>
|
|
232
|
+
<div v-else-if="!visibleAssets.length" class="py-12 text-center text-sm text-muted-foreground">
|
|
233
|
+
<p class="font-medium text-foreground/80">{{ hasCatalogue && scope === "assets" ? t("shared.media.picker.emptyAssets") : t("shared.media.picker.empty") }}</p>
|
|
234
|
+
<button v-if="hasCatalogue && scope === 'assets'" type="button" class="mt-1 text-primary hover:underline" @click="scope = 'files'">{{ t("shared.media.picker.showFiles") }}</button>
|
|
235
|
+
</div>
|
|
236
|
+
<div v-else-if="view === 'gallery'" class="grid grid-cols-3 gap-3 sm:grid-cols-4">
|
|
237
|
+
<button
|
|
238
|
+
v-for="asset in visibleAssets"
|
|
239
|
+
:key="asset.id"
|
|
240
|
+
type="button"
|
|
241
|
+
class="group relative aspect-square overflow-hidden rounded-md border transition-all"
|
|
242
|
+
:class="isSelected(asset) ? 'border-primary ring-2 ring-primary' : 'border-black/[0.06] hover:border-primary/40'"
|
|
243
|
+
:aria-pressed="isSelected(asset)"
|
|
244
|
+
@click="toggle(asset)"
|
|
245
|
+
>
|
|
246
|
+
<img
|
|
247
|
+
v-if="thumbnailUrl(asset) && !failedThumbs.has(thumbnailUrl(asset))"
|
|
248
|
+
:src="thumbnailUrl(asset)"
|
|
249
|
+
:alt="asset.alt_text ?? titleOf(asset)"
|
|
250
|
+
class="h-full w-full object-cover"
|
|
251
|
+
:class="{ 'opacity-50': isProcessing(asset) }"
|
|
252
|
+
@error="markFailed(thumbnailUrl(asset))"
|
|
253
|
+
>
|
|
254
|
+
<span v-else class="flex h-full w-full items-center justify-center">
|
|
255
|
+
<FileText :size="28" class="text-foreground/30" />
|
|
256
|
+
</span>
|
|
257
|
+
<span class="absolute inset-x-0 bottom-0 bg-black/55 px-1.5 py-0.5 text-left text-[11px] text-white">
|
|
258
|
+
<span class="block truncate">{{ titleOf(asset) }}</span>
|
|
259
|
+
<span v-if="entryOf(asset)?.sub" class="block truncate text-white/75">{{ entryOf(asset).sub }}</span>
|
|
260
|
+
</span>
|
|
261
|
+
</button>
|
|
262
|
+
</div>
|
|
263
|
+
<ul v-else class="divide-y divide-black/[0.06] rounded-md border border-black/[0.06]">
|
|
264
|
+
<li v-for="asset in visibleAssets" :key="asset.id">
|
|
265
|
+
<button
|
|
266
|
+
type="button"
|
|
267
|
+
class="flex w-full items-center gap-3 px-2 py-1.5 text-left text-sm transition-colors"
|
|
268
|
+
:class="isSelected(asset) ? 'bg-primary/10' : 'hover:bg-primary/[0.04]'"
|
|
269
|
+
:aria-pressed="isSelected(asset)"
|
|
270
|
+
@click="toggle(asset)"
|
|
271
|
+
>
|
|
272
|
+
<span class="grid size-9 shrink-0 place-items-center overflow-hidden rounded border border-black/[0.06] bg-muted/40">
|
|
273
|
+
<img v-if="thumbnailUrl(asset, 80) && !failedThumbs.has(thumbnailUrl(asset, 80))" :src="thumbnailUrl(asset, 80)" alt="" class="h-full w-full object-cover" @error="markFailed(thumbnailUrl(asset, 80))">
|
|
274
|
+
<FileText v-else :size="16" class="text-foreground/30" />
|
|
275
|
+
</span>
|
|
276
|
+
<span class="min-w-0 flex-1">
|
|
277
|
+
<span class="block truncate font-medium text-[#0B0522]">{{ titleOf(asset) }}</span>
|
|
278
|
+
<span class="block truncate text-xs text-muted-foreground">{{ [entryOf(asset)?.sub, factsOf(asset)].filter(Boolean).join(" \xB7 ") }}</span>
|
|
279
|
+
</span>
|
|
280
|
+
<span v-if="!asset.alt_text && asset.kind === 'image'" class="shrink-0 rounded-full bg-amber-50 px-2 py-0.5 text-[11px] text-amber-700">{{ t("shared.media.picker.altMissing") }}</span>
|
|
281
|
+
</button>
|
|
282
|
+
</li>
|
|
283
|
+
</ul>
|
|
284
|
+
|
|
285
|
+
<div v-if="hasMore" ref="sentinel" class="mt-3 flex justify-center">
|
|
286
|
+
<Button variant="outline" size="sm" class="h-7 text-sm" :disabled="loadingAssets" @click="loadMore">
|
|
287
|
+
{{ t("shared.media.picker.action.loadmore") }}
|
|
288
|
+
</Button>
|
|
289
|
+
</div>
|
|
138
290
|
</div>
|
|
139
291
|
</div>
|
|
140
292
|
</div>
|
|
@@ -1,18 +1,30 @@
|
|
|
1
1
|
import type { StorageAsset } from '../../types/storage.js';
|
|
2
|
+
export interface PickerCatalogueEntry {
|
|
3
|
+
/** What the record is called — shown instead of the file name. */
|
|
4
|
+
title: string;
|
|
5
|
+
/** One quiet line under it: type, licence. */
|
|
6
|
+
sub?: string;
|
|
7
|
+
}
|
|
2
8
|
type __VLS_Props = {
|
|
3
9
|
open: boolean;
|
|
4
10
|
multiple?: boolean;
|
|
5
11
|
/** Restrict the grid to these asset kinds (e.g. ['image']). */
|
|
6
12
|
kinds?: string[];
|
|
13
|
+
/** Records that manage these files, keyed by storage id — see the header. */
|
|
14
|
+
catalogue?: Record<string, PickerCatalogueEntry> | null;
|
|
7
15
|
};
|
|
8
|
-
declare const
|
|
16
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
9
17
|
"update:open": (value: boolean) => any;
|
|
10
18
|
select: (assets: StorageAsset[]) => any;
|
|
19
|
+
uploaded: (assets: StorageAsset[]) => any;
|
|
11
20
|
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
12
21
|
"onUpdate:open"?: ((value: boolean) => any) | undefined;
|
|
13
22
|
onSelect?: ((assets: StorageAsset[]) => any) | undefined;
|
|
23
|
+
onUploaded?: ((assets: StorageAsset[]) => any) | undefined;
|
|
14
24
|
}>, {
|
|
15
25
|
multiple: boolean;
|
|
16
26
|
kinds: string[];
|
|
27
|
+
catalogue: Record<string, PickerCatalogueEntry> | null;
|
|
17
28
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
29
|
+
declare const _default: typeof __VLS_export;
|
|
18
30
|
export default _default;
|
|
@@ -13,7 +13,7 @@ type __VLS_Props = {
|
|
|
13
13
|
folderId: string | null;
|
|
14
14
|
folderName: string | null;
|
|
15
15
|
};
|
|
16
|
-
declare const
|
|
16
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
17
17
|
"update:open": (value: boolean) => any;
|
|
18
18
|
done: (summary: {
|
|
19
19
|
created: number;
|
|
@@ -26,4 +26,5 @@ declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {
|
|
|
26
26
|
failed: number;
|
|
27
27
|
}) => any) | undefined;
|
|
28
28
|
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
29
|
+
declare const _default: typeof __VLS_export;
|
|
29
30
|
export default _default;
|
|
@@ -82,7 +82,7 @@ const folderLabel = computed(() => props.folderName ?? t("shared.media.uploader.
|
|
|
82
82
|
|
|
83
83
|
<template>
|
|
84
84
|
<Dialog :open="open" @update:open="(v) => emit('update:open', v)">
|
|
85
|
-
<DialogContent class="max-w-
|
|
85
|
+
<DialogContent class="sm:max-w-xl">
|
|
86
86
|
<DialogHeader>
|
|
87
87
|
<DialogTitle>{{ t("shared.media.uploader.title") }}</DialogTitle>
|
|
88
88
|
<DialogDescription>
|
|
@@ -13,7 +13,7 @@ type __VLS_Props = {
|
|
|
13
13
|
folderId: string | null;
|
|
14
14
|
folderName: string | null;
|
|
15
15
|
};
|
|
16
|
-
declare const
|
|
16
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
17
17
|
"update:open": (value: boolean) => any;
|
|
18
18
|
done: (summary: {
|
|
19
19
|
created: number;
|
|
@@ -26,4 +26,5 @@ declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {
|
|
|
26
26
|
failed: number;
|
|
27
27
|
}) => any) | undefined;
|
|
28
28
|
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
29
|
+
declare const _default: typeof __VLS_export;
|
|
29
30
|
export default _default;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Component } from 'vue';
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
icon?: string | null;
|
|
4
|
+
navIcon?: string | null;
|
|
5
|
+
alt?: string;
|
|
6
|
+
/** Glyph size in px; also the box size when not `fill`. */
|
|
7
|
+
size?: number;
|
|
8
|
+
/** Fill the parent tile instead of drawing a `size`-px square. */
|
|
9
|
+
fill?: boolean;
|
|
10
|
+
fallback?: Component;
|
|
11
|
+
};
|
|
12
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
|
|
13
|
+
size: number;
|
|
14
|
+
icon: string | null;
|
|
15
|
+
fill: boolean;
|
|
16
|
+
alt: string;
|
|
17
|
+
navIcon: string | null;
|
|
18
|
+
fallback: Component;
|
|
19
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
20
|
+
declare const _default: typeof __VLS_export;
|
|
21
|
+
export default _default;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { computed, ref, watch } from "vue";
|
|
3
|
+
import { Box } from "#solar-icons";
|
|
4
|
+
import { appIconCandidates } from "../../lib/appIcon";
|
|
5
|
+
import { solarIcon } from "../../lib/solarIcons";
|
|
6
|
+
const props = defineProps({
|
|
7
|
+
icon: { type: [String, null], required: false, default: null },
|
|
8
|
+
navIcon: { type: [String, null], required: false, default: null },
|
|
9
|
+
alt: { type: String, required: false, default: "" },
|
|
10
|
+
size: { type: Number, required: false, default: 14 },
|
|
11
|
+
fill: { type: Boolean, required: false, default: false },
|
|
12
|
+
fallback: { type: null, required: false, default: void 0 }
|
|
13
|
+
});
|
|
14
|
+
const failed = ref(/* @__PURE__ */ new Set());
|
|
15
|
+
watch(() => props.icon, () => {
|
|
16
|
+
failed.value = /* @__PURE__ */ new Set();
|
|
17
|
+
});
|
|
18
|
+
const resolved = computed(() => {
|
|
19
|
+
for (const c of appIconCandidates(props.icon, props.navIcon)) {
|
|
20
|
+
if (c.kind === "file") {
|
|
21
|
+
if (!failed.value.has(c.src)) return { src: c.src };
|
|
22
|
+
continue;
|
|
23
|
+
}
|
|
24
|
+
const glyph = solarIcon(c.name);
|
|
25
|
+
if (glyph) return { glyph };
|
|
26
|
+
}
|
|
27
|
+
return { glyph: props.fallback ?? Box };
|
|
28
|
+
});
|
|
29
|
+
const box = computed(() => props.fill ? void 0 : { width: `${props.size}px`, height: `${props.size}px` });
|
|
30
|
+
function onError(src) {
|
|
31
|
+
failed.value = new Set(failed.value).add(src);
|
|
32
|
+
}
|
|
33
|
+
</script>
|
|
34
|
+
|
|
35
|
+
<template>
|
|
36
|
+
<span class="inline-flex shrink-0 items-center justify-center" :class="fill ? 'size-full' : ''" :style="box">
|
|
37
|
+
<img
|
|
38
|
+
v-if="'src' in resolved"
|
|
39
|
+
:src="resolved.src"
|
|
40
|
+
:alt="alt"
|
|
41
|
+
class="size-full object-contain"
|
|
42
|
+
data-app-icon="file"
|
|
43
|
+
@error="onError(resolved.src)"
|
|
44
|
+
>
|
|
45
|
+
<component :is="resolved.glyph" v-else :size="size" data-app-icon="glyph" />
|
|
46
|
+
</span>
|
|
47
|
+
</template>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Component } from 'vue';
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
icon?: string | null;
|
|
4
|
+
navIcon?: string | null;
|
|
5
|
+
alt?: string;
|
|
6
|
+
/** Glyph size in px; also the box size when not `fill`. */
|
|
7
|
+
size?: number;
|
|
8
|
+
/** Fill the parent tile instead of drawing a `size`-px square. */
|
|
9
|
+
fill?: boolean;
|
|
10
|
+
fallback?: Component;
|
|
11
|
+
};
|
|
12
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
|
|
13
|
+
size: number;
|
|
14
|
+
icon: string | null;
|
|
15
|
+
fill: boolean;
|
|
16
|
+
alt: string;
|
|
17
|
+
navIcon: string | null;
|
|
18
|
+
fallback: Component;
|
|
19
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
20
|
+
declare const _default: typeof __VLS_export;
|
|
21
|
+
export default _default;
|
|
@@ -20,11 +20,12 @@ type __VLS_Props = {
|
|
|
20
20
|
userPinned?: boolean;
|
|
21
21
|
error?: string | null;
|
|
22
22
|
};
|
|
23
|
-
declare const
|
|
23
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
24
24
|
"update:open": (args_0: boolean) => any;
|
|
25
25
|
refresh: () => any;
|
|
26
26
|
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
27
27
|
"onUpdate:open"?: ((args_0: boolean) => any) | undefined;
|
|
28
28
|
onRefresh?: (() => any) | undefined;
|
|
29
29
|
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
30
|
+
declare const _default: typeof __VLS_export;
|
|
30
31
|
export default _default;
|
|
@@ -20,11 +20,12 @@ type __VLS_Props = {
|
|
|
20
20
|
userPinned?: boolean;
|
|
21
21
|
error?: string | null;
|
|
22
22
|
};
|
|
23
|
-
declare const
|
|
23
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
24
24
|
"update:open": (args_0: boolean) => any;
|
|
25
25
|
refresh: () => any;
|
|
26
26
|
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
27
27
|
"onUpdate:open"?: ((args_0: boolean) => any) | undefined;
|
|
28
28
|
onRefresh?: (() => any) | undefined;
|
|
29
29
|
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
30
|
+
declare const _default: typeof __VLS_export;
|
|
30
31
|
export default _default;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { CardSize } from '../../lib/cardSize.js';
|
|
2
|
+
type __VLS_ModelProps = {
|
|
3
|
+
modelValue?: CardSize;
|
|
4
|
+
};
|
|
5
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
6
|
+
"update:modelValue": (value: CardSize) => any;
|
|
7
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_ModelProps> & Readonly<{
|
|
8
|
+
"onUpdate:modelValue"?: ((value: CardSize) => any) | undefined;
|
|
9
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
10
|
+
declare const _default: typeof __VLS_export;
|
|
11
|
+
export default _default;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { HamburgerMenu, List } from "#solar-icons";
|
|
3
|
+
import { SegmentedToggle, SegmentedToggleItem } from "@revenexx/studio";
|
|
4
|
+
import { useT } from "../../composables/useT";
|
|
5
|
+
const size = defineModel({ type: String, ...{ default: "comfortable" } });
|
|
6
|
+
const t = useT();
|
|
7
|
+
const ITEM = "transition-colors data-[state=on]:text-primary data-[state=off]:hover:text-primary!";
|
|
8
|
+
</script>
|
|
9
|
+
|
|
10
|
+
<template>
|
|
11
|
+
<SegmentedToggle v-model="size" variant="inset" :aria-label="t('shared.cardSize.label')" data-test="card-size">
|
|
12
|
+
<SegmentedToggleItem value="comfortable" :aria-label="t('shared.cardSize.comfortable')" :class="ITEM">
|
|
13
|
+
<List :size="14" weight="Bold" />
|
|
14
|
+
</SegmentedToggleItem>
|
|
15
|
+
<SegmentedToggleItem value="compact" :aria-label="t('shared.cardSize.compact')" :class="ITEM">
|
|
16
|
+
<HamburgerMenu :size="14" weight="Linear" />
|
|
17
|
+
</SegmentedToggleItem>
|
|
18
|
+
</SegmentedToggle>
|
|
19
|
+
</template>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { CardSize } from '../../lib/cardSize.js';
|
|
2
|
+
type __VLS_ModelProps = {
|
|
3
|
+
modelValue?: CardSize;
|
|
4
|
+
};
|
|
5
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
6
|
+
"update:modelValue": (value: CardSize) => any;
|
|
7
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_ModelProps> & Readonly<{
|
|
8
|
+
"onUpdate:modelValue"?: ((value: CardSize) => any) | undefined;
|
|
9
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
10
|
+
declare const _default: typeof __VLS_export;
|
|
11
|
+
export default _default;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
type __VLS_Props = {
|
|
2
|
+
open: boolean;
|
|
3
|
+
/** Accessible name of the panel — normally the record's title. */
|
|
4
|
+
label: string;
|
|
5
|
+
/** The body is still fetching: `aria-busy` plus a spoken "loading". */
|
|
6
|
+
busy?: boolean;
|
|
7
|
+
/** Panel width in the wide layout. */
|
|
8
|
+
width?: string;
|
|
9
|
+
/** Distance from the viewport top in the wide layout — clears the top bar. */
|
|
10
|
+
top?: string;
|
|
11
|
+
/** Where focus goes on close. Defaults to the element focused at open. */
|
|
12
|
+
returnFocus?: () => HTMLElement | null | undefined;
|
|
13
|
+
/** Which neighbours exist — draws the previous/next buttons. Omit for none. */
|
|
14
|
+
canStep?: {
|
|
15
|
+
prev: boolean;
|
|
16
|
+
next: boolean;
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
declare var __VLS_13: {}, __VLS_30: {
|
|
20
|
+
layout: string;
|
|
21
|
+
}, __VLS_32: {}, __VLS_61: {}, __VLS_73: {}, __VLS_75: {
|
|
22
|
+
layout: string;
|
|
23
|
+
};
|
|
24
|
+
type __VLS_Slots = {} & {
|
|
25
|
+
header?: (props: typeof __VLS_13) => any;
|
|
26
|
+
} & {
|
|
27
|
+
actions?: (props: typeof __VLS_30) => any;
|
|
28
|
+
} & {
|
|
29
|
+
default?: (props: typeof __VLS_32) => any;
|
|
30
|
+
} & {
|
|
31
|
+
header?: (props: typeof __VLS_61) => any;
|
|
32
|
+
} & {
|
|
33
|
+
default?: (props: typeof __VLS_73) => any;
|
|
34
|
+
} & {
|
|
35
|
+
actions?: (props: typeof __VLS_75) => any;
|
|
36
|
+
};
|
|
37
|
+
declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
38
|
+
"update:open": (open: boolean) => any;
|
|
39
|
+
step: (dir: 1 | -1) => any;
|
|
40
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
41
|
+
"onUpdate:open"?: ((open: boolean) => any) | undefined;
|
|
42
|
+
onStep?: ((dir: 1 | -1) => any) | undefined;
|
|
43
|
+
}>, {
|
|
44
|
+
busy: boolean;
|
|
45
|
+
width: string;
|
|
46
|
+
top: string;
|
|
47
|
+
returnFocus: () => HTMLElement | null | undefined;
|
|
48
|
+
canStep: {
|
|
49
|
+
prev: boolean;
|
|
50
|
+
next: boolean;
|
|
51
|
+
};
|
|
52
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
53
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
54
|
+
declare const _default: typeof __VLS_export;
|
|
55
|
+
export default _default;
|
|
56
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
57
|
+
new (): {
|
|
58
|
+
$slots: S;
|
|
59
|
+
};
|
|
60
|
+
};
|