@agent-native/core-corpus 0.201.0-nightly-20261005183955 → 0.201.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 (23) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/analytics/CHANGELOG.md +6 -0
  3. package/corpus/templates/assets/CHANGELOG.md +7 -0
  4. package/corpus/templates/brain/CHANGELOG.md +6 -0
  5. package/corpus/templates/calendar/CHANGELOG.md +7 -0
  6. package/corpus/templates/clips/CHANGELOG.md +24 -0
  7. package/corpus/templates/content/CHANGELOG.md +41 -0
  8. package/corpus/templates/content/app/components/editor/DocumentBlockFields.tsx +21 -6
  9. package/corpus/templates/content/app/components/editor/TableHoverControls.tsx +139 -70
  10. package/corpus/templates/content/app/components/editor/VisualEditor.tsx +2 -0
  11. package/corpus/templates/content/app/components/editor/table-view.ts +73 -0
  12. package/corpus/templates/content/app/global.css +16 -8
  13. package/corpus/templates/content/changelog/2026-10-02-pages-stay-inside-the-window-at-every-width-long-inline-code.md +6 -0
  14. package/corpus/templates/content/e2e/playwright.config.ts +1 -1
  15. package/corpus/templates/design/CHANGELOG.md +41 -0
  16. package/corpus/templates/design/app/pages/Index.tsx +1 -1
  17. package/corpus/templates/design/changelog/2026-10-05-the-recent-tab-shows-loading-placeholders-until-your-designs.md +6 -0
  18. package/corpus/templates/mail/CHANGELOG.md +6 -0
  19. package/corpus/templates/plan/CHANGELOG.md +1 -0
  20. package/corpus/templates/slides/CHANGELOG.md +23 -0
  21. package/corpus/templates/slides/app/pages/Index.tsx +51 -24
  22. package/corpus/templates/slides/changelog/2026-10-05-the-recent-tab-shows-loading-placeholders-until-your-decks-a.md +6 -0
  23. package/package.json +1 -1
package/corpus/README.md CHANGED
@@ -32,4 +32,4 @@ rg -n "defineAction|useActionQuery" node_modules/@agent-native/core-corpus/corpu
32
32
 
33
33
  ## Generated Counts
34
34
 
35
- - template files: 11146
35
+ - template files: 11150
@@ -7,8 +7,14 @@ time from the command menu (Cmd+K → "What's new") or from Settings.
7
7
 
8
8
  ### Improved
9
9
 
10
+ - Builder.io setup now explains free credits and the existing-account option.
11
+ - Owners and admins can save data source credentials for the whole organization or just for themselves.
10
12
  - Retention reports now compare returns from paid and untagged signups.
11
13
 
14
+ ### Fixed
15
+
16
+ - Events with a very long name, app, or page path no longer cause the rest of their batch to be lost
17
+
12
18
  ## 2026-10-01
13
19
 
14
20
  ### Improved
@@ -3,6 +3,13 @@
3
3
  All notable user-facing changes to Assets are documented here. Open it any
4
4
  time from the command menu (Cmd+K → "What's new") or from Settings.
5
5
 
6
+ ## 2026-10-02
7
+
8
+ ### Improved
9
+
10
+ - Builder.io setup copy now clarifies account use and available credits.
11
+ - Owners and admins can save image generation keys for the whole organization, which is now the default.
12
+
6
13
  ## 2026-10-01
7
14
 
8
15
  ### Fixed
@@ -3,6 +3,12 @@
3
3
  All notable user-facing changes to Agent-Native Brain are documented here. Open it any
4
4
  time from the command menu (Cmd+K → "What's new") or from Settings.
5
5
 
6
+ ## 2026-10-05
7
+
8
+ ### Improved
9
+
10
+ - Messages from private Slack channels the Brain app is invited to are now searchable by everyone in the org once they pass sensitivity screening. Syncs no longer look up channel members, so a member without a visible email no longer stops a channel from syncing. Personal sources stay visible only to their owner and the people they are shared with.
11
+
6
12
  ## 2026-10-02
7
13
 
8
14
  ### Improved
@@ -3,6 +3,13 @@
3
3
  All notable user-facing changes to Agent-Native Calendar are documented here. Open it any
4
4
  time from the command menu (Cmd+K → "What's new") or from Settings.
5
5
 
6
+ ## 2026-10-02
7
+
8
+ ### Improved
9
+
10
+ - Builder.io setup copy now clarifies account activation and sign-in.
11
+ - Owners and admins can save Apollo, HubSpot, Gong, and Pylon keys for the whole organization or just for themselves.
12
+
6
13
  ## 2026-10-01
7
14
 
8
15
  ### Improved
@@ -3,10 +3,34 @@
3
3
  All notable user-facing changes to Clips are documented here. Open it any time
4
4
  from the command menu (Cmd+K → "What's new") or from Settings.
5
5
 
6
+ ## 2026-10-05
7
+
8
+ ### Fixed
9
+
10
+ - Confirming Discard recording now returns you to your library.
11
+ - Discarding a recording now removes its failed upload card from your library.
12
+ - Discarding a recovered recording no longer warns that it's open in another tab.
13
+ - Search results identify recordings in Trash and open them with Trash navigation.
14
+
15
+ ## 2026-10-03
16
+
17
+ ### Fixed
18
+
19
+ - Invalid Lab choices can be repaired from Labs settings.
20
+
6
21
  ## 2026-10-02
7
22
 
23
+ ### Improved
24
+
25
+ - Builder.io setup now offers one-click activation and clear existing-account sign-in.
26
+
8
27
  ### Fixed
9
28
 
29
+ - Cancelled Rewind Clip setup can be retried immediately
30
+ - Long uploads (an hour or more) now transcribe reliably instead of failing.
31
+ - Recording countdowns begin during setup, with explicit cue outcomes and startup timing
32
+ - Recording visibility defaults no longer switch to Public when saved settings cannot be read.
33
+ - Screen recording startup now cleans up canceled Rewind setup and keeps countdown timing reliable on older macOS.
10
34
  - Recording reminders and other actionable notifications show their message above the buttons
11
35
  - Temporary upload authorization failures remain retryable, while permanently rejected Builder credentials trigger storage setup errors.
12
36
 
