@agent-native/core 0.159.2 → 0.159.5

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 (58) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/clips/.agents/skills/meetings/SKILL.md +11 -6
  3. package/corpus/templates/clips/AGENTS.md +1 -0
  4. package/corpus/templates/clips/actions/lib/meeting-content.ts +15 -4
  5. package/corpus/templates/clips/actions/list-meetings.ts +179 -42
  6. package/corpus/templates/clips/actions/search-meetings.ts +277 -0
  7. package/corpus/templates/clips/app/components/meetings/agenda-card.tsx +273 -0
  8. package/corpus/templates/clips/app/components/meetings/day-grouped-card.tsx +113 -0
  9. package/corpus/templates/clips/app/components/meetings/meeting-history-row.tsx +117 -0
  10. package/corpus/templates/clips/app/hooks/use-navigation-state.ts +12 -2
  11. package/corpus/templates/clips/app/i18n/en-US.ts +7 -2
  12. package/corpus/templates/clips/app/routes/_app.meetings._index.tsx +263 -357
  13. package/corpus/templates/clips/changelog/2026-08-14-meetings-history-is-searchable-again.md +6 -0
  14. package/corpus/templates/clips/desktop/design-refs/granola-ux.md +17 -0
  15. package/corpus/templates/content/actions/_database-source-utils.ts +29 -2
  16. package/corpus/templates/content/app/components/editor/SlashCommandMenu.tsx +11 -11
  17. package/corpus/templates/content/app/components/editor/VisualEditor.tsx +11 -50
  18. package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +57 -20
  19. package/corpus/templates/content/app/components/editor/database-sources/BuilderSourceReviewDialog.tsx +30 -0
  20. package/corpus/templates/content/app/components/editor/extensions/NotionExtensions.tsx +204 -51
  21. package/corpus/templates/content/app/global.css +4 -1
  22. package/corpus/templates/content/app/i18n-data.ts +30 -0
  23. package/corpus/templates/content/changelog/2026-08-12-toggle-blocks-now-follow-notion-style-enter-and-shift-tab-be.md +6 -0
  24. package/corpus/templates/content/docs/solutions/2026-08-12-toggle-summary-focus-persistence-shape.md +733 -0
  25. package/corpus/templates/content/shared/builder-mdx.ts +44 -4
  26. package/corpus/templates/slides/actions/get-layout-overflows.ts +65 -2
  27. package/dist/client/chat-first/app-pane.js +1 -1
  28. package/dist/client/chat-first/copy.js +1 -0
  29. package/dist/collab/awareness.d.ts +2 -2
  30. package/dist/collab/struct-routes.d.ts +1 -1
  31. package/dist/deploy/build.d.ts +6 -4
  32. package/dist/deploy/build.js +27 -11
  33. package/dist/feature-flags/index.d.ts +0 -2
  34. package/dist/feature-flags/index.js +3 -2
  35. package/dist/feature-flags/server.d.ts +2 -0
  36. package/dist/feature-flags/server.js +2 -0
  37. package/dist/file-upload/actions/upload-image.d.ts +1 -1
  38. package/dist/index.d.ts +2 -1
  39. package/dist/index.js +2 -1
  40. package/dist/mcp/screen-memory-stdio.d.ts +7 -7
  41. package/dist/notifications/routes.d.ts +6 -6
  42. package/dist/observability/routes.d.ts +5 -5
  43. package/dist/progress/routes.d.ts +1 -1
  44. package/dist/provider-api/actions/custom-provider-registration.d.ts +2 -2
  45. package/dist/secrets/routes.d.ts +9 -9
  46. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  47. package/dist/server/auth.js +10 -0
  48. package/dist/server/index.d.ts +1 -1
  49. package/dist/server/index.js +1 -1
  50. package/dist/server/onboarding-html.js +16 -257
  51. package/dist/shared/auth-copy.d.ts +34 -0
  52. package/dist/shared/auth-copy.js +293 -0
  53. package/dist/shared/index.d.ts +1 -0
  54. package/dist/shared/index.js +1 -0
  55. package/docs/content/actions-advanced.mdx +1 -1
  56. package/docs/content/portal.mdx +21 -8
  57. package/package.json +4 -2
  58. package/corpus/templates/clips/app/components/meetings/meeting-card.tsx +0 -333
