@streamoid/chat-components 0.2.7 → 0.2.9
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/index.js +115 -15
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -417,6 +417,38 @@ function DynamicForm(props) {
|
|
|
417
417
|
const fields = uiProps.fields ?? [];
|
|
418
418
|
const submitText = uiProps.submit_button_text ?? "Submit";
|
|
419
419
|
const cancelText = uiProps.cancel_button_text;
|
|
420
|
+
const getTextValue = (value, fallback = "") => {
|
|
421
|
+
if (typeof value === "string") return value;
|
|
422
|
+
if (typeof value === "number" || typeof value === "boolean") return String(value);
|
|
423
|
+
if (value && typeof value === "object") {
|
|
424
|
+
const obj = value;
|
|
425
|
+
if (typeof obj.label === "string") return obj.label;
|
|
426
|
+
if (typeof obj.text === "string") return obj.text;
|
|
427
|
+
if (typeof obj.value === "string") return obj.value;
|
|
428
|
+
}
|
|
429
|
+
return fallback;
|
|
430
|
+
};
|
|
431
|
+
const normalizeMediaUrls = (raw) => {
|
|
432
|
+
if (Array.isArray(raw)) {
|
|
433
|
+
return raw.filter((item) => typeof item === "string" && item.trim().length > 0);
|
|
434
|
+
}
|
|
435
|
+
if (typeof raw === "string" && raw.trim().length > 0) {
|
|
436
|
+
const maybeJson = raw.trim();
|
|
437
|
+
if (maybeJson.startsWith("[") && maybeJson.endsWith("]")) {
|
|
438
|
+
try {
|
|
439
|
+
const parsed = JSON.parse(maybeJson);
|
|
440
|
+
if (Array.isArray(parsed)) {
|
|
441
|
+
return parsed.filter(
|
|
442
|
+
(item) => typeof item === "string" && item.trim().length > 0
|
|
443
|
+
);
|
|
444
|
+
}
|
|
445
|
+
} catch {
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
return maybeJson.split(/[\n,]/).map((part) => part.trim()).filter(Boolean);
|
|
449
|
+
}
|
|
450
|
+
return [];
|
|
451
|
+
};
|
|
420
452
|
const inferMediaTypeFromUrl = (url) => {
|
|
421
453
|
const cleanUrl = (url || "").split("?")[0].toLowerCase();
|
|
422
454
|
const videoExts = [".mp4", ".mov", ".webm", ".m4v", ".avi", ".mkv"];
|
|
@@ -438,7 +470,7 @@ function DynamicForm(props) {
|
|
|
438
470
|
} else if (field.type === "approval") {
|
|
439
471
|
values[field.id] = null;
|
|
440
472
|
} else if (field.type === "media_approval") {
|
|
441
|
-
const mediaUrls =
|
|
473
|
+
const mediaUrls = normalizeMediaUrls(field.media_urls);
|
|
442
474
|
values[field.id] = {
|
|
443
475
|
decision: null,
|
|
444
476
|
feedback: "",
|
|
@@ -462,6 +494,7 @@ function DynamicForm(props) {
|
|
|
462
494
|
const [editingTodoContent, setEditingTodoContent] = useState("");
|
|
463
495
|
const [newTodoInputs, setNewTodoInputs] = useState({});
|
|
464
496
|
const [fileUploadState, setFileUploadState] = useState({});
|
|
497
|
+
const [mediaPreview, setMediaPreview] = useState(null);
|
|
465
498
|
const scrollRef = useRef(null);
|
|
466
499
|
const [canScrollUp, setCanScrollUp] = useState(false);
|
|
467
500
|
const [canScrollDown, setCanScrollDown] = useState(false);
|
|
@@ -694,7 +727,13 @@ function DynamicForm(props) {
|
|
|
694
727
|
const field = fields.find((f) => f.id === fieldId);
|
|
695
728
|
const fieldLabel = field?.label || fieldId;
|
|
696
729
|
let displayVal;
|
|
697
|
-
if (field?.
|
|
730
|
+
if (field?.type === "media_approval" && val && typeof val === "object") {
|
|
731
|
+
const mediaVal = val;
|
|
732
|
+
const decisionText = mediaVal.decision ?? "pending";
|
|
733
|
+
const feedbackText = mediaVal.feedback?.trim() || "none";
|
|
734
|
+
const mediaCount = Array.isArray(mediaVal.media_urls) ? mediaVal.media_urls.length : 0;
|
|
735
|
+
displayVal = `decision=${decisionText}, feedback=${feedbackText}, media_count=${mediaCount}`;
|
|
736
|
+
} else if (field?.options && typeof val === "string") {
|
|
698
737
|
const opt = field.options.find((o) => o.id === val);
|
|
699
738
|
displayVal = opt?.label || val;
|
|
700
739
|
} else if (field?.options && Array.isArray(val)) {
|
|
@@ -853,13 +892,13 @@ ${valueSummaryParts.join("\n")}` : "";
|
|
|
853
892
|
)
|
|
854
893
|
] });
|
|
855
894
|
case "media_approval": {
|
|
856
|
-
const mediaUrls = Array.isArray(field.media_urls) ? field.media_urls.filter(Boolean) : [];
|
|
857
895
|
const mediaValue = formValues[field.id] ?? {
|
|
858
896
|
decision: null,
|
|
859
897
|
feedback: "",
|
|
860
|
-
media_urls:
|
|
898
|
+
media_urls: normalizeMediaUrls(field.media_urls),
|
|
861
899
|
media_type: field.media_type ?? "mixed"
|
|
862
900
|
};
|
|
901
|
+
const mediaUrls = normalizeMediaUrls(field.media_urls ?? mediaValue.media_urls);
|
|
863
902
|
const feedbackLabel = field.feedback_label ?? "What should be changed?";
|
|
864
903
|
const feedbackPlaceholder = field.feedback_placeholder ?? "Describe what needs to be modified.";
|
|
865
904
|
const approveLabel = field.approve_label ?? "Approve";
|
|
@@ -871,13 +910,29 @@ ${valueSummaryParts.join("\n")}` : "";
|
|
|
871
910
|
"div",
|
|
872
911
|
{
|
|
873
912
|
className: "rounded-md border border-border overflow-hidden bg-muted/20",
|
|
874
|
-
children:
|
|
875
|
-
"
|
|
913
|
+
children: /* @__PURE__ */ jsx10(
|
|
914
|
+
"button",
|
|
876
915
|
{
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
className: "w-full
|
|
880
|
-
|
|
916
|
+
type: "button",
|
|
917
|
+
onClick: () => setMediaPreview({ url, type: mediaType }),
|
|
918
|
+
className: "w-full text-left cursor-zoom-in",
|
|
919
|
+
title: "Click to view full media",
|
|
920
|
+
children: mediaType === "video" ? /* @__PURE__ */ jsx10(
|
|
921
|
+
"video",
|
|
922
|
+
{
|
|
923
|
+
src: url,
|
|
924
|
+
controls: true,
|
|
925
|
+
className: "w-full h-44 object-cover bg-black"
|
|
926
|
+
}
|
|
927
|
+
) : /* @__PURE__ */ jsx10(
|
|
928
|
+
"img",
|
|
929
|
+
{
|
|
930
|
+
src: url,
|
|
931
|
+
alt: `Generated media ${idx + 1}`,
|
|
932
|
+
className: "w-full h-44 object-cover",
|
|
933
|
+
loading: "lazy"
|
|
934
|
+
}
|
|
935
|
+
)
|
|
881
936
|
}
|
|
882
937
|
)
|
|
883
938
|
},
|
|
@@ -893,7 +948,7 @@ ${valueSummaryParts.join("\n")}` : "";
|
|
|
893
948
|
onChange: (e) => handleFieldChange(field.id, {
|
|
894
949
|
...mediaValue,
|
|
895
950
|
feedback: e.target.value,
|
|
896
|
-
media_urls: mediaValue.media_urls ?? mediaUrls,
|
|
951
|
+
media_urls: normalizeMediaUrls(mediaValue.media_urls ?? mediaUrls),
|
|
897
952
|
media_type: mediaValue.media_type ?? field.media_type ?? "mixed"
|
|
898
953
|
}),
|
|
899
954
|
placeholder: feedbackPlaceholder,
|
|
@@ -1181,12 +1236,14 @@ ${valueSummaryParts.join("\n")}` : "";
|
|
|
1181
1236
|
children: /* @__PURE__ */ jsxs2("div", { className: "space-y-3 pb-2", children: [
|
|
1182
1237
|
fields.map((field) => {
|
|
1183
1238
|
const statusText = getFieldStatusText(field);
|
|
1239
|
+
const labelText = getTextValue(field.label, field.id);
|
|
1240
|
+
const descriptionText = getTextValue(field.description, "");
|
|
1184
1241
|
return /* @__PURE__ */ jsxs2("div", { className: "space-y-1", children: [
|
|
1185
1242
|
/* @__PURE__ */ jsxs2(Label2, { className: "text-xs font-medium flex items-center gap-1.5", children: [
|
|
1186
|
-
/* @__PURE__ */ jsx10("span", { children:
|
|
1243
|
+
/* @__PURE__ */ jsx10("span", { children: labelText }),
|
|
1187
1244
|
field.required && /* @__PURE__ */ jsx10("span", { className: "text-destructive text-[10px]", children: "*" })
|
|
1188
1245
|
] }),
|
|
1189
|
-
|
|
1246
|
+
descriptionText && /* @__PURE__ */ jsx10("p", { className: "text-[11px] text-muted-foreground leading-snug", children: descriptionText }),
|
|
1190
1247
|
renderField(field),
|
|
1191
1248
|
statusText && field.type !== "file" && field.type !== "todo_list" && /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-1 text-emerald-600 mt-0.5", children: [
|
|
1192
1249
|
/* @__PURE__ */ jsx10(CheckCircle, { className: "w-2.5 h-2.5" }),
|
|
@@ -1202,7 +1259,7 @@ ${valueSummaryParts.join("\n")}` : "";
|
|
|
1202
1259
|
}
|
|
1203
1260
|
),
|
|
1204
1261
|
/* @__PURE__ */ jsx10("div", { className: `scroll-fade-bottom ${!canScrollDown ? "fade-hidden" : ""}` }),
|
|
1205
|
-
/* @__PURE__ */ jsxs2("div", { className: "flex justify-end gap-2 px-5 py-2 flex-shrink-0", children: [
|
|
1262
|
+
!(fields.length === 1 && fields[0]?.type === "media_approval") && /* @__PURE__ */ jsxs2("div", { className: "flex justify-end gap-2 px-5 py-2 flex-shrink-0", children: [
|
|
1206
1263
|
cancelText && /* @__PURE__ */ jsx10(
|
|
1207
1264
|
Button,
|
|
1208
1265
|
{
|
|
@@ -1227,7 +1284,50 @@ ${valueSummaryParts.join("\n")}` : "";
|
|
|
1227
1284
|
}
|
|
1228
1285
|
)
|
|
1229
1286
|
] })
|
|
1230
|
-
] })
|
|
1287
|
+
] }),
|
|
1288
|
+
mediaPreview && /* @__PURE__ */ jsx10(
|
|
1289
|
+
"div",
|
|
1290
|
+
{
|
|
1291
|
+
className: "fixed inset-0 z-50 bg-black/80 flex items-center justify-center p-4",
|
|
1292
|
+
onClick: () => setMediaPreview(null),
|
|
1293
|
+
children: /* @__PURE__ */ jsxs2(
|
|
1294
|
+
"div",
|
|
1295
|
+
{
|
|
1296
|
+
className: "relative w-full max-w-5xl max-h-[90vh] bg-background rounded-lg border border-border overflow-hidden",
|
|
1297
|
+
onClick: (e) => e.stopPropagation(),
|
|
1298
|
+
children: [
|
|
1299
|
+
/* @__PURE__ */ jsx10(
|
|
1300
|
+
Button,
|
|
1301
|
+
{
|
|
1302
|
+
type: "button",
|
|
1303
|
+
variant: "ghost",
|
|
1304
|
+
size: "sm",
|
|
1305
|
+
onClick: () => setMediaPreview(null),
|
|
1306
|
+
className: "absolute right-2 top-2 z-10 bg-background/80 hover:bg-background",
|
|
1307
|
+
children: /* @__PURE__ */ jsx10(X, { className: "w-4 h-4" })
|
|
1308
|
+
}
|
|
1309
|
+
),
|
|
1310
|
+
/* @__PURE__ */ jsx10("div", { className: "w-full h-full p-2 flex items-center justify-center", children: mediaPreview.type === "video" ? /* @__PURE__ */ jsx10(
|
|
1311
|
+
"video",
|
|
1312
|
+
{
|
|
1313
|
+
src: mediaPreview.url,
|
|
1314
|
+
controls: true,
|
|
1315
|
+
autoPlay: true,
|
|
1316
|
+
className: "max-w-full max-h-[84vh] object-contain bg-black rounded"
|
|
1317
|
+
}
|
|
1318
|
+
) : /* @__PURE__ */ jsx10(
|
|
1319
|
+
"img",
|
|
1320
|
+
{
|
|
1321
|
+
src: mediaPreview.url,
|
|
1322
|
+
alt: "Full preview",
|
|
1323
|
+
className: "max-w-full max-h-[84vh] object-contain rounded"
|
|
1324
|
+
}
|
|
1325
|
+
) })
|
|
1326
|
+
]
|
|
1327
|
+
}
|
|
1328
|
+
)
|
|
1329
|
+
}
|
|
1330
|
+
)
|
|
1231
1331
|
] });
|
|
1232
1332
|
}
|
|
1233
1333
|
|
package/package.json
CHANGED