@@ -3,10 +3,51 @@
3
3
  All notable user-facing changes to Agent-Native Content are documented here. Open it any
4
4
  time from the command menu (Cmd+K → "What's new").
5
5
 
6
+ ## 2026-10-05
7
+
8
+ ### Improved
9
+
10
+ - Collection pages keep selected rows visible through failed refreshes, and review space stays in place while comments refresh.
11
+
12
+ ### Fixed
13
+
14
+ - Collection view context now survives quick page changes when the saved summary fits.
15
+ - Exact saved-view links keep the collection retry available when rows fail to load
16
+ - Expanding a Files folder now shares one navigation read across open branches, and legacy owner shares retain their row controls.
17
+ - Files navigation retries temporary failures consistently
18
+ - Shared page owners keep edit and manage controls in Files, and newly opened folders populate faster.
19
+ - Tagging an AI in a comment works again instead of failing right away with "AI request failed".
20
+ - The home loading shell keeps the layout of your last opened page.
21
+ - Typing `>` and a space, or inserting a toggle or callout, no longer freezes and crashes the page on a Mac.
22
+
23
+ ## 2026-10-03
24
+
25
+ ### Fixed
26
+
27
+ - A malformed Lab preference no longer blocks unrelated editor commands.
28
+
29
+ ## 2026-10-02
30
+
31
+ ### Improved
32
+
33
+ - After a refresh, the Files sidebar shows the open page's folders in one load instead of one level at a time
34
+ - Builder.io setup instructions now use consistent action language across editor workflows.
35
+ - Large collections open faster
36
+ - Pages with open comments and collections with sorted or filtered views no longer jump while they load
37
+
38
+ ### Fixed
39
+
40
+ - A page link you can't open now says so, with the account you're signed in as, instead of opening another page. People who can open a private share link no longer see "This document is private" first.
41
+ - Comment edits and deletions now refresh collaborators with the document open.
42
+ - Pages stay inside the window at every width: long inline code and links wrap, and wide tables scroll inside their own frame instead of crushing their columns
43
+ - Suggest edits works on pages written by agents, including pages with Markdown tables, instead of refusing to start or rejecting each edit; suggestions inside a table cell are still not supported
44
+ - While you suggest edits, tables and other blocks that suggestions don't support yet are read-only, and an agent that tries to suggest a change inside one gets a clear message instead of "Internal server error".
45
+
6
46
  ## 2026-10-01
7
47
 
8
48
  ### Improved
9
49
 
50
+ - Home opens the page you were last on sooner
10
51
  - Pages and the sidebar load in place instead of jumping around
11
52
 
12
53
  ### Fixed
