@jiggai/kitchen-plugin-marketing 0.5.0 → 0.5.2

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.
@@ -0,0 +1,13 @@
1
+ {
2
+ "version": "5",
3
+ "dialect": "sqlite",
4
+ "entries": [
5
+ {
6
+ "idx": 0,
7
+ "version": "5",
8
+ "when": 1743811200000,
9
+ "tag": "0001_initial",
10
+ "breakpoints": true
11
+ }
12
+ ]
13
+ }
@@ -219,7 +219,20 @@ function initializeDatabase(teamId) {
219
219
  const migrationsDir = (0, import_path.join)(PLUGIN_ROOT, "db", "migrations");
220
220
  (0, import_migrator.migrate)(db, { migrationsFolder: migrationsDir });
221
221
  } catch (error) {
222
- console.warn("Migration warning:", error?.message);
222
+ try {
223
+ const sqlPath = (0, import_path.join)(PLUGIN_ROOT, "db", "migrations", "0001_initial.sql");
224
+ if ((0, import_fs.existsSync)(sqlPath)) {
225
+ const sql2 = require("fs").readFileSync(sqlPath, "utf8");
226
+ const statements = sql2.split(";").map((s) => s.trim()).filter((s) => s.length > 0);
227
+ for (const stmt of statements) {
228
+ try {
229
+ sqlite.exec(stmt + ";");
230
+ } catch {
231
+ }
232
+ }
233
+ }
234
+ } catch {
235
+ }
223
236
  }
224
237
  return { db, sqlite };
225
238
  }
