@sendbird/actionbook-core 0.10.2 → 0.10.3

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.
@@ -346,6 +346,8 @@ declare function DocumentTreeView({ doc, className, onNavigate }: DocumentTreeVi
346
346
  * get clipped by overflow:hidden ancestors.
347
347
  */
348
348
 
349
+ /** Custom event name for triggering the insert-link dialog from outside. */
350
+ declare const INSERT_LINK_EVENT = "ab-insert-link";
349
351
  interface FloatingMenuProps {
350
352
  view: EditorView | null;
351
353
  editorState: EditorState | null;
@@ -432,4 +434,4 @@ declare function astNodesToJSONContent(nodes: (InlineNode | BlockNode)[]): JSONC
432
434
  */
433
435
  declare function hasInvalidJinjaConditions(state: EditorState): boolean;
434
436
 
435
- export { type ActionbookPlugin, ActionbookRenderer, type ActionbookRendererProps, DocumentTreeView, type DocumentTreeViewProps, EditorShell, type EditorShellProps, type EditorViewConfig, type EditorViewHandle, FloatingMenu, type FloatingMenuProps, type InlineSuggestContext, type InlineSuggestProvider, type InlineSuggestState, JUMP_POINT_ADJACENT_SPEC, JinjaTreeView, type JinjaTreeViewProps, type NodeViewFactory, type ReactNodeViewOptions, type ReactNodeViewProps, type SlashCommandItem, SlashCommandMenu, type SlashCommandMenuProps, type SlashCommandState, actionbookSchema, astNodesToJSONContent, convertBlock, convertInline, createDragHandlePlugin, createHistoryPlugin, createInlineSuggestPlugin, createInlineToolTagNodeViewPlugin, createInputRulesPlugin, createJinjaDecorationPlugin, createJinjaIfBlockPlugin, createJumpPointAdjacentPlugin, createJumpPointNodeViewPlugin, createJumpPointValidationPlugin, createKeymapPlugin, createLinkPlugin, createMarkdownClipboardPlugin, createNoteBlockPlugin, createPlaceholderPlugin, createPluginArray, createReactNodeView, createSlashCommandPlugin, createTodoNodeViewPlugin, hasBrokenAnchorRefs, hasDuplicateJumpPoints, hasInvalidJinjaConditions, inlineSuggestKey, slashCommandKey, toProseMirrorJSON, useEditorView };
437
+ export { type ActionbookPlugin, ActionbookRenderer, type ActionbookRendererProps, DocumentTreeView, type DocumentTreeViewProps, EditorShell, type EditorShellProps, type EditorViewConfig, type EditorViewHandle, FloatingMenu, type FloatingMenuProps, INSERT_LINK_EVENT, type InlineSuggestContext, type InlineSuggestProvider, type InlineSuggestState, JUMP_POINT_ADJACENT_SPEC, JinjaTreeView, type JinjaTreeViewProps, type NodeViewFactory, type ReactNodeViewOptions, type ReactNodeViewProps, type SlashCommandItem, SlashCommandMenu, type SlashCommandMenuProps, type SlashCommandState, actionbookSchema, astNodesToJSONContent, convertBlock, convertInline, createDragHandlePlugin, createHistoryPlugin, createInlineSuggestPlugin, createInlineToolTagNodeViewPlugin, createInputRulesPlugin, createJinjaDecorationPlugin, createJinjaIfBlockPlugin, createJumpPointAdjacentPlugin, createJumpPointNodeViewPlugin, createJumpPointValidationPlugin, createKeymapPlugin, createLinkPlugin, createMarkdownClipboardPlugin, createNoteBlockPlugin, createPlaceholderPlugin, createPluginArray, createReactNodeView, createSlashCommandPlugin, createTodoNodeViewPlugin, hasBrokenAnchorRefs, hasDuplicateJumpPoints, hasInvalidJinjaConditions, inlineSuggestKey, slashCommandKey, toProseMirrorJSON, useEditorView };
package/dist/ui/index.js CHANGED
@@ -6430,16 +6430,18 @@ var JINJA_STYLES = `
6430
6430
  letter-spacing: -0.3px;
6431
6431
  }
6432
6432
 
6433
- .jinja-branch-condition-invalid {
6434
- text-decoration: wavy underline #D9352C;
6435
- text-underline-offset: 3px;
6433
+ .jinja-branch-header-invalid {
6434
+ border: 1px solid #D9352C;
6435
+ border-radius: 4px;
6436
6436
  }
6437
6437
 
6438
- .jinja-condition-error-icon {
6438
+ .jinja-condition-error {
6439
+ display: flex;
6440
+ align-items: center;
6441
+ padding: 4px 0 4px 52px;
6439
6442
  color: #D9352C;
6440
- margin-left: 4px;
6441
6443
  font-size: 12px;
6442
- flex-shrink: 0;
6444
+ line-height: 16px;
6443
6445
  }
6444
6446
 
6445
6447
  .jinja-token-variable {
@@ -6827,7 +6829,8 @@ function ConditionDisplay({
6827
6829
  condition,
6828
6830
  editable = true,
6829
6831
  onConditionChange,
6830
- onBackspaceEmpty
6832
+ onBackspaceEmpty,
6833
+ onConditionBlur
6831
6834
  }) {
6832
6835
  const [isEditing, setIsEditing] = useState3(false);
6833
6836
  const [draftValue, setDraftValue] = useState3(condition);
@@ -6855,6 +6858,7 @@ function ConditionDisplay({
6855
6858
  }
6856
6859
  const commit = () => {
6857
6860
  setIsEditing(false);
6861
+ onConditionBlur?.();
6858
6862
  if (draftValue !== condition) {
6859
6863
  onConditionChange(draftValue);
6860
6864
  }
@@ -6890,14 +6894,11 @@ function ConditionDisplay({
6890
6894
  }
6891
6895
  );
6892
6896
  }
6893
- const validation = condition.length > 0 ? validateCondition(condition) : null;
6894
- const isInvalid = validation != null && !validation.valid;
6895
6897
  return /* @__PURE__ */ jsx6(
6896
6898
  "button",
6897
6899
  {
6898
6900
  type: "button",
6899
- className: `jinja-branch-condition${isInvalid ? " jinja-branch-condition-invalid" : ""}`,
6900
- title: isInvalid ? validation.error : void 0,
6901
+ className: "jinja-branch-condition",
6901
6902
  onMouseDown: (event) => event.preventDefault(),
6902
6903
  onClick: () => {
6903
6904
  if (editable) {
@@ -6905,10 +6906,7 @@ function ConditionDisplay({
6905
6906
  setIsEditing(true);
6906
6907
  }
6907
6908
  },
6908
- children: condition.length > 0 ? /* @__PURE__ */ jsxs5(Fragment2, { children: [
6909
- renderCondition(condition),
6910
- isInvalid && /* @__PURE__ */ jsx6("span", { className: "jinja-condition-error-icon", children: "\u26A0" })
6911
- ] }) : /* @__PURE__ */ jsx6("span", { className: "jinja-condition-placeholder", children: CONDITION_PLACEHOLDER })
6909
+ children: condition.length > 0 ? renderCondition(condition) : /* @__PURE__ */ jsx6("span", { className: "jinja-condition-placeholder", children: CONDITION_PLACEHOLDER })
6912
6910
  }
6913
6911
  );
6914
6912
  }
@@ -7002,8 +7000,17 @@ function JinjaBranchHeader({
7002
7000
  }
7003
7001
  const canOpenFooterMenu = editable && isLastBranch && branchType !== "else";
7004
7002
  const isMenuOpen = (source) => menuSource === source && menuItems.length > 0;
7003
+ const [conditionTouched, setConditionTouched] = useState3(false);
7004
+ const conditionError = (() => {
7005
+ if (branchType === "else") return null;
7006
+ if (condition.length === 0) {
7007
+ return conditionTouched ? "This field is required." : null;
7008
+ }
7009
+ const result = validateCondition(condition);
7010
+ return result.valid ? null : result.error || "Invalid condition";
7011
+ })();
7005
7012
  return /* @__PURE__ */ jsxs5(Fragment2, { children: [
7006
- /* @__PURE__ */ jsxs5("div", { className: "jinja-branch-header", children: [
7013
+ /* @__PURE__ */ jsxs5("div", { className: `jinja-branch-header${conditionError ? " jinja-branch-header-invalid" : ""}`, children: [
7007
7014
  /* @__PURE__ */ jsx6("span", { className: `jinja-branch-badge jinja-branch-badge-${branchType}`, children: branchType === "elif" ? "ELSE IF" : branchType.toUpperCase() }),
7008
7015
  /* @__PURE__ */ jsx6(
7009
7016
  ConditionDisplay,
@@ -7012,7 +7019,8 @@ function JinjaBranchHeader({
7012
7019
  condition,
7013
7020
  editable,
7014
7021
  onConditionChange,
7015
- onBackspaceEmpty: onDelete
7022
+ onBackspaceEmpty: onDelete,
7023
+ onConditionBlur: () => setConditionTouched(true)
7016
7024
  }
7017
7025
  ),
7018
7026
  editable ? /* @__PURE__ */ jsxs5("div", { className: "jinja-branch-actions", ref: kebabRef, children: [
@@ -7050,6 +7058,7 @@ function JinjaBranchHeader({
7050
7058
  ) : null
7051
7059
  ] }) : null
7052
7060
  ] }),
7061
+ conditionError && /* @__PURE__ */ jsx6("div", { className: "jinja-condition-error", children: conditionError }),
7053
7062
  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: [
7054
7063
  /* @__PURE__ */ jsx6(
7055
7064
  "button",
@@ -7359,17 +7368,17 @@ function createLinkEditPlugin() {
7359
7368
  if (match) {
7360
7369
  const [, label, href, title] = match;
7361
7370
  const linkMarkType = newState.schema.marks.link;
7362
- if (linkMarkType && href) {
7371
+ if (!label) {
7372
+ reconvertTr.delete(safeFrom, safeTo);
7373
+ } else if (linkMarkType && href) {
7363
7374
  const attrs = title ? { href, title: title.trim() } : { href };
7364
7375
  reconvertTr.delete(safeFrom, safeTo);
7365
- if (label.length > 0) {
7366
- reconvertTr.insertText(label, safeFrom);
7367
- reconvertTr.addMark(
7368
- safeFrom,
7369
- safeFrom + label.length,
7370
- linkMarkType.create(attrs)
7371
- );
7372
- }
7376
+ reconvertTr.insertText(label, safeFrom);
7377
+ reconvertTr.addMark(
7378
+ safeFrom,
7379
+ safeFrom + label.length,
7380
+ linkMarkType.create(attrs)
7381
+ );
7373
7382
  }
7374
7383
  }
7375
7384
  }
@@ -7383,12 +7392,17 @@ function createLinkInputRule() {
7383
7392
  (state, match, start, end) => {
7384
7393
  const [, label, href, title] = match;
7385
7394
  const linkMarkType = state.schema.marks.link;
7386
- if (!linkMarkType || !href) return null;
7387
- const displayText = label || href;
7388
- const attrs = title ? { href, title: title.trim() } : { href };
7395
+ if (!linkMarkType) return null;
7389
7396
  const { tr } = state;
7390
- tr.replaceWith(start, end, state.schema.text(displayText));
7391
- tr.addMark(start, start + displayText.length, linkMarkType.create(attrs));
7397
+ if (!label) {
7398
+ tr.delete(start, end);
7399
+ tr.setMeta(linkEditKey, null);
7400
+ return tr;
7401
+ }
7402
+ if (!href) return null;
7403
+ const attrs = title ? { href, title: title.trim() } : { href };
7404
+ tr.replaceWith(start, end, state.schema.text(label));
7405
+ tr.addMark(start, start + label.length, linkMarkType.create(attrs));
7392
7406
  tr.setMeta(linkEditKey, null);
7393
7407
  return tr;
7394
7408
  }
@@ -8455,14 +8469,12 @@ function injectScrollbarStyle() {
8455
8469
  const style = document.createElement("style");
8456
8470
  style.id = SCROLLBAR_STYLE_ID;
8457
8471
  style.textContent = `
8458
- .ab-slash-menu::-webkit-scrollbar { width: 6px; }
8459
- .ab-slash-menu::-webkit-scrollbar-track { background: transparent; }
8460
- .ab-slash-menu::-webkit-scrollbar-thumb { background: #c4c4c4; border-radius: 3px; }
8461
- .ab-slash-menu::-webkit-scrollbar-thumb:hover { background: #999; }
8472
+ .ab-slash-menu::-webkit-scrollbar { display: none; }
8473
+ .ab-slash-menu { scrollbar-width: none; }
8462
8474
  `;
8463
8475
  document.head.appendChild(style);
8464
8476
  }
8465
- var POPUP_SHADOW = "0 8px 10px rgba(13,13,13,0.12), 0 3px 14px rgba(13,13,13,0.08), 0 3px 5px rgba(13,13,13,0.04)";
8477
+ var POPUP_SHADOW = "0 0 0 1px #CCCCCC, 0 4px 16px rgba(0, 0, 0, 0.12)";
8466
8478
  var BTN_RESET = {
8467
8479
  border: "none",
8468
8480
  padding: 0,
@@ -8544,12 +8556,10 @@ function SlashCommandMenu({ view, editorState, items }) {
8544
8556
  width: MENU_WIDTH,
8545
8557
  maxHeight: MAX_MENU_H,
8546
8558
  overflowY: "auto",
8547
- scrollbarWidth: "thin",
8548
- scrollbarColor: "#c4c4c4 transparent",
8549
8559
  background: "#fff",
8550
- borderRadius: 4,
8560
+ borderRadius: 8,
8551
8561
  boxShadow: POPUP_SHADOW,
8552
- padding: "8px 0",
8562
+ padding: "4px",
8553
8563
  zIndex: 1100,
8554
8564
  animation: "ab-float-in 0.12s ease"
8555
8565
  },
@@ -8615,8 +8625,8 @@ function SlashMenuItem({ item, index, selected, onMouseEnter, onMouseDown }) {
8615
8625
  display: "flex",
8616
8626
  alignItems: "center",
8617
8627
  gap: 12,
8618
- padding: "6px 16px",
8619
- background: selected ? "rgba(13,13,13,0.04)" : "transparent",
8628
+ padding: "6px 8px",
8629
+ background: selected ? "rgba(0, 0, 0, 0.04)" : "transparent",
8620
8630
  transition: "background 0.08s"
8621
8631
  },
8622
8632
  onMouseEnter,
@@ -9037,7 +9047,7 @@ function getSelectionDOMRect() {
9037
9047
  if (rect.width === 0 && rect.height === 0) return null;
9038
9048
  return rect;
9039
9049
  }
9040
- var POPUP_SHADOW2 = "0 0 0 1px rgba(0,0,0,0.07), 0 4px 20px rgba(0,0,0,0.11), 0 1px 4px rgba(0,0,0,0.05)";
9050
+ var POPUP_SHADOW2 = "0 0 0 1px #CCCCCC, 0 4px 16px rgba(0, 0, 0, 0.12)";
9041
9051
  var BTN_RESET2 = {
9042
9052
  border: "none",
9043
9053
  padding: 0,
@@ -9069,8 +9079,8 @@ function TBtn({ children, active, title, onMouseDown, style }) {
9069
9079
  borderRadius: 6,
9070
9080
  fontSize: 13,
9071
9081
  fontWeight: 600,
9072
- color: active ? "#6366f1" : "#3f3f46",
9073
- background: active ? "rgba(99,102,241,0.1)" : hover ? "rgba(0,0,0,0.05)" : "transparent",
9082
+ color: active ? "#6210CC" : "#0D0D0D",
9083
+ background: active ? "rgba(98,16,204,0.08)" : hover ? "rgba(0,0,0,0.05)" : "transparent",
9074
9084
  transition: "background 0.1s, color 0.1s",
9075
9085
  ...style
9076
9086
  },
@@ -9164,8 +9174,8 @@ function BlockTypeDropdown({ view, state, label }) {
9164
9174
  borderRadius: 6,
9165
9175
  fontSize: 11,
9166
9176
  fontWeight: 600,
9167
- color: open ? "#6366f1" : "#3f3f46",
9168
- background: open ? "rgba(99,102,241,0.1)" : hover ? "rgba(0,0,0,0.05)" : "transparent",
9177
+ color: open ? "#6210CC" : "#0D0D0D",
9178
+ background: open ? "rgba(98,16,204,0.08)" : hover ? "rgba(0,0,0,0.04)" : "transparent",
9169
9179
  transition: "background 0.1s, color 0.1s",
9170
9180
  whiteSpace: "nowrap"
9171
9181
  },
@@ -9186,9 +9196,9 @@ function BlockTypeDropdown({ view, state, label }) {
9186
9196
  left: btnRect.left,
9187
9197
  top: btnRect.bottom + 4,
9188
9198
  background: "#fff",
9189
- borderRadius: 10,
9199
+ borderRadius: 8,
9190
9200
  boxShadow: POPUP_SHADOW2,
9191
- padding: 6,
9201
+ padding: 4,
9192
9202
  minWidth: 168,
9193
9203
  animation: "ab-float-in 0.12s ease"
9194
9204
  },
@@ -9219,16 +9229,16 @@ function DropdownItem({ item, onRun }) {
9219
9229
  gap: 10,
9220
9230
  width: "100%",
9221
9231
  padding: "6px 8px",
9222
- borderRadius: 6,
9232
+ borderRadius: 4,
9223
9233
  textAlign: "left",
9224
9234
  fontSize: 13,
9225
- color: item.active ? "#6366f1" : "#3f3f46",
9235
+ color: item.active ? "#6210CC" : "#0D0D0D",
9226
9236
  fontWeight: item.active ? 600 : 400,
9227
9237
  background: hover ? "rgba(0,0,0,0.04)" : "transparent",
9228
9238
  transition: "background 0.1s"
9229
9239
  },
9230
9240
  children: [
9231
- /* @__PURE__ */ jsx10("span", { style: { width: 24, flexShrink: 0, textAlign: "center", fontWeight: 700, fontSize: 12, fontFamily: "monospace", color: "#6366f1" }, children: item.shortLabel }),
9241
+ /* @__PURE__ */ jsx10("span", { style: { width: 24, flexShrink: 0, textAlign: "center", fontWeight: 700, fontSize: 12, fontFamily: "monospace", color: "#6210CC" }, children: item.shortLabel }),
9232
9242
  item.label
9233
9243
  ]
9234
9244
  }
@@ -9305,7 +9315,7 @@ function SelectionToolbar({ view, state, selectionRect }) {
9305
9315
  gap: 2,
9306
9316
  padding: "0 6px",
9307
9317
  background: "#fff",
9308
- borderRadius: 10,
9318
+ borderRadius: 8,
9309
9319
  boxShadow: POPUP_SHADOW2,
9310
9320
  userSelect: "none",
9311
9321
  animation: "ab-float-in 0.12s ease"
@@ -9353,7 +9363,7 @@ function SelectionToolbar({ view, state, selectionRect }) {
9353
9363
  e.preventDefault();
9354
9364
  applyLink();
9355
9365
  },
9356
- style: { color: "#6366f1", width: 24, fontSize: 14 },
9366
+ style: { color: "#6210CC", width: 24, fontSize: 14 },
9357
9367
  children: "\u21B5"
9358
9368
  }
9359
9369
  ),
@@ -9602,8 +9612,8 @@ function LinkEditDialog({ view, link: link2, onClose }) {
9602
9612
  top = Math.min(anchorBottom + 12, window.innerHeight - estimatedDialogH - VPORT_MARGIN2);
9603
9613
  }
9604
9614
  const finalHref = normalizeLinkHref(hrefValue);
9605
- const finalText = textValue.trim() ? textValue : finalHref;
9606
- const canSave = Boolean(finalHref) && (finalHref !== link2.href || finalText !== link2.text);
9615
+ const finalText = textValue.trim() ? textValue : "";
9616
+ const canSave = !textValue.trim() || Boolean(finalHref) && (finalHref !== link2.href || finalText !== link2.text);
9607
9617
  const currentLink = () => {
9608
9618
  const activeLink = getLinkAtCursor(view.state);
9609
9619
  if (activeLink && activeLink.from === link2.from && activeLink.to === link2.to) {
@@ -9614,7 +9624,14 @@ function LinkEditDialog({ view, link: link2, onClose }) {
9614
9624
  const saveLink = () => {
9615
9625
  const activeLink = currentLink();
9616
9626
  const nextHref = normalizeLinkHref(hrefValue);
9617
- const nextText = textValue.trim() ? textValue : nextHref;
9627
+ if (!textValue.trim()) {
9628
+ const tr2 = view.state.tr.delete(activeLink.from, activeLink.to);
9629
+ view.dispatch(tr2);
9630
+ onClose();
9631
+ view.focus();
9632
+ return;
9633
+ }
9634
+ const nextText = textValue;
9618
9635
  if (!nextHref) return;
9619
9636
  if (nextHref === activeLink.href && nextText === activeLink.text) return;
9620
9637
  const cursorOffset = Math.max(0, view.state.selection.from - activeLink.from);
@@ -9674,8 +9691,8 @@ function LinkEditDialog({ view, link: link2, onClose }) {
9674
9691
  gap: 16,
9675
9692
  padding: 16,
9676
9693
  background: "#FFFFFF",
9677
- borderRadius: 4,
9678
- boxShadow: "0px 8px 10px rgba(13,13,13,0.12), 0px 3px 14px rgba(13,13,13,0.08), 0px 3px 5px rgba(13,13,13,0.04)",
9694
+ borderRadius: 8,
9695
+ boxShadow: "0 0 0 1px #CCCCCC, 0 4px 16px rgba(0, 0, 0, 0.12)",
9679
9696
  boxSizing: "border-box",
9680
9697
  animation: "ab-float-in 0.12s ease"
9681
9698
  },
@@ -9843,6 +9860,189 @@ function LinkEditDialog({ view, link: link2, onClose }) {
9843
9860
  document.body
9844
9861
  );
9845
9862
  }
9863
+ var INSERT_LINK_EVENT = "ab-insert-link";
9864
+ function LinkInsertDialog({ view, cursorPos, onClose }) {
9865
+ const [textValue, setTextValue] = useState7("");
9866
+ const [hrefValue, setHrefValue] = useState7("");
9867
+ const textInputRef = useRef4(null);
9868
+ useEffect4(() => {
9869
+ setTimeout(() => textInputRef.current?.focus(), 0);
9870
+ }, []);
9871
+ useEffect4(() => {
9872
+ const onDown = (e) => {
9873
+ if (!e.target.closest(`[${FLOAT_ATTR}]`)) {
9874
+ onClose();
9875
+ }
9876
+ };
9877
+ document.addEventListener("mousedown", onDown, true);
9878
+ return () => document.removeEventListener("mousedown", onDown, true);
9879
+ }, [onClose]);
9880
+ let coords;
9881
+ try {
9882
+ coords = view.coordsAtPos(cursorPos);
9883
+ } catch {
9884
+ onClose();
9885
+ return null;
9886
+ }
9887
+ const dialogW = 280;
9888
+ const left = Math.max(
9889
+ VPORT_MARGIN2,
9890
+ Math.min(coords.left - dialogW / 2, window.innerWidth - dialogW - VPORT_MARGIN2)
9891
+ );
9892
+ const top = Math.min(coords.bottom + 8, window.innerHeight - 220 - VPORT_MARGIN2);
9893
+ const finalHref = normalizeLinkHref(hrefValue);
9894
+ const canSave = Boolean(finalHref);
9895
+ const saveLink = () => {
9896
+ if (!finalHref) return;
9897
+ const displayText = textValue.trim() || finalHref;
9898
+ const tr = view.state.tr;
9899
+ const linkMarkType = view.state.schema.marks.link;
9900
+ if (!linkMarkType) return;
9901
+ tr.insertText(displayText, cursorPos);
9902
+ tr.addMark(cursorPos, cursorPos + displayText.length, linkMarkType.create({ href: finalHref }));
9903
+ view.dispatch(tr);
9904
+ onClose();
9905
+ view.focus();
9906
+ };
9907
+ const handleKeyDown = (e) => {
9908
+ if (e.key === "Escape") {
9909
+ e.preventDefault();
9910
+ onClose();
9911
+ view.focus();
9912
+ }
9913
+ if (e.key === "Enter") {
9914
+ e.preventDefault();
9915
+ saveLink();
9916
+ }
9917
+ };
9918
+ return createPortal2(
9919
+ /* @__PURE__ */ jsxs9(
9920
+ "div",
9921
+ {
9922
+ ...{ [FLOAT_ATTR]: "" },
9923
+ style: {
9924
+ position: "fixed",
9925
+ left,
9926
+ top,
9927
+ zIndex: 1001,
9928
+ width: dialogW,
9929
+ display: "flex",
9930
+ flexDirection: "column",
9931
+ gap: 16,
9932
+ padding: 16,
9933
+ background: "#FFFFFF",
9934
+ borderRadius: 8,
9935
+ boxShadow: POPUP_SHADOW2,
9936
+ boxSizing: "border-box",
9937
+ animation: "ab-float-in 0.12s ease"
9938
+ },
9939
+ children: [
9940
+ /* @__PURE__ */ jsxs9("div", { ...{ [FLOAT_ATTR]: "" }, style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
9941
+ /* @__PURE__ */ jsxs9("div", { ...{ [FLOAT_ATTR]: "" }, style: { fontSize: 12, lineHeight: "16px", fontWeight: 600, color: "#0D0D0D" }, children: [
9942
+ "Text ",
9943
+ /* @__PURE__ */ jsx10("span", { style: { color: "#858585" }, children: "(optional)" })
9944
+ ] }),
9945
+ /* @__PURE__ */ jsx10(
9946
+ "input",
9947
+ {
9948
+ ref: textInputRef,
9949
+ ...{ [FLOAT_ATTR]: "" },
9950
+ value: textValue,
9951
+ placeholder: "",
9952
+ onChange: (e) => setTextValue(e.target.value),
9953
+ onKeyDown: handleKeyDown,
9954
+ style: {
9955
+ height: 32,
9956
+ border: "1px solid #CCCCCC",
9957
+ borderRadius: 4,
9958
+ padding: "0 16px",
9959
+ fontSize: 14,
9960
+ color: "#0D0D0D",
9961
+ outline: "none",
9962
+ boxSizing: "border-box"
9963
+ }
9964
+ }
9965
+ )
9966
+ ] }),
9967
+ /* @__PURE__ */ jsxs9("div", { ...{ [FLOAT_ATTR]: "" }, style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
9968
+ /* @__PURE__ */ jsx10("div", { ...{ [FLOAT_ATTR]: "" }, style: { fontSize: 12, lineHeight: "16px", fontWeight: 600, color: "#0D0D0D" }, children: "Link" }),
9969
+ /* @__PURE__ */ jsx10(
9970
+ "input",
9971
+ {
9972
+ ...{ [FLOAT_ATTR]: "" },
9973
+ value: hrefValue,
9974
+ onChange: (e) => setHrefValue(e.target.value),
9975
+ onKeyDown: handleKeyDown,
9976
+ style: {
9977
+ height: 32,
9978
+ border: "1px solid #CCCCCC",
9979
+ borderRadius: 4,
9980
+ padding: "0 16px",
9981
+ fontSize: 14,
9982
+ color: "#0D0D0D",
9983
+ outline: "none",
9984
+ boxSizing: "border-box"
9985
+ }
9986
+ }
9987
+ )
9988
+ ] }),
9989
+ /* @__PURE__ */ jsxs9("div", { ...{ [FLOAT_ATTR]: "" }, style: { display: "flex", alignItems: "center", justifyContent: "flex-end", gap: 8 }, children: [
9990
+ /* @__PURE__ */ jsx10(
9991
+ "button",
9992
+ {
9993
+ type: "button",
9994
+ ...{ [FLOAT_ATTR]: "" },
9995
+ onMouseDown: (e) => {
9996
+ e.preventDefault();
9997
+ onClose();
9998
+ view.focus();
9999
+ },
10000
+ style: {
10001
+ ...BTN_RESET2,
10002
+ height: 32,
10003
+ padding: "0 13px",
10004
+ border: "1px solid #CCCCCC",
10005
+ borderRadius: 4,
10006
+ fontSize: 14,
10007
+ lineHeight: "20px",
10008
+ fontWeight: 600,
10009
+ color: "#0D0D0D"
10010
+ },
10011
+ children: "Cancel"
10012
+ }
10013
+ ),
10014
+ /* @__PURE__ */ jsx10(
10015
+ "button",
10016
+ {
10017
+ type: "button",
10018
+ disabled: !canSave,
10019
+ ...{ [FLOAT_ATTR]: "" },
10020
+ onMouseDown: (e) => {
10021
+ e.preventDefault();
10022
+ if (canSave) saveLink();
10023
+ },
10024
+ style: {
10025
+ ...BTN_RESET2,
10026
+ height: 32,
10027
+ padding: "0 13px",
10028
+ borderRadius: 4,
10029
+ fontSize: 14,
10030
+ lineHeight: "20px",
10031
+ fontWeight: 600,
10032
+ background: canSave ? "#6210CC" : "#ECECEC",
10033
+ color: canSave ? "#FFFFFF" : "#A6A6A6",
10034
+ cursor: canSave ? "pointer" : "default"
10035
+ },
10036
+ children: "Save"
10037
+ }
10038
+ )
10039
+ ] })
10040
+ ]
10041
+ }
10042
+ ),
10043
+ document.body
10044
+ );
10045
+ }
9846
10046
  var BLOCK_ITEMS = [
9847
10047
  {
9848
10048
  shortLabel: "\xB6",
@@ -9965,12 +10165,12 @@ function EmptyParaHandle({ view, cursorPos }) {
9965
10165
  height: btnSize,
9966
10166
  border: "1px solid rgba(0,0,0,0.1)",
9967
10167
  borderRadius: 5,
9968
- background: menuOpen ? "rgba(99,102,241,0.08)" : "#fff",
10168
+ background: menuOpen ? "rgba(98,16,204,0.08)" : "#fff",
9969
10169
  boxShadow: "0 1px 3px rgba(0,0,0,0.06)",
9970
10170
  display: "flex",
9971
10171
  alignItems: "center",
9972
10172
  justifyContent: "center",
9973
- color: menuOpen ? "#6366f1" : "#9ca3af",
10173
+ color: menuOpen ? "#6210CC" : "#9ca3af",
9974
10174
  fontSize: 16,
9975
10175
  animation: "ab-float-in 0.15s ease",
9976
10176
  transition: "color 0.1s, background 0.1s, border-color 0.1s"
@@ -9988,9 +10188,9 @@ function EmptyParaHandle({ view, cursorPos }) {
9988
10188
  left: menuLeft,
9989
10189
  top: menuTop,
9990
10190
  background: "#fff",
9991
- borderRadius: 10,
10191
+ borderRadius: 8,
9992
10192
  boxShadow: POPUP_SHADOW2,
9993
- padding: 6,
10193
+ padding: 4,
9994
10194
  minWidth: 168,
9995
10195
  animation: "ab-float-in 0.12s ease"
9996
10196
  },
@@ -10034,7 +10234,7 @@ function BlockMenuItem({
10034
10234
  borderRadius: 6,
10035
10235
  textAlign: "left",
10036
10236
  fontSize: 13,
10037
- color: "#3f3f46",
10237
+ color: "#0D0D0D",
10038
10238
  background: hover ? "rgba(0,0,0,0.04)" : "transparent",
10039
10239
  transition: "background 0.1s"
10040
10240
  },
@@ -10049,7 +10249,7 @@ function BlockMenuItem({
10049
10249
  fontWeight: 700,
10050
10250
  fontSize: 12,
10051
10251
  fontFamily: "monospace",
10052
- color: "#6366f1"
10252
+ color: "#6210CC"
10053
10253
  },
10054
10254
  children: item.shortLabel
10055
10255
  }
@@ -10062,8 +10262,19 @@ function BlockMenuItem({
10062
10262
  function FloatingMenu({ view, editorState }) {
10063
10263
  const [showEmptyHandle, setShowEmptyHandle] = useState7(false);
10064
10264
  const [editingLink, setEditingLink] = useState7(null);
10265
+ const [insertLinkPos, setInsertLinkPos] = useState7(null);
10065
10266
  const dwellTimerRef = useRef4(null);
10066
10267
  const lastEmptyPosRef = useRef4(null);
10268
+ useEffect4(() => {
10269
+ const dom = view?.dom;
10270
+ if (!dom) return;
10271
+ const handler = () => {
10272
+ const pos = view.state.selection.from;
10273
+ setInsertLinkPos(pos);
10274
+ };
10275
+ dom.addEventListener(INSERT_LINK_EVENT, handler);
10276
+ return () => dom.removeEventListener(INSERT_LINK_EVENT, handler);
10277
+ }, [view]);
10067
10278
  const [, setScrollTick] = useState7(0);
10068
10279
  useEffect4(() => {
10069
10280
  const editorDom = view?.dom;
@@ -10136,7 +10347,15 @@ function FloatingMenu({ view, editorState }) {
10136
10347
  onClose: () => setEditingLink(null)
10137
10348
  }
10138
10349
  ),
10139
- !hasSelection && !linkAtCursor && showEmptyHandle && emptyPos !== null && /* @__PURE__ */ jsx10(EmptyParaHandle, { view, cursorPos: emptyPos })
10350
+ insertLinkPos !== null && /* @__PURE__ */ jsx10(
10351
+ LinkInsertDialog,
10352
+ {
10353
+ view,
10354
+ cursorPos: insertLinkPos,
10355
+ onClose: () => setInsertLinkPos(null)
10356
+ }
10357
+ ),
10358
+ !hasSelection && !linkAtCursor && !insertLinkPos && showEmptyHandle && emptyPos !== null && /* @__PURE__ */ jsx10(EmptyParaHandle, { view, cursorPos: emptyPos })
10140
10359
  ] }),
10141
10360
  document.body
10142
10361
  );
@@ -10324,6 +10543,7 @@ export {
10324
10543
  DocumentTreeView,
10325
10544
  EditorShell,
10326
10545
  FloatingMenu,
10546
+ INSERT_LINK_EVENT,
10327
10547
  JUMP_POINT_ADJACENT_SPEC,
10328
10548
  JinjaTreeView,
10329
10549
  SlashCommandMenu,