@sendbird/actionbook-core 0.9.7 → 0.9.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
@@ -2745,27 +2745,52 @@ function findParentList(state, pos) {
2745
2745
  }
2746
2746
  return null;
2747
2747
  }
2748
+ var NOOP = /* @__PURE__ */ Symbol("noop");
2748
2749
  function handleListInputRule(state, start, end, listType, attrs) {
2749
2750
  const resolvePos = Math.max(start, end - 1);
2750
2751
  const parentList = findParentList(state, resolvePos);
2751
2752
  if (!parentList) return null;
2752
2753
  const $from = state.doc.resolve(resolvePos);
2753
- const { depth, node: listNode } = parentList;
2754
+ const { depth: listDepth, node: listNode } = parentList;
2754
2755
  const paraContentSize = $from.parent.content.size;
2755
2756
  const matchedLen = end - start;
2756
2757
  if (paraContentSize !== matchedLen) return null;
2757
- const listStart = $from.before(depth);
2758
- const listEnd = $from.after(depth);
2759
2758
  if (listNode.type === listType) {
2760
- const tr = state.tr.replaceWith(listStart, listEnd, actionbookSchema.nodes.paragraph.create());
2761
- tr.setSelection(TextSelection.near(tr.doc.resolve(listStart)));
2762
- return tr;
2763
- } else {
2764
- const tr = state.tr.delete(start, end);
2765
- const mappedListPos = tr.mapping.map(listStart);
2766
- tr.setNodeMarkup(mappedListPos, listType, attrs ?? null);
2767
- return tr;
2759
+ return NOOP;
2768
2760
  }
2761
+ const { listItem: liType } = actionbookSchema.nodes;
2762
+ const tr = state.tr.delete(start, end);
2763
+ const $pos = tr.doc.resolve(tr.mapping.map(resolvePos));
2764
+ let liDepth = -1;
2765
+ for (let d = $pos.depth; d > 0; d--) {
2766
+ if ($pos.node(d).type === liType) {
2767
+ liDepth = d;
2768
+ break;
2769
+ }
2770
+ }
2771
+ if (liDepth < 0) return null;
2772
+ const parentListAfterDelete = $pos.node(liDepth - 1);
2773
+ const liIndex = $pos.index(liDepth - 1);
2774
+ const liNode = parentListAfterDelete.child(liIndex);
2775
+ const parentListStart = $pos.before(liDepth - 1);
2776
+ const parentListEnd = $pos.after(liDepth - 1);
2777
+ const fragments = [];
2778
+ if (liIndex > 0) {
2779
+ const beforeItems = [];
2780
+ for (let i = 0; i < liIndex; i++) beforeItems.push(parentListAfterDelete.child(i));
2781
+ fragments.push(parentListAfterDelete.type.create(parentListAfterDelete.attrs, beforeItems));
2782
+ }
2783
+ fragments.push(listType.create(attrs ?? null, liNode));
2784
+ if (liIndex < parentListAfterDelete.childCount - 1) {
2785
+ const afterItems = [];
2786
+ for (let i = liIndex + 1; i < parentListAfterDelete.childCount; i++) {
2787
+ afterItems.push(parentListAfterDelete.child(i));
2788
+ }
2789
+ fragments.push(parentListAfterDelete.type.create(parentListAfterDelete.attrs, afterItems));
2790
+ }
2791
+ tr.replaceWith(parentListStart, parentListEnd, fragments);
2792
+ tr.setSelection(TextSelection.near(tr.doc.resolve(tr.mapping.map(start))));
2793
+ return tr;
2769
2794
  }
