nuxt-media-library 0.0.44

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 (164) hide show
  1. package/README.md +243 -0
  2. package/dist/module.d.mts +31 -0
  3. package/dist/module.d.ts +31 -0
  4. package/dist/module.json +9 -0
  5. package/dist/module.mjs +118 -0
  6. package/dist/runtime/components/MLAssetManager/AssetActivity.d.vue.ts +6 -0
  7. package/dist/runtime/components/MLAssetManager/AssetActivity.vue +13 -0
  8. package/dist/runtime/components/MLAssetManager/AssetActivity.vue.d.ts +6 -0
  9. package/dist/runtime/components/MLAssetManager/AssetCard.d.vue.ts +14 -0
  10. package/dist/runtime/components/MLAssetManager/AssetCard.vue +100 -0
  11. package/dist/runtime/components/MLAssetManager/AssetCard.vue.d.ts +14 -0
  12. package/dist/runtime/components/MLAssetManager/AssetDetail.d.vue.ts +14 -0
  13. package/dist/runtime/components/MLAssetManager/AssetDetail.vue +156 -0
  14. package/dist/runtime/components/MLAssetManager/AssetDetail.vue.d.ts +14 -0
  15. package/dist/runtime/components/MLAssetManager/AssetList.d.vue.ts +15 -0
  16. package/dist/runtime/components/MLAssetManager/AssetList.vue +41 -0
  17. package/dist/runtime/components/MLAssetManager/AssetList.vue.d.ts +15 -0
  18. package/dist/runtime/components/MLAssetManager/AssetOverview.d.vue.ts +8 -0
  19. package/dist/runtime/components/MLAssetManager/AssetOverview.vue +321 -0
  20. package/dist/runtime/components/MLAssetManager/AssetOverview.vue.d.ts +8 -0
  21. package/dist/runtime/components/MLAssetManager/AssetPreview.d.vue.ts +10 -0
  22. package/dist/runtime/components/MLAssetManager/AssetPreview.vue +18 -0
  23. package/dist/runtime/components/MLAssetManager/AssetPreview.vue.d.ts +10 -0
  24. package/dist/runtime/components/MLAssetManager/AssetPreviewAudio.d.vue.ts +9 -0
  25. package/dist/runtime/components/MLAssetManager/AssetPreviewAudio.vue +21 -0
  26. package/dist/runtime/components/MLAssetManager/AssetPreviewAudio.vue.d.ts +9 -0
  27. package/dist/runtime/components/MLAssetManager/AssetPreviewDocument.d.vue.ts +9 -0
  28. package/dist/runtime/components/MLAssetManager/AssetPreviewDocument.vue +39 -0
  29. package/dist/runtime/components/MLAssetManager/AssetPreviewDocument.vue.d.ts +9 -0
  30. package/dist/runtime/components/MLAssetManager/AssetPreviewFallback.d.vue.ts +7 -0
  31. package/dist/runtime/components/MLAssetManager/AssetPreviewFallback.vue +41 -0
  32. package/dist/runtime/components/MLAssetManager/AssetPreviewFallback.vue.d.ts +7 -0
  33. package/dist/runtime/components/MLAssetManager/AssetPreviewImage.d.vue.ts +9 -0
  34. package/dist/runtime/components/MLAssetManager/AssetPreviewImage.vue +30 -0
  35. package/dist/runtime/components/MLAssetManager/AssetPreviewImage.vue.d.ts +9 -0
  36. package/dist/runtime/components/MLAssetManager/AssetPreviewSidebar.d.vue.ts +15 -0
  37. package/dist/runtime/components/MLAssetManager/AssetPreviewSidebar.vue +69 -0
  38. package/dist/runtime/components/MLAssetManager/AssetPreviewSidebar.vue.d.ts +15 -0
  39. package/dist/runtime/components/MLAssetManager/AssetPreviewVideo.d.vue.ts +9 -0
  40. package/dist/runtime/components/MLAssetManager/AssetPreviewVideo.vue +148 -0
  41. package/dist/runtime/components/MLAssetManager/AssetPreviewVideo.vue.d.ts +9 -0
  42. package/dist/runtime/components/MLAssetManager/AssetRenditions.d.vue.ts +8 -0
  43. package/dist/runtime/components/MLAssetManager/AssetRenditions.vue +148 -0
  44. package/dist/runtime/components/MLAssetManager/AssetRenditions.vue.d.ts +8 -0
  45. package/dist/runtime/components/MLAssetManager/Processing.d.vue.ts +8 -0
  46. package/dist/runtime/components/MLAssetManager/Processing.vue +84 -0
  47. package/dist/runtime/components/MLAssetManager/Processing.vue.d.ts +8 -0
  48. package/dist/runtime/components/MLAssetManager/SlotCard.d.vue.ts +17 -0
  49. package/dist/runtime/components/MLAssetManager/SlotCard.vue +94 -0
  50. package/dist/runtime/components/MLAssetManager/SlotCard.vue.d.ts +17 -0
  51. package/dist/runtime/components/MLAssetManager/Widget.d.vue.ts +14 -0
  52. package/dist/runtime/components/MLAssetManager/Widget.vue +328 -0
  53. package/dist/runtime/components/MLAssetManager/Widget.vue.d.ts +14 -0
  54. package/dist/runtime/components/MLPreviewProvider.d.vue.ts +31 -0
  55. package/dist/runtime/components/MLPreviewProvider.vue +51 -0
  56. package/dist/runtime/components/MLPreviewProvider.vue.d.ts +31 -0
  57. package/dist/runtime/components/MLProcessing/Forms/ConfigureStepModal.d.vue.ts +13 -0
  58. package/dist/runtime/components/MLProcessing/Forms/ConfigureStepModal.vue +47 -0
  59. package/dist/runtime/components/MLProcessing/Forms/ConfigureStepModal.vue.d.ts +13 -0
  60. package/dist/runtime/components/MLProcessing/Forms/FramePicker.d.vue.ts +11 -0
  61. package/dist/runtime/components/MLProcessing/Forms/FramePicker.vue +162 -0
  62. package/dist/runtime/components/MLProcessing/Forms/FramePicker.vue.d.ts +11 -0
  63. package/dist/runtime/components/MLProcessing/Forms/StepOptionsForm.d.vue.ts +14 -0
  64. package/dist/runtime/components/MLProcessing/Forms/StepOptionsForm.vue +113 -0
  65. package/dist/runtime/components/MLProcessing/Forms/StepOptionsForm.vue.d.ts +14 -0
  66. package/dist/runtime/components/MLProcessing/Pipeline.d.vue.ts +15 -0
  67. package/dist/runtime/components/MLProcessing/Pipeline.vue +178 -0
  68. package/dist/runtime/components/MLProcessing/Pipeline.vue.d.ts +15 -0
  69. package/dist/runtime/components/MLProcessing/PipelineStepItem.d.vue.ts +20 -0
  70. package/dist/runtime/components/MLProcessing/PipelineStepItem.vue +309 -0
  71. package/dist/runtime/components/MLProcessing/PipelineStepItem.vue.d.ts +20 -0
  72. package/dist/runtime/components/MLProcessing/ProgressBar.d.vue.ts +9 -0
  73. package/dist/runtime/components/MLProcessing/ProgressBar.vue +27 -0
  74. package/dist/runtime/components/MLProcessing/ProgressBar.vue.d.ts +9 -0
  75. package/dist/runtime/components/MLProcessing/StepLayout.d.vue.ts +31 -0
  76. package/dist/runtime/components/MLProcessing/StepLayout.vue +36 -0
  77. package/dist/runtime/components/MLProcessing/StepLayout.vue.d.ts +31 -0
  78. package/dist/runtime/components/MLProcessing/Stepper.d.vue.ts +16 -0
  79. package/dist/runtime/components/MLProcessing/Stepper.vue +87 -0
  80. package/dist/runtime/components/MLProcessing/Stepper.vue.d.ts +16 -0
  81. package/dist/runtime/components/MLProcessing/StepperItem.d.vue.ts +16 -0
  82. package/dist/runtime/components/MLProcessing/StepperItem.vue +150 -0
  83. package/dist/runtime/components/MLProcessing/StepperItem.vue.d.ts +16 -0
  84. package/dist/runtime/components/MLProcessing/TopBar.d.vue.ts +21 -0
  85. package/dist/runtime/components/MLProcessing/TopBar.vue +46 -0
  86. package/dist/runtime/components/MLProcessing/TopBar.vue.d.ts +21 -0
  87. package/dist/runtime/components/MLUploader/ButtonUploader.d.vue.ts +55 -0
  88. package/dist/runtime/components/MLUploader/ButtonUploader.vue +211 -0
  89. package/dist/runtime/components/MLUploader/ButtonUploader.vue.d.ts +55 -0
  90. package/dist/runtime/components/MLUploader/Item.d.vue.ts +34 -0
  91. package/dist/runtime/components/MLUploader/Item.vue +242 -0
  92. package/dist/runtime/components/MLUploader/Item.vue.d.ts +34 -0
  93. package/dist/runtime/components/MLUploader/PolicyPopover.d.vue.ts +7 -0
  94. package/dist/runtime/components/MLUploader/PolicyPopover.vue +160 -0
  95. package/dist/runtime/components/MLUploader/PolicyPopover.vue.d.ts +7 -0
  96. package/dist/runtime/components/MLUploader/Widget.d.vue.ts +44 -0
  97. package/dist/runtime/components/MLUploader/Widget.vue +251 -0
  98. package/dist/runtime/components/MLUploader/Widget.vue.d.ts +44 -0
  99. package/dist/runtime/composables/resourcePolicy/mimeUtils.d.ts +4 -0
  100. package/dist/runtime/composables/resourcePolicy/mimeUtils.js +71 -0
  101. package/dist/runtime/composables/resourcePolicy/useMLResourcePolicy.d.ts +17 -0
  102. package/dist/runtime/composables/resourcePolicy/useMLResourcePolicy.js +150 -0
  103. package/dist/runtime/composables/useElapsedTimer.d.ts +13 -0
  104. package/dist/runtime/composables/useElapsedTimer.js +46 -0
  105. package/dist/runtime/composables/useMLAssetLibrary.d.ts +31 -0
  106. package/dist/runtime/composables/useMLAssetLibrary.js +53 -0
  107. package/dist/runtime/composables/useMLAssetManager.d.ts +30 -0
  108. package/dist/runtime/composables/useMLAssetManager.js +229 -0
  109. package/dist/runtime/composables/useMLAssetManagerPreview.d.ts +28 -0
  110. package/dist/runtime/composables/useMLAssetManagerPreview.js +232 -0
  111. package/dist/runtime/composables/useMLAssetPreview.d.ts +23 -0
  112. package/dist/runtime/composables/useMLAssetPreview.js +153 -0
  113. package/dist/runtime/composables/useMLChunkUploader.d.ts +9 -0
  114. package/dist/runtime/composables/useMLChunkUploader.js +22 -0
  115. package/dist/runtime/composables/useMLProcessingPipeline.d.ts +38 -0
  116. package/dist/runtime/composables/useMLProcessingPipeline.js +258 -0
  117. package/dist/runtime/composables/useMLProcessingStatus.d.ts +34 -0
  118. package/dist/runtime/composables/useMLProcessingStatus.js +100 -0
  119. package/dist/runtime/composables/useMLProcessingStepper.d.ts +32 -0
  120. package/dist/runtime/composables/useMLProcessingStepper.js +280 -0
  121. package/dist/runtime/composables/useMLProcessingStrategies.d.ts +7 -0
  122. package/dist/runtime/composables/useMLProcessingStrategies.js +47 -0
  123. package/dist/runtime/composables/useMLRepeater.d.ts +5 -0
  124. package/dist/runtime/composables/useMLRepeater.js +11 -0
  125. package/dist/runtime/css/index.css +1 -0
  126. package/dist/runtime/index.d.ts +13 -0
  127. package/dist/runtime/index.js +13 -0
  128. package/dist/runtime/plugins/asset-direcetive-client.d.ts +2 -0
  129. package/dist/runtime/plugins/asset-direcetive-client.js +64 -0
  130. package/dist/runtime/plugins/config.d.ts +13 -0
  131. package/dist/runtime/plugins/config.js +23 -0
  132. package/dist/runtime/schemas/resource-policy.schema.d.ts +607 -0
  133. package/dist/runtime/schemas/resource-policy.schema.js +117 -0
  134. package/dist/runtime/server/assets-proxy.d.ts +2 -0
  135. package/dist/runtime/server/assets-proxy.js +81 -0
  136. package/dist/runtime/server/create-ml-proxy.d.ts +47 -0
  137. package/dist/runtime/server/create-ml-proxy.js +232 -0
  138. package/dist/runtime/server/delivery-proxy.d.ts +2 -0
  139. package/dist/runtime/server/delivery-proxy.js +74 -0
  140. package/dist/runtime/server/index.d.ts +2 -0
  141. package/dist/runtime/server/index.js +1 -0
  142. package/dist/runtime/server/processing-proxy.d.ts +2 -0
  143. package/dist/runtime/server/processing-proxy.js +55 -0
  144. package/dist/runtime/server/resource-policy-proxy.d.ts +2 -0
  145. package/dist/runtime/server/resource-policy-proxy.js +80 -0
  146. package/dist/runtime/server/tsconfig.json +0 -0
  147. package/dist/runtime/server/uploads-proxy.d.ts +2 -0
  148. package/dist/runtime/server/uploads-proxy.js +99 -0
  149. package/dist/runtime/types/asset.d.ts +174 -0
  150. package/dist/runtime/types/asset.js +7 -0
  151. package/dist/runtime/types/preview.d.ts +20 -0
  152. package/dist/runtime/types/preview.js +0 -0
  153. package/dist/runtime/types/resourcePolicy.d.ts +77 -0
  154. package/dist/runtime/types/resourcePolicy.js +25 -0
  155. package/dist/runtime/types/uploader.d.ts +71 -0
  156. package/dist/runtime/types/uploader.js +0 -0
  157. package/dist/runtime/utils/uploader/checksum.d.ts +21 -0
  158. package/dist/runtime/utils/uploader/checksum.js +23 -0
  159. package/dist/runtime/utils/uploader/chunking.d.ts +8 -0
  160. package/dist/runtime/utils/uploader/chunking.js +21 -0
  161. package/dist/runtime/utils/uploader/uploader.d.ts +20 -0
  162. package/dist/runtime/utils/uploader/uploader.js +206 -0
  163. package/dist/types.d.mts +11 -0
  164. package/package.json +81 -0
