pxengine 0.1.28 → 0.1.30

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.mjs CHANGED
@@ -63,6 +63,10 @@ __export(atoms_exports, {
63
63
  VideoAtom: () => VideoAtom
64
64
  });
65
65
 
66
+ // src/atoms/TextAtom.tsx
67
+ import ReactMarkdown from "react-markdown";
68
+ import remarkGfm from "remark-gfm";
69
+
66
70
  // src/lib/utils.ts
67
71
  import { clsx } from "clsx";
68
72
  import { twMerge } from "tailwind-merge";
@@ -77,7 +81,8 @@ var TextAtom = ({
77
81
  variant = "p",
78
82
  className,
79
83
  style,
80
- backgroundColor
84
+ backgroundColor,
85
+ markdown = false
81
86
  }) => {
82
87
  const baseStyles = {
83
88
  h1: "scroll-m-20 text-4xl font-extrabold tracking-tight lg:text-5xl text-gray900",
@@ -90,14 +95,25 @@ var TextAtom = ({
90
95
  label: "text-[10px] font-bold text-gray400 uppercase tracking-widest pl-1"
91
96
  };
92
97
  const Component2 = variant === "small" || variant === "muted" || variant === "label" ? "p" : variant;
98
+ const wrapperStyles = {
99
+ ...style,
100
+ ...backgroundColor && { backgroundColor }
101
+ };
102
+ if (markdown) {
103
+ return /* @__PURE__ */ jsx(
104
+ "div",
105
+ {
106
+ className: cn(baseStyles[variant], "prose prose-sm max-w-none", className),
107
+ style: wrapperStyles,
108
+ children: /* @__PURE__ */ jsx(ReactMarkdown, { remarkPlugins: [remarkGfm], children: content })
109
+ }
110
+ );
111
+ }
93
112
  return /* @__PURE__ */ jsx(
94
113
  Component2,
95
114
  {
96
115
  className: cn(baseStyles[variant], className),
97
- style: {
98
- ...style,
99
- ...backgroundColor && { backgroundColor }
100
- },
116
+ style: wrapperStyles,
101
117
  children: content
102
118
  }
103
119
  );
@@ -25256,7 +25272,7 @@ var InputAtom = ({
25256
25272
  import { cva as cva3 } from "class-variance-authority";
25257
25273
  import { jsx as jsx18 } from "react/jsx-runtime";
25258
25274
  var badgeVariants = cva3(
25259
- "inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
25275
+ "inline-flex items-center rounded-full border px-2.5 py-1 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
25260
25276
  {
25261
25277
  variants: {
25262
25278
  variant: {
@@ -33772,7 +33788,7 @@ var EditableField = React85.memo(
33772
33788
  "div",
33773
33789
  {
33774
33790
  className: cn(
33775
- "relative z-10 group flex flex-col gap-2 p-3 bg-background dark:bg-gray700 rounded-md mb-8",
33791
+ "relative z-10 group flex flex-col gap-2 p-3 bg-paperBackground rounded-md mb-8",
33776
33792
  className
33777
33793
  ),
33778
33794
  children: [
@@ -33784,13 +33800,14 @@ var EditableField = React85.memo(
33784
33800
  children: label
33785
33801
  }
33786
33802
  ),
33787
- !isEditingProp && /* @__PURE__ */ jsxs54("span", { className: "inline-flex items-center gap-1 text-[10px] font-medium text-green-500 dark:text-green-500", children: [
33803
+ !isEditingProp && /* @__PURE__ */ jsxs54("span", { className: "inline-flex items-center gap-1.5 text-[0.75rem] font-medium text-green-600 dark:text-green-500 bg-green-500/5 px-2 py-0.5 rounded-full ", children: [
33788
33804
  "Suggested by an Agent",
33789
33805
  /* @__PURE__ */ jsx94(
33790
- Pencil,
33806
+ "span",
33791
33807
  {
33792
- className: "h-3 w-3 hover:text-green-700 cursor-pointer",
33793
- onClick: onEdit
33808
+ className: "flex items-center gap-1 cursor-pointer text-foreground hover:text-green-700 transition-colors ml-1 pl-1.5 ",
33809
+ onClick: onEdit,
33810
+ children: /* @__PURE__ */ jsx94(SquarePen, { className: "h-5 w-5" })
33794
33811
  }
33795
33812
  )
33796
33813
  ] })
@@ -33803,7 +33820,7 @@ var EditableField = React85.memo(
33803
33820
  {
33804
33821
  size: "icon",
33805
33822
  variant: "outline",
33806
- className: "h-8 w-8 text-destructive border-destructive/20 hover:bg-destructive/10 rounded-lg",
33823
+ className: "h-8 w-8 text-foreground rounded-lg",
33807
33824
  onClick: onCancel,
33808
33825
  disabled: isSaving,
33809
33826
  children: /* @__PURE__ */ jsx94(X, { className: "h-4 w-4" })
@@ -33813,10 +33830,10 @@ var EditableField = React85.memo(
33813
33830
  Button,
33814
33831
  {
33815
33832
  size: "icon",
33816
- className: "h-8 w-8 bg-purpleLight text-purpleText2 hover:bg-purpleText1 rounded-lg border border-purpleText1 shadow-none",
33833
+ className: "h-8 w-8 text-foreground rounded-lg shadow-none",
33817
33834
  onClick: handleSave,
33818
33835
  disabled: isSaving,
33819
- children: isSaving ? /* @__PURE__ */ jsx94(LoaderCircle, { className: "h-4 w-4 animate-spin" }) : /* @__PURE__ */ jsx94(Check, { className: "h-4 w-4" })
33836
+ children: isSaving ? /* @__PURE__ */ jsx94(LoaderCircle, { className: "h-4 w-4 animate-spin" }) : /* @__PURE__ */ jsx94(Save, { className: "h-4 w-4" })
33820
33837
  }
33821
33838
  )
33822
33839
  ] })
@@ -33824,9 +33841,10 @@ var EditableField = React85.memo(
33824
33841
  "div",
33825
33842
  {
33826
33843
  className: cn(
33827
- "relative flex items-center justify-between rounded-lg px-3 py-2",
33828
- "text-[14px] text-foreground font-normal leading-relaxed"
33844
+ "relative flex items-start justify-between rounded-lg px-3 py-2",
33845
+ "text-base text-foreground/90 font-medium leading-relaxed"
33829
33846
  ),
33847
+ style: { fontFamily: "Noto Sans, sans-serif" },
33830
33848
  children: /* @__PURE__ */ jsx94("div", { className: "flex-1", children: formattedValue() })
33831
33849
  }
33832
33850
  )
@@ -33930,51 +33948,113 @@ var ActionButton = React86.memo(
33930
33948
  ActionButton.displayName = "ActionButton";
33931
33949
 
33932
33950
  // src/molecules/generic/FormCard/FormCard.tsx
33933
- import React87 from "react";
33951
+ import React87, { useState as useState7 } from "react";
33934
33952
  import { jsx as jsx96, jsxs as jsxs56 } from "react/jsx-runtime";
33935
33953
  var FormCard = React87.memo(
33936
33954
  ({
33937
- // title,
33955
+ title,
33938
33956
  fields,
33939
33957
  data,
33940
- editingFields = {},
33958
+ editingFields: externalEditingFields,
33941
33959
  changedFields = {},
33942
33960
  savingFields = {},
33943
- onFieldEdit,
33944
- onFieldSave,
33945
- onFieldCancel,
33961
+ onFieldEdit: externalOnFieldEdit,
33962
+ onFieldSave: externalOnFieldSave,
33963
+ onFieldCancel: externalOnFieldCancel,
33946
33964
  showTimeline = true,
33947
33965
  proceedLabel,
33948
33966
  onProceed,
33949
33967
  isLatestMessage = true,
33968
+ hideTitle = false,
33969
+ hideCopyButton = false,
33950
33970
  className,
33951
33971
  footer
33952
33972
  }) => {
33973
+ const [copied, setCopied] = useState7(false);
33974
+ const [internalEditingFields, setInternalEditingFields] = useState7({});
33975
+ const [internalData, setInternalData] = useState7(data);
33976
+ React87.useEffect(() => {
33977
+ setInternalData(data);
33978
+ }, [data]);
33979
+ const isExternallyControlled = !!(externalOnFieldEdit || externalOnFieldSave || externalOnFieldCancel);
33980
+ const editingFields = isExternallyControlled ? externalEditingFields || {} : internalEditingFields;
33981
+ const activeData = isExternallyControlled ? data : internalData;
33982
+ const handleFieldEdit = (key) => {
33983
+ if (isExternallyControlled) {
33984
+ externalOnFieldEdit?.(key);
33985
+ } else {
33986
+ setInternalEditingFields((prev) => ({ ...prev, [key]: true }));
33987
+ }
33988
+ };
33989
+ const handleFieldSave = (key, newValue) => {
33990
+ if (isExternallyControlled) {
33991
+ externalOnFieldSave?.(key, newValue);
33992
+ } else {
33993
+ setInternalData((prev) => ({ ...prev, [key]: newValue }));
33994
+ setInternalEditingFields((prev) => ({ ...prev, [key]: false }));
33995
+ }
33996
+ };
33997
+ const handleFieldCancel = (key) => {
33998
+ if (isExternallyControlled) {
33999
+ externalOnFieldCancel?.(key);
34000
+ } else {
34001
+ setInternalEditingFields((prev) => ({ ...prev, [key]: false }));
34002
+ }
34003
+ };
33953
34004
  const handleCopyAll = () => {
33954
- const text = fields.map((field) => {
33955
- const value = data[field.key];
33956
- return `${field.label}: ${typeof value === "object" ? JSON.stringify(value) : value}`;
33957
- }).join("\n");
33958
- navigator.clipboard.writeText(text);
34005
+ const flattenValue = (val) => {
34006
+ if (val === null || val === void 0) return "-";
34007
+ if (Array.isArray(val)) {
34008
+ return val.map((item) => {
34009
+ if (typeof item === "object" && item !== null) {
34010
+ return item.label || item.value || item.name || JSON.stringify(item);
34011
+ }
34012
+ return String(item);
34013
+ }).join(", ");
34014
+ }
34015
+ if (typeof val === "object") {
34016
+ return Object.entries(val).map(([k, v]) => `${k.replace(/_/g, " ")}: ${v}`).join(", ");
34017
+ }
34018
+ return String(val);
34019
+ };
34020
+ const text = [
34021
+ title,
34022
+ "",
34023
+ ...fields.map((field) => {
34024
+ const value = activeData[field.key];
34025
+ return `${field.label}: ${flattenValue(value)}`;
34026
+ })
34027
+ ].join("\n");
34028
+ navigator.clipboard.writeText(text).then(() => {
34029
+ setCopied(true);
34030
+ setTimeout(() => setCopied(false), 2e3);
34031
+ });
33959
34032
  };
33960
34033
  return /* @__PURE__ */ jsxs56(
33961
34034
  "div",
33962
34035
  {
33963
34036
  className: cn(
33964
- "relative w-full rounded-[20px] bg-background dark:bg-gray100 border border-gray400 shadow-lg overflow-hidden mb-6 font-noto",
34037
+ "relative w-full rounded-[20px] bg-paperBackground dark:bg-gray100 border border-gray400 shadow-lg overflow-hidden mb-6 font-noto",
33965
34038
  className
33966
34039
  ),
33967
34040
  children: [
33968
- /* @__PURE__ */ jsx96(
34041
+ !hideCopyButton && /* @__PURE__ */ jsx96(
33969
34042
  "button",
33970
34043
  {
33971
34044
  onClick: handleCopyAll,
33972
34045
  title: "Copy all details",
33973
- className: "absolute top-4 right-4 p-2 rounded-lg hover:bg-gray-100 dark:hover:bg-gray200 text-gray-400 hover:text-gray-600 dark:hover:text-gray300 transition-all active:scale-95 z-10",
33974
- children: /* @__PURE__ */ jsx96(Copy, { className: "h-4 w-4" })
34046
+ className: "absolute top-4 right-4 p-2 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-200 text-gray-400 hover:text-gray-600 dark:hover:text-gray300 transition-all active:scale-95 z-10",
34047
+ children: copied ? /* @__PURE__ */ jsx96(Check, { className: "h-4 w-4 text-green-500" }) : /* @__PURE__ */ jsx96(Copy, { className: "h-4 w-4" })
33975
34048
  }
33976
34049
  ),
33977
34050
  /* @__PURE__ */ jsxs56("div", { className: "p-6 relative", children: [
34051
+ !hideTitle && title && /* @__PURE__ */ jsx96(
34052
+ "h3",
34053
+ {
34054
+ className: "text-gray900 dark:text-white mb-12 text-[1rem] font-bold",
34055
+ children: title
34056
+ }
34057
+ ),
33978
34058
  showTimeline && /* @__PURE__ */ jsx96(
33979
34059
  "div",
33980
34060
  {
@@ -33991,16 +34071,16 @@ var FormCard = React87.memo(
33991
34071
  EditableField,
33992
34072
  {
33993
34073
  label: field.label,
33994
- value: data[field.key],
34074
+ value: activeData[field.key],
33995
34075
  type: field.type,
33996
34076
  config: field,
33997
34077
  isEditing: editingFields[field.key],
33998
34078
  isChanged: changedFields[field.key],
33999
34079
  isSaving: savingFields[field.key],
34000
34080
  isLatestMessage,
34001
- onEdit: () => onFieldEdit?.(field.key),
34002
- onSave: (val) => onFieldSave?.(field.key, val),
34003
- onCancel: () => onFieldCancel?.(field.key),
34081
+ onEdit: () => handleFieldEdit(field.key),
34082
+ onSave: (val) => handleFieldSave(field.key, val),
34083
+ onCancel: () => handleFieldCancel(field.key),
34004
34084
  renderDisplay: field.renderDisplay,
34005
34085
  renderEdit: field.renderEdit,
34006
34086
  showIndex: showTimeline,
@@ -34537,7 +34617,7 @@ function generateFieldsFromData(data) {
34537
34617
  }
34538
34618
 
34539
34619
  // src/molecules/creator-discovery/SearchSpecCard/CustomFieldRenderers.tsx
34540
- import { useState as useState7, useRef as useRef5, useEffect as useEffect6 } from "react";
34620
+ import { useState as useState8, useRef as useRef5, useEffect as useEffect6 } from "react";
34541
34621
 
34542
34622
  // src/lib/countries.ts
34543
34623
  var countries = [
@@ -34749,8 +34829,8 @@ var CountrySelectEdit = ({
34749
34829
  value,
34750
34830
  onChange
34751
34831
  }) => {
34752
- const [isDropdownOpen, setIsDropdownOpen] = useState7(false);
34753
- const [searchTerm, setSearchTerm] = useState7("");
34832
+ const [isDropdownOpen, setIsDropdownOpen] = useState8(false);
34833
+ const [searchTerm, setSearchTerm] = useState8("");
34754
34834
  const dropdownRef = useRef5(null);
34755
34835
  useEffect6(() => {
34756
34836
  const handleClickOutside = (event) => {
@@ -34861,7 +34941,7 @@ var CountrySelectDisplay = ({ value }) => {
34861
34941
  Badge2,
34862
34942
  {
34863
34943
  variant: "outline",
34864
- className: "bg-gray-50 text-gray-700 border-gray-200",
34944
+ className: "text-foreground border-gray-200 py-1",
34865
34945
  children: countryCode
34866
34946
  },
34867
34947
  countryCode
@@ -34881,7 +34961,7 @@ var KeywordBundlesEdit = ({
34881
34961
  const sortedPriorities = Object.keys(groups).map((n) => parseInt(n)).sort((a, b) => a - b);
34882
34962
  return /* @__PURE__ */ jsx106("div", { className: "space-y-6 pt-2", children: sortedPriorities.map((priority) => /* @__PURE__ */ jsxs66("div", { className: "space-y-3", children: [
34883
34963
  /* @__PURE__ */ jsxs66("div", { className: "flex items-center gap-2", children: [
34884
- /* @__PURE__ */ jsxs66(Badge2, { className: "bg-purple500 hover:bg-purple500", children: [
34964
+ /* @__PURE__ */ jsxs66(Badge2, { className: "bg-purple500 hover:bg-purple500 py-1", children: [
34885
34965
  "Priority ",
34886
34966
  priority
34887
34967
  ] }),
@@ -34897,7 +34977,7 @@ var KeywordBundlesEdit = ({
34897
34977
  /* @__PURE__ */ jsx106("div", { className: "flex flex-wrap gap-1.5", children: Array.isArray(bundle.keywords) && bundle.keywords.map((keyword, kIndex) => /* @__PURE__ */ jsxs66(
34898
34978
  Badge2,
34899
34979
  {
34900
- className: "bg-white border-gray-200 text-gray-700 hover:bg-red-50 hover:text-red-600 hover:border-red-100 transition-all cursor-pointer group",
34980
+ className: "bg-white py-1 border-gray-200 text-gray-700 hover:bg-red-50 hover:text-red-600 hover:border-red-100 transition-all cursor-pointer group",
34901
34981
  onClick: () => {
34902
34982
  const updatedBundles = [...bundles];
34903
34983
  updatedBundles[bundleIndex] = {
@@ -34991,7 +35071,7 @@ var KeywordBundlesDisplay = ({ value }) => {
34991
35071
  /* @__PURE__ */ jsx106("div", { className: "flex flex-wrap gap-2", children: deduped.map((keyword) => /* @__PURE__ */ jsx106(
34992
35072
  "div",
34993
35073
  {
34994
- className: "px-2 py-1 rounded bg-background bg-gray400 border border-white/10 text-gray-300 text-xs font-medium",
35074
+ className: "px-2 py-1 rounded bg-background border text-gray-300 text-sm font-medium py-1",
34995
35075
  children: keyword
34996
35076
  },
34997
35077
  keyword
@@ -35015,7 +35095,7 @@ var ObjectDisplay = ({ value }) => {
35015
35095
  var StringArrayDisplay = ({ value }) => {
35016
35096
  if (!Array.isArray(value) || value.length === 0)
35017
35097
  return /* @__PURE__ */ jsx107("span", { className: "text-muted-foreground italic text-sm", children: "Not specified" });
35018
- return /* @__PURE__ */ jsx107("div", { className: "flex flex-wrap gap-1.5 pt-1", children: value.map((item) => /* @__PURE__ */ jsx107(Badge2, { variant: "outline", className: "text-xs", children: item }, item)) });
35098
+ return /* @__PURE__ */ jsx107("div", { className: "flex flex-wrap gap-1.5 pt-1", children: value.map((item) => /* @__PURE__ */ jsx107(Badge2, { variant: "outline", className: "text-sm border-gray-200 py-1", children: item }, item)) });
35019
35099
  };
35020
35100
  function buildCampaignSeedFields(data) {
35021
35101
  if (!data || typeof data !== "object") return [];
@@ -35026,7 +35106,32 @@ function buildCampaignSeedFields(data) {
35026
35106
  key,
35027
35107
  label: "Keyword Bundles",
35028
35108
  type: "custom",
35029
- renderDisplay: (v) => /* @__PURE__ */ jsx107(KeywordBundlesDisplay, { value: v })
35109
+ renderDisplay: (v) => /* @__PURE__ */ jsx107(KeywordBundlesDisplay, { value: v }),
35110
+ renderEdit: (v, onChange) => /* @__PURE__ */ jsx107(
35111
+ Textarea,
35112
+ {
35113
+ value: Array.isArray(v) ? v.map((b) => `${(b.keywords || []).join(", ")} (Priority: ${b.priority || 1})`).join("\n") : String(v || ""),
35114
+ onChange: (e) => {
35115
+ const lines = e.target.value.split("\n").filter(Boolean);
35116
+ const bundles = lines.map((line) => {
35117
+ const match2 = line.match(/(.*?)\s*\(Priority:\s*(\d+)\)/i);
35118
+ if (match2) {
35119
+ return {
35120
+ keywords: match2[1].split(",").map((s) => s.trim()).filter(Boolean),
35121
+ priority: parseInt(match2[2]) || 1
35122
+ };
35123
+ }
35124
+ return {
35125
+ keywords: line.split(",").map((s) => s.trim()).filter(Boolean),
35126
+ priority: 1
35127
+ };
35128
+ });
35129
+ onChange(bundles);
35130
+ },
35131
+ placeholder: "Keyword 1, Keyword 2 (Priority: 1)...",
35132
+ className: "min-h-[120px] bg-background border-gray-300"
35133
+ }
35134
+ )
35030
35135
  };
35031
35136
  }
35032
35137
  if (key === "geography") {
@@ -35034,7 +35139,19 @@ function buildCampaignSeedFields(data) {
35034
35139
  key,
35035
35140
  label: "Geography",
35036
35141
  type: "custom",
35037
- renderDisplay: (v) => /* @__PURE__ */ jsx107(CountrySelectDisplay, { value: v })
35142
+ renderDisplay: (v) => /* @__PURE__ */ jsx107(CountrySelectDisplay, { value: v }),
35143
+ renderEdit: (v, onChange) => /* @__PURE__ */ jsx107(
35144
+ Textarea,
35145
+ {
35146
+ value: Array.isArray(v) ? v.join(", ") : String(v || ""),
35147
+ onChange: (e) => {
35148
+ const items = e.target.value.split(",").map((s) => s.trim().toUpperCase()).filter(Boolean);
35149
+ onChange(items);
35150
+ },
35151
+ placeholder: "Enter country codes (US, GB, PK) separated by commas...",
35152
+ className: "min-h-[80px] bg-background border-gray-300"
35153
+ }
35154
+ )
35038
35155
  };
35039
35156
  }
35040
35157
  if (key === "platforms" && Array.isArray(value)) {
@@ -35055,7 +35172,19 @@ function buildCampaignSeedFields(data) {
35055
35172
  },
35056
35173
  p
35057
35174
  )) });
35058
- }
35175
+ },
35176
+ renderEdit: (v, onChange) => /* @__PURE__ */ jsx107(
35177
+ Textarea,
35178
+ {
35179
+ value: Array.isArray(v) ? v.join(", ") : String(v || ""),
35180
+ onChange: (e) => {
35181
+ const items = e.target.value.split(",").map((s) => s.trim()).filter(Boolean);
35182
+ onChange(items);
35183
+ },
35184
+ placeholder: "Enter platforms separated by commas...",
35185
+ className: "min-h-[80px] bg-background border-gray-300"
35186
+ }
35187
+ )
35059
35188
  };
35060
35189
  }
35061
35190
  if (Array.isArray(value) && value.every((v) => typeof v === "string")) {
@@ -35087,7 +35216,26 @@ function buildCampaignSeedFields(data) {
35087
35216
  key,
35088
35217
  label,
35089
35218
  type: "custom",
35090
- renderDisplay: (v) => /* @__PURE__ */ jsx107(ObjectDisplay, { value: v })
35219
+ renderDisplay: (v) => /* @__PURE__ */ jsx107(ObjectDisplay, { value: v }),
35220
+ renderEdit: (v, onChange) => /* @__PURE__ */ jsx107(
35221
+ Textarea,
35222
+ {
35223
+ value: Object.entries(v || {}).map(([k, val]) => `${k.replace(/_/g, " ")}: ${val}`).join("\n"),
35224
+ onChange: (e) => {
35225
+ const lines = e.target.value.split("\n").filter(Boolean);
35226
+ const newObj = {};
35227
+ lines.forEach((line) => {
35228
+ const [k, ...rest] = line.split(":");
35229
+ if (k) {
35230
+ newObj[k.trim().replace(/\s+/g, "_").toLowerCase()] = rest.join(":").trim();
35231
+ }
35232
+ });
35233
+ onChange(newObj);
35234
+ },
35235
+ placeholder: "Enter key: value pairs (one per line)...",
35236
+ className: "min-h-[120px] bg-background border-gray-300 font-mono text-xs"
35237
+ }
35238
+ )
35091
35239
  };
35092
35240
  }
35093
35241
  const [generated] = generateFieldsFromData({ [key]: value });
@@ -35128,7 +35276,7 @@ var CampaignSeedCard = React90.memo(
35128
35276
  showTimeline: true,
35129
35277
  isLatestMessage: effectiveIsLatest,
35130
35278
  className: cn("font-noto", className),
35131
- footer: !effectiveIsLatest && (selectionStatus || hasUserResponded) ? /* @__PURE__ */ jsxs67("div", { className: "flex justify-end items-center gap-1.5 text-green-600 text-[10px] font-semibold py-4 pr-6", children: [
35279
+ footer: !effectiveIsLatest && selectionStatus ? /* @__PURE__ */ jsxs67("div", { className: "flex justify-end items-center gap-1.5 text-green-600 text-[10px] font-semibold py-4 pr-6", children: [
35132
35280
  /* @__PURE__ */ jsx107(CircleCheck, { className: "h-3.5 w-3.5" }),
35133
35281
  /* @__PURE__ */ jsx107("span", { children: selectionStatus === "agent" ? "Suggested by Agent" : "Selected by you" })
35134
35282
  ] }) : formCardProps.footer
@@ -35154,7 +35302,7 @@ var ObjectDisplay2 = ({ value }) => {
35154
35302
  var StringArrayDisplay2 = ({ value }) => {
35155
35303
  if (!Array.isArray(value) || value.length === 0)
35156
35304
  return /* @__PURE__ */ jsx108("span", { className: "text-muted-foreground italic text-sm", children: "Not specified" });
35157
- return /* @__PURE__ */ jsx108("div", { className: "flex flex-wrap gap-1.5 pt-1", children: value.map((item) => /* @__PURE__ */ jsx108(Badge2, { variant: "outline", className: "text-xs", children: item }, item)) });
35305
+ return /* @__PURE__ */ jsx108("div", { className: "flex flex-wrap gap-1.5 pt-1", children: value.map((item) => /* @__PURE__ */ jsx108(Badge2, { variant: "outline", className: "text-sm border-gray-200 py-1", children: item }, item)) });
35158
35306
  };
35159
35307
  function buildSearchSpecFields(data) {
35160
35308
  if (!data || typeof data !== "object") return [];
@@ -35178,12 +35326,25 @@ function buildSearchSpecFields(data) {
35178
35326
  renderEdit: (v, onChange) => /* @__PURE__ */ jsx108(CountrySelectEdit, { value: v, onChange })
35179
35327
  };
35180
35328
  }
35181
- if (key === "platforms" && Array.isArray(value)) {
35329
+ if ((key === "platforms" || key === "exclude_keywords" || key === "excludeKeywords") && Array.isArray(value)) {
35330
+ const label = key === "platforms" ? "Platforms" : "Exclude Keywords";
35182
35331
  return {
35183
35332
  key,
35184
- label: "Platforms",
35333
+ label,
35185
35334
  type: "custom",
35186
- renderDisplay: (v) => /* @__PURE__ */ jsx108(StringArrayDisplay2, { value: v })
35335
+ renderDisplay: (v) => /* @__PURE__ */ jsx108(StringArrayDisplay2, { value: v }),
35336
+ renderEdit: (v, onChange) => /* @__PURE__ */ jsx108(
35337
+ Textarea,
35338
+ {
35339
+ value: Array.isArray(v) ? v.join(", ") : String(v || ""),
35340
+ onChange: (e) => {
35341
+ const items = e.target.value.split(",").map((s) => s.trim()).filter(Boolean);
35342
+ onChange(items);
35343
+ },
35344
+ placeholder: `Enter ${label.toLowerCase()} separated by commas...`,
35345
+ className: "min-h-[100px] bg-background border-gray-300"
35346
+ }
35347
+ )
35187
35348
  };
35188
35349
  }
35189
35350
  if (typeof value === "object" && value !== null && !Array.isArray(value) && !("min" in value && "max" in value)) {
@@ -35192,7 +35353,26 @@ function buildSearchSpecFields(data) {
35192
35353
  key,
35193
35354
  label,
35194
35355
  type: "custom",
35195
- renderDisplay: (v) => /* @__PURE__ */ jsx108(ObjectDisplay2, { value: v })
35356
+ renderDisplay: (v) => /* @__PURE__ */ jsx108(ObjectDisplay2, { value: v }),
35357
+ renderEdit: (v, onChange) => /* @__PURE__ */ jsx108(
35358
+ Textarea,
35359
+ {
35360
+ value: Object.entries(v || {}).map(([k, val]) => `${k.replace(/_/g, " ")}: ${val}`).join("\n"),
35361
+ onChange: (e) => {
35362
+ const lines = e.target.value.split("\n").filter(Boolean);
35363
+ const newObj = {};
35364
+ lines.forEach((line) => {
35365
+ const [k, ...rest] = line.split(":");
35366
+ if (k) {
35367
+ newObj[k.trim().replace(/\s+/g, "_").toLowerCase()] = rest.join(":").trim();
35368
+ }
35369
+ });
35370
+ onChange(newObj);
35371
+ },
35372
+ placeholder: "Enter key: value pairs (one per line)...",
35373
+ className: "min-h-[120px] bg-background border-gray-300 font-mono text-xs"
35374
+ }
35375
+ )
35196
35376
  };
35197
35377
  }
35198
35378
  const [generated] = generateFieldsFromData({ [key]: value });
@@ -35223,7 +35403,7 @@ var SearchSpecCard = React91.memo(
35223
35403
  });
35224
35404
  };
35225
35405
  const effectiveIsLatest = isLatestMessage && !hasUserResponded;
35226
- return /* @__PURE__ */ jsx108(
35406
+ return /* @__PURE__ */ jsx108("div", { className: "flex flex-col gap-2", children: /* @__PURE__ */ jsx108(
35227
35407
  FormCard,
35228
35408
  {
35229
35409
  ...formCardProps,
@@ -35234,12 +35414,12 @@ var SearchSpecCard = React91.memo(
35234
35414
  onProceed: handleProceed,
35235
35415
  isLatestMessage: effectiveIsLatest,
35236
35416
  className,
35237
- footer: !effectiveIsLatest && (selectionStatus || hasUserResponded) ? /* @__PURE__ */ jsxs68("div", { className: "flex justify-end items-center gap-1.5 text-green-600 text-xs font-semibold py-1", children: [
35417
+ footer: !effectiveIsLatest && selectionStatus ? /* @__PURE__ */ jsxs68("div", { className: "flex justify-end items-center gap-1.5 text-green-600 text-xs font-semibold py-1", children: [
35238
35418
  /* @__PURE__ */ jsx108(CircleCheck, { className: "h-4 w-4" }),
35239
35419
  /* @__PURE__ */ jsx108("span", { children: selectionStatus === "agent" ? "Selected by Agent" : "Selected by User" })
35240
35420
  ] }) : formCardProps.footer
35241
35421
  }
35242
- );
35422
+ ) });
35243
35423
  }
35244
35424
  );
35245
35425
  SearchSpecCard.displayName = "SearchSpecCard";
@@ -35944,7 +36124,7 @@ var CreatorSearch = React93.memo(
35944
36124
  CreatorSearch.displayName = "CreatorSearch";
35945
36125
 
35946
36126
  // src/molecules/creator-discovery/CampaignConceptCard/CampaignConceptCard.tsx
35947
- import React94, { useMemo as useMemo7, useState as useState8 } from "react";
36127
+ import React94, { useMemo as useMemo7, useState as useState9 } from "react";
35948
36128
  import { motion, AnimatePresence } from "framer-motion";
35949
36129
  import { jsx as jsx121, jsxs as jsxs80 } from "react/jsx-runtime";
35950
36130
  var CampaignConceptCard = React94.memo(
@@ -35962,8 +36142,8 @@ var CampaignConceptCard = React94.memo(
35962
36142
  onAction,
35963
36143
  ...formCardProps
35964
36144
  }) => {
35965
- const [internalIsOpen, setInternalIsOpen] = useState8(false);
35966
- const [copied, setCopied] = useState8(false);
36145
+ const [internalIsOpen, setInternalIsOpen] = useState9(false);
36146
+ const [copied, setCopied] = useState9(false);
35967
36147
  const isOpen = controlledIsOpen !== void 0 ? controlledIsOpen : internalIsOpen;
35968
36148
  const handleToggle = () => {
35969
36149
  if (onToggle) {
@@ -36076,7 +36256,26 @@ var CampaignConceptCard = React94.memo(
36076
36256
  ] }, k)) });
36077
36257
  }
36078
36258
  return /* @__PURE__ */ jsx121("span", { className: "text-muted-foreground text-sm", children: String(val) });
36079
- }
36259
+ },
36260
+ renderEdit: (v, onChange) => /* @__PURE__ */ jsx121(
36261
+ Textarea,
36262
+ {
36263
+ value: typeof v === "object" ? Object.entries(v || {}).map(([k, val]) => `${k.replace(/_/g, " ")}: ${val}`).join("\n") : String(v || ""),
36264
+ onChange: (e) => {
36265
+ const lines = e.target.value.split("\n").filter(Boolean);
36266
+ const newObj = {};
36267
+ lines.forEach((line) => {
36268
+ if (line.includes(":")) {
36269
+ const [k, ...rest] = line.split(":");
36270
+ newObj[k.trim().replace(/\s+/g, "_").toLowerCase()] = rest.join(":").trim().replace("%", "");
36271
+ }
36272
+ });
36273
+ onChange(newObj);
36274
+ },
36275
+ placeholder: "Tier name: percentage (one per line)...",
36276
+ className: "min-h-[120px] bg-background border-gray-300 font-mono text-xs"
36277
+ }
36278
+ )
36080
36279
  };
36081
36280
  }
36082
36281
  if (field.key === "estimatedCreators" || field.key === "estimated_creators") {
@@ -36109,14 +36308,40 @@ var CampaignConceptCard = React94.memo(
36109
36308
  )) });
36110
36309
  }
36111
36310
  return /* @__PURE__ */ jsx121("span", { className: "text-txtColor font-medium", children: String(val) });
36112
- }
36311
+ },
36312
+ renderEdit: (v, onChange) => /* @__PURE__ */ jsx121(
36313
+ Input,
36314
+ {
36315
+ value: typeof v === "object" ? `${v.min ?? 0}-${v.max ?? 0}` : String(v || ""),
36316
+ onChange: (e) => {
36317
+ const val = e.target.value;
36318
+ if (val.includes("-")) {
36319
+ const [min2, max2] = val.split("-").map((s) => parseInt(s.trim()) || 0);
36320
+ onChange({ min: min2, max: max2 });
36321
+ } else {
36322
+ onChange(val);
36323
+ }
36324
+ },
36325
+ placeholder: "Min-Max (e.g. 10-30)...",
36326
+ className: "bg-background border-gray-300"
36327
+ }
36328
+ )
36113
36329
  };
36114
36330
  }
36115
36331
  if (field.key === "primary_kpi" || field.key === "primaryKpi") {
36116
36332
  return {
36117
36333
  ...field,
36118
36334
  label: field.label || "Primary KPI",
36119
- renderDisplay: (val) => /* @__PURE__ */ jsx121("span", { className: "text-foreground text-sm", children: val ? String(val) : "-" })
36335
+ renderDisplay: (val) => /* @__PURE__ */ jsx121("span", { className: "text-foreground text-sm", children: val ? String(val) : "-" }),
36336
+ renderEdit: (v, onChange) => /* @__PURE__ */ jsx121(
36337
+ Input,
36338
+ {
36339
+ value: String(v || ""),
36340
+ onChange: (e) => onChange(e.target.value),
36341
+ placeholder: "Enter primary KPI...",
36342
+ className: "bg-background border-gray-300"
36343
+ }
36344
+ )
36120
36345
  };
36121
36346
  }
36122
36347
  if (field.key === "secondary_kpis" || field.key === "secondaryKpis") {
@@ -36126,7 +36351,19 @@ var CampaignConceptCard = React94.memo(
36126
36351
  renderDisplay: (val) => {
36127
36352
  const display = Array.isArray(val) ? val.map(String).join(", ") : val ? String(val) : "-";
36128
36353
  return /* @__PURE__ */ jsx121("span", { className: "text-foreground text-sm", children: display });
36129
- }
36354
+ },
36355
+ renderEdit: (v, onChange) => /* @__PURE__ */ jsx121(
36356
+ Textarea,
36357
+ {
36358
+ value: Array.isArray(v) ? v.join(", ") : String(v || ""),
36359
+ onChange: (e) => {
36360
+ const items = e.target.value.split(",").map((s) => s.trim()).filter(Boolean);
36361
+ onChange(items);
36362
+ },
36363
+ placeholder: "Enter KPIs separated by commas...",
36364
+ className: "min-h-[80px] bg-background border-gray-300"
36365
+ }
36366
+ )
36130
36367
  };
36131
36368
  }
36132
36369
  if (field.key === "platforms" || field.key === "target_platforms" || field.key === "targetPlatforms") {
@@ -36143,7 +36380,19 @@ var CampaignConceptCard = React94.memo(
36143
36380
  },
36144
36381
  p
36145
36382
  )) });
36146
- }
36383
+ },
36384
+ renderEdit: (v, onChange) => /* @__PURE__ */ jsx121(
36385
+ Textarea,
36386
+ {
36387
+ value: Array.isArray(v) ? v.join(", ") : String(v || ""),
36388
+ onChange: (e) => {
36389
+ const items = e.target.value.split(",").map((s) => s.trim()).filter(Boolean);
36390
+ onChange(items);
36391
+ },
36392
+ placeholder: "Enter platforms separated by commas...",
36393
+ className: "min-h-[80px] bg-background border-gray-300"
36394
+ }
36395
+ )
36147
36396
  };
36148
36397
  }
36149
36398
  return {
@@ -36189,8 +36438,8 @@ var CampaignConceptCard = React94.memo(
36189
36438
  /* @__PURE__ */ jsxs80("div", { className: "flex-1", children: [
36190
36439
  /* @__PURE__ */ jsx121("h2", { className: "mb-1 py-1 text-txtColor font-bold", children: typeof cardTitle === "object" ? JSON.stringify(cardTitle) : String(cardTitle) }),
36191
36440
  /* @__PURE__ */ jsxs80("div", { className: "flex flex-wrap gap-2", children: [
36192
- isRecommended && /* @__PURE__ */ jsx121("div", { className: "inline-flex text-[10px] font-bold uppercase tracking-widest text-[#22C55E]", children: /* @__PURE__ */ jsx121("span", { className: "bg-[#22C55E]/10 px-2 py-0.5 rounded border border-[#22C55E]/20", children: "Recommended" }) }),
36193
- !effectiveIsLatest && (selectionStatus || hasUserResponded) && /* @__PURE__ */ jsx121("div", { className: "inline-flex text-[10px] font-bold uppercase tracking-widest text-[#3B82F6]", children: /* @__PURE__ */ jsx121("span", { className: "bg-[#3B82F6]/10 px-2 py-0.5 rounded border border-[#3B82F6]/20", children: selectionStatus === "agent" ? "Selected by Agent" : "Selected by You" }) })
36441
+ isRecommended && /* @__PURE__ */ jsx121("div", { className: "inline-flex text-[10px] font-bold uppercase tracking-widest", children: /* @__PURE__ */ jsx121("span", { className: "bg-green-600 text-white px-2 py-0.5 rounded border border-green-700", children: "Recommended" }) }),
36442
+ !effectiveIsLatest && selectionStatus && /* @__PURE__ */ jsx121("div", { className: "inline-flex text-[10px] font-bold uppercase tracking-widest text-[#3B82F6]", children: /* @__PURE__ */ jsx121("span", { className: "bg-[#3B82F6]/10 px-2 py-0.5 rounded border border-[#3B82F6]/20", children: selectionStatus === "agent" ? "Selected by Agent" : "Selected by You" }) })
36194
36443
  ] })
36195
36444
  ] }),
36196
36445
  /* @__PURE__ */ jsxs80("div", { className: "flex items-center gap-2 ml-3", onClick: (e) => e.stopPropagation(), children: [
@@ -36256,8 +36505,10 @@ var CampaignConceptCard = React94.memo(
36256
36505
  proceedLabel: "Continue with this concept",
36257
36506
  onProceed: handleProceed,
36258
36507
  isLatestMessage: effectiveIsLatest,
36508
+ hideTitle: true,
36509
+ hideCopyButton: true,
36259
36510
  className: "bg-transparent border-none shadow-none mb-0 p-0",
36260
- footer: !effectiveIsLatest && (selectionStatus || hasUserResponded) ? /* @__PURE__ */ jsxs80("div", { className: "flex justify-end items-center gap-1.5 text-green-600 text-[10px] font-semibold py-4 pr-6", children: [
36511
+ footer: !effectiveIsLatest && selectionStatus ? /* @__PURE__ */ jsxs80("div", { className: "flex justify-end items-center gap-1.5 text-green-600 text-[10px] font-semibold py-4 pr-6", children: [
36261
36512
  /* @__PURE__ */ jsx121(CircleCheck, { className: "h-3.5 w-3.5" }),
36262
36513
  /* @__PURE__ */ jsx121("span", { children: selectionStatus === "agent" ? "Selected by Agent" : "Selected by You" })
36263
36514
  ] }) : formCardProps.footer