@@ -42,6 +42,9 @@ import {
42
42
  import { VisualEditor } from "./VisualEditor";
43
43
 
44
44
  const BLOCK_FIELD_DRAG_THRESHOLD = 6;
45
+ // The default `auto` track grows to its widest unbreakable line, which widens
46
+ // the whole page body past the window; the track must be allowed to shrink.
47
+ const BLOCK_FIELDS_GRID = "grid grid-cols-[minmax(0,1fr)]";
45
48
 
46
49
  interface DocumentBlockFieldsProps {
47
50
  documentId: string;
@@ -309,7 +312,10 @@ export function DocumentBlockFields({
309
312
  // that state could bind the body before we know which storage target owns it.
310
313
  if (query.isError) {
311
314
  return (
312
- <div className="grid gap-1" data-block-fields-state="error">
315
+ <div
316
+ className={cn(BLOCK_FIELDS_GRID, "gap-1")}
317
+ data-block-fields-state="error"
318
+ >
313
319
  <QueryErrorState
314
320
  compact
315
321
  onRetry={() => globalThis.location.reload()}
@@ -325,7 +331,7 @@ export function DocumentBlockFields({
325
331
  case "loading":
326
332
  return (
327
333
  <div
328
- className="grid gap-1"
334
+ className={cn(BLOCK_FIELDS_GRID, "gap-1")}
329
335
  data-block-fields-state="loading"
330
336
  aria-busy="true"
331
337
  >
@@ -334,7 +340,10 @@ export function DocumentBlockFields({
334
340
  );
335
341
  case "empty":
336
342
  return (
337
- <div className="grid gap-1" data-block-fields-state="empty">
343
+ <div
344
+ className={cn(BLOCK_FIELDS_GRID, "gap-1")}
345
+ data-block-fields-state="empty"
346
+ >
338
347
  {canEdit ? (
339
348
  <p className="px-1 py-2 text-sm text-muted-foreground">
340
349
  {t("editor.noBlocksFields")}
@@ -345,7 +354,10 @@ export function DocumentBlockFields({
345
354
  case "solo":
346
355
  if (state.target === "block_field_store") {
347
356
  return (
348
- <div className="grid gap-1" data-block-fields-state="solo">
357
+ <div
358
+ className={cn(BLOCK_FIELDS_GRID, "gap-1")}
359
+ data-block-fields-state="solo"
360
+ >
349
361
  <AdditionalBlockEditor
350
362
  key={`${documentId}:${state.field.definition.id}`}
351
363
  documentId={documentId}
@@ -359,7 +371,10 @@ export function DocumentBlockFields({
359
371
  );
360
372
  }
361
373
  return (
362
- <div className="grid gap-1" data-block-fields-state="solo">
374
+ <div
375
+ className={cn(BLOCK_FIELDS_GRID, "gap-1")}
376
+ data-block-fields-state="solo"
377
+ >
363
378
  {primaryEditor}
364
379
  </div>
365
380
  );
@@ -546,7 +561,7 @@ function MultiBlockFields({
546
561
  }
547
562
 
548
563
  return (
549
- <div className="grid">
564
+ <div className={BLOCK_FIELDS_GRID}>
550
565
  <BlockFieldDragPreview preview={dragPreview} />
551
566
  {blockFields.map((property, index) => {
552
567
  const primary = isPrimaryBlocksField(property.definition.options);
@@ -165,7 +165,7 @@ function getCellAtAddress(
165
165
  return getCells(row)[address.columnIndex] ?? null;
166
166
  }
167
167
 
168
- function getSelectionOverlayRect(rects: DOMRect[]) {
168
+ function getSelectionOverlayRect(table: HTMLElement, rects: DOMRect[]) {
169
169
  if (rects.length === 0) return null;
170
170
 
171
171
  const left = Math.min(...rects.map((rect) => rect.left));
@@ -173,12 +173,32 @@ function getSelectionOverlayRect(rects: DOMRect[]) {
173
173
  const top = Math.min(...rects.map((rect) => rect.top));
174
174
  const bottom = Math.max(...rects.map((rect) => rect.bottom));
175
175
 
176
+ return clampToScrollport(
177
+ { height: bottom - top, left, top, width: right - left },
178
+ getTableScrollport(table),
179
+ );
180
+ }
181
+
182
+ // Tables scroll sideways inside `.tableWrapper`, but these controls render
183
+ // beside the editor, outside its clipping, so they clip themselves to it.
184
+ function getTableScrollport(table: HTMLElement) {
185
+ return (table.closest(".tableWrapper") ?? table).getBoundingClientRect();
186
+ }
187
+
188
+ function clampToScrollport(
189
+ rect: SelectionOverlayRect,
190
+ scrollport: DOMRect,
191
+ ): SelectionOverlayRect {
192
+ const clamp = (x: number) =>
193
+ Math.min(Math.max(x, scrollport.left), scrollport.right);
194
+ const left = clamp(rect.left);
195
+
176
196
  return {
177
- height: bottom - top,
197
+ height: rect.height,
178
198
  left,
179
- top,
180
- width: right - left,
181
- } satisfies SelectionOverlayRect;
199
+ top: rect.top,
200
+ width: clamp(rect.left + rect.width) - left,
201
+ };
182
202
  }
183
203
 
184
204
  function getRowSelectionOverlayRect(
@@ -188,6 +208,7 @@ function getRowSelectionOverlayRect(
188
208
  if (!address) return null;
189
209
 
190
210
  return getSelectionOverlayRect(
211
+ table,
191
212
  getCells(getRows(table)[address.rowIndex]).map((cell) =>
192
213
  cell.getBoundingClientRect(),
193
214
  ),
@@ -201,6 +222,7 @@ function getColumnSelectionOverlayRect(
201
222
  if (!address) return null;
202
223
 
203
224
  return getSelectionOverlayRect(
225
+ table,
204
226
  getRows(table)
205
227
  .map((row) => getCells(row)[address.columnIndex])
206
228
  .filter((cell): cell is HTMLElement => Boolean(cell))
@@ -381,6 +403,7 @@ export function TableHoverControls({ editor }: TableHoverControlsProps) {
381
403
  const [columnMenuOpen, setColumnMenuOpen] = useState(false);
382
404
  const [rowMenuOpen, setRowMenuOpen] = useState(false);
383
405
  const [viewRetry, setViewRetry] = useState(0);
406
+ const [, setGeometryRevision] = useState(0);
384
407
 
385
408
  const holdTableUiSelection = () => {
386
409
  tableUiPointerDownRef.current = true;
@@ -971,7 +994,19 @@ export function TableHoverControls({ editor }: TableHoverControlsProps) {
971
994
  syncOverlay();
972
995
  };
973
996
 
974
- const handleGeometryChange = () => syncOverlay();
997
+ const handleGeometryChange = () => {
998
+ syncOverlay();
999
+ setGeometryRevision((revision) => revision + 1);
1000
+ };
1001
+ // Page scrolls carry the overlay along with the tables, but a table
1002
+ // scrolled sideways inside its own `.tableWrapper` leaves the overlay behind.
1003
+ const handleScroll = (event: Event) => {
1004
+ if (event.target instanceof Node && view.dom.contains(event.target)) {
1005
+ handleGeometryChange();
1006
+ } else {
1007
+ syncOverlay();
1008
+ }
1009
+ };
975
1010
  const observer = new MutationObserver(syncOverlay);
976
1011
 
977
1012
  syncOverlay();
@@ -982,7 +1017,7 @@ export function TableHoverControls({ editor }: TableHoverControlsProps) {
982
1017
  document.addEventListener("click", handlePointerDown, true);
983
1018
  document.addEventListener("pointermove", handleHoverPointerMove, true);
984
1019
  window.addEventListener("resize", handleGeometryChange);
985
- window.addEventListener("scroll", handleGeometryChange, true);
1020
+ window.addEventListener("scroll", handleScroll, true);
986
1021
  view.dom.addEventListener("keyup", handleKeyUp);
987
1022
 
988
1023
  return () => {
@@ -992,7 +1027,7 @@ export function TableHoverControls({ editor }: TableHoverControlsProps) {
992
1027
  document.removeEventListener("click", handlePointerDown, true);
993
1028
  document.removeEventListener("pointermove", handleHoverPointerMove, true);
994
1029
  window.removeEventListener("resize", handleGeometryChange);
995
- window.removeEventListener("scroll", handleGeometryChange, true);
1030
+ window.removeEventListener("scroll", handleScroll, true);
996
1031
  window.removeEventListener("pointermove", handlePointerMove);
997
1032
  window.removeEventListener("pointerup", handlePointerUp);
998
1033
  view.dom.removeEventListener("keyup", handleKeyUp);
@@ -1000,6 +1035,18 @@ export function TableHoverControls({ editor }: TableHoverControlsProps) {
1000
1035
  };
1001
1036
  }, [editor, viewRetry]);
1002
1037
 
1038
+ // Panels opening beside the page narrow the editor without a window resize.
1039
+ useEffect(() => {
1040
+ const view = getMountedEditorView(editor);
1041
+ if (!view || tables.length === 0) return;
1042
+ const observer = new ResizeObserver(() =>
1043
+ setGeometryRevision((revision) => revision + 1),
1044
+ );
1045
+ observer.observe(view.dom);
1046
+ for (const table of tables) observer.observe(table);
1047
+ return () => observer.disconnect();
1048
+ }, [editor, tables]);
1049
+
1003
1050
  const view = getMountedEditorView(editor);
1004
1051
  if (!view) return null;
1005
1052
 
@@ -1020,6 +1067,13 @@ export function TableHoverControls({ editor }: TableHoverControlsProps) {
1020
1067
  : null);
1021
1068
  const selectedTableRect =
1022
1069
  selectedTable?.getBoundingClientRect() ?? selectedTableRectRef.current;
1070
+ const selectedScrollport = selectedTable
1071
+ ? getTableScrollport(selectedTable)
1072
+ : null;
1073
+ const visibleSelectedRect =
1074
+ selectedRect && selectedScrollport
1075
+ ? clampToScrollport(selectedRect, selectedScrollport)
1076
+ : null;
1023
1077
  const selectedDimensions = selectedTable
1024
1078
  ? getTableDimensions(selectedTable)
1025
1079
  : { rowCount: 0, columnCount: 0 };
@@ -1050,9 +1104,9 @@ export function TableHoverControls({ editor }: TableHoverControlsProps) {
1050
1104
  typeof window === "undefined"
1051
1105
  ? Number.POSITIVE_INFINITY
1052
1106
  : window.innerHeight;
1053
- const columnMenuWouldOverflowRight = selectedRect
1054
- ? selectedRect.left +
1055
- selectedRect.width / 2 +
1107
+ const columnMenuWouldOverflowRight = visibleSelectedRect
1108
+ ? visibleSelectedRect.left +
1109
+ visibleSelectedRect.width / 2 +
1056
1110
  COLUMN_OPTIONS_MENU_ALIGN_OFFSET +
1057
1111
  COLUMN_OPTIONS_MENU_WIDTH >
1058
1112
  viewportWidth - MENU_COLLISION_PADDING
@@ -1084,9 +1138,12 @@ export function TableHoverControls({ editor }: TableHoverControlsProps) {
1084
1138
 
1085
1139
  return (
1086
1140
  <>
1087
- {selectedRect && selectedTable && selectedTableRect ? (
1141
+ {visibleSelectedRect &&
1142
+ selectedScrollport &&
1143
+ selectedTable &&
1144
+ selectedTableRect ? (
1088
1145
  <>
1089
- {selectedColumnOverlayRect ? (
1146
+ {selectedColumnOverlayRect?.width ? (
1090
1147
  <div
1091
1148
  className="pointer-events-none absolute z-20 rounded-[3px] border-2 border-primary/60 bg-primary/10"
1092
1149
  data-testid="table-selected-column"
@@ -1099,7 +1156,7 @@ export function TableHoverControls({ editor }: TableHoverControlsProps) {
1099
1156
  />
1100
1157
  ) : null}
1101
1158
 
1102
- {selectedRowOverlayRect ? (
1159
+ {selectedRowOverlayRect?.width ? (
1103
1160
  <div
1104
1161
  className="pointer-events-none absolute z-20 rounded-[3px] border-2 border-primary/60 bg-primary/10"
1105
1162
  data-testid="table-selected-row"
@@ -1112,22 +1169,27 @@ export function TableHoverControls({ editor }: TableHoverControlsProps) {
1112
1169
  />
1113
1170
  ) : null}
1114
1171
 
1115
- <div
1116
- className="pointer-events-none absolute z-30 rounded-[3px] border-2 border-primary/75 bg-primary/10"
1117
- data-testid="table-selected-cell"
1118
- style={{
1119
- left: selectedRect.left - wrapperRect.left,
1120
- top: selectedRect.top - wrapperRect.top,
1121
- width: selectedRect.width,
1122
- height: selectedRect.height,
1123
- }}
1124
- />
1172
+ {visibleSelectedRect.width ? (
1173
+ <div
1174
+ className="pointer-events-none absolute z-30 rounded-[3px] border-2 border-primary/75 bg-primary/10"
1175
+ data-testid="table-selected-cell"
1176
+ style={{
1177
+ left: visibleSelectedRect.left - wrapperRect.left,
1178
+ top: visibleSelectedRect.top - wrapperRect.top,
1179
+ width: visibleSelectedRect.width,
1180
+ height: visibleSelectedRect.height,
1181
+ }}
1182
+ />
1183
+ ) : null}
1125
1184
 
1126
1185
  <DropdownMenu open={columnMenuOpen} onOpenChange={setColumnMenuOpen}>
1127
1186
  <DropdownMenuTrigger asChild>
1128
1187
  <button
1129
1188
  aria-label={t("database.columnOptions")}
1130
- className={lineButtonClass}
1189
+ className={cn(
1190
+ lineButtonClass,
1191
+ !visibleSelectedRect.width && "invisible",
1192
+ )}
1131
1193
  data-testid="table-column-options"
1132
1194
  onClickCapture={(event) => {
1133
1195
  event.preventDefault();
@@ -1146,9 +1208,9 @@ export function TableHoverControls({ editor }: TableHoverControlsProps) {
1146
1208
  }}
1147
1209
  style={{
1148
1210
  left:
1149
- selectedRect.left -
1211
+ visibleSelectedRect.left -
1150
1212
  wrapperRect.left +
1151
- selectedRect.width / 2,
1213
+ visibleSelectedRect.width / 2,
1152
1214
  top:
1153
1215
  selectedTableRect.top -
1154
1216
  wrapperRect.top -
@@ -1290,13 +1352,13 @@ export function TableHoverControls({ editor }: TableHoverControlsProps) {
1290
1352
  }}
1291
1353
  style={{
1292
1354
  left:
1293
- selectedTableRect.left -
1355
+ Math.max(selectedTableRect.left, selectedScrollport.left) -
1294
1356
  wrapperRect.left -
1295
1357
  ROW_OPTIONS_HIT_WIDTH / 2,
1296
1358
  top:
1297
- selectedRect.top -
1359
+ visibleSelectedRect.top -
1298
1360
  wrapperRect.top +
1299
- selectedRect.height / 2,
1361
+ visibleSelectedRect.height / 2,
1300
1362
  height: ROW_OPTIONS_HIT_HEIGHT,
1301
1363
  transform: "translateY(-50%)",
1302
1364
  width: ROW_OPTIONS_HIT_WIDTH,
@@ -1416,55 +1478,62 @@ export function TableHoverControls({ editor }: TableHoverControlsProps) {
1416
1478
 
1417
1479
  const tableId = getTableOverlayId(table);
1418
1480
  const rect = table.getBoundingClientRect();
1419
- const left = rect.left - wrapperRect.left;
1481
+ const scrollportRect = getTableScrollport(table);
1482
+ const visibleLeft = Math.max(rect.left, scrollportRect.left);
1483
+ const visibleRight = Math.min(rect.right, scrollportRect.right);
1484
+ const isTableEndVisible = rect.right <= visibleRight + 1;
1420
1485
  const top = rect.top - wrapperRect.top;
1421
1486
  const right = rect.right - wrapperRect.left;
1422
1487
  const bottom = rect.bottom - wrapperRect.top;
1488
+ const visibleCenter =
1489
+ (visibleLeft + visibleRight) / 2 - wrapperRect.left;
1423
1490
  const isColumnHandleVisible = hoveredEdges.columnTable === table;
1424
1491
  const isRowHandleVisible = hoveredEdges.rowTable === table;
1425
1492
 
1426
1493
  return (
1427
1494
  <div key={tableId}>
1428
- <Tooltip delayDuration={EDGE_HANDLE_TOOLTIP_DELAY}>
1429
- <TooltipTrigger asChild>
1430
- <button
1431
- aria-label={t("database.tableColumnHandle")}
1432
- className={cn(
1433
- handleClass,
1434
- "cursor-col-resize -translate-y-1/2",
1435
- isColumnHandleVisible && "opacity-100",
1436
- )}
1437
- data-table-edge-control
1438
- data-table-edge="column"
1439
- data-table-id={tableId}
1440
- data-testid="table-column-handle"
1441
- onPointerDown={(event) =>
1442
- startHandlePointer("column", table, event)
1443
- }
1444
- style={{
1445
- height: COLUMN_EDGE_HANDLE_HIT_HEIGHT,
1446
- left: right - COLUMN_EDGE_HANDLE_HIT_WIDTH / 2,
1447
- top: top + rect.height / 2,
1448
- width: COLUMN_EDGE_HANDLE_HIT_WIDTH,
1449
- }}
1450
- type="button"
1451
- >
1452
- <span
1453
- className={edgeHandleMarkerClass}
1495
+ {isTableEndVisible ? (
1496
+ <Tooltip delayDuration={EDGE_HANDLE_TOOLTIP_DELAY}>
1497
+ <TooltipTrigger asChild>
1498
+ <button
1499
+ aria-label={t("database.tableColumnHandle")}
1500
+ className={cn(
1501
+ handleClass,
1502
+ "cursor-col-resize -translate-y-1/2",
1503
+ isColumnHandleVisible && "opacity-100",
1504
+ )}
1505
+ data-table-edge-control
1506
+ data-table-edge="column"
1507
+ data-table-id={tableId}
1508
+ data-testid="table-column-handle"
1509
+ onPointerDown={(event) =>
1510
+ startHandlePointer("column", table, event)
1511
+ }
1454
1512
  style={{
1455
- height: EDGE_HANDLE_LENGTH,
1456
- width: EDGE_HANDLE_THICKNESS,
1513
+ height: COLUMN_EDGE_HANDLE_HIT_HEIGHT,
1514
+ left: right - COLUMN_EDGE_HANDLE_HIT_WIDTH / 2,
1515
+ top: top + rect.height / 2,
1516
+ width: COLUMN_EDGE_HANDLE_HIT_WIDTH,
1457
1517
  }}
1458
- />
1459
- </button>
1460
- </TooltipTrigger>
1461
- <TooltipContent>
1462
- <strong>{t("database.click")}</strong>{" "}
1463
- {t("database.toAddAColumn")}{" "}
1464
- <strong>{t("database.drag")}</strong>{" "}
1465
- {t("database.toAddOrRemoveColumns")}
1466
- </TooltipContent>
1467
- </Tooltip>
1518
+ type="button"
1519
+ >
1520
+ <span
1521
+ className={edgeHandleMarkerClass}
1522
+ style={{
1523
+ height: EDGE_HANDLE_LENGTH,
1524
+ width: EDGE_HANDLE_THICKNESS,
1525
+ }}
1526
+ />
1527
+ </button>
1528
+ </TooltipTrigger>
1529
+ <TooltipContent>
1530
+ <strong>{t("database.click")}</strong>{" "}
1531
+ {t("database.toAddAColumn")}{" "}
1532
+ <strong>{t("database.drag")}</strong>{" "}
1533
+ {t("database.toAddOrRemoveColumns")}
1534
+ </TooltipContent>
1535
+ </Tooltip>
1536
+ ) : null}
1468
1537
 
1469
1538
  <Tooltip delayDuration={EDGE_HANDLE_TOOLTIP_DELAY}>
1470
1539
  <TooltipTrigger asChild>
@@ -1484,7 +1553,7 @@ export function TableHoverControls({ editor }: TableHoverControlsProps) {
1484
1553
  }
1485
1554
  style={{
1486
1555
  height: ROW_EDGE_HANDLE_HIT_HEIGHT,
1487
- left: left + rect.width / 2,
1556
+ left: visibleCenter,
1488
1557
  top: bottom - ROW_EDGE_HANDLE_HIT_HEIGHT / 2,
1489
1558
  width: ROW_EDGE_HANDLE_HIT_WIDTH,
1490
1559
  }}
@@ -166,6 +166,7 @@ import {
166
166
  type SuggestionPresentationTransition,
167
167
  } from "./suggestions/presentation-rebase";
168
168
  import { SuggestingReadOnlyBlocks } from "./suggestions/read-only-blocks";
169
+ import { ContentTableView } from "./table-view";
169
170
  import { TableHoverControls } from "./TableHoverControls";
170
171
 
171
172
  function compareDocumentBodyRevisions(
@@ -2645,6 +2646,7 @@ export function createVisualEditorExtensions({
2645
2646
  MediaSourceCommit.configure({ onMediaSourceCommitted }),
2646
2647
  CustomTable.configure({
2647
2648
  resizable: true,
2649
+ View: ContentTableView,
2648
2650
  HTMLAttributes: { class: "notion-table" },
2649
2651
  }),
2650
2652
  TableRow,
@@ -0,0 +1,73 @@
1
+ import { TableView } from "@tiptap/extension-table";
2
+ import type { Node as ProseMirrorNode } from "@tiptap/pm/model";
3
+ import type { EditorView } from "@tiptap/pm/view";
4
+
5
+ // The table's CSS keeps it at least as wide as the page, so this floor only
6
+ // matters once unresized columns stop fitting: the table then scrolls inside
7
+ // `.tableWrapper` instead of squeezing each column to a letter per line.
8
+ // Tiptap's `cellMinWidth` stays small because it is also the drag minimum.
9
+ export const READABLE_TABLE_COLUMN_MIN_WIDTH = 96;
10
+
11
+ // Column drags rewrite the table's inline `min-width` on every frame, so the
12
+ // floor lives in a custom property that the stylesheet enforces instead.
13
+ export const READABLE_TABLE_MIN_WIDTH_PROPERTY = "--content-table-min-width";
14
+
15
+ export function readableTableMinWidth(colgroup: HTMLElement): number | null {
16
+ let total = 0;
17
+ let hasUnsizedColumn = false;
18
+ for (const col of Array.from(colgroup.children)) {
19
+ const width = Number.parseFloat((col as HTMLElement).style.width);
20
+ if (width > 0) {
21
+ total += width;
22
+ } else {
23
+ total += READABLE_TABLE_COLUMN_MIN_WIDTH;
24
+ hasUnsizedColumn = true;
25
+ }
26
+ }
27
+ return hasUnsizedColumn ? total : null;
28
+ }
29
+
30
+ export class ContentTableView extends TableView {
31
+ // A column drag restyles the <col>s on every frame but writes the new width
32
+ // to the document only on release, so the floor follows the <col>s.
33
+ private readonly columnObserver = new MutationObserver(() =>
34
+ this.applyReadableMinWidth(),
35
+ );
36
+
37
+ constructor(
38
+ node: ProseMirrorNode,
39
+ cellMinWidth: number,
40
+ view?: EditorView,
41
+ HTMLAttributes: Record<string, unknown> = {},
42
+ ) {
43
+ super(node, cellMinWidth, view, HTMLAttributes);
44
+ this.applyReadableMinWidth();
45
+ this.columnObserver.observe(this.colgroup, {
46
+ attributeFilter: ["style"],
47
+ childList: true,
48
+ subtree: true,
49
+ });
50
+ }
51
+
52
+ override update(node: ProseMirrorNode) {
53
+ if (!super.update(node)) return false;
54
+ this.applyReadableMinWidth();
55
+ return true;
56
+ }
57
+
58
+ destroy() {
59
+ this.columnObserver.disconnect();
60
+ }
61
+
62
+ private applyReadableMinWidth() {
63
+ const minWidth = readableTableMinWidth(this.colgroup);
64
+ if (minWidth === null) {
65
+ this.table.style.removeProperty(READABLE_TABLE_MIN_WIDTH_PROPERTY);
66
+ } else {
67
+ this.table.style.setProperty(
68
+ READABLE_TABLE_MIN_WIDTH_PROPERTY,
69
+ `${minWidth}px`,
70
+ );
71
+ }
72
+ }
73
+ }
@@ -121,10 +121,14 @@
121
121
  }
122
122
 
123
123
  pre,
124
- code {
124
+ pre code {
125
125
  overflow-x: auto;
126
126
  white-space: pre;
127
127
  }
128
+
129
+ code {
130
+ white-space: pre-wrap;
131
+ }
128
132
  }
129
133
 
130
134
  .notion-logo-icon {
@@ -476,7 +480,7 @@
476
480
  .notion-editor ul:not(.notion-task-list) > li,
477
481
  .notion-editor ol > li {
478
482
  display: grid;
479
- grid-template-columns: minmax(1rem, auto) 1fr;
483
+ grid-template-columns: minmax(1rem, auto) minmax(0, 1fr);
480
484
  column-gap: 0.5em;
481
485
  }
482
486
 
@@ -567,7 +571,7 @@
567
571
  }
568
572
  .notion-editor .notion-task-list li {
569
573
  display: grid;
570
- grid-template-columns: 1rem 1fr;
574
+ grid-template-columns: 1rem minmax(0, 1fr);
571
575
  column-gap: 0.5em;
572
576
  }
573
577
  .notion-editor .notion-task-list li label {
@@ -719,6 +723,7 @@
719
723
  margin: 0.6em 0;
720
724
  }
721
725
  .notion-editor pre code {
726
+ white-space: pre;
722
727
  font-family: inherit;
723
728
  background: none;
724
729
  padding: 0;
@@ -836,6 +841,7 @@
836
841
  border-spacing: 0;
837
842
  table-layout: fixed;
838
843
  width: 100% !important;
844
+ min-width: var(--content-table-min-width, 0px) !important;
839
845
  margin: 0;
840
846
  overflow: hidden;
841
847
  border-radius: var(--radius);
@@ -1063,7 +1069,7 @@
1063
1069
 
1064
1070
  div[data-notion-callout] {
1065
1071
  display: grid;
1066
- grid-template-columns: auto 1fr;
1072
+ grid-template-columns: auto minmax(0, 1fr);
1067
1073
  gap: 0.8rem;
1068
1074
  align-items: start;
1069
1075
  margin: 0.9em 0;
@@ -1430,7 +1436,7 @@ div[data-notion-column] > :last-child {
1430
1436
  display: flex;
1431
1437
  align-items: center;
1432
1438
  width: min(100%, 42rem);
1433
- min-width: min(18rem, calc(100vw - 3rem));
1439
+ min-width: min(18rem, 100%);
1434
1440
  min-height: 10rem;
1435
1441
  gap: 0.9rem;
1436
1442
  border: 1px dashed hsl(var(--border));
@@ -1478,7 +1484,7 @@ video.media-block__content {
1478
1484
 
1479
1485
  audio.media-block__content {
1480
1486
  width: min(40rem, calc(100vw - 2rem));
1481
- min-width: min(16.25rem, calc(100vw - 2rem));
1487
+ min-width: min(16.25rem, 100%);
1482
1488
  min-height: 54px;
1483
1489
  background: hsl(var(--muted));
1484
1490
  }
@@ -1611,12 +1617,14 @@ audio.media-block__content {
1611
1617
  outline: none;
1612
1618
  }
1613
1619
 
1620
+ /* Even hidden, a handle box that reaches past the page's narrowest side
1621
+ padding (16px) lets a full-width image scroll the page sideways. */
1614
1622
  .media-block__resize-handle--left {
1615
- left: -22px;
1623
+ left: -16px;
1616
1624
  }
1617
1625
 
1618
1626
  .media-block__resize-handle--right {
1619
- right: -22px;
1627
+ right: -16px;
1620
1628
  }
1621
1629
 
1622
1630
  .media-block__alt-badge {
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-10-02
4
+ ---
5
+
6
+ Pages stay inside the window at every width: long inline code and links wrap, and wide tables scroll inside their own frame instead of crushing their columns
@@ -3,7 +3,7 @@ import { defineConfig, devices } from "@playwright/test";
3
3
  export default defineConfig({
4
4
  testDir: ".",
5
5
  testMatch:
6
- /(registry-blocks|local-files|database-preview-menu|sidebar-delete|shared-personal-page|unreadable-page-link|realtime-collab)\.spec\.ts/,
6
+ /(registry-blocks|local-files|database-preview-menu|sidebar-delete|shared-personal-page|signup-landing|unreadable-page-link|content-responsive-layout|realtime-collab)\.spec\.ts/,
7
7
  fullyParallel: true,
8
8
  workers: process.env.CI ? 2 : 3,
9
9
  retries: 2,
@@ -3,17 +3,58 @@
3
3
  All notable user-facing changes to Design are documented here. Open it any time
4
4
  from the command menu (Cmd+K → "What's new") or from Settings.
5
5
 
6
+ ## 2026-10-05
7
+
8
+ ### Fixed
9
+
10
+ - The Recent tab shows loading placeholders until your designs are ready.
11
+
12
+ ## 2026-10-03
13
+
14
+ ### Fixed
15
+
16
+ - Alt-drag can increase an oversized corner radius even when CSS did not normalize the radius map.
17
+ - Corner-radius handles resize oversized radii without jumping
18
+ - Cross-screen drops skip flex targets whose axis or item placement cannot be modeled.
19
+ - Layers dropped into visible canvas space beyond a Screen now stay on the board.
20
+ - Reopening a Visual Edit connection keeps screens in its saved project
21
+ - Visible Screen overflow no longer routes drops to the canvas
22
+
6
23
  ## 2026-10-02
7
24
 
25
+ ### Improved
26
+
27
+ - Builder.io setup now routes account activation through the one-click flow.
28
+
8
29
  ### Fixed
9
30
 
31
+ - Cross-screen auto-layout drops avoid guessing when direction comes from stylesheet rules
32
+ - Cross-Screen grid drops preserve the selected cell and the layer's track span
33
+ - Design drops now keep the chosen grid cell and follow reverse flex order when falling back to a fitting container
34
+ - Editing a design source file now refreshes collaborators with that design open.
35
+ - Grid drops avoid cells occupied by generated content
36
+ - Grid drops avoid mis-targeting cells in scrolled grids
37
+ - Layers that exceed a frame's width or height now fall back to the nearest container that fits
38
+ - Oversized drops target the nearest container that can fit the dragged layer.
39
+ - Oversized layers can now drop into a fitting ancestor when a nested frame is too small
40
+ - Reverse auto-layout drops keep their visual and layer order aligned.
41
+ - Drag-and-drop placement follows item size, spacing, and visible order in reversed layouts.
10
42
  - Cross-screen drag targets no longer jump when an earlier screen sends a late move.
11
43
  - Cross-screen drags continue when focus moves between screens
12
44
 
13
45
  ## 2026-10-01
14
46
 
47
+ ### Improved
48
+
49
+ - Collaborators on the same screen now appear in the avatar bar in overview.
50
+ - The Design home opens on Recent when designs are available, hides the empty Recent tab, and distinguishes designs you own from those shared with you.
51
+
15
52
  ### Fixed
16
53
 
54
+ - Edits from collaborators now show up in an open design without a refresh, including frame moves and added or deleted screens.
55
+ - PNG and PDF exports now preserve fonts, images, effects, and page framing in imported screens.
56
+ - Two people editing different parts of the same screen no longer lose edits, and one person's undo no longer reverts the other's changes.
57
+ - Viewers on a shared design now see an editor's changes within a few seconds instead of minutes.
17
58
  - A prompt you send before connecting AI is sent automatically once you connect.
18
59
  - Cross-Screen drags now apply modifier keys reliably when the source screen loses focus.
19
60
  - Cross-screen drops now respect modifier keys at release.
@@ -1396,7 +1396,7 @@ export default function Index() {
1396
1396
  }
1397
1397
  recent={
1398
1398
  <>
1399
- {isLoading ? (
1399
+ {isLoading || (isFetching && designs.length === 0) ? (
1400
1400
  <LoadingSkeleton />
1401
1401
  ) : isError ? (
1402
1402
  <QueryErrorState
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-10-05
4
+ ---
5
+
6
+ The Recent tab shows loading placeholders until your designs are ready.
@@ -3,6 +3,12 @@
3
3
  All notable user-facing changes to Agent-Native Mail are documented here. Open it any
4
4
  time from the command menu (Cmd+K → "What's new") or from Settings.
5
5
 
6
+ ## 2026-10-02
7
+
8
+ ### Improved
9
+
10
+ - Builder.io setup copy now clarifies the account action and available credits.
11
+
6
12
  ## 2026-10-01
7
13
 
8
14
  ### Improved
@@ -11,6 +11,7 @@ time from the command menu (Cmd+K → "What's new").
11
11
 
12
12
  ### Fixed
13
13
 
14
+ - Two people editing one plan at the same time, or one of them offline, now keep both sets of edits, and opening a plan together no longer duplicates its content.
14
15
  - Consecutive Plan edits now use the latest saved revision.
15
16
 
16
17
  ## 2026-09-25
@@ -3,10 +3,31 @@
3
3
  All notable user-facing changes to Agent-Native Slides are documented here. Open it any
4
4
  time from the command menu (Cmd+K → "What's new").
5
5
 
6
+ ## 2026-10-05
7
+
8
+ ### Fixed
9
+
10
+ - The Recent tab shows loading placeholders until your decks are ready.
11
+
12
+ ## 2026-10-03
13
+
14
+ ### Fixed
15
+
16
+ - Slide text edits preserve layout with inline-size containment.
17
+
6
18
  ## 2026-10-02
7
19
 
20
+ ### Improved
21
+
22
+ - Builder.io setup now routes account activation through the one-click flow.
23
+ - Recent appears when you have accessible decks, and shared decks are shown when you have none of your own.
24
+ - In-place slide editing now supports slash commands, Markdown shortcuts, and reliable list authoring while preserving text styling.
25
+ - Slides refreshes faster when a collaborator changes the deck open in your tab.
26
+
8
27
  ### Fixed
9
28
 
29
+ - Markdown list shortcuts work when text inherits link formatting
30
+ - Only one queued message action menu stays open at a time
10
31
  - Google Slides imports keep skipped slides and their images in the right place.
11
32
  - Heading text stays intact when Backspace joins it into a styled block.
12
33
  - Slide text editing now preserves formatting and caret placement across browsers.
@@ -15,11 +36,13 @@ time from the command menu (Cmd+K → "What's new").
15
36
 
16
37
  ### Improved
17
38
 
39
+ - Filter decks by owner with an option to view items shared with me.
18
40
  - Recover failed deck saves with explicit retry or reload
19
41
  - The observability settings tab is now labeled Observability.
20
42
 
21
43
  ### Fixed
22
44
 
45
+ - Collaborators editing different text boxes on the same slide now keep both edits instead of hitting a text conflict, and comments, replies and resolves reach other open editors within about a second.
23
46
  - A prompt you send before connecting AI is sent automatically once you connect, and a deck generation that ends without slides shows Try again instead of an empty canvas.
24
47
  - Blank speaker notes can be edited and saved without a conflict.
25
48
  - New deck prompts no longer add a default design system unless you choose one, and empty failed generations explain what happened.
@@ -2623,31 +2623,35 @@ export default function Index({ active = true }: { active?: boolean }) {
2623
2623
  }
2624
2624
  templates={<DeckTemplateLibrary enabled={isHome} />}
2625
2625
  recent={
2626
- <div className="agent-template-library-grid">
2627
- {visibleDecks.map((deck) => (
2628
- <DeckCard
2629
- key={deck.id}
2630
- deck={deck}
2631
- onDelete={(id) => setDeckToDelete(id)}
2632
- onRename={handleRename}
2633
- onDuplicate={handleDuplicate}
2634
- onToggleStar={handleToggleStar}
2635
- isWorkspaceDefault={workspaceReferenceDeck?.id === deck.id}
2636
- canSetWorkspaceDefault={canManageWorkspaceDefaults}
2637
- onSetWorkspaceDefault={handleSetWorkspaceDefaultDeck}
2638
- />
2639
- ))}
2640
- {visibleDecks.length === 0 &&
2641
- (normalizedDeckSearch ? (
2642
- <div className="rounded-xl bg-card p-6 text-sm text-muted-foreground">
2643
- {t("home.noDecksMatchSearch")}
2644
- </div>
2645
- ) : (
2646
- <div className="rounded-xl bg-card p-6 text-sm text-muted-foreground">
2647
- {t("home.noDecksMatchFilter")}
2648
- </div>
2626
+ viewState === "loading" ? (
2627
+ <DeckListLoadingSkeleton />
2628
+ ) : viewState === "error" ? null : (
2629
+ <div className="agent-template-library-grid">
2630
+ {visibleDecks.map((deck) => (
2631
+ <DeckCard
2632
+ key={deck.id}
2633
+ deck={deck}
2634
+ onDelete={(id) => setDeckToDelete(id)}
2635
+ onRename={handleRename}
2636
+ onDuplicate={handleDuplicate}
2637
+ onToggleStar={handleToggleStar}
2638
+ isWorkspaceDefault={workspaceReferenceDeck?.id === deck.id}
2639
+ canSetWorkspaceDefault={canManageWorkspaceDefaults}
2640
+ onSetWorkspaceDefault={handleSetWorkspaceDefaultDeck}
2641
+ />
2649
2642
  ))}
2650
- </div>
2643
+ {visibleDecks.length === 0 &&
2644
+ (normalizedDeckSearch ? (
2645
+ <div className="rounded-xl bg-card p-6 text-sm text-muted-foreground">
2646
+ {t("home.noDecksMatchSearch")}
2647
+ </div>
2648
+ ) : (
2649
+ <div className="rounded-xl bg-card p-6 text-sm text-muted-foreground">
2650
+ {t("home.noDecksMatchFilter")}
2651
+ </div>
2652
+ ))}
2653
+ </div>
2654
+ )
2651
2655
  }
2652
2656
  />
2653
2657
  </ClientOnly>
@@ -2814,6 +2818,29 @@ export default function Index({ active = true }: { active?: boolean }) {
2814
2818
  );
2815
2819
  }
2816
2820
 
2821
+ function DeckListLoadingSkeleton() {
2822
+ return (
2823
+ <div className="agent-template-library-grid" aria-busy="true">
2824
+ {Array.from({ length: 8 }, (_, index) => (
2825
+ <div
2826
+ key={index}
2827
+ className="agent-template-library-card group relative min-w-0"
2828
+ aria-hidden="true"
2829
+ >
2830
+ <div className="agent-template-library-primary overflow-hidden rounded-xl border border-border bg-card">
2831
+ <div className="agent-template-library-preview bg-muted/30">
2832
+ <Skeleton className="size-full rounded-none" />
2833
+ </div>
2834
+ <div className="agent-template-library-caption">
2835
+ <Skeleton className="h-4 w-3/4" />
2836
+ </div>
2837
+ </div>
2838
+ </div>
2839
+ ))}
2840
+ </div>
2841
+ );
2842
+ }
2843
+
2817
2844
  function DeckSearchInput({
2818
2845
  value,
2819
2846
  onChange,
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-10-05
4
+ ---
5
+
6
+ The Recent tab shows loading placeholders until your decks are ready.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-native/core-corpus",
3
- "version": "0.201.0-nightly-20261005183955",
3
+ "version": "0.201.0",
4
4
  "description": "Opt-in source corpus for Agent-Native Core source-search.",
5
5
  "homepage": "https://github.com/BuilderIO/agent-native#readme",
6
6
  "bugs": {