@carlonicora/nextjs-jsonapi 1.109.0 → 1.110.0

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.
Files changed (146) hide show
  1. package/dist/{AssistantMessageInterface-Cs1yb-gF.d.ts → AssistantMessageInterface-BNzf1etU.d.ts} +14 -1
  2. package/dist/{AssistantMessageInterface-DQ3mH5L8.d.mts → AssistantMessageInterface-DrgHDjZ5.d.mts} +14 -1
  3. package/dist/{BlockNoteEditor-3XYBZLWO.js → BlockNoteEditor-7OKW6HHN.js} +19 -20
  4. package/dist/BlockNoteEditor-7OKW6HHN.js.map +1 -0
  5. package/dist/{BlockNoteEditor-EBFZG7AL.mjs → BlockNoteEditor-K7IIWM3S.mjs} +4 -5
  6. package/dist/{BlockNoteEditor-EBFZG7AL.mjs.map → BlockNoteEditor-K7IIWM3S.mjs.map} +1 -1
  7. package/dist/BlockNoteViewer-OPSCTHKJ.mjs +31 -0
  8. package/dist/BlockNoteViewer-OPSCTHKJ.mjs.map +1 -0
  9. package/dist/BlockNoteViewer-UW5VZ5UF.js +31 -0
  10. package/dist/BlockNoteViewer-UW5VZ5UF.js.map +1 -0
  11. package/dist/billing/index.d.mts +41 -41
  12. package/dist/billing/index.d.ts +41 -41
  13. package/dist/billing/index.js +346 -347
  14. package/dist/billing/index.js.map +1 -1
  15. package/dist/billing/index.mjs +3 -4
  16. package/dist/billing/index.mjs.map +1 -1
  17. package/dist/{chunk-7E3O52U5.js → chunk-6XWW67F2.js} +25 -12
  18. package/dist/chunk-6XWW67F2.js.map +1 -0
  19. package/dist/{chunk-UHO3KUUH.js → chunk-AKXUNE3A.js} +977 -850
  20. package/dist/chunk-AKXUNE3A.js.map +1 -0
  21. package/dist/{chunk-UOYIWJEJ.mjs → chunk-CWVYU4YZ.mjs} +18 -5
  22. package/dist/{chunk-UOYIWJEJ.mjs.map → chunk-CWVYU4YZ.mjs.map} +1 -1
  23. package/dist/{chunk-CRTVAQEK.mjs → chunk-TXVVZLUQ.mjs} +1388 -1261
  24. package/dist/chunk-TXVVZLUQ.mjs.map +1 -0
  25. package/dist/{chunk-CFI4WZ5R.js → chunk-U2HR57MY.js} +111 -5
  26. package/dist/chunk-U2HR57MY.js.map +1 -0
  27. package/dist/chunk-WPAQRB5Q.mjs +7 -0
  28. package/dist/chunk-WPAQRB5Q.mjs.map +1 -0
  29. package/dist/chunk-YBZVWLPH.js +7 -0
  30. package/dist/chunk-YBZVWLPH.js.map +1 -0
  31. package/dist/{chunk-MSNNAHDB.mjs → chunk-ZYPNVEHB.mjs} +112 -6
  32. package/dist/{chunk-MSNNAHDB.mjs.map → chunk-ZYPNVEHB.mjs.map} +1 -1
  33. package/dist/client/index.d.mts +3 -4
  34. package/dist/client/index.d.ts +3 -4
  35. package/dist/client/index.js +4 -5
  36. package/dist/client/index.js.map +1 -1
  37. package/dist/client/index.mjs +3 -4
  38. package/dist/components/index.d.mts +418 -415
  39. package/dist/components/index.d.ts +418 -415
  40. package/dist/components/index.js +6 -5
  41. package/dist/components/index.js.map +1 -1
  42. package/dist/components/index.mjs +5 -4
  43. package/dist/{config-CN23v3eJ.d.ts → config-BrkU_Ynz.d.ts} +2 -2
  44. package/dist/{config-gh88Qn4h.d.mts → config-snd2ToEB.d.mts} +2 -2
  45. package/dist/contexts/index.d.mts +15 -15
  46. package/dist/contexts/index.d.ts +15 -15
  47. package/dist/contexts/index.js +4 -5
  48. package/dist/contexts/index.js.map +1 -1
  49. package/dist/contexts/index.mjs +3 -4
  50. package/dist/core/index.d.mts +35 -4
  51. package/dist/core/index.d.ts +35 -4
  52. package/dist/core/index.js +2 -2
  53. package/dist/core/index.mjs +1 -1
  54. package/dist/features/help/index.d.mts +25 -66
  55. package/dist/features/help/index.d.ts +25 -66
  56. package/dist/features/help/index.js +114 -124
  57. package/dist/features/help/index.js.map +1 -1
  58. package/dist/features/help/index.mjs +95 -105
  59. package/dist/features/help/index.mjs.map +1 -1
  60. package/dist/features/help/server.d.mts +27 -65
  61. package/dist/features/help/server.d.ts +27 -65
  62. package/dist/features/help/server.js +4 -119
  63. package/dist/features/help/server.js.map +1 -1
  64. package/dist/features/help/server.mjs +4 -119
  65. package/dist/features/help/server.mjs.map +1 -1
  66. package/dist/help-content-config.interface-C5ESIod9.d.mts +13 -0
  67. package/dist/help-content-config.interface-C5ESIod9.d.ts +13 -0
  68. package/dist/index.d.mts +3 -3
  69. package/dist/index.d.ts +3 -3
  70. package/dist/index.js +3 -4
  71. package/dist/index.js.map +1 -1
  72. package/dist/index.mjs +2 -3
  73. package/dist/server/index.js +3 -3
  74. package/dist/server/index.mjs +1 -1
  75. package/dist/testing/index.d.mts +1 -2
  76. package/dist/testing/index.d.ts +1 -2
  77. package/package.json +1 -6
  78. package/src/client/config.ts +1 -1
  79. package/src/components/index.ts +1 -0
  80. package/src/components/viewers/BlockNoteViewer.tsx +27 -0
  81. package/src/components/viewers/BlockNoteViewerContainer.tsx +10 -0
  82. package/src/core/registry/helpStore.ts +2 -19
  83. package/src/features/assistant-message/components/parts/MessageSourcesContainer.tsx +4 -0
  84. package/src/features/assistant-message/components/parts/tabs/ContentsTab.tsx +5 -5
  85. package/src/features/assistant-message/components/parts/tabs/ReferencesTab.tsx +3 -2
  86. package/src/features/help/components/HelpArticleBody.tsx +27 -19
  87. package/src/features/help/components/HelpHint.tsx +20 -11
  88. package/src/features/help/components/HelpSearchResultRow.tsx +16 -6
  89. package/src/features/help/components/HelpSideNav.tsx +54 -19
  90. package/src/features/help/components/__tests__/HelpAskAi.spec.tsx +1 -1
  91. package/src/features/help/components/__tests__/HelpHint.spec.tsx +17 -17
  92. package/src/features/help/components/__tests__/HelpSearchResultRow.spec.tsx +18 -19
  93. package/src/features/help/components/__tests__/HelpSideNav.spec.tsx +20 -22
  94. package/src/features/help/contexts/HelpContext.spec.tsx +1 -3
  95. package/src/features/help/index.ts +3 -6
  96. package/src/features/help/interfaces/help-content-config.interface.ts +0 -5
  97. package/src/features/help/server-entry.ts +6 -15
  98. package/src/features/help/types/help-article.types.ts +2 -4
  99. package/src/features/how-to/HowToModule.ts +14 -1
  100. package/src/features/how-to/components/forms/HowToEditor.tsx +108 -4
  101. package/src/features/how-to/data/HowTo.spec.ts +43 -0
  102. package/src/features/how-to/data/HowTo.ts +47 -4
  103. package/src/features/how-to/data/HowToInterface.ts +14 -1
  104. package/src/features/how-to/data/HowToService.ts +61 -0
  105. package/dist/BlockNoteEditor-3XYBZLWO.js.map +0 -1
  106. package/dist/chunk-3J7RQBF3.js +0 -123
  107. package/dist/chunk-3J7RQBF3.js.map +0 -1
  108. package/dist/chunk-7E3O52U5.js.map +0 -1
  109. package/dist/chunk-CFI4WZ5R.js.map +0 -1
  110. package/dist/chunk-CQID6RCF.mjs +0 -38
  111. package/dist/chunk-CQID6RCF.mjs.map +0 -1
  112. package/dist/chunk-CRTVAQEK.mjs.map +0 -1
  113. package/dist/chunk-MZTKPPET.mjs +0 -123
  114. package/dist/chunk-MZTKPPET.mjs.map +0 -1
  115. package/dist/chunk-UHO3KUUH.js.map +0 -1
  116. package/dist/chunk-YQQHAFBS.js +0 -38
  117. package/dist/chunk-YQQHAFBS.js.map +0 -1
  118. package/dist/features/help/server/createHelpAssetRouteHandler.d.mts +0 -11
  119. package/dist/features/help/server/createHelpAssetRouteHandler.d.ts +0 -11
  120. package/dist/features/help/server/createHelpAssetRouteHandler.js +0 -43
  121. package/dist/features/help/server/createHelpAssetRouteHandler.js.map +0 -1
  122. package/dist/features/help/server/createHelpAssetRouteHandler.mjs +0 -43
  123. package/dist/features/help/server/createHelpAssetRouteHandler.mjs.map +0 -1
  124. package/dist/help-content-config.interface-B9L02u9i.d.mts +0 -50
  125. package/dist/help-content-config.interface-B9L02u9i.d.ts +0 -50
  126. package/src/features/help/components/mdx/Callout.tsx +0 -21
  127. package/src/features/help/components/mdx/EntityRef.tsx +0 -18
  128. package/src/features/help/components/mdx/KeyBinding.tsx +0 -6
  129. package/src/features/help/components/mdx/Related.tsx +0 -33
  130. package/src/features/help/components/mdx/Screenshot.tsx +0 -9
  131. package/src/features/help/components/mdx/Steps.tsx +0 -21
  132. package/src/features/help/components/mdx/Video.tsx +0 -8
  133. package/src/features/help/components/mdx/mdx-server-components.ts +0 -23
  134. package/src/features/help/components/mdx/mdxComponents.ts +0 -9
  135. package/src/features/help/hooks/useHelpArticle.ts +0 -7
  136. package/src/features/help/hooks/useHelpManifest.ts +0 -5
  137. package/src/features/help/server/__tests__/createHelpAssetRouteHandler.spec.ts +0 -43
  138. package/src/features/help/server/createHelpAssetRouteHandler.ts +0 -35
  139. package/src/features/help/server/generateHelpArticleMetadata.ts +0 -18
  140. package/src/features/help/server/generateHelpArticleStaticParams.ts +0 -7
  141. package/src/features/help/server/generateHelpModeStaticParams.ts +0 -5
  142. package/src/features/help/server/getHelpContent.ts +0 -17
  143. package/src/features/help/server/index.ts +0 -8
  144. package/src/features/help/server/serializeHelpArticle.tsx +0 -46
  145. package/src/features/help/utils/__tests__/helpNavigation.spec.ts +0 -70
  146. package/src/features/help/utils/helpNavigation.ts +0 -29
@@ -9,11 +9,24 @@ type BreadcrumbItemData = {
9
9
  type HowToInput = ContentInput & {
10
10
  description?: any;
11
11
  pages?: string | undefined | null;
12
+ howToType?: string;
13
+ slug?: string;
14
+ order?: number;
15
+ summary?: string;
16
+ tags?: string[];
17
+ contextualKeys?: string[];
18
+ draft?: boolean;
12
19
  };
13
20
  interface HowToInterface extends ContentInterface {
14
21
  get description(): any;
15
22
  get pages(): string | undefined;
16
- get helpContentSlug(): string | undefined;
23
+ get howToType(): string | undefined;
24
+ get slug(): string | undefined;
25
+ get order(): number | undefined;
26
+ get summary(): string | undefined;
27
+ get tags(): string[];
28
+ get contextualKeys(): string[];
29
+ get draft(): boolean;
17
30
  }
18
31
 
19
32
  /**
@@ -9,11 +9,24 @@ type BreadcrumbItemData = {
9
9
  type HowToInput = ContentInput & {
10
10
  description?: any;
11
11
  pages?: string | undefined | null;
12
+ howToType?: string;
13
+ slug?: string;
14
+ order?: number;
15
+ summary?: string;
16
+ tags?: string[];
17
+ contextualKeys?: string[];
18
+ draft?: boolean;
12
19
  };
13
20
  interface HowToInterface extends ContentInterface {
14
21
  get description(): any;
15
22
  get pages(): string | undefined;
16
- get helpContentSlug(): string | undefined;
23
+ get howToType(): string | undefined;
24
+ get slug(): string | undefined;
25
+ get order(): number | undefined;
26
+ get summary(): string | undefined;
27
+ get tags(): string[];
28
+ get contextualKeys(): string[];
29
+ get draft(): boolean;
17
30
  }
18
31
 
19
32
  /**
@@ -6,18 +6,17 @@
6
6
 
7
7
 
8
8
 
9
- var _chunkUHO3KUUHjs = require('./chunk-UHO3KUUH.js');
9
+ var _chunkAKXUNE3Ajs = require('./chunk-AKXUNE3A.js');
10
10
 
11
11
 
12
12
 
13
- var _chunk7E3O52U5js = require('./chunk-7E3O52U5.js');
14
- require('./chunk-YQQHAFBS.js');
13
+ var _chunk6XWW67F2js = require('./chunk-6XWW67F2.js');
15
14
 
16
15
 
17
16
 
18
17
 
19
18
 
20
- var _chunkCFI4WZ5Rjs = require('./chunk-CFI4WZ5R.js');
19
+ var _chunkU2HR57MYjs = require('./chunk-U2HR57MY.js');
21
20
 
22
21
 
23
22
  var _chunkLXKSUWAVjs = require('./chunk-LXKSUWAV.js');
@@ -145,7 +144,7 @@ var createDiffActionsInlineContentSpec = /* @__PURE__ */ _chunk7QVYU63Ejs.__name
145
144
  const diffIds = props.inlineContent.props.diffIds;
146
145
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "span", { className: "diff-actions-container mx-2 inline-flex items-center gap-1 align-middle", children: [
147
146
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
148
- _chunkUHO3KUUHjs.Button,
147
+ _chunkAKXUNE3Ajs.Button,
149
148
  {
150
149
  title: "Accept change",
151
150
  onClick: (e) => {
@@ -157,7 +156,7 @@ var createDiffActionsInlineContentSpec = /* @__PURE__ */ _chunk7QVYU63Ejs.__name
157
156
  }
158
157
  ),
159
158
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
160
- _chunkUHO3KUUHjs.Button,
159
+ _chunkAKXUNE3Ajs.Button,
161
160
  {
162
161
  title: "Reject change",
163
162
  className: "mx-2 p-0",
@@ -348,8 +347,8 @@ function BlockNoteEditor({
348
347
  stretch
349
348
  }) {
350
349
  const t = _nextintl.useTranslations.call(void 0, );
351
- const locale = _chunk7E3O52U5js.useI18nLocale.call(void 0, );
352
- const { company } = _chunkUHO3KUUHjs.useCurrentUserContext.call(void 0, );
350
+ const locale = _chunk6XWW67F2js.useI18nLocale.call(void 0, );
351
+ const { company } = _chunkAKXUNE3Ajs.useCurrentUserContext.call(void 0, );
353
352
  const [acceptedChanges, setAcceptedChanges] = _react3.useState.call(void 0, /* @__PURE__ */ new Set());
354
353
  const [rejectedChanges, setRejectedChanges] = _react3.useState.call(void 0, /* @__PURE__ */ new Set());
355
354
  const editorRef = _react3.useRef.call(void 0, null);
@@ -387,7 +386,7 @@ function BlockNoteEditor({
387
386
  [handleAcceptChange, handleRejectChange]
388
387
  );
389
388
  const mentionSpec = _react3.useMemo.call(void 0,
390
- () => _chunkUHO3KUUHjs.createMentionInlineContentSpec.call(void 0, mentionResolveFn, disableMentions, mentionNameResolver),
389
+ () => _chunkAKXUNE3Ajs.createMentionInlineContentSpec.call(void 0, mentionResolveFn, disableMentions, mentionNameResolver),
391
390
  [disableMentions, mentionResolveFn, mentionNameResolver]
392
391
  );
393
392
  const schema = _react3.useMemo.call(void 0,
@@ -406,7 +405,7 @@ function BlockNoteEditor({
406
405
  const companyId = _optionalChain([company, 'optionalAccess', _11 => _11.id]);
407
406
  const aiExtension = _react3.useMemo.call(void 0, () => {
408
407
  if (!aiConfig) return void 0;
409
- const base = _chunk7E3O52U5js.getPublicApiUrl.call(void 0, );
408
+ const base = _chunk6XWW67F2js.getPublicApiUrl.call(void 0, );
410
409
  const url = new URL(aiConfig.endpoint, base.endsWith("/") ? base : base + "/").toString();
411
410
  return _xlai.AIExtension.call(void 0, {
412
411
  transport: new (0, _ai.DefaultChatTransport)({
@@ -448,7 +447,7 @@ function BlockNoteEditor({
448
447
  const uploadImage = _react3.useCallback.call(void 0,
449
448
  async (file) => {
450
449
  if (!company) {
451
- _chunkUHO3KUUHjs.errorToast.call(void 0, {
450
+ _chunkAKXUNE3Ajs.errorToast.call(void 0, {
452
451
  title: t(`common.errors.upload`),
453
452
  error: t(`common.errors.upload_description`)
454
453
  });
@@ -456,7 +455,7 @@ function BlockNoteEditor({
456
455
  }
457
456
  const fileType = file.type;
458
457
  const key = `companies/${company.id}/${type}/${id}/${file.name}`;
459
- const s3 = await _chunkCFI4WZ5Rjs.S3Service.getPreSignedUrl({
458
+ const s3 = await _chunkU2HR57MYjs.S3Service.getPreSignedUrl({
460
459
  key,
461
460
  contentType: fileType,
462
461
  isPublic: true
@@ -466,7 +465,7 @@ function BlockNoteEditor({
466
465
  headers: s3.headers,
467
466
  body: file
468
467
  });
469
- const signedImage = await _chunkCFI4WZ5Rjs.S3Service.getSignedUrl({
468
+ const signedImage = await _chunkU2HR57MYjs.S3Service.getSignedUrl({
470
469
  key,
471
470
  isPublic: true
472
471
  });
@@ -495,8 +494,8 @@ function BlockNoteEditor({
495
494
  const processedContent = _react3.useMemo.call(void 0, () => {
496
495
  if (diffContent && initialContent) {
497
496
  try {
498
- const diffResult = _chunkCFI4WZ5Rjs.BlockNoteDiffUtil.diff(initialContent, diffContent);
499
- const renderedDiff = _chunkCFI4WZ5Rjs.BlockNoteWordDiffRendererUtil.renderWordDiffs(
497
+ const diffResult = _chunkU2HR57MYjs.BlockNoteDiffUtil.diff(initialContent, diffContent);
498
+ const renderedDiff = _chunkU2HR57MYjs.BlockNoteWordDiffRendererUtil.renderWordDiffs(
500
499
  diffResult.blocks,
501
500
  handleAcceptChange,
502
501
  handleRejectChange,
@@ -678,7 +677,7 @@ function BlockNoteEditor({
678
677
  "div",
679
678
  {
680
679
  ref: editorRef,
681
- className: _chunkCFI4WZ5Rjs.cn.call(void 0,
680
+ className: _chunkU2HR57MYjs.cn.call(void 0,
682
681
  bordered ? "rounded-md border border-input bg-input/20 dark:bg-input/30" : "",
683
682
  "flex flex-col w-full",
684
683
  // Pin BlockNote's font-size so it doesn't jump from 14→16px when the
@@ -698,7 +697,7 @@ function BlockNoteEditor({
698
697
  formattingToolbar: false,
699
698
  slashMenu: !aiConfig,
700
699
  theme: "light",
701
- className: _chunkCFI4WZ5Rjs.cn.call(void 0,
700
+ className: _chunkU2HR57MYjs.cn.call(void 0,
702
701
  "BlockNoteView flex-1",
703
702
  onChange && "[&.bn-container]:p-4",
704
703
  // In stretch mode the parent chain caps our height via flex; without
@@ -712,7 +711,7 @@ function BlockNoteEditor({
712
711
  children: [
713
712
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, BlockNoteEditorFormattingToolbar, { showAI: !!aiConfig }),
714
713
  enableMentions && mentionSearchFn && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
715
- _chunkUHO3KUUHjs.BlockNoteEditorMentionSuggestionMenu,
714
+ _chunkAKXUNE3Ajs.BlockNoteEditorMentionSuggestionMenu,
716
715
  {
717
716
  editor,
718
717
  mentionSearchFn,
@@ -721,7 +720,7 @@ function BlockNoteEditor({
721
720
  }
722
721
  ),
723
722
  _optionalChain([renderOverlays, 'optionalCall', _21 => _21(editor)]),
724
- enableMentions && mentionResolveFn && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkUHO3KUUHjs.BlockNoteEditorMentionHoverCard, { containerRef: editorRef, mentionResolveFn }),
723
+ enableMentions && mentionResolveFn && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkAKXUNE3Ajs.BlockNoteEditorMentionHoverCard, { containerRef: editorRef, mentionResolveFn }),
725
724
  aiConfig && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
726
725
  _react.SuggestionMenuController,
727
726
  {
@@ -740,4 +739,4 @@ _chunk7QVYU63Ejs.__name.call(void 0, BlockNoteEditor, "BlockNoteEditor");
740
739
 
741
740
 
742
741
  exports.default = BlockNoteEditor;
743
- //# sourceMappingURL=BlockNoteEditor-3XYBZLWO.js.map
742
+ //# sourceMappingURL=BlockNoteEditor-7OKW6HHN.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/home/runner/work/nextjs-jsonapi/nextjs-jsonapi/dist/BlockNoteEditor-7OKW6HHN.js","../src/components/editors/BlockNoteEditor.tsx","../src/components/editors/BlockNoteEditorFormattingToolbar.tsx"],"names":["jsxs","jsx"],"mappings":"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","file":"/home/runner/work/nextjs-jsonapi/nextjs-jsonapi/dist/BlockNoteEditor-7OKW6HHN.js","sourcesContent":[null,"\"use client\";\n\nimport { BlockNoteSchema, defaultInlineContentSpecs, filterSuggestionItems, PartialBlock } from \"@blocknote/core\";\nimport { en as coreEn } from \"@blocknote/core/locales\";\nimport {\n createReactInlineContentSpec,\n DefaultReactSuggestionItem,\n getDefaultReactSlashMenuItems,\n SuggestionMenuController,\n SuggestionMenuProps,\n useBlockNoteEditor,\n useCreateBlockNote,\n useExtension,\n useExtensionState,\n} from \"@blocknote/react\";\nimport { BlockNoteView } from \"@blocknote/shadcn\";\nimport \"@blocknote/shadcn/style.css\";\nimport {\n AIExtension,\n AIMenuController,\n getAISlashMenuItems,\n getDefaultAIMenuItems,\n PromptSuggestionMenu,\n useAIDictionary,\n} from \"@blocknote/xl-ai\";\nimport { en as aiEn } from \"@blocknote/xl-ai/locales\";\nimport \"@blocknote/xl-ai/style.css\";\nimport { DefaultChatTransport } from \"ai\";\nimport {\n CheckIcon,\n LanguagesIcon,\n LayoutTemplateIcon,\n SparklesIcon,\n TypeIcon,\n WandSparklesIcon,\n XIcon,\n} from \"lucide-react\";\nimport { useTranslations } from \"next-intl\";\nimport React, { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { getPublicApiUrl } from \"../../client/config\";\nimport { getClientToken } from \"../../client/token\";\nimport { useCurrentUserContext } from \"../../contexts\";\nimport { S3Interface } from \"../../features/s3/data\";\nimport { S3Service } from \"../../features/s3/data/s3.service\";\nimport { UserInterface } from \"../../features/user/data\";\nimport { useI18nLocale } from \"../../i18n/config\";\nimport { Button } from \"../../shadcnui\";\nimport { BlockNoteDiffUtil, BlockNoteWordDiffRendererUtil, cn } from \"../../utils\";\nimport { errorToast } from \"../errors\";\nimport { BlockNoteEditorFormattingToolbar } from \"./BlockNoteEditorFormattingToolbar\";\nimport { BlockNoteEditorMentionHoverCard } from \"./BlockNoteEditorMentionHoverCard\";\nimport {\n createMentionInlineContentSpec,\n type MentionNameResolver,\n type MentionResolveFn,\n} from \"./BlockNoteEditorMentionInlineContent\";\nimport { BlockNoteEditorMentionSuggestionMenu } from \"./BlockNoteEditorSuggestionMenuController\";\n\nexport type BlockNoteAiConfig = {\n endpoint: string;\n entityType: string;\n entityId?: string;\n};\n\nexport type BlockNoteEditorProps = {\n id: string;\n type: string;\n initialContent?: PartialBlock[];\n onChange?: (content: any, isEmpty: boolean, hasUnresolvedDiff: boolean) => void;\n size?: \"sm\" | \"md\";\n className?: string;\n markdownContent?: string;\n diffContent?: PartialBlock[];\n placeholder?: string;\n bordered?: boolean;\n inlineContentSpecs?: Record<string, any>;\n renderOverlays?: (editor: any) => React.ReactNode;\n enableMentions?: boolean;\n disableMentions?: boolean;\n mentionSearchFn?: (\n query: string,\n params?: Record<string, string>,\n ) => Promise<import(\"./BlockNoteEditorSuggestionMenuController\").MentionItem[]>;\n mentionSearchParams?: Record<string, string>;\n mentionResolveFn?: MentionResolveFn;\n suggestionMenuComponent?: React.FC<SuggestionMenuProps<DefaultReactSuggestionItem>>;\n mentionNameResolver?: MentionNameResolver;\n onWarmMentions?: (blocks: PartialBlock[]) => void;\n aiConfig?: BlockNoteAiConfig;\n // When the editor is inside a bounded flex column (parent gives it a real\n // height via flex-1+min-h-0), set this so `.bn-container` shrinks to that\n // height and scrolls internally. Without it the editor grows to fit its\n // content and pushes the surrounding form to scroll instead.\n stretch?: boolean;\n};\n\nfunction isBlockEmpty(block: any): boolean {\n if (!block || typeof block !== \"object\") return true;\n if (block.type !== \"paragraph\") return false;\n if (Array.isArray(block.children) && block.children.length > 0 && !isDocumentEmpty(block.children)) {\n return false;\n }\n if (Array.isArray(block.content)) {\n for (const inline of block.content) {\n if (typeof inline === \"string\") {\n if (inline.trim()) return false;\n } else if (inline && typeof inline === \"object\") {\n if (inline.type !== \"text\") return false;\n if (typeof inline.text === \"string\" && inline.text.trim()) return false;\n }\n }\n } else if (typeof block.content === \"string\" && block.content.trim()) {\n return false;\n }\n return true;\n}\n\nfunction isDocumentEmpty(blocks: any[]): boolean {\n if (!Array.isArray(blocks) || blocks.length === 0) return true;\n return blocks.every(isBlockEmpty);\n}\n\nconst createDiffActionsInlineContentSpec = (\n handleAcceptChange: (diffId: string) => void,\n handleRejectChange: (diffId: string) => void,\n) => {\n return createReactInlineContentSpec(\n {\n type: \"diffActions\",\n propSchema: {\n diffIds: {\n default: \"\",\n },\n },\n content: \"none\",\n },\n {\n render: (props) => {\n const diffIds = props.inlineContent.props.diffIds;\n\n return (\n <span className=\"diff-actions-container mx-2 inline-flex items-center gap-1 align-middle\">\n <Button\n title=\"Accept change\"\n onClick={(e) => {\n e.preventDefault();\n e.stopPropagation();\n diffIds.split(\",\").forEach((id: string) => handleAcceptChange(id.trim()));\n }}\n >\n <CheckIcon className=\"h-3 w-3 text-green-600\" />\n </Button>\n <Button\n title=\"Reject change\"\n className=\"mx-2 p-0\"\n onClick={(e) => {\n e.preventDefault();\n e.stopPropagation();\n diffIds.split(\",\").forEach((id: string) => handleRejectChange(id.trim()));\n }}\n >\n <XIcon className=\"h-3 w-3 text-red-600\" />\n </Button>\n </span>\n );\n },\n },\n );\n};\n\n/**\n * Custom AI menu wrapper. Surfaces our backend-driven action items\n * (Improve Writing, Fix Spelling) above the free-form prompt input.\n *\n * Why a custom wrapper instead of `<AIMenu items={…}>` with the BlockNote\n * defaults: BlockNote's `PromptSuggestionMenu` hijacks Enter to pick the\n * highlighted item whenever `items.length > 0`. We gate items on\n * - status === \"user-input\"\n * - editor has a selection\n * - prompt input is empty\n * so the moment the user types, items disappear and Enter falls back to\n * free-form submission. Outside `user-input` (review / error states) we\n * keep BlockNote's default review buttons (accept/revert/retry/cancel).\n *\n * Each custom item passes a `type` discriminator on `chatRequestOptions.body`.\n * That field flows through `chat.sendMessage(msg, opts)` to the transport's\n * `prepareSendMessagesRequest({messages, body})` (see types.ts in\n * `@blocknote/xl-ai` — `ChatRequestOptions = Parameters<Chat[\"sendMessage\"]>[1]`).\n * The backend dispatcher reads `body.type` and routes to a per-type handler\n * with its own canonical prompt. NO prompt text lives in this file.\n */\nfunction NarrAIMenu() {\n const editor = useBlockNoteEditor();\n const ai = useExtension(AIExtension);\n const dict = useAIDictionary();\n const status = useExtensionState(AIExtension, {\n selector: (s) => (s.aiMenuState !== \"closed\" ? s.aiMenuState.status : \"closed\"),\n });\n const [prompt, setPrompt] = useState(\"\");\n // Set by items that pre-fill the input (Translate) so handleSubmit knows\n // which `type` to attach when the user submits the captured text. Cleared\n // after submit or on status change.\n const pendingTypeRef = useRef<string | null>(null);\n\n useEffect(() => {\n if (status === \"ai-writing\" || status === \"user-reviewing\" || status === \"error\" || status === \"closed\") {\n setPrompt(\"\");\n pendingTypeRef.current = null;\n }\n }, [status]);\n\n // Selection-edit ops operate per-block. If the user's selection only\n // covers part of a block (cursor mid-paragraph dragged to mid-next), the\n // rewrite would silently replace the WHOLE containing blocks — beyond\n // what the user highlighted. Expand the selection to whole-block bounds\n // BEFORE invokeAI so the user sees exactly what will be rewritten.\n const expandSelectionToBlocks = useCallback(() => {\n const sel = editor.getSelection?.();\n const blocks = (sel as any)?.blocks;\n if (!Array.isArray(blocks) || blocks.length === 0) return;\n const first = blocks[0];\n const last = blocks[blocks.length - 1];\n try {\n (editor as any).setSelection?.(first, last);\n } catch {\n // If BlockNote's setSelection signature changes, fail silently — the\n // backend still operates per-block, so we just lose the visual hint.\n }\n }, [editor]);\n\n const items = useMemo(() => {\n // Outside user-input (reviewing / error), use BlockNote's default\n // review buttons (accept/revert/retry/cancel). Need to wrap onItemClick\n // because the default items expect a setPrompt argument.\n if (status !== \"user-input\") {\n return getDefaultAIMenuItems(editor, status).map((item) => ({\n ...item,\n onItemClick: () => item.onItemClick(setPrompt),\n }));\n }\n const hasSelection = editor.getSelection() !== undefined;\n const hasTyped = prompt.trim().length > 0;\n // Once the user starts typing, hide all items so Enter submits the\n // free-form (or pending-type) prompt instead of being hijacked.\n if (hasTyped) return [];\n\n // Generate from Template is shown in BOTH contexts (with and without\n // selection) because it operates on the whole document — it ignores any\n // active selection and runs the per-section template-fill flow. Listed\n // first so it's the default-highlighted item.\n const generateFromTemplate = {\n key: \"generate_from_template\",\n title: \"Generate from Template\",\n aliases: [\"generate\", \"template\", \"fill\"],\n icon: <LayoutTemplateIcon size={18} />,\n size: \"small\" as const,\n onItemClick: () => {\n void ai.invokeAI({\n userPrompt: \"fill-template\",\n useSelection: false,\n chatRequestOptions: { body: { type: \"fill-template\" } },\n });\n },\n };\n\n if (hasSelection) {\n // Selection-edit items + the always-available Generate from Template.\n // Each selection item invokes ai.invokeAI with chatRequestOptions\n // carrying the `type` body field. The userPrompt is a short tag — the\n // backend ignores it and uses the canonical prompt for the type instead.\n return [\n generateFromTemplate,\n {\n key: \"improve_writing\",\n title: \"Improve Writing\",\n aliases: [\"improve\", \"rewrite\", \"polish\"],\n icon: <SparklesIcon size={18} />,\n size: \"small\" as const,\n onItemClick: () => {\n expandSelectionToBlocks();\n void ai.invokeAI({\n userPrompt: \"improve-writing\",\n useSelection: true,\n chatRequestOptions: { body: { type: \"improve-writing\" } },\n });\n },\n },\n {\n key: \"fix_spelling\",\n title: \"Fix Spelling\",\n aliases: [\"spelling\", \"grammar\", \"typo\"],\n icon: <TypeIcon size={18} />,\n size: \"small\" as const,\n onItemClick: () => {\n expandSelectionToBlocks();\n void ai.invokeAI({\n userPrompt: \"fix-spelling\",\n useSelection: true,\n chatRequestOptions: { body: { type: \"fix-spelling\" } },\n });\n },\n },\n {\n key: \"translate\",\n title: \"Translate…\",\n aliases: [\"translate\", \"language\"],\n icon: <LanguagesIcon size={18} />,\n size: \"small\" as const,\n // Pre-fills the input with a placeholder. User appends/replaces\n // with the target language and submits via Enter. handleSubmit\n // reads pendingTypeRef and forwards `type: \"translate\"`. We\n // expand the selection now so the user sees the scope before\n // typing the language — handleSubmit doesn't re-expand.\n onItemClick: () => {\n expandSelectionToBlocks();\n pendingTypeRef.current = \"translate\";\n setPrompt(\"Translate to \");\n },\n },\n {\n key: \"simplify\",\n title: \"Simplify\",\n aliases: [\"simplify\", \"easier\", \"plain\"],\n icon: <WandSparklesIcon size={18} />,\n size: \"small\" as const,\n onItemClick: () => {\n expandSelectionToBlocks();\n void ai.invokeAI({\n userPrompt: \"simplify\",\n useSelection: true,\n chatRequestOptions: { body: { type: \"simplify\" } },\n });\n },\n },\n ];\n }\n\n // No selection (the /ai slash menu path): just Generate from Template.\n // Free-form typing still works — once the user types, items hide and\n // Enter submits with no type (backend defaults to fill-template).\n return [generateFromTemplate];\n }, [editor, status, prompt, ai, expandSelectionToBlocks]);\n\n const handleSubmit = useCallback(\n async (userPrompt: string) => {\n if (!userPrompt.trim()) return;\n const pendingType = pendingTypeRef.current;\n pendingTypeRef.current = null;\n const body = pendingType ? { type: pendingType } : undefined;\n await ai.invokeAI({\n userPrompt,\n useSelection: editor.getSelection() !== undefined,\n ...(body ? { chatRequestOptions: { body } } : {}),\n });\n },\n [ai, editor],\n );\n\n const placeholder =\n status === \"thinking\"\n ? dict.ai_menu.status.thinking\n : status === \"ai-writing\"\n ? dict.ai_menu.status.editing\n : status === \"error\"\n ? dict.ai_menu.status.error\n : dict.ai_menu.input_placeholder;\n\n const disabled = status === \"thinking\" || status === \"ai-writing\";\n\n return (\n <PromptSuggestionMenu\n items={items}\n onManualPromptSubmit={handleSubmit}\n promptText={prompt}\n onPromptTextChange={setPrompt}\n placeholder={placeholder}\n disabled={disabled}\n icon={\n <div className=\"bn-combobox-icon\">\n <SparklesIcon size={16} />\n </div>\n }\n />\n );\n}\n\nexport default function BlockNoteEditor({\n id,\n type,\n initialContent,\n onChange,\n size,\n className,\n markdownContent,\n diffContent,\n placeholder,\n bordered,\n inlineContentSpecs,\n renderOverlays,\n enableMentions,\n disableMentions,\n mentionSearchFn,\n mentionSearchParams,\n mentionResolveFn,\n suggestionMenuComponent,\n mentionNameResolver,\n onWarmMentions,\n aiConfig,\n stretch,\n}: BlockNoteEditorProps): React.JSX.Element {\n const t = useTranslations();\n const locale = useI18nLocale();\n const { company } = useCurrentUserContext<UserInterface>();\n\n const [acceptedChanges, setAcceptedChanges] = useState<Set<string>>(new Set());\n const [rejectedChanges, setRejectedChanges] = useState<Set<string>>(new Set());\n\n const editorRef = useRef<HTMLDivElement>(null);\n\n // Ensure side menu buttons don't trigger form submission\n useEffect(() => {\n if (!editorRef.current) return;\n const setButtonTypes = () => {\n editorRef.current?.querySelectorAll(\".bn-side-menu button\").forEach((btn) => {\n if (!btn.getAttribute(\"type\")) {\n btn.setAttribute(\"type\", \"button\");\n }\n });\n };\n const observer = new MutationObserver(setButtonTypes);\n observer.observe(editorRef.current, { childList: true, subtree: true });\n return () => observer.disconnect();\n }, []);\n\n const handleAcceptChange = useCallback((diffId: string) => {\n setAcceptedChanges((prev) => new Set([...prev, diffId]));\n setRejectedChanges((prev) => {\n const newSet = new Set(prev);\n newSet.delete(diffId);\n return newSet;\n });\n }, []);\n\n const handleRejectChange = useCallback((diffId: string) => {\n setRejectedChanges((prev) => new Set([...prev, diffId]));\n setAcceptedChanges((prev) => {\n const newSet = new Set(prev);\n newSet.delete(diffId);\n return newSet;\n });\n }, []);\n\n const DiffActionsInlineContent = useMemo(\n () => createDiffActionsInlineContentSpec(handleAcceptChange, handleRejectChange),\n [handleAcceptChange, handleRejectChange],\n );\n\n const mentionSpec = useMemo(\n () => createMentionInlineContentSpec(mentionResolveFn, disableMentions, mentionNameResolver),\n [disableMentions, mentionResolveFn, mentionNameResolver],\n );\n\n const schema = useMemo(\n () =>\n BlockNoteSchema.create({\n inlineContentSpecs: {\n ...defaultInlineContentSpecs,\n diffActions: DiffActionsInlineContent,\n mention: mentionSpec,\n ...inlineContentSpecs,\n },\n } as any),\n [DiffActionsInlineContent, mentionSpec, inlineContentSpecs],\n );\n\n const docRef = useRef<{ getDoc: () => any[] }>({ getDoc: () => [] });\n // Selection getter used by the AI transport to attach `selectionBlocks` to\n // the outgoing request metadata. Populated in a useEffect once the editor\n // instance exists; reads the current BlockNote selection on every send.\n const selectionRef = useRef<{ getSelectedBlocks: () => any[] }>({ getSelectedBlocks: () => [] });\n\n const companyId = company?.id;\n const aiExtension = useMemo(() => {\n if (!aiConfig) return undefined;\n const base = getPublicApiUrl();\n const url = new URL(aiConfig.endpoint, base.endsWith(\"/\") ? base : base + \"/\").toString();\n return AIExtension({\n transport: new DefaultChatTransport({\n api: url,\n credentials: \"include\",\n headers: async () => {\n const headers: Record<string, string> = { \"x-language\": locale };\n const token = await getClientToken();\n if (token) headers[\"Authorization\"] = `Bearer ${token}`;\n if (companyId) headers[\"x-companyid\"] = companyId;\n return headers;\n },\n prepareSendMessagesRequest: ({ messages, body }: any) => {\n let lastUserIdx = -1;\n for (let i = messages.length - 1; i >= 0; i--) {\n if (messages[i]?.role === \"user\") {\n lastUserIdx = i;\n break;\n }\n }\n const selectedBlocks = selectionRef.current.getSelectedBlocks();\n const augmented = messages.map((m: any, i: number) =>\n i === lastUserIdx\n ? {\n ...m,\n metadata: {\n ...(m.metadata ?? {}),\n entityType: aiConfig.entityType,\n entityId: aiConfig.entityId,\n blocks: docRef.current.getDoc(),\n selectionBlocks: selectedBlocks,\n },\n }\n : m,\n );\n return { body: { ...(body ?? {}), messages: augmented } };\n },\n }),\n });\n }, [aiConfig, companyId, locale]);\n\n const uploadImage = useCallback(\n async (file: File): Promise<string> => {\n if (!company) {\n errorToast({\n title: t(`common.errors.upload`),\n error: t(`common.errors.upload_description`),\n });\n throw new Error(t(`common.errors.upload`));\n }\n\n const fileType = file.type;\n const key = `companies/${company.id}/${type}/${id}/${file.name}`;\n\n const s3: S3Interface = await S3Service.getPreSignedUrl({\n key: key,\n contentType: fileType,\n isPublic: true,\n });\n\n await fetch(s3.url, {\n method: \"PUT\",\n headers: s3.headers,\n body: file,\n });\n\n const signedImage: S3Interface = await S3Service.getSignedUrl({\n key: key,\n isPublic: true,\n });\n\n return signedImage.url;\n },\n [company, id, t],\n );\n\n // Utility: Remove trailing empty blocks for read-only display\n const removeTrailingEmptyBlocks = useCallback(\n (blocks: PartialBlock[]): PartialBlock[] => {\n if (!blocks || blocks.length === 0) return blocks;\n\n // Only remove trailing empty blocks in read-only mode\n if (onChange !== undefined) return blocks;\n\n const result = [...blocks];\n\n // Remove trailing empty paragraph blocks, but keep at least one block\n while (result.length > 1) {\n const lastBlock = result[result.length - 1];\n\n // Check if it's an empty paragraph\n const isEmptyParagraph =\n lastBlock.type === \"paragraph\" &&\n (!lastBlock.content ||\n lastBlock.content.length === 0 ||\n (Array.isArray(lastBlock.content) && lastBlock.content.every((c: any) => !c.text || c.text.trim() === \"\")));\n\n if (isEmptyParagraph) {\n result.pop();\n } else {\n break;\n }\n }\n\n return result;\n },\n [onChange],\n );\n\n const processedContent = useMemo(() => {\n if (diffContent && initialContent) {\n try {\n const diffResult = BlockNoteDiffUtil.diff(initialContent, diffContent);\n const renderedDiff = BlockNoteWordDiffRendererUtil.renderWordDiffs(\n diffResult.blocks,\n handleAcceptChange,\n handleRejectChange,\n acceptedChanges,\n rejectedChanges,\n );\n return removeTrailingEmptyBlocks(renderedDiff);\n } catch (_error) {\n return initialContent && Array.isArray(initialContent) && initialContent.length > 0\n ? removeTrailingEmptyBlocks(initialContent)\n : [];\n }\n }\n\n if (!initialContent) {\n return [];\n }\n\n if (!Array.isArray(initialContent)) {\n return [];\n }\n\n return initialContent.length > 0 ? removeTrailingEmptyBlocks(initialContent) : [];\n }, [\n initialContent,\n diffContent,\n handleAcceptChange,\n handleRejectChange,\n acceptedChanges,\n rejectedChanges,\n removeTrailingEmptyBlocks,\n ]);\n\n const validatedInitialContent = useMemo(() => {\n if (processedContent && Array.isArray(processedContent) && processedContent.length > 0) {\n const validatedContent = processedContent.filter((block) => {\n if (!block || typeof block !== \"object\") return false;\n if (!(block as any).type) return false;\n return true;\n });\n return validatedContent.length > 0 ? (validatedContent as PartialBlock[]) : undefined;\n }\n return undefined;\n }, [processedContent]);\n\n const editor = useCreateBlockNote(\n useMemo(\n () => ({\n placeholders: {\n emptyDocument: placeholder || t(`common.blocknote.placeholder`),\n },\n schema,\n initialContent: validatedInitialContent,\n uploadFile: uploadImage,\n extensions: aiExtension ? [aiExtension] : undefined,\n dictionary: aiExtension ? { ...coreEn, ai: aiEn } : undefined,\n }),\n [placeholder, t, schema, validatedInitialContent, uploadImage, aiExtension],\n ),\n );\n\n // Tracks the hash of the document the editor itself just emitted via onChange.\n // The sync effect below uses it to skip replaceBlocks when the parent's\n // initialContent is just an echo of our own emission (form-controlled flow).\n const lastEmittedHashRef = useRef<string | null>(null);\n\n const handleChange = useCallback(async () => {\n if (!onChange) return;\n const newBlocks = editor.document;\n lastEmittedHashRef.current = JSON.stringify(newBlocks);\n const isEmpty = isDocumentEmpty(newBlocks);\n\n function hasUnresolvedDiffsRecursive(block: any): boolean {\n if (!block || typeof block !== \"object\") return false;\n let diffId = undefined;\n if (block.props && block.props.diffId) diffId = block.props.diffId;\n if (!diffId && block.attrs && block.attrs.diffId) diffId = block.attrs.diffId;\n if (diffId && !acceptedChanges.has(diffId) && !rejectedChanges.has(diffId)) {\n return true;\n }\n\n if (block.content) {\n const contentArr = Array.isArray(block.content) ? block.content : [block.content];\n for (const inline of contentArr) {\n if (inline && typeof inline === \"object\") {\n if (inline.type === \"diffActions\" && inline.props && inline.props.diffIds) {\n const ids =\n typeof inline.props.diffIds === \"string\" ? inline.props.diffIds.split(\",\") : inline.props.diffIds;\n for (const id of ids) {\n const trimmed = (id || \"\").toString().trim();\n if (trimmed && !acceptedChanges.has(trimmed) && !rejectedChanges.has(trimmed)) {\n return true;\n }\n }\n }\n if (inline.props && inline.props.diffId) {\n const diffIdInline = inline.props.diffId;\n if (diffIdInline && !acceptedChanges.has(diffIdInline) && !rejectedChanges.has(diffIdInline)) {\n return true;\n }\n }\n if (inline.children && Array.isArray(inline.children)) {\n for (const child of inline.children) {\n if (hasUnresolvedDiffsRecursive(child)) return true;\n }\n }\n }\n }\n }\n if (Array.isArray(block.children)) {\n for (const child of block.children) {\n if (hasUnresolvedDiffsRecursive(child)) return true;\n }\n }\n return false;\n }\n\n let hasUnresolvedDiff = false;\n if (Array.isArray(newBlocks)) {\n hasUnresolvedDiff = newBlocks.some((block: any) => hasUnresolvedDiffsRecursive(block));\n }\n\n onChange(newBlocks, isEmpty, hasUnresolvedDiff);\n }, [editor, onChange, id, acceptedChanges, rejectedChanges]);\n\n // Utility: deep equality for arrays of blocks\n const areBlocksEqual = (a: any[], b: any[]): boolean => {\n return JSON.stringify(a) === JSON.stringify(b);\n };\n\n // Only initialize from markdownContent once per value, and only if different\n const hasInitializedFromMarkdown = useRef<string | null>(null);\n useEffect(() => {\n const updateContent = async (markdown: string) => {\n const blocks = await editor.tryParseMarkdownToBlocks(markdown);\n if (!areBlocksEqual(blocks, editor.document)) {\n editor.replaceBlocks(editor.document, blocks);\n }\n };\n\n if (markdownContent && hasInitializedFromMarkdown.current !== markdownContent) {\n hasInitializedFromMarkdown.current = markdownContent;\n updateContent(markdownContent).then(() => handleChange());\n }\n }, [markdownContent, editor]);\n\n // Update editor content when diff content changes, but only if different\n // Prevent unnecessary replaceBlocks calls that reset scroll/cursor.\n const previousContentHashRef = useRef<string | null>(null);\n useEffect(() => {\n if (!processedContent || !editor) return;\n const hash = JSON.stringify(processedContent);\n if (previousContentHashRef.current === hash) return; // no changes\n // Skip replaceBlocks when the new initialContent is just an echo of what\n // the editor itself emitted. Without this, a form-controlled parent\n // (FormBlockNote) round-trips field.value back as initialContent on every\n // keystroke and triggers replaceBlocks, which resets the cursor and can\n // strip just-inserted inline content like mentions.\n if (lastEmittedHashRef.current === hash) {\n previousContentHashRef.current = hash;\n return;\n }\n const currentHash = JSON.stringify(editor.document);\n if (currentHash === hash) {\n previousContentHashRef.current = hash;\n return; // already in sync\n }\n editor.replaceBlocks(editor.document, processedContent as PartialBlock[]);\n previousContentHashRef.current = hash;\n }, [processedContent, editor]);\n\n useEffect(() => {\n if (!onWarmMentions || !initialContent || !Array.isArray(initialContent) || initialContent.length === 0) return;\n onWarmMentions(initialContent);\n }, [onWarmMentions, initialContent]);\n\n useEffect(() => {\n docRef.current.getDoc = () => editor?.document ?? [];\n selectionRef.current.getSelectedBlocks = () => {\n const sel = editor?.getSelection?.();\n const blocks = (sel as any)?.blocks;\n return Array.isArray(blocks) ? blocks : [];\n };\n }, [editor]);\n\n // Handle audio received from whisper transcription\n const _handleAudioReceived = useCallback(\n (message: string) => {\n try {\n // Ensure the editor has focus\n const editorElement = editorRef.current?.querySelector('[contenteditable=\"true\"]') as HTMLElement;\n if (editorElement && document.activeElement !== editorElement) {\n editorElement.focus();\n }\n\n // Insert the transcribed text at the current cursor position\n editor.insertInlineContent(message);\n } catch (error) {\n console.error(\"Error inserting transcribed text:\", error);\n // Fallback: try to insert at the end of the document\n try {\n const blocks = editor.document;\n if (blocks.length > 0) {\n const lastBlock = blocks[blocks.length - 1];\n editor.setTextCursorPosition(lastBlock.id, \"end\");\n editor.insertInlineContent(message);\n }\n } catch (fallbackError) {\n console.error(\"Fallback insertion also failed:\", fallbackError);\n }\n }\n },\n [editor],\n );\n\n return (\n <div\n ref={editorRef}\n className={cn(\n bordered ? \"rounded-md border border-input bg-input/20 dark:bg-input/30\" : \"\",\n \"flex flex-col w-full\",\n // Pin BlockNote's font-size so it doesn't jump from 14→16px when the\n // xl-ai AIMenu mounts. The shadcn theme sets `.bn-default-styles {\n // font-size: 16px }` explicitly; outside AI mode the form's text-sm\n // wins via cascade, but ForkYDocExtension re-evaluates the style\n // context on AI activation and the explicit 16px takes over.\n \"[&_.bn-default-styles]:!text-sm\",\n className,\n )}\n >\n <BlockNoteView\n editor={editor}\n onChange={handleChange}\n editable={onChange !== undefined}\n formattingToolbar={false}\n slashMenu={!aiConfig}\n theme=\"light\"\n // `className` is applied by BlockNote to both the main `.bn-container`\n // AND `editor.portalElement` (the floating-UI portal root). Gate `p-4`\n // on `.bn-container` so it doesn't add padding to the empty portal\n // element and produce a phantom scrollbar on the wrapper.\n className={cn(\n \"BlockNoteView flex-1\",\n onChange && \"[&.bn-container]:p-4\",\n // In stretch mode the parent chain caps our height via flex; without\n // these two classes the `.bn-container` keeps `min-height: auto`\n // (its content's intrinsic height) and pushes the bordered wrapper\n // — and the surrounding EditorSheet form — to scroll instead of\n // scrolling internally.\n onChange && stretch && \"[&.bn-container]:min-h-0 [&.bn-container]:overflow-y-auto\",\n size === \"sm\" && \"small\",\n )}\n >\n <BlockNoteEditorFormattingToolbar showAI={!!aiConfig} />\n {enableMentions && mentionSearchFn && (\n <BlockNoteEditorMentionSuggestionMenu\n editor={editor}\n mentionSearchFn={mentionSearchFn}\n mentionSearchParams={mentionSearchParams}\n suggestionMenuComponent={suggestionMenuComponent}\n />\n )}\n {renderOverlays?.(editor)}\n {enableMentions && mentionResolveFn && (\n <BlockNoteEditorMentionHoverCard containerRef={editorRef} mentionResolveFn={mentionResolveFn} />\n )}\n {aiConfig && (\n <SuggestionMenuController\n triggerCharacter=\"/\"\n getItems={async (query: string) =>\n filterSuggestionItems([...getDefaultReactSlashMenuItems(editor), ...getAISlashMenuItems(editor)], query)\n }\n />\n )}\n {aiConfig && <AIMenuController aiMenu={() => <NarrAIMenu />} />}\n </BlockNoteView>\n </div>\n );\n}\n","\"use client\";\n\nimport {\n BasicTextStyleButton,\n BlockTypeSelect,\n CreateLinkButton,\n FileCaptionButton,\n FileReplaceButton,\n FormattingToolbar,\n FormattingToolbarController,\n TextAlignButton,\n} from \"@blocknote/react\";\nimport { AIToolbarButton } from \"@blocknote/xl-ai\";\n\nexport function BlockNoteEditorFormattingToolbar({ showAI = false }: { showAI?: boolean }) {\n return (\n <FormattingToolbarController\n formattingToolbar={() => (\n <FormattingToolbar>\n <BlockTypeSelect key={\"blockTypeSelect\"} />\n\n <FileCaptionButton key={\"fileCaptionButton\"} />\n <FileReplaceButton key={\"replaceFileButton\"} />\n\n <BasicTextStyleButton basicTextStyle={\"bold\"} key={\"boldStyleButton\"} />\n <BasicTextStyleButton basicTextStyle={\"italic\"} key={\"italicStyleButton\"} />\n <BasicTextStyleButton basicTextStyle={\"underline\"} key={\"underlineStyleButton\"} />\n <BasicTextStyleButton basicTextStyle={\"strike\"} key={\"strikeStyleButton\"} />\n\n <TextAlignButton textAlignment={\"left\"} key={\"textAlignLeftButton\"} />\n <TextAlignButton textAlignment={\"center\"} key={\"textAlignCenterButton\"} />\n <TextAlignButton textAlignment={\"right\"} key={\"textAlignRightButton\"} />\n\n <CreateLinkButton key={\"createLinkButton\"} />\n\n {showAI ? <AIToolbarButton key={\"aiToolbarButton\"} /> : null}\n </FormattingToolbar>\n )}\n />\n );\n}\n"]}
@@ -6,18 +6,17 @@ import {
6
6
  createMentionInlineContentSpec,
7
7
  errorToast,
8
8
  useCurrentUserContext
9
- } from "./chunk-CRTVAQEK.mjs";
9
+ } from "./chunk-TXVVZLUQ.mjs";
10
10
  import {
11
11
  getPublicApiUrl,
12
12
  useI18nLocale
13
- } from "./chunk-UOYIWJEJ.mjs";
14
- import "./chunk-CQID6RCF.mjs";
13
+ } from "./chunk-CWVYU4YZ.mjs";
15
14
  import {
16
15
  BlockNoteDiffUtil,
17
16
  BlockNoteWordDiffRendererUtil,
18
17
  S3Service,
19
18
  cn
20
- } from "./chunk-MSNNAHDB.mjs";
19
+ } from "./chunk-ZYPNVEHB.mjs";
21
20
  import {
22
21
  getClientToken
23
22
  } from "./chunk-AUXK7QSA.mjs";
@@ -740,4 +739,4 @@ __name(BlockNoteEditor, "BlockNoteEditor");
740
739
  export {
741
740
  BlockNoteEditor as default
742
741
  };
743
- //# sourceMappingURL=BlockNoteEditor-EBFZG7AL.mjs.map
742
+ //# sourceMappingURL=BlockNoteEditor-K7IIWM3S.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/editors/BlockNoteEditor.tsx","../src/components/editors/BlockNoteEditorFormattingToolbar.tsx"],"sourcesContent":["\"use client\";\n\nimport { BlockNoteSchema, defaultInlineContentSpecs, filterSuggestionItems, PartialBlock } from \"@blocknote/core\";\nimport { en as coreEn } from \"@blocknote/core/locales\";\nimport {\n createReactInlineContentSpec,\n DefaultReactSuggestionItem,\n getDefaultReactSlashMenuItems,\n SuggestionMenuController,\n SuggestionMenuProps,\n useBlockNoteEditor,\n useCreateBlockNote,\n useExtension,\n useExtensionState,\n} from \"@blocknote/react\";\nimport { BlockNoteView } from \"@blocknote/shadcn\";\nimport \"@blocknote/shadcn/style.css\";\nimport {\n AIExtension,\n AIMenuController,\n getAISlashMenuItems,\n getDefaultAIMenuItems,\n PromptSuggestionMenu,\n useAIDictionary,\n} from \"@blocknote/xl-ai\";\nimport { en as aiEn } from \"@blocknote/xl-ai/locales\";\nimport \"@blocknote/xl-ai/style.css\";\nimport { DefaultChatTransport } from \"ai\";\nimport {\n CheckIcon,\n LanguagesIcon,\n LayoutTemplateIcon,\n SparklesIcon,\n TypeIcon,\n WandSparklesIcon,\n XIcon,\n} from \"lucide-react\";\nimport { useTranslations } from \"next-intl\";\nimport React, { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { getPublicApiUrl } from \"../../client/config\";\nimport { getClientToken } from \"../../client/token\";\nimport { useCurrentUserContext } from \"../../contexts\";\nimport { S3Interface } from \"../../features/s3/data\";\nimport { S3Service } from \"../../features/s3/data/s3.service\";\nimport { UserInterface } from \"../../features/user/data\";\nimport { useI18nLocale } from \"../../i18n/config\";\nimport { Button } from \"../../shadcnui\";\nimport { BlockNoteDiffUtil, BlockNoteWordDiffRendererUtil, cn } from \"../../utils\";\nimport { errorToast } from \"../errors\";\nimport { BlockNoteEditorFormattingToolbar } from \"./BlockNoteEditorFormattingToolbar\";\nimport { BlockNoteEditorMentionHoverCard } from \"./BlockNoteEditorMentionHoverCard\";\nimport {\n createMentionInlineContentSpec,\n type MentionNameResolver,\n type MentionResolveFn,\n} from \"./BlockNoteEditorMentionInlineContent\";\nimport { BlockNoteEditorMentionSuggestionMenu } from \"./BlockNoteEditorSuggestionMenuController\";\n\nexport type BlockNoteAiConfig = {\n endpoint: string;\n entityType: string;\n entityId?: string;\n};\n\nexport type BlockNoteEditorProps = {\n id: string;\n type: string;\n initialContent?: PartialBlock[];\n onChange?: (content: any, isEmpty: boolean, hasUnresolvedDiff: boolean) => void;\n size?: \"sm\" | \"md\";\n className?: string;\n markdownContent?: string;\n diffContent?: PartialBlock[];\n placeholder?: string;\n bordered?: boolean;\n inlineContentSpecs?: Record<string, any>;\n renderOverlays?: (editor: any) => React.ReactNode;\n enableMentions?: boolean;\n disableMentions?: boolean;\n mentionSearchFn?: (\n query: string,\n params?: Record<string, string>,\n ) => Promise<import(\"./BlockNoteEditorSuggestionMenuController\").MentionItem[]>;\n mentionSearchParams?: Record<string, string>;\n mentionResolveFn?: MentionResolveFn;\n suggestionMenuComponent?: React.FC<SuggestionMenuProps<DefaultReactSuggestionItem>>;\n mentionNameResolver?: MentionNameResolver;\n onWarmMentions?: (blocks: PartialBlock[]) => void;\n aiConfig?: BlockNoteAiConfig;\n // When the editor is inside a bounded flex column (parent gives it a real\n // height via flex-1+min-h-0), set this so `.bn-container` shrinks to that\n // height and scrolls internally. Without it the editor grows to fit its\n // content and pushes the surrounding form to scroll instead.\n stretch?: boolean;\n};\n\nfunction isBlockEmpty(block: any): boolean {\n if (!block || typeof block !== \"object\") return true;\n if (block.type !== \"paragraph\") return false;\n if (Array.isArray(block.children) && block.children.length > 0 && !isDocumentEmpty(block.children)) {\n return false;\n }\n if (Array.isArray(block.content)) {\n for (const inline of block.content) {\n if (typeof inline === \"string\") {\n if (inline.trim()) return false;\n } else if (inline && typeof inline === \"object\") {\n if (inline.type !== \"text\") return false;\n if (typeof inline.text === \"string\" && inline.text.trim()) return false;\n }\n }\n } else if (typeof block.content === \"string\" && block.content.trim()) {\n return false;\n }\n return true;\n}\n\nfunction isDocumentEmpty(blocks: any[]): boolean {\n if (!Array.isArray(blocks) || blocks.length === 0) return true;\n return blocks.every(isBlockEmpty);\n}\n\nconst createDiffActionsInlineContentSpec = (\n handleAcceptChange: (diffId: string) => void,\n handleRejectChange: (diffId: string) => void,\n) => {\n return createReactInlineContentSpec(\n {\n type: \"diffActions\",\n propSchema: {\n diffIds: {\n default: \"\",\n },\n },\n content: \"none\",\n },\n {\n render: (props) => {\n const diffIds = props.inlineContent.props.diffIds;\n\n return (\n <span className=\"diff-actions-container mx-2 inline-flex items-center gap-1 align-middle\">\n <Button\n title=\"Accept change\"\n onClick={(e) => {\n e.preventDefault();\n e.stopPropagation();\n diffIds.split(\",\").forEach((id: string) => handleAcceptChange(id.trim()));\n }}\n >\n <CheckIcon className=\"h-3 w-3 text-green-600\" />\n </Button>\n <Button\n title=\"Reject change\"\n className=\"mx-2 p-0\"\n onClick={(e) => {\n e.preventDefault();\n e.stopPropagation();\n diffIds.split(\",\").forEach((id: string) => handleRejectChange(id.trim()));\n }}\n >\n <XIcon className=\"h-3 w-3 text-red-600\" />\n </Button>\n </span>\n );\n },\n },\n );\n};\n\n/**\n * Custom AI menu wrapper. Surfaces our backend-driven action items\n * (Improve Writing, Fix Spelling) above the free-form prompt input.\n *\n * Why a custom wrapper instead of `<AIMenu items={…}>` with the BlockNote\n * defaults: BlockNote's `PromptSuggestionMenu` hijacks Enter to pick the\n * highlighted item whenever `items.length > 0`. We gate items on\n * - status === \"user-input\"\n * - editor has a selection\n * - prompt input is empty\n * so the moment the user types, items disappear and Enter falls back to\n * free-form submission. Outside `user-input` (review / error states) we\n * keep BlockNote's default review buttons (accept/revert/retry/cancel).\n *\n * Each custom item passes a `type` discriminator on `chatRequestOptions.body`.\n * That field flows through `chat.sendMessage(msg, opts)` to the transport's\n * `prepareSendMessagesRequest({messages, body})` (see types.ts in\n * `@blocknote/xl-ai` — `ChatRequestOptions = Parameters<Chat[\"sendMessage\"]>[1]`).\n * The backend dispatcher reads `body.type` and routes to a per-type handler\n * with its own canonical prompt. NO prompt text lives in this file.\n */\nfunction NarrAIMenu() {\n const editor = useBlockNoteEditor();\n const ai = useExtension(AIExtension);\n const dict = useAIDictionary();\n const status = useExtensionState(AIExtension, {\n selector: (s) => (s.aiMenuState !== \"closed\" ? s.aiMenuState.status : \"closed\"),\n });\n const [prompt, setPrompt] = useState(\"\");\n // Set by items that pre-fill the input (Translate) so handleSubmit knows\n // which `type` to attach when the user submits the captured text. Cleared\n // after submit or on status change.\n const pendingTypeRef = useRef<string | null>(null);\n\n useEffect(() => {\n if (status === \"ai-writing\" || status === \"user-reviewing\" || status === \"error\" || status === \"closed\") {\n setPrompt(\"\");\n pendingTypeRef.current = null;\n }\n }, [status]);\n\n // Selection-edit ops operate per-block. If the user's selection only\n // covers part of a block (cursor mid-paragraph dragged to mid-next), the\n // rewrite would silently replace the WHOLE containing blocks — beyond\n // what the user highlighted. Expand the selection to whole-block bounds\n // BEFORE invokeAI so the user sees exactly what will be rewritten.\n const expandSelectionToBlocks = useCallback(() => {\n const sel = editor.getSelection?.();\n const blocks = (sel as any)?.blocks;\n if (!Array.isArray(blocks) || blocks.length === 0) return;\n const first = blocks[0];\n const last = blocks[blocks.length - 1];\n try {\n (editor as any).setSelection?.(first, last);\n } catch {\n // If BlockNote's setSelection signature changes, fail silently — the\n // backend still operates per-block, so we just lose the visual hint.\n }\n }, [editor]);\n\n const items = useMemo(() => {\n // Outside user-input (reviewing / error), use BlockNote's default\n // review buttons (accept/revert/retry/cancel). Need to wrap onItemClick\n // because the default items expect a setPrompt argument.\n if (status !== \"user-input\") {\n return getDefaultAIMenuItems(editor, status).map((item) => ({\n ...item,\n onItemClick: () => item.onItemClick(setPrompt),\n }));\n }\n const hasSelection = editor.getSelection() !== undefined;\n const hasTyped = prompt.trim().length > 0;\n // Once the user starts typing, hide all items so Enter submits the\n // free-form (or pending-type) prompt instead of being hijacked.\n if (hasTyped) return [];\n\n // Generate from Template is shown in BOTH contexts (with and without\n // selection) because it operates on the whole document — it ignores any\n // active selection and runs the per-section template-fill flow. Listed\n // first so it's the default-highlighted item.\n const generateFromTemplate = {\n key: \"generate_from_template\",\n title: \"Generate from Template\",\n aliases: [\"generate\", \"template\", \"fill\"],\n icon: <LayoutTemplateIcon size={18} />,\n size: \"small\" as const,\n onItemClick: () => {\n void ai.invokeAI({\n userPrompt: \"fill-template\",\n useSelection: false,\n chatRequestOptions: { body: { type: \"fill-template\" } },\n });\n },\n };\n\n if (hasSelection) {\n // Selection-edit items + the always-available Generate from Template.\n // Each selection item invokes ai.invokeAI with chatRequestOptions\n // carrying the `type` body field. The userPrompt is a short tag — the\n // backend ignores it and uses the canonical prompt for the type instead.\n return [\n generateFromTemplate,\n {\n key: \"improve_writing\",\n title: \"Improve Writing\",\n aliases: [\"improve\", \"rewrite\", \"polish\"],\n icon: <SparklesIcon size={18} />,\n size: \"small\" as const,\n onItemClick: () => {\n expandSelectionToBlocks();\n void ai.invokeAI({\n userPrompt: \"improve-writing\",\n useSelection: true,\n chatRequestOptions: { body: { type: \"improve-writing\" } },\n });\n },\n },\n {\n key: \"fix_spelling\",\n title: \"Fix Spelling\",\n aliases: [\"spelling\", \"grammar\", \"typo\"],\n icon: <TypeIcon size={18} />,\n size: \"small\" as const,\n onItemClick: () => {\n expandSelectionToBlocks();\n void ai.invokeAI({\n userPrompt: \"fix-spelling\",\n useSelection: true,\n chatRequestOptions: { body: { type: \"fix-spelling\" } },\n });\n },\n },\n {\n key: \"translate\",\n title: \"Translate…\",\n aliases: [\"translate\", \"language\"],\n icon: <LanguagesIcon size={18} />,\n size: \"small\" as const,\n // Pre-fills the input with a placeholder. User appends/replaces\n // with the target language and submits via Enter. handleSubmit\n // reads pendingTypeRef and forwards `type: \"translate\"`. We\n // expand the selection now so the user sees the scope before\n // typing the language — handleSubmit doesn't re-expand.\n onItemClick: () => {\n expandSelectionToBlocks();\n pendingTypeRef.current = \"translate\";\n setPrompt(\"Translate to \");\n },\n },\n {\n key: \"simplify\",\n title: \"Simplify\",\n aliases: [\"simplify\", \"easier\", \"plain\"],\n icon: <WandSparklesIcon size={18} />,\n size: \"small\" as const,\n onItemClick: () => {\n expandSelectionToBlocks();\n void ai.invokeAI({\n userPrompt: \"simplify\",\n useSelection: true,\n chatRequestOptions: { body: { type: \"simplify\" } },\n });\n },\n },\n ];\n }\n\n // No selection (the /ai slash menu path): just Generate from Template.\n // Free-form typing still works — once the user types, items hide and\n // Enter submits with no type (backend defaults to fill-template).\n return [generateFromTemplate];\n }, [editor, status, prompt, ai, expandSelectionToBlocks]);\n\n const handleSubmit = useCallback(\n async (userPrompt: string) => {\n if (!userPrompt.trim()) return;\n const pendingType = pendingTypeRef.current;\n pendingTypeRef.current = null;\n const body = pendingType ? { type: pendingType } : undefined;\n await ai.invokeAI({\n userPrompt,\n useSelection: editor.getSelection() !== undefined,\n ...(body ? { chatRequestOptions: { body } } : {}),\n });\n },\n [ai, editor],\n );\n\n const placeholder =\n status === \"thinking\"\n ? dict.ai_menu.status.thinking\n : status === \"ai-writing\"\n ? dict.ai_menu.status.editing\n : status === \"error\"\n ? dict.ai_menu.status.error\n : dict.ai_menu.input_placeholder;\n\n const disabled = status === \"thinking\" || status === \"ai-writing\";\n\n return (\n <PromptSuggestionMenu\n items={items}\n onManualPromptSubmit={handleSubmit}\n promptText={prompt}\n onPromptTextChange={setPrompt}\n placeholder={placeholder}\n disabled={disabled}\n icon={\n <div className=\"bn-combobox-icon\">\n <SparklesIcon size={16} />\n </div>\n }\n />\n );\n}\n\nexport default function BlockNoteEditor({\n id,\n type,\n initialContent,\n onChange,\n size,\n className,\n markdownContent,\n diffContent,\n placeholder,\n bordered,\n inlineContentSpecs,\n renderOverlays,\n enableMentions,\n disableMentions,\n mentionSearchFn,\n mentionSearchParams,\n mentionResolveFn,\n suggestionMenuComponent,\n mentionNameResolver,\n onWarmMentions,\n aiConfig,\n stretch,\n}: BlockNoteEditorProps): React.JSX.Element {\n const t = useTranslations();\n const locale = useI18nLocale();\n const { company } = useCurrentUserContext<UserInterface>();\n\n const [acceptedChanges, setAcceptedChanges] = useState<Set<string>>(new Set());\n const [rejectedChanges, setRejectedChanges] = useState<Set<string>>(new Set());\n\n const editorRef = useRef<HTMLDivElement>(null);\n\n // Ensure side menu buttons don't trigger form submission\n useEffect(() => {\n if (!editorRef.current) return;\n const setButtonTypes = () => {\n editorRef.current?.querySelectorAll(\".bn-side-menu button\").forEach((btn) => {\n if (!btn.getAttribute(\"type\")) {\n btn.setAttribute(\"type\", \"button\");\n }\n });\n };\n const observer = new MutationObserver(setButtonTypes);\n observer.observe(editorRef.current, { childList: true, subtree: true });\n return () => observer.disconnect();\n }, []);\n\n const handleAcceptChange = useCallback((diffId: string) => {\n setAcceptedChanges((prev) => new Set([...prev, diffId]));\n setRejectedChanges((prev) => {\n const newSet = new Set(prev);\n newSet.delete(diffId);\n return newSet;\n });\n }, []);\n\n const handleRejectChange = useCallback((diffId: string) => {\n setRejectedChanges((prev) => new Set([...prev, diffId]));\n setAcceptedChanges((prev) => {\n const newSet = new Set(prev);\n newSet.delete(diffId);\n return newSet;\n });\n }, []);\n\n const DiffActionsInlineContent = useMemo(\n () => createDiffActionsInlineContentSpec(handleAcceptChange, handleRejectChange),\n [handleAcceptChange, handleRejectChange],\n );\n\n const mentionSpec = useMemo(\n () => createMentionInlineContentSpec(mentionResolveFn, disableMentions, mentionNameResolver),\n [disableMentions, mentionResolveFn, mentionNameResolver],\n );\n\n const schema = useMemo(\n () =>\n BlockNoteSchema.create({\n inlineContentSpecs: {\n ...defaultInlineContentSpecs,\n diffActions: DiffActionsInlineContent,\n mention: mentionSpec,\n ...inlineContentSpecs,\n },\n } as any),\n [DiffActionsInlineContent, mentionSpec, inlineContentSpecs],\n );\n\n const docRef = useRef<{ getDoc: () => any[] }>({ getDoc: () => [] });\n // Selection getter used by the AI transport to attach `selectionBlocks` to\n // the outgoing request metadata. Populated in a useEffect once the editor\n // instance exists; reads the current BlockNote selection on every send.\n const selectionRef = useRef<{ getSelectedBlocks: () => any[] }>({ getSelectedBlocks: () => [] });\n\n const companyId = company?.id;\n const aiExtension = useMemo(() => {\n if (!aiConfig) return undefined;\n const base = getPublicApiUrl();\n const url = new URL(aiConfig.endpoint, base.endsWith(\"/\") ? base : base + \"/\").toString();\n return AIExtension({\n transport: new DefaultChatTransport({\n api: url,\n credentials: \"include\",\n headers: async () => {\n const headers: Record<string, string> = { \"x-language\": locale };\n const token = await getClientToken();\n if (token) headers[\"Authorization\"] = `Bearer ${token}`;\n if (companyId) headers[\"x-companyid\"] = companyId;\n return headers;\n },\n prepareSendMessagesRequest: ({ messages, body }: any) => {\n let lastUserIdx = -1;\n for (let i = messages.length - 1; i >= 0; i--) {\n if (messages[i]?.role === \"user\") {\n lastUserIdx = i;\n break;\n }\n }\n const selectedBlocks = selectionRef.current.getSelectedBlocks();\n const augmented = messages.map((m: any, i: number) =>\n i === lastUserIdx\n ? {\n ...m,\n metadata: {\n ...(m.metadata ?? {}),\n entityType: aiConfig.entityType,\n entityId: aiConfig.entityId,\n blocks: docRef.current.getDoc(),\n selectionBlocks: selectedBlocks,\n },\n }\n : m,\n );\n return { body: { ...(body ?? {}), messages: augmented } };\n },\n }),\n });\n }, [aiConfig, companyId, locale]);\n\n const uploadImage = useCallback(\n async (file: File): Promise<string> => {\n if (!company) {\n errorToast({\n title: t(`common.errors.upload`),\n error: t(`common.errors.upload_description`),\n });\n throw new Error(t(`common.errors.upload`));\n }\n\n const fileType = file.type;\n const key = `companies/${company.id}/${type}/${id}/${file.name}`;\n\n const s3: S3Interface = await S3Service.getPreSignedUrl({\n key: key,\n contentType: fileType,\n isPublic: true,\n });\n\n await fetch(s3.url, {\n method: \"PUT\",\n headers: s3.headers,\n body: file,\n });\n\n const signedImage: S3Interface = await S3Service.getSignedUrl({\n key: key,\n isPublic: true,\n });\n\n return signedImage.url;\n },\n [company, id, t],\n );\n\n // Utility: Remove trailing empty blocks for read-only display\n const removeTrailingEmptyBlocks = useCallback(\n (blocks: PartialBlock[]): PartialBlock[] => {\n if (!blocks || blocks.length === 0) return blocks;\n\n // Only remove trailing empty blocks in read-only mode\n if (onChange !== undefined) return blocks;\n\n const result = [...blocks];\n\n // Remove trailing empty paragraph blocks, but keep at least one block\n while (result.length > 1) {\n const lastBlock = result[result.length - 1];\n\n // Check if it's an empty paragraph\n const isEmptyParagraph =\n lastBlock.type === \"paragraph\" &&\n (!lastBlock.content ||\n lastBlock.content.length === 0 ||\n (Array.isArray(lastBlock.content) && lastBlock.content.every((c: any) => !c.text || c.text.trim() === \"\")));\n\n if (isEmptyParagraph) {\n result.pop();\n } else {\n break;\n }\n }\n\n return result;\n },\n [onChange],\n );\n\n const processedContent = useMemo(() => {\n if (diffContent && initialContent) {\n try {\n const diffResult = BlockNoteDiffUtil.diff(initialContent, diffContent);\n const renderedDiff = BlockNoteWordDiffRendererUtil.renderWordDiffs(\n diffResult.blocks,\n handleAcceptChange,\n handleRejectChange,\n acceptedChanges,\n rejectedChanges,\n );\n return removeTrailingEmptyBlocks(renderedDiff);\n } catch (_error) {\n return initialContent && Array.isArray(initialContent) && initialContent.length > 0\n ? removeTrailingEmptyBlocks(initialContent)\n : [];\n }\n }\n\n if (!initialContent) {\n return [];\n }\n\n if (!Array.isArray(initialContent)) {\n return [];\n }\n\n return initialContent.length > 0 ? removeTrailingEmptyBlocks(initialContent) : [];\n }, [\n initialContent,\n diffContent,\n handleAcceptChange,\n handleRejectChange,\n acceptedChanges,\n rejectedChanges,\n removeTrailingEmptyBlocks,\n ]);\n\n const validatedInitialContent = useMemo(() => {\n if (processedContent && Array.isArray(processedContent) && processedContent.length > 0) {\n const validatedContent = processedContent.filter((block) => {\n if (!block || typeof block !== \"object\") return false;\n if (!(block as any).type) return false;\n return true;\n });\n return validatedContent.length > 0 ? (validatedContent as PartialBlock[]) : undefined;\n }\n return undefined;\n }, [processedContent]);\n\n const editor = useCreateBlockNote(\n useMemo(\n () => ({\n placeholders: {\n emptyDocument: placeholder || t(`common.blocknote.placeholder`),\n },\n schema,\n initialContent: validatedInitialContent,\n uploadFile: uploadImage,\n extensions: aiExtension ? [aiExtension] : undefined,\n dictionary: aiExtension ? { ...coreEn, ai: aiEn } : undefined,\n }),\n [placeholder, t, schema, validatedInitialContent, uploadImage, aiExtension],\n ),\n );\n\n // Tracks the hash of the document the editor itself just emitted via onChange.\n // The sync effect below uses it to skip replaceBlocks when the parent's\n // initialContent is just an echo of our own emission (form-controlled flow).\n const lastEmittedHashRef = useRef<string | null>(null);\n\n const handleChange = useCallback(async () => {\n if (!onChange) return;\n const newBlocks = editor.document;\n lastEmittedHashRef.current = JSON.stringify(newBlocks);\n const isEmpty = isDocumentEmpty(newBlocks);\n\n function hasUnresolvedDiffsRecursive(block: any): boolean {\n if (!block || typeof block !== \"object\") return false;\n let diffId = undefined;\n if (block.props && block.props.diffId) diffId = block.props.diffId;\n if (!diffId && block.attrs && block.attrs.diffId) diffId = block.attrs.diffId;\n if (diffId && !acceptedChanges.has(diffId) && !rejectedChanges.has(diffId)) {\n return true;\n }\n\n if (block.content) {\n const contentArr = Array.isArray(block.content) ? block.content : [block.content];\n for (const inline of contentArr) {\n if (inline && typeof inline === \"object\") {\n if (inline.type === \"diffActions\" && inline.props && inline.props.diffIds) {\n const ids =\n typeof inline.props.diffIds === \"string\" ? inline.props.diffIds.split(\",\") : inline.props.diffIds;\n for (const id of ids) {\n const trimmed = (id || \"\").toString().trim();\n if (trimmed && !acceptedChanges.has(trimmed) && !rejectedChanges.has(trimmed)) {\n return true;\n }\n }\n }\n if (inline.props && inline.props.diffId) {\n const diffIdInline = inline.props.diffId;\n if (diffIdInline && !acceptedChanges.has(diffIdInline) && !rejectedChanges.has(diffIdInline)) {\n return true;\n }\n }\n if (inline.children && Array.isArray(inline.children)) {\n for (const child of inline.children) {\n if (hasUnresolvedDiffsRecursive(child)) return true;\n }\n }\n }\n }\n }\n if (Array.isArray(block.children)) {\n for (const child of block.children) {\n if (hasUnresolvedDiffsRecursive(child)) return true;\n }\n }\n return false;\n }\n\n let hasUnresolvedDiff = false;\n if (Array.isArray(newBlocks)) {\n hasUnresolvedDiff = newBlocks.some((block: any) => hasUnresolvedDiffsRecursive(block));\n }\n\n onChange(newBlocks, isEmpty, hasUnresolvedDiff);\n }, [editor, onChange, id, acceptedChanges, rejectedChanges]);\n\n // Utility: deep equality for arrays of blocks\n const areBlocksEqual = (a: any[], b: any[]): boolean => {\n return JSON.stringify(a) === JSON.stringify(b);\n };\n\n // Only initialize from markdownContent once per value, and only if different\n const hasInitializedFromMarkdown = useRef<string | null>(null);\n useEffect(() => {\n const updateContent = async (markdown: string) => {\n const blocks = await editor.tryParseMarkdownToBlocks(markdown);\n if (!areBlocksEqual(blocks, editor.document)) {\n editor.replaceBlocks(editor.document, blocks);\n }\n };\n\n if (markdownContent && hasInitializedFromMarkdown.current !== markdownContent) {\n hasInitializedFromMarkdown.current = markdownContent;\n updateContent(markdownContent).then(() => handleChange());\n }\n }, [markdownContent, editor]);\n\n // Update editor content when diff content changes, but only if different\n // Prevent unnecessary replaceBlocks calls that reset scroll/cursor.\n const previousContentHashRef = useRef<string | null>(null);\n useEffect(() => {\n if (!processedContent || !editor) return;\n const hash = JSON.stringify(processedContent);\n if (previousContentHashRef.current === hash) return; // no changes\n // Skip replaceBlocks when the new initialContent is just an echo of what\n // the editor itself emitted. Without this, a form-controlled parent\n // (FormBlockNote) round-trips field.value back as initialContent on every\n // keystroke and triggers replaceBlocks, which resets the cursor and can\n // strip just-inserted inline content like mentions.\n if (lastEmittedHashRef.current === hash) {\n previousContentHashRef.current = hash;\n return;\n }\n const currentHash = JSON.stringify(editor.document);\n if (currentHash === hash) {\n previousContentHashRef.current = hash;\n return; // already in sync\n }\n editor.replaceBlocks(editor.document, processedContent as PartialBlock[]);\n previousContentHashRef.current = hash;\n }, [processedContent, editor]);\n\n useEffect(() => {\n if (!onWarmMentions || !initialContent || !Array.isArray(initialContent) || initialContent.length === 0) return;\n onWarmMentions(initialContent);\n }, [onWarmMentions, initialContent]);\n\n useEffect(() => {\n docRef.current.getDoc = () => editor?.document ?? [];\n selectionRef.current.getSelectedBlocks = () => {\n const sel = editor?.getSelection?.();\n const blocks = (sel as any)?.blocks;\n return Array.isArray(blocks) ? blocks : [];\n };\n }, [editor]);\n\n // Handle audio received from whisper transcription\n const _handleAudioReceived = useCallback(\n (message: string) => {\n try {\n // Ensure the editor has focus\n const editorElement = editorRef.current?.querySelector('[contenteditable=\"true\"]') as HTMLElement;\n if (editorElement && document.activeElement !== editorElement) {\n editorElement.focus();\n }\n\n // Insert the transcribed text at the current cursor position\n editor.insertInlineContent(message);\n } catch (error) {\n console.error(\"Error inserting transcribed text:\", error);\n // Fallback: try to insert at the end of the document\n try {\n const blocks = editor.document;\n if (blocks.length > 0) {\n const lastBlock = blocks[blocks.length - 1];\n editor.setTextCursorPosition(lastBlock.id, \"end\");\n editor.insertInlineContent(message);\n }\n } catch (fallbackError) {\n console.error(\"Fallback insertion also failed:\", fallbackError);\n }\n }\n },\n [editor],\n );\n\n return (\n <div\n ref={editorRef}\n className={cn(\n bordered ? \"rounded-md border border-input bg-input/20 dark:bg-input/30\" : \"\",\n \"flex flex-col w-full\",\n // Pin BlockNote's font-size so it doesn't jump from 14→16px when the\n // xl-ai AIMenu mounts. The shadcn theme sets `.bn-default-styles {\n // font-size: 16px }` explicitly; outside AI mode the form's text-sm\n // wins via cascade, but ForkYDocExtension re-evaluates the style\n // context on AI activation and the explicit 16px takes over.\n \"[&_.bn-default-styles]:!text-sm\",\n className,\n )}\n >\n <BlockNoteView\n editor={editor}\n onChange={handleChange}\n editable={onChange !== undefined}\n formattingToolbar={false}\n slashMenu={!aiConfig}\n theme=\"light\"\n // `className` is applied by BlockNote to both the main `.bn-container`\n // AND `editor.portalElement` (the floating-UI portal root). Gate `p-4`\n // on `.bn-container` so it doesn't add padding to the empty portal\n // element and produce a phantom scrollbar on the wrapper.\n className={cn(\n \"BlockNoteView flex-1\",\n onChange && \"[&.bn-container]:p-4\",\n // In stretch mode the parent chain caps our height via flex; without\n // these two classes the `.bn-container` keeps `min-height: auto`\n // (its content's intrinsic height) and pushes the bordered wrapper\n // — and the surrounding EditorSheet form — to scroll instead of\n // scrolling internally.\n onChange && stretch && \"[&.bn-container]:min-h-0 [&.bn-container]:overflow-y-auto\",\n size === \"sm\" && \"small\",\n )}\n >\n <BlockNoteEditorFormattingToolbar showAI={!!aiConfig} />\n {enableMentions && mentionSearchFn && (\n <BlockNoteEditorMentionSuggestionMenu\n editor={editor}\n mentionSearchFn={mentionSearchFn}\n mentionSearchParams={mentionSearchParams}\n suggestionMenuComponent={suggestionMenuComponent}\n />\n )}\n {renderOverlays?.(editor)}\n {enableMentions && mentionResolveFn && (\n <BlockNoteEditorMentionHoverCard containerRef={editorRef} mentionResolveFn={mentionResolveFn} />\n )}\n {aiConfig && (\n <SuggestionMenuController\n triggerCharacter=\"/\"\n getItems={async (query: string) =>\n filterSuggestionItems([...getDefaultReactSlashMenuItems(editor), ...getAISlashMenuItems(editor)], query)\n }\n />\n )}\n {aiConfig && <AIMenuController aiMenu={() => <NarrAIMenu />} />}\n </BlockNoteView>\n </div>\n );\n}\n","\"use client\";\n\nimport {\n BasicTextStyleButton,\n BlockTypeSelect,\n CreateLinkButton,\n FileCaptionButton,\n FileReplaceButton,\n FormattingToolbar,\n FormattingToolbarController,\n TextAlignButton,\n} from \"@blocknote/react\";\nimport { AIToolbarButton } from \"@blocknote/xl-ai\";\n\nexport function BlockNoteEditorFormattingToolbar({ showAI = false }: { showAI?: boolean }) {\n return (\n <FormattingToolbarController\n formattingToolbar={() => (\n <FormattingToolbar>\n <BlockTypeSelect key={\"blockTypeSelect\"} />\n\n <FileCaptionButton key={\"fileCaptionButton\"} />\n <FileReplaceButton key={\"replaceFileButton\"} />\n\n <BasicTextStyleButton basicTextStyle={\"bold\"} key={\"boldStyleButton\"} />\n <BasicTextStyleButton basicTextStyle={\"italic\"} key={\"italicStyleButton\"} />\n <BasicTextStyleButton basicTextStyle={\"underline\"} key={\"underlineStyleButton\"} />\n <BasicTextStyleButton basicTextStyle={\"strike\"} key={\"strikeStyleButton\"} />\n\n <TextAlignButton textAlignment={\"left\"} key={\"textAlignLeftButton\"} />\n <TextAlignButton textAlignment={\"center\"} key={\"textAlignCenterButton\"} />\n <TextAlignButton textAlignment={\"right\"} key={\"textAlignRightButton\"} />\n\n <CreateLinkButton key={\"createLinkButton\"} />\n\n {showAI ? <AIToolbarButton key={\"aiToolbarButton\"} /> : null}\n </FormattingToolbar>\n )}\n />\n );\n}\n"],"mappings":"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","names":["jsx","jsxs","id"]}
1
+ {"version":3,"sources":["../src/components/editors/BlockNoteEditor.tsx","../src/components/editors/BlockNoteEditorFormattingToolbar.tsx"],"sourcesContent":["\"use client\";\n\nimport { BlockNoteSchema, defaultInlineContentSpecs, filterSuggestionItems, PartialBlock } from \"@blocknote/core\";\nimport { en as coreEn } from \"@blocknote/core/locales\";\nimport {\n createReactInlineContentSpec,\n DefaultReactSuggestionItem,\n getDefaultReactSlashMenuItems,\n SuggestionMenuController,\n SuggestionMenuProps,\n useBlockNoteEditor,\n useCreateBlockNote,\n useExtension,\n useExtensionState,\n} from \"@blocknote/react\";\nimport { BlockNoteView } from \"@blocknote/shadcn\";\nimport \"@blocknote/shadcn/style.css\";\nimport {\n AIExtension,\n AIMenuController,\n getAISlashMenuItems,\n getDefaultAIMenuItems,\n PromptSuggestionMenu,\n useAIDictionary,\n} from \"@blocknote/xl-ai\";\nimport { en as aiEn } from \"@blocknote/xl-ai/locales\";\nimport \"@blocknote/xl-ai/style.css\";\nimport { DefaultChatTransport } from \"ai\";\nimport {\n CheckIcon,\n LanguagesIcon,\n LayoutTemplateIcon,\n SparklesIcon,\n TypeIcon,\n WandSparklesIcon,\n XIcon,\n} from \"lucide-react\";\nimport { useTranslations } from \"next-intl\";\nimport React, { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { getPublicApiUrl } from \"../../client/config\";\nimport { getClientToken } from \"../../client/token\";\nimport { useCurrentUserContext } from \"../../contexts\";\nimport { S3Interface } from \"../../features/s3/data\";\nimport { S3Service } from \"../../features/s3/data/s3.service\";\nimport { UserInterface } from \"../../features/user/data\";\nimport { useI18nLocale } from \"../../i18n/config\";\nimport { Button } from \"../../shadcnui\";\nimport { BlockNoteDiffUtil, BlockNoteWordDiffRendererUtil, cn } from \"../../utils\";\nimport { errorToast } from \"../errors\";\nimport { BlockNoteEditorFormattingToolbar } from \"./BlockNoteEditorFormattingToolbar\";\nimport { BlockNoteEditorMentionHoverCard } from \"./BlockNoteEditorMentionHoverCard\";\nimport {\n createMentionInlineContentSpec,\n type MentionNameResolver,\n type MentionResolveFn,\n} from \"./BlockNoteEditorMentionInlineContent\";\nimport { BlockNoteEditorMentionSuggestionMenu } from \"./BlockNoteEditorSuggestionMenuController\";\n\nexport type BlockNoteAiConfig = {\n endpoint: string;\n entityType: string;\n entityId?: string;\n};\n\nexport type BlockNoteEditorProps = {\n id: string;\n type: string;\n initialContent?: PartialBlock[];\n onChange?: (content: any, isEmpty: boolean, hasUnresolvedDiff: boolean) => void;\n size?: \"sm\" | \"md\";\n className?: string;\n markdownContent?: string;\n diffContent?: PartialBlock[];\n placeholder?: string;\n bordered?: boolean;\n inlineContentSpecs?: Record<string, any>;\n renderOverlays?: (editor: any) => React.ReactNode;\n enableMentions?: boolean;\n disableMentions?: boolean;\n mentionSearchFn?: (\n query: string,\n params?: Record<string, string>,\n ) => Promise<import(\"./BlockNoteEditorSuggestionMenuController\").MentionItem[]>;\n mentionSearchParams?: Record<string, string>;\n mentionResolveFn?: MentionResolveFn;\n suggestionMenuComponent?: React.FC<SuggestionMenuProps<DefaultReactSuggestionItem>>;\n mentionNameResolver?: MentionNameResolver;\n onWarmMentions?: (blocks: PartialBlock[]) => void;\n aiConfig?: BlockNoteAiConfig;\n // When the editor is inside a bounded flex column (parent gives it a real\n // height via flex-1+min-h-0), set this so `.bn-container` shrinks to that\n // height and scrolls internally. Without it the editor grows to fit its\n // content and pushes the surrounding form to scroll instead.\n stretch?: boolean;\n};\n\nfunction isBlockEmpty(block: any): boolean {\n if (!block || typeof block !== \"object\") return true;\n if (block.type !== \"paragraph\") return false;\n if (Array.isArray(block.children) && block.children.length > 0 && !isDocumentEmpty(block.children)) {\n return false;\n }\n if (Array.isArray(block.content)) {\n for (const inline of block.content) {\n if (typeof inline === \"string\") {\n if (inline.trim()) return false;\n } else if (inline && typeof inline === \"object\") {\n if (inline.type !== \"text\") return false;\n if (typeof inline.text === \"string\" && inline.text.trim()) return false;\n }\n }\n } else if (typeof block.content === \"string\" && block.content.trim()) {\n return false;\n }\n return true;\n}\n\nfunction isDocumentEmpty(blocks: any[]): boolean {\n if (!Array.isArray(blocks) || blocks.length === 0) return true;\n return blocks.every(isBlockEmpty);\n}\n\nconst createDiffActionsInlineContentSpec = (\n handleAcceptChange: (diffId: string) => void,\n handleRejectChange: (diffId: string) => void,\n) => {\n return createReactInlineContentSpec(\n {\n type: \"diffActions\",\n propSchema: {\n diffIds: {\n default: \"\",\n },\n },\n content: \"none\",\n },\n {\n render: (props) => {\n const diffIds = props.inlineContent.props.diffIds;\n\n return (\n <span className=\"diff-actions-container mx-2 inline-flex items-center gap-1 align-middle\">\n <Button\n title=\"Accept change\"\n onClick={(e) => {\n e.preventDefault();\n e.stopPropagation();\n diffIds.split(\",\").forEach((id: string) => handleAcceptChange(id.trim()));\n }}\n >\n <CheckIcon className=\"h-3 w-3 text-green-600\" />\n </Button>\n <Button\n title=\"Reject change\"\n className=\"mx-2 p-0\"\n onClick={(e) => {\n e.preventDefault();\n e.stopPropagation();\n diffIds.split(\",\").forEach((id: string) => handleRejectChange(id.trim()));\n }}\n >\n <XIcon className=\"h-3 w-3 text-red-600\" />\n </Button>\n </span>\n );\n },\n },\n );\n};\n\n/**\n * Custom AI menu wrapper. Surfaces our backend-driven action items\n * (Improve Writing, Fix Spelling) above the free-form prompt input.\n *\n * Why a custom wrapper instead of `<AIMenu items={…}>` with the BlockNote\n * defaults: BlockNote's `PromptSuggestionMenu` hijacks Enter to pick the\n * highlighted item whenever `items.length > 0`. We gate items on\n * - status === \"user-input\"\n * - editor has a selection\n * - prompt input is empty\n * so the moment the user types, items disappear and Enter falls back to\n * free-form submission. Outside `user-input` (review / error states) we\n * keep BlockNote's default review buttons (accept/revert/retry/cancel).\n *\n * Each custom item passes a `type` discriminator on `chatRequestOptions.body`.\n * That field flows through `chat.sendMessage(msg, opts)` to the transport's\n * `prepareSendMessagesRequest({messages, body})` (see types.ts in\n * `@blocknote/xl-ai` — `ChatRequestOptions = Parameters<Chat[\"sendMessage\"]>[1]`).\n * The backend dispatcher reads `body.type` and routes to a per-type handler\n * with its own canonical prompt. NO prompt text lives in this file.\n */\nfunction NarrAIMenu() {\n const editor = useBlockNoteEditor();\n const ai = useExtension(AIExtension);\n const dict = useAIDictionary();\n const status = useExtensionState(AIExtension, {\n selector: (s) => (s.aiMenuState !== \"closed\" ? s.aiMenuState.status : \"closed\"),\n });\n const [prompt, setPrompt] = useState(\"\");\n // Set by items that pre-fill the input (Translate) so handleSubmit knows\n // which `type` to attach when the user submits the captured text. Cleared\n // after submit or on status change.\n const pendingTypeRef = useRef<string | null>(null);\n\n useEffect(() => {\n if (status === \"ai-writing\" || status === \"user-reviewing\" || status === \"error\" || status === \"closed\") {\n setPrompt(\"\");\n pendingTypeRef.current = null;\n }\n }, [status]);\n\n // Selection-edit ops operate per-block. If the user's selection only\n // covers part of a block (cursor mid-paragraph dragged to mid-next), the\n // rewrite would silently replace the WHOLE containing blocks — beyond\n // what the user highlighted. Expand the selection to whole-block bounds\n // BEFORE invokeAI so the user sees exactly what will be rewritten.\n const expandSelectionToBlocks = useCallback(() => {\n const sel = editor.getSelection?.();\n const blocks = (sel as any)?.blocks;\n if (!Array.isArray(blocks) || blocks.length === 0) return;\n const first = blocks[0];\n const last = blocks[blocks.length - 1];\n try {\n (editor as any).setSelection?.(first, last);\n } catch {\n // If BlockNote's setSelection signature changes, fail silently — the\n // backend still operates per-block, so we just lose the visual hint.\n }\n }, [editor]);\n\n const items = useMemo(() => {\n // Outside user-input (reviewing / error), use BlockNote's default\n // review buttons (accept/revert/retry/cancel). Need to wrap onItemClick\n // because the default items expect a setPrompt argument.\n if (status !== \"user-input\") {\n return getDefaultAIMenuItems(editor, status).map((item) => ({\n ...item,\n onItemClick: () => item.onItemClick(setPrompt),\n }));\n }\n const hasSelection = editor.getSelection() !== undefined;\n const hasTyped = prompt.trim().length > 0;\n // Once the user starts typing, hide all items so Enter submits the\n // free-form (or pending-type) prompt instead of being hijacked.\n if (hasTyped) return [];\n\n // Generate from Template is shown in BOTH contexts (with and without\n // selection) because it operates on the whole document — it ignores any\n // active selection and runs the per-section template-fill flow. Listed\n // first so it's the default-highlighted item.\n const generateFromTemplate = {\n key: \"generate_from_template\",\n title: \"Generate from Template\",\n aliases: [\"generate\", \"template\", \"fill\"],\n icon: <LayoutTemplateIcon size={18} />,\n size: \"small\" as const,\n onItemClick: () => {\n void ai.invokeAI({\n userPrompt: \"fill-template\",\n useSelection: false,\n chatRequestOptions: { body: { type: \"fill-template\" } },\n });\n },\n };\n\n if (hasSelection) {\n // Selection-edit items + the always-available Generate from Template.\n // Each selection item invokes ai.invokeAI with chatRequestOptions\n // carrying the `type` body field. The userPrompt is a short tag — the\n // backend ignores it and uses the canonical prompt for the type instead.\n return [\n generateFromTemplate,\n {\n key: \"improve_writing\",\n title: \"Improve Writing\",\n aliases: [\"improve\", \"rewrite\", \"polish\"],\n icon: <SparklesIcon size={18} />,\n size: \"small\" as const,\n onItemClick: () => {\n expandSelectionToBlocks();\n void ai.invokeAI({\n userPrompt: \"improve-writing\",\n useSelection: true,\n chatRequestOptions: { body: { type: \"improve-writing\" } },\n });\n },\n },\n {\n key: \"fix_spelling\",\n title: \"Fix Spelling\",\n aliases: [\"spelling\", \"grammar\", \"typo\"],\n icon: <TypeIcon size={18} />,\n size: \"small\" as const,\n onItemClick: () => {\n expandSelectionToBlocks();\n void ai.invokeAI({\n userPrompt: \"fix-spelling\",\n useSelection: true,\n chatRequestOptions: { body: { type: \"fix-spelling\" } },\n });\n },\n },\n {\n key: \"translate\",\n title: \"Translate…\",\n aliases: [\"translate\", \"language\"],\n icon: <LanguagesIcon size={18} />,\n size: \"small\" as const,\n // Pre-fills the input with a placeholder. User appends/replaces\n // with the target language and submits via Enter. handleSubmit\n // reads pendingTypeRef and forwards `type: \"translate\"`. We\n // expand the selection now so the user sees the scope before\n // typing the language — handleSubmit doesn't re-expand.\n onItemClick: () => {\n expandSelectionToBlocks();\n pendingTypeRef.current = \"translate\";\n setPrompt(\"Translate to \");\n },\n },\n {\n key: \"simplify\",\n title: \"Simplify\",\n aliases: [\"simplify\", \"easier\", \"plain\"],\n icon: <WandSparklesIcon size={18} />,\n size: \"small\" as const,\n onItemClick: () => {\n expandSelectionToBlocks();\n void ai.invokeAI({\n userPrompt: \"simplify\",\n useSelection: true,\n chatRequestOptions: { body: { type: \"simplify\" } },\n });\n },\n },\n ];\n }\n\n // No selection (the /ai slash menu path): just Generate from Template.\n // Free-form typing still works — once the user types, items hide and\n // Enter submits with no type (backend defaults to fill-template).\n return [generateFromTemplate];\n }, [editor, status, prompt, ai, expandSelectionToBlocks]);\n\n const handleSubmit = useCallback(\n async (userPrompt: string) => {\n if (!userPrompt.trim()) return;\n const pendingType = pendingTypeRef.current;\n pendingTypeRef.current = null;\n const body = pendingType ? { type: pendingType } : undefined;\n await ai.invokeAI({\n userPrompt,\n useSelection: editor.getSelection() !== undefined,\n ...(body ? { chatRequestOptions: { body } } : {}),\n });\n },\n [ai, editor],\n );\n\n const placeholder =\n status === \"thinking\"\n ? dict.ai_menu.status.thinking\n : status === \"ai-writing\"\n ? dict.ai_menu.status.editing\n : status === \"error\"\n ? dict.ai_menu.status.error\n : dict.ai_menu.input_placeholder;\n\n const disabled = status === \"thinking\" || status === \"ai-writing\";\n\n return (\n <PromptSuggestionMenu\n items={items}\n onManualPromptSubmit={handleSubmit}\n promptText={prompt}\n onPromptTextChange={setPrompt}\n placeholder={placeholder}\n disabled={disabled}\n icon={\n <div className=\"bn-combobox-icon\">\n <SparklesIcon size={16} />\n </div>\n }\n />\n );\n}\n\nexport default function BlockNoteEditor({\n id,\n type,\n initialContent,\n onChange,\n size,\n className,\n markdownContent,\n diffContent,\n placeholder,\n bordered,\n inlineContentSpecs,\n renderOverlays,\n enableMentions,\n disableMentions,\n mentionSearchFn,\n mentionSearchParams,\n mentionResolveFn,\n suggestionMenuComponent,\n mentionNameResolver,\n onWarmMentions,\n aiConfig,\n stretch,\n}: BlockNoteEditorProps): React.JSX.Element {\n const t = useTranslations();\n const locale = useI18nLocale();\n const { company } = useCurrentUserContext<UserInterface>();\n\n const [acceptedChanges, setAcceptedChanges] = useState<Set<string>>(new Set());\n const [rejectedChanges, setRejectedChanges] = useState<Set<string>>(new Set());\n\n const editorRef = useRef<HTMLDivElement>(null);\n\n // Ensure side menu buttons don't trigger form submission\n useEffect(() => {\n if (!editorRef.current) return;\n const setButtonTypes = () => {\n editorRef.current?.querySelectorAll(\".bn-side-menu button\").forEach((btn) => {\n if (!btn.getAttribute(\"type\")) {\n btn.setAttribute(\"type\", \"button\");\n }\n });\n };\n const observer = new MutationObserver(setButtonTypes);\n observer.observe(editorRef.current, { childList: true, subtree: true });\n return () => observer.disconnect();\n }, []);\n\n const handleAcceptChange = useCallback((diffId: string) => {\n setAcceptedChanges((prev) => new Set([...prev, diffId]));\n setRejectedChanges((prev) => {\n const newSet = new Set(prev);\n newSet.delete(diffId);\n return newSet;\n });\n }, []);\n\n const handleRejectChange = useCallback((diffId: string) => {\n setRejectedChanges((prev) => new Set([...prev, diffId]));\n setAcceptedChanges((prev) => {\n const newSet = new Set(prev);\n newSet.delete(diffId);\n return newSet;\n });\n }, []);\n\n const DiffActionsInlineContent = useMemo(\n () => createDiffActionsInlineContentSpec(handleAcceptChange, handleRejectChange),\n [handleAcceptChange, handleRejectChange],\n );\n\n const mentionSpec = useMemo(\n () => createMentionInlineContentSpec(mentionResolveFn, disableMentions, mentionNameResolver),\n [disableMentions, mentionResolveFn, mentionNameResolver],\n );\n\n const schema = useMemo(\n () =>\n BlockNoteSchema.create({\n inlineContentSpecs: {\n ...defaultInlineContentSpecs,\n diffActions: DiffActionsInlineContent,\n mention: mentionSpec,\n ...inlineContentSpecs,\n },\n } as any),\n [DiffActionsInlineContent, mentionSpec, inlineContentSpecs],\n );\n\n const docRef = useRef<{ getDoc: () => any[] }>({ getDoc: () => [] });\n // Selection getter used by the AI transport to attach `selectionBlocks` to\n // the outgoing request metadata. Populated in a useEffect once the editor\n // instance exists; reads the current BlockNote selection on every send.\n const selectionRef = useRef<{ getSelectedBlocks: () => any[] }>({ getSelectedBlocks: () => [] });\n\n const companyId = company?.id;\n const aiExtension = useMemo(() => {\n if (!aiConfig) return undefined;\n const base = getPublicApiUrl();\n const url = new URL(aiConfig.endpoint, base.endsWith(\"/\") ? base : base + \"/\").toString();\n return AIExtension({\n transport: new DefaultChatTransport({\n api: url,\n credentials: \"include\",\n headers: async () => {\n const headers: Record<string, string> = { \"x-language\": locale };\n const token = await getClientToken();\n if (token) headers[\"Authorization\"] = `Bearer ${token}`;\n if (companyId) headers[\"x-companyid\"] = companyId;\n return headers;\n },\n prepareSendMessagesRequest: ({ messages, body }: any) => {\n let lastUserIdx = -1;\n for (let i = messages.length - 1; i >= 0; i--) {\n if (messages[i]?.role === \"user\") {\n lastUserIdx = i;\n break;\n }\n }\n const selectedBlocks = selectionRef.current.getSelectedBlocks();\n const augmented = messages.map((m: any, i: number) =>\n i === lastUserIdx\n ? {\n ...m,\n metadata: {\n ...(m.metadata ?? {}),\n entityType: aiConfig.entityType,\n entityId: aiConfig.entityId,\n blocks: docRef.current.getDoc(),\n selectionBlocks: selectedBlocks,\n },\n }\n : m,\n );\n return { body: { ...(body ?? {}), messages: augmented } };\n },\n }),\n });\n }, [aiConfig, companyId, locale]);\n\n const uploadImage = useCallback(\n async (file: File): Promise<string> => {\n if (!company) {\n errorToast({\n title: t(`common.errors.upload`),\n error: t(`common.errors.upload_description`),\n });\n throw new Error(t(`common.errors.upload`));\n }\n\n const fileType = file.type;\n const key = `companies/${company.id}/${type}/${id}/${file.name}`;\n\n const s3: S3Interface = await S3Service.getPreSignedUrl({\n key: key,\n contentType: fileType,\n isPublic: true,\n });\n\n await fetch(s3.url, {\n method: \"PUT\",\n headers: s3.headers,\n body: file,\n });\n\n const signedImage: S3Interface = await S3Service.getSignedUrl({\n key: key,\n isPublic: true,\n });\n\n return signedImage.url;\n },\n [company, id, t],\n );\n\n // Utility: Remove trailing empty blocks for read-only display\n const removeTrailingEmptyBlocks = useCallback(\n (blocks: PartialBlock[]): PartialBlock[] => {\n if (!blocks || blocks.length === 0) return blocks;\n\n // Only remove trailing empty blocks in read-only mode\n if (onChange !== undefined) return blocks;\n\n const result = [...blocks];\n\n // Remove trailing empty paragraph blocks, but keep at least one block\n while (result.length > 1) {\n const lastBlock = result[result.length - 1];\n\n // Check if it's an empty paragraph\n const isEmptyParagraph =\n lastBlock.type === \"paragraph\" &&\n (!lastBlock.content ||\n lastBlock.content.length === 0 ||\n (Array.isArray(lastBlock.content) && lastBlock.content.every((c: any) => !c.text || c.text.trim() === \"\")));\n\n if (isEmptyParagraph) {\n result.pop();\n } else {\n break;\n }\n }\n\n return result;\n },\n [onChange],\n );\n\n const processedContent = useMemo(() => {\n if (diffContent && initialContent) {\n try {\n const diffResult = BlockNoteDiffUtil.diff(initialContent, diffContent);\n const renderedDiff = BlockNoteWordDiffRendererUtil.renderWordDiffs(\n diffResult.blocks,\n handleAcceptChange,\n handleRejectChange,\n acceptedChanges,\n rejectedChanges,\n );\n return removeTrailingEmptyBlocks(renderedDiff);\n } catch (_error) {\n return initialContent && Array.isArray(initialContent) && initialContent.length > 0\n ? removeTrailingEmptyBlocks(initialContent)\n : [];\n }\n }\n\n if (!initialContent) {\n return [];\n }\n\n if (!Array.isArray(initialContent)) {\n return [];\n }\n\n return initialContent.length > 0 ? removeTrailingEmptyBlocks(initialContent) : [];\n }, [\n initialContent,\n diffContent,\n handleAcceptChange,\n handleRejectChange,\n acceptedChanges,\n rejectedChanges,\n removeTrailingEmptyBlocks,\n ]);\n\n const validatedInitialContent = useMemo(() => {\n if (processedContent && Array.isArray(processedContent) && processedContent.length > 0) {\n const validatedContent = processedContent.filter((block) => {\n if (!block || typeof block !== \"object\") return false;\n if (!(block as any).type) return false;\n return true;\n });\n return validatedContent.length > 0 ? (validatedContent as PartialBlock[]) : undefined;\n }\n return undefined;\n }, [processedContent]);\n\n const editor = useCreateBlockNote(\n useMemo(\n () => ({\n placeholders: {\n emptyDocument: placeholder || t(`common.blocknote.placeholder`),\n },\n schema,\n initialContent: validatedInitialContent,\n uploadFile: uploadImage,\n extensions: aiExtension ? [aiExtension] : undefined,\n dictionary: aiExtension ? { ...coreEn, ai: aiEn } : undefined,\n }),\n [placeholder, t, schema, validatedInitialContent, uploadImage, aiExtension],\n ),\n );\n\n // Tracks the hash of the document the editor itself just emitted via onChange.\n // The sync effect below uses it to skip replaceBlocks when the parent's\n // initialContent is just an echo of our own emission (form-controlled flow).\n const lastEmittedHashRef = useRef<string | null>(null);\n\n const handleChange = useCallback(async () => {\n if (!onChange) return;\n const newBlocks = editor.document;\n lastEmittedHashRef.current = JSON.stringify(newBlocks);\n const isEmpty = isDocumentEmpty(newBlocks);\n\n function hasUnresolvedDiffsRecursive(block: any): boolean {\n if (!block || typeof block !== \"object\") return false;\n let diffId = undefined;\n if (block.props && block.props.diffId) diffId = block.props.diffId;\n if (!diffId && block.attrs && block.attrs.diffId) diffId = block.attrs.diffId;\n if (diffId && !acceptedChanges.has(diffId) && !rejectedChanges.has(diffId)) {\n return true;\n }\n\n if (block.content) {\n const contentArr = Array.isArray(block.content) ? block.content : [block.content];\n for (const inline of contentArr) {\n if (inline && typeof inline === \"object\") {\n if (inline.type === \"diffActions\" && inline.props && inline.props.diffIds) {\n const ids =\n typeof inline.props.diffIds === \"string\" ? inline.props.diffIds.split(\",\") : inline.props.diffIds;\n for (const id of ids) {\n const trimmed = (id || \"\").toString().trim();\n if (trimmed && !acceptedChanges.has(trimmed) && !rejectedChanges.has(trimmed)) {\n return true;\n }\n }\n }\n if (inline.props && inline.props.diffId) {\n const diffIdInline = inline.props.diffId;\n if (diffIdInline && !acceptedChanges.has(diffIdInline) && !rejectedChanges.has(diffIdInline)) {\n return true;\n }\n }\n if (inline.children && Array.isArray(inline.children)) {\n for (const child of inline.children) {\n if (hasUnresolvedDiffsRecursive(child)) return true;\n }\n }\n }\n }\n }\n if (Array.isArray(block.children)) {\n for (const child of block.children) {\n if (hasUnresolvedDiffsRecursive(child)) return true;\n }\n }\n return false;\n }\n\n let hasUnresolvedDiff = false;\n if (Array.isArray(newBlocks)) {\n hasUnresolvedDiff = newBlocks.some((block: any) => hasUnresolvedDiffsRecursive(block));\n }\n\n onChange(newBlocks, isEmpty, hasUnresolvedDiff);\n }, [editor, onChange, id, acceptedChanges, rejectedChanges]);\n\n // Utility: deep equality for arrays of blocks\n const areBlocksEqual = (a: any[], b: any[]): boolean => {\n return JSON.stringify(a) === JSON.stringify(b);\n };\n\n // Only initialize from markdownContent once per value, and only if different\n const hasInitializedFromMarkdown = useRef<string | null>(null);\n useEffect(() => {\n const updateContent = async (markdown: string) => {\n const blocks = await editor.tryParseMarkdownToBlocks(markdown);\n if (!areBlocksEqual(blocks, editor.document)) {\n editor.replaceBlocks(editor.document, blocks);\n }\n };\n\n if (markdownContent && hasInitializedFromMarkdown.current !== markdownContent) {\n hasInitializedFromMarkdown.current = markdownContent;\n updateContent(markdownContent).then(() => handleChange());\n }\n }, [markdownContent, editor]);\n\n // Update editor content when diff content changes, but only if different\n // Prevent unnecessary replaceBlocks calls that reset scroll/cursor.\n const previousContentHashRef = useRef<string | null>(null);\n useEffect(() => {\n if (!processedContent || !editor) return;\n const hash = JSON.stringify(processedContent);\n if (previousContentHashRef.current === hash) return; // no changes\n // Skip replaceBlocks when the new initialContent is just an echo of what\n // the editor itself emitted. Without this, a form-controlled parent\n // (FormBlockNote) round-trips field.value back as initialContent on every\n // keystroke and triggers replaceBlocks, which resets the cursor and can\n // strip just-inserted inline content like mentions.\n if (lastEmittedHashRef.current === hash) {\n previousContentHashRef.current = hash;\n return;\n }\n const currentHash = JSON.stringify(editor.document);\n if (currentHash === hash) {\n previousContentHashRef.current = hash;\n return; // already in sync\n }\n editor.replaceBlocks(editor.document, processedContent as PartialBlock[]);\n previousContentHashRef.current = hash;\n }, [processedContent, editor]);\n\n useEffect(() => {\n if (!onWarmMentions || !initialContent || !Array.isArray(initialContent) || initialContent.length === 0) return;\n onWarmMentions(initialContent);\n }, [onWarmMentions, initialContent]);\n\n useEffect(() => {\n docRef.current.getDoc = () => editor?.document ?? [];\n selectionRef.current.getSelectedBlocks = () => {\n const sel = editor?.getSelection?.();\n const blocks = (sel as any)?.blocks;\n return Array.isArray(blocks) ? blocks : [];\n };\n }, [editor]);\n\n // Handle audio received from whisper transcription\n const _handleAudioReceived = useCallback(\n (message: string) => {\n try {\n // Ensure the editor has focus\n const editorElement = editorRef.current?.querySelector('[contenteditable=\"true\"]') as HTMLElement;\n if (editorElement && document.activeElement !== editorElement) {\n editorElement.focus();\n }\n\n // Insert the transcribed text at the current cursor position\n editor.insertInlineContent(message);\n } catch (error) {\n console.error(\"Error inserting transcribed text:\", error);\n // Fallback: try to insert at the end of the document\n try {\n const blocks = editor.document;\n if (blocks.length > 0) {\n const lastBlock = blocks[blocks.length - 1];\n editor.setTextCursorPosition(lastBlock.id, \"end\");\n editor.insertInlineContent(message);\n }\n } catch (fallbackError) {\n console.error(\"Fallback insertion also failed:\", fallbackError);\n }\n }\n },\n [editor],\n );\n\n return (\n <div\n ref={editorRef}\n className={cn(\n bordered ? \"rounded-md border border-input bg-input/20 dark:bg-input/30\" : \"\",\n \"flex flex-col w-full\",\n // Pin BlockNote's font-size so it doesn't jump from 14→16px when the\n // xl-ai AIMenu mounts. The shadcn theme sets `.bn-default-styles {\n // font-size: 16px }` explicitly; outside AI mode the form's text-sm\n // wins via cascade, but ForkYDocExtension re-evaluates the style\n // context on AI activation and the explicit 16px takes over.\n \"[&_.bn-default-styles]:!text-sm\",\n className,\n )}\n >\n <BlockNoteView\n editor={editor}\n onChange={handleChange}\n editable={onChange !== undefined}\n formattingToolbar={false}\n slashMenu={!aiConfig}\n theme=\"light\"\n // `className` is applied by BlockNote to both the main `.bn-container`\n // AND `editor.portalElement` (the floating-UI portal root). Gate `p-4`\n // on `.bn-container` so it doesn't add padding to the empty portal\n // element and produce a phantom scrollbar on the wrapper.\n className={cn(\n \"BlockNoteView flex-1\",\n onChange && \"[&.bn-container]:p-4\",\n // In stretch mode the parent chain caps our height via flex; without\n // these two classes the `.bn-container` keeps `min-height: auto`\n // (its content's intrinsic height) and pushes the bordered wrapper\n // — and the surrounding EditorSheet form — to scroll instead of\n // scrolling internally.\n onChange && stretch && \"[&.bn-container]:min-h-0 [&.bn-container]:overflow-y-auto\",\n size === \"sm\" && \"small\",\n )}\n >\n <BlockNoteEditorFormattingToolbar showAI={!!aiConfig} />\n {enableMentions && mentionSearchFn && (\n <BlockNoteEditorMentionSuggestionMenu\n editor={editor}\n mentionSearchFn={mentionSearchFn}\n mentionSearchParams={mentionSearchParams}\n suggestionMenuComponent={suggestionMenuComponent}\n />\n )}\n {renderOverlays?.(editor)}\n {enableMentions && mentionResolveFn && (\n <BlockNoteEditorMentionHoverCard containerRef={editorRef} mentionResolveFn={mentionResolveFn} />\n )}\n {aiConfig && (\n <SuggestionMenuController\n triggerCharacter=\"/\"\n getItems={async (query: string) =>\n filterSuggestionItems([...getDefaultReactSlashMenuItems(editor), ...getAISlashMenuItems(editor)], query)\n }\n />\n )}\n {aiConfig && <AIMenuController aiMenu={() => <NarrAIMenu />} />}\n </BlockNoteView>\n </div>\n );\n}\n","\"use client\";\n\nimport {\n BasicTextStyleButton,\n BlockTypeSelect,\n CreateLinkButton,\n FileCaptionButton,\n FileReplaceButton,\n FormattingToolbar,\n FormattingToolbarController,\n TextAlignButton,\n} from \"@blocknote/react\";\nimport { AIToolbarButton } from \"@blocknote/xl-ai\";\n\nexport function BlockNoteEditorFormattingToolbar({ showAI = false }: { showAI?: boolean }) {\n return (\n <FormattingToolbarController\n formattingToolbar={() => (\n <FormattingToolbar>\n <BlockTypeSelect key={\"blockTypeSelect\"} />\n\n <FileCaptionButton key={\"fileCaptionButton\"} />\n <FileReplaceButton key={\"replaceFileButton\"} />\n\n <BasicTextStyleButton basicTextStyle={\"bold\"} key={\"boldStyleButton\"} />\n <BasicTextStyleButton basicTextStyle={\"italic\"} key={\"italicStyleButton\"} />\n <BasicTextStyleButton basicTextStyle={\"underline\"} key={\"underlineStyleButton\"} />\n <BasicTextStyleButton basicTextStyle={\"strike\"} key={\"strikeStyleButton\"} />\n\n <TextAlignButton textAlignment={\"left\"} key={\"textAlignLeftButton\"} />\n <TextAlignButton textAlignment={\"center\"} key={\"textAlignCenterButton\"} />\n <TextAlignButton textAlignment={\"right\"} key={\"textAlignRightButton\"} />\n\n <CreateLinkButton key={\"createLinkButton\"} />\n\n {showAI ? <AIToolbarButton key={\"aiToolbarButton\"} /> : null}\n </FormattingToolbar>\n )}\n />\n );\n}\n"],"mappings":"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","names":["jsx","jsxs","id"]}