@streamoid/chat-components 0.2.7 → 0.2.8

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 (2) hide show
  1. package/dist/index.js +48 -8
  2. 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 = Array.isArray(field.media_urls) ? field.media_urls.filter(Boolean) : [];
473
+ const mediaUrls = normalizeMediaUrls(field.media_urls);
442
474
  values[field.id] = {
443
475
  decision: null,
444
476
  feedback: "",
@@ -694,7 +726,13 @@ function DynamicForm(props) {
694
726
  const field = fields.find((f) => f.id === fieldId);
695
727
  const fieldLabel = field?.label || fieldId;
696
728
  let displayVal;
697
- if (field?.options && typeof val === "string") {
729
+ if (field?.type === "media_approval" && val && typeof val === "object") {
730
+ const mediaVal = val;
731
+ const decisionText = mediaVal.decision ?? "pending";
732
+ const feedbackText = mediaVal.feedback?.trim() || "none";
733
+ const mediaCount = Array.isArray(mediaVal.media_urls) ? mediaVal.media_urls.length : 0;
734
+ displayVal = `decision=${decisionText}, feedback=${feedbackText}, media_count=${mediaCount}`;
735
+ } else if (field?.options && typeof val === "string") {
698
736
  const opt = field.options.find((o) => o.id === val);
699
737
  displayVal = opt?.label || val;
700
738
  } else if (field?.options && Array.isArray(val)) {
@@ -853,13 +891,13 @@ ${valueSummaryParts.join("\n")}` : "";
853
891
  )
854
892
  ] });
855
893
  case "media_approval": {
856
- const mediaUrls = Array.isArray(field.media_urls) ? field.media_urls.filter(Boolean) : [];
857
894
  const mediaValue = formValues[field.id] ?? {
858
895
  decision: null,
859
896
  feedback: "",
860
- media_urls: mediaUrls,
897
+ media_urls: normalizeMediaUrls(field.media_urls),
861
898
  media_type: field.media_type ?? "mixed"
862
899
  };
900
+ const mediaUrls = normalizeMediaUrls(field.media_urls ?? mediaValue.media_urls);
863
901
  const feedbackLabel = field.feedback_label ?? "What should be changed?";
864
902
  const feedbackPlaceholder = field.feedback_placeholder ?? "Describe what needs to be modified.";
865
903
  const approveLabel = field.approve_label ?? "Approve";
@@ -893,7 +931,7 @@ ${valueSummaryParts.join("\n")}` : "";
893
931
  onChange: (e) => handleFieldChange(field.id, {
894
932
  ...mediaValue,
895
933
  feedback: e.target.value,
896
- media_urls: mediaValue.media_urls ?? mediaUrls,
934
+ media_urls: normalizeMediaUrls(mediaValue.media_urls ?? mediaUrls),
897
935
  media_type: mediaValue.media_type ?? field.media_type ?? "mixed"
898
936
  }),
899
937
  placeholder: feedbackPlaceholder,
@@ -1181,12 +1219,14 @@ ${valueSummaryParts.join("\n")}` : "";
1181
1219
  children: /* @__PURE__ */ jsxs2("div", { className: "space-y-3 pb-2", children: [
1182
1220
  fields.map((field) => {
1183
1221
  const statusText = getFieldStatusText(field);
1222
+ const labelText = getTextValue(field.label, field.id);
1223
+ const descriptionText = getTextValue(field.description, "");
1184
1224
  return /* @__PURE__ */ jsxs2("div", { className: "space-y-1", children: [
1185
1225
  /* @__PURE__ */ jsxs2(Label2, { className: "text-xs font-medium flex items-center gap-1.5", children: [
1186
- /* @__PURE__ */ jsx10("span", { children: field.label }),
1226
+ /* @__PURE__ */ jsx10("span", { children: labelText }),
1187
1227
  field.required && /* @__PURE__ */ jsx10("span", { className: "text-destructive text-[10px]", children: "*" })
1188
1228
  ] }),
1189
- field.description && /* @__PURE__ */ jsx10("p", { className: "text-[11px] text-muted-foreground leading-snug", children: field.description }),
1229
+ descriptionText && /* @__PURE__ */ jsx10("p", { className: "text-[11px] text-muted-foreground leading-snug", children: descriptionText }),
1190
1230
  renderField(field),
1191
1231
  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
1232
  /* @__PURE__ */ jsx10(CheckCircle, { className: "w-2.5 h-2.5" }),
@@ -1202,7 +1242,7 @@ ${valueSummaryParts.join("\n")}` : "";
1202
1242
  }
1203
1243
  ),
1204
1244
  /* @__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: [
1245
+ !(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
1246
  cancelText && /* @__PURE__ */ jsx10(
1207
1247
  Button,
1208
1248
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@streamoid/chat-components",
3
- "version": "0.2.7",
3
+ "version": "0.2.8",
4
4
  "description": "Shared chat UI components for the Streamoid chat host — DynamicForm and other cross-service components",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",