@tangle-network/sandbox-ui 0.130.1 → 0.131.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/assets.d.ts +16 -2
- package/dist/assets.js +211 -104
- package/dist/{dashboard-BW-rPRwj.js → dashboard-B7mrHa2A.js} +1 -1
- package/dist/dashboard.js +1 -1
- package/dist/globals.css +74 -28
- package/dist/index-BVMgdFU9.d.ts +30 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +5 -5
- package/dist/primitives-DVo5ldkk.js +25 -0
- package/dist/primitives.d.ts +2 -2
- package/dist/primitives.js +2 -2
- package/dist/styles.css +74 -28
- package/dist/{workbench-C2CzWiZU.js → workbench-syQB06Hc.js} +1 -1
- package/dist/workbench.js +1 -1
- package/dist/{workspace-DRz3SoJc.js → workspace-CgG0B5NC.js} +10 -8
- package/dist/workspace.js +1 -1
- package/package.json +5 -5
- package/dist/index-C6oItkj5.d.ts +0 -30
- package/dist/primitives-JjV1ruzp.js +0 -25
package/dist/assets.d.ts
CHANGED
|
@@ -189,11 +189,13 @@ interface ApprovalQueueProps {
|
|
|
189
189
|
onSave?: (spec: AssetSpec) => void;
|
|
190
190
|
onRevisionRequest?: (id: string, instruction: string) => void;
|
|
191
191
|
onRenderRequest?: (id: string) => void;
|
|
192
|
+
/** Opens one asset's detail view, with the ids the queue shows, in order, for previous and next. */
|
|
193
|
+
onOpen?: (id: string, visibleIds: string[]) => void;
|
|
192
194
|
renderingIds?: Set<string>;
|
|
193
195
|
previewUrls?: Record<string, string>;
|
|
194
196
|
className?: string;
|
|
195
197
|
}
|
|
196
|
-
export declare function ApprovalQueue({ assets, variantCounts, onApprove, onReject, onEdit, onSave, onRevisionRequest, onRenderRequest, renderingIds, previewUrls, className }: ApprovalQueueProps): React$1.JSX.Element;
|
|
198
|
+
export declare function ApprovalQueue({ assets, variantCounts, onApprove, onReject, onEdit, onSave, onRevisionRequest, onRenderRequest, onOpen, renderingIds, previewUrls, className }: ApprovalQueueProps): React$1.JSX.Element;
|
|
197
199
|
//#endregion
|
|
198
200
|
//#region src/assets/asset-card.d.ts
|
|
199
201
|
interface AssetCardProps {
|
|
@@ -202,9 +204,15 @@ interface AssetCardProps {
|
|
|
202
204
|
onApprove?: (id: string) => void;
|
|
203
205
|
onReject?: (id: string) => void;
|
|
204
206
|
onEdit?: (id: string) => void;
|
|
207
|
+
/** Opens the asset's detail view. When set, the thumbnail and card body are one click target. */
|
|
208
|
+
onOpen?: (id: string) => void;
|
|
205
209
|
className?: string;
|
|
206
210
|
}
|
|
207
|
-
|
|
211
|
+
/** The URL of an image slide that is one picture with nothing layered on it. */
|
|
212
|
+
export declare function imageOnlyUrl(content: ImageContent): string | null;
|
|
213
|
+
/** The still frame a video asset carries: its first image scene or image slide. */
|
|
214
|
+
export declare function videoPosterUrl(content: VideoContent): string | null;
|
|
215
|
+
export declare function AssetCard({ spec, variantCount, onApprove, onReject, onEdit, onOpen, className }: AssetCardProps): import("react").JSX.Element;
|
|
208
216
|
//#endregion
|
|
209
217
|
//#region src/assets/asset-editor.d.ts
|
|
210
218
|
interface AssetEditorProps {
|
|
@@ -218,6 +226,12 @@ interface AssetEditorProps {
|
|
|
218
226
|
}
|
|
219
227
|
export declare function AssetEditor({ spec, previewUrl, isRendering, onSave, onRenderRequest, onRevisionRequest, className }: AssetEditorProps): React$1.JSX.Element;
|
|
220
228
|
//#endregion
|
|
229
|
+
//#region src/assets/labels.d.ts
|
|
230
|
+
/** Reader-facing name for each asset format. */
|
|
231
|
+
export declare const ASSET_FORMAT_LABEL: Record<AssetFormat, string>;
|
|
232
|
+
/** Reader-facing name for each review status. */
|
|
233
|
+
export declare const ASSET_STATUS_LABEL: Record<AssetStatus, string>;
|
|
234
|
+
//#endregion
|
|
221
235
|
//#region src/assets/preview/copy-preview.d.ts
|
|
222
236
|
interface CopyPreviewProps {
|
|
223
237
|
content: CopyContent;
|
package/dist/assets.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { t as cn } from "./utils-DzWbktWG.js";
|
|
2
|
-
import { Badge, Button, Input, Label, Textarea } from "@tangle-network/ui/primitives";
|
|
3
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Badge, Button, DatePicker, FilterField, Input, Label, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, Textarea, Toolbar, localToday } from "@tangle-network/ui/primitives";
|
|
3
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
4
4
|
import * as React$1 from "react";
|
|
5
5
|
import { Fragment as Fragment$1 } from "react";
|
|
6
|
-
import { Check, CheckCheck, ChevronDown, ChevronLeft, ChevronRight, Film, GitBranch, Loader2, MessageSquare, Pencil, Play, Save, Search, X } from "lucide-react";
|
|
6
|
+
import { Check, CheckCheck, ChevronDown, ChevronLeft, ChevronRight, Film, GitBranch, Loader2, Maximize2, MessageSquare, Pencil, Play, Save, Search, X } from "lucide-react";
|
|
7
7
|
//#region src/assets/preview/image-preview.tsx
|
|
8
8
|
const ASPECT = {
|
|
9
9
|
feed: "aspect-square",
|
|
@@ -118,6 +118,29 @@ function ImagePreview({ content, brand, format = "feed", className }) {
|
|
|
118
118
|
});
|
|
119
119
|
}
|
|
120
120
|
//#endregion
|
|
121
|
+
//#region src/assets/labels.ts
|
|
122
|
+
/** Reader-facing name for each asset format. */
|
|
123
|
+
const ASSET_FORMAT_LABEL = {
|
|
124
|
+
email: "Email",
|
|
125
|
+
"image:feed": "Feed image",
|
|
126
|
+
"image:story": "Story",
|
|
127
|
+
"image:carousel": "Carousel",
|
|
128
|
+
"video:reel": "Reel",
|
|
129
|
+
"video:feed": "Feed video",
|
|
130
|
+
"copy:caption": "Caption",
|
|
131
|
+
"copy:headline": "Headline",
|
|
132
|
+
"copy:sms": "SMS"
|
|
133
|
+
};
|
|
134
|
+
/** Reader-facing name for each review status. */
|
|
135
|
+
const ASSET_STATUS_LABEL = {
|
|
136
|
+
draft: "Draft",
|
|
137
|
+
pending_review: "Pending review",
|
|
138
|
+
approved: "Approved",
|
|
139
|
+
rejected: "Rejected",
|
|
140
|
+
scheduled: "Scheduled",
|
|
141
|
+
published: "Published"
|
|
142
|
+
};
|
|
143
|
+
//#endregion
|
|
121
144
|
//#region src/assets/asset-card.tsx
|
|
122
145
|
const STATUS_VARIANT = {
|
|
123
146
|
draft: "secondary",
|
|
@@ -127,111 +150,173 @@ const STATUS_VARIANT = {
|
|
|
127
150
|
scheduled: "secondary",
|
|
128
151
|
published: "default"
|
|
129
152
|
};
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
153
|
+
/** The URL of an image slide that is one picture with nothing layered on it. */
|
|
154
|
+
function imageOnlyUrl(content) {
|
|
155
|
+
const slide = content.slides[0];
|
|
156
|
+
return slide && slide.layers.length === 0 && slide.background.type === "image" ? slide.background.url : null;
|
|
157
|
+
}
|
|
158
|
+
/** The still frame a video asset carries: its first image scene or image slide. */
|
|
159
|
+
function videoPosterUrl(content) {
|
|
160
|
+
for (const scene of content.scenes) {
|
|
161
|
+
if (scene.type === "image-reveal") return scene.imageUrl;
|
|
162
|
+
if (scene.type === "slide" && scene.slide.background.type === "image") return scene.slide.background.url;
|
|
163
|
+
}
|
|
164
|
+
return null;
|
|
165
|
+
}
|
|
166
|
+
function formatDuration(seconds) {
|
|
167
|
+
const whole = Math.max(0, Math.round(seconds));
|
|
168
|
+
return `${Math.floor(whole / 60)}:${String(whole % 60).padStart(2, "0")}`;
|
|
169
|
+
}
|
|
170
|
+
/** A short phrase that tells one asset from another of the same format. */
|
|
171
|
+
function assetSummary(spec) {
|
|
172
|
+
if (spec.format === "email") return spec.content.subject || null;
|
|
173
|
+
if (spec.format.startsWith("copy:")) return spec.content.headline || null;
|
|
174
|
+
return null;
|
|
175
|
+
}
|
|
138
176
|
function Thumbnail({ spec }) {
|
|
139
177
|
const { format, brand, content } = spec;
|
|
140
178
|
if (format === "email") {
|
|
141
179
|
const ec = content;
|
|
142
180
|
return /* @__PURE__ */ jsxs("div", {
|
|
143
|
-
className: "
|
|
181
|
+
className: "flex h-full flex-col gap-1 p-3 text-sm",
|
|
144
182
|
children: [/* @__PURE__ */ jsx("div", {
|
|
145
|
-
className: "font-medium
|
|
183
|
+
className: "line-clamp-3 font-medium",
|
|
146
184
|
children: ec.subject
|
|
147
185
|
}), /* @__PURE__ */ jsxs("div", {
|
|
148
|
-
className: "text-muted-foreground
|
|
186
|
+
className: "text-xs text-muted-foreground",
|
|
149
187
|
children: [ec.sections.length, " sections"]
|
|
150
188
|
})]
|
|
151
189
|
});
|
|
152
190
|
}
|
|
153
|
-
if (format.startsWith("image:"))
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
191
|
+
if (format.startsWith("image:")) {
|
|
192
|
+
const ic = content;
|
|
193
|
+
const url = imageOnlyUrl(ic);
|
|
194
|
+
if (url) return /* @__PURE__ */ jsx("img", {
|
|
195
|
+
src: url,
|
|
196
|
+
alt: "",
|
|
197
|
+
loading: "lazy",
|
|
198
|
+
decoding: "async",
|
|
199
|
+
className: "h-full w-full object-contain"
|
|
200
|
+
});
|
|
201
|
+
return /* @__PURE__ */ jsx("div", {
|
|
202
|
+
className: "h-full overflow-hidden",
|
|
203
|
+
children: /* @__PURE__ */ jsx(ImagePreview, {
|
|
204
|
+
content: ic,
|
|
205
|
+
brand,
|
|
206
|
+
format: format === "image:story" ? "story" : "feed"
|
|
207
|
+
})
|
|
208
|
+
});
|
|
209
|
+
}
|
|
162
210
|
if (format.startsWith("video:")) {
|
|
163
211
|
const vc = content;
|
|
212
|
+
const poster = videoPosterUrl(vc);
|
|
164
213
|
return /* @__PURE__ */ jsxs("div", {
|
|
165
|
-
className: "
|
|
166
|
-
children: [
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
214
|
+
className: "relative h-full w-full",
|
|
215
|
+
children: [
|
|
216
|
+
poster ? /* @__PURE__ */ jsx("img", {
|
|
217
|
+
src: poster,
|
|
218
|
+
alt: "",
|
|
219
|
+
loading: "lazy",
|
|
220
|
+
decoding: "async",
|
|
221
|
+
className: "h-full w-full object-contain"
|
|
222
|
+
}) : /* @__PURE__ */ jsx("div", {
|
|
223
|
+
className: "flex h-full flex-col gap-1 p-3 text-sm",
|
|
224
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
225
|
+
className: "font-medium",
|
|
226
|
+
children: [vc.scenes.length, " scenes"]
|
|
227
|
+
})
|
|
228
|
+
}),
|
|
229
|
+
/* @__PURE__ */ jsx("span", {
|
|
230
|
+
className: "pointer-events-none absolute top-1/2 left-1/2 flex size-10 -translate-x-1/2 -translate-y-1/2 items-center justify-center rounded-full bg-black/60 text-white",
|
|
231
|
+
children: /* @__PURE__ */ jsx(Play, {
|
|
232
|
+
size: 18,
|
|
233
|
+
className: "translate-x-px",
|
|
234
|
+
"aria-hidden": true
|
|
235
|
+
})
|
|
236
|
+
}),
|
|
237
|
+
/* @__PURE__ */ jsx("span", {
|
|
238
|
+
className: "pointer-events-none absolute right-2 bottom-2 rounded bg-black/70 px-1.5 py-0.5 text-xs text-white tabular-nums",
|
|
239
|
+
children: formatDuration(vc.durationSeconds)
|
|
240
|
+
})
|
|
241
|
+
]
|
|
173
242
|
});
|
|
174
243
|
}
|
|
175
244
|
if (format.startsWith("copy:")) {
|
|
176
245
|
const cc = content;
|
|
177
246
|
return /* @__PURE__ */ jsxs("div", {
|
|
178
|
-
className: "
|
|
247
|
+
className: "flex h-full flex-col gap-1 p-3 text-sm",
|
|
179
248
|
children: [/* @__PURE__ */ jsx("div", {
|
|
180
|
-
className: "font-medium
|
|
249
|
+
className: "line-clamp-2 font-medium",
|
|
181
250
|
children: cc.headline
|
|
182
251
|
}), /* @__PURE__ */ jsx("div", {
|
|
183
|
-
className: "
|
|
252
|
+
className: "line-clamp-4 text-xs text-muted-foreground",
|
|
184
253
|
children: cc.body
|
|
185
254
|
})]
|
|
186
255
|
});
|
|
187
256
|
}
|
|
188
257
|
return null;
|
|
189
258
|
}
|
|
190
|
-
function AssetCard({ spec, variantCount, onApprove, onReject, onEdit, className }) {
|
|
259
|
+
function AssetCard({ spec, variantCount, onApprove, onReject, onEdit, onOpen, className }) {
|
|
260
|
+
const formatLabel = ASSET_FORMAT_LABEL[spec.format] ?? spec.format;
|
|
261
|
+
const statusLabel = ASSET_STATUS_LABEL[spec.status] ?? spec.status;
|
|
262
|
+
const summary = assetSummary(spec);
|
|
263
|
+
const hasActions = Boolean(onEdit || spec.status === "pending_review" && (onReject || onApprove));
|
|
191
264
|
return /* @__PURE__ */ jsxs("div", {
|
|
192
|
-
|
|
265
|
+
"data-asset-id": spec.id,
|
|
266
|
+
className: cn("group relative flex flex-col overflow-hidden rounded-lg border border-border bg-card transition-[border-color,box-shadow]", onOpen && "hover:border-primary/60 hover:shadow-md", className),
|
|
193
267
|
children: [
|
|
194
|
-
/* @__PURE__ */ jsx("
|
|
195
|
-
|
|
196
|
-
|
|
268
|
+
onOpen && /* @__PURE__ */ jsx("button", {
|
|
269
|
+
type: "button",
|
|
270
|
+
"data-asset-open": "",
|
|
271
|
+
onClick: () => onOpen(spec.id),
|
|
272
|
+
"aria-label": `Open ${formatLabel.toLowerCase()}${summary ? `: ${summary}` : ""}, ${statusLabel.toLowerCase()}`,
|
|
273
|
+
className: "absolute inset-0 z-[1] cursor-pointer rounded-lg focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-inset"
|
|
274
|
+
}),
|
|
275
|
+
/* @__PURE__ */ jsxs("div", {
|
|
276
|
+
className: "relative aspect-square overflow-hidden bg-muted/40",
|
|
277
|
+
children: [/* @__PURE__ */ jsx(Thumbnail, { spec }), onOpen && /* @__PURE__ */ jsx("span", {
|
|
278
|
+
"aria-hidden": true,
|
|
279
|
+
className: "pointer-events-none absolute top-2 right-2 flex size-7 items-center justify-center rounded-md bg-background/90 text-foreground opacity-0 shadow-sm transition-opacity group-hover:opacity-100 group-focus-within:opacity-100",
|
|
280
|
+
children: /* @__PURE__ */ jsx(Maximize2, { size: 14 })
|
|
281
|
+
})]
|
|
197
282
|
}),
|
|
198
283
|
/* @__PURE__ */ jsxs("div", {
|
|
199
|
-
className: "
|
|
284
|
+
className: "flex items-center gap-2 px-2.5 py-2",
|
|
200
285
|
children: [
|
|
201
286
|
/* @__PURE__ */ jsx("span", {
|
|
202
|
-
className: "text-
|
|
203
|
-
children:
|
|
287
|
+
className: "min-w-0 flex-1 truncate text-xs text-muted-foreground",
|
|
288
|
+
children: formatLabel
|
|
204
289
|
}),
|
|
205
290
|
/* @__PURE__ */ jsx(Badge, {
|
|
206
291
|
variant: STATUS_VARIANT[spec.status],
|
|
207
|
-
className: "
|
|
208
|
-
children:
|
|
292
|
+
className: "shrink-0 text-xs",
|
|
293
|
+
children: statusLabel
|
|
209
294
|
}),
|
|
210
295
|
variantCount !== void 0 && variantCount > 0 && /* @__PURE__ */ jsxs("span", {
|
|
211
|
-
className: "flex items-center gap-0.5 text-
|
|
212
|
-
children: [/* @__PURE__ */ jsx(GitBranch, { size:
|
|
296
|
+
className: "flex shrink-0 items-center gap-0.5 text-xs text-muted-foreground",
|
|
297
|
+
children: [/* @__PURE__ */ jsx(GitBranch, { size: 12 }), variantCount]
|
|
213
298
|
})
|
|
214
299
|
]
|
|
215
300
|
}),
|
|
216
|
-
/* @__PURE__ */ jsxs("div", {
|
|
217
|
-
className: "flex border-t border-border",
|
|
301
|
+
hasActions && /* @__PURE__ */ jsxs("div", {
|
|
302
|
+
className: "relative z-[2] flex border-t border-border bg-card",
|
|
218
303
|
children: [
|
|
219
304
|
onEdit && /* @__PURE__ */ jsxs("button", {
|
|
220
305
|
type: "button",
|
|
221
306
|
onClick: () => onEdit(spec.id),
|
|
222
|
-
className: "flex-1
|
|
307
|
+
className: "flex flex-1 items-center justify-center gap-1 py-2 text-xs text-muted-foreground transition-colors hover:bg-muted/50 hover:text-foreground",
|
|
223
308
|
children: [/* @__PURE__ */ jsx(Pencil, { size: 12 }), "Edit"]
|
|
224
309
|
}),
|
|
225
310
|
onReject && spec.status === "pending_review" && /* @__PURE__ */ jsxs("button", {
|
|
226
311
|
type: "button",
|
|
227
312
|
onClick: () => onReject(spec.id),
|
|
228
|
-
className: "flex-1
|
|
313
|
+
className: "flex flex-1 items-center justify-center gap-1 border-l border-border py-2 text-xs text-muted-foreground transition-colors hover:bg-destructive/5 hover:text-destructive",
|
|
229
314
|
children: [/* @__PURE__ */ jsx(X, { size: 12 }), "Reject"]
|
|
230
315
|
}),
|
|
231
316
|
onApprove && spec.status === "pending_review" && /* @__PURE__ */ jsxs("button", {
|
|
232
317
|
type: "button",
|
|
233
318
|
onClick: () => onApprove(spec.id),
|
|
234
|
-
className: "flex-1
|
|
319
|
+
className: "flex flex-1 items-center justify-center gap-1 border-l border-border py-2 text-xs text-muted-foreground transition-colors hover:bg-green-600/5 hover:text-green-600",
|
|
235
320
|
children: [/* @__PURE__ */ jsx(Check, { size: 12 }), "Approve"]
|
|
236
321
|
})
|
|
237
322
|
]
|
|
@@ -886,12 +971,15 @@ const STATUS_OPTIONS = [
|
|
|
886
971
|
label: "Published"
|
|
887
972
|
}
|
|
888
973
|
];
|
|
889
|
-
function ApprovalQueue({ assets, variantCounts = {}, onApprove, onReject, onEdit, onSave, onRevisionRequest, onRenderRequest, renderingIds = /* @__PURE__ */ new Set(), previewUrls = {}, className }) {
|
|
974
|
+
function ApprovalQueue({ assets, variantCounts = {}, onApprove, onReject, onEdit, onSave, onRevisionRequest, onRenderRequest, onOpen, renderingIds = /* @__PURE__ */ new Set(), previewUrls = {}, className }) {
|
|
890
975
|
const [search, setSearch] = React$1.useState("");
|
|
891
976
|
const [formatFilter, setFormatFilter] = React$1.useState("all");
|
|
892
977
|
const [statusFilter, setStatusFilter] = React$1.useState("pending_review");
|
|
893
978
|
const [editingId, setEditingId] = React$1.useState(null);
|
|
894
979
|
const [scheduleDate, setScheduleDate] = React$1.useState("");
|
|
980
|
+
const formatId = React$1.useId();
|
|
981
|
+
const statusId = React$1.useId();
|
|
982
|
+
const scheduleId = React$1.useId();
|
|
895
983
|
const filtered = assets.filter((a) => {
|
|
896
984
|
if (formatFilter !== "all" && a.format !== formatFilter) return false;
|
|
897
985
|
if (statusFilter !== "all" && a.status !== statusFilter) return false;
|
|
@@ -949,60 +1037,78 @@ function ApprovalQueue({ assets, variantCounts = {}, onApprove, onReject, onEdit
|
|
|
949
1037
|
});
|
|
950
1038
|
return /* @__PURE__ */ jsxs("div", {
|
|
951
1039
|
className: cn("flex flex-col gap-3", className),
|
|
952
|
-
children: [/* @__PURE__ */
|
|
953
|
-
className: "
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
})
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
1040
|
+
children: [/* @__PURE__ */ jsx(Toolbar, {
|
|
1041
|
+
className: "mb-0",
|
|
1042
|
+
search: /* @__PURE__ */ jsxs("div", {
|
|
1043
|
+
className: "relative",
|
|
1044
|
+
children: [/* @__PURE__ */ jsx(Search, {
|
|
1045
|
+
size: 14,
|
|
1046
|
+
"aria-hidden": true,
|
|
1047
|
+
className: "pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground"
|
|
1048
|
+
}), /* @__PURE__ */ jsx(Input, {
|
|
1049
|
+
value: search,
|
|
1050
|
+
onChange: (e) => setSearch(e.target.value),
|
|
1051
|
+
placeholder: "Filter assets…",
|
|
1052
|
+
"aria-label": "Filter assets",
|
|
1053
|
+
className: "pl-9"
|
|
1054
|
+
})]
|
|
1055
|
+
}),
|
|
1056
|
+
filters: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1057
|
+
/* @__PURE__ */ jsx(FilterField, {
|
|
1058
|
+
label: "Format",
|
|
1059
|
+
htmlFor: formatId,
|
|
1060
|
+
children: /* @__PURE__ */ jsxs(Select, {
|
|
1061
|
+
value: formatFilter,
|
|
1062
|
+
onValueChange: setFormatFilter,
|
|
1063
|
+
children: [/* @__PURE__ */ jsx(SelectTrigger, {
|
|
1064
|
+
id: formatId,
|
|
1065
|
+
className: "w-36",
|
|
1066
|
+
children: /* @__PURE__ */ jsx(SelectValue, {})
|
|
1067
|
+
}), /* @__PURE__ */ jsx(SelectContent, { children: FORMAT_OPTIONS.map((o) => /* @__PURE__ */ jsx(SelectItem, {
|
|
1068
|
+
value: o.value,
|
|
1069
|
+
children: o.label
|
|
1070
|
+
}, o.value)) })]
|
|
1071
|
+
})
|
|
975
1072
|
}),
|
|
976
|
-
/* @__PURE__ */ jsx(
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
children:
|
|
983
|
-
|
|
1073
|
+
/* @__PURE__ */ jsx(FilterField, {
|
|
1074
|
+
label: "Status",
|
|
1075
|
+
htmlFor: statusId,
|
|
1076
|
+
children: /* @__PURE__ */ jsxs(Select, {
|
|
1077
|
+
value: statusFilter,
|
|
1078
|
+
onValueChange: setStatusFilter,
|
|
1079
|
+
children: [/* @__PURE__ */ jsx(SelectTrigger, {
|
|
1080
|
+
id: statusId,
|
|
1081
|
+
className: "w-36",
|
|
1082
|
+
children: /* @__PURE__ */ jsx(SelectValue, {})
|
|
1083
|
+
}), /* @__PURE__ */ jsx(SelectContent, { children: STATUS_OPTIONS.map((o) => /* @__PURE__ */ jsx(SelectItem, {
|
|
1084
|
+
value: o.value,
|
|
1085
|
+
children: o.label
|
|
1086
|
+
}, o.value)) })]
|
|
1087
|
+
})
|
|
984
1088
|
}),
|
|
985
|
-
pendingCount > 0 && onApprove && /* @__PURE__ */
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
1089
|
+
pendingCount > 0 && onApprove && /* @__PURE__ */ jsx(FilterField, {
|
|
1090
|
+
label: "Schedule for",
|
|
1091
|
+
htmlFor: scheduleId,
|
|
1092
|
+
children: /* @__PURE__ */ jsx(DatePicker, {
|
|
1093
|
+
id: scheduleId,
|
|
1094
|
+
className: "w-40",
|
|
1095
|
+
placeholder: "Not scheduled",
|
|
1096
|
+
min: localToday(),
|
|
989
1097
|
value: scheduleDate,
|
|
990
|
-
onChange:
|
|
991
|
-
|
|
992
|
-
}), /* @__PURE__ */ jsxs(Button, {
|
|
993
|
-
size: "sm",
|
|
994
|
-
variant: "outline",
|
|
995
|
-
onClick: handleBulkApprove,
|
|
996
|
-
className: "h-8 gap-1.5 text-xs",
|
|
997
|
-
children: [
|
|
998
|
-
/* @__PURE__ */ jsx(CheckCheck, { size: 13 }),
|
|
999
|
-
"Approve all (",
|
|
1000
|
-
pendingCount,
|
|
1001
|
-
")"
|
|
1002
|
-
]
|
|
1003
|
-
})]
|
|
1098
|
+
onChange: setScheduleDate
|
|
1099
|
+
})
|
|
1004
1100
|
})
|
|
1005
|
-
]
|
|
1101
|
+
] }),
|
|
1102
|
+
actions: pendingCount > 0 && onApprove ? /* @__PURE__ */ jsxs(Button, {
|
|
1103
|
+
variant: "outline",
|
|
1104
|
+
onClick: handleBulkApprove,
|
|
1105
|
+
children: [
|
|
1106
|
+
/* @__PURE__ */ jsx(CheckCheck, {}),
|
|
1107
|
+
"Approve all (",
|
|
1108
|
+
pendingCount,
|
|
1109
|
+
")"
|
|
1110
|
+
]
|
|
1111
|
+
}) : void 0
|
|
1006
1112
|
}), filtered.length === 0 ? /* @__PURE__ */ jsx("div", {
|
|
1007
1113
|
className: "py-12 text-center text-sm text-muted-foreground",
|
|
1008
1114
|
children: "No assets match your filters."
|
|
@@ -1013,10 +1119,11 @@ function ApprovalQueue({ assets, variantCounts = {}, onApprove, onReject, onEdit
|
|
|
1013
1119
|
variantCount: variantCounts[a.id],
|
|
1014
1120
|
onApprove,
|
|
1015
1121
|
onReject,
|
|
1016
|
-
onEdit: () => setEditingId(a.id)
|
|
1122
|
+
onEdit: () => setEditingId(a.id),
|
|
1123
|
+
onOpen: onOpen ? (id) => onOpen(id, filtered.map((asset) => asset.id)) : void 0
|
|
1017
1124
|
}, a.id))
|
|
1018
1125
|
})]
|
|
1019
1126
|
});
|
|
1020
1127
|
}
|
|
1021
1128
|
//#endregion
|
|
1022
|
-
export { ApprovalQueue, AssetCard, AssetEditor, CopyPreview, EmailPreview, ImagePreview, VideoPreview };
|
|
1129
|
+
export { ASSET_FORMAT_LABEL, ASSET_STATUS_LABEL, ApprovalQueue, AssetCard, AssetEditor, CopyPreview, EmailPreview, ImagePreview, VideoPreview, imageOnlyUrl, videoPosterUrl };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { b as Button$1, sr as Logo } from "./primitives-DVo5ldkk.js";
|
|
2
2
|
import { t as cn$1 } from "./utils-DzWbktWG.js";
|
|
3
3
|
import { n as MOTION_SURFACE, r as MOTION_TRAVEL, t as MOTION_CONTROL } from "./motion-DkyBRJb9.js";
|
|
4
4
|
import { i as moonshot_default } from "./model-brand-hMyDTUqB.js";
|
package/dist/dashboard.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as useSidebar, A as parseInsufficientBalance, B as SidebarPanel, C as SandboxStatusPill, D as ResourceMeter, E as ResourceSnapshot, F as RailHeader, G as SidebarRailNav, H as SidebarPanelHeader, I as RailModeButton, J as SIDEBAR_PANEL_WIDTH, K as RailTooltip, L as RailSeparator, M as RailButton, N as RailExpandable, O as INSUFFICIENT_BALANCE_CODE, P as RailFlyout, Q as SidebarProvider, R as Sidebar, S as SANDBOX_STATUS, T as ActivityFeed, U as SidebarRail, V as SidebarPanelContent, W as SidebarRailFooter, X as SIDEBAR_RAIL_WIDTH, Y as SIDEBAR_RAIL_LABELED_WIDTH, Z as SIDEBAR_TOTAL_WIDTH, _ as BackendSelector, a as PortsList, b as SandboxCard, c as SystemLogsViewer, d as DashboardLayout, f as HARNESS_OPTIONS, g as HarnessLogo, h as HARNESS_BRAND, i as TemplateCard, j as ProfileAvatar, k as OutOfCreditsModal, l as MetricAreaChart, m as chatCapableHarnesses, n as SnapshotList, o as GitPanel, p as HarnessPicker, q as SIDEBAR_MOBILE_WIDTH, r as ProcessList, s as UsageSummary, t as PromoBanner, u as SidebarLayout, v as SandboxTable, w as sandboxStatus, x as canAdminSandbox, y as NewSandboxCard, z as SidebarContent } from "./dashboard-
|
|
1
|
+
import { $ as useSidebar, A as parseInsufficientBalance, B as SidebarPanel, C as SandboxStatusPill, D as ResourceMeter, E as ResourceSnapshot, F as RailHeader, G as SidebarRailNav, H as SidebarPanelHeader, I as RailModeButton, J as SIDEBAR_PANEL_WIDTH, K as RailTooltip, L as RailSeparator, M as RailButton, N as RailExpandable, O as INSUFFICIENT_BALANCE_CODE, P as RailFlyout, Q as SidebarProvider, R as Sidebar, S as SANDBOX_STATUS, T as ActivityFeed, U as SidebarRail, V as SidebarPanelContent, W as SidebarRailFooter, X as SIDEBAR_RAIL_WIDTH, Y as SIDEBAR_RAIL_LABELED_WIDTH, Z as SIDEBAR_TOTAL_WIDTH, _ as BackendSelector, a as PortsList, b as SandboxCard, c as SystemLogsViewer, d as DashboardLayout, f as HARNESS_OPTIONS, g as HarnessLogo, h as HARNESS_BRAND, i as TemplateCard, j as ProfileAvatar, k as OutOfCreditsModal, l as MetricAreaChart, m as chatCapableHarnesses, n as SnapshotList, o as GitPanel, p as HarnessPicker, q as SIDEBAR_MOBILE_WIDTH, r as ProcessList, s as UsageSummary, t as PromoBanner, u as SidebarLayout, v as SandboxTable, w as sandboxStatus, x as canAdminSandbox, y as NewSandboxCard, z as SidebarContent } from "./dashboard-B7mrHa2A.js";
|
|
2
2
|
import { n as canonicalModelId, r as modelBrandFor, t as ModelBrandStack } from "./model-brand-hMyDTUqB.js";
|
|
3
3
|
import { a as formatPrice, i as PricingPage, n as SandboxPageShell, o as BillingDashboard, r as UsageChart, t as DashboardPageHeader } from "./page-layout-2IRtfx51.js";
|
|
4
4
|
export { ActivityFeed, BackendSelector, BillingDashboard, DashboardLayout, DashboardPageHeader, GitPanel, HARNESS_BRAND, HARNESS_OPTIONS, HarnessLogo, HarnessPicker, INSUFFICIENT_BALANCE_CODE, MetricAreaChart, ModelBrandStack, NewSandboxCard, OutOfCreditsModal, PortsList, PricingPage, ProcessList, ProfileAvatar, PromoBanner, RailButton, RailExpandable, RailFlyout, RailHeader, RailModeButton, RailSeparator, RailTooltip, ResourceMeter, ResourceSnapshot, SANDBOX_STATUS, SIDEBAR_MOBILE_WIDTH, SIDEBAR_PANEL_WIDTH, SIDEBAR_RAIL_LABELED_WIDTH, SIDEBAR_RAIL_WIDTH, SIDEBAR_TOTAL_WIDTH, SandboxCard, SandboxPageShell, SandboxStatusPill, SandboxTable, Sidebar, SidebarContent, SidebarLayout, SidebarPanel, SidebarPanelContent, SidebarPanelHeader, SidebarProvider, SidebarRail, SidebarRailFooter, SidebarRailNav, SnapshotList, SystemLogsViewer, TemplateCard, UsageChart, UsageSummary, canAdminSandbox, canonicalModelId, chatCapableHarnesses, formatPrice, modelBrandFor, parseInsufficientBalance, sandboxStatus, useSidebar };
|