@agent-native/core 0.134.0 → 0.134.1

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 (57) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/core/CHANGELOG.md +6 -0
  3. package/corpus/core/docs/content/template-content-developers.mdx +1 -1
  4. package/corpus/core/package.json +1 -1
  5. package/corpus/templates/clips/changelog/2026-07-29-meeting-notes-no-longer-transcribe-the-other-side-twice-when.md +6 -0
  6. package/corpus/templates/clips/desktop/src/hooks/useMeetingTranscription.ts +37 -48
  7. package/corpus/templates/clips/desktop/src/lib/transcription-capture.ts +7 -5
  8. package/corpus/templates/clips/desktop/src/lib/transcription-engine.ts +182 -106
  9. package/corpus/templates/clips/desktop/src/overlays/live-transcript.tsx +43 -14
  10. package/corpus/templates/clips/desktop/src/overlays/recording-pill.tsx +3 -3
  11. package/corpus/templates/clips/desktop/src-tauri/src/echo_guard.rs +443 -0
  12. package/corpus/templates/clips/desktop/src-tauri/src/lib.rs +1 -0
  13. package/corpus/templates/clips/desktop/src-tauri/src/whisper_speech.rs +125 -16
  14. package/corpus/templates/content/.agents/skills/document-editing/references/databases.md +6 -4
  15. package/corpus/templates/content/actions/_database-membership-lock.ts +25 -0
  16. package/corpus/templates/content/actions/_database-row-batch.ts +6 -2
  17. package/corpus/templates/content/actions/_database-source-utils.ts +289 -129
  18. package/corpus/templates/content/actions/_database-utils.ts +12 -3
  19. package/corpus/templates/content/actions/add-content-database-source-field-property.ts +39 -21
  20. package/corpus/templates/content/actions/attach-content-database-source.ts +4 -1
  21. package/corpus/templates/content/actions/change-content-database-source-role.ts +3 -5
  22. package/corpus/templates/content/actions/duplicate-document-property.ts +59 -46
  23. package/corpus/templates/content/actions/execute-builder-source-execution.ts +77 -71
  24. package/corpus/templates/content/actions/materialize-builder-required-fields.ts +7 -0
  25. package/corpus/templates/content/actions/remove-database-items.ts +183 -0
  26. package/corpus/templates/content/actions/set-document-property.ts +57 -39
  27. package/corpus/templates/content/actions/sync-local-folder-source.ts +7 -0
  28. package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +471 -329
  29. package/corpus/templates/content/app/components/editor/database/row-access.ts +45 -0
  30. package/corpus/templates/content/app/components/editor/database/shared.tsx +141 -38
  31. package/corpus/templates/content/app/hooks/use-content-database.ts +2 -2
  32. package/corpus/templates/content/app/i18n-data.ts +130 -0
  33. package/corpus/templates/content/changelog/2026-07-30-database-rows-can-now-be-removed-without-deleting-their-page.md +6 -0
  34. package/corpus/templates/content/parity/eval-scenarios.ts +2 -2
  35. package/corpus/templates/content/parity/matrix.md +1 -1
  36. package/corpus/templates/content/parity/matrix.ts +4 -5
  37. package/corpus/templates/content/shared/api.ts +4 -0
  38. package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +26 -11
  39. package/corpus/templates/design/actions/take-design-screenshot.ts +7 -0
  40. package/corpus/templates/design/app/components/design/DesignCanvas.tsx +11 -3
  41. package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +4 -1
  42. package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +54 -17
  43. package/corpus/templates/design/app/components/design/design-canvas/local-runtime.ts +126 -0
  44. package/corpus/templates/design/app/components/templates/TemplatePreview.tsx +2 -0
  45. package/corpus/templates/design/app/pages/Index.tsx +3 -1
  46. package/corpus/templates/design/app/pages/Present.tsx +2 -1
  47. package/corpus/templates/design/changelog/2026-07-30-a-broken-inline-script-in-a-generated-screen-is-now-caught-o.md +6 -0
  48. package/corpus/templates/design/changelog/2026-07-30-design-html-is-now-validated-with-a-spec-grade-html-parser-i.md +6 -0
  49. package/corpus/templates/design/changelog/2026-07-30-designs-now-load-their-tailwind-and-alpine-runtimes-from-the.md +6 -0
  50. package/corpus/templates/design/changelog/2026-07-30-designs-with-a-broken-alpine-expression-are-now-caught-on-sa.md +6 -0
  51. package/corpus/templates/design/changelog/2026-07-30-editing-a-design-no-longer-strips-its-styling-the-canvas-kep.md +6 -0
  52. package/corpus/templates/design/package.json +4 -0
  53. package/corpus/templates/design/shared/html-integrity.ts +802 -556
  54. package/dist/notifications/routes.d.ts +3 -3
  55. package/docs/content/template-content-developers.mdx +1 -1
  56. package/package.json +1 -1
  57. package/corpus/templates/content/actions/delete-database-items.ts +0 -89
