veo-sdk 0.5.3 → 0.5.5

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.cjs CHANGED
@@ -506,7 +506,15 @@ function buildStepContent(step, doc, callbacks) {
506
506
  function buildContentNodes(step, doc) {
507
507
  const blocks = normalizeBlocks(step);
508
508
  if (blocks) {
509
- return blocks.filter((b) => b.type !== "button").map((b) => buildContentBlock(b, doc)).filter((n) => n !== null);
509
+ const nodes2 = [];
510
+ for (const { block, idx } of blocks) {
511
+ if (block.type === "button") continue;
512
+ const node = buildContentBlock(block, doc);
513
+ if (!node) continue;
514
+ node.dataset.veoIdx = String(idx);
515
+ nodes2.push(node);
516
+ }
517
+ return nodes2;
510
518
  }
511
519
  const nodes = [];
512
520
  if (typeof step.imageUrl === "string" && step.imageUrl && isSafeUrl(step.imageUrl)) {
@@ -568,7 +576,8 @@ function renderLegacyStep(container, step, doc, callbacks) {
568
576
  }
569
577
  function normalizeBlocks(step) {
570
578
  if (!Array.isArray(step.blocks) || step.blocks.length === 0) return null;
571
- const valid = step.blocks.filter((b) => {
579
+ const valid = step.blocks.map((block, idx) => ({ block, idx })).filter((entry) => {
580
+ const b = entry.block;
572
581
  if (!b || typeof b !== "object") return false;
573
582
  if (b.type === "image") return typeof b.url === "string" && isSafeUrl(b.url);
574
583
  return b.type === "title" || b.type === "text" || b.type === "button";
@@ -578,13 +587,14 @@ function normalizeBlocks(step) {
578
587
  function renderBlocks(container, blocks, doc, callbacks) {
579
588
  let i = 0;
580
589
  while (i < blocks.length) {
581
- const block = blocks[i];
582
- if (block?.type === "button") {
590
+ const entry = blocks[i];
591
+ if (entry?.block.type === "button") {
583
592
  const actions = doc.createElement("div");
584
593
  actions.className = "veo-guide-actions";
594
+ actions.dataset.veoIdx = String(entry.idx);
585
595
  let rowAlign;
586
- while (i < blocks.length && blocks[i]?.type === "button") {
587
- const btnBlock = blocks[i];
596
+ while (i < blocks.length && blocks[i]?.block.type === "button") {
597
+ const btnBlock = blocks[i].block;
588
598
  if (!rowAlign) {
589
599
  const a = btnBlock.style?.align;
590
600
  if (a === "left" || a === "center" || a === "right") rowAlign = a;
@@ -596,8 +606,11 @@ function renderBlocks(container, blocks, doc, callbacks) {
596
606
  container.appendChild(actions);
597
607
  continue;
598
608
  }
599
- const node = buildContentBlock(block, doc);
600
- if (node) container.appendChild(node);
609
+ const node = entry ? buildContentBlock(entry.block, doc) : null;
610
+ if (node && entry) {
611
+ node.dataset.veoIdx = String(entry.idx);
612
+ container.appendChild(node);
613
+ }
601
614
  i++;
602
615
  }
603
616
  }
@@ -3051,6 +3064,117 @@ var init_guide_preview = __esm({
3051
3064
  }
3052
3065
  });
3053
3066
 
3067
+ // src/plugins/builder/block-drop-target.ts
3068
+ function attachBlockDropTarget(options) {
3069
+ const { host, stepIndex, onDrop } = options;
3070
+ const doc = host.ownerDocument;
3071
+ let line = null;
3072
+ let spot = null;
3073
+ const contentEl = () => host.shadowRoot?.querySelector(".veo-guide-content") ?? null;
3074
+ const blockChildren = (container) => Array.from(container.children).filter(
3075
+ (el) => el instanceof HTMLElement && el.dataset.veoIdx !== void 0
3076
+ );
3077
+ const hideLine = () => {
3078
+ line?.remove();
3079
+ line = null;
3080
+ spot = null;
3081
+ };
3082
+ const showLine = (at) => {
3083
+ if (!line) {
3084
+ line = doc.createElement("div");
3085
+ line.style.cssText = "position:fixed;height:3px;border-radius:2px;background:#FF5B35;box-shadow:0 0 0 1px rgba(255,255,255,0.65);pointer-events:none;z-index:2147483647;";
3086
+ host.shadowRoot?.appendChild(line);
3087
+ }
3088
+ line.style.left = `${at.rect.left + 4}px`;
3089
+ line.style.width = `${Math.max(0, at.rect.width - 8)}px`;
3090
+ line.style.top = `${at.y - 1.5}px`;
3091
+ };
3092
+ const isBlockDrag = (event) => {
3093
+ const types = event.dataTransfer?.types;
3094
+ return !!types && Array.from(types).includes(VEO_BLOCK_MIME);
3095
+ };
3096
+ const NEAR_PX = 48;
3097
+ const locate = (clientY) => {
3098
+ const container = contentEl();
3099
+ if (!container) return null;
3100
+ const rect = container.getBoundingClientRect();
3101
+ const kids = blockChildren(container);
3102
+ let beforeIndex = null;
3103
+ let y = kids.length === 0 ? rect.top + rect.height / 2 : 0;
3104
+ for (const kid of kids) {
3105
+ const r = kid.getBoundingClientRect();
3106
+ if (clientY < r.top + r.height / 2) {
3107
+ const idx = Number(kid.dataset.veoIdx);
3108
+ beforeIndex = Number.isFinite(idx) ? idx : null;
3109
+ y = r.top;
3110
+ break;
3111
+ }
3112
+ y = r.bottom;
3113
+ }
3114
+ return { beforeIndex, y, rect };
3115
+ };
3116
+ const overContent = (x, y, rect) => x >= rect.left - NEAR_PX && x <= rect.right + NEAR_PX && y >= rect.top - NEAR_PX && y <= rect.bottom + NEAR_PX;
3117
+ const hoverAt = (x, y) => {
3118
+ const at = locate(y);
3119
+ if (!at || !overContent(x, y, at.rect)) {
3120
+ hideLine();
3121
+ return false;
3122
+ }
3123
+ spot = at;
3124
+ showLine(at);
3125
+ return true;
3126
+ };
3127
+ const dropAt = (x, y) => {
3128
+ const at = locate(y);
3129
+ hideLine();
3130
+ if (!at || !overContent(x, y, at.rect)) return null;
3131
+ return { beforeIndex: at.beforeIndex };
3132
+ };
3133
+ const onDragOver = (event) => {
3134
+ if (!isBlockDrag(event)) return;
3135
+ const at = locate(event.clientY);
3136
+ if (!at) return;
3137
+ event.preventDefault();
3138
+ if (event.dataTransfer) event.dataTransfer.dropEffect = "copy";
3139
+ spot = at;
3140
+ showLine(at);
3141
+ };
3142
+ const onDropEvent = (event) => {
3143
+ if (!isBlockDrag(event)) return;
3144
+ event.preventDefault();
3145
+ const blockType = event.dataTransfer?.getData(VEO_BLOCK_MIME) ?? "";
3146
+ const at = spot ?? locate(event.clientY);
3147
+ hideLine();
3148
+ if (!blockType || !at) return;
3149
+ onDrop({ stepIndex, blockType, beforeIndex: at.beforeIndex });
3150
+ };
3151
+ const onDragLeave = (event) => {
3152
+ const to = event.relatedTarget;
3153
+ if (to instanceof Node && (to === host || host.contains(to))) return;
3154
+ hideLine();
3155
+ };
3156
+ host.addEventListener("dragover", onDragOver);
3157
+ host.addEventListener("drop", onDropEvent);
3158
+ host.addEventListener("dragleave", onDragLeave);
3159
+ return {
3160
+ hoverAt,
3161
+ dropAt,
3162
+ cancelHover: hideLine,
3163
+ detach() {
3164
+ host.removeEventListener("dragover", onDragOver);
3165
+ host.removeEventListener("drop", onDropEvent);
3166
+ host.removeEventListener("dragleave", onDragLeave);
3167
+ hideLine();
3168
+ }
3169
+ };
3170
+ }
3171
+ var VEO_BLOCK_MIME;
3172
+ var init_block_drop_target = __esm({
3173
+ "src/plugins/builder/block-drop-target.ts"() {
3174
+ VEO_BLOCK_MIME = "application/x-veo-block";
3175
+ }
3176
+ });
3177
+
3054
3178
  // src/plugins/builder/bridge-protocol.ts
3055
3179
  var VEO_BUILDER_SOURCE;
3056
3180
  var init_bridge_protocol = __esm({
@@ -3063,7 +3187,7 @@ var init_bridge_protocol = __esm({
3063
3187
  // src/plugins/builder/builder-panel.ts
3064
3188
  function injectBuilderPanel(opts) {
3065
3189
  if (!hasWindow() || !hasDocument()) {
3066
- return { target: () => null, teardown: () => {
3190
+ return { target: () => null, frameRect: () => null, teardown: () => {
3067
3191
  } };
3068
3192
  }
3069
3193
  const panelUrl = buildPanelUrl(opts);
@@ -3180,6 +3304,7 @@ function injectBuilderPanel(opts) {
3180
3304
  });
3181
3305
  return {
3182
3306
  target: () => popped && !popped.closed ? popped : iframe.contentWindow,
3307
+ frameRect: () => popped && !popped.closed ? null : iframe.getBoundingClientRect(),
3183
3308
  teardown: () => {
3184
3309
  stopPoll();
3185
3310
  if (popped && !popped.closed) popped.close();
@@ -3701,6 +3826,9 @@ function initBuilderMode() {
3701
3826
  let panel = null;
3702
3827
  let staticTarget = null;
3703
3828
  let manipulator = null;
3829
+ let dropTarget = null;
3830
+ let dragGhost = null;
3831
+ let previewStepIndex = 0;
3704
3832
  let pendingPreview = null;
3705
3833
  const getTarget = () => panel ? panel.target() : staticTarget;
3706
3834
  const post = (event) => {
@@ -3709,6 +3837,9 @@ function initBuilderMode() {
3709
3837
  const applyPreview = (cmd) => {
3710
3838
  manipulator?.detach();
3711
3839
  manipulator = null;
3840
+ dropTarget?.detach();
3841
+ dropTarget = null;
3842
+ previewStepIndex = cmd.guide.startStepIndex ?? 0;
3712
3843
  const handle = previewGuide(cmd.guide);
3713
3844
  if (!cmd.editable) return;
3714
3845
  void handle.ready.then((result) => {
@@ -3727,8 +3858,54 @@ function initBuilderMode() {
3727
3858
  applyPreview(queued);
3728
3859
  }
3729
3860
  });
3861
+ dropTarget = attachBlockDropTarget({
3862
+ host,
3863
+ stepIndex: cmd.guide.startStepIndex ?? 0,
3864
+ onDrop: (payload) => post({ type: "block-dropped", payload })
3865
+ });
3730
3866
  });
3731
3867
  };
3868
+ const hideDragGhost = () => {
3869
+ dragGhost?.remove();
3870
+ dragGhost = null;
3871
+ };
3872
+ const moveDragGhost = (x, y, label) => {
3873
+ if (!dragGhost) {
3874
+ dragGhost = document.createElement("div");
3875
+ dragGhost.style.cssText = "position:fixed;padding:4px 10px;border-radius:999px;background:#1c1917;color:#fff;font:12px/1.4 system-ui,sans-serif;box-shadow:0 4px 14px rgba(0,0,0,0.35);border:1px solid rgba(255,255,255,0.25);pointer-events:none;z-index:2147483647;";
3876
+ document.body.appendChild(dragGhost);
3877
+ }
3878
+ dragGhost.textContent = label;
3879
+ dragGhost.style.left = `${x + 14}px`;
3880
+ dragGhost.style.top = `${y + 12}px`;
3881
+ };
3882
+ const handleBlockDrag = (cmd) => {
3883
+ const rect = panel?.frameRect();
3884
+ if (!rect || !dropTarget) {
3885
+ if (cmd.phase !== "move") hideDragGhost();
3886
+ dropTarget?.cancelHover();
3887
+ return;
3888
+ }
3889
+ const x = rect.left + cmd.x;
3890
+ const y = rect.top + cmd.y;
3891
+ if (cmd.phase === "move") {
3892
+ moveDragGhost(x, y, cmd.label || cmd.blockType);
3893
+ dropTarget.hoverAt(x, y);
3894
+ return;
3895
+ }
3896
+ hideDragGhost();
3897
+ if (cmd.phase === "cancel") {
3898
+ dropTarget.cancelHover();
3899
+ return;
3900
+ }
3901
+ const spotAt = dropTarget.dropAt(x, y);
3902
+ if (spotAt) {
3903
+ post({
3904
+ type: "block-dropped",
3905
+ payload: { stepIndex: previewStepIndex, blockType: cmd.blockType, ...spotAt }
3906
+ });
3907
+ }
3908
+ };
3732
3909
  const handleCommand = (cmd) => {
3733
3910
  switch (cmd.type) {
3734
3911
  case "panel-ready":
@@ -3758,9 +3935,15 @@ function initBuilderMode() {
3758
3935
  if (manipulator?.isDragging()) pendingPreview = cmd;
3759
3936
  else applyPreview(cmd);
3760
3937
  break;
3938
+ case "block-drag":
3939
+ handleBlockDrag(cmd);
3940
+ break;
3761
3941
  case "close-preview":
3762
3942
  manipulator?.detach();
3763
3943
  manipulator = null;
3944
+ dropTarget?.detach();
3945
+ dropTarget = null;
3946
+ hideDragGhost();
3764
3947
  pendingPreview = null;
3765
3948
  closeGuidePreview();
3766
3949
  break;
@@ -3783,6 +3966,9 @@ function initBuilderMode() {
3783
3966
  picker = null;
3784
3967
  manipulator?.detach();
3785
3968
  manipulator = null;
3969
+ dropTarget?.detach();
3970
+ dropTarget = null;
3971
+ hideDragGhost();
3786
3972
  pendingPreview = null;
3787
3973
  closeGuidePreview();
3788
3974
  post({ type: "closed" });
@@ -3861,6 +4047,7 @@ var init_builder_mode = __esm({
3861
4047
  init_builder_token();
3862
4048
  init_safe_env();
3863
4049
  init_guide_preview();
4050
+ init_block_drop_target();
3864
4051
  init_bridge_protocol();
3865
4052
  init_builder_panel();
3866
4053
  init_design_manipulator();
@@ -3997,6 +4184,8 @@ var init_builder_session = __esm({
3997
4184
  // src/plugins/builder/index.ts
3998
4185
  var builder_exports = {};
3999
4186
  __export(builder_exports, {
4187
+ VEO_BLOCK_MIME: () => VEO_BLOCK_MIME,
4188
+ attachBlockDropTarget: () => attachBlockDropTarget,
4000
4189
  attachDesignManipulator: () => attachDesignManipulator,
4001
4190
  createBuilderSession: () => createBuilderSession,
4002
4191
  initBuilderMode: () => initBuilderMode,
@@ -4005,6 +4194,7 @@ __export(builder_exports, {
4005
4194
  });
4006
4195
  var init_builder = __esm({
4007
4196
  "src/plugins/builder/index.ts"() {
4197
+ init_block_drop_target();
4008
4198
  init_builder_mode();
4009
4199
  init_builder_session();
4010
4200
  init_design_manipulator();