@@ -440,7 +453,8 @@ var XDriver = class extends BaseDriver {
440
453
  var InstagramDriver = class extends BaseDriver {
441
454
  platform = "instagram";
442
455
  label = "Instagram";
443
- icon = "\u{1F4F7}";
456
+ // Text fallback; UI renders these inside icon circles
457
+ icon = "IG";
444
458
  postizProvider = "instagram";
445
459
  getMaxLength() {
446
460
  return 2200;
@@ -454,7 +468,7 @@ var InstagramDriver = class extends BaseDriver {
454
468
  var FacebookDriver = class extends BaseDriver {
455
469
  platform = "facebook";
456
470
  label = "Facebook";
457
- icon = "\u{1F4D8}";
471
+ icon = "f";
458
472
  postizProvider = "facebook";
459
473
  getMaxLength() {
460
474
  return 63206;
@@ -468,7 +482,7 @@ var FacebookDriver = class extends BaseDriver {
468
482
  var LinkedInDriver = class extends BaseDriver {
469
483
  platform = "linkedin";
470
484
  label = "LinkedIn";
471
- icon = "\u{1F4BC}";
485
+ icon = "in";
472
486
  postizProvider = "linkedin";
473
487
  getMaxLength() {
474
488
  return 3e3;
@@ -482,7 +496,7 @@ var LinkedInDriver = class extends BaseDriver {
482
496
  var TikTokDriver = class extends BaseDriver {
483
497
  platform = "tiktok";
484
498
  label = "TikTok";
485
- icon = "\u{1F3B5}";
499
+ icon = "TT";
486
500
  postizProvider = "tiktok";
487
501
  getMaxLength() {
488
502
  return 2200;
@@ -496,7 +510,7 @@ var TikTokDriver = class extends BaseDriver {
496
510
  var DiscordDriver = class extends BaseDriver {
497
511
  platform = "discord";
498
512
  label = "Discord";
499
- icon = "\u{1F4AC}";
513
+ icon = "DS";
500
514
  postizProvider = "discord";
501
515
  getMaxLength() {
502
516
  return 2e3;
@@ -533,7 +547,7 @@ var DiscordDriver = class extends BaseDriver {
533
547
  var TelegramDriver = class extends BaseDriver {
534
548
  platform = "telegram";
535
549
  label = "Telegram";
536
- icon = "\u2708\uFE0F";
550
+ icon = "TG";
537
551
  postizProvider = "telegram";
538
552
  getMaxLength() {
539
553
  return 4096;
@@ -0,0 +1,13 @@
1
+ {
2
+ "version": "5",
3
+ "dialect": "sqlite",
4
+ "entries": [
5
+ {
6
+ "idx": 0,
7
+ "version": "5",
8
+ "when": 1743811200000,
9
+ "tag": "0001_initial",
10
+ "breakpoints": true
11
+ }
12
+ ]
13
+ }
package/dist/index.js CHANGED
@@ -204,7 +204,20 @@ function initializeDatabase(teamId) {
204
204
  const migrationsDir = (0, import_path.join)(PLUGIN_ROOT, "db", "migrations");
205
205
  (0, import_migrator.migrate)(db, { migrationsFolder: migrationsDir });
206
206
  } catch (error) {
207
- console.warn("Migration warning:", error?.message);
207
+ try {
208
+ const sqlPath = (0, import_path.join)(PLUGIN_ROOT, "db", "migrations", "0001_initial.sql");
209
+ if ((0, import_fs.existsSync)(sqlPath)) {
210
+ const sql2 = require("fs").readFileSync(sqlPath, "utf8");
211
+ const statements = sql2.split(";").map((s) => s.trim()).filter((s) => s.length > 0);
212
+ for (const stmt of statements) {
213
+ try {
214
+ sqlite.exec(stmt + ";");
215
+ } catch {
216
+ }
217
+ }
218
+ }
219
+ } catch {
220
+ }
208
221
  }
209
222
  return { db, sqlite };
210
223
  }
@@ -185,9 +185,9 @@
185
185
  background: "var(--ck-bg-base, #0b0c10)",
186
186
  border: "1px solid var(--ck-border-subtle)",
187
187
  borderRadius: "14px",
188
- width: "95vw",
189
- maxWidth: "900px",
190
- maxHeight: "90vh",
188
+ width: "96vw",
189
+ maxWidth: "1200px",
190
+ maxHeight: "92vh",
191
191
  overflow: "auto",
192
192
  display: "flex",
193
193
  flexDirection: "column"
@@ -201,7 +201,7 @@
201
201
  },
202
202
  modalBody: { display: "flex", flex: 1, minHeight: 0 },
203
203
  modalLeft: { flex: 1, padding: "1rem 1.25rem", borderRight: "1px solid var(--ck-border-subtle)", display: "flex", flexDirection: "column", gap: "0.75rem" },
204
- modalRight: { width: "280px", padding: "1rem 1.25rem", flexShrink: 0 },
204
+ modalRight: { width: "380px", padding: "1rem 1.25rem", flexShrink: 0 },
205
205
  modalFooter: {
206
206
  display: "flex",
207
207
  alignItems: "center",
@@ -230,7 +230,11 @@
230
230
  resize: "vertical",
231
231
  fontFamily: "inherit",
232
232
  fontSize: "0.9rem",
233
- outline: "none"
233
+ outline: "none",
234
+ // Hard-force LTR to avoid any inherited RTL / bidi overrides in host app
235
+ direction: "ltr",
236
+ unicodeBidi: "plaintext",
237
+ textAlign: "left"
234
238
  },
235
239
  input: {
236
240
  background: "rgba(255,255,255,0.03)",
@@ -342,6 +346,11 @@
342
346
  const [modalContent, setModalContent] = useState("");
343
347
  const [modalPlatforms, setModalPlatforms] = useState([]);
344
348
  const [modalMediaUrl, setModalMediaUrl] = useState("");
349
+ const [modalShowMedia, setModalShowMedia] = useState(false);
350
+ const [modalUploading, setModalUploading] = useState(false);
351
+ const [modalMediaLibrary, setModalMediaLibrary] = useState([]);
352
+ const [modalSelectedMediaIds, setModalSelectedMediaIds] = useState([]);
353
+ const modalFileInputRef = useRef(null);
345
354
  const [modalSaving, setModalSaving] = useState(false);
346
355
  const [modalPublishing, setModalPublishing] = useState(false);
347
356
  const [modalError, setModalError] = useState(null);
@@ -374,6 +383,51 @@
374
383
  } catch {
375
384
  }
376
385
  }, [teamId, postizHeaders]);
386
+ const loadMedia = useCallback(async () => {
387
+ try {
388
+ const res = await fetch(`${apiBase}/media?team=${encodeURIComponent(teamId)}&limit=200`);
389
+ const json = await res.json();
390
+ setModalMediaLibrary(Array.isArray(json.data) ? json.data : []);
391
+ } catch {
392
+ }
393
+ }, [teamId]);
394
+ const handleModalFileUpload = useCallback(async (files) => {
395
+ if (!files || files.length === 0) return;
396
+ setModalUploading(true);
397
+ setModalError(null);
398
+ try {
399
+ for (const file of Array.from(files)) {
400
+ const base64 = await new Promise((resolve, reject) => {
401
+ const reader = new FileReader();
402
+ reader.onload = () => resolve(reader.result);
403
+ reader.onerror = reject;
404
+ reader.readAsDataURL(file);
405
+ });
406
+ const up = await fetch(`${apiBase}/media?team=${encodeURIComponent(teamId)}`, {
407
+ method: "POST",
408
+ headers: { "content-type": "application/json" },
409
+ body: JSON.stringify({ data: base64, filename: file.name, mimeType: file.type })
410
+ });
411
+ if (!up.ok) {
412
+ const err = await up.json().catch(() => ({}));
413
+ throw new Error(err?.message || `Upload failed (${up.status})`);
414
+ }
415
+ const item = await up.json().catch(() => null);
416
+ if (item?.id) {
417
+ setModalSelectedMediaIds((prev) => prev.includes(item.id) ? prev : [...prev, item.id]);
418
+ }
419
+ }
420
+ await loadMedia();
421
+ } catch (e) {
422
+ setModalError(e?.message || "Upload failed");
423
+ } finally {
424
+ setModalUploading(false);
425
+ if (modalFileInputRef.current) modalFileInputRef.current.value = "";
426
+ }
427
+ }, [teamId, loadMedia]);
428
+ const toggleModalMedia = (id) => {
429
+ setModalSelectedMediaIds((prev) => prev.includes(id) ? prev.filter((x) => x !== id) : [...prev, id]);
430
+ };
377
431
  useEffect(() => {
378
432
  setLoading(true);
379
433
  Promise.all([loadPosts(), loadDrivers()]).finally(() => setLoading(false));
@@ -393,6 +447,9 @@
393
447
  setModalContent("");
394
448
  setModalPlatforms([]);
395
449
  setModalMediaUrl("");
450
+ setModalShowMedia(false);
451
+ setModalSelectedMediaIds([]);
452
+ setModalMediaLibrary([]);
396
453
  setModalError(null);
397
454
  setModalSuccess(null);
398
455
  setModalOpen(true);
@@ -423,7 +480,8 @@
423
480
  content: modalContent,
424
481
  platforms: modalPlatforms.length > 0 ? modalPlatforms : ["draft"],
425
482
  status: modalDate ? "scheduled" : "draft",
426
- scheduledAt: modalDate || void 0
483
+ scheduledAt: modalDate || void 0,
484
+ mediaIds: modalSelectedMediaIds
427
485
  })
428
486
  });
429
487
  if (!res.ok) throw new Error(`Save failed (${res.status})`);
@@ -451,6 +509,7 @@
451
509
  content: modalContent,
452
510
  platforms: modalPlatforms,
453
511
  scheduledAt: modalDate || void 0,
512
+ // NOTE: Postiz expects publicly reachable URLs; uploaded library media is local-only for now.
454
513
  mediaUrls: modalMediaUrl ? [modalMediaUrl] : void 0
455
514
  })
456
515
  });
@@ -468,7 +527,8 @@
468
527
  content: modalContent,
469
528
  platforms: modalPlatforms,
470
529
  status: modalDate ? "scheduled" : "published",
471
- scheduledAt: modalDate || void 0
530
+ scheduledAt: modalDate || void 0,
531
+ mediaIds: modalSelectedMediaIds
472
532
  })
473
533
  }).catch(() => {
474
534
  });
@@ -793,6 +853,7 @@
793
853
  // Textarea
794
854
  h("textarea", {
795
855
  style: s.textarea,
856
+ dir: "ltr",
796
857
  value: modalContent,
797
858
  onChange: (e) => setModalContent(e.target.value),
798
859
  placeholder: "Write something \u2026",
@@ -803,8 +864,13 @@
803
864
  "div",
804
865
  { style: { display: "flex", gap: "0.5rem", alignItems: "center", flexWrap: "wrap" } },
805
866
  h("button", {
867
+ type: "button",
806
868
  style: { ...s.btnGhost, padding: "0.3rem 0.6rem", fontSize: "0.75rem" },
807
- onClick: () => setModalMediaUrl(modalMediaUrl ? "" : " ")
869
+ onClick: async () => {
870
+ const next = !modalShowMedia;
871
+ setModalShowMedia(next);
872
+ if (next) await loadMedia();
873
+ }
808
874
  }, "\u{1F5BC} Insert Media"),
809
875
  charLimit && h("span", {
810
876
  style: {
@@ -814,21 +880,283 @@
814
880
  }
815
881
  }, `${modalContent.length}/${charLimit}`)
816
882
  ),
817
- // Media URL input
818
- modalMediaUrl !== "" && h("input", {
819
- style: s.input,
820
- type: "url",
821
- value: modalMediaUrl.trim(),
822
- onChange: (e) => setModalMediaUrl(e.target.value),
823
- placeholder: "Paste image or video URL\u2026"
824
- })
883
+ // Media panel (upload + library + URL)
884
+ modalShowMedia && h(
885
+ "div",
886
+ {
887
+ style: {
888
+ background: "rgba(255,255,255,0.02)",
889
+ border: "1px solid var(--ck-border-subtle)",
890
+ borderRadius: "10px",
891
+ padding: "0.75rem"
892
+ }
893
+ },
894
+ h(
895
+ "div",
896
+ { style: { display: "flex", gap: "0.5rem", alignItems: "center", marginBottom: "0.5rem", flexWrap: "wrap" } },
897
+ h("input", {
898
+ ref: modalFileInputRef,
899
+ type: "file",
900
+ accept: "image/*,video/*",
901
+ multiple: true,
902
+ style: { display: "none" },
903
+ onChange: (e) => void handleModalFileUpload(e.target.files)
904
+ }),
905
+ h("button", {
906
+ type: "button",
907
+ style: { ...s.btnGhost, padding: "0.35rem 0.6rem", fontSize: "0.75rem", opacity: modalUploading ? 0.7 : 1 },
908
+ onClick: () => modalFileInputRef.current?.click(),
909
+ disabled: modalUploading
910
+ }, modalUploading ? "\u23F3 Uploading\u2026" : "\u{1F4C1} Upload"),
911
+ h("button", {
912
+ type: "button",
913
+ style: { ...s.btnGhost, padding: "0.35rem 0.6rem", fontSize: "0.75rem" },
914
+ onClick: () => setModalShowMedia(false)
915
+ }, "Done")
916
+ ),
917
+ h("input", {
918
+ style: s.input,
919
+ type: "url",
920
+ value: modalMediaUrl,
921
+ onChange: (e) => setModalMediaUrl(e.target.value),
922
+ placeholder: "Paste a public image/video URL (needed for Postiz)\u2026"
923
+ }),
924
+ // Selected media strip
925
+ modalSelectedMediaIds.length > 0 && h(
926
+ "div",
927
+ { style: { display: "flex", flexWrap: "wrap", gap: "0.5rem", marginTop: "0.65rem" } },
928
+ ...modalSelectedMediaIds.map((id) => {
929
+ const item = modalMediaLibrary.find((m) => m.id === id);
930
+ if (!item) return null;
931
+ return h(
932
+ "div",
933
+ {
934
+ key: id,
935
+ style: {
936
+ position: "relative",
937
+ width: "64px",
938
+ height: "64px",
939
+ borderRadius: "8px",
940
+ overflow: "hidden",
941
+ border: "2px solid rgba(127,90,240,0.55)"
942
+ }
943
+ },
944
+ item.mimeType?.startsWith("video/") ? h("div", {
945
+ style: { width: "100%", height: "100%", background: "rgba(0,0,0,0.35)", display: "flex", alignItems: "center", justifyContent: "center", color: "white" }
946
+ }, "\u{1F3A5}") : h("img", { src: item.thumbnailDataUrl, style: { width: "100%", height: "100%", objectFit: "cover" } }),
947
+ h("button", {
948
+ type: "button",
949
+ onClick: () => toggleModalMedia(id),
950
+ style: {
951
+ position: "absolute",
952
+ top: "2px",
953
+ right: "2px",
954
+ background: "rgba(0,0,0,0.6)",
955
+ border: "none",
956
+ borderRadius: "50%",
957
+ width: "18px",
958
+ height: "18px",
959
+ color: "white",
960
+ fontSize: "0.65rem",
961
+ cursor: "pointer",
962
+ display: "flex",
963
+ alignItems: "center",
964
+ justifyContent: "center"
965
+ }
966
+ }, "\u2715")
967
+ );
968
+ })
969
+ ),
970
+ // Library grid
971
+ h(
972
+ "div",
973
+ { style: { marginTop: "0.65rem" } },
974
+ h("div", { style: { fontSize: "0.75rem", fontWeight: 600, color: "var(--ck-text-secondary)", marginBottom: "0.4rem" } }, "Media Library"),
975
+ modalMediaLibrary.length === 0 ? h("div", { style: { fontSize: "0.75rem", color: "var(--ck-text-tertiary)", padding: "0.5rem 0" } }, "No media yet \u2014 upload something.") : h(
976
+ "div",
977
+ {
978
+ style: {
979
+ display: "grid",
980
+ gridTemplateColumns: "repeat(auto-fill, minmax(86px, 1fr))",
981
+ gap: "0.5rem",
982
+ maxHeight: "220px",
983
+ overflowY: "auto",
984
+ paddingRight: "4px"
985
+ }
986
+ },
987
+ ...modalMediaLibrary.map((item) => {
988
+ const selected = modalSelectedMediaIds.includes(item.id);
989
+ const thumb = item.thumbnailDataUrl;
990
+ return h(
991
+ "div",
992
+ {
993
+ key: item.id,
994
+ onClick: () => toggleModalMedia(item.id),
995
+ style: {
996
+ position: "relative",
997
+ width: "100%",
998
+ paddingTop: "100%",
999
+ borderRadius: "10px",
1000
+ overflow: "hidden",
1001
+ cursor: "pointer",
1002
+ border: selected ? "2px solid rgba(127,90,240,0.75)" : "1px solid var(--ck-border-subtle)",
1003
+ boxShadow: selected ? "0 0 10px rgba(127,90,240,0.25)" : "none",
1004
+ background: "rgba(0,0,0,0.25)"
1005
+ }
1006
+ },
1007
+ item.mimeType?.startsWith("video/") ? h("div", {
1008
+ style: { position: "absolute", inset: 0, display: "flex", alignItems: "center", justifyContent: "center", color: "white", fontSize: "1.4rem" }
1009
+ }, "\u{1F3A5}") : h("img", {
1010
+ src: thumb,
1011
+ style: { position: "absolute", inset: 0, width: "100%", height: "100%", objectFit: "cover" }
1012
+ }),
1013
+ selected && h("div", {
1014
+ style: {
1015
+ position: "absolute",
1016
+ top: "6px",
1017
+ right: "6px",
1018
+ width: "20px",
1019
+ height: "20px",
1020
+ borderRadius: "50%",
1021
+ background: "rgba(127,90,240,0.9)",
1022
+ display: "flex",
1023
+ alignItems: "center",
1024
+ justifyContent: "center",
1025
+ color: "white",
1026
+ fontSize: "0.75rem",
1027
+ fontWeight: 800
1028
+ }
1029
+ }, "\u2713")
1030
+ );
1031
+ })
1032
+ )
1033
+ )
1034
+ )
825
1035
  ),
826
- // Right — preview
1036
+ // Right — social-post-style preview
827
1037
  h(
828
1038
  "div",
829
1039
  { style: s.modalRight },
830
- h("div", { style: { fontWeight: 600, fontSize: "0.9rem", color: "var(--ck-text-primary)", marginBottom: "0.5rem" } }, "Post Preview"),
831
- modalContent.trim() ? h("div", { style: { ...s.previewPanel, whiteSpace: "pre-wrap", fontSize: "0.85rem", color: "var(--ck-text-secondary)" } }, modalContent) : h("div", { style: { color: "var(--ck-text-tertiary)", fontSize: "0.85rem" } }, "Start writing your post for a preview")
1040
+ h("div", { style: { fontWeight: 600, fontSize: "0.85rem", color: "var(--ck-text-secondary)", marginBottom: "0.75rem" } }, "Post Preview"),
1041
+ h(
1042
+ "div",
1043
+ {
1044
+ style: {
1045
+ background: "rgba(22,22,28,0.95)",
1046
+ borderRadius: "12px",
1047
+ border: "1px solid rgba(255,255,255,0.08)",
1048
+ overflow: "hidden"
1049
+ }
1050
+ },
1051
+ // Header
1052
+ h(
1053
+ "div",
1054
+ { style: { display: "flex", alignItems: "center", gap: "0.65rem", padding: "0.85rem 1rem 0" } },
1055
+ h("div", {
1056
+ style: {
1057
+ width: "40px",
1058
+ height: "40px",
1059
+ borderRadius: "50%",
1060
+ background: "rgba(127,90,240,0.25)",
1061
+ display: "flex",
1062
+ alignItems: "center",
1063
+ justifyContent: "center",
1064
+ fontSize: "1.1rem",
1065
+ color: "rgba(127,90,240,0.9)",
1066
+ flexShrink: 0
1067
+ }
1068
+ }, "\u{1F464}"),
1069
+ h(
1070
+ "div",
1071
+ null,
1072
+ h(
1073
+ "div",
1074
+ { style: { display: "flex", alignItems: "center", gap: "0.3rem" } },
1075
+ h("span", { style: { fontWeight: 700, fontSize: "0.9rem", color: "var(--ck-text-primary)" } }, "Your Brand"),
1076
+ h("span", { style: { color: "rgba(99,179,237,0.9)", fontSize: "0.85rem" } }, "\u2713")
1077
+ ),
1078
+ h(
1079
+ "div",
1080
+ { style: { fontSize: "0.75rem", color: "var(--ck-text-tertiary)" } },
1081
+ modalDate ? new Date(modalDate).toLocaleDateString(void 0, { month: "short", day: "numeric", hour: "2-digit", minute: "2-digit" }) : "Just now"
1082
+ )
1083
+ )
1084
+ ),
1085
+ // Body
1086
+ h(
1087
+ "div",
1088
+ { style: { padding: "0.65rem 1rem 0.75rem" } },
1089
+ modalContent.trim() ? h("div", {
1090
+ style: {
1091
+ whiteSpace: "pre-wrap",
1092
+ fontSize: "0.9rem",
1093
+ color: "var(--ck-text-primary)",
1094
+ lineHeight: "1.5",
1095
+ maxHeight: "300px",
1096
+ overflowY: "auto",
1097
+ wordBreak: "break-word"
1098
+ }
1099
+ }, modalContent) : h("div", {
1100
+ style: { color: "var(--ck-text-tertiary)", fontSize: "0.85rem", fontStyle: "italic", padding: "1.5rem 0", textAlign: "center" }
1101
+ }, "Start writing to see a preview")
1102
+ ),
1103
+ // Media preview (selected library media first, then URL)
1104
+ (modalSelectedMediaIds.length > 0 || modalMediaUrl) && h(
1105
+ "div",
1106
+ null,
1107
+ ...modalSelectedMediaIds.slice(0, 1).map((id) => {
1108
+ const item = modalMediaLibrary.find((m) => m.id === id);
1109
+ if (!item) return null;
1110
+ return item.mimeType?.startsWith("video/") ? h("div", {
1111
+ key: id,
1112
+ style: { background: "rgba(0,0,0,0.4)", padding: "1.25rem", textAlign: "center", color: "var(--ck-text-secondary)" }
1113
+ }, "\u{1F3A5} Video") : h("img", { key: id, src: item.thumbnailDataUrl, style: { width: "100%", display: "block" } });
1114
+ }),
1115
+ modalMediaUrl && h("img", {
1116
+ src: modalMediaUrl,
1117
+ style: { width: "100%", display: "block" },
1118
+ onError: (e) => {
1119
+ e.target.style.display = "none";
1120
+ }
1121
+ })
1122
+ ),
1123
+ // Engagement bar
1124
+ h(
1125
+ "div",
1126
+ {
1127
+ style: {
1128
+ display: "flex",
1129
+ justifyContent: "space-around",
1130
+ padding: "0.6rem 1rem",
1131
+ borderTop: "1px solid rgba(255,255,255,0.06)",
1132
+ fontSize: "0.8rem",
1133
+ color: "var(--ck-text-tertiary)"
1134
+ }
1135
+ },
1136
+ h("span", null, "\u2764\uFE0F 0"),
1137
+ h("span", null, "\u{1F4AC} 0"),
1138
+ h("span", null, "\u{1F501} 0"),
1139
+ h("span", null, "\u{1F4CA} 0")
1140
+ )
1141
+ ),
1142
+ // Platform pills
1143
+ modalPlatforms.length > 0 && h(
1144
+ "div",
1145
+ {
1146
+ style: { display: "flex", flexWrap: "wrap", gap: "0.35rem", marginTop: "0.65rem" }
1147
+ },
1148
+ ...modalPlatforms.map((pl) => h("span", {
1149
+ key: pl,
1150
+ style: {
1151
+ background: "rgba(127,90,240,0.12)",
1152
+ border: "1px solid rgba(127,90,240,0.25)",
1153
+ borderRadius: "999px",
1154
+ padding: "0.1rem 0.4rem",
1155
+ fontSize: "0.7rem",
1156
+ color: "var(--ck-text-secondary)"
1157
+ }
1158
+ }, pl))
1159
+ )
832
1160
  )
833
1161
  ),
834
1162
  // Footer
@@ -683,118 +683,181 @@
683
683
  error && h("div", { className: "text-xs", style: { color: "rgba(248,113,113,0.95)" } }, error),
684
684
  success && h("div", { className: "text-xs", style: { color: "rgba(74,222,128,0.9)" } }, success)
685
685
  ),
686
- // RIGHT — live preview pane
686
+ // RIGHT — social-post-style preview
687
687
  h(
688
688
  "div",
689
689
  {
690
690
  style: {
691
- width: "320px",
691
+ width: "380px",
692
692
  flexShrink: 0,
693
- background: "rgba(255,255,255,0.02)",
693
+ background: "rgba(0,0,0,0.25)",
694
694
  border: "1px solid var(--ck-border-subtle)",
695
- borderRadius: "10px",
696
- padding: "1rem",
695
+ borderRadius: "16px",
696
+ padding: "1.25rem",
697
697
  display: "flex",
698
698
  flexDirection: "column",
699
699
  alignSelf: "flex-start"
700
700
  }
701
701
  },
702
- h("div", { className: "text-sm font-medium mb-3", style: t.text }, "Post Preview"),
703
- // Selected platforms
702
+ h("div", {
703
+ style: { fontSize: "0.85rem", fontWeight: 600, color: "var(--ck-text-secondary)", marginBottom: "1rem" }
704
+ }, "Post Preview"),
705
+ // Social post card
706
+ h(
707
+ "div",
708
+ {
709
+ style: {
710
+ background: "rgba(22,22,28,0.95)",
711
+ borderRadius: "12px",
712
+ border: "1px solid rgba(255,255,255,0.08)",
713
+ overflow: "hidden"
714
+ }
715
+ },
716
+ // Post header (avatar + name + handle)
717
+ h(
718
+ "div",
719
+ {
720
+ style: {
721
+ display: "flex",
722
+ alignItems: "center",
723
+ gap: "0.65rem",
724
+ padding: "0.85rem 1rem 0"
725
+ }
726
+ },
727
+ // Avatar circle
728
+ h("div", {
729
+ style: {
730
+ width: "40px",
731
+ height: "40px",
732
+ borderRadius: "50%",
733
+ background: "rgba(127,90,240,0.25)",
734
+ display: "flex",
735
+ alignItems: "center",
736
+ justifyContent: "center",
737
+ fontSize: "1.1rem",
738
+ color: "rgba(127,90,240,0.9)",
739
+ flexShrink: 0
740
+ }
741
+ }, "\u{1F464}"),
742
+ h(
743
+ "div",
744
+ null,
745
+ h(
746
+ "div",
747
+ { style: { display: "flex", alignItems: "center", gap: "0.3rem" } },
748
+ h("span", {
749
+ style: { fontWeight: 700, fontSize: "0.9rem", color: "var(--ck-text-primary)" }
750
+ }, "Your Brand"),
751
+ h("span", { style: { color: "rgba(99,179,237,0.9)", fontSize: "0.85rem" } }, "\u2713")
752
+ ),
753
+ h("div", {
754
+ style: { fontSize: "0.75rem", color: "var(--ck-text-tertiary)" }
755
+ }, scheduledAt ? `Scheduled \xB7 ${new Date(scheduledAt).toLocaleDateString(void 0, { month: "short", day: "numeric" })}` : "Just now")
756
+ )
757
+ ),
758
+ // Post body
759
+ h(
760
+ "div",
761
+ { style: { padding: "0.65rem 1rem 0.75rem" } },
762
+ content.trim() ? h("div", {
763
+ style: {
764
+ whiteSpace: "pre-wrap",
765
+ fontSize: "0.9rem",
766
+ color: "var(--ck-text-primary)",
767
+ lineHeight: "1.5",
768
+ maxHeight: "260px",
769
+ overflowY: "auto",
770
+ wordBreak: "break-word"
771
+ }
772
+ }, content) : h("div", {
773
+ style: {
774
+ color: "var(--ck-text-tertiary)",
775
+ fontSize: "0.85rem",
776
+ fontStyle: "italic",
777
+ padding: "1.5rem 0",
778
+ textAlign: "center"
779
+ }
780
+ }, "Start writing to see a preview")
781
+ ),
782
+ // Media preview
783
+ (selectedMediaIds.length > 0 || mediaUrl && showMedia) && h(
784
+ "div",
785
+ {
786
+ style: { padding: "0 0 0" }
787
+ },
788
+ ...selectedMediaIds.map((id) => {
789
+ const item = mediaLibrary.find((m) => m.id === id);
790
+ if (!item) return null;
791
+ return item.mimeType?.startsWith("video/") ? h("div", {
792
+ key: id,
793
+ style: {
794
+ background: "rgba(0,0,0,0.4)",
795
+ padding: "1.5rem",
796
+ textAlign: "center",
797
+ color: "var(--ck-text-secondary)",
798
+ fontSize: "0.85rem"
799
+ }
800
+ }, `\u{1F3A5} ${item.filename}`) : h("img", {
801
+ key: id,
802
+ src: item.thumbnailDataUrl || item.url,
803
+ style: { width: "100%", display: "block" }
804
+ });
805
+ }),
806
+ mediaUrl && showMedia && h("img", {
807
+ src: mediaUrl,
808
+ style: { width: "100%", display: "block" },
809
+ onError: (e) => {
810
+ e.target.style.display = "none";
811
+ }
812
+ })
813
+ ),
814
+ // Engagement bar (fake social actions)
815
+ h(
816
+ "div",
817
+ {
818
+ style: {
819
+ display: "flex",
820
+ justifyContent: "space-around",
821
+ padding: "0.6rem 1rem",
822
+ borderTop: "1px solid rgba(255,255,255,0.06)",
823
+ fontSize: "0.8rem",
824
+ color: "var(--ck-text-tertiary)"
825
+ }
826
+ },
827
+ h("span", null, "\u2764\uFE0F 0"),
828
+ h("span", null, "\u{1F4AC} 0"),
829
+ h("span", null, "\u{1F501} 0"),
830
+ h("span", null, "\u{1F4CA} 0")
831
+ )
832
+ ),
833
+ // Platform pills below card
704
834
  selectedPlatforms.length > 0 && h(
705
835
  "div",
706
- { className: "flex flex-wrap gap-1 mb-3" },
836
+ {
837
+ style: { display: "flex", flexWrap: "wrap", gap: "0.35rem", marginTop: "0.75rem" }
838
+ },
707
839
  ...selectedPlatforms.map((pl) => {
708
840
  const drv = drivers.find((d) => d.platform === pl);
709
841
  return h("span", {
710
842
  key: pl,
711
843
  style: {
712
- background: "rgba(127,90,240,0.15)",
713
- border: "1px solid rgba(127,90,240,0.3)",
844
+ background: "rgba(127,90,240,0.12)",
845
+ border: "1px solid rgba(127,90,240,0.25)",
714
846
  borderRadius: "999px",
715
- padding: "0.12rem 0.45rem",
716
- fontSize: "0.72rem",
847
+ padding: "0.1rem 0.4rem",
848
+ fontSize: "0.7rem",
717
849
  color: "var(--ck-text-secondary)"
718
850
  }
719
851
  }, drv ? `${drv.icon} ${drv.label}` : pl);
720
852
  })
721
853
  ),
722
- // Scheduling info
723
- scheduledAt && h("div", {
724
- className: "text-xs mb-3",
725
- style: { color: "rgba(251,191,36,0.85)" }
726
- }, `\u23F1 Scheduled: ${new Date(scheduledAt).toLocaleString()}`),
727
- // Content preview
728
- content.trim() ? h("div", {
729
- style: {
730
- background: "rgba(255,255,255,0.03)",
731
- border: "1px solid var(--ck-border-subtle)",
732
- borderRadius: "10px",
733
- padding: "0.85rem",
734
- whiteSpace: "pre-wrap",
735
- fontSize: "0.85rem",
736
- color: "var(--ck-text-primary)",
737
- lineHeight: "1.55",
738
- maxHeight: "300px",
739
- overflowY: "auto",
740
- wordBreak: "break-word"
741
- }
742
- }, content) : h("div", {
743
- style: {
744
- color: "var(--ck-text-tertiary)",
745
- fontSize: "0.85rem",
746
- fontStyle: "italic",
747
- padding: "2rem 0.5rem",
748
- textAlign: "center"
749
- }
750
- }, "Start writing to see a preview"),
751
- // Media preview (selected library items + URL)
752
- (selectedMediaIds.length > 0 || mediaUrl && showMedia) && h(
753
- "div",
754
- { className: "mt-3 space-y-2" },
755
- ...selectedMediaIds.map((id) => {
756
- const item = mediaLibrary.find((m) => m.id === id);
757
- if (!item) return null;
758
- return item.mimeType?.startsWith("video/") ? h("div", {
759
- key: id,
760
- style: {
761
- background: "rgba(0,0,0,0.3)",
762
- borderRadius: "8px",
763
- border: "1px solid var(--ck-border-subtle)",
764
- padding: "1rem",
765
- textAlign: "center",
766
- color: "var(--ck-text-secondary)",
767
- fontSize: "0.8rem"
768
- }
769
- }, `\u{1F3A5} ${item.filename}`) : h("img", {
770
- key: id,
771
- src: item.thumbnailDataUrl || item.url,
772
- style: {
773
- maxWidth: "100%",
774
- borderRadius: "8px",
775
- border: "1px solid var(--ck-border-subtle)"
776
- }
777
- });
778
- }),
779
- mediaUrl && showMedia && h("img", {
780
- src: mediaUrl,
781
- style: {
782
- maxWidth: "100%",
783
- borderRadius: "8px",
784
- border: "1px solid var(--ck-border-subtle)"
785
- },
786
- onError: (e) => {
787
- e.target.style.display = "none";
788
- }
789
- })
790
- ),
791
854
  // Character limit bar
792
855
  charLimit && content.length > 0 && h(
793
856
  "div",
794
- { className: "mt-3" },
857
+ { style: { marginTop: "0.75rem" } },
795
858
  h(
796
859
  "div",
797
- { style: { height: "4px", borderRadius: "2px", background: "rgba(255,255,255,0.06)", overflow: "hidden" } },
860
+ { style: { height: "3px", borderRadius: "2px", background: "rgba(255,255,255,0.06)", overflow: "hidden" } },
798
861
  h("div", {
799
862
  style: {
800
863
  height: "100%",
@@ -806,10 +869,11 @@
806
869
  })
807
870
  ),
808
871
  h("div", {
809
- className: "text-xs mt-1",
810
872
  style: {
811
- color: content.length > charLimit ? "rgba(248,113,113,0.9)" : "var(--ck-text-tertiary)",
812
- textAlign: "right"
873
+ fontSize: "0.7rem",
874
+ marginTop: "0.2rem",
875
+ textAlign: "right",
876
+ color: content.length > charLimit ? "rgba(248,113,113,0.9)" : "var(--ck-text-tertiary)"
813
877
  }
814
878
  }, `${content.length} / ${charLimit}`)
815
879
  )
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jiggai/kitchen-plugin-marketing",
3
- "version": "0.5.0",
3
+ "version": "0.5.2",
4
4
  "description": "Marketing Suite plugin for ClawKitchen",
5
5
  "main": "dist/index.js",
6
6
  "files": [