2770
2795
  function markInputRule(pattern, markType, markerLen) {
2771
2796
  return new InputRule(pattern, (state, match, start, end) => {
@@ -2836,8 +2861,9 @@ function createInputRulesPlugin() {
2836
2861
  const fallback = wrappingInputRule(BULLET_LIST_RE, blType);
2837
2862
  rules.push(
2838
2863
  new InputRule(BULLET_LIST_RE, (state, match, start, end) => {
2839
- const toggled = handleListInputRule(state, start, end, blType);
2840
- if (toggled) return toggled;
2864
+ const result = handleListInputRule(state, start, end, blType);
2865
+ if (result === NOOP) return null;
2866
+ if (result) return result;
2841
2867
  const handler = fallback.handler;
2842
2868
  return handler(state, match, start, end);
2843
2869
  })
@@ -2848,8 +2874,9 @@ function createInputRulesPlugin() {
2848
2874
  const fallback = wrappingInputRule(ORDERED_LIST_RE, olType, (m) => ({ start: +m[1] }));
2849
2875
  rules.push(
2850
2876
  new InputRule(ORDERED_LIST_RE, (state, match, start, end) => {
2851
- const toggled = handleListInputRule(state, start, end, olType, { start: +match[1] });
2852
- if (toggled) return toggled;
2877
+ const result = handleListInputRule(state, start, end, olType, { start: +match[1] });
2878
+ if (result === NOOP) return null;
2879
+ if (result) return result;
2853
2880
  const handler = fallback.handler;
2854
2881
  return handler(state, match, start, end);
2855
2882
  })
@@ -2859,14 +2886,6 @@ function createInputRulesPlugin() {
2859
2886
  rules.push(
2860
2887
  new InputRule(JUMP_POINT_RE2, (state, match, start, end) => {
2861
2888
  const id = match[1];
2862
- let exists = false;
2863
- state.doc.descendants((node) => {
2864
- if (node.type === jumpPointType && node.attrs.id === id) {
2865
- exists = true;
2866
- return false;
2867
- }
2868
- });
2869
- if (exists) return null;
2870
2889
  const tr = state.tr.delete(start, end).insert(start, jumpPointType.create({ id }));
2871
2890
  const afterAtom = start + 1;
2872
2891
  tr.insertText(" ", afterAtom);
@@ -3071,6 +3090,69 @@ var backspaceDeleteEmptyBlock = (state, dispatch) => {
3071
3090
  }
3072
3091
  return false;
3073
3092
  };
3093
+ var joinListItemBackward = (state, dispatch) => {
3094
+ const { $from } = state.selection;
3095
+ if (!state.selection.empty) return false;
3096
+ if ($from.parentOffset !== 0) return false;
3097
+ if (!cursorDirectlyInListItem(state)) return false;
3098
+ if ($from.index($from.depth - 1) !== 0) return false;
3099
+ const liDepth = $from.depth - 1;
3100
+ const listDepth = liDepth - 1;
3101
+ if (listDepth < 0) return false;
3102
+ const listNode = $from.node(listDepth);
3103
+ if (listNode.type !== bulletList && listNode.type !== orderedList) return false;
3104
+ const liIndex = $from.index(listDepth);
3105
+ if (liIndex > 0) {
3106
+ if (dispatch) {
3107
+ const joinPos = $from.before(liDepth);
3108
+ const tr = state.tr.join(joinPos);
3109
+ const mappedPos = tr.mapping.map(joinPos);
3110
+ if (tr.doc.resolve(mappedPos).nodeBefore?.isTextblock && tr.doc.resolve(mappedPos).nodeAfter?.isTextblock) {
3111
+ tr.join(mappedPos);
3112
+ }
3113
+ dispatch(tr.scrollIntoView());
3114
+ }
3115
+ return true;
3116
+ }
3117
+ const listStart = $from.before(listDepth);
3118
+ const parentOfList = $from.node(listDepth - 1);
3119
+ const listIndexInParent = $from.index(listDepth - 1);
3120
+ if (listIndexInParent > 0) {
3121
+ const prevBlock = parentOfList.child(listIndexInParent - 1);
3122
+ if (prevBlock.isTextblock) {
3123
+ if (dispatch) {
3124
+ const liNode = listNode.child(0);
3125
+ const firstPara = liNode.firstChild;
3126
+ const liStart = $from.before(liDepth);
3127
+ const liEnd = $from.after(liDepth);
3128
+ const tr = state.tr;
3129
+ if (listNode.childCount === 1) {
3130
+ tr.delete(listStart, $from.after(listDepth));
3131
+ } else {
3132
+ tr.delete(liStart, liEnd);
3133
+ }
3134
+ const prevBlockEnd = tr.mapping.map(listStart) - 1;
3135
+ if (firstPara.content.size > 0) {
3136
+ tr.insert(prevBlockEnd, firstPara.content);
3137
+ }
3138
+ if (liNode.childCount > 1) {
3139
+ const nestedContent = [];
3140
+ for (let i = 1; i < liNode.childCount; i++) {
3141
+ nestedContent.push(liNode.child(i));
3142
+ }
3143
+ const insertPos = tr.mapping.map(listStart);
3144
+ for (const node of nestedContent) {
3145
+ tr.insert(insertPos, node);
3146
+ }
3147
+ }
3148
+ tr.setSelection(TextSelection2.near(tr.doc.resolve(prevBlockEnd)));
3149
+ dispatch(tr.scrollIntoView());
3150
+ }
3151
+ return true;
3152
+ }
3153
+ }
3154
+ return liftListItem(listItem)(state, dispatch);
3155
+ };
3074
3156
  var backspaceCommand = chainCommands(
3075
3157
  backspaceDeleteEmptyBlock,
3076
3158
  backspaceAfterList,
@@ -3082,7 +3164,13 @@ var backspaceCommand = chainCommands(
3082
3164
  if ($from.parent.type === heading) {
3083
3165
  return setBlockType(paragraph)(state, dispatch);
3084
3166
  }
3167
+ return false;
3168
+ },
3169
+ joinListItemBackward,
3170
+ (state, dispatch) => {
3085
3171
  if (!cursorDirectlyInListItem(state)) return false;
3172
+ const { $from } = state.selection;
3173
+ if ($from.parentOffset !== 0) return false;
3086
3174
  if ($from.index($from.depth - 1) !== 0) return false;
3087
3175
  return liftListItem(listItem)(state, dispatch);
3088
3176
  },
@@ -3168,9 +3256,27 @@ var exitBlockOnDoubleEnter = (state, dispatch) => {
3168
3256
  dispatch(tr.scrollIntoView());
3169
3257
  return true;
3170
3258
  };
3259
+ var exitCodeBlockOnEnter = (state, dispatch) => {
3260
+ const { $from } = state.selection;
3261
+ if ($from.parent.type.name !== "codeBlock") return false;
3262
+ const codeBlock = $from.parent;
3263
+ const text2 = codeBlock.textContent;
3264
+ if ($from.parentOffset !== text2.length) return false;
3265
+ if (!text2.endsWith("\n")) return false;
3266
+ if (dispatch) {
3267
+ const codeBlockPos = $from.before($from.depth);
3268
+ const tr = state.tr.delete($from.pos - 1, $from.pos);
3269
+ const blockEnd = tr.mapping.map(codeBlockPos + codeBlock.nodeSize);
3270
+ tr.insert(blockEnd, paragraph.create());
3271
+ tr.setSelection(TextSelection2.near(tr.doc.resolve(blockEnd + 1)));
3272
+ dispatch(tr.scrollIntoView());
3273
+ }
3274
+ return true;
3275
+ };
3171
3276
  var enterCommand = chainCommands(
3172
3277
  exitNoteBlockOnEnter,
3173
3278
  exitBlockOnDoubleEnter,
3279
+ exitCodeBlockOnEnter,
3174
3280
  newlineInCode,
3175
3281
  // Split list item on Enter; lift empty list item out of list
3176
3282
  splitListItem(listItem),
@@ -5293,18 +5399,10 @@ function createJumpPointEditPlugin() {
5293
5399
  const [, id] = match;
5294
5400
  const jumpPointType = newState.schema.nodes.jumpPoint;
5295
5401
  if (jumpPointType) {
5296
- let duplicate = false;
5297
- newState.doc.descendants((node, pos) => {
5298
- if (node.type === jumpPointType && node.attrs.id === id) {
5299
- if (pos < safeFrom || pos >= safeTo) duplicate = true;
5300
- }
5301
- });
5302
- if (!duplicate) {
5303
- reconvertTr.replaceWith(safeFrom, safeTo, jumpPointType.create({ id }));
5304
- const mappedCursor = reconvertTr.mapping.map(cursor);
5305
- const clampedCursor = Math.min(mappedCursor, reconvertTr.doc.content.size);
5306
- reconvertTr.setSelection(TextSelection3.near(reconvertTr.doc.resolve(clampedCursor)));
5307
- }
5402
+ reconvertTr.replaceWith(safeFrom, safeTo, jumpPointType.create({ id }));
5403
+ const mappedCursor = reconvertTr.mapping.map(cursor);
5404
+ const clampedCursor = Math.min(mappedCursor, reconvertTr.doc.content.size);
5405
+ reconvertTr.setSelection(TextSelection3.near(reconvertTr.doc.resolve(clampedCursor)));
5308
5406
  }
5309
5407
  }
5310
5408
  }
@@ -6205,15 +6303,6 @@ function getElseBranch(view, nodePos) {
6205
6303
  }
6206
6304
  return false;
6207
6305
  }
6208
- function deleteBlock(view, blockPos) {
6209
- const blockNode = view.state.doc.nodeAt(blockPos);
6210
- if (blockNode?.type.name !== "jinjaIfBlock") {
6211
- return false;
6212
- }
6213
- view.dispatch(view.state.tr.delete(blockPos, blockPos + blockNode.nodeSize).scrollIntoView());
6214
- view.focus();
6215
- return true;
6216
- }
6217
6306
  function insertNewBranch(view, nodePos, branchType, condition = "") {
6218
6307
  const context = getBranchContext(view, nodePos);
6219
6308
  if (!context) return false;
@@ -6239,14 +6328,36 @@ function insertNewBranch(view, nodePos, branchType, condition = "") {
6239
6328
  function deleteBranch(view, nodePos, branchType) {
6240
6329
  const context = getBranchContext(view, nodePos);
6241
6330
  if (!context) return false;
6331
+ const { branchNode, branchPos, branchIndex, blockNode, blockPos } = context;
6332
+ const branchContent = branchNode.content;
6242
6333
  if (branchType === "if") {
6243
- if (context.blockNode.childCount === 1) {
6244
- return deleteBlock(view, context.blockPos);
6334
+ if (blockNode.childCount === 1) {
6335
+ const tr2 = view.state.tr;
6336
+ if (isBranchBodyEmpty(branchNode)) {
6337
+ tr2.replaceWith(blockPos, blockPos + blockNode.nodeSize, view.state.schema.nodes.paragraph.create());
6338
+ tr2.setSelection(TextSelection4.near(tr2.doc.resolve(blockPos)));
6339
+ } else {
6340
+ tr2.replaceWith(blockPos, blockPos + blockNode.nodeSize, branchContent);
6341
+ tr2.setSelection(TextSelection4.near(tr2.doc.resolve(blockPos)));
6342
+ }
6343
+ view.dispatch(tr2.scrollIntoView());
6344
+ view.focus();
6345
+ return true;
6245
6346
  }
6246
- const nextBranch = context.blockNode.child(context.branchIndex + 1);
6347
+ const nextBranch = blockNode.child(branchIndex + 1);
6247
6348
  const promotedCondition = typeof nextBranch.attrs.condition === "string" ? nextBranch.attrs.condition : "";
6248
- const tr = view.state.tr.delete(context.branchPos, context.branchPos + context.branchNode.nodeSize);
6249
- tr.setNodeMarkup(context.branchPos, void 0, {
6349
+ const tr = view.state.tr;
6350
+ if (!isBranchBodyEmpty(branchNode)) {
6351
+ const nextBranchPos = branchPos + branchNode.nodeSize;
6352
+ const nextBranchContentStart = nextBranchPos + 1;
6353
+ for (let i = branchContent.childCount - 1; i >= 0; i--) {
6354
+ tr.insert(nextBranchContentStart, branchContent.child(i));
6355
+ }
6356
+ }
6357
+ const mappedBranchPos = tr.mapping.map(branchPos);
6358
+ const mappedBranchEnd = tr.mapping.map(branchPos + branchNode.nodeSize);
6359
+ tr.delete(mappedBranchPos, mappedBranchEnd);
6360
+ tr.setNodeMarkup(mappedBranchPos, void 0, {
6250
6361
  ...nextBranch.attrs,
6251
6362
  branchType: "if",
6252
6363
  condition: promotedCondition
@@ -6255,7 +6366,23 @@ function deleteBranch(view, nodePos, branchType) {
6255
6366
  view.focus();
6256
6367
  return true;
6257
6368
  }
6258
- view.dispatch(view.state.tr.delete(context.branchPos, context.branchPos + context.branchNode.nodeSize).scrollIntoView());
6369
+ if (!isBranchBodyEmpty(branchNode) && branchIndex > 0) {
6370
+ const prevBranch = blockNode.child(branchIndex - 1);
6371
+ const prevBranchPos = branchPos - prevBranch.nodeSize;
6372
+ const prevBranchContentEnd = prevBranchPos + prevBranch.nodeSize - 1;
6373
+ const tr = view.state.tr;
6374
+ for (let i = 0; i < branchContent.childCount; i++) {
6375
+ tr.insert(prevBranchContentEnd + i, branchContent.child(i));
6376
+ }
6377
+ const mappedBranchPos = tr.mapping.map(branchPos);
6378
+ const mappedBranchEnd = tr.mapping.map(branchPos + branchNode.nodeSize);
6379
+ tr.delete(mappedBranchPos, mappedBranchEnd);
6380
+ tr.setSelection(TextSelection4.near(tr.doc.resolve(tr.mapping.map(prevBranchContentEnd)), -1));
6381
+ view.dispatch(tr.scrollIntoView());
6382
+ view.focus();
6383
+ return true;
6384
+ }
6385
+ view.dispatch(view.state.tr.delete(branchPos, branchPos + branchNode.nodeSize).scrollIntoView());
6259
6386
  view.focus();
6260
6387
  return true;
6261
6388
  }
@@ -6274,7 +6401,8 @@ function ConditionDisplay({
6274
6401
  branchType,
6275
6402
  condition,
6276
6403
  editable = true,
6277
- onConditionChange
6404
+ onConditionChange,
6405
+ onBackspaceEmpty
6278
6406
  }) {
6279
6407
  const [isEditing, setIsEditing] = useState3(false);
6280
6408
  const [draftValue, setDraftValue] = useState3(condition);
@@ -6329,6 +6457,10 @@ function ConditionDisplay({
6329
6457
  event.preventDefault();
6330
6458
  cancel();
6331
6459
  }
6460
+ if (event.key === "Backspace" && draftValue === "" && onBackspaceEmpty) {
6461
+ event.preventDefault();
6462
+ onBackspaceEmpty();
6463
+ }
6332
6464
  }
6333
6465
  }
6334
6466
  );
@@ -6448,7 +6580,8 @@ function JinjaBranchHeader({
6448
6580
  branchType,
6449
6581
  condition,
6450
6582
  editable,
6451
- onConditionChange
6583
+ onConditionChange,
6584
+ onBackspaceEmpty: onDelete
6452
6585
  }
6453
6586
  ),
6454
6587
  editable ? /* @__PURE__ */ jsxs5("div", { className: "jinja-branch-actions", ref: kebabRef, children: [
@@ -6486,7 +6619,7 @@ function JinjaBranchHeader({
6486
6619
  ) : null
6487
6620
  ] }) : null
6488
6621
  ] }),
6489
- isLastBranch ? /* @__PURE__ */ jsx6("div", { className: "jinja-add-footer", children: /* @__PURE__ */ jsx6("div", { className: "jinja-add-footer-col", children: /* @__PURE__ */ jsxs5("div", { className: "jinja-add-footer-actions", ref: footerRef, children: [
6622
+ isLastBranch && editable ? /* @__PURE__ */ jsx6("div", { className: "jinja-add-footer", children: /* @__PURE__ */ jsx6("div", { className: "jinja-add-footer-col", children: /* @__PURE__ */ jsxs5("div", { className: "jinja-add-footer-actions", ref: footerRef, children: [
6490
6623
  /* @__PURE__ */ jsx6(
6491
6624
  "button",
6492
6625
  {
@@ -6661,7 +6794,7 @@ var JinjaIfBranchView = class {
6661
6794
  return target != null && this.headerContainer.contains(target);
6662
6795
  }
6663
6796
  ignoreMutation(mutation) {
6664
- return this.headerContainer.contains(mutation.target);
6797
+ return mutation.target === this.dom || this.headerContainer.contains(mutation.target);
6665
6798
  }
6666
6799
  destroy() {
6667
6800
  if (this._onSiblingsChanged) {