@agent-native/core 0.157.2 → 0.157.4

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 (167) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/analytics/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
  3. package/corpus/templates/analytics/.agents/skills/sharing/SKILL.md +21 -0
  4. package/corpus/templates/analytics/server/lib/first-party-analytics-backend.ts +40 -1
  5. package/corpus/templates/assets/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
  6. package/corpus/templates/assets/.agents/skills/sharing/SKILL.md +21 -0
  7. package/corpus/templates/brain/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
  8. package/corpus/templates/brain/.agents/skills/sharing/SKILL.md +21 -0
  9. package/corpus/templates/calendar/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
  10. package/corpus/templates/calendar/.agents/skills/sharing/SKILL.md +21 -0
  11. package/corpus/templates/calendar/app/components/layout/AppLayout.tsx +3 -1
  12. package/corpus/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
  13. package/corpus/templates/chat/.agents/skills/sharing/SKILL.md +21 -0
  14. package/corpus/templates/clips/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
  15. package/corpus/templates/clips/.agents/skills/meetings/SKILL.md +7 -7
  16. package/corpus/templates/clips/actions/approve-recording-access-request.ts +147 -0
  17. package/corpus/templates/clips/actions/request-recording-access.ts +121 -23
  18. package/corpus/templates/clips/actions/view-screen.ts +1 -1
  19. package/corpus/templates/clips/app/components/meetings/share-meeting-dialog.tsx +34 -53
  20. package/corpus/templates/clips/app/components/player/request-access-dialog.tsx +104 -0
  21. package/corpus/templates/clips/app/components/player/share-dialog.tsx +36 -45
  22. package/corpus/templates/clips/app/components/sharing/share-ui.tsx +3 -6
  23. package/corpus/templates/clips/app/i18n/en-US.ts +26 -1
  24. package/corpus/templates/clips/app/lib/public-meeting.ts +1 -1
  25. package/corpus/templates/clips/app/routes/access-request.approve.tsx +250 -0
  26. package/corpus/templates/clips/app/routes/r.$recordingId.tsx +9 -32
  27. package/corpus/templates/clips/app/routes/share.$shareId.tsx +123 -37
  28. package/corpus/templates/clips/app/routes/share.meeting.$meetingId.tsx +41 -1
  29. package/corpus/templates/clips/server/lib/calendar-event-meetings.ts +1 -0
  30. package/corpus/templates/clips/server/lib/emails.ts +40 -11
  31. package/corpus/templates/clips/shared/recording-link.ts +32 -1
  32. package/corpus/templates/clips/shared/share-attribution.ts +13 -0
  33. package/corpus/templates/content/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
  34. package/corpus/templates/content/.agents/skills/sharing/SKILL.md +21 -0
  35. package/corpus/templates/content/actions/add-database-item.ts +9 -0
  36. package/corpus/templates/content/actions/describe-content-database.ts +92 -0
  37. package/corpus/templates/content/actions/list-content-databases.ts +213 -72
  38. package/corpus/templates/content/actions/set-document-property.ts +9 -0
  39. package/corpus/templates/content/actions/submit-content-database-form.ts +9 -0
  40. package/corpus/templates/content/actions/update-document.ts +9 -0
  41. package/corpus/templates/content/app/components/editor/DocumentBlockFields.tsx +22 -10
  42. package/corpus/templates/content/app/components/editor/SlashCommandMenu.tsx +2 -1
  43. package/corpus/templates/content/app/components/editor/VisualEditor.tsx +245 -9
  44. package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +192 -134
  45. package/corpus/templates/content/app/components/editor/database/settings.tsx +7 -0
  46. package/corpus/templates/content/app/components/editor/extensions/ImageBlock.tsx +61 -45
  47. package/corpus/templates/content/app/components/editor/extensions/ImageNode.ts +6 -0
  48. package/corpus/templates/content/app/components/editor/image-upload.ts +137 -5
  49. package/corpus/templates/content/app/global.css +8 -0
  50. package/corpus/templates/content/app/hooks/use-content-database.ts +91 -11
  51. package/corpus/templates/content/changelog/2026-08-12-image-uploads-now-confirm-the-image-can-be-displayed-before-.md +6 -0
  52. package/corpus/templates/content/changelog/2026-08-14-images-fill-the-page-width-by-default-and-remain-visible-whe.md +6 -0
  53. package/corpus/templates/content/changelog/2026-08-14-images-inserted-from-the-slash-command-stay-saved-after-uplo.md +6 -0
  54. package/corpus/templates/content/changelog/2026-08-14-svg-files-can-be-selected-reliably-from-the-image-picker.md +6 -0
  55. package/corpus/templates/content/parity/matrix.md +1 -1
  56. package/corpus/templates/content/parity/matrix.ts +7 -1
  57. package/corpus/templates/content/server/plugins/agent-chat.ts +3 -0
  58. package/corpus/templates/content/shared/api.ts +9 -0
  59. package/corpus/templates/crm/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
  60. package/corpus/templates/crm/.agents/skills/sharing/SKILL.md +21 -0
  61. package/corpus/templates/design/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
  62. package/corpus/templates/design/.agents/skills/sharing/SKILL.md +21 -0
  63. package/corpus/templates/dispatch/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
  64. package/corpus/templates/dispatch/.agents/skills/sharing/SKILL.md +21 -0
  65. package/corpus/templates/factory/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
  66. package/corpus/templates/factory/.agents/skills/sharing/SKILL.md +21 -0
  67. package/corpus/templates/forms/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
  68. package/corpus/templates/forms/.agents/skills/sharing/SKILL.md +21 -0
  69. package/corpus/templates/macros/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
  70. package/corpus/templates/macros/.agents/skills/sharing/SKILL.md +21 -0
  71. package/corpus/templates/mail/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
  72. package/corpus/templates/mail/.agents/skills/sharing/SKILL.md +21 -0
  73. package/corpus/templates/mail/app/components/layout/AppLayout.tsx +6 -1
  74. package/corpus/templates/plan/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
  75. package/corpus/templates/plan/.agents/skills/sharing/SKILL.md +21 -0
  76. package/corpus/templates/plan/app/pages/PlansPage.tsx +25 -30
  77. package/corpus/templates/slides/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
  78. package/corpus/templates/slides/.agents/skills/sharing/SKILL.md +21 -0
  79. package/corpus/templates/slides/app/components/deck/SlideRenderer.tsx +2 -1
  80. package/corpus/templates/slides/app/components/editor/ShareDialog.tsx +124 -180
  81. package/corpus/templates/slides/app/components/onboarding/FirstDeckOnboardingFlow.tsx +1 -0
  82. package/corpus/templates/slides/app/global.css +99 -3
  83. package/corpus/templates/slides/app/i18n/en-US.ts +1 -0
  84. package/corpus/templates/tasks/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
  85. package/corpus/templates/tasks/.agents/skills/sharing/SKILL.md +21 -0
  86. package/dist/chat-threads/schema.d.ts +1 -1
  87. package/dist/cli/code-agent-executor.js +318 -0
  88. package/dist/client/AgentPanel.d.ts +13 -1
  89. package/dist/client/AgentPanel.js +41 -3
  90. package/dist/client/AssistantChat.d.ts +9 -1
  91. package/dist/client/AssistantChat.js +26 -13
  92. package/dist/client/MultiTabAssistantChat.js +18 -5
  93. package/dist/client/agent-chat.d.ts +8 -0
  94. package/dist/client/agent-chat.js +15 -0
  95. package/dist/client/app-chat-sidebar.d.ts +23 -0
  96. package/dist/client/app-chat-sidebar.js +53 -0
  97. package/dist/client/app-providers.js +31 -2
  98. package/dist/client/frame-protocol.d.ts +20 -2
  99. package/dist/client/hooks/index.d.ts +1 -0
  100. package/dist/client/hooks/index.js +1 -0
  101. package/dist/client/sharing/AgentShareSection.d.ts +8 -0
  102. package/dist/client/sharing/AgentShareSection.js +50 -0
  103. package/dist/client/sharing/ShareButton.js +2 -1
  104. package/dist/client/sharing/ShareDialog.d.ts +2 -2
  105. package/dist/client/sharing/ShareDialog.js +21 -29
  106. package/dist/client/sharing/index.d.ts +1 -0
  107. package/dist/client/sharing/index.js +1 -0
  108. package/dist/client/sharing/useShareButtonController.d.ts +1 -0
  109. package/dist/client/sharing/useShareDialogController.d.ts +3 -0
  110. package/dist/client/sharing/useShareDialogController.js +2 -1
  111. package/dist/client/theme.d.ts +21 -0
  112. package/dist/client/theme.js +60 -0
  113. package/dist/client/ui/index.d.ts +1 -1
  114. package/dist/client/ui/index.js +1 -1
  115. package/dist/client/use-session.js +23 -0
  116. package/dist/collab/awareness.d.ts +2 -2
  117. package/dist/collab/routes.d.ts +1 -1
  118. package/dist/collab/struct-routes.d.ts +1 -1
  119. package/dist/dashboard-storage/schema.d.ts +1 -1
  120. package/dist/data-programs/schema.d.ts +1 -1
  121. package/dist/extensions/schema.d.ts +1 -1
  122. package/dist/localization/core-messages/ar-SA.js +6 -0
  123. package/dist/localization/core-messages/de-DE.js +6 -0
  124. package/dist/localization/core-messages/en-US.d.ts +6 -0
  125. package/dist/localization/core-messages/en-US.js +6 -0
  126. package/dist/localization/core-messages/es-ES.js +6 -0
  127. package/dist/localization/core-messages/fr-FR.js +6 -0
  128. package/dist/localization/core-messages/hi-IN.js +6 -0
  129. package/dist/localization/core-messages/ja-JP.js +6 -0
  130. package/dist/localization/core-messages/ko-KR.js +6 -0
  131. package/dist/localization/core-messages/pt-BR.js +6 -0
  132. package/dist/localization/core-messages/zh-CN.js +6 -0
  133. package/dist/localization/core-messages/zh-TW.js +6 -0
  134. package/dist/localization/core-messages.d.ts +6 -0
  135. package/dist/localization/default-messages.d.ts +1 -0
  136. package/dist/localization/default-messages.js +1 -0
  137. package/dist/notifications/routes.d.ts +3 -3
  138. package/dist/observability/routes.d.ts +5 -5
  139. package/dist/provider-api/actions/custom-provider-registration.d.ts +14 -14
  140. package/dist/provider-api/actions/provider-api.d.ts +14 -14
  141. package/dist/secrets/routes.d.ts +9 -9
  142. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  143. package/dist/server/auth.js +8 -5
  144. package/dist/server/identity-sso-store.d.ts +6 -1
  145. package/dist/server/identity-sso-store.js +57 -14
  146. package/dist/server/identity-sso.d.ts +7 -8
  147. package/dist/server/identity-sso.js +15 -12
  148. package/dist/sharing/actions/list-resource-shares.d.ts +2 -0
  149. package/dist/sharing/actions/list-resource-shares.js +1 -0
  150. package/dist/sharing/schema.d.ts +1 -1
  151. package/dist/sharing/schema.js +4 -1
  152. package/dist/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
  153. package/dist/templates/chat/.agents/skills/sharing/SKILL.md +21 -0
  154. package/dist/templates/default/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
  155. package/dist/templates/default/.agents/skills/sharing/SKILL.md +21 -0
  156. package/dist/templates/headless/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
  157. package/dist/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
  158. package/dist/templates/workspace-core/.agents/skills/sharing/SKILL.md +21 -0
  159. package/docs/content/cross-app-sso.mdx +24 -17
  160. package/package.json +3 -3
  161. package/src/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
  162. package/src/templates/chat/.agents/skills/sharing/SKILL.md +21 -0
  163. package/src/templates/default/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
  164. package/src/templates/default/.agents/skills/sharing/SKILL.md +21 -0
  165. package/src/templates/headless/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
  166. package/src/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
  167. package/src/templates/workspace-core/.agents/skills/sharing/SKILL.md +21 -0