@@ -0,0 +1,31 @@
1
+ type __VLS_Props = {
2
+ assetId?: string | null;
3
+ fallbackSrc?: string | null;
4
+ autoRegister?: boolean;
5
+ };
6
+ declare var __VLS_1: {
7
+ asset: import("../types/preview.js").AssetPreview | undefined;
8
+ src: string | null;
9
+ broken: boolean;
10
+ forbidden: boolean;
11
+ loading: boolean;
12
+ renditions: import("..").DeliveryRendition[];
13
+ sources: import("../types/preview.js").AssetSource[];
14
+ thumbnailUrl: string | null;
15
+ status: string | null;
16
+ refresh: () => Promise<void>;
17
+ };
18
+ type __VLS_Slots = {} & {
19
+ default?: (props: typeof __VLS_1) => any;
20
+ };
21
+ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
22
+ autoRegister: boolean;
23
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
24
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
25
+ declare const _default: typeof __VLS_export;
26
+ export default _default;
27
+ type __VLS_WithSlots<T, S> = T & {
28
+ new (): {
29
+ $slots: S;
30
+ };
31
+ };
@@ -0,0 +1,13 @@
1
+ import type { PipelineOptionSchema } from "../../../types/asset.js";
2
+ type __VLS_Props = {
3
+ taskType: string;
4
+ schema: Record<string, PipelineOptionSchema>;
5
+ downloadUrl?: string | null;
6
+ };
7
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
8
+ close: (result?: Record<string, any> | undefined) => any;
9
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
10
+ onClose?: ((result?: Record<string, any> | undefined) => any) | undefined;
11
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
12
+ declare const _default: typeof __VLS_export;
13
+ export default _default;
@@ -0,0 +1,47 @@
1
+ <script setup>
2
+ import { ref } from "vue";
3
+ const props = defineProps({
4
+ taskType: { type: String, required: true },
5
+ schema: { type: Object, required: true },
6
+ downloadUrl: { type: [String, null], required: false }
7
+ });
8
+ const emit = defineEmits(["close"]);
9
+ const title = props.taskType.replace(/_/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
10
+ const initialOptions = {};
11
+ for (const [key, opt] of Object.entries(props.schema)) {
12
+ if (opt.default !== void 0) initialOptions[key] = opt.default;
13
+ }
14
+ const options = ref(initialOptions);
15
+ function submit() {
16
+ emit("close", options.value);
17
+ }
18
+ </script>
19
+
20
+ <template>
21
+ <UModal :title="`Configure ${title}`" @update:open="(v) => !v && emit('close')">
22
+ <template #body>
23
+ <MLProcessingFormsFramePicker
24
+ v-if="taskType === 'video_thumbnail'"
25
+ :download-url="downloadUrl ?? null"
26
+ v-model="options"
27
+ />
28
+
29
+ <MLProcessingFormsStepOptionsForm
30
+ v-else-if="Object.keys(schema).length"
31
+ :schema="schema"
32
+ v-model="options"
33
+ />
34
+
35
+ <div v-else class="text-sm text-muted">
36
+ No configurable options for this step.
37
+ </div>
38
+ </template>
39
+
40
+ <template #footer>
41
+ <div class="flex justify-end gap-2">
42
+ <UButton variant="outline" color="neutral" label="Cancel" @click="emit('close')" />
43
+ <UButton color="primary" label="Apply & Start" @click="submit" />
44
+ </div>
45
+ </template>
46
+ </UModal>
47
+ </template>
@@ -0,0 +1,13 @@
1
+ import type { PipelineOptionSchema } from "../../../types/asset.js";
2
+ type __VLS_Props = {
3
+ taskType: string;
4
+ schema: Record<string, PipelineOptionSchema>;
5
+ downloadUrl?: string | null;
6
+ };
7
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
8
+ close: (result?: Record<string, any> | undefined) => any;
9
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
10
+ onClose?: ((result?: Record<string, any> | undefined) => any) | undefined;
11
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
12
+ declare const _default: typeof __VLS_export;
13
+ export default _default;
@@ -0,0 +1,11 @@
1
+ type __VLS_Props = {
2
+ downloadUrl: string | null;
3
+ modelValue: Record<string, any>;
4
+ };
5
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
6
+ "update:modelValue": (value: Record<string, any>) => any;
7
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
8
+ "onUpdate:modelValue"?: ((value: Record<string, any>) => any) | undefined;
9
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
10
+ declare const _default: typeof __VLS_export;
11
+ export default _default;
@@ -0,0 +1,162 @@
1
+ <script setup>
2
+ import { computed, ref, watch } from "vue";
3
+ const props = defineProps({
4
+ downloadUrl: { type: [String, null], required: true },
5
+ modelValue: { type: Object, required: true }
6
+ });
7
+ const emit = defineEmits(["update:modelValue"]);
8
+ const videoEl = ref(null);
9
+ function parseTimestamp(val) {
10
+ if (typeof val === "number") return val;
11
+ if (typeof val === "string") {
12
+ const parts = val.split(":").map(Number);
13
+ if (parts.length === 3) return (parts[0] ?? 0) * 3600 + (parts[1] ?? 0) * 60 + (parts[2] ?? 0);
14
+ if (parts.length === 2) return (parts[0] ?? 0) * 60 + (parts[1] ?? 0);
15
+ const num = Number(val);
16
+ if (!Number.isNaN(num)) return num;
17
+ }
18
+ return 1;
19
+ }
20
+ const duration = ref(0);
21
+ const currentTimestamp = ref(parseTimestamp(props.modelValue.timestamp));
22
+ const seeking = ref(false);
23
+ const sizeOptions = ["default", "medium", "high", "standard", "maxres"];
24
+ const selectedSizes = computed(
25
+ () => Array.isArray(props.modelValue.sizes) ? props.modelValue.sizes : []
26
+ );
27
+ function formatTimestamp(secs) {
28
+ const h = Math.floor(secs / 3600);
29
+ const m = Math.floor(secs % 3600 / 60);
30
+ const s = secs % 60;
31
+ if (h > 0) return `${h}:${String(m).padStart(2, "0")}:${s.toFixed(1).padStart(4, "0")}`;
32
+ return `${m}:${s.toFixed(1).padStart(4, "0")}`;
33
+ }
34
+ function onMetadata() {
35
+ if (videoEl.value) {
36
+ duration.value = videoEl.value.duration || 0;
37
+ }
38
+ }
39
+ function onSeeked() {
40
+ seeking.value = false;
41
+ }
42
+ function seekTo(time) {
43
+ const clamped = Math.max(0, Math.min(time, duration.value));
44
+ currentTimestamp.value = clamped;
45
+ if (videoEl.value) {
46
+ seeking.value = true;
47
+ videoEl.value.currentTime = clamped;
48
+ }
49
+ emitUpdate(clamped);
50
+ }
51
+ function onSliderChange(value) {
52
+ const v = Array.isArray(value) ? value[0] : value;
53
+ if (v != null) seekTo(v);
54
+ }
55
+ function onManualInput(value) {
56
+ const num = Number.parseFloat(value);
57
+ if (!Number.isNaN(num) && num >= 0) {
58
+ seekTo(num);
59
+ }
60
+ }
61
+ function emitUpdate(timestamp) {
62
+ emit("update:modelValue", { ...props.modelValue, timestamp });
63
+ }
64
+ function onSizesChange(sizes) {
65
+ emit("update:modelValue", { ...props.modelValue, sizes, timestamp: currentTimestamp.value });
66
+ }
67
+ watch(() => props.modelValue.timestamp, (val) => {
68
+ const parsed = parseTimestamp(val);
69
+ if (parsed !== currentTimestamp.value) {
70
+ currentTimestamp.value = parsed;
71
+ }
72
+ });
73
+ const quickJumps = [0, 25, 50, 75, 100];
74
+ </script>
75
+
76
+ <template>
77
+ <div class="flex gap-4">
78
+ <!-- Video Preview -->
79
+ <div class="flex-1 /crelative rounded-lg overflow-hidden bg-black aspect-video">
80
+ <div class="">
81
+ <video
82
+ v-if="downloadUrl"
83
+ ref="videoEl"
84
+ :src="downloadUrl"
85
+ crossorigin="anonymous"
86
+ preload="metadata"
87
+ muted
88
+ class="w-full h-full object-contain"
89
+ @loadedmetadata="onMetadata"
90
+ @seeked="onSeeked"
91
+ />
92
+
93
+ <div v-else class="flex items-center justify-center h-full text-muted text-sm">
94
+ <div class="text-center">
95
+ <UIcon name="i-lucide-video-off" class="size-8 mb-2"/>
96
+ <div>Video preview unavailable</div>
97
+ <div class="text-xs mt-1">Enter timestamp manually below</div>
98
+ </div>
99
+ </div>
100
+
101
+ <!-- Seeking indicator -->
102
+ <div v-if="seeking" class="absolute inset-0 flex items-center justify-center bg-black/30">
103
+ <UIcon name="i-lucide-loader" class="size-6 text-white animate-spin"/>
104
+ </div>
105
+ </div>
106
+ <!-- Scrubber -->
107
+ <div v-if="duration > 0" class="space-y-2">
108
+ <USlider
109
+ :model-value="currentTimestamp"
110
+ :min="0"
111
+ :max="duration"
112
+ :step="0.1"
113
+ size="sm"
114
+ @update:model-value="onSliderChange"
115
+ />
116
+ <div class="flex items-center justify-between text-xs text-muted">
117
+ <span>{{ formatTimestamp(currentTimestamp) }}</span>
118
+ <span>{{ formatTimestamp(duration) }}</span>
119
+ </div>
120
+
121
+ <!-- Quick jump buttons -->
122
+ <div class="flex gap-1">
123
+ <UButton
124
+ v-for="pct in quickJumps"
125
+ :key="pct"
126
+ size="xs"
127
+ variant="ghost"
128
+ color="neutral"
129
+ :label="`${pct}%`"
130
+ @click="seekTo(duration * pct / 100)"
131
+ />
132
+ </div>
133
+ </div>
134
+
135
+ <!-- Manual timestamp input (always shown as fallback/alternative) -->
136
+ <UFormField label="Timestamp (seconds)">
137
+ <UInput
138
+ type="number"
139
+ :model-value="currentTimestamp"
140
+ :min="0"
141
+ :max="duration || void 0"
142
+ :step="0.1"
143
+ size="sm"
144
+ class="w-40"
145
+ @update:model-value="onManualInput(String($event))"
146
+ />
147
+ </UFormField>
148
+ </div>
149
+
150
+ <div class="flex-1">
151
+
152
+ <!-- Thumbnail sizes -->
153
+ <UCheckboxGroup
154
+ legend="Sizes"
155
+ :items="sizeOptions"
156
+ :model-value="selectedSizes"
157
+ @update:model-value="onSizesChange"
158
+ />
159
+ </div>
160
+
161
+ </div>
162
+ </template>
@@ -0,0 +1,11 @@
1
+ type __VLS_Props = {
2
+ downloadUrl: string | null;
3
+ modelValue: Record<string, any>;
4
+ };
5
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
6
+ "update:modelValue": (value: Record<string, any>) => any;
7
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
8
+ "onUpdate:modelValue"?: ((value: Record<string, any>) => any) | undefined;
9
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
10
+ declare const _default: typeof __VLS_export;
11
+ export default _default;
@@ -0,0 +1,14 @@
1
+ import type { PipelineOptionSchema } from "../../../types/asset.js";
2
+ type __VLS_Props = {
3
+ schema: Record<string, PipelineOptionSchema>;
4
+ modelValue: Record<string, any>;
5
+ /** Keys to exclude from rendering (handled elsewhere, e.g., timestamp in FramePicker) */
6
+ exclude?: string[];
7
+ };
8
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
9
+ "update:modelValue": (value: Record<string, any>) => any;
10
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
11
+ "onUpdate:modelValue"?: ((value: Record<string, any>) => any) | undefined;
12
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
13
+ declare const _default: typeof __VLS_export;
14
+ export default _default;
@@ -0,0 +1,113 @@
1
+ <script setup>
2
+ import { computed } from "vue";
3
+ const props = defineProps({
4
+ schema: { type: Object, required: true },
5
+ modelValue: { type: Object, required: true },
6
+ exclude: { type: Array, required: false }
7
+ });
8
+ const emit = defineEmits(["update:modelValue"]);
9
+ const entries = computed(() => {
10
+ const excluded = new Set(props.exclude ?? []);
11
+ return Object.entries(props.schema).filter(([key]) => !excluded.has(key));
12
+ });
13
+ function formatLabel(key) {
14
+ return key.replace(/_/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
15
+ }
16
+ function update(key, value) {
17
+ emit("update:modelValue", { ...props.modelValue, [key]: value });
18
+ }
19
+ function toggleArrayItem(key, item) {
20
+ const current = Array.isArray(props.modelValue[key]) ? [...props.modelValue[key]] : [];
21
+ const idx = current.indexOf(item);
22
+ if (idx >= 0) current.splice(idx, 1);
23
+ else current.push(item);
24
+ update(key, current);
25
+ }
26
+ function isArrayItemSelected(key, item) {
27
+ const current = props.modelValue[key];
28
+ return Array.isArray(current) && current.includes(item);
29
+ }
30
+ </script>
31
+
32
+ <template>
33
+ <div class="space-y-3">
34
+ <div v-for="([key, opt]) in entries" :key="key">
35
+ <!-- String with allowed values → Select -->
36
+ <UFormField v-if="opt.type === 'string' && opt.allowed_values?.length" :label="formatLabel(key)">
37
+ <USelect
38
+ :model-value="modelValue[key] ?? opt.default"
39
+ :items="opt.allowed_values.map((v) => ({ label: String(v), value: v }))"
40
+ size="sm"
41
+ class="w-full"
42
+ @update:model-value="update(key, $event)"
43
+ />
44
+ </UFormField>
45
+
46
+ <!-- String without allowed values → Input -->
47
+ <UFormField v-else-if="opt.type === 'string'" :label="formatLabel(key)">
48
+ <UInput
49
+ :model-value="modelValue[key] ?? opt.default ?? ''"
50
+ size="sm"
51
+ @update:model-value="update(key, $event)"
52
+ />
53
+ </UFormField>
54
+
55
+ <!-- Integer → Number input with min/max -->
56
+ <UFormField v-else-if="opt.type === 'integer'" :label="formatLabel(key)">
57
+ <UInput
58
+ type="number"
59
+ :model-value="modelValue[key] ?? opt.default"
60
+ :min="opt.min"
61
+ :max="opt.max"
62
+ size="sm"
63
+ class="w-32"
64
+ @update:model-value="update(key, Number($event))"
65
+ />
66
+ <template v-if="opt.min != null || opt.max != null" #hint>
67
+ <span class="text-[10px] text-muted">
68
+ {{ opt.min != null ? `Min: ${opt.min}` : "" }}
69
+ {{ opt.min != null && opt.max != null ? " \xB7 " : "" }}
70
+ {{ opt.max != null ? `Max: ${opt.max}` : "" }}
71
+ </span>
72
+ </template>
73
+ </UFormField>
74
+
75
+ <!-- Boolean → Checkbox -->
76
+ <UFormField v-else-if="opt.type === 'boolean'" :label="formatLabel(key)">
77
+ <UCheckbox
78
+ :model-value="modelValue[key] ?? opt.default ?? false"
79
+ @update:model-value="update(key, $event)"
80
+ />
81
+ </UFormField>
82
+
83
+ <!-- Array with allowed values → Checkbox group -->
84
+ <UFormField v-else-if="opt.type === 'array' && opt.allowed_values?.length" :label="formatLabel(key)">
85
+ <div class="flex flex-wrap gap-2">
86
+ <UButton
87
+ v-for="item in opt.allowed_values"
88
+ :key="String(item)"
89
+ size="xs"
90
+ :variant="isArrayItemSelected(key, item) ? 'solid' : 'outline'"
91
+ :color="isArrayItemSelected(key, item) ? 'primary' : 'neutral'"
92
+ :label="String(item)"
93
+ @click="toggleArrayItem(key, item)"
94
+ />
95
+ </div>
96
+ </UFormField>
97
+
98
+ <!-- Array without allowed values → Comma input -->
99
+ <UFormField v-else-if="opt.type === 'array'" :label="formatLabel(key)">
100
+ <UInput
101
+ :model-value="Array.isArray(modelValue[key]) ? modelValue[key].join(', ') : (opt.default ?? []).join(', ')"
102
+ size="sm"
103
+ placeholder="Comma-separated values"
104
+ @update:model-value="update(key, $event.split(',').map((s) => s.trim()).filter(Boolean))"
105
+ />
106
+ </UFormField>
107
+ </div>
108
+
109
+ <div v-if="!entries.length" class="text-xs text-muted">
110
+ No configurable options for this step.
111
+ </div>
112
+ </div>
113
+ </template>
@@ -0,0 +1,14 @@
1
+ import type { PipelineOptionSchema } from "../../../types/asset.js";
2
+ type __VLS_Props = {
3
+ schema: Record<string, PipelineOptionSchema>;
4
+ modelValue: Record<string, any>;
5
+ /** Keys to exclude from rendering (handled elsewhere, e.g., timestamp in FramePicker) */
6
+ exclude?: string[];
7
+ };
8
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
9
+ "update:modelValue": (value: Record<string, any>) => any;
10
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
11
+ "onUpdate:modelValue"?: ((value: Record<string, any>) => any) | undefined;
12
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
13
+ declare const _default: typeof __VLS_export;
14
+ export default _default;
@@ -0,0 +1,15 @@
1
+ type __VLS_Props = {
2
+ assetId: string;
3
+ downloadUrl?: string | null;
4
+ /** Authoritative asset status (`processing` | `awaiting_input` | `ready` | `failed`). When provided, drives the headline status. */
5
+ assetStatus?: string | null;
6
+ };
7
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
8
+ failed: () => any;
9
+ complete: () => any;
10
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
11
+ onFailed?: (() => any) | undefined;
12
+ onComplete?: (() => any) | undefined;
13
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
14
+ declare const _default: typeof __VLS_export;
15
+ export default _default;
@@ -0,0 +1,178 @@
1
+ <script setup>
2
+ import { computed, watch } from "vue";
3
+ import { useOverlay, useToast } from "#imports";
4
+ import { useMLProcessingPipeline } from "../../composables/useMLProcessingPipeline";
5
+ import ConfigureStepModal from "./Forms/ConfigureStepModal.vue";
6
+ const props = defineProps({
7
+ assetId: { type: String, required: true },
8
+ downloadUrl: { type: [String, null], required: false },
9
+ assetStatus: { type: [String, null], required: false }
10
+ });
11
+ const emit = defineEmits(["complete", "failed"]);
12
+ const overlay = useOverlay();
13
+ const toast = useToast();
14
+ const {
15
+ tasks,
16
+ loading,
17
+ stream,
18
+ taskEventMap,
19
+ pipelineStatus,
20
+ pipelineElapsed,
21
+ completedCount,
22
+ totalSteps,
23
+ hasFailedSteps,
24
+ progressPercent,
25
+ expandedSteps,
26
+ pipelineSchema,
27
+ toggleStep,
28
+ configureTask,
29
+ triggerProcessing,
30
+ retryTask,
31
+ getBlocker,
32
+ groupedTasks,
33
+ firstPendingInputTask
34
+ } = useMLProcessingPipeline(() => props.assetId, () => props.assetStatus);
35
+ function humanize(name) {
36
+ return name.replace(/_/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
37
+ }
38
+ const pendingInputStepName = computed(
39
+ () => firstPendingInputTask.value ? humanize(firstPendingInputTask.value.task_type) : ""
40
+ );
41
+ async function onRetry(taskId) {
42
+ try {
43
+ await retryTask(taskId);
44
+ } catch (err) {
45
+ const message = err?.data?.detail ?? err?.data?.message ?? err?.statusMessage ?? "Could not retry task";
46
+ toast.add({ title: "Retry failed", description: String(message), color: "error" });
47
+ }
48
+ }
49
+ async function openConfigure(taskId) {
50
+ const task = tasks.value.find((t) => t.id === taskId);
51
+ if (!task) return;
52
+ const schema = pipelineSchema.value[task.task_type] ?? {};
53
+ const modal = overlay.create(ConfigureStepModal, {
54
+ props: {
55
+ taskType: task.task_type,
56
+ schema,
57
+ downloadUrl: props.downloadUrl
58
+ }
59
+ });
60
+ const result = await modal.open();
61
+ if (result) {
62
+ await configureTask(taskId, result);
63
+ }
64
+ }
65
+ watch(pipelineStatus, (status) => {
66
+ if (status === "succeeded") emit("complete");
67
+ if (status === "failed") emit("failed");
68
+ });
69
+ </script>
70
+
71
+ <template>
72
+ <div class="space-y-0">
73
+ <MLProcessingTopBar title="Processing Pipeline" :status="pipelineStatus">
74
+ <template #subtitle>
75
+ {{ completedCount }} of {{ totalSteps }} steps completed
76
+ <template v-if="pipelineElapsed"> · {{ pipelineElapsed }}</template>
77
+ <template v-if="pipelineStatus === 'awaiting_input'"> · Awaiting configuration</template>
78
+ </template>
79
+ <template #actions>
80
+ <UButton
81
+ variant="outline"
82
+ :color="hasFailedSteps ? 'warning' : 'neutral'"
83
+ size="xs"
84
+ :icon="hasFailedSteps ? 'i-lucide-refresh-cw' : 'i-lucide-play'"
85
+ label="Reprocess"
86
+ @click="triggerProcessing()"
87
+ />
88
+ </template>
89
+ </MLProcessingTopBar>
90
+
91
+ <MLProcessingProgressBar
92
+ v-if="pipelineStatus === 'running'"
93
+ :percent="progressPercent"
94
+ />
95
+
96
+ <!-- AWAITING_INPUT banner: pipeline is paused on a configurable step -->
97
+ <UAlert
98
+ v-if="pipelineStatus === 'awaiting_input' && firstPendingInputTask"
99
+ icon="i-lucide-pencil-line"
100
+ color="warning"
101
+ variant="subtle"
102
+ :title="`Pipeline paused \u2014 configure ${pendingInputStepName} to continue`"
103
+ description="The pipeline will resume automatically once options are provided."
104
+ class="rounded-none border-x border-default"
105
+ >
106
+ <template #actions>
107
+ <UButton
108
+ size="xs"
109
+ color="warning"
110
+ icon="i-lucide-settings"
111
+ label="Configure"
112
+ @click="openConfigure(firstPendingInputTask.id)"
113
+ />
114
+ </template>
115
+ </UAlert>
116
+
117
+ <!-- Timeline Body -->
118
+ <div class="border border-t-0 border-default rounded-b-lg">
119
+ <!-- Loading -->
120
+ <div v-if="loading && !tasks.length" class="space-y-3 p-4">
121
+ <USkeleton v-for="i in 4" :key="i" class="h-10 w-full" />
122
+ </div>
123
+
124
+ <!-- Task Timeline -->
125
+ <template v-else-if="tasks.length">
126
+ <!-- Asset pipeline -->
127
+ <div v-if="groupedTasks.assetTasks.length">
128
+ <MLProcessingPipelineStepItem
129
+ v-for="task in groupedTasks.assetTasks"
130
+ :key="task.id"
131
+ :task="task"
132
+ :expanded="expandedSteps.has(task.id)"
133
+ :sse-event="taskEventMap.get(task.id) ?? null"
134
+ :blocker="getBlocker(task.id)"
135
+ @toggle="toggleStep(task.id)"
136
+ @retry="onRetry"
137
+ @configure="openConfigure"
138
+ />
139
+ </div>
140
+
141
+ <!-- Per-rendition pipelines -->
142
+ <div
143
+ v-for="group in groupedTasks.renditionGroups"
144
+ :key="group.renditionId"
145
+ class="border-t border-default"
146
+ >
147
+ <div class="flex items-center gap-2 px-4 py-2 bg-muted/20 text-xs text-muted">
148
+ <UIcon name="i-lucide-layers" class="size-3.5" />
149
+ <span class="font-medium">Rendition</span>
150
+ <span class="font-mono">{{ group.renditionId.slice(0, 8) }}</span>
151
+ </div>
152
+ <MLProcessingPipelineStepItem
153
+ v-for="task in group.tasks"
154
+ :key="task.id"
155
+ :task="task"
156
+ :expanded="expandedSteps.has(task.id)"
157
+ :sse-event="taskEventMap.get(task.id) ?? null"
158
+ :blocker="getBlocker(task.id)"
159
+ @toggle="toggleStep(task.id)"
160
+ @retry="onRetry"
161
+ @configure="openConfigure"
162
+ />
163
+ </div>
164
+ </template>
165
+
166
+ <!-- Empty -->
167
+ <UEmpty
168
+ v-else
169
+ icon="i-lucide-cpu"
170
+ title="No processing tasks"
171
+ description="Processing tasks will appear here when the asset is being processed."
172
+ size="sm"
173
+ class="py-8"
174
+ />
175
+ </div>
176
+
177
+ </div>
178
+ </template>
@@ -0,0 +1,15 @@
1
+ type __VLS_Props = {
2
+ assetId: string;
3
+ downloadUrl?: string | null;
4
+ /** Authoritative asset status (`processing` | `awaiting_input` | `ready` | `failed`). When provided, drives the headline status. */
5
+ assetStatus?: string | null;
6
+ };
7
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
8
+ failed: () => any;
9
+ complete: () => any;
10
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
11
+ onFailed?: (() => any) | undefined;
12
+ onComplete?: (() => any) | undefined;
13
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
14
+ declare const _default: typeof __VLS_export;
15
+ export default _default;
@@ -0,0 +1,20 @@
1
+ import type { ProcessingTask } from "../../types/asset.js";
2
+ import type { ProcessingEvent } from "../../composables/useMLProcessingStatus.js";
3
+ type __VLS_Props = {
4
+ task: ProcessingTask;
5
+ expanded: boolean;
6
+ sseEvent?: ProcessingEvent | null;
7
+ /** Upstream task currently blocking this row (only meaningful for `waiting` rows). */
8
+ blocker?: ProcessingTask | null;
9
+ };
10
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
11
+ toggle: () => any;
12
+ retry: (taskId: string) => any;
13
+ configure: (taskId: string) => any;
14
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
15
+ onToggle?: (() => any) | undefined;
16
+ onRetry?: ((taskId: string) => any) | undefined;
17
+ onConfigure?: ((taskId: string) => any) | undefined;
18
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
19
+ declare const _default: typeof __VLS_export;
20
+ export default _default;