@@ -176,7 +176,7 @@ import {
176
176
  useContentDatabasePersonalView,
177
177
  useContentDatabases,
178
178
  contentDatabaseQueryKey,
179
- useDeleteDatabaseItems,
179
+ useRemoveDatabaseItems,
180
180
  useDisconnectContentDatabaseSource,
181
181
  useDuplicateDatabaseItem,
182
182
  useDuplicateDatabaseItems,
@@ -276,6 +276,12 @@ import { VisualEditor } from "../VisualEditor";
276
276
  import { DatabaseFormView } from "./FormView";
277
277
  import { DatabaseGalleryView } from "./GalleryView";
278
278
  import { DatabaseListView } from "./ListView";
279
+ import {
280
+ databaseItemCanDuplicate,
281
+ databaseItemCanRemoveFromDatabase,
282
+ databaseItemHasViewerAccess,
283
+ databaseItemIsSourceBacked,
284
+ } from "./row-access";
279
285
  import { DatabaseTimelineView } from "./TimelineView";
280
286
 
281
287
  export interface DatabaseViewProps {
@@ -736,6 +742,7 @@ export function DatabaseView({
736
742
  const { data: document } = useDocument(databaseDocumentId);
737
743
 
738
744
  if (!document?.database || document.database.id !== databaseId) return null;
745
+ const effectiveCanEdit = canEdit && document.canEdit === true;
739
746
 
740
747
  return (
741
748
  <DatabaseTable
@@ -744,7 +751,7 @@ export function DatabaseView({
744
751
  databaseId={databaseId}
745
752
  hostDocumentId={hostDocumentId}
746
753
  renderMode={renderMode}
747
- canEdit={canEdit}
754
+ canEdit={effectiveCanEdit}
748
755
  isActive={isActive ?? renderMode === "page"}
749
756
  />
750
757
  );
@@ -2851,6 +2858,7 @@ function DatabaseTable({
2851
2858
  ) : (
2852
2859
  <DatabaseTableView
2853
2860
  databaseId={databaseId}
2861
+ databaseSystemRole={data?.database.systemRole}
2854
2862
  newRowLabel={newDatabaseRowLabel}
2855
2863
  properties={tableProperties}
2856
2864
  groupableProperties={orderedProperties}
@@ -2859,6 +2867,7 @@ function DatabaseTable({
2859
2867
  sources={sources}
2860
2868
  databaseDocumentId={document.id}
2861
2869
  canEdit={effectiveCanEdit}
2870
+ canManageDatabase={effectiveCanEdit && document.canManage === true}
2862
2871
  workspaceCreationPropertyValues={workspaceCreationPropertyValues}
2863
2872
  isLoading={isDatabaseViewLoading}
2864
2873
  isCreating={isCreatingDatabaseItem}
@@ -2896,6 +2905,12 @@ function DatabaseTable({
2896
2905
  )
2897
2906
  }
2898
2907
  onClearSelection={() => setSelectedItemIds([])}
2908
+ onRemoveSelection={(itemIds) =>
2909
+ setSelectedItemIds((current) => {
2910
+ const removedIds = new Set(itemIds);
2911
+ return current.filter((itemId) => !removedIds.has(itemId));
2912
+ })
2913
+ }
2899
2914
  onCreateRow={createInlineRow}
2900
2915
  onCreateGroupedRow={createInlineGroupedRow}
2901
2916
  onTitleFocusHandled={() => setInlineTitleFocusDocumentId(null)}
@@ -3420,6 +3435,41 @@ export function databaseSelectedItems(
3420
3435
  return visibleItems.filter((item) => selectedIds.has(item.id));
3421
3436
  }
3422
3437
 
3438
+ export function databaseSelectionCapabilities(args: {
3439
+ canEdit: boolean;
3440
+ canManageDatabase: boolean;
3441
+ databaseSystemRole: string | null | undefined;
3442
+ selectedItemIds: string[];
3443
+ selectedItems: ContentDatabaseItem[];
3444
+ sources: ContentDatabaseSource[];
3445
+ removesFavoriteMembership: boolean;
3446
+ isWorkspaceCatalog: boolean;
3447
+ }) {
3448
+ const selectionComplete =
3449
+ args.selectedItems.length === args.selectedItemIds.length;
3450
+ const canEditSelected = args.canEdit && selectionComplete;
3451
+ return {
3452
+ selectionComplete,
3453
+ canEditSelected,
3454
+ canDuplicateSelected:
3455
+ canEditSelected &&
3456
+ args.selectedItems.every((item) =>
3457
+ databaseItemCanDuplicate(item, args.isWorkspaceCatalog),
3458
+ ),
3459
+ canRemoveSelected: args.removesFavoriteMembership
3460
+ ? canEditSelected
3461
+ : selectionComplete &&
3462
+ args.canManageDatabase &&
3463
+ args.databaseSystemRole === null &&
3464
+ !args.isWorkspaceCatalog &&
3465
+ args.selectedItems.every(
3466
+ (item) =>
3467
+ databaseItemHasViewerAccess(item) &&
3468
+ !databaseItemIsSourceBacked(item, args.sources),
3469
+ ),
3470
+ };
3471
+ }
3472
+
3423
3473
  export function databaseBulkEditableProperties(properties: DocumentProperty[]) {
3424
3474
  return properties.filter(
3425
3475
  (property) =>
@@ -5209,6 +5259,7 @@ function DatabaseItemPreview({
5209
5259
 
5210
5260
  function DatabaseTableView({
5211
5261
  databaseId,
5262
+ databaseSystemRole,
5212
5263
  newRowLabel,
5213
5264
  properties,
5214
5265
  groupableProperties,
@@ -5217,6 +5268,7 @@ function DatabaseTableView({
5217
5268
  sources,
5218
5269
  databaseDocumentId,
5219
5270
  canEdit,
5271
+ canManageDatabase,
5220
5272
  workspaceCreationPropertyValues,
5221
5273
  isLoading,
5222
5274
  isCreating,
@@ -5245,6 +5297,7 @@ function DatabaseTableView({
5245
5297
  onToggleRowSelection,
5246
5298
  onToggleAllRowsSelection,
5247
5299
  onClearSelection,
5300
+ onRemoveSelection,
5248
5301
  onClearResultConstraints,
5249
5302
  onCreateRow,
5250
5303
  onCreateGroupedRow,
@@ -5256,6 +5309,7 @@ function DatabaseTableView({
5256
5309
  onOpenPage,
5257
5310
  }: {
5258
5311
  databaseId: string;
5312
+ databaseSystemRole: string | null | undefined;
5259
5313
  newRowLabel: string;
5260
5314
  properties: DocumentProperty[];
5261
5315
  groupableProperties: DocumentProperty[];
@@ -5264,6 +5318,7 @@ function DatabaseTableView({
5264
5318
  sources: ContentDatabaseSource[];
5265
5319
  databaseDocumentId: string;
5266
5320
  canEdit: boolean;
5321
+ canManageDatabase: boolean;
5267
5322
  workspaceCreationPropertyValues?: Record<string, DocumentPropertyValue>;
5268
5323
  isLoading: boolean;
5269
5324
  isCreating: boolean;
@@ -5303,6 +5358,7 @@ function DatabaseTableView({
5303
5358
  onToggleRowSelection: (itemId: string) => void;
5304
5359
  onToggleAllRowsSelection: () => void;
5305
5360
  onClearSelection: () => void;
5361
+ onRemoveSelection: (itemIds: string[]) => void;
5306
5362
  onClearResultConstraints: () => void;
5307
5363
  onCreateRow: CreateDatabaseRowHandler;
5308
5364
  onCreateGroupedRow: (
@@ -5325,7 +5381,7 @@ function DatabaseTableView({
5325
5381
  databaseId,
5326
5382
  databaseDocumentId,
5327
5383
  );
5328
- const deleteItems = useDeleteDatabaseItems(databaseDocumentId);
5384
+ const removeItems = useRemoveDatabaseItems(databaseDocumentId);
5329
5385
  const [draggedItemId, setDraggedItemId] = useState<string | null>(null);
5330
5386
  const [dropTargetItemId, setDropTargetItemId] = useState<string | null>(null);
5331
5387
  const [draggedPropertyId, setDraggedPropertyId] = useState<string | null>(
@@ -5335,17 +5391,45 @@ function DatabaseTableView({
5335
5391
  useState<DatabaseDropTargetState | null>(null);
5336
5392
  const [dragPreview, setDragPreview] =
5337
5393
  useState<DatabaseDragPreviewState | null>(null);
5338
- const [confirmDeleteSelectedOpen, setConfirmDeleteSelectedOpen] =
5394
+ const [confirmRemoveSelectedOpen, setConfirmRemoveSelectedOpen] =
5339
5395
  useState(false);
5396
+ const [removeSelectedSnapshotIds, setRemoveSelectedSnapshotIds] = useState<
5397
+ string[]
5398
+ >([]);
5340
5399
  const [isDuplicatingSelected, setIsDuplicatingSelected] = useState(false);
5341
5400
  const selectedCount = selectedItemIds.length;
5342
5401
  const selectableCount = items.length;
5343
5402
  const selectedIdSet = new Set(selectedItemIds);
5344
5403
  const selectedItems = databaseSelectedItems(items, selectedItemIds);
5404
+ const removeSelectedSnapshot = databaseSelectedItems(
5405
+ items,
5406
+ removeSelectedSnapshotIds,
5407
+ );
5345
5408
  const removesFavoriteMembership =
5346
5409
  contentSpaces.data?.favoritesDocumentId === databaseDocumentId;
5347
5410
  const isWorkspaceCatalog =
5348
5411
  contentSpaces.data?.catalogDocumentId === databaseDocumentId;
5412
+ const { canEditSelected, canDuplicateSelected, canRemoveSelected } =
5413
+ databaseSelectionCapabilities({
5414
+ canEdit,
5415
+ canManageDatabase,
5416
+ databaseSystemRole,
5417
+ selectedItemIds,
5418
+ selectedItems,
5419
+ sources,
5420
+ removesFavoriteMembership,
5421
+ isWorkspaceCatalog,
5422
+ });
5423
+ const canConfirmRemoveSelected = databaseSelectionCapabilities({
5424
+ canEdit,
5425
+ canManageDatabase,
5426
+ databaseSystemRole,
5427
+ selectedItemIds: removeSelectedSnapshotIds,
5428
+ selectedItems: removeSelectedSnapshot,
5429
+ sources,
5430
+ removesFavoriteMembership,
5431
+ isWorkspaceCatalog,
5432
+ }).canRemoveSelected;
5349
5433
  const bulkEditableProperties = databaseBulkEditableProperties(properties);
5350
5434
  const groups = databaseVisibleGroups(
5351
5435
  databaseViewItemGroups(items, groupableProperties, groupByPropertyId),
@@ -5570,17 +5654,17 @@ function DatabaseTableView({
5570
5654
  }
5571
5655
  }
5572
5656
 
5573
- async function deleteSelectedRows() {
5574
- if (selectedItems.length === 0) return;
5575
- const selectedSnapshot = selectedItems;
5576
- setConfirmDeleteSelectedOpen(false);
5657
+ async function removeSelectedRows(selectedSnapshot: ContentDatabaseItem[]) {
5658
+ if (selectedSnapshot.length === 0) return;
5659
+ setConfirmRemoveSelectedOpen(false);
5660
+ setRemoveSelectedSnapshotIds([]);
5577
5661
 
5578
5662
  try {
5579
- await deleteItems.mutateAsync({
5663
+ await removeItems.mutateAsync({
5580
5664
  documentId: databaseDocumentId,
5581
5665
  itemIds: selectedSnapshot.map((item) => item.id),
5582
5666
  });
5583
- onClearSelection();
5667
+ onRemoveSelection(selectedSnapshot.map((item) => item.id));
5584
5668
  onDeletedPreviewItems(selectedSnapshot);
5585
5669
  await queryClient.invalidateQueries({
5586
5670
  queryKey: [
@@ -5593,7 +5677,7 @@ function DatabaseTableView({
5593
5677
  queryKey: ["action", "list-documents"],
5594
5678
  });
5595
5679
  } catch (err) {
5596
- toast.error(dbText("failedToDeleteSelectedRows"), {
5680
+ toast.error(dbText("failedToRemoveEverySelectedRowFromDatabase"), {
5597
5681
  description:
5598
5682
  err instanceof Error ? err.message : dbText("somethingWentWrong"),
5599
5683
  });
@@ -5601,7 +5685,12 @@ function DatabaseTableView({
5601
5685
  }
5602
5686
 
5603
5687
  async function duplicateSelectedRows() {
5604
- if (selectedItems.length === 0 || isDuplicatingSelected) return;
5688
+ if (
5689
+ !canDuplicateSelected ||
5690
+ selectedItems.length === 0 ||
5691
+ isDuplicatingSelected
5692
+ )
5693
+ return;
5605
5694
  const selectedSnapshot = selectedItems;
5606
5695
  setIsDuplicatingSelected(true);
5607
5696
 
@@ -5640,7 +5729,7 @@ function DatabaseTableView({
5640
5729
  property: DocumentProperty,
5641
5730
  operation: DatabaseBulkPropertyValueOperation,
5642
5731
  ) {
5643
- if (selectedItems.length === 0) return;
5732
+ if (!canEditSelected || selectedItems.length === 0) return;
5644
5733
  const selectedSnapshot = selectedItems;
5645
5734
 
5646
5735
  let updatedCount = 0;
@@ -5677,275 +5766,289 @@ function DatabaseTableView({
5677
5766
  }
5678
5767
 
5679
5768
  return (
5680
- <div
5681
- data-database-scroll-surface="table"
5682
- className="relative w-full min-w-0 max-w-full overflow-x-auto overscroll-x-contain"
5683
- >
5769
+ <div className="relative w-full min-w-0 max-w-full">
5684
5770
  <DatabaseDragPreview preview={dragPreview} />
5685
- <div className="w-max min-w-full min-w-[720px]">
5686
- {selectedCount > 0 ? (
5687
- <DatabaseSelectionBar
5688
- selectedCount={selectedCount}
5689
- canEdit={canEdit}
5690
- properties={bulkEditableProperties}
5691
- selectedItems={selectedItems}
5692
- duplicateDisabled={
5693
- isDuplicatingSelected ||
5694
- duplicateItems.isPending ||
5695
- deleteItems.isPending
5771
+ {selectedCount > 0 ? (
5772
+ <DatabaseSelectionBar
5773
+ selectedCount={selectedCount}
5774
+ canEditSelected={canEditSelected}
5775
+ canDuplicateSelected={canDuplicateSelected}
5776
+ canRemoveSelected={canRemoveSelected}
5777
+ properties={bulkEditableProperties}
5778
+ selectedItems={selectedItems}
5779
+ duplicateDisabled={
5780
+ isDuplicatingSelected ||
5781
+ duplicateItems.isPending ||
5782
+ removeItems.isPending
5783
+ }
5784
+ removeDisabled={removeItems.isPending}
5785
+ removesFavoriteMembership={removesFavoriteMembership}
5786
+ updateDisabled={setProperty.isPending}
5787
+ onClearSelection={onClearSelection}
5788
+ onSetPropertyValue={setSelectedPropertyValue}
5789
+ onDuplicateSelected={() => void duplicateSelectedRows()}
5790
+ onRemoveSelected={() => {
5791
+ if (removesFavoriteMembership) {
5792
+ void removeSelectedRows(selectedItems);
5793
+ return;
5696
5794
  }
5697
- deleteDisabled={deleteItems.isPending}
5698
- removesFavoriteMembership={removesFavoriteMembership}
5699
- updateDisabled={setProperty.isPending}
5700
- onClearSelection={onClearSelection}
5701
- onSetPropertyValue={setSelectedPropertyValue}
5702
- onDuplicateSelected={() => void duplicateSelectedRows()}
5703
- onDeleteSelected={() => {
5704
- if (removesFavoriteMembership) {
5705
- void deleteSelectedRows();
5706
- return;
5707
- }
5708
- setConfirmDeleteSelectedOpen(true);
5709
- }}
5710
- />
5711
- ) : null}
5712
- <div
5713
- className="grid border-y border-border/35 text-xs font-medium text-muted-foreground/80"
5714
- style={{
5715
- gridTemplateColumns: databaseGridColumns(
5716
- properties,
5717
- canEdit,
5718
- columnWidths,
5719
- actionColumnWidth,
5720
- ),
5795
+ setRemoveSelectedSnapshotIds(selectedItems.map((item) => item.id));
5796
+ setConfirmRemoveSelectedOpen(true);
5721
5797
  }}
5722
- >
5723
- <DatabaseNameHeader
5724
- sorts={sorts}
5725
- filters={filters}
5726
- source={source}
5727
- selectedCount={selectedCount}
5728
- selectableCount={selectableCount}
5729
- onSortsChange={onSortsChange}
5730
- onFiltersChange={onFiltersChange}
5731
- onToggleAllRowsSelection={onToggleAllRowsSelection}
5732
- onResize={(event) =>
5733
- onResizeColumn("name", DEFAULT_NAME_COLUMN_WIDTH, event)
5734
- }
5735
- />
5736
- {properties.map((property) => {
5737
- return (
5738
- <DatabasePropertyHeader
5739
- key={property.definition.id}
5740
- property={property}
5741
- documentId={databaseDocumentId}
5742
- source={source}
5743
- canEdit={canEdit}
5744
- isDragging={draggedPropertyId === property.definition.id}
5745
- dropSide={
5746
- !!draggedPropertyId &&
5747
- dropTargetProperty?.id === property.definition.id &&
5748
- draggedPropertyId !== property.definition.id
5749
- ? dropTargetProperty.side
5750
- : null
5751
- }
5752
- sorts={sorts}
5753
- filters={filters}
5754
- onSortsChange={onSortsChange}
5755
- onFiltersChange={onFiltersChange}
5756
- onPropertyHiddenChange={onPropertyHiddenChange}
5757
- onPointerDown={(event) =>
5758
- startPropertyPointerDrag(property, event)
5759
- }
5760
- onResize={(event) =>
5761
- onResizeColumn(
5762
- property.definition.id,
5763
- DEFAULT_PROPERTY_COLUMN_WIDTH,
5764
- event,
5765
- )
5766
- }
5767
- />
5768
- );
5769
- })}
5770
- {canEdit ? (
5771
- <div
5772
- className={cn(
5773
- "flex h-8 items-center",
5774
- cleanDefaultTable
5775
- ? "justify-start border-r border-border/30 px-1"
5776
- : "justify-center",
5777
- )}
5778
- >
5779
- <AddProperty
5780
- documentId={databaseDocumentId}
5781
- databaseId={databaseId}
5782
- variant={cleanDefaultTable ? "header" : "icon"}
5783
- label={dbText("addProperty")}
5784
- source={source}
5785
- sources={sources}
5786
- />
5787
- </div>
5788
- ) : null}
5789
- </div>
5790
-
5791
- {databaseTableShouldShowBlockingLoader(isLoading, items.length) ? (
5792
- <div className="flex h-16 items-center gap-2 border-t border-border px-2 text-sm text-muted-foreground">
5793
- <Spinner className="size-4" />
5794
- {dbText("loadingDatabase")}
5795
- </div>
5796
- ) : (
5797
- <>
5798
- {databaseViewHasNoMatchingPages(
5799
- items.length,
5800
- hasSearch,
5801
- activeFilters.length,
5802
- ) ? (
5803
- <DatabaseNoMatchingPages
5804
- className="border-t border-border"
5805
- label={dbText("noRowsMatchThisView")}
5806
- onClear={onClearResultConstraints}
5807
- />
5798
+ />
5799
+ ) : null}
5800
+ <div
5801
+ data-database-scroll-surface="table"
5802
+ tabIndex={0}
5803
+ className="w-full min-w-0 max-w-full overflow-x-auto overscroll-x-contain"
5804
+ >
5805
+ <div className="w-max min-w-full min-w-[720px]">
5806
+ <div
5807
+ className="grid border-y border-border/35 text-xs font-medium text-muted-foreground/80"
5808
+ style={{
5809
+ gridTemplateColumns: databaseGridColumns(
5810
+ properties,
5811
+ canEdit,
5812
+ columnWidths,
5813
+ actionColumnWidth,
5814
+ ),
5815
+ }}
5816
+ >
5817
+ <DatabaseNameHeader
5818
+ sorts={sorts}
5819
+ filters={filters}
5820
+ source={source}
5821
+ selectedCount={selectedCount}
5822
+ selectableCount={selectableCount}
5823
+ onSortsChange={onSortsChange}
5824
+ onFiltersChange={onFiltersChange}
5825
+ onToggleAllRowsSelection={onToggleAllRowsSelection}
5826
+ onResize={(event) =>
5827
+ onResizeColumn("name", DEFAULT_NAME_COLUMN_WIDTH, event)
5828
+ }
5829
+ />
5830
+ {properties.map((property) => {
5831
+ return (
5832
+ <DatabasePropertyHeader
5833
+ key={property.definition.id}
5834
+ property={property}
5835
+ documentId={databaseDocumentId}
5836
+ source={source}
5837
+ canEdit={canEdit}
5838
+ isDragging={draggedPropertyId === property.definition.id}
5839
+ dropSide={
5840
+ !!draggedPropertyId &&
5841
+ dropTargetProperty?.id === property.definition.id &&
5842
+ draggedPropertyId !== property.definition.id
5843
+ ? dropTargetProperty.side
5844
+ : null
5845
+ }
5846
+ sorts={sorts}
5847
+ filters={filters}
5848
+ onSortsChange={onSortsChange}
5849
+ onFiltersChange={onFiltersChange}
5850
+ onPropertyHiddenChange={onPropertyHiddenChange}
5851
+ onPointerDown={(event) =>
5852
+ startPropertyPointerDrag(property, event)
5853
+ }
5854
+ onResize={(event) =>
5855
+ onResizeColumn(
5856
+ property.definition.id,
5857
+ DEFAULT_PROPERTY_COLUMN_WIDTH,
5858
+ event,
5859
+ )
5860
+ }
5861
+ />
5862
+ );
5863
+ })}
5864
+ {canEdit ? (
5865
+ <div
5866
+ className={cn(
5867
+ "flex h-8 items-center",
5868
+ cleanDefaultTable
5869
+ ? "justify-start border-r border-border/30 px-1"
5870
+ : "justify-center",
5871
+ )}
5872
+ >
5873
+ <AddProperty
5874
+ documentId={databaseDocumentId}
5875
+ databaseId={databaseId}
5876
+ variant={cleanDefaultTable ? "header" : "icon"}
5877
+ label={dbText("addProperty")}
5878
+ source={source}
5879
+ sources={sources}
5880
+ />
5881
+ </div>
5808
5882
  ) : null}
5809
- {grouped
5810
- ? groups.map((group) => (
5811
- <DatabaseGroupedTableSection
5812
- key={group.id}
5813
- group={group}
5883
+ </div>
5884
+
5885
+ {databaseTableShouldShowBlockingLoader(isLoading, items.length) ? (
5886
+ <div className="flex h-16 items-center gap-2 border-t border-border px-2 text-sm text-muted-foreground">
5887
+ <Spinner className="size-4" />
5888
+ {dbText("loadingDatabase")}
5889
+ </div>
5890
+ ) : (
5891
+ <>
5892
+ {databaseViewHasNoMatchingPages(
5893
+ items.length,
5894
+ hasSearch,
5895
+ activeFilters.length,
5896
+ ) ? (
5897
+ <DatabaseNoMatchingPages
5898
+ className="border-t border-border"
5899
+ label={dbText("noRowsMatchThisView")}
5900
+ onClear={onClearResultConstraints}
5901
+ />
5902
+ ) : null}
5903
+ {grouped
5904
+ ? groups.map((group) => (
5905
+ <DatabaseGroupedTableSection
5906
+ key={group.id}
5907
+ group={group}
5908
+ properties={properties}
5909
+ columnWidths={columnWidths}
5910
+ databaseDocumentId={databaseDocumentId}
5911
+ workspaceCatalog={isWorkspaceCatalog}
5912
+ workspaceCreationPropertyValues={
5913
+ workspaceCreationPropertyValues
5914
+ }
5915
+ canEdit={canEdit}
5916
+ selectedIdSet={selectedIdSet}
5917
+ wrapCells={wrapCells}
5918
+ rowDensity={rowDensity}
5919
+ isCreating={isCreating}
5920
+ newRowLabel={newRowLabel}
5921
+ focusedTitleDocumentId={focusedTitleDocumentId}
5922
+ collapsed={databaseGroupIsCollapsed(
5923
+ collapsedGroupIds,
5924
+ group.id,
5925
+ )}
5926
+ onCreateRow={onCreateGroupedRow}
5927
+ onTitleFocusHandled={onTitleFocusHandled}
5928
+ onCollapsedChange={(collapsed) =>
5929
+ onGroupCollapsedChange(group.id, collapsed)
5930
+ }
5931
+ onToggleCheckbox={toggleCheckboxCell}
5932
+ onToggleRowSelection={onToggleRowSelection}
5933
+ onPreview={onPreview}
5934
+ onDeletedPreviewItem={onDeletedPreviewItem}
5935
+ onOpenPage={onOpenPage}
5936
+ />
5937
+ ))
5938
+ : items.map((item, index) => (
5939
+ <DatabaseTableRow
5940
+ key={item.id}
5941
+ item={item}
5942
+ databaseDocumentId={databaseDocumentId}
5943
+ workspaceCatalog={isWorkspaceCatalog}
5944
+ properties={properties}
5945
+ columnWidths={columnWidths}
5946
+ canEdit={canEdit}
5947
+ rowIndex={index}
5948
+ canReorder={rowsAreManuallyOrdered}
5949
+ canDragRow={rowDraggingEnabled}
5950
+ canMoveUp={rowsAreManuallyOrdered && index > 0}
5951
+ canMoveDown={
5952
+ rowsAreManuallyOrdered && index < items.length - 1
5953
+ }
5954
+ selected={selectedIdSet.has(item.id)}
5955
+ isDragging={draggedItemId === item.id}
5956
+ isDropTarget={
5957
+ !!draggedItemId &&
5958
+ dropTargetItemId === item.id &&
5959
+ draggedItemId !== item.id
5960
+ }
5961
+ startEditingTitle={
5962
+ focusedTitleDocumentId === item.document.id
5963
+ }
5964
+ onDragHandlePointerDown={(event) =>
5965
+ startRowDrag(item.id, event)
5966
+ }
5967
+ onToggleCheckbox={(property) =>
5968
+ void toggleCheckboxCell(item, property)
5969
+ }
5970
+ wrapCells={wrapCells}
5971
+ rowDensity={rowDensity}
5972
+ onToggleSelected={() => onToggleRowSelection(item.id)}
5973
+ onPreviewItem={onPreview}
5974
+ onDeletedPreviewItem={onDeletedPreviewItem}
5975
+ onTitleEditStarted={onTitleFocusHandled}
5976
+ onPreview={() => onPreview(item)}
5977
+ onOpenPage={() => onOpenPage(item)}
5978
+ />
5979
+ ))}
5980
+ {canEdit && !grouped ? (
5981
+ isWorkspaceCatalog ? (
5982
+ <WorkspaceSourceMenuRow
5983
+ label={newRowLabel}
5814
5984
  properties={properties}
5815
5985
  columnWidths={columnWidths}
5816
- databaseDocumentId={databaseDocumentId}
5817
- workspaceCatalog={isWorkspaceCatalog}
5818
- workspaceCreationPropertyValues={
5819
- workspaceCreationPropertyValues
5820
- }
5821
- canEdit={canEdit}
5822
- selectedIdSet={selectedIdSet}
5823
- wrapCells={wrapCells}
5824
5986
  rowDensity={rowDensity}
5825
- isCreating={isCreating}
5826
- newRowLabel={newRowLabel}
5827
- focusedTitleDocumentId={focusedTitleDocumentId}
5828
- collapsed={databaseGroupIsCollapsed(
5829
- collapsedGroupIds,
5830
- group.id,
5831
- )}
5832
- onCreateRow={onCreateGroupedRow}
5833
- onTitleFocusHandled={onTitleFocusHandled}
5834
- onCollapsedChange={(collapsed) =>
5835
- onGroupCollapsedChange(group.id, collapsed)
5836
- }
5837
- onToggleCheckbox={toggleCheckboxCell}
5838
- onToggleRowSelection={onToggleRowSelection}
5839
- onPreview={onPreview}
5840
- onDeletedPreviewItem={onDeletedPreviewItem}
5841
- onOpenPage={onOpenPage}
5987
+ propertyValues={workspaceCreationPropertyValues}
5988
+ actionColumnWidth={actionColumnWidth}
5842
5989
  />
5843
- ))
5844
- : items.map((item, index) => (
5845
- <DatabaseTableRow
5846
- key={item.id}
5847
- item={item}
5848
- databaseDocumentId={databaseDocumentId}
5849
- workspaceCatalog={isWorkspaceCatalog}
5990
+ ) : (
5991
+ <NewDatabaseRow
5992
+ label={newRowLabel}
5850
5993
  properties={properties}
5851
5994
  columnWidths={columnWidths}
5852
- canEdit={canEdit}
5853
- rowIndex={index}
5854
- canReorder={rowsAreManuallyOrdered}
5855
- canDragRow={rowDraggingEnabled}
5856
- canMoveUp={rowsAreManuallyOrdered && index > 0}
5857
- canMoveDown={
5858
- rowsAreManuallyOrdered && index < items.length - 1
5859
- }
5860
- selected={selectedIdSet.has(item.id)}
5861
- isDragging={draggedItemId === item.id}
5862
- isDropTarget={
5863
- !!draggedItemId &&
5864
- dropTargetItemId === item.id &&
5865
- draggedItemId !== item.id
5866
- }
5867
- startEditingTitle={
5868
- focusedTitleDocumentId === item.document.id
5869
- }
5870
- onDragHandlePointerDown={(event) =>
5871
- startRowDrag(item.id, event)
5872
- }
5873
- onToggleCheckbox={(property) =>
5874
- void toggleCheckboxCell(item, property)
5875
- }
5876
- wrapCells={wrapCells}
5877
5995
  rowDensity={rowDensity}
5878
- onToggleSelected={() => onToggleRowSelection(item.id)}
5879
- onPreviewItem={onPreview}
5880
- onDeletedPreviewItem={onDeletedPreviewItem}
5881
- onTitleEditStarted={onTitleFocusHandled}
5882
- onPreview={() => onPreview(item)}
5883
- onOpenPage={() => onOpenPage(item)}
5996
+ disabled={isCreating}
5997
+ isPending={isCreating}
5998
+ onCreate={onCreateRow}
5999
+ actionColumnWidth={actionColumnWidth}
5884
6000
  />
5885
- ))}
5886
- {canEdit && !grouped ? (
5887
- isWorkspaceCatalog ? (
5888
- <WorkspaceSourceMenuRow
5889
- label={newRowLabel}
5890
- properties={properties}
5891
- columnWidths={columnWidths}
5892
- rowDensity={rowDensity}
5893
- propertyValues={workspaceCreationPropertyValues}
5894
- actionColumnWidth={actionColumnWidth}
5895
- />
5896
- ) : (
5897
- <NewDatabaseRow
5898
- label={newRowLabel}
5899
- properties={properties}
5900
- columnWidths={columnWidths}
5901
- rowDensity={rowDensity}
5902
- disabled={isCreating}
5903
- isPending={isCreating}
5904
- onCreate={onCreateRow}
6001
+ )
6002
+ ) : null}
6003
+ {cleanDefaultTable ? (
6004
+ <DatabaseBlankDefaultRows
6005
+ rowCount={EMPTY_DEFAULT_BLANK_ROW_COUNT}
5905
6006
  actionColumnWidth={actionColumnWidth}
5906
6007
  />
5907
- )
5908
- ) : null}
5909
- {cleanDefaultTable ? (
5910
- <DatabaseBlankDefaultRows
5911
- rowCount={EMPTY_DEFAULT_BLANK_ROW_COUNT}
6008
+ ) : null}
6009
+ <DatabaseTableFooter
6010
+ properties={properties}
6011
+ items={items}
6012
+ totalCount={totalCount}
6013
+ constrained={constrained}
6014
+ columnWidths={columnWidths}
6015
+ canEdit={canEdit}
6016
+ calculations={calculations}
5912
6017
  actionColumnWidth={actionColumnWidth}
6018
+ onCalculationChange={onCalculationChange}
5913
6019
  />
5914
- ) : null}
5915
- <DatabaseTableFooter
5916
- properties={properties}
5917
- items={items}
5918
- totalCount={totalCount}
5919
- constrained={constrained}
5920
- columnWidths={columnWidths}
5921
- canEdit={canEdit}
5922
- calculations={calculations}
5923
- actionColumnWidth={actionColumnWidth}
5924
- onCalculationChange={onCalculationChange}
5925
- />
5926
- </>
5927
- )}
6020
+ </>
6021
+ )}
6022
+ </div>
5928
6023
  </div>
5929
6024
  <AlertDialog
5930
- open={!removesFavoriteMembership && confirmDeleteSelectedOpen}
5931
- onOpenChange={setConfirmDeleteSelectedOpen}
6025
+ open={
6026
+ !removesFavoriteMembership &&
6027
+ canConfirmRemoveSelected &&
6028
+ confirmRemoveSelectedOpen
6029
+ }
6030
+ onOpenChange={(open) => {
6031
+ setConfirmRemoveSelectedOpen(open);
6032
+ if (!open) setRemoveSelectedSnapshotIds([]);
6033
+ }}
5932
6034
  >
5933
6035
  <AlertDialogContent>
5934
6036
  <AlertDialogHeader>
5935
- <AlertDialogTitle>{dbText("deleteSelectedRows")}</AlertDialogTitle>
6037
+ <AlertDialogTitle>
6038
+ {dbText("removeSelectedRowsFromDatabaseQuestion")}
6039
+ </AlertDialogTitle>
5936
6040
  <AlertDialogDescription>
5937
- {selectedCount} selected row{selectedCount === 1 ? "" : "s"} and
5938
- any sub-pages will be permanently deleted. This cannot be undone.
6041
+ {dbText("removeSelectedRowsFromDatabaseDescription")}
5939
6042
  </AlertDialogDescription>
5940
6043
  </AlertDialogHeader>
5941
6044
  <AlertDialogFooter>
5942
- <AlertDialogCancel>Cancel</AlertDialogCancel>
6045
+ <AlertDialogCancel>{dbText("cancel")}</AlertDialogCancel>
5943
6046
  <AlertDialogAction
5944
6047
  className="bg-destructive text-destructive-foreground hover:bg-destructive/90"
5945
- disabled={deleteItems.isPending}
5946
- onClick={() => void deleteSelectedRows()}
6048
+ disabled={removeItems.isPending || !canConfirmRemoveSelected}
6049
+ onClick={() => void removeSelectedRows(removeSelectedSnapshot)}
5947
6050
  >
5948
- {deleteItems.isPending ? "Deleting..." : "Delete"}
6051
+ {removeItems.isPending ? dbText("removing") : dbText("remove")}
5949
6052
  </AlertDialogAction>
5950
6053
  </AlertDialogFooter>
5951
6054
  </AlertDialogContent>
@@ -15355,26 +15458,30 @@ function DatabaseNameHeader({
15355
15458
  );
15356
15459
  }
15357
15460
 
15358
- function DatabaseSelectionBar({
15461
+ export function DatabaseSelectionBar({
15359
15462
  selectedCount,
15360
- canEdit,
15463
+ canEditSelected,
15464
+ canDuplicateSelected,
15465
+ canRemoveSelected,
15361
15466
  properties,
15362
15467
  selectedItems,
15363
15468
  duplicateDisabled,
15364
- deleteDisabled,
15469
+ removeDisabled,
15365
15470
  removesFavoriteMembership,
15366
15471
  updateDisabled,
15367
15472
  onClearSelection,
15368
15473
  onSetPropertyValue,
15369
15474
  onDuplicateSelected,
15370
- onDeleteSelected,
15475
+ onRemoveSelected,
15371
15476
  }: {
15372
15477
  selectedCount: number;
15373
- canEdit: boolean;
15478
+ canEditSelected: boolean;
15479
+ canDuplicateSelected: boolean;
15480
+ canRemoveSelected: boolean;
15374
15481
  properties: DocumentProperty[];
15375
15482
  selectedItems: ContentDatabaseItem[];
15376
15483
  duplicateDisabled: boolean;
15377
- deleteDisabled: boolean;
15484
+ removeDisabled: boolean;
15378
15485
  removesFavoriteMembership: boolean;
15379
15486
  updateDisabled: boolean;
15380
15487
  onClearSelection: () => void;
@@ -15383,7 +15490,7 @@ function DatabaseSelectionBar({
15383
15490
  operation: DatabaseBulkPropertyValueOperation,
15384
15491
  ) => Promise<void>;
15385
15492
  onDuplicateSelected: () => void;
15386
- onDeleteSelected: () => void;
15493
+ onRemoveSelected: () => void;
15387
15494
  }) {
15388
15495
  return (
15389
15496
  <div className="flex h-8 items-center justify-between gap-2 border-y border-border/45 bg-muted/20 px-2 text-xs text-muted-foreground">
@@ -15391,46 +15498,48 @@ function DatabaseSelectionBar({
15391
15498
  {selectedCount} selected
15392
15499
  </span>
15393
15500
  <div className="flex items-center gap-1">
15394
- {canEdit ? (
15395
- <>
15396
- <DatabaseBulkEditPopover
15397
- properties={properties}
15398
- selectedCount={selectedCount}
15399
- selectedItems={selectedItems}
15400
- disabled={updateDisabled || properties.length === 0}
15401
- onSetPropertyValue={onSetPropertyValue}
15402
- />
15403
- <Button
15404
- type="button"
15405
- variant="ghost"
15406
- size="sm"
15407
- className="h-7 gap-1.5 px-2 text-xs"
15408
- disabled={duplicateDisabled}
15409
- onClick={onDuplicateSelected}
15410
- >
15411
- <IconCopy className="size-3.5" />
15412
- Duplicate
15413
- </Button>
15414
- <Button
15415
- type="button"
15416
- variant="ghost"
15417
- size="sm"
15418
- className={cn(
15419
- "h-7 gap-1.5 px-2 text-xs",
15420
- !removesFavoriteMembership &&
15421
- "text-destructive hover:bg-destructive/10 hover:text-destructive",
15422
- )}
15423
- disabled={deleteDisabled}
15424
- onClick={onDeleteSelected}
15425
- >
15426
- {removesFavoriteMembership ? (
15427
- <IconStarOff className="size-3.5" />
15428
- ) : (
15429
- <IconTrash className="size-3.5" />
15430
- )}
15431
- {removesFavoriteMembership ? "Remove" : "Delete"}
15432
- </Button>
15433
- </>
15501
+ {canEditSelected ? (
15502
+ <DatabaseBulkEditPopover
15503
+ properties={properties}
15504
+ selectedCount={selectedCount}
15505
+ selectedItems={selectedItems}
15506
+ disabled={updateDisabled || properties.length === 0}
15507
+ onSetPropertyValue={onSetPropertyValue}
15508
+ />
15509
+ ) : null}
15510
+ {canDuplicateSelected ? (
15511
+ <Button
15512
+ type="button"
15513
+ variant="ghost"
15514
+ size="sm"
15515
+ className="h-7 gap-1.5 px-2 text-xs"
15516
+ disabled={duplicateDisabled}
15517
+ onClick={onDuplicateSelected}
15518
+ >
15519
+ <IconCopy className="size-3.5" />
15520
+ Duplicate
15521
+ </Button>
15522
+ ) : null}
15523
+ {canRemoveSelected ? (
15524
+ <Button
15525
+ type="button"
15526
+ variant="ghost"
15527
+ size="sm"
15528
+ className={cn(
15529
+ "h-7 gap-1.5 px-2 text-xs",
15530
+ !removesFavoriteMembership &&
15531
+ "text-destructive hover:bg-destructive/10 hover:text-destructive",
15532
+ )}
15533
+ disabled={removeDisabled}
15534
+ onClick={onRemoveSelected}
15535
+ >
15536
+ {removesFavoriteMembership ? (
15537
+ <IconStarOff className="size-3.5" />
15538
+ ) : (
15539
+ <IconTrash className="size-3.5" />
15540
+ )}
15541
+ Remove
15542
+ </Button>
15434
15543
  ) : null}
15435
15544
  <Button
15436
15545
  type="button"
@@ -18536,9 +18645,11 @@ export function RowActionsCell({
18536
18645
  }) {
18537
18646
  const queryClient = useQueryClient();
18538
18647
  const contentSpaces = useContentSpaces();
18539
- const deleteDocument = useDeleteDocument();
18648
+ const { data: databaseDocument } = useDocument(databaseDocumentId);
18649
+ const databaseQuery = useContentDatabase(databaseDocumentId);
18540
18650
  const deleteContentSpace = useDeleteContentSpace();
18541
18651
  const duplicateItem = useDuplicateDatabaseItem(databaseDocumentId);
18652
+ const removeItems = useRemoveDatabaseItems(databaseDocumentId);
18542
18653
  const [menuOpen, setMenuOpen] = useState(false);
18543
18654
  const [confirmDeleteOpen, setConfirmDeleteOpen] = useState(false);
18544
18655
  const title = item.document.title || "Untitled";
@@ -18551,8 +18662,27 @@ export function RowActionsCell({
18551
18662
  contentSpaces.data?.catalogDocumentId === databaseDocumentId;
18552
18663
  const canDeleteWorkspace =
18553
18664
  isWorkspaceCatalog && workspaceSpace?.kind === "user";
18665
+ const databaseData = isContentDatabaseUnavailable(databaseQuery.data)
18666
+ ? undefined
18667
+ : databaseQuery.data;
18668
+ const databaseSources = databaseAttachedSources(
18669
+ databaseData?.sources,
18670
+ databaseData?.source ?? null,
18671
+ );
18672
+ const canRemoveFromDatabase = removesFavoriteMembership
18673
+ ? databaseDocument?.canEdit === true
18674
+ : databaseData !== undefined &&
18675
+ databaseItemCanRemoveFromDatabase({
18676
+ item,
18677
+ databaseCanManage: databaseDocument?.canManage === true,
18678
+ databaseSystemRole: databaseData.database.systemRole,
18679
+ isWorkspaceCatalog,
18680
+ sources: databaseSources,
18681
+ });
18682
+ const canDuplicateRow = databaseItemCanDuplicate(item, isWorkspaceCatalog);
18554
18683
 
18555
18684
  async function duplicateRow() {
18685
+ if (!canDuplicateRow) return;
18556
18686
  setMenuOpen(false);
18557
18687
  try {
18558
18688
  const response = await duplicateItem.mutateAsync({ itemId: item.id });
@@ -18566,15 +18696,19 @@ export function RowActionsCell({
18566
18696
  }
18567
18697
  }
18568
18698
 
18569
- async function deleteRow() {
18699
+ async function removeRowOrDeleteWorkspace() {
18700
+ if (!canRemoveFromDatabase && !canDeleteWorkspace) {
18701
+ setConfirmDeleteOpen(false);
18702
+ return;
18703
+ }
18570
18704
  const previewMoved = onDeletedPreviewItem?.(item) ?? false;
18571
18705
  try {
18572
18706
  if (canDeleteWorkspace && workspaceSpace) {
18573
18707
  await deleteContentSpace.mutateAsync({ spaceId: workspaceSpace.id });
18574
18708
  } else {
18575
- await deleteDocument.mutateAsync({
18576
- id: item.document.id,
18577
- databaseDocumentId,
18709
+ await removeItems.mutateAsync({
18710
+ documentId: databaseDocumentId,
18711
+ documentIds: [item.document.id],
18578
18712
  });
18579
18713
  }
18580
18714
  await queryClient.invalidateQueries({
@@ -18589,10 +18723,15 @@ export function RowActionsCell({
18589
18723
  });
18590
18724
  } catch (err) {
18591
18725
  if (previewMoved) onPreviewItem?.(item);
18592
- toast.error(dbText("failedToDeleteRow"), {
18593
- description:
18594
- err instanceof Error ? err.message : dbText("somethingWentWrong"),
18595
- });
18726
+ toast.error(
18727
+ canDeleteWorkspace
18728
+ ? dbText("failedToDeleteRow")
18729
+ : dbText("failedToRemoveRowFromDatabase"),
18730
+ {
18731
+ description:
18732
+ err instanceof Error ? err.message : dbText("somethingWentWrong"),
18733
+ },
18734
+ );
18596
18735
  }
18597
18736
  }
18598
18737
 
@@ -18619,7 +18758,7 @@ export function RowActionsCell({
18619
18758
  <IconExternalLink className="mr-2 size-4 text-muted-foreground" />
18620
18759
  {dbText("openPage")}
18621
18760
  </DropdownMenuItem>
18622
- {!isWorkspaceCatalog ? (
18761
+ {canDuplicateRow ? (
18623
18762
  <DropdownMenuItem
18624
18763
  disabled={duplicateItem.isPending}
18625
18764
  onSelect={(event) => {
@@ -18631,21 +18770,21 @@ export function RowActionsCell({
18631
18770
  {dbText("duplicateRow")}
18632
18771
  </DropdownMenuItem>
18633
18772
  ) : null}
18634
- {!isWorkspaceCatalog || canDeleteWorkspace ? (
18773
+ {canRemoveFromDatabase || canDeleteWorkspace ? (
18635
18774
  <DropdownMenuSeparator />
18636
18775
  ) : null}
18637
- {removesFavoriteMembership ? (
18776
+ {removesFavoriteMembership && canRemoveFromDatabase ? (
18638
18777
  <DropdownMenuItem
18639
18778
  onSelect={(event) => {
18640
18779
  event.preventDefault();
18641
18780
  setMenuOpen(false);
18642
- void deleteRow();
18781
+ void removeRowOrDeleteWorkspace();
18643
18782
  }}
18644
18783
  >
18645
18784
  <IconStarOff className="mr-2 size-4 text-muted-foreground" />
18646
18785
  {sidebarText("removeFromFavorites")}
18647
18786
  </DropdownMenuItem>
18648
- ) : !isWorkspaceCatalog || canDeleteWorkspace ? (
18787
+ ) : canRemoveFromDatabase || canDeleteWorkspace ? (
18649
18788
  <DropdownMenuItem
18650
18789
  className="text-destructive focus:bg-destructive/10 focus:text-destructive"
18651
18790
  onSelect={(event) => {
@@ -18655,7 +18794,9 @@ export function RowActionsCell({
18655
18794
  }}
18656
18795
  >
18657
18796
  <IconTrash className="mr-2 size-4" />
18658
- {canDeleteWorkspace ? "Delete workspace" : dbText("deleteRow")}
18797
+ {canDeleteWorkspace
18798
+ ? "Delete workspace"
18799
+ : dbText("removeFromDatabase")}
18659
18800
  </DropdownMenuItem>
18660
18801
  ) : null}
18661
18802
  </DropdownMenuContent>
@@ -18664,7 +18805,7 @@ export function RowActionsCell({
18664
18805
  <AlertDialog
18665
18806
  open={
18666
18807
  !removesFavoriteMembership &&
18667
- (!isWorkspaceCatalog || canDeleteWorkspace) &&
18808
+ (canRemoveFromDatabase || canDeleteWorkspace) &&
18668
18809
  confirmDeleteOpen
18669
18810
  }
18670
18811
  onOpenChange={setConfirmDeleteOpen}
@@ -18672,7 +18813,9 @@ export function RowActionsCell({
18672
18813
  <AlertDialogContent>
18673
18814
  <AlertDialogHeader>
18674
18815
  <AlertDialogTitle>
18675
- {canDeleteWorkspace ? "Delete workspace?" : dbText("deleteRow2")}
18816
+ {canDeleteWorkspace
18817
+ ? "Delete workspace?"
18818
+ : dbText("removeFromDatabaseQuestion")}
18676
18819
  </AlertDialogTitle>
18677
18820
  <AlertDialogDescription>
18678
18821
  {canDeleteWorkspace ? (
@@ -18681,10 +18824,7 @@ export function RowActionsCell({
18681
18824
  will be permanently deleted. This cannot be undone.
18682
18825
  </>
18683
18826
  ) : (
18684
- <>
18685
- &ldquo;{title}&rdquo; and any sub-pages will be permanently
18686
- deleted. This cannot be undone.
18687
- </>
18827
+ dbText("removeFromDatabaseDescription", { title })
18688
18828
  )}
18689
18829
  </AlertDialogDescription>
18690
18830
  </AlertDialogHeader>
@@ -18692,14 +18832,16 @@ export function RowActionsCell({
18692
18832
  <AlertDialogCancel>Cancel</AlertDialogCancel>
18693
18833
  <AlertDialogAction
18694
18834
  className="bg-destructive text-destructive-foreground hover:bg-destructive/90"
18695
- disabled={
18696
- deleteDocument.isPending || deleteContentSpace.isPending
18697
- }
18698
- onClick={() => void deleteRow()}
18835
+ disabled={removeItems.isPending || deleteContentSpace.isPending}
18836
+ onClick={() => void removeRowOrDeleteWorkspace()}
18699
18837
  >
18700
- {deleteDocument.isPending || deleteContentSpace.isPending
18701
- ? "Deleting..."
18702
- : "Delete"}
18838
+ {removeItems.isPending || deleteContentSpace.isPending
18839
+ ? canDeleteWorkspace
18840
+ ? "Deleting..."
18841
+ : dbText("removing")
18842
+ : canDeleteWorkspace
18843
+ ? "Delete"
18844
+ : dbText("remove")}
18703
18845
  </AlertDialogAction>
18704
18846
  </AlertDialogFooter>
18705
18847
  </AlertDialogContent>