@@ -10,6 +10,7 @@ import {
10
10
  useBuilderConnectFlow,
11
11
  useBuilderStatus,
12
12
  } from "@agent-native/core/client/settings";
13
+ import { DataGrid, type DataGridColumn } from "@agent-native/toolkit/data-grid";
13
14
  import {
14
15
  CONTENT_DATABASE_PERSONAL_VIEW_OVERRIDES_VERSION,
15
16
  type BuilderCmsModelSummary,
@@ -113,6 +114,7 @@ import {
113
114
  import { Link, useLocation, useNavigate } from "react-router";
114
115
  import { toast } from "sonner";
115
116
 
117
+ import { QueryErrorState } from "@/components/QueryErrorState";
116
118
  import {
117
119
  contentSpaceForCatalogItem,
118
120
  createContentSpaceSelectionQueue,
@@ -4903,6 +4905,16 @@ function DatabaseItemPreview({
4903
4905
  if (controller) scheduleDraftWrite(controller);
4904
4906
  }
4905
4907
 
4908
+ async function handleContentSaveNow(nextContent: string) {
4909
+ setLocalContent(nextContent);
4910
+ if (!previewCanEdit || !document) return false;
4911
+ const controller = saveControllerRef.current;
4912
+ if (!controller) return false;
4913
+ controller.changeContent(nextContent);
4914
+ await controller.flush();
4915
+ return controller.lastSaved.content === nextContent;
4916
+ }
4917
+
4906
4918
  function keepLocalBodyDraft() {
4907
4919
  if (!activeBodyDraftConflict) return;
4908
4920
  const controller = peekPreviewDocumentSaveController(documentId);
@@ -5221,6 +5233,7 @@ function DatabaseItemPreview({
5221
5233
  documentId={previewDocument.id}
5222
5234
  content={localContent}
5223
5235
  onChange={handleContentChange}
5236
+ onSaveContent={handleContentSaveNow}
5224
5237
  ydoc={null}
5225
5238
  editable={previewCanEdit}
5226
5239
  />
@@ -5534,6 +5547,36 @@ function DatabaseTableView({
5534
5547
  const actionColumnWidth = cleanDefaultTable
5535
5548
  ? EMPTY_DEFAULT_ADD_PROPERTY_COLUMN_WIDTH
5536
5549
  : ACTION_COLUMN_WIDTH;
5550
+ const dataGridColumns = useMemo<DataGridColumn<ContentDatabaseItem>[]>(
5551
+ () => [
5552
+ {
5553
+ id: "name",
5554
+ width: DEFAULT_NAME_COLUMN_WIDTH,
5555
+ minWidth: MIN_COLUMN_WIDTH,
5556
+ maxWidth: MAX_COLUMN_WIDTH,
5557
+ resizable: false,
5558
+ },
5559
+ ...properties.map((property) => ({
5560
+ id: property.definition.id,
5561
+ width: DEFAULT_PROPERTY_COLUMN_WIDTH,
5562
+ minWidth: MIN_COLUMN_WIDTH,
5563
+ maxWidth: MAX_COLUMN_WIDTH,
5564
+ resizable: false,
5565
+ })),
5566
+ ...(canEdit
5567
+ ? [
5568
+ {
5569
+ id: "actions",
5570
+ width: actionColumnWidth,
5571
+ minWidth: actionColumnWidth,
5572
+ maxWidth: actionColumnWidth,
5573
+ resizable: false,
5574
+ },
5575
+ ]
5576
+ : []),
5577
+ ],
5578
+ [actionColumnWidth, canEdit, properties],
5579
+ );
5537
5580
  const rowDraggingEnabled =
5538
5581
  canEdit &&
5539
5582
  rowsAreManuallyOrdered &&
@@ -5883,12 +5926,18 @@ function DatabaseTableView({
5883
5926
  }}
5884
5927
  />
5885
5928
  ) : null}
5886
- <div
5887
- data-database-scroll-surface="table"
5888
- tabIndex={0}
5889
- className="w-full min-w-0 max-w-full overflow-x-auto overscroll-x-contain"
5890
- >
5891
- <div className="w-max min-w-full min-w-[720px]">
5929
+ {/* DataGrid preserves the table contract: data-database-scroll-surface="table", tabIndex={0}, and min-w-0 max-w-full overflow-x-auto. */}
5930
+ <DataGrid
5931
+ rows={items}
5932
+ columns={dataGridColumns}
5933
+ getRowId={(item) => item.id}
5934
+ columnWidths={columnWidths}
5935
+ contentClassName="min-w-[720px]"
5936
+ scrollContainerProps={{
5937
+ "data-database-scroll-surface": "table",
5938
+ tabIndex: 0,
5939
+ }}
5940
+ renderHeader={() => (
5892
5941
  <div
5893
5942
  className="grid border-y border-border/35 text-xs font-medium text-muted-foreground/80"
5894
5943
  style={{
@@ -5970,146 +6019,149 @@ function DatabaseTableView({
5970
6019
  </div>
5971
6020
  ) : null}
5972
6021
  </div>
5973
-
5974
- {databaseTableShouldShowBlockingLoader(isLoading, items.length) ? (
5975
- <div className="flex h-16 items-center gap-2 border-t border-border px-2 text-sm text-muted-foreground">
5976
- <Spinner className="size-4" />
5977
- {dbText("loadingDatabase")}
5978
- </div>
5979
- ) : (
5980
- <>
5981
- {databaseViewHasNoMatchingPages(
5982
- items.length,
5983
- hasSearch,
5984
- activeFilters.length,
5985
- ) ? (
5986
- <DatabaseNoMatchingPages
5987
- className="border-t border-border"
5988
- label={dbText("noRowsMatchThisView")}
5989
- onClear={onClearResultConstraints}
5990
- />
5991
- ) : null}
5992
- {grouped
5993
- ? groups.map((group) => (
5994
- <DatabaseGroupedTableSection
5995
- key={group.id}
5996
- group={group}
6022
+ )}
6023
+ renderBody={() => (
6024
+ <>
6025
+ {databaseTableShouldShowBlockingLoader(isLoading, items.length) ? (
6026
+ <div className="flex h-16 items-center gap-2 border-t border-border px-2 text-sm text-muted-foreground">
6027
+ <Spinner className="size-4" />
6028
+ {dbText("loadingDatabase")}
6029
+ </div>
6030
+ ) : (
6031
+ <>
6032
+ {databaseViewHasNoMatchingPages(
6033
+ items.length,
6034
+ hasSearch,
6035
+ activeFilters.length,
6036
+ ) ? (
6037
+ <DatabaseNoMatchingPages
6038
+ className="border-t border-border"
6039
+ label={dbText("noRowsMatchThisView")}
6040
+ onClear={onClearResultConstraints}
6041
+ />
6042
+ ) : null}
6043
+ {grouped
6044
+ ? groups.map((group) => (
6045
+ <DatabaseGroupedTableSection
6046
+ key={group.id}
6047
+ group={group}
6048
+ properties={properties}
6049
+ columnWidths={columnWidths}
6050
+ databaseDocumentId={databaseDocumentId}
6051
+ workspaceCatalog={isWorkspaceCatalog}
6052
+ workspaceCreationPropertyValues={
6053
+ workspaceCreationPropertyValues
6054
+ }
6055
+ canEdit={canEdit}
6056
+ selectedIdSet={selectedIdSet}
6057
+ wrapCells={wrapCells}
6058
+ rowDensity={rowDensity}
6059
+ isCreating={isCreating}
6060
+ newRowLabel={newRowLabel}
6061
+ focusedTitleDocumentId={focusedTitleDocumentId}
6062
+ collapsed={databaseGroupIsCollapsed(
6063
+ collapsedGroupIds,
6064
+ group.id,
6065
+ )}
6066
+ onCreateRow={onCreateGroupedRow}
6067
+ onTitleFocusHandled={onTitleFocusHandled}
6068
+ onCollapsedChange={(collapsed) =>
6069
+ onGroupCollapsedChange(group.id, collapsed)
6070
+ }
6071
+ onToggleCheckbox={toggleCheckboxCell}
6072
+ onToggleRowSelection={onToggleRowSelection}
6073
+ onPreview={onPreview}
6074
+ onDeletedPreviewItem={onDeletedPreviewItem}
6075
+ onOpenPage={onOpenPage}
6076
+ />
6077
+ ))
6078
+ : items.map((item, index) => (
6079
+ <DatabaseTableRow
6080
+ key={item.id}
6081
+ item={item}
6082
+ databaseDocumentId={databaseDocumentId}
6083
+ workspaceCatalog={isWorkspaceCatalog}
6084
+ properties={properties}
6085
+ columnWidths={columnWidths}
6086
+ canEdit={canEdit}
6087
+ rowIndex={index}
6088
+ canReorder={rowsAreManuallyOrdered}
6089
+ canDragRow={rowDraggingEnabled}
6090
+ canMoveUp={rowsAreManuallyOrdered && index > 0}
6091
+ canMoveDown={
6092
+ rowsAreManuallyOrdered && index < items.length - 1
6093
+ }
6094
+ selected={selectedIdSet.has(item.id)}
6095
+ isDragging={draggedItemId === item.id}
6096
+ isDropTarget={
6097
+ !!draggedItemId &&
6098
+ dropTargetItemId === item.id &&
6099
+ draggedItemId !== item.id
6100
+ }
6101
+ startEditingTitle={
6102
+ focusedTitleDocumentId === item.document.id
6103
+ }
6104
+ onDragHandlePointerDown={(event) =>
6105
+ startRowDrag(item.id, event)
6106
+ }
6107
+ onToggleCheckbox={(property) =>
6108
+ void toggleCheckboxCell(item, property)
6109
+ }
6110
+ wrapCells={wrapCells}
6111
+ rowDensity={rowDensity}
6112
+ onToggleSelected={() => onToggleRowSelection(item.id)}
6113
+ onPreviewItem={onPreview}
6114
+ onDeletedPreviewItem={onDeletedPreviewItem}
6115
+ onTitleEditStarted={onTitleFocusHandled}
6116
+ onPreview={() => onPreview(item)}
6117
+ onOpenPage={() => onOpenPage(item)}
6118
+ />
6119
+ ))}
6120
+ {canEdit && !grouped ? (
6121
+ isWorkspaceCatalog ? (
6122
+ <WorkspaceSourceMenuRow
6123
+ label={newRowLabel}
5997
6124
  properties={properties}
5998
6125
  columnWidths={columnWidths}
5999
- databaseDocumentId={databaseDocumentId}
6000
- workspaceCatalog={isWorkspaceCatalog}
6001
- workspaceCreationPropertyValues={
6002
- workspaceCreationPropertyValues
6003
- }
6004
- canEdit={canEdit}
6005
- selectedIdSet={selectedIdSet}
6006
- wrapCells={wrapCells}
6007
6126
  rowDensity={rowDensity}
6008
- isCreating={isCreating}
6009
- newRowLabel={newRowLabel}
6010
- focusedTitleDocumentId={focusedTitleDocumentId}
6011
- collapsed={databaseGroupIsCollapsed(
6012
- collapsedGroupIds,
6013
- group.id,
6014
- )}
6015
- onCreateRow={onCreateGroupedRow}
6016
- onTitleFocusHandled={onTitleFocusHandled}
6017
- onCollapsedChange={(collapsed) =>
6018
- onGroupCollapsedChange(group.id, collapsed)
6019
- }
6020
- onToggleCheckbox={toggleCheckboxCell}
6021
- onToggleRowSelection={onToggleRowSelection}
6022
- onPreview={onPreview}
6023
- onDeletedPreviewItem={onDeletedPreviewItem}
6024
- onOpenPage={onOpenPage}
6127
+ propertyValues={workspaceCreationPropertyValues}
6128
+ actionColumnWidth={actionColumnWidth}
6025
6129
  />
6026
- ))
6027
- : items.map((item, index) => (
6028
- <DatabaseTableRow
6029
- key={item.id}
6030
- item={item}
6031
- databaseDocumentId={databaseDocumentId}
6032
- workspaceCatalog={isWorkspaceCatalog}
6130
+ ) : (
6131
+ <NewDatabaseRow
6132
+ label={newRowLabel}
6033
6133
  properties={properties}
6034
6134
  columnWidths={columnWidths}
6035
- canEdit={canEdit}
6036
- rowIndex={index}
6037
- canReorder={rowsAreManuallyOrdered}
6038
- canDragRow={rowDraggingEnabled}
6039
- canMoveUp={rowsAreManuallyOrdered && index > 0}
6040
- canMoveDown={
6041
- rowsAreManuallyOrdered && index < items.length - 1
6042
- }
6043
- selected={selectedIdSet.has(item.id)}
6044
- isDragging={draggedItemId === item.id}
6045
- isDropTarget={
6046
- !!draggedItemId &&
6047
- dropTargetItemId === item.id &&
6048
- draggedItemId !== item.id
6049
- }
6050
- startEditingTitle={
6051
- focusedTitleDocumentId === item.document.id
6052
- }
6053
- onDragHandlePointerDown={(event) =>
6054
- startRowDrag(item.id, event)
6055
- }
6056
- onToggleCheckbox={(property) =>
6057
- void toggleCheckboxCell(item, property)
6058
- }
6059
- wrapCells={wrapCells}
6060
6135
  rowDensity={rowDensity}
6061
- onToggleSelected={() => onToggleRowSelection(item.id)}
6062
- onPreviewItem={onPreview}
6063
- onDeletedPreviewItem={onDeletedPreviewItem}
6064
- onTitleEditStarted={onTitleFocusHandled}
6065
- onPreview={() => onPreview(item)}
6066
- onOpenPage={() => onOpenPage(item)}
6136
+ disabled={isCreating}
6137
+ isPending={isCreating}
6138
+ onCreate={onCreateRow}
6139
+ actionColumnWidth={actionColumnWidth}
6067
6140
  />
6068
- ))}
6069
- {canEdit && !grouped ? (
6070
- isWorkspaceCatalog ? (
6071
- <WorkspaceSourceMenuRow
6072
- label={newRowLabel}
6073
- properties={properties}
6074
- columnWidths={columnWidths}
6075
- rowDensity={rowDensity}
6076
- propertyValues={workspaceCreationPropertyValues}
6077
- actionColumnWidth={actionColumnWidth}
6078
- />
6079
- ) : (
6080
- <NewDatabaseRow
6081
- label={newRowLabel}
6082
- properties={properties}
6083
- columnWidths={columnWidths}
6084
- rowDensity={rowDensity}
6085
- disabled={isCreating}
6086
- isPending={isCreating}
6087
- onCreate={onCreateRow}
6141
+ )
6142
+ ) : null}
6143
+ {cleanDefaultTable ? (
6144
+ <DatabaseBlankDefaultRows
6145
+ rowCount={EMPTY_DEFAULT_BLANK_ROW_COUNT}
6088
6146
  actionColumnWidth={actionColumnWidth}
6089
6147
  />
6090
- )
6091
- ) : null}
6092
- {cleanDefaultTable ? (
6093
- <DatabaseBlankDefaultRows
6094
- rowCount={EMPTY_DEFAULT_BLANK_ROW_COUNT}
6148
+ ) : null}
6149
+ <DatabaseTableFooter
6150
+ properties={properties}
6151
+ items={items}
6152
+ totalCount={totalCount}
6153
+ constrained={constrained}
6154
+ columnWidths={columnWidths}
6155
+ canEdit={canEdit}
6156
+ calculations={calculations}
6095
6157
  actionColumnWidth={actionColumnWidth}
6158
+ onCalculationChange={onCalculationChange}
6096
6159
  />
6097
- ) : null}
6098
- <DatabaseTableFooter
6099
- properties={properties}
6100
- items={items}
6101
- totalCount={totalCount}
6102
- constrained={constrained}
6103
- columnWidths={columnWidths}
6104
- canEdit={canEdit}
6105
- calculations={calculations}
6106
- actionColumnWidth={actionColumnWidth}
6107
- onCalculationChange={onCalculationChange}
6108
- />
6109
- </>
6110
- )}
6111
- </div>
6112
- </div>
6160
+ </>
6161
+ )}
6162
+ </>
6163
+ )}
6164
+ />
6113
6165
  <AlertDialog
6114
6166
  open={
6115
6167
  !removesFavoriteMembership &&
@@ -9265,6 +9317,12 @@ function AddSourceView({
9265
9317
  <Spinner className="size-3.5" />
9266
9318
  {dbText("loadingTables")}
9267
9319
  </div>
9320
+ ) : query.isError ? (
9321
+ <QueryErrorState
9322
+ compact
9323
+ onRetry={() => void query.refetch()}
9324
+ retrying={query.isFetching}
9325
+ />
9268
9326
  ) : tables.length === 0 ? (
9269
9327
  <div className="min-w-0 break-words px-2 text-xs text-muted-foreground">
9270
9328
  {dbText("noOtherDatabasesAvailableToAdd")}
@@ -52,6 +52,7 @@ import {
52
52
  } from "react";
53
53
  import { toast } from "sonner";
54
54
 
55
+ import { QueryErrorState } from "@/components/QueryErrorState";
55
56
  import { Button } from "@/components/ui/button";
56
57
  import {
57
58
  DropdownMenu,
@@ -1543,6 +1544,12 @@ function AddSourceView({
1543
1544
  <Spinner className="size-3.5" />
1544
1545
  {dbText("loadingTables")}
1545
1546
  </div>
1547
+ ) : query.isError ? (
1548
+ <QueryErrorState
1549
+ compact
1550
+ onRetry={() => void query.refetch()}
1551
+ retrying={query.isFetching}
1552
+ />
1546
1553
  ) : tables.length === 0 ? (
1547
1554
  <div className="min-w-0 break-words px-2 text-xs text-muted-foreground">
1548
1555
  {dbText("noOtherDatabasesAvailableToAdd")}
@@ -22,7 +22,6 @@ import {
22
22
  } from "@tabler/icons-react";
23
23
  import { NodeViewWrapper, type NodeViewProps } from "@tiptap/react";
24
24
  import {
25
- type ChangeEvent,
26
25
  type FormEvent,
27
26
  type PointerEvent as ReactPointerEvent,
28
27
  useEffect,
@@ -52,7 +51,7 @@ import {
52
51
  TooltipTrigger,
53
52
  } from "@/components/ui/tooltip";
54
53
 
55
- import { imageUploadErrorMessage, uploadImageFile } from "../image-upload";
54
+ import { createImagePickerId } from "../image-upload";
56
55
  import type { ContentImageOptions } from "./ImageNode";
57
56
 
58
57
  type ImageSourceTab = "upload" | "assets" | "link";
@@ -69,7 +68,6 @@ const MIN_IMAGE_WIDTH = 160;
69
68
  const MAX_AGENT_IMAGE_DIMENSION = 1600;
70
69
  const ALT_TEXT_CONTEXT_WORD_LIMIT = 250;
71
70
  const DEFAULT_ASSETS_PICKER_URL = "https://assets.agent-native.com/picker";
72
-
73
71
  interface PickedAssetImagePayload {
74
72
  url?: unknown;
75
73
  previewUrl?: unknown;
@@ -515,7 +513,6 @@ export function ImageBlock({
515
513
  const [moreMenuOpen, setMoreMenuOpen] = useState(false);
516
514
  const [isGeneratingAlt, setIsGeneratingAlt] = useState(false);
517
515
  const [imageLoadFailed, setImageLoadFailed] = useState(false);
518
- const fileInputRef = useRef<HTMLInputElement>(null);
519
516
  const altInputRef = useRef<HTMLInputElement>(null);
520
517
  const emptyBlockRef = useRef<HTMLDivElement>(null);
521
518
  const lightboxImageRef = useRef<HTMLImageElement>(null);
@@ -524,7 +521,9 @@ export function ImageBlock({
524
521
  const isEditable = editor.isEditable;
525
522
  const src = node.attrs.src as string;
526
523
  const alt = (node.attrs.alt as string) || "";
527
- const isUploading = Boolean(node.attrs.uploadId);
524
+ const isUploading = String(node.attrs.uploadId ?? "").startsWith(
525
+ "image-upload-",
526
+ );
528
527
  const width = normalizedImageWidth(node.attrs.width);
529
528
  const activeWidth = dragWidth ?? width;
530
529
  const controlsVisible = isEditable && (isHovered || selected);
@@ -546,6 +545,12 @@ export function ImageBlock({
546
545
  ) {
547
546
  return;
548
547
  }
548
+ if (
549
+ !src &&
550
+ String(node.attrs.uploadId ?? "").startsWith("image-picker-")
551
+ ) {
552
+ updateAttributes({ uploadId: null });
553
+ }
549
554
  setSourcePanelOpen(false);
550
555
  setSourcePanelDismissed(true);
551
556
  }
@@ -553,7 +558,7 @@ export function ImageBlock({
553
558
  document.addEventListener("pointerdown", handlePointerDown, true);
554
559
  return () =>
555
560
  document.removeEventListener("pointerdown", handlePointerDown, true);
556
- }, [selected, sourcePanelOpen]);
561
+ }, [node.attrs.uploadId, selected, sourcePanelOpen, src, updateAttributes]);
557
562
 
558
563
  function handleComment() {
559
564
  if (!options.onImageComment) return;
@@ -761,20 +766,25 @@ export function ImageBlock({
761
766
  };
762
767
  }, [updateAttributes]);
763
768
 
764
- async function handleImageFilePicked(event: ChangeEvent<HTMLInputElement>) {
765
- const file = event.currentTarget.files?.[0];
766
- event.currentTarget.value = "";
767
- if (!file) return;
769
+ function restoreEmptyPlaceholderSelection() {
770
+ if (src || typeof getPos !== "function") return;
771
+ const position = getPos();
772
+ if (typeof position !== "number") return;
773
+ editor.chain().focus().setNodeSelection(position).run();
774
+ }
768
775
 
769
- const toastId = toast.loading(t("editor.media.uploadingImage"));
770
- try {
771
- const nextSrc = await uploadImageFile(file);
772
- updateAttributes({ src: nextSrc });
773
- setSourcePanelOpen(false);
774
- toast.success(t("editor.media.imageAdded"), { id: toastId });
775
- } catch (error) {
776
- toast.error(imageUploadErrorMessage(error), { id: toastId });
777
- }
776
+ function handleImageFileSelectionStart() {
777
+ if (isUploading) return;
778
+ if (typeof getPos !== "function") return;
779
+ const position = getPos();
780
+ if (typeof position !== "number") return;
781
+ const pickerId = String(node.attrs.uploadId || createImagePickerId());
782
+ if (!node.attrs.uploadId) updateAttributes({ uploadId: pickerId });
783
+ options.onImageFilePickerRequest?.({
784
+ pickerId,
785
+ position,
786
+ attrs: { ...node.attrs, uploadId: pickerId },
787
+ });
778
788
  }
779
789
 
780
790
  function handleEmbedLink(event: FormEvent<HTMLFormElement>) {
@@ -792,7 +802,7 @@ export function ImageBlock({
792
802
  return;
793
803
  }
794
804
 
795
- updateAttributes({ src: nextSrc, alt });
805
+ updateAttributes({ src: nextSrc, alt, uploadId: null });
796
806
  setImageUrl("");
797
807
  setSourcePanelOpen(false);
798
808
  }
@@ -811,6 +821,10 @@ export function ImageBlock({
811
821
  function handleAssetsPickerMessage(name: string, payload: unknown) {
812
822
  if (name === "close") {
813
823
  setAssetsPickerOpen(false);
824
+ if (!src) {
825
+ updateAttributes({ uploadId: null });
826
+ restoreEmptyPlaceholderSelection();
827
+ }
814
828
  return;
815
829
  }
816
830
 
@@ -824,16 +838,25 @@ export function ImageBlock({
824
838
  updateAttributes({
825
839
  src: nextSrc,
826
840
  alt: pickedAssetImageAlt(payload) ?? alt,
841
+ uploadId: null,
827
842
  });
828
843
  setAssetsPickerOpen(false);
829
844
  toast.success(t("editor.media.imageAdded"));
830
845
  }
831
846
 
847
+ function handleAssetsPickerOpenChange(open: boolean) {
848
+ setAssetsPickerOpen(open);
849
+ if (!open && !src) {
850
+ updateAttributes({ uploadId: null });
851
+ restoreEmptyPlaceholderSelection();
852
+ }
853
+ }
854
+
832
855
  function renderAssetsPickerDialog() {
833
856
  return (
834
857
  <AssetsPickerDialog
835
858
  open={assetsPickerOpen}
836
- onOpenChange={setAssetsPickerOpen}
859
+ onOpenChange={handleAssetsPickerOpenChange}
837
860
  url={assetsPickerUrl()}
838
861
  title={t("editor.media.assets")}
839
862
  embeddedTitle={t("editor.media.assetsImagePicker")}
@@ -856,6 +879,7 @@ export function ImageBlock({
856
879
  type="button"
857
880
  role="tab"
858
881
  aria-selected={sourceTab === "upload"}
882
+ disabled={isUploading}
859
883
  className="media-source-panel__tab"
860
884
  onClick={() => setSourceTab("upload")}
861
885
  >
@@ -865,6 +889,7 @@ export function ImageBlock({
865
889
  type="button"
866
890
  role="tab"
867
891
  aria-selected={sourceTab === "assets"}
892
+ disabled={isUploading}
868
893
  className="media-source-panel__tab"
869
894
  onClick={() => setSourceTab("assets")}
870
895
  >
@@ -874,6 +899,7 @@ export function ImageBlock({
874
899
  type="button"
875
900
  role="tab"
876
901
  aria-selected={sourceTab === "link"}
902
+ disabled={isUploading}
877
903
  className="media-source-panel__tab"
878
904
  onClick={() => setSourceTab("link")}
879
905
  >
@@ -887,14 +913,20 @@ export function ImageBlock({
887
913
  type="button"
888
914
  variant="outline"
889
915
  className="w-full"
890
- onClick={() => fileInputRef.current?.click()}
916
+ disabled={isUploading}
917
+ onClick={handleImageFileSelectionStart}
891
918
  >
892
919
  {t("editor.media.uploadFile")}
893
920
  </Button>
894
921
  </div>
895
922
  ) : sourceTab === "assets" ? (
896
923
  <div className="media-source-panel__body">
897
- <Button type="button" className="w-full" onClick={openAssetsPicker}>
924
+ <Button
925
+ type="button"
926
+ className="w-full"
927
+ disabled={isUploading}
928
+ onClick={openAssetsPicker}
929
+ >
898
930
  {t("editor.media.chooseFromAssets")}
899
931
  </Button>
900
932
  </div>
@@ -907,7 +939,7 @@ export function ImageBlock({
907
939
  onChange={(event) => setImageUrl(event.target.value)}
908
940
  placeholder={t("editor.media.pasteImageLink")}
909
941
  />
910
- <Button type="submit" className="w-full">
942
+ <Button type="submit" className="w-full" disabled={isUploading}>
911
943
  {replace
912
944
  ? t("editor.media.replaceImage")
913
945
  : t("editor.media.embedImage")}
@@ -955,16 +987,6 @@ export function ImageBlock({
955
987
  </span>
956
988
  </button>
957
989
 
958
- <input
959
- ref={fileInputRef}
960
- type="file"
961
- accept="image/*"
962
- className="hidden"
963
- tabIndex={-1}
964
- aria-hidden="true"
965
- onChange={handleImageFilePicked}
966
- />
967
-
968
990
  {showSourcePanel ? renderSourcePanel() : null}
969
991
  {renderAssetsPickerDialog()}
970
992
  </div>
@@ -973,7 +995,11 @@ export function ImageBlock({
973
995
  }
974
996
 
975
997
  return (
976
- <NodeViewWrapper className="media-block-wrapper" data-drag-handle>
998
+ <NodeViewWrapper
999
+ className="media-block-wrapper"
1000
+ data-drag-handle
1001
+ data-image-upload-id={node.attrs.uploadId || undefined}
1002
+ >
977
1003
  <div
978
1004
  ref={mediaBlockRef}
979
1005
  className={`media-block ${selected ? "media-block--selected" : ""}`}
@@ -1017,16 +1043,6 @@ export function ImageBlock({
1017
1043
  />
1018
1044
  )}
1019
1045
 
1020
- <input
1021
- ref={fileInputRef}
1022
- type="file"
1023
- accept="image/*"
1024
- className="hidden"
1025
- tabIndex={-1}
1026
- aria-hidden="true"
1027
- onChange={handleImageFilePicked}
1028
- />
1029
-
1030
1046
  {isEditable && (alt.trim() || altPopoverOpen) ? (
1031
1047
  <Popover open={altPopoverOpen} onOpenChange={setAltPopoverOpen}>
1032
1048
  <Tooltip delayDuration={350}>
@@ -7,6 +7,11 @@ import { ImageBlock } from "./ImageBlock";
7
7
  export interface ContentImageOptions extends ImageOptions {
8
8
  documentId?: string;
9
9
  onImageComment?: (quotedText: string, offsetTop: number) => void;
10
+ onImageFilePickerRequest?: (request: {
11
+ pickerId: string;
12
+ position: number;
13
+ attrs: Record<string, unknown>;
14
+ }) => void;
10
15
  }
11
16
 
12
17
  function normalizedImageWidth(value: unknown): number | null {
@@ -65,6 +70,7 @@ export const ImageNode = Image.extend<ContentImageOptions>({
65
70
  ...this.parent!(),
66
71
  documentId: undefined,
67
72
  onImageComment: undefined,
73
+ onImageFilePickerRequest: undefined,
68
74
  };
69
75
  },
70
76