@@ -11,8 +11,9 @@ import {
11
11
  IconExternalLink,
12
12
  IconFileText,
13
13
  } from "@tabler/icons-react";
14
- import { InputRule } from "@tiptap/core";
14
+ import { InputRule, type Editor } from "@tiptap/core";
15
15
  import type { Fragment, Node as ProseMirrorNode } from "@tiptap/pm/model";
16
+ import { Selection } from "@tiptap/pm/state";
16
17
  import {
17
18
  Mark,
18
19
  Node,
@@ -173,6 +174,119 @@ export const TOGGLE_SUMMARY_PLACEHOLDER = "Toggle";
173
174
  export const EMPTY_TOGGLE_BODY_PLACEHOLDER =
174
175
  "Empty toggle. Click or drop blocks inside.";
175
176
 
177
+ export type ToggleSummaryEnterDestination =
178
+ | "paragraph"
179
+ | "toggle-body"
180
+ | "sibling-toggle";
181
+
182
+ function scheduleEditorViewFocus(editor: Editor) {
183
+ setTimeout(() => {
184
+ if (!editor.isDestroyed) editor.view.focus();
185
+ }, 0);
186
+ }
187
+
188
+ export function applyToggleSummaryEnter(
189
+ editor: Editor,
190
+ pos: number,
191
+ summary: string,
192
+ ): ToggleSummaryEnterDestination | null {
193
+ const { state, view } = editor;
194
+ const toggle = state.doc.nodeAt(pos);
195
+ const paragraphType = state.schema.nodes.paragraph;
196
+ const toggleType = state.schema.nodes.notionToggle;
197
+ if (toggle?.type !== toggleType || !paragraphType || !toggleType) return null;
198
+
199
+ if (!summary && toggle.childCount === 0) {
200
+ const tr = state.tr.replaceWith(
201
+ pos,
202
+ pos + toggle.nodeSize,
203
+ paragraphType.create(),
204
+ );
205
+ tr.setMeta("preventClearDocument", true);
206
+ tr.setMeta("uiEvent", "keydown");
207
+ tr.setSelection(Selection.near(tr.doc.resolve(pos + 1)));
208
+ view.dispatch(tr.scrollIntoView());
209
+ scheduleEditorViewFocus(editor);
210
+ return "paragraph";
211
+ }
212
+
213
+ if (toggle.attrs.open) {
214
+ if (toggle.childCount === 0) {
215
+ const tr = state.tr.replaceWith(
216
+ pos,
217
+ pos + toggle.nodeSize,
218
+ toggleType.create({ ...toggle.attrs, summary }, paragraphType.create()),
219
+ );
220
+ tr.setMeta("preventClearDocument", true);
221
+ tr.setMeta("uiEvent", "keydown");
222
+ tr.setSelection(Selection.near(tr.doc.resolve(pos + 2)));
223
+ view.dispatch(tr.scrollIntoView());
224
+ scheduleEditorViewFocus(editor);
225
+ return "toggle-body";
226
+ }
227
+ const tr = state.tr.setNodeMarkup(pos, undefined, {
228
+ ...toggle.attrs,
229
+ summary,
230
+ });
231
+ tr.setMeta("preventClearDocument", true);
232
+ tr.setMeta("uiEvent", "keydown");
233
+ tr.setSelection(Selection.near(tr.doc.resolve(pos + 2)));
234
+ view.dispatch(tr.scrollIntoView());
235
+ scheduleEditorViewFocus(editor);
236
+ return "toggle-body";
237
+ }
238
+
239
+ const tr = state.tr
240
+ .setNodeMarkup(pos, undefined, { ...toggle.attrs, summary })
241
+ .insert(
242
+ pos + toggle.nodeSize,
243
+ toggleType.create({ summary: "", open: false }),
244
+ );
245
+ tr.setMeta("preventClearDocument", true);
246
+ tr.setMeta("uiEvent", "keydown");
247
+ view.dispatch(tr.scrollIntoView());
248
+ return "sibling-toggle";
249
+ }
250
+
251
+ export function outdentDirectToggleChild(editor: Editor): boolean {
252
+ const { state, view } = editor;
253
+ const { $from, $to } = state.selection;
254
+ if ($from.depth < 2 || $to.depth !== $from.depth) return false;
255
+
256
+ const toggleDepth = $from.depth - 1;
257
+ if (
258
+ $from.node(toggleDepth).type.name !== "notionToggle" ||
259
+ $to.node(toggleDepth) !== $from.node(toggleDepth)
260
+ ) {
261
+ return false;
262
+ }
263
+
264
+ const range = $from.blockRange($to);
265
+ if (!range || range.depth !== toggleDepth) return false;
266
+ const childDepth = $from.depth;
267
+ const child = $from.node(childDepth);
268
+ const childPos = $from.before(childDepth);
269
+ const togglePos = $from.before(toggleDepth);
270
+ const cursorOffset = $from.parentOffset;
271
+ const tr = state.tr.delete(childPos, childPos + child.nodeSize);
272
+ const remainingToggle = tr.doc.nodeAt(togglePos);
273
+ if (remainingToggle?.type.name !== "notionToggle") return false;
274
+ const insertPos = togglePos + remainingToggle.nodeSize;
275
+ tr.insert(insertPos, child);
276
+ tr.setMeta("preventClearDocument", true);
277
+ tr.setMeta("uiEvent", "keydown");
278
+ tr.setSelection(
279
+ Selection.near(
280
+ tr.doc.resolve(
281
+ insertPos + 1 + Math.min(cursorOffset, child.content.size),
282
+ ),
283
+ ),
284
+ );
285
+ view.dispatch(tr.scrollIntoView());
286
+ scheduleEditorViewFocus(editor);
287
+ return true;
288
+ }
289
+
176
290
  function normalizeIndentAttr(value: unknown): number {
177
291
  const parsed =
178
292
  typeof value === "number"
@@ -191,7 +305,7 @@ export function focusMostRecentEmptyToggleSummary(editor: {
191
305
  ? requestAnimationFrame
192
306
  : (callback: FrameRequestCallback) => setTimeout(callback, 0);
193
307
 
194
- schedule(() => {
308
+ const focusSummary = (attempt: number) => {
195
309
  let editorDom: HTMLElement;
196
310
  try {
197
311
  editorDom = editor.view.dom;
@@ -206,24 +320,56 @@ export function focusMostRecentEmptyToggleSummary(editor: {
206
320
  [...inputs].reverse().find((input) => input.value === "") ??
207
321
  inputs[inputs.length - 1];
208
322
 
209
- target?.focus();
323
+ if (!target && attempt < 3) {
324
+ schedule(() => focusSummary(attempt + 1));
325
+ return;
326
+ }
327
+
328
+ target?.focus({ preventScroll: true });
210
329
  target?.select();
211
- });
330
+ };
331
+
332
+ schedule(() => focusSummary(0));
333
+ }
334
+
335
+ export function focusToggleSummaryAtPosition(
336
+ editor: Pick<Editor, "view">,
337
+ pos: number,
338
+ ) {
339
+ const nodeDom = editor.view.nodeDOM(pos);
340
+ if (!(nodeDom instanceof HTMLElement)) return;
341
+ const target = nodeDom.querySelector<HTMLInputElement>(
342
+ ".notion-toggle__summary",
343
+ );
344
+ target?.focus();
345
+ target?.select();
212
346
  }
213
347
 
214
- function ToggleView({ node, updateAttributes, editor, getPos }: NodeViewProps) {
348
+ function ToggleView({ node, editor, getPos }: NodeViewProps) {
215
349
  const open = !!node.attrs.open;
216
- const setOpen = (value: boolean) => updateAttributes({ open: value });
217
350
  const summary = (node.attrs.summary || "") as string;
218
351
  const isEditable = editor.isEditable;
219
- const firstChild = node.firstChild;
220
352
  const bodyHasNoBlocks = node.childCount === 0;
221
- const bodyIsEmpty =
222
- bodyHasNoBlocks ||
223
- (node.childCount === 1 &&
224
- firstChild?.type.name === "paragraph" &&
225
- firstChild.content.size === 0 &&
226
- !firstChild.textContent.trim());
353
+
354
+ const updateToggleAttributes = (
355
+ attrs: Record<string, unknown>,
356
+ uiEvent: "input" | "pointer",
357
+ ) => {
358
+ const pos = getPos();
359
+ if (typeof pos !== "number") return;
360
+ const currentNode = editor.state.doc.nodeAt(pos);
361
+ if (currentNode?.type.name !== "notionToggle") return;
362
+ const tr = editor.state.tr.setNodeMarkup(pos, undefined, {
363
+ ...currentNode.attrs,
364
+ ...attrs,
365
+ });
366
+ tr.setMeta("preventClearDocument", true);
367
+ tr.setMeta("uiEvent", uiEvent);
368
+ editor.view.dispatch(tr);
369
+ };
370
+
371
+ const setOpen = (value: boolean) =>
372
+ updateToggleAttributes({ open: value }, "pointer");
227
373
 
228
374
  const focusEmptyBody = (event: React.MouseEvent<HTMLElement>) => {
229
375
  if (!isEditable) return;
@@ -235,12 +381,14 @@ function ToggleView({ node, updateAttributes, editor, getPos }: NodeViewProps) {
235
381
 
236
382
  if (!open) setOpen(true);
237
383
 
238
- editor
239
- .chain()
240
- .focus()
241
- .insertContentAt(pos + 1, { type: "paragraph" })
242
- .focus(pos + 2)
243
- .run();
384
+ const paragraph = editor.state.schema.nodes.paragraph;
385
+ if (!paragraph) return;
386
+ const tr = editor.state.tr.insert(pos + 1, paragraph.create());
387
+ tr.setMeta("preventClearDocument", true);
388
+ tr.setMeta("uiEvent", "pointer");
389
+ tr.setSelection(Selection.near(tr.doc.resolve(pos + 2)));
390
+ editor.view.dispatch(tr.scrollIntoView());
391
+ scheduleEditorViewFocus(editor);
244
392
  };
245
393
 
246
394
  const getEmptyBodyInsertPos = () => {
@@ -322,6 +470,9 @@ function ToggleView({ node, updateAttributes, editor, getPos }: NodeViewProps) {
322
470
  );
323
471
  }
324
472
 
473
+ tr.setMeta("preventClearDocument", true);
474
+ tr.setMeta("uiEvent", "drop");
475
+
325
476
  editor.view.dispatch(tr.scrollIntoView());
326
477
  editor.view.focus();
327
478
  (
@@ -338,48 +489,41 @@ function ToggleView({ node, updateAttributes, editor, getPos }: NodeViewProps) {
338
489
  e.preventDefault();
339
490
  const pos = getPos();
340
491
  if (typeof pos !== "number") return;
341
- // Insert a new toggle after this one
342
- const endPos = pos + node.nodeSize;
343
- editor
344
- .chain()
345
- .focus()
346
- .insertContentAt(endPos, {
347
- type: "notionToggle",
348
- attrs: { summary: "", open: true },
349
- content: [{ type: "paragraph" }],
350
- })
351
- .run();
352
- // Focus the new toggle's summary input after render
353
- setTimeout(() => {
354
- const wrapper = editor.view.dom.closest(".visual-editor-wrapper");
355
- if (!wrapper) return;
356
- const toggles = wrapper.querySelectorAll(".notion-toggle__summary");
357
- const allToggles = Array.from(toggles) as HTMLInputElement[];
358
- const currentInput = e.currentTarget;
359
- const idx = allToggles.indexOf(currentInput);
360
- if (idx >= 0 && allToggles[idx + 1]) {
361
- allToggles[idx + 1].focus();
362
- }
363
- }, 0);
492
+ const currentInput = e.currentTarget;
493
+ const destination = applyToggleSummaryEnter(
494
+ editor,
495
+ pos,
496
+ currentInput.value,
497
+ );
498
+ if (destination === "sibling-toggle") {
499
+ setTimeout(() => {
500
+ focusToggleSummaryAtPosition(editor, pos + node.nodeSize);
501
+ }, 0);
502
+ }
364
503
  } else if (e.key === "Backspace" && summary === "") {
365
504
  e.preventDefault();
366
505
  const pos = getPos();
367
506
  if (typeof pos !== "number") return;
368
507
  // Delete this empty toggle and replace with paragraph
369
- editor
370
- .chain()
371
- .focus()
372
- .deleteRange({ from: pos, to: pos + node.nodeSize })
373
- .insertContentAt(pos, { type: "paragraph" })
374
- .focus(pos + 1)
375
- .run();
508
+ const paragraph = editor.state.schema.nodes.paragraph;
509
+ if (!paragraph) return;
510
+ const tr = editor.state.tr.replaceWith(
511
+ pos,
512
+ pos + node.nodeSize,
513
+ paragraph.create(),
514
+ );
515
+ tr.setMeta("preventClearDocument", true);
516
+ tr.setMeta("uiEvent", "keydown");
517
+ tr.setSelection(Selection.near(tr.doc.resolve(pos + 1)));
518
+ editor.view.dispatch(tr.scrollIntoView());
519
+ scheduleEditorViewFocus(editor);
376
520
  }
377
521
  };
378
522
 
379
523
  return (
380
524
  <NodeViewWrapper
381
525
  className={`notion-toggle ${open ? "notion-toggle--open" : ""} ${
382
- bodyIsEmpty ? "notion-toggle--body-empty" : ""
526
+ bodyHasNoBlocks ? "notion-toggle--body-empty" : ""
383
527
  }`}
384
528
  data-color={node.attrs.color || undefined}
385
529
  data-heading-level={node.attrs.headingLevel || undefined}
@@ -402,7 +546,10 @@ function ToggleView({ node, updateAttributes, editor, getPos }: NodeViewProps) {
402
546
  <input
403
547
  value={summary}
404
548
  onChange={(event) =>
405
- updateAttributes({ summary: event.currentTarget.value })
549
+ updateToggleAttributes(
550
+ { summary: event.currentTarget.value },
551
+ "input",
552
+ )
406
553
  }
407
554
  onKeyDown={handleKeyDown}
408
555
  onClick={(e) => e.stopPropagation()}
@@ -642,6 +789,7 @@ export const NotionSpanMark = Mark.create({
642
789
 
643
790
  export const NotionToggle = Node.create({
644
791
  name: "notionToggle",
792
+ priority: 1000,
645
793
  group: "block",
646
794
  content: "block*",
647
795
  defining: true,
@@ -730,6 +878,11 @@ export const NotionToggle = Node.create({
730
878
  addNodeView() {
731
879
  return ReactNodeViewRenderer(ToggleView);
732
880
  },
881
+ addKeyboardShortcuts() {
882
+ return {
883
+ "Shift-Tab": ({ editor }) => outdentDirectToggleChild(editor),
884
+ };
885
+ },
733
886
  addStorage() {
734
887
  return {
735
888
  markdown: {
@@ -1046,7 +1046,7 @@
1046
1046
  }
1047
1047
 
1048
1048
  .notion-toggle__chevron {
1049
- color: hsl(var(--muted-foreground));
1049
+ color: hsl(var(--foreground));
1050
1050
  user-select: none;
1051
1051
  display: flex;
1052
1052
  align-items: center;
@@ -1056,6 +1056,9 @@
1056
1056
  border-radius: 3px;
1057
1057
  transition: background-color 120ms ease-out;
1058
1058
  }
1059
+ .notion-toggle--body-empty .notion-toggle__chevron {
1060
+ color: hsl(var(--muted-foreground));
1061
+ }
1059
1062
  .notion-toggle__chevron:hover {
1060
1063
  background: hsl(var(--muted));
1061
1064
  }
@@ -425,6 +425,9 @@ const databaseMessages = {
425
425
  toValue: "To: {{value}}",
426
426
  unknown: "unknown",
427
427
  whatChanged: "What changed",
428
+ bodyChangeComparison: "Body change comparison",
429
+ currentBody: "Current body",
430
+ proposedBody: "Proposed body",
428
431
  whereItWillGo: "Where it will go",
429
432
  openAsFullPage: "Open as full page",
430
433
  pick: "& Pick",
@@ -569,6 +572,9 @@ const databaseMessagesByLocale = {
569
572
  preparedUpdateAlreadyCancelled: "准备好的 Builder 更新已被取消",
570
573
  cancelPreparedUpdateFailed: "未能取消准备好的 Builder 更新",
571
574
  whatChanged: "更改内容",
575
+ bodyChangeComparison: "正文更改对比",
576
+ currentBody: "当前正文",
577
+ proposedBody: "建议正文",
572
578
  confirmUnpublish: "确认取消发布",
573
579
  builderBodyEditsNeedSaferPath:
574
580
  "Builder 正文编辑需要更安全的推送路径才能发送。",
@@ -794,6 +800,9 @@ const databaseMessagesByLocale = {
794
800
  cancelPreparedUpdateFailed:
795
801
  "No se canceló la actualización preparada de Builder",
796
802
  whatChanged: "Qué cambió",
803
+ bodyChangeComparison: "Comparación de cambios del cuerpo",
804
+ currentBody: "Cuerpo actual",
805
+ proposedBody: "Cuerpo propuesto",
797
806
  confirmUnpublish: "Confirmar retirada de publicación",
798
807
  builderBodyEditsNeedSaferPath:
799
808
  "Las ediciones del cuerpo en Builder necesitan una ruta de envío más segura antes de poder enviarse.",
@@ -1032,6 +1041,9 @@ const databaseMessagesByLocale = {
1032
1041
  cancelPreparedUpdateFailed:
1033
1042
  "La mise à jour Builder préparée n’a pas été annulée",
1034
1043
  whatChanged: "Ce qui a changé",
1044
+ bodyChangeComparison: "Comparaison des modifications du corps",
1045
+ currentBody: "Corps actuel",
1046
+ proposedBody: "Corps proposé",
1035
1047
  confirmUnpublish: "Confirmer la dépublication",
1036
1048
  builderBodyEditsNeedSaferPath:
1037
1049
  "Les modifications du corps dans Builder nécessitent un chemin d'envoi plus sûr avant de pouvoir être envoyées.",
@@ -1269,6 +1281,9 @@ const databaseMessagesByLocale = {
1269
1281
  cancelPreparedUpdateFailed:
1270
1282
  "Das vorbereitete Builder-Update wurde nicht abgebrochen",
1271
1283
  whatChanged: "Was sich geändert hat",
1284
+ bodyChangeComparison: "Vergleich der Textänderung",
1285
+ currentBody: "Aktueller Text",
1286
+ proposedBody: "Vorgeschlagener Text",
1272
1287
  confirmUnpublish: "Zurückziehen bestätigen",
1273
1288
  builderBodyEditsNeedSaferPath:
1274
1289
  "Builder-Textänderungen benötigen einen sichereren Übertragungsweg, bevor sie gesendet werden können.",
@@ -1504,6 +1519,9 @@ const databaseMessagesByLocale = {
1504
1519
  cancelPreparedUpdateFailed:
1505
1520
  "準備済み Builder 更新をキャンセルできませんでした",
1506
1521
  whatChanged: "変更内容",
1522
+ bodyChangeComparison: "本文変更の比較",
1523
+ currentBody: "現在の本文",
1524
+ proposedBody: "変更後の本文",
1507
1525
  confirmUnpublish: "非公開を確認",
1508
1526
  builderBodyEditsNeedSaferPath:
1509
1527
  "Builder の本文編集は、送信する前により安全なプッシュ経路が必要です。",
@@ -1734,6 +1752,9 @@ const databaseMessagesByLocale = {
1734
1752
  "준비된 Builder 업데이트가 이미 취소되었습니다",
1735
1753
  cancelPreparedUpdateFailed: "준비된 Builder 업데이트를 취소하지 못했습니다",
1736
1754
  whatChanged: "변경 내용",
1755
+ bodyChangeComparison: "본문 변경 비교",
1756
+ currentBody: "현재 본문",
1757
+ proposedBody: "제안된 본문",
1737
1758
  confirmUnpublish: "게시 취소 확인",
1738
1759
  builderBodyEditsNeedSaferPath:
1739
1760
  "Builder 본문 편집은 전송하기 전에 더 안전한 푸시 경로가 필요합니다.",
@@ -1967,6 +1988,9 @@ const databaseMessagesByLocale = {
1967
1988
  cancelPreparedUpdateFailed:
1968
1989
  "A atualização preparada do Builder não foi cancelada",
1969
1990
  whatChanged: "O que mudou",
1991
+ bodyChangeComparison: "Comparação da alteração do corpo",
1992
+ currentBody: "Corpo atual",
1993
+ proposedBody: "Corpo proposto",
1970
1994
  confirmUnpublish: "Confirmar cancelamento de publicação",
1971
1995
  builderBodyEditsNeedSaferPath:
1972
1996
  "As edições de corpo do Builder precisam de um caminho de envio mais seguro antes de poderem ser enviadas.",
@@ -2196,6 +2220,9 @@ const databaseMessagesByLocale = {
2196
2220
  "तैयार Builder अपडेट पहले ही रद्द किया जा चुका था",
2197
2221
  cancelPreparedUpdateFailed: "तैयार Builder अपडेट रद्द नहीं हुआ",
2198
2222
  whatChanged: "क्या बदला",
2223
+ bodyChangeComparison: "मुख्य पाठ के बदलाव की तुलना",
2224
+ currentBody: "वर्तमान मुख्य पाठ",
2225
+ proposedBody: "प्रस्तावित मुख्य पाठ",
2199
2226
  confirmUnpublish: "अप्रकाशित करने की पुष्टि करें",
2200
2227
  builderBodyEditsNeedSaferPath:
2201
2228
  "Builder बॉडी संपादनों को भेजे जाने से पहले एक सुरक्षित पुश पथ की आवश्यकता होती है।",
@@ -2417,6 +2444,9 @@ const databaseMessagesByLocale = {
2417
2444
  preparedUpdateAlreadyCancelled: "كان تحديث Builder المُعَد ملغى بالفعل",
2418
2445
  cancelPreparedUpdateFailed: "لم يتم إلغاء تحديث Builder المُعَد",
2419
2446
  whatChanged: "ما الذي تغيّر",
2447
+ bodyChangeComparison: "مقارنة تغيير المحتوى",
2448
+ currentBody: "المحتوى الحالي",
2449
+ proposedBody: "المحتوى المقترح",
2420
2450
  confirmUnpublish: "تأكيد إلغاء النشر",
2421
2451
  builderBodyEditsNeedSaferPath:
2422
2452
  "تتطلب تعديلات نص Builder مسار دفع أكثر أمانًا قبل أن يمكن إرسالها.",
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: improved
3
+ date: 2026-08-12
4
+ ---
5
+
6
+ Toggle blocks now follow Notion-style Enter and Shift-Tab behavior while preserving summaries and nested paragraphs.