@carlonicora/nextjs-jsonapi 3.15.1 → 3.16.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 (71) hide show
  1. package/dist/{AbstractService-B0T7h8fX.d.mts → AbstractService-Ckm2X5fW.d.mts} +2 -5
  2. package/dist/{AbstractService-Cew0PD0L.d.ts → AbstractService-V3VGQMhL.d.ts} +2 -5
  3. package/dist/{BlockNoteEditor-6KPJWJJM.js → BlockNoteEditor-S43PQJEC.js} +93 -53
  4. package/dist/BlockNoteEditor-S43PQJEC.js.map +1 -0
  5. package/dist/{BlockNoteEditor-RRUV4TZY.mjs → BlockNoteEditor-SGISBQD5.mjs} +103 -63
  6. package/dist/BlockNoteEditor-SGISBQD5.mjs.map +1 -0
  7. package/dist/{BlockNoteViewer-P2VKEFRN.mjs → BlockNoteViewer-RK2RKOB7.mjs} +2 -2
  8. package/dist/{BlockNoteViewer-CWFPYYIU.js → BlockNoteViewer-SVVAZ6TQ.js} +3 -3
  9. package/dist/{BlockNoteViewer-CWFPYYIU.js.map → BlockNoteViewer-SVVAZ6TQ.js.map} +1 -1
  10. package/dist/{HandbookSectionInterface-CAXxbDw0.d.ts → HandbookSectionInterface-DFj2zErb.d.ts} +1 -1
  11. package/dist/{HandbookSectionInterface-BOxIdBdd.d.mts → HandbookSectionInterface-DqU_d0sy.d.mts} +1 -1
  12. package/dist/billing/index.js +401 -401
  13. package/dist/billing/index.mjs +3 -3
  14. package/dist/{chunk-2SP4NBQA.mjs → chunk-47CLHN2G.mjs} +19 -8
  15. package/dist/chunk-47CLHN2G.mjs.map +1 -0
  16. package/dist/{chunk-ZNAY65EO.js → chunk-AOWHVECO.js} +828 -817
  17. package/dist/chunk-AOWHVECO.js.map +1 -0
  18. package/dist/{chunk-VZKJIAND.mjs → chunk-IALPADOD.mjs} +2 -2
  19. package/dist/{chunk-XH4IURUD.js → chunk-ODH2LYWC.js} +7 -7
  20. package/dist/{chunk-XH4IURUD.js.map → chunk-ODH2LYWC.js.map} +1 -1
  21. package/dist/{chunk-IB7DTXWG.js → chunk-TBSMAL5Y.js} +120 -115
  22. package/dist/chunk-TBSMAL5Y.js.map +1 -0
  23. package/dist/{chunk-OSFYCSTW.mjs → chunk-YCFPSXLK.mjs} +22 -17
  24. package/dist/chunk-YCFPSXLK.mjs.map +1 -0
  25. package/dist/client/index.js +4 -4
  26. package/dist/client/index.mjs +3 -3
  27. package/dist/components/index.d.mts +37 -6
  28. package/dist/components/index.d.ts +37 -6
  29. package/dist/components/index.js +4 -4
  30. package/dist/components/index.mjs +3 -3
  31. package/dist/contexts/index.js +4 -4
  32. package/dist/contexts/index.mjs +3 -3
  33. package/dist/core/index.d.mts +12 -7
  34. package/dist/core/index.d.ts +12 -7
  35. package/dist/core/index.js +2 -2
  36. package/dist/core/index.mjs +1 -1
  37. package/dist/features/help/index.js +37 -37
  38. package/dist/features/help/index.mjs +3 -3
  39. package/dist/features/tokenusage/index.d.mts +1 -1
  40. package/dist/features/tokenusage/index.d.ts +1 -1
  41. package/dist/features/tokenusage/index.js +101 -101
  42. package/dist/features/tokenusage/index.mjs +3 -3
  43. package/dist/index.d.mts +5 -5
  44. package/dist/index.d.ts +5 -5
  45. package/dist/index.js +3 -3
  46. package/dist/index.mjs +2 -2
  47. package/dist/{s3.service-CUGarZs3.d.ts → s3.service-DJHqEZAp.d.ts} +1 -1
  48. package/dist/{s3.service-C0Yq2Sx3.d.mts → s3.service-DaRFLnrX.d.mts} +1 -1
  49. package/dist/server/index.d.mts +2 -2
  50. package/dist/server/index.d.ts +2 -2
  51. package/dist/server/index.js +3 -3
  52. package/dist/server/index.mjs +1 -1
  53. package/package.json +1 -1
  54. package/src/components/editors/BlockNoteEditor.tsx +70 -33
  55. package/src/components/editors/BlockNoteEditorAiActions.tsx +49 -0
  56. package/src/components/editors/__tests__/BlockNoteEditorAiActions.test.ts +25 -0
  57. package/src/components/editors/index.ts +2 -1
  58. package/src/components/forms/FormBlockNote.tsx +8 -0
  59. package/src/components/forms/FormFieldWrapper.tsx +22 -6
  60. package/src/core/abstracts/AbstractService.ts +9 -30
  61. package/src/core/abstracts/ClientAbstractService.ts +5 -0
  62. package/src/core/abstracts/__tests__/lastApiResponse.spec.ts +45 -0
  63. package/src/core/abstracts/lastApiResponse.ts +37 -0
  64. package/dist/BlockNoteEditor-6KPJWJJM.js.map +0 -1
  65. package/dist/BlockNoteEditor-RRUV4TZY.mjs.map +0 -1
  66. package/dist/chunk-2SP4NBQA.mjs.map +0 -1
  67. package/dist/chunk-IB7DTXWG.js.map +0 -1
  68. package/dist/chunk-OSFYCSTW.mjs.map +0 -1
  69. package/dist/chunk-ZNAY65EO.js.map +0 -1
  70. /package/dist/{BlockNoteViewer-P2VKEFRN.mjs.map → BlockNoteViewer-RK2RKOB7.mjs.map} +0 -0
  71. /package/dist/{chunk-VZKJIAND.mjs.map → chunk-IALPADOD.mjs.map} +0 -0
@@ -19,10 +19,7 @@ interface SelfRef {
19
19
  interface TotalRef {
20
20
  total?: number;
21
21
  }
22
- declare function getLastApiTotal(): number | undefined;
23
- declare function clearLastApiTotal(): void;
24
- declare function getLastApiMeta(): Record<string, any> | undefined;
25
- declare function clearLastApiMeta(): void;
22
+
26
23
  /**
27
24
  * Set a global error handler for API errors (client-side only).
28
25
  * This handler will be called instead of throwing errors.
@@ -121,4 +118,4 @@ declare abstract class AbstractService {
121
118
  }): Promise<any>;
122
119
  }
123
120
 
124
- export { AbstractService as A, HttpMethod as H, type NextRef as N, type PreviousRef as P, type SelfRef as S, type TotalRef as T, getLastApiMeta as a, clearLastApiMeta as b, clearLastApiTotal as c, getGlobalErrorHandler as d, getLastApiTotal as g, setGlobalErrorHandler as s };
121
+ export { AbstractService as A, HttpMethod as H, type NextRef as N, type PreviousRef as P, type SelfRef as S, type TotalRef as T, getGlobalErrorHandler as g, setGlobalErrorHandler as s };
@@ -19,10 +19,7 @@ interface SelfRef {
19
19
  interface TotalRef {
20
20
  total?: number;
21
21
  }
22
- declare function getLastApiTotal(): number | undefined;
23
- declare function clearLastApiTotal(): void;
24
- declare function getLastApiMeta(): Record<string, any> | undefined;
25
- declare function clearLastApiMeta(): void;
22
+
26
23
  /**
27
24
  * Set a global error handler for API errors (client-side only).
28
25
  * This handler will be called instead of throwing errors.
@@ -121,4 +118,4 @@ declare abstract class AbstractService {
121
118
  }): Promise<any>;
122
119
  }
123
120
 
124
- export { AbstractService as A, HttpMethod as H, type NextRef as N, type PreviousRef as P, type SelfRef as S, type TotalRef as T, getLastApiMeta as a, clearLastApiMeta as b, clearLastApiTotal as c, getGlobalErrorHandler as d, getLastApiTotal as g, setGlobalErrorHandler as s };
121
+ export { AbstractService as A, HttpMethod as H, type NextRef as N, type PreviousRef as P, type SelfRef as S, type TotalRef as T, getGlobalErrorHandler as g, setGlobalErrorHandler as s };
@@ -6,17 +6,17 @@
6
6
 
7
7
 
8
8
 
9
- var _chunkZNAY65EOjs = require('./chunk-ZNAY65EO.js');
9
+ var _chunkAOWHVECOjs = require('./chunk-AOWHVECO.js');
10
10
 
11
11
 
12
12
 
13
- var _chunkXH4IURUDjs = require('./chunk-XH4IURUD.js');
13
+ var _chunkODH2LYWCjs = require('./chunk-ODH2LYWC.js');
14
14
 
15
15
 
16
16
 
17
17
 
18
18
 
19
- var _chunkIB7DTXWGjs = require('./chunk-IB7DTXWG.js');
19
+ var _chunkTBSMAL5Yjs = require('./chunk-TBSMAL5Y.js');
20
20
 
21
21
 
22
22
  var _chunkLXKSUWAVjs = require('./chunk-LXKSUWAV.js');
@@ -52,19 +52,39 @@ var _xlai = require('@blocknote/xl-ai');
52
52
  var _locales3 = require('@blocknote/xl-ai/locales');
53
53
  require('@blocknote/xl-ai/style.css');
54
54
  var _ai = require('ai');
55
-
56
-
57
-
58
-
59
-
60
-
61
-
62
-
63
55
  var _lucidereact = require('lucide-react');
64
56
  var _nextintl = require('next-intl');
65
57
  var _nextthemes = require('next-themes');
66
58
  var _react3 = require('react');
67
59
 
60
+ // src/components/editors/BlockNoteEditorAiActions.tsx
61
+
62
+ var _jsxruntime = require('react/jsx-runtime');
63
+ var DEFAULT_AI_GENERATE_ACTIONS = ["fill-template"];
64
+ var ITEMS = {
65
+ "fill-template": {
66
+ key: "generate_from_template",
67
+ title: "Generate from Template",
68
+ aliases: ["generate", "template", "fill"],
69
+ icon: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.LayoutTemplateIcon, { size: 18 }),
70
+ size: "small"
71
+ },
72
+ "draft-impression": {
73
+ key: "suggest_impression",
74
+ title: "Suggest impression",
75
+ aliases: ["suggest", "impression"],
76
+ icon: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.SparklesIcon, { size: 18 }),
77
+ size: "small"
78
+ }
79
+ };
80
+ function generateActionItems(actions, invoke) {
81
+ return (_nullishCoalesce(actions, () => ( DEFAULT_AI_GENERATE_ACTIONS))).map((type) => ({
82
+ ...ITEMS[type],
83
+ onItemClick: /* @__PURE__ */ _chunk7QVYU63Ejs.__name.call(void 0, () => invoke(type), "onItemClick")
84
+ }));
85
+ }
86
+ _chunk7QVYU63Ejs.__name.call(void 0, generateActionItems, "generateActionItems");
87
+
68
88
  // src/components/editors/BlockNoteEditorFormattingToolbar.tsx
69
89
 
70
90
 
@@ -77,7 +97,7 @@ var _react3 = require('react');
77
97
 
78
98
 
79
99
 
80
- var _jsxruntime = require('react/jsx-runtime');
100
+
81
101
  function BlockNoteEditorFormattingToolbar({ showAI = false }) {
82
102
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
83
103
  _react.FormattingToolbarController,
@@ -145,7 +165,7 @@ var createDiffActionsInlineContentSpec = /* @__PURE__ */ _chunk7QVYU63Ejs.__name
145
165
  const diffIds = props.inlineContent.props.diffIds;
146
166
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "span", { className: "diff-actions-container mx-2 inline-flex items-center gap-1 align-middle", children: [
147
167
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
148
- _chunkZNAY65EOjs.Button,
168
+ _chunkAOWHVECOjs.Button,
149
169
  {
150
170
  title: "Accept change",
151
171
  onClick: (e) => {
@@ -157,7 +177,7 @@ var createDiffActionsInlineContentSpec = /* @__PURE__ */ _chunk7QVYU63Ejs.__name
157
177
  }
158
178
  ),
159
179
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
160
- _chunkZNAY65EOjs.Button,
180
+ _chunkAOWHVECOjs.Button,
161
181
  {
162
182
  title: "Reject change",
163
183
  className: "mx-2 p-0",
@@ -174,7 +194,7 @@ var createDiffActionsInlineContentSpec = /* @__PURE__ */ _chunk7QVYU63Ejs.__name
174
194
  }
175
195
  );
176
196
  }, "createDiffActionsInlineContentSpec");
177
- function NarrAIMenu() {
197
+ function NarrAIMenu({ actions }) {
178
198
  const editor = _react.useBlockNoteEditor.call(void 0, );
179
199
  const ai = _react.useExtension.call(void 0, _xlai.AIExtension);
180
200
  const dict = _xlai.useAIDictionary.call(void 0, );
@@ -210,23 +230,17 @@ function NarrAIMenu() {
210
230
  const hasSelection = editor.getSelection() !== void 0;
211
231
  const hasTyped = prompt.trim().length > 0;
212
232
  if (hasTyped) return [];
213
- const generateFromTemplate = {
214
- key: "generate_from_template",
215
- title: "Generate from Template",
216
- aliases: ["generate", "template", "fill"],
217
- icon: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.LayoutTemplateIcon, { size: 18 }),
218
- size: "small",
219
- onItemClick: /* @__PURE__ */ _chunk7QVYU63Ejs.__name.call(void 0, () => {
220
- void ai.invokeAI({
221
- userPrompt: "fill-template",
222
- useSelection: false,
223
- chatRequestOptions: { body: { type: "fill-template" } }
224
- });
225
- }, "onItemClick")
226
- };
233
+ const invokeGenerate = /* @__PURE__ */ _chunk7QVYU63Ejs.__name.call(void 0, (type) => {
234
+ void ai.invokeAI({
235
+ userPrompt: type,
236
+ useSelection: false,
237
+ chatRequestOptions: { body: { type } }
238
+ });
239
+ }, "invokeGenerate");
240
+ const generateItems = generateActionItems(actions, invokeGenerate);
227
241
  if (hasSelection) {
228
242
  return [
229
- generateFromTemplate,
243
+ ...generateItems,
230
244
  {
231
245
  key: "improve_writing",
232
246
  title: "Improve Writing",
@@ -291,8 +305,8 @@ function NarrAIMenu() {
291
305
  }
292
306
  ];
293
307
  }
294
- return [generateFromTemplate];
295
- }, [editor, status, prompt, ai, expandSelectionToBlocks]);
308
+ return generateItems;
309
+ }, [editor, status, prompt, ai, expandSelectionToBlocks, actions]);
296
310
  const handleSubmit = _react3.useCallback.call(void 0,
297
311
  async (userPrompt) => {
298
312
  if (!userPrompt.trim()) return;
@@ -346,12 +360,13 @@ function BlockNoteEditor({
346
360
  onWarmMentions,
347
361
  aiConfig,
348
362
  stretch,
349
- aiEnabled = true
363
+ aiEnabled = true,
364
+ aiHandleRef
350
365
  }) {
351
366
  const t = _nextintl.useTranslations.call(void 0, );
352
- const locale = _chunkXH4IURUDjs.useI18nLocale.call(void 0, );
367
+ const locale = _chunkODH2LYWCjs.useI18nLocale.call(void 0, );
353
368
  const { resolvedTheme } = _nextthemes.useTheme.call(void 0, );
354
- const company = _nullishCoalesce(_optionalChain([_chunkZNAY65EOjs.useCurrentUserContextOptional.call(void 0, ), 'optionalAccess', _6 => _6.company]), () => ( null));
369
+ const company = _nullishCoalesce(_optionalChain([_chunkAOWHVECOjs.useCurrentUserContextOptional.call(void 0, ), 'optionalAccess', _6 => _6.company]), () => ( null));
355
370
  const [acceptedChanges, setAcceptedChanges] = _react3.useState.call(void 0, /* @__PURE__ */ new Set());
356
371
  const [rejectedChanges, setRejectedChanges] = _react3.useState.call(void 0, /* @__PURE__ */ new Set());
357
372
  const editorRef = _react3.useRef.call(void 0, null);
@@ -389,7 +404,7 @@ function BlockNoteEditor({
389
404
  [handleAcceptChange, handleRejectChange]
390
405
  );
391
406
  const mentionSpec = _react3.useMemo.call(void 0,
392
- () => _chunkZNAY65EOjs.createMentionInlineContentSpec.call(void 0, mentionResolveFn, disableMentions, mentionNameResolver),
407
+ () => _chunkAOWHVECOjs.createMentionInlineContentSpec.call(void 0, mentionResolveFn, disableMentions, mentionNameResolver),
393
408
  [disableMentions, mentionResolveFn, mentionNameResolver]
394
409
  );
395
410
  const schema = _react3.useMemo.call(void 0,
@@ -408,7 +423,7 @@ function BlockNoteEditor({
408
423
  const companyId = _optionalChain([company, 'optionalAccess', _12 => _12.id]);
409
424
  const aiExtension = _react3.useMemo.call(void 0, () => {
410
425
  if (!aiConfig || !aiEnabled) return void 0;
411
- const base = _chunkXH4IURUDjs.getPublicApiUrl.call(void 0, );
426
+ const base = _chunkODH2LYWCjs.getPublicApiUrl.call(void 0, );
412
427
  const url = new URL(aiConfig.endpoint, base.endsWith("/") ? base : base + "/").toString();
413
428
  return _xlai.AIExtension.call(void 0, {
414
429
  transport: new (0, _ai.DefaultChatTransport)({
@@ -450,7 +465,7 @@ function BlockNoteEditor({
450
465
  const uploadImage = _react3.useCallback.call(void 0,
451
466
  async (file) => {
452
467
  if (!company) {
453
- _chunkZNAY65EOjs.errorToast.call(void 0, {
468
+ _chunkAOWHVECOjs.errorToast.call(void 0, {
454
469
  title: t(`common.errors.upload`),
455
470
  error: t(`common.errors.upload_description`)
456
471
  });
@@ -458,7 +473,7 @@ function BlockNoteEditor({
458
473
  }
459
474
  const fileType = file.type;
460
475
  const key = `companies/${company.id}/${type}/${id}/${file.name}`;
461
- const s3 = await _chunkIB7DTXWGjs.S3Service.getPreSignedUrl({
476
+ const s3 = await _chunkTBSMAL5Yjs.S3Service.getPreSignedUrl({
462
477
  key,
463
478
  contentType: fileType,
464
479
  isPublic: true
@@ -468,7 +483,7 @@ function BlockNoteEditor({
468
483
  headers: s3.headers,
469
484
  body: file
470
485
  });
471
- const signedImage = await _chunkIB7DTXWGjs.S3Service.getSignedUrl({
486
+ const signedImage = await _chunkTBSMAL5Yjs.S3Service.getSignedUrl({
472
487
  key,
473
488
  isPublic: true
474
489
  });
@@ -497,8 +512,8 @@ function BlockNoteEditor({
497
512
  const processedContent = _react3.useMemo.call(void 0, () => {
498
513
  if (diffContent && initialContent) {
499
514
  try {
500
- const diffResult = _chunkIB7DTXWGjs.BlockNoteDiffUtil.diff(initialContent, diffContent);
501
- const renderedDiff = _chunkIB7DTXWGjs.BlockNoteWordDiffRendererUtil.renderWordDiffs(
515
+ const diffResult = _chunkTBSMAL5Yjs.BlockNoteDiffUtil.diff(initialContent, diffContent);
516
+ const renderedDiff = _chunkTBSMAL5Yjs.BlockNoteWordDiffRendererUtil.renderWordDiffs(
502
517
  diffResult.blocks,
503
518
  handleAcceptChange,
504
519
  handleRejectChange,
@@ -552,6 +567,31 @@ function BlockNoteEditor({
552
567
  [placeholder, t, schema, validatedInitialContent, uploadImage, aiExtension]
553
568
  )
554
569
  );
570
+ _react3.useEffect.call(void 0, () => {
571
+ if (!aiHandleRef) return;
572
+ if (!aiConfig || !aiEnabled) {
573
+ aiHandleRef.current = null;
574
+ return;
575
+ }
576
+ aiHandleRef.current = {
577
+ invokeAi: /* @__PURE__ */ _chunk7QVYU63Ejs.__name.call(void 0, (type2) => {
578
+ const ai = editor.getExtension(_xlai.AIExtension);
579
+ if (!ai) return;
580
+ editor.focus();
581
+ const blocks = editor.document;
582
+ const anchor = _optionalChain([blocks, 'optionalAccess', _15 => _15[blocks.length - 1]]);
583
+ if (_optionalChain([anchor, 'optionalAccess', _16 => _16.id])) ai.openAIMenuAtBlock(anchor.id);
584
+ void ai.invokeAI({
585
+ userPrompt: type2,
586
+ useSelection: false,
587
+ chatRequestOptions: { body: { type: type2 } }
588
+ });
589
+ }, "invokeAi")
590
+ };
591
+ return () => {
592
+ aiHandleRef.current = null;
593
+ };
594
+ }, [aiHandleRef, aiConfig, aiEnabled, editor]);
555
595
  const lastEmittedHashRef = _react3.useRef.call(void 0, null);
556
596
  const handleChange = _react3.useCallback.call(void 0, async () => {
557
597
  if (!onChange) return;
@@ -645,17 +685,17 @@ function BlockNoteEditor({
645
685
  onWarmMentions(initialContent);
646
686
  }, [onWarmMentions, initialContent]);
647
687
  _react3.useEffect.call(void 0, () => {
648
- docRef.current.getDoc = () => _nullishCoalesce(_optionalChain([editor, 'optionalAccess', _15 => _15.document]), () => ( []));
688
+ docRef.current.getDoc = () => _nullishCoalesce(_optionalChain([editor, 'optionalAccess', _17 => _17.document]), () => ( []));
649
689
  selectionRef.current.getSelectedBlocks = () => {
650
- const sel = _optionalChain([editor, 'optionalAccess', _16 => _16.getSelection, 'optionalCall', _17 => _17()]);
651
- const blocks = _optionalChain([sel, 'optionalAccess', _18 => _18.blocks]);
690
+ const sel = _optionalChain([editor, 'optionalAccess', _18 => _18.getSelection, 'optionalCall', _19 => _19()]);
691
+ const blocks = _optionalChain([sel, 'optionalAccess', _20 => _20.blocks]);
652
692
  return Array.isArray(blocks) ? blocks : [];
653
693
  };
654
694
  }, [editor]);
655
695
  const _handleAudioReceived = _react3.useCallback.call(void 0,
656
696
  (message) => {
657
697
  try {
658
- const editorElement = _optionalChain([editorRef, 'access', _19 => _19.current, 'optionalAccess', _20 => _20.querySelector, 'call', _21 => _21('[contenteditable="true"]')]);
698
+ const editorElement = _optionalChain([editorRef, 'access', _21 => _21.current, 'optionalAccess', _22 => _22.querySelector, 'call', _23 => _23('[contenteditable="true"]')]);
659
699
  if (editorElement && document.activeElement !== editorElement) {
660
700
  editorElement.focus();
661
701
  }
@@ -680,7 +720,7 @@ function BlockNoteEditor({
680
720
  "div",
681
721
  {
682
722
  ref: editorRef,
683
- className: _chunkIB7DTXWGjs.cn.call(void 0,
723
+ className: _chunkTBSMAL5Yjs.cn.call(void 0,
684
724
  bordered ? "rounded-md border border-input bg-input/20 dark:bg-input/30" : "",
685
725
  "flex flex-col w-full",
686
726
  // Pin BlockNote's font-size so it doesn't jump from 14→16px when the
@@ -700,7 +740,7 @@ function BlockNoteEditor({
700
740
  formattingToolbar: false,
701
741
  slashMenu: !aiConfig || !aiEnabled,
702
742
  theme: resolvedTheme === "dark" ? "dark" : "light",
703
- className: _chunkIB7DTXWGjs.cn.call(void 0,
743
+ className: _chunkTBSMAL5Yjs.cn.call(void 0,
704
744
  "BlockNoteView flex-1",
705
745
  onChange && "[&.bn-container]:p-4",
706
746
  // In stretch mode the parent chain caps our height via flex; without
@@ -714,7 +754,7 @@ function BlockNoteEditor({
714
754
  children: [
715
755
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, BlockNoteEditorFormattingToolbar, { showAI: !!aiConfig && aiEnabled }),
716
756
  enableMentions && mentionSearchFn && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
717
- _chunkZNAY65EOjs.BlockNoteEditorMentionSuggestionMenu,
757
+ _chunkAOWHVECOjs.BlockNoteEditorMentionSuggestionMenu,
718
758
  {
719
759
  editor,
720
760
  mentionSearchFn,
@@ -722,8 +762,8 @@ function BlockNoteEditor({
722
762
  suggestionMenuComponent
723
763
  }
724
764
  ),
725
- _optionalChain([renderOverlays, 'optionalCall', _22 => _22(editor)]),
726
- enableMentions && mentionResolveFn && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkZNAY65EOjs.BlockNoteEditorMentionHoverCard, { containerRef: editorRef, mentionResolveFn }),
765
+ _optionalChain([renderOverlays, 'optionalCall', _24 => _24(editor)]),
766
+ enableMentions && mentionResolveFn && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkAOWHVECOjs.BlockNoteEditorMentionHoverCard, { containerRef: editorRef, mentionResolveFn }),
727
767
  aiConfig && aiEnabled && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
728
768
  _react.SuggestionMenuController,
729
769
  {
@@ -731,7 +771,7 @@ function BlockNoteEditor({
731
771
  getItems: async (query) => _core.filterSuggestionItems.call(void 0, [..._react.getDefaultReactSlashMenuItems.call(void 0, editor), ..._xlai.getAISlashMenuItems.call(void 0, editor)], query)
732
772
  }
733
773
  ),
734
- aiConfig && aiEnabled && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _xlai.AIMenuController, { aiMenu: () => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, NarrAIMenu, {}) })
774
+ aiConfig && aiEnabled && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _xlai.AIMenuController, { aiMenu: () => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, NarrAIMenu, { actions: aiConfig.actions }) })
735
775
  ]
736
776
  }
737
777
  )
@@ -742,4 +782,4 @@ _chunk7QVYU63Ejs.__name.call(void 0, BlockNoteEditor, "BlockNoteEditor");
742
782
 
743
783
 
744
784
  exports.default = BlockNoteEditor;
745
- //# sourceMappingURL=BlockNoteEditor-6KPJWJJM.js.map
785
+ //# sourceMappingURL=BlockNoteEditor-S43PQJEC.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/home/runner/work/nextjs-jsonapi/nextjs-jsonapi/dist/BlockNoteEditor-S43PQJEC.js","../src/components/editors/BlockNoteEditor.tsx","../src/components/editors/BlockNoteEditorAiActions.tsx","../src/components/editors/BlockNoteEditorFormattingToolbar.tsx"],"names":["jsx","jsxs","SparklesIcon","type"],"mappings":"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","file":"/home/runner/work/nextjs-jsonapi/nextjs-jsonapi/dist/BlockNoteEditor-S43PQJEC.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 { CheckIcon, LanguagesIcon, SparklesIcon, TypeIcon, WandSparklesIcon, XIcon } from \"lucide-react\";\nimport { useTranslations } from \"next-intl\";\nimport { useTheme } from \"next-themes\";\nimport React, { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { getPublicApiUrl } from \"../../client/config\";\nimport { getClientToken } from \"../../client/token\";\nimport { useCurrentUserContextOptional } 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 { BlockNoteAiGenerateAction, generateActionItems } from \"./BlockNoteEditorAiActions\";\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\n/**\n * Lets app code trigger a whole-document AI action from OUTSIDE the editor\n * (a visible button next to the field label, for instance) without owning the\n * BlockNote instance. Delivered through a plain prop, not a React `ref`:\n * `BlockNoteEditorContainer` is a `next/dynamic` import wrapped in\n * `React.memo`, and refs do not pass through that reliably.\n */\nexport type BlockNoteAiHandle = { invokeAi: (type: BlockNoteAiGenerateAction) => void };\n\nexport type BlockNoteAiConfig = {\n endpoint: string;\n entityType: string;\n entityId?: string;\n /** Whole-document actions shown when nothing is selected. Default: [\"fill-template\"]. */\n actions?: BlockNoteAiGenerateAction[];\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 // Gates AI on top of `aiConfig` (credit availability, etc.). Defaults to\n // true so existing callers that only pass `aiConfig` are unaffected. When\n // false, no AI extension is created, the AI toolbar button and AI slash\n // items are hidden, and the editor falls back to the plain slash menu.\n aiEnabled?: boolean;\n // Filled with a {@link BlockNoteAiHandle} while the editor is mounted and AI\n // is on, so a control outside the editor can run a whole-document AI action.\n // Cleared on unmount and whenever AI is unavailable.\n aiHandleRef?: React.MutableRefObject<BlockNoteAiHandle | null>;\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=\"text-success h-3 w-3\" />\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=\"text-destructive h-3 w-3\" />\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({ actions }: { actions?: BlockNoteAiGenerateAction[] }) {\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 const invokeGenerate = (type: BlockNoteAiGenerateAction) => {\n void ai.invokeAI({\n userPrompt: type,\n useSelection: false,\n chatRequestOptions: { body: { type } },\n });\n };\n // Whole-document items are shown in BOTH contexts (with and without\n // selection) because they operate on the whole document — they ignore any\n // active selection. Listed first so the first one is the\n // default-highlighted item.\n const generateItems = generateActionItems(actions, invokeGenerate);\n\n if (hasSelection) {\n // Selection-edit items + the always-available whole-document items.\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 ...generateItems,\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 the whole-document items.\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 generateItems;\n }, [editor, status, prompt, ai, expandSelectionToBlocks, actions]);\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 aiEnabled = true,\n aiHandleRef,\n}: BlockNoteEditorProps): React.JSX.Element {\n const t = useTranslations();\n const locale = useI18nLocale();\n const { resolvedTheme } = useTheme();\n // Optional on purpose: a host app may mount its own user context instead of\n // this package's, and the editor already degrades without a company — image\n // upload reports it (`uploadImage`) and the AI transport simply omits the\n // company header. Throwing here would take the whole page down instead.\n const company = useCurrentUserContextOptional<UserInterface>()?.company ?? null;\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 || !aiEnabled) 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, aiEnabled, 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 // Publish the outside-the-editor AI trigger. `editor.getExtension(AIExtension)`\n // is BlockNote 0.54's documented lookup by extension factory (core's\n // `getExtension` resolves a function argument through `extensionFactories`),\n // so the instance is reachable without the `useExtension` hook that only\n // works inside the BlockNote context (NarrAIMenu). The menu MUST be opened\n // first: `invokeAI` routes every status update through `setAIResponseStatus`,\n // which is a no-op while `aiMenuState === \"closed\"` — without the open menu\n // the request runs but the accept / reject UI never appears.\n useEffect(() => {\n if (!aiHandleRef) return;\n if (!aiConfig || !aiEnabled) {\n aiHandleRef.current = null;\n return;\n }\n aiHandleRef.current = {\n invokeAi: (type: BlockNoteAiGenerateAction) => {\n const ai = editor.getExtension(AIExtension);\n if (!ai) return;\n editor.focus();\n const blocks = editor.document;\n const anchor = blocks?.[blocks.length - 1];\n if (anchor?.id) ai.openAIMenuAtBlock(anchor.id);\n void ai.invokeAI({\n userPrompt: type,\n useSelection: false,\n chatRequestOptions: { body: { type } },\n });\n },\n };\n return () => {\n aiHandleRef.current = null;\n };\n }, [aiHandleRef, aiConfig, aiEnabled, editor]);\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 || !aiEnabled}\n // Follow the app theme: hardcoding \"light\" leaves dark (light-theme)\n // text on the dark card, which is nearly unreadable in dark mode.\n theme={resolvedTheme === \"dark\" ? \"dark\" : \"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 && aiEnabled} />\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 && aiEnabled && (\n <SuggestionMenuController\n triggerCharacter=\"/\"\n getItems={async (query: string) =>\n filterSuggestionItems([...getDefaultReactSlashMenuItems(editor), ...getAISlashMenuItems(editor)], query)\n }\n />\n )}\n {aiConfig && aiEnabled && <AIMenuController aiMenu={() => <NarrAIMenu actions={aiConfig.actions} />} />}\n </BlockNoteView>\n </div>\n );\n}\n","import { LayoutTemplateIcon, SparklesIcon } from \"lucide-react\";\nimport React from \"react\";\n\n/**\n * Whole-document AI actions an editor can offer in its AI menu when nothing\n * is selected. Each maps to a backend `type` discriminator; NO prompt text\n * lives here. Selection-edit actions (Improve, Fix spelling, …) are separate\n * and always available.\n */\nexport type BlockNoteAiGenerateAction = \"fill-template\" | \"draft-impression\";\n\nexport const DEFAULT_AI_GENERATE_ACTIONS: BlockNoteAiGenerateAction[] = [\"fill-template\"];\n\nexport type AiGenerateMenuItem = {\n key: string;\n title: string;\n aliases: string[];\n /** BlockNote's DefaultReactSuggestionItem types icon as an element, not ReactNode. */\n icon: React.JSX.Element;\n size: \"small\";\n onItemClick: () => void;\n};\n\nconst ITEMS: Record<BlockNoteAiGenerateAction, Omit<AiGenerateMenuItem, \"onItemClick\">> = {\n \"fill-template\": {\n key: \"generate_from_template\",\n title: \"Generate from Template\",\n aliases: [\"generate\", \"template\", \"fill\"],\n icon: <LayoutTemplateIcon size={18} />,\n size: \"small\",\n },\n \"draft-impression\": {\n key: \"suggest_impression\",\n title: \"Suggest impression\",\n aliases: [\"suggest\", \"impression\"],\n icon: <SparklesIcon size={18} />,\n size: \"small\",\n },\n};\n\nexport function generateActionItems(\n actions: BlockNoteAiGenerateAction[] | undefined,\n invoke: (type: BlockNoteAiGenerateAction) => void,\n): AiGenerateMenuItem[] {\n return (actions ?? DEFAULT_AI_GENERATE_ACTIONS).map((type) => ({\n ...ITEMS[type],\n onItemClick: () => invoke(type),\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"]}