@sendbird/actionbook-core 0.10.7 → 0.10.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/ui/index.js CHANGED
@@ -2418,6 +2418,14 @@ var gfmNoAutolinkToMarkdown = () => ({
2418
2418
  function isEmptyParagraph(node) {
2419
2419
  return node.type === "paragraph" && (!("children" in node) || !node.children || node.children.length === 0);
2420
2420
  }
2421
+ var JINJA_TAG_RE = /^\{%\s*(if|elif|else|endif)\b/;
2422
+ function isJinjaTagParagraph(node) {
2423
+ if (node.type !== "paragraph") return false;
2424
+ const children = node.children;
2425
+ if (!children || children.length !== 1) return false;
2426
+ const child = children[0];
2427
+ return child.type === "text" && typeof child.value === "string" && JINJA_TAG_RE.test(child.value);
2428
+ }
2421
2429
  function textHandler(node, parent, state, info) {
2422
2430
  const originalUnsafe = state.unsafe;
2423
2431
  state.unsafe = originalUnsafe.filter((p) => !(p.character === "_" && !p.atBreak));
@@ -2460,7 +2468,10 @@ function serializeToMarkdown(doc2) {
2460
2468
  // Empty paragraphs represent blank-line spacers.
2461
2469
  // Reduce the separator after an empty paragraph from \n\n to \n
2462
2470
  // so that 1 empty paragraph = 1 extra blank line in the output.
2463
- (left) => isEmptyParagraph(left) ? 0 : null
2471
+ (left) => isEmptyParagraph(left) ? 0 : null,
2472
+ // Consecutive paragraphs: single newline instead of blank line
2473
+ // (skip jinja tag paragraphs — they need blank lines for proper roundtrip)
2474
+ (left, right) => left.type === "paragraph" && right.type === "paragraph" && !isJinjaTagParagraph(left) && !isJinjaTagParagraph(right) ? 0 : null
2464
2475
  ],
2465
2476
  handlers: {
2466
2477
  text: textHandler,
@@ -5597,6 +5608,11 @@ function tokenize(input) {
5597
5608
  i++;
5598
5609
  continue;
5599
5610
  }
5611
+ if (input[i] === ",") {
5612
+ tokens.push({ type: "COMMA", value: "," });
5613
+ i++;
5614
+ continue;
5615
+ }
5600
5616
  return { tokens: [], error: `Unexpected character: ${input[i]}` };
5601
5617
  }
5602
5618
  tokens.push({ type: "EOF", value: "" });
@@ -5727,6 +5743,17 @@ var Parser = class {
5727
5743
  return null;
5728
5744
  case "IDENT": {
5729
5745
  this.advance();
5746
+ if (this.peek().type === "LPAREN") {
5747
+ this.advance();
5748
+ while (this.peek().type !== "RPAREN" && this.peek().type !== "EOF") {
5749
+ this.orExpr();
5750
+ if (this.peek().type === "COMMA") {
5751
+ this.advance();
5752
+ }
5753
+ }
5754
+ this.expect("RPAREN");
5755
+ return null;
5756
+ }
5730
5757
  return this.resolveVariable(t.value);
5731
5758
  }
5732
5759
  case "LPAREN": {
@@ -5806,7 +5833,7 @@ var END_ACTION_TEXTS = /* @__PURE__ */ new Set([
5806
5833
  function isEndActionTag(tagType, resourceId, text2) {
5807
5834
  return tagType === "handoff" || END_ACTION_RESOURCE_IDS.has(resourceId) || END_ACTION_TEXTS.has(text2.toLowerCase());
5808
5835
  }
5809
- function extractInlineItems(content, blockIndex) {
5836
+ function extractInlineItems(content, blockIndex, listItemPath = []) {
5810
5837
  const items = [];
5811
5838
  for (const node of content) {
5812
5839
  if (node.type === "jumpPoint") {
@@ -5823,22 +5850,26 @@ function extractInlineItems(content, blockIndex) {
5823
5850
  label: endAction ? `End ${node.text}` : node.text,
5824
5851
  blockIndex,
5825
5852
  children: [],
5826
- meta: { tagType: node.tagType, resourceId: node.resourceId }
5853
+ meta: {
5854
+ tagType: node.tagType,
5855
+ resourceId: node.resourceId,
5856
+ ...listItemPath.length > 0 && { listItemPath: [...listItemPath] }
5857
+ }
5827
5858
  });
5828
5859
  }
5829
5860
  }
5830
5861
  return items;
5831
5862
  }
5832
- function extractBlockItems(blocks, startIndex, depth) {
5863
+ function extractBlockItems(blocks, startIndex, depth, listItemPath = [], fixedBlockIndex) {
5833
5864
  if (depth > MAX_DEPTH6) return [];
5834
5865
  const items = [];
5835
5866
  for (let i = 0; i < blocks.length; i++) {
5836
5867
  const block = blocks[i];
5837
- const blockIndex = startIndex + i;
5868
+ const blockIndex = fixedBlockIndex ?? startIndex + i;
5838
5869
  switch (block.type) {
5839
5870
  case "heading": {
5840
5871
  const label = textContent(block) || `Heading ${block.level}`;
5841
- const inlineItems = extractInlineItems(block.content, blockIndex);
5872
+ const inlineItems = extractInlineItems(block.content, blockIndex, listItemPath);
5842
5873
  items.push({
5843
5874
  type: "heading",
5844
5875
  label,
@@ -5849,7 +5880,7 @@ function extractBlockItems(blocks, startIndex, depth) {
5849
5880
  break;
5850
5881
  }
5851
5882
  case "paragraph": {
5852
- const inlineItems = extractInlineItems(block.content, blockIndex);
5883
+ const inlineItems = extractInlineItems(block.content, blockIndex, listItemPath);
5853
5884
  items.push(...inlineItems);
5854
5885
  break;
5855
5886
  }
@@ -5885,14 +5916,15 @@ function extractBlockItems(blocks, startIndex, depth) {
5885
5916
  }
5886
5917
  case "bulletList":
5887
5918
  case "orderedList": {
5888
- for (const li of block.content) {
5889
- const childItems = extractBlockItems(li.content, blockIndex, depth + 1);
5919
+ for (let liIdx = 0; liIdx < block.content.length; liIdx++) {
5920
+ const li = block.content[liIdx];
5921
+ const childItems = extractBlockItems(li.content, blockIndex, depth + 1, [...listItemPath, liIdx], blockIndex);
5890
5922
  items.push(...childItems);
5891
5923
  }
5892
5924
  break;
5893
5925
  }
5894
5926
  case "blockquote": {
5895
- const childItems = extractBlockItems(block.content, blockIndex, depth + 1);
5927
+ const childItems = extractBlockItems(block.content, blockIndex, depth + 1, listItemPath, blockIndex);
5896
5928
  items.push(...childItems);
5897
5929
  break;
5898
5930
  }
@@ -6656,7 +6688,7 @@ function createInlineToolTagNodeViewPlugin() {
6656
6688
  import { Plugin as Plugin6, PluginKey as PluginKey5 } from "prosemirror-state";
6657
6689
  import { Decoration as Decoration4, DecorationSet as DecorationSet4 } from "prosemirror-view";
6658
6690
  var jinjaPluginKey = new PluginKey5("jinjaDecoration");
6659
- var JINJA_TAG_RE = /\{%\s*(if|elif|else|endif)\s*([^%]*?)\s*%\}/g;
6691
+ var JINJA_TAG_RE2 = /\{%\s*(if|elif|else|endif)\s*([^%]*?)\s*%\}/g;
6660
6692
  function getBlockPositions(doc2) {
6661
6693
  const blocks = [];
6662
6694
  let index = 0;
@@ -6670,9 +6702,9 @@ function addInlineChipDecorations(doc2, decorations) {
6670
6702
  doc2.descendants((node, pos) => {
6671
6703
  if (!node.isText) return;
6672
6704
  const text2 = node.text;
6673
- JINJA_TAG_RE.lastIndex = 0;
6705
+ JINJA_TAG_RE2.lastIndex = 0;
6674
6706
  let match;
6675
- while ((match = JINJA_TAG_RE.exec(text2)) !== null) {
6707
+ while ((match = JINJA_TAG_RE2.exec(text2)) !== null) {
6676
6708
  const from = pos + match.index;
6677
6709
  const to = from + match[0].length;
6678
6710
  const keyword = match[1];
@@ -6837,6 +6869,7 @@ var JINJA_STYLES = `
6837
6869
  .jinja-branch-condition {
6838
6870
  flex: 1;
6839
6871
  min-width: 0;
6872
+ min-height: 20px;
6840
6873
  display: flex;
6841
6874
  flex-wrap: wrap;
6842
6875
  gap: 8px;
@@ -7014,6 +7047,15 @@ var JINJA_STYLES = `
7014
7047
  background: rgba(13, 13, 13, 0.04);
7015
7048
  }
7016
7049
 
7050
+ .jinja-ghost-btn.jinja-add-btn {
7051
+ color: #5E5E5E;
7052
+ }
7053
+
7054
+ .jinja-ghost-btn.jinja-add-btn.active {
7055
+ background: #DCDBFF;
7056
+ color: #6210CC;
7057
+ }
7058
+
7017
7059
  .jinja-ghost-btn:disabled {
7018
7060
  opacity: 0.45;
7019
7061
  cursor: default;
@@ -7316,7 +7358,7 @@ function ConditionDisplay({
7316
7358
  setIsEditing(true);
7317
7359
  }
7318
7360
  },
7319
- children: condition.length > 0 ? renderCondition(condition) : /* @__PURE__ */ jsx6("span", { className: "jinja-condition-placeholder", children: CONDITION_PLACEHOLDER })
7361
+ children: condition.length > 0 ? condition.trim().length > 0 ? renderCondition(condition) : /* @__PURE__ */ jsx6("span", { className: "jinja-token-identifier", children: condition }) : /* @__PURE__ */ jsx6("span", { className: "jinja-condition-placeholder", children: CONDITION_PLACEHOLDER })
7320
7362
  }
7321
7363
  );
7322
7364
  }
@@ -7390,6 +7432,16 @@ function JinjaBranchHeader({
7390
7432
  }, [menuSource]);
7391
7433
  const menuItems = [];
7392
7434
  if (editable) {
7435
+ if (!hasElseBranch) {
7436
+ menuItems.push({
7437
+ label: "Else if",
7438
+ onSelect: () => onAddBranch("elif")
7439
+ });
7440
+ menuItems.push({
7441
+ label: "Else",
7442
+ onSelect: () => onAddBranch("else")
7443
+ });
7444
+ }
7393
7445
  menuItems.push({
7394
7446
  label: "Delete",
7395
7447
  onSelect: onDelete
@@ -7444,8 +7496,9 @@ function JinjaBranchHeader({
7444
7496
  BranchPopupMenu,
7445
7497
  {
7446
7498
  position: { top: 28, right: 0 },
7447
- items: menuItems.map((item) => ({
7499
+ items: menuItems.filter((item) => item.label === "Delete").map((item) => ({
7448
7500
  ...item,
7501
+ label: branchType === "if" ? "Delete all" : "Delete",
7449
7502
  onSelect: () => {
7450
7503
  setMenuSource(null);
7451
7504
  item.onSelect();
@@ -7462,7 +7515,7 @@ function JinjaBranchHeader({
7462
7515
  "button",
7463
7516
  {
7464
7517
  type: "button",
7465
- className: "jinja-ghost-btn",
7518
+ className: `jinja-ghost-btn jinja-add-btn${menuSource === "footer" ? " active" : ""}`,
7466
7519
  "aria-label": "Add branch",
7467
7520
  disabled: !canOpenFooterMenu,
7468
7521
  onMouseDown: (event) => event.preventDefault(),
@@ -7471,9 +7524,9 @@ function JinjaBranchHeader({
7471
7524
  setMenuSource((current) => current === "footer" ? null : "footer");
7472
7525
  }
7473
7526
  },
7474
- children: /* @__PURE__ */ jsxs5("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", children: [
7475
- /* @__PURE__ */ jsx6("line", { x1: "8", y1: "3", x2: "8", y2: "13" }),
7476
- /* @__PURE__ */ jsx6("line", { x1: "3", y1: "8", x2: "13", y2: "8" })
7527
+ children: /* @__PURE__ */ jsxs5("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
7528
+ /* @__PURE__ */ jsx6("path", { d: "M7.33337 11L7.33337 8.66666L5.00004 8.66666V7.33333L7.33337 7.33333V4.99999H8.66671V7.33333H11V8.66666H8.66671L8.66671 11H7.33337Z", fill: "currentColor" }),
7529
+ /* @__PURE__ */ jsx6("path", { "fill-rule": "evenodd", "clip-rule": "evenodd", d: "M8.00004 14.6667C11.6819 14.6667 14.6667 11.6819 14.6667 7.99999C14.6667 4.3181 11.6819 1.33333 8.00004 1.33333C4.31814 1.33333 1.33337 4.3181 1.33337 7.99999C1.33337 11.6819 4.31814 14.6667 8.00004 14.6667ZM13.3334 7.99999C13.3334 10.9455 10.9456 13.3333 8.00004 13.3333C5.05452 13.3333 2.66671 10.9455 2.66671 7.99999C2.66671 5.05448 5.05452 2.66666 8.00004 2.66666C10.9456 2.66666 13.3334 5.05448 13.3334 7.99999Z", fill: "currentColor" })
7477
7530
  ] })
7478
7531
  }
7479
7532
  ),
@@ -7825,23 +7878,10 @@ function createLinkClickPlugin() {
7825
7878
  if (target.tagName !== "A") return false;
7826
7879
  const href = target.getAttribute("href");
7827
7880
  if (!href) return false;
7828
- if (href.startsWith("#")) {
7829
- event.preventDefault();
7830
- const targetId = `jp-${href.slice(1)}`;
7831
- const el = document.getElementById(targetId);
7832
- if (el) {
7833
- el.scrollIntoView({ block: "end" });
7834
- el.focus();
7835
- if (el.parentElement) {
7836
- el.parentElement.style.outline = "2px solid #6213cc";
7837
- setTimeout(() => {
7838
- el.parentElement.style.outline = "none";
7839
- }, 500);
7840
- }
7841
- }
7842
- return true;
7843
- }
7844
- return false;
7881
+ event.preventDefault();
7882
+ if (href.startsWith("#")) return true;
7883
+ window.open(href, "_blank", "noopener,noreferrer");
7884
+ return true;
7845
7885
  }
7846
7886
  }
7847
7887
  }
@@ -7871,7 +7911,7 @@ function createLinkPlugin() {
7871
7911
  // src/ui/plugin/dragHandlePlugin.ts
7872
7912
  import { Plugin as Plugin9, PluginKey as PluginKey7 } from "prosemirror-state";
7873
7913
  var PLUGIN_KEY = new PluginKey7("dragHandle");
7874
- var GRIP_SVG = `<svg width="12" height="12" viewBox="0 0 12 12" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
7914
+ var GRIP_SVG = `<svg width="16" height="16" viewBox="0 0 12 12" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
7875
7915
  <circle cx="4" cy="2.5" r="1.2"/><circle cx="8" cy="2.5" r="1.2"/>
7876
7916
  <circle cx="4" cy="6" r="1.2"/><circle cx="8" cy="6" r="1.2"/>
7877
7917
  <circle cx="4" cy="9.5" r="1.2"/><circle cx="8" cy="9.5" r="1.2"/>
@@ -8481,6 +8521,7 @@ var DragHandleController = class {
8481
8521
  this.dropIndicator.className = "ab-drop-indicator";
8482
8522
  this.dropIndicator.style.display = "none";
8483
8523
  parent.appendChild(this.dropIndicator);
8524
+ this.scrollContainer = this.findScrollContainer(this.view.dom);
8484
8525
  this.tickAutoScroll();
8485
8526
  }
8486
8527
  addGlobalDragListeners(pointerId) {
@@ -8629,6 +8670,7 @@ var DragHandleController = class {
8629
8670
  while (current) {
8630
8671
  const overflow = getComputedStyle(current).overflowY;
8631
8672
  if (overflow === "auto" || overflow === "scroll") return current;
8673
+ if (overflow === "hidden" && (current.classList.contains("ps") || current.scrollHeight > current.clientHeight + 1)) return current;
8632
8674
  current = current.parentElement;
8633
8675
  }
8634
8676
  return el.parentElement ?? el;
@@ -9715,7 +9757,7 @@ function DropdownItem({ item, onRun }) {
9715
9757
  transition: "background 0.1s"
9716
9758
  },
9717
9759
  children: [
9718
- /* @__PURE__ */ jsx10("span", { style: { width: 24, flexShrink: 0, textAlign: "center", fontWeight: 700, fontSize: 12, fontFamily: "monospace", color: "#6210CC" }, children: item.shortLabel }),
9760
+ /* @__PURE__ */ jsx10("span", { style: { width: 24, flexShrink: 0, textAlign: "center", fontWeight: 700, fontSize: 12, fontFamily: "monospace", color: item.active ? "#6210CC" : "#666" }, children: item.shortLabel }),
9719
9761
  item.label
9720
9762
  ]
9721
9763
  }