@agent-native/core-corpus 0.216.0 → 0.218.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 (196) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/analytics/.agents/skills/session-replay/SKILL.md +61 -1
  3. package/corpus/templates/analytics/AGENTS.md +1 -1
  4. package/corpus/templates/analytics/CHANGELOG.md +3 -0
  5. package/corpus/templates/analytics/actions/get-session-replay-summary.ts +9 -65
  6. package/corpus/templates/analytics/actions/list-event-catalog.ts +1 -1
  7. package/corpus/templates/analytics/actions/list-session-outputs.ts +40 -0
  8. package/corpus/templates/analytics/actions/list-session-recordings.ts +17 -4
  9. package/corpus/templates/analytics/actions/view-screen.ts +29 -3
  10. package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +38 -167
  11. package/corpus/templates/analytics/app/i18n/en-US.ts +27 -0
  12. package/corpus/templates/analytics/app/pages/sessions/EventCatalogPage.tsx +18 -1
  13. package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +3 -1
  14. package/corpus/templates/analytics/app/pages/sessions/SessionOutputs.tsx +197 -0
  15. package/corpus/templates/analytics/app/pages/sessions/SessionsTriagePage.tsx +114 -4
  16. package/corpus/templates/analytics/changelog/2026-10-15-sessions-can-find-people-who-made-a-slides-deck-but-didn-t-p.md +6 -0
  17. package/corpus/templates/analytics/changelog/2026-10-16-owned-and-shared-chats-appear-in-separate-history-sections.md +6 -0
  18. package/corpus/templates/analytics/changelog/2026-10-16-the-activation-funnel-counts-visitors-who-decline-analytics-.md +6 -0
  19. package/corpus/templates/analytics/server/db/schema.ts +67 -0
  20. package/corpus/templates/analytics/server/lib/canonical-first-party-dashboard-repair.ts +9 -0
  21. package/corpus/templates/analytics/server/lib/first-party-analytics.ts +28 -22
  22. package/corpus/templates/analytics/server/lib/first-party-metric-catalog.ts +36 -1
  23. package/corpus/templates/analytics/server/lib/output-outcomes.ts +712 -0
  24. package/corpus/templates/analytics/server/lib/replay-origins.ts +33 -0
  25. package/corpus/templates/analytics/server/lib/session-event-index.ts +20 -0
  26. package/corpus/templates/analytics/server/lib/session-performance.ts +6 -40
  27. package/corpus/templates/analytics/server/lib/session-recording-associations.ts +30 -1
  28. package/corpus/templates/analytics/server/lib/session-replay-triage.ts +99 -0
  29. package/corpus/templates/analytics/server/lib/session-replay.ts +45 -31
  30. package/corpus/templates/analytics/server/lib/sessions-triage-lab.ts +8 -2
  31. package/corpus/templates/analytics/server/plugins/db.ts +46 -0
  32. package/corpus/templates/analytics/shared/output-use.ts +205 -0
  33. package/corpus/templates/analytics/shared/session-events.ts +6 -0
  34. package/corpus/templates/assets/CHANGELOG.md +6 -0
  35. package/corpus/templates/assets/app/components/layout/Sidebar.tsx +51 -117
  36. package/corpus/templates/assets/changelog/2026-10-16-owned-and-shared-chats-appear-in-separate-history-sections.md +6 -0
  37. package/corpus/templates/brain/app/components/layout/Sidebar.tsx +34 -101
  38. package/corpus/templates/brain/app/routes/sources.tsx +1 -1
  39. package/corpus/templates/brain/vitest.config.ts +7 -0
  40. package/corpus/templates/calendar/CHANGELOG.md +12 -0
  41. package/corpus/templates/calendar/actions/create-event.ts +2 -4
  42. package/corpus/templates/calendar/actions/update-event.ts +35 -6
  43. package/corpus/templates/calendar/app/pages/BookingLinksPage.tsx +1 -1
  44. package/corpus/templates/calendar/changelog/2026-10-16-booking-links-show-localized-visibility-badges.md +6 -0
  45. package/corpus/templates/calendar/changelog/2026-10-21-solo-events-avoid-notification-approval.md +6 -0
  46. package/corpus/templates/chat/app/components/layout/Sidebar.tsx +62 -101
  47. package/corpus/templates/clips/CHANGELOG.md +7 -20
  48. package/corpus/templates/clips/app/components/meetings/share-meeting-dialog.tsx +20 -77
  49. package/corpus/templates/clips/app/components/player/share-dialog.tsx +63 -90
  50. package/corpus/templates/clips/app/components/sharing/share-test-support.tsx +180 -0
  51. package/corpus/templates/clips/app/components/sharing/share-ui.tsx +5 -584
  52. package/corpus/templates/clips/changelog/2026-10-16-share-dialogs-make-it-easier-to-see-who-has-access-and-manag.md +6 -0
  53. package/corpus/templates/clips/changelog/2026-10-21-share-panels-describe-general-access-in-a-sentence.md +6 -0
  54. package/corpus/templates/community/qr/package.json +1 -1
  55. package/corpus/templates/content/.agents/skills/document-editing/references/databases.md +6 -3
  56. package/corpus/templates/content/CHANGELOG.md +10 -0
  57. package/corpus/templates/content/actions/_browser-document-save-attempt.ts +23 -1
  58. package/corpus/templates/content/actions/_builder-cms-blob-custody.ts +467 -0
  59. package/corpus/templates/content/actions/_builder-cms-execution-lease.ts +17 -0
  60. package/corpus/templates/content/actions/_builder-cms-intent-lookup.ts +5 -0
  61. package/corpus/templates/content/actions/_builder-cms-read-client.ts +881 -21
  62. package/corpus/templates/content/actions/_builder-cms-write-adapter.ts +28 -2
  63. package/corpus/templates/content/actions/_builder-cms-write-client.ts +109 -11
  64. package/corpus/templates/content/actions/_builder-docs-client.ts +1 -0
  65. package/corpus/templates/content/actions/_builder-private-blob.test-fixture.ts +90 -0
  66. package/corpus/templates/content/actions/_builder-source-execution-guard.ts +48 -0
  67. package/corpus/templates/content/actions/_content-save-outcomes.ts +5 -0
  68. package/corpus/templates/content/actions/_database-source-utils.ts +290 -8
  69. package/corpus/templates/content/actions/_database-utils.ts +93 -7
  70. package/corpus/templates/content/actions/_database-view-setup.ts +21 -2
  71. package/corpus/templates/content/actions/_delete-content-space.ts +8 -1
  72. package/corpus/templates/content/actions/_github-source-freshness.ts +30 -4
  73. package/corpus/templates/content/actions/add-content-database-source-field-property.ts +23 -6
  74. package/corpus/templates/content/actions/cancel-prepared-builder-source-update.ts +110 -26
  75. package/corpus/templates/content/actions/change-content-database-source-role.ts +51 -7
  76. package/corpus/templates/content/actions/delete-document.ts +41 -3
  77. package/corpus/templates/content/actions/disconnect-content-database-source.ts +68 -2
  78. package/corpus/templates/content/actions/disconnect-local-folder-source.ts +33 -2
  79. package/corpus/templates/content/actions/execute-builder-source-execution.ts +900 -140
  80. package/corpus/templates/content/actions/get-document.ts +2 -0
  81. package/corpus/templates/content/actions/permanently-delete-document.ts +6 -0
  82. package/corpus/templates/content/actions/prepare-builder-source-execution.ts +155 -13
  83. package/corpus/templates/content/actions/prepare-builder-source-review.ts +299 -73
  84. package/corpus/templates/content/actions/set-live-body-switch.ts +45 -0
  85. package/corpus/templates/content/actions/update-document.ts +139 -20
  86. package/corpus/templates/content/actions/validate-builder-source-execution.ts +135 -26
  87. package/corpus/templates/content/app/components/editor/CommentsSidebar.tsx +119 -30
  88. package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +56 -13
  89. package/corpus/templates/content/app/components/editor/SuggestionText.tsx +18 -3
  90. package/corpus/templates/content/app/components/editor/VisualEditor.tsx +89 -22
  91. package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +23 -0
  92. package/corpus/templates/content/app/components/editor/database/GitHubSourceStatusLine.tsx +27 -2
  93. package/corpus/templates/content/app/components/editor/database/ListItemLayout.tsx +32 -8
  94. package/corpus/templates/content/app/components/editor/database/ListItemRow.tsx +27 -2
  95. package/corpus/templates/content/app/components/editor/database-sources/BuilderSourceReviewDialog.tsx +1 -0
  96. package/corpus/templates/content/app/components/editor/extensions/SuggestionHighlight.ts +383 -34
  97. package/corpus/templates/content/app/components/editor/suggestions/draft-session.ts +31 -0
  98. package/corpus/templates/content/app/components/editor/suggestions/presentation-rebase.ts +82 -4
  99. package/corpus/templates/content/app/global.css +31 -0
  100. package/corpus/templates/content/app/hooks/use-content-database.ts +40 -2
  101. package/corpus/templates/content/app/hooks/use-documents.ts +14 -0
  102. package/corpus/templates/content/app/i18n-data.ts +1 -0
  103. package/corpus/templates/content/changelog/2026-10-16-accepting-a-suggestion-on-a-page-that-changed-since-it-was-s.md +6 -0
  104. package/corpus/templates/content/changelog/2026-10-17-builder-content-avoids-retrying-a-write-when-builder-accepte.md +6 -0
  105. package/corpus/templates/content/changelog/2026-10-18-link-a-new-collection-to-a-github-folder-from-its-sources.md +1 -1
  106. package/corpus/templates/content/changelog/2026-10-20-builder-content-sync-keeps-read-and-write-status-accurate-wh.md +6 -0
  107. package/corpus/templates/content/changelog/2026-10-20-suggested-edits-that-add-remove-split-or-merge-paragraphs-li.md +6 -0
  108. package/corpus/templates/content/changelog/2026-10-21-list-rows-can-show-each-pages-first-lines.md +6 -0
  109. package/corpus/templates/content/changelog/2026-10-22-a-collection-linked-to-a-big-github-folder-fills-faster-and-p.md +6 -0
  110. package/corpus/templates/content/docs/product/capabilities/content.source.adapters.md +29 -0
  111. package/corpus/templates/content/parity/matrix.md +42 -42
  112. package/corpus/templates/content/parity/matrix.ts +3 -1
  113. package/corpus/templates/content/server/db/schema.ts +20 -0
  114. package/corpus/templates/content/server/lib/content-trash-purge.ts +15 -1
  115. package/corpus/templates/content/server/lib/live-body-writer.ts +138 -26
  116. package/corpus/templates/content/server/live-copy/binding.ts +31 -0
  117. package/corpus/templates/content/server/live-copy/bounded-task.d.ts +6 -0
  118. package/corpus/templates/content/server/live-copy/exec-db.ts +1 -0
  119. package/corpus/templates/content/server/live-copy/holds.ts +59 -0
  120. package/corpus/templates/content/server/live-copy/persist.ts +656 -0
  121. package/corpus/templates/content/server/live-copy/switch.ts +136 -0
  122. package/corpus/templates/content/server/live-copy/task-names.ts +4 -0
  123. package/corpus/templates/content/server/live-copy/tasks.ts +183 -0
  124. package/corpus/templates/content/server/live-copy/write-cause.ts +85 -0
  125. package/corpus/templates/content/server/live-copy/write.ts +85 -0
  126. package/corpus/templates/content/server/plugins/builder-private-payload-cleanup.ts +22 -0
  127. package/corpus/templates/content/server/plugins/collab.ts +3 -0
  128. package/corpus/templates/content/server/plugins/db.ts +28 -0
  129. package/corpus/templates/content/shared/api.ts +30 -1
  130. package/corpus/templates/content/shared/database-item-layout.ts +54 -22
  131. package/corpus/templates/content/shared/document-intent-merge.ts +16 -9
  132. package/corpus/templates/content/shared/og-description.ts +258 -36
  133. package/corpus/templates/content/shared/suggestion-diff.ts +23 -6
  134. package/corpus/templates/content/shared/suggestion-formatting.ts +44 -14
  135. package/corpus/templates/content/shared/suggestion-text.ts +20 -5
  136. package/corpus/templates/design/.agents/skills/design-templates/SKILL.md +5 -1
  137. package/corpus/templates/design/.generated/bridge/shader-runtime.generated.ts +25 -4
  138. package/corpus/templates/design/CHANGELOG.md +5 -0
  139. package/corpus/templates/design/actions/get-getting-started.ts +53 -0
  140. package/corpus/templates/design/app/components/design/DesignCanvas.tsx +10 -0
  141. package/corpus/templates/design/app/components/design/bridge/native-shader-runtime.bridge.ts +132 -79
  142. package/corpus/templates/design/app/components/design/bridge/native-source-provider.ts +268 -130
  143. package/corpus/templates/design/app/components/design/bridge/native-worker-scene-host.ts +122 -42
  144. package/corpus/templates/design/app/components/design/bridge/shader-runtime.bridge.ts +41 -4
  145. package/corpus/templates/design/app/components/design/design-canvas/text-content-change-result.ts +46 -12
  146. package/corpus/templates/design/app/components/home/DesignHomeLibrary.tsx +15 -8
  147. package/corpus/templates/design/app/components/layout/GettingStarted.tsx +50 -0
  148. package/corpus/templates/design/app/components/layout/Sidebar.tsx +3 -0
  149. package/corpus/templates/design/app/components/templates/DesignTemplateGrid.tsx +163 -0
  150. package/corpus/templates/design/app/components/templates/DesignTemplateLibrary.tsx +65 -78
  151. package/corpus/templates/design/app/components/templates/TemplatePreview.tsx +6 -2
  152. package/corpus/templates/design/app/global.css +6 -0
  153. package/corpus/templates/design/app/i18n/en-US.ts +17 -0
  154. package/corpus/templates/design/app/lib/canvas-load-outcome.ts +147 -0
  155. package/corpus/templates/design/app/lib/canvas-outcome-tracking.ts +531 -0
  156. package/corpus/templates/design/app/lib/canvas-style-kind.ts +50 -0
  157. package/corpus/templates/design/app/pages/DesignSystems.tsx +1 -1
  158. package/corpus/templates/design/app/pages/Index.tsx +28 -67
  159. package/corpus/templates/design/app/pages/design-editor/commands/commit-visual-styles.ts +86 -29
  160. package/corpus/templates/design/app/pages/design-editor/commands/save-file-content.ts +38 -3
  161. package/corpus/templates/design/app/pages/design-editor/domains/use-editor-core.ts +9 -0
  162. package/corpus/templates/design/app/pages/design-editor/domains/use-editor-files-and-saving.ts +2 -0
  163. package/corpus/templates/design/changelog/2026-10-16-design-pages-use-localized-visibility-badges-and-a-shared-ow.md +6 -0
  164. package/corpus/templates/design/changelog/2026-10-21-a-getting-started-checklist-at-the-bottom-of-the-sidebar-tra.md +6 -0
  165. package/corpus/templates/design/changelog/2026-10-21-templates-now-open-a-read-only-preview-from-the-card-and-the.md +6 -0
  166. package/corpus/templates/design/changelog/2026-10-22-collapsed-shader-layers-no-longer-interrupt-other-shaders-on.md +6 -0
  167. package/corpus/templates/design/changelog/2026-10-22-shader-fills-keep-rendering-when-other-screen-content-cannot.md +6 -0
  168. package/corpus/templates/design/scripts/design-export-validation/export-baseline.json +24 -0
  169. package/corpus/templates/design/server/lib/getting-started.ts +267 -0
  170. package/corpus/templates/design/server/plugins/getting-started.ts +5 -0
  171. package/corpus/templates/design/shared/design-template-presets/analytics-dashboard.ts +127 -0
  172. package/corpus/templates/design/shared/design-template-presets/design-studio.ts +98 -0
  173. package/corpus/templates/design/shared/design-template-presets/messaging-app.ts +101 -0
  174. package/corpus/templates/design/shared/design-template-presets/project-tasks.ts +120 -0
  175. package/corpus/templates/design/shared/design-template-presets.ts +8 -0
  176. package/corpus/templates/dispatch/CHANGELOG.md +4 -0
  177. package/corpus/templates/dispatch/app/i18n-data.ts +75 -0
  178. package/corpus/templates/dispatch/changelog/2026-10-21-owned-and-shared-chats-appear-in-separate-history-sections.md +6 -0
  179. package/corpus/templates/factory/app/components/layout/Sidebar.tsx +34 -100
  180. package/corpus/templates/forms/app/pages/FormsListPage.tsx +1 -1
  181. package/corpus/templates/forms/server/plugins/agent-chat.ts +1 -1
  182. package/corpus/templates/plan/CHANGELOG.md +6 -0
  183. package/corpus/templates/plan/app/components/layout/Sidebar.tsx +34 -109
  184. package/corpus/templates/plan/changelog/2026-10-16-owned-and-shared-chats-appear-in-separate-history-sections.md +6 -0
  185. package/corpus/templates/slides/CHANGELOG.md +7 -0
  186. package/corpus/templates/slides/actions/delete-deck.ts +7 -0
  187. package/corpus/templates/slides/app/components/deck/DeckCard.tsx +1 -1
  188. package/corpus/templates/slides/app/components/design-system/DesignSystemCard.tsx +1 -1
  189. package/corpus/templates/slides/app/pages/Index.tsx +7 -2
  190. package/corpus/templates/slides/changelog/2026-10-16-deck-lists-use-the-shared-ownership-filter-and-visibility-ba.md +6 -0
  191. package/corpus/templates/slides/changelog/2026-10-21-connected-deck-deletion-requires-approval.md +6 -0
  192. package/corpus/templates/slides/scripts/edit-fidelity/client-action.ts +61 -0
  193. package/corpus/templates/slides/scripts/edit-fidelity/run.ts +10 -0
  194. package/package.json +1 -1
  195. package/corpus/templates/chat/app/lib/sidebar-thread-state.ts +0 -29
  196. package/corpus/templates/slides/app/components/deck/DeckFilterMenu.tsx +0 -83
@@ -1,91 +1,14 @@
1
1
  import { trackEvent } from "@agent-native/core/client/analytics";
2
- import {
3
- useActionMutation,
4
- useActionQuery,
5
- } from "@agent-native/core/client/hooks";
6
2
  import { useT } from "@agent-native/core/client/i18n";
7
- import { useOrg } from "@agent-native/core/client/org";
3
+ import type { ShareButtonVisibility } from "@agent-native/core/client/sharing/useShareButtonController";
8
4
  import { writeClipboardText } from "@agent-native/toolkit/clipboard";
9
- import {
10
- IconCheck,
11
- IconChevronDown,
12
- IconLink,
13
- IconLock,
14
- IconSend2,
15
- IconTrash,
16
- IconUsersGroup,
17
- IconWorld,
18
- } from "@tabler/icons-react";
19
- import { useQueryClient } from "@tanstack/react-query";
20
- import { useEffect, useMemo, useRef, useState, type ReactNode } from "react";
5
+ import { IconCheck, IconLink } from "@tabler/icons-react";
6
+ import { useEffect, useRef, useState, type ReactNode } from "react";
21
7
 
22
- import {
23
- Avatar as UserAvatar,
24
- AvatarFallback as UserAvatarFallback,
25
- AvatarImage as UserAvatarImage,
26
- } from "@/components/ui/avatar";
27
8
  import { Button } from "@/components/ui/button";
28
- import { Checkbox } from "@/components/ui/checkbox";
29
- import {
30
- Collapsible,
31
- CollapsibleContent,
32
- CollapsibleTrigger,
33
- } from "@/components/ui/collapsible";
34
- import { Input } from "@/components/ui/input";
35
- import {
36
- Select,
37
- SelectContent,
38
- SelectItem,
39
- SelectTrigger,
40
- SelectValue,
41
- } from "@/components/ui/select";
42
- import { useVisibleAvatarUrl } from "@/lib/use-visible-avatar-url";
43
9
  import { cn } from "@/lib/utils";
44
10
 
45
- export type Visibility = "private" | "org" | "public";
46
- export type Role = "viewer" | "commenter" | "editor" | "admin";
47
- export type ShareSettingsView = "people" | null;
48
-
49
- export interface RoleCopy {
50
- label: string;
51
- description: string;
52
- }
53
-
54
- export interface Share {
55
- id: string;
56
- principalType: "user" | "org";
57
- principalId: string;
58
- role: Role;
59
- }
60
-
61
- export interface SharesResponse {
62
- ownerEmail: string | null;
63
- orgId: string | null;
64
- visibility: Visibility | null;
65
- role?: "owner" | Role;
66
- shares: Share[];
67
- }
68
-
69
- export type SharesQuery = ReturnType<typeof useActionQuery<SharesResponse>>;
70
-
71
- export const VIS_META: Record<Visibility, { Icon: typeof IconLock }> = {
72
- private: {
73
- Icon: IconLock,
74
- },
75
- org: {
76
- Icon: IconUsersGroup,
77
- },
78
- public: {
79
- Icon: IconWorld,
80
- },
81
- };
82
-
83
- export const ROLE_OPTIONS: Array<{ value: Role; label: string }> = [
84
- { value: "viewer", label: "Viewer" },
85
- { value: "commenter", label: "Commenter" },
86
- { value: "editor", label: "Editor" },
87
- { value: "admin", label: "Admin" },
88
- ];
11
+ export type Visibility = ShareButtonVisibility;
89
12
 
90
13
  export function copyToClipboard(value: string): Promise<boolean> {
91
14
  return writeClipboardText(value);
@@ -98,6 +21,7 @@ const NESTED_LAYER_SELECTOR = [
98
21
  "[role='menu']",
99
22
  "[role='listbox']",
100
23
  "[data-sonner-toaster]",
24
+ "[data-agent-native-share-overlay]",
101
25
  ].join(",");
102
26
 
103
27
  const OPEN_NESTED_LAYER_SELECTOR = [
@@ -135,51 +59,6 @@ export function nestedLayerDismissGuards(): {
135
59
  };
136
60
  }
137
61
 
138
- export function useResourceVisibilityMutation(
139
- resourceType: string,
140
- resourceId: string,
141
- sharesQuery: SharesQuery,
142
- ) {
143
- const queryClient = useQueryClient();
144
- const setVisibility = useActionMutation("set-resource-visibility");
145
- const shareQueryKey = useMemo(
146
- () =>
147
- ["action", "list-resource-shares", { resourceType, resourceId }] as const,
148
- [resourceType, resourceId],
149
- );
150
-
151
- const setResourceVisibility = (
152
- next: Visibility,
153
- options?: { onSuccess?: () => void },
154
- ) => {
155
- const previous = queryClient.getQueryData<SharesResponse>(shareQueryKey);
156
- queryClient.setQueryData<SharesResponse>(shareQueryKey, (current) =>
157
- current ? { ...current, visibility: next } : current,
158
- );
159
- setVisibility.mutate(
160
- {
161
- resourceType,
162
- resourceId,
163
- visibility: next,
164
- } as any,
165
- {
166
- onSuccess: () => {
167
- void sharesQuery.refetch().finally(() => options?.onSuccess?.());
168
- },
169
- onError: () => {
170
- if (previous) {
171
- queryClient.setQueryData(shareQueryKey, previous);
172
- } else {
173
- void queryClient.invalidateQueries({ queryKey: shareQueryKey });
174
- }
175
- },
176
- },
177
- );
178
- };
179
-
180
- return { setResourceVisibility, isPending: setVisibility.isPending };
181
- }
182
-
183
62
  export function ShareSectionLabel({
184
63
  children,
185
64
  className,
@@ -268,461 +147,3 @@ export function CopyButton({
268
147
  </Button>
269
148
  );
270
149
  }
271
-
272
- export function Avatar({ label, org }: { label: string; org?: boolean }) {
273
- const { avatarRef, avatarUrl } = useVisibleAvatarUrl(org ? null : label);
274
-
275
- if (org) {
276
- return (
277
- <span
278
- aria-hidden
279
- className="inline-flex size-6 shrink-0 items-center justify-center rounded-full bg-muted text-[10px] font-semibold text-muted-foreground dark:bg-background"
280
- >
281
- <IconUsersGroup size={12} strokeWidth={1.75} />
282
- </span>
283
- );
284
- }
285
-
286
- return (
287
- <UserAvatar ref={avatarRef} className="size-6 shrink-0">
288
- {avatarUrl ? <UserAvatarImage src={avatarUrl} alt={label} /> : null}
289
- <UserAvatarFallback className="bg-muted text-[10px] font-semibold text-muted-foreground dark:bg-background">
290
- {(label.split("@")[0]?.[0] ?? label[0] ?? "?").toUpperCase()}
291
- </UserAvatarFallback>
292
- </UserAvatar>
293
- );
294
- }
295
-
296
- export function AccessAccordionRow({
297
- icon,
298
- label,
299
- meta,
300
- disabled,
301
- open,
302
- onOpenChange,
303
- children,
304
- }: {
305
- icon: ReactNode;
306
- label: ReactNode;
307
- meta?: ReactNode;
308
- disabled?: boolean;
309
- open: boolean;
310
- onOpenChange: (open: boolean) => void;
311
- children?: ReactNode;
312
- }) {
313
- const summary = (
314
- <>
315
- {icon}
316
- <span className="min-w-0 flex-1 truncate text-sm">{label}</span>
317
- {meta ? (
318
- <span className="shrink-0 truncate text-xs text-muted-foreground">
319
- {meta}
320
- </span>
321
- ) : null}
322
- </>
323
- );
324
-
325
- if (!children) {
326
- return (
327
- <div className="flex min-h-8 w-full items-center gap-2 px-1.5 py-1">
328
- {summary}
329
- </div>
330
- );
331
- }
332
-
333
- return (
334
- <Collapsible open={open} onOpenChange={onOpenChange}>
335
- <CollapsibleTrigger
336
- disabled={disabled}
337
- className="flex min-h-8 w-full cursor-pointer items-center gap-2 rounded-md px-1.5 py-1 text-start transition-colors hover:bg-muted/50 disabled:pointer-events-none disabled:opacity-50"
338
- >
339
- {summary}
340
- {/* Sized like the row-level remove button so both trailing icons
341
- share the same optical center. */}
342
- <span className="flex size-6 shrink-0 items-center justify-center">
343
- <IconChevronDown
344
- aria-hidden
345
- className={cn(
346
- "size-3.5 opacity-50 transition-transform",
347
- open && "rotate-180",
348
- )}
349
- />
350
- </span>
351
- </CollapsibleTrigger>
352
- <CollapsibleContent className="clips-collapsible-content">
353
- <div className="pt-1">{children}</div>
354
- </CollapsibleContent>
355
- </Collapsible>
356
- );
357
- }
358
-
359
- const ACCESS_ORDER: Visibility[] = ["public", "org", "private"];
360
-
361
- export function GeneralAccessSelect({
362
- visibility,
363
- canManage,
364
- isPending,
365
- onChange,
366
- }: {
367
- visibility: Visibility;
368
- canManage: boolean;
369
- isPending: boolean;
370
- onChange: (next: Visibility) => void;
371
- }) {
372
- const t = useT();
373
- const { data: org } = useOrg();
374
- const orgName = org?.orgName;
375
- const meta = VIS_META[visibility];
376
-
377
- const optionLabel = (value: Visibility) => {
378
- if (value !== "org") return t(`shareUi.accessOptions.${value}`);
379
- return orgName
380
- ? t("shareUi.accessOptions.org", { orgName })
381
- : t("shareUi.accessOptions.orgFallback");
382
- };
383
-
384
- return (
385
- <Select
386
- value={visibility}
387
- onValueChange={(v) => onChange(v as Visibility)}
388
- disabled={!canManage || isPending}
389
- >
390
- {/* The trigger spans the whole row so the hover affordance matches the
391
- hit area. The icon is a bare svg, not a wrapped span, because the
392
- shared trigger applies line-clamp to every direct span child. */}
393
- <SelectTrigger
394
- size="sm"
395
- aria-label={t("shareUi.selectAccess")}
396
- className="w-full cursor-pointer justify-start gap-2 rounded-md border-0 bg-transparent px-1.5 py-1 text-sm shadow-none transition-colors hover:bg-muted/50 focus:ring-0 focus:ring-offset-0 [&>span]:flex-1 [&>span]:text-start [&>svg:last-child]:me-1"
397
- >
398
- <meta.Icon
399
- aria-hidden
400
- strokeWidth={1.75}
401
- className="size-6 shrink-0 rounded-full bg-muted p-1.5 text-muted-foreground"
402
- />
403
- <SelectValue>{optionLabel(visibility)}</SelectValue>
404
- </SelectTrigger>
405
- <SelectContent align="start">
406
- {ACCESS_ORDER.map((value) => {
407
- const OptionIcon = VIS_META[value].Icon;
408
- return (
409
- <SelectItem
410
- key={value}
411
- value={value}
412
- className="ps-2 pe-8 [&>span:first-child]:start-auto [&>span:first-child]:end-2"
413
- >
414
- <span className="flex items-center gap-2">
415
- <OptionIcon
416
- aria-hidden
417
- size={16}
418
- strokeWidth={1.75}
419
- className="shrink-0 text-muted-foreground"
420
- />
421
- {optionLabel(value)}
422
- </span>
423
- </SelectItem>
424
- );
425
- })}
426
- </SelectContent>
427
- </Select>
428
- );
429
- }
430
-
431
- export function InvitePeopleField({
432
- resourceType,
433
- resourceId,
434
- resourceUrl,
435
- sharesQuery,
436
- onError,
437
- }: {
438
- resourceType: string;
439
- resourceId: string;
440
- resourceUrl?: string;
441
- sharesQuery: SharesQuery;
442
- onError?: (err: unknown) => void;
443
- }) {
444
- const t = useT();
445
- const share = useActionMutation("share-resource");
446
- const [email, setEmail] = useState("");
447
- const [role, setRole] = useState<Role>("viewer");
448
- const [notifyPeople, setNotifyPeople] = useState(true);
449
- const hasInviteEmail = email.trim().length > 0;
450
-
451
- const handleAdd = () => {
452
- const trimmed = email.trim().toLowerCase();
453
- if (!trimmed) return;
454
- share.mutate(
455
- {
456
- resourceType,
457
- resourceId,
458
- principalType: "user",
459
- principalId: trimmed,
460
- role,
461
- notify: notifyPeople,
462
- ...(resourceUrl ? { resourceUrl } : {}),
463
- } as any,
464
- {
465
- onSuccess: () => {
466
- setEmail("");
467
- void sharesQuery.refetch();
468
- },
469
- onError: (err: unknown) => onError?.(err),
470
- },
471
- );
472
- };
473
-
474
- return (
475
- <div className="space-y-2">
476
- <div className="flex items-stretch gap-1.5">
477
- <div className="flex h-8 min-w-0 flex-1 items-center overflow-hidden rounded-md border border-input bg-background focus-within:ring-1 focus-within:ring-ring">
478
- <Input
479
- type="email"
480
- placeholder={t("shareUi.addPeopleByEmail")}
481
- value={email}
482
- onChange={(e) => setEmail(e.target.value)}
483
- onKeyDown={(e) => {
484
- if (e.key === "Enter") handleAdd();
485
- }}
486
- autoComplete="off"
487
- className="h-full min-w-0 flex-1 rounded-none border-0 bg-transparent text-sm shadow-none focus-visible:ring-0 focus-visible:ring-offset-0"
488
- />
489
- <Select value={role} onValueChange={(v) => setRole(v as Role)}>
490
- <SelectTrigger className="h-full w-auto shrink-0 gap-1 rounded-none border-0 bg-transparent px-2 text-xs text-muted-foreground shadow-none focus:ring-0 focus:ring-offset-0">
491
- <SelectValue>{t(`shareUi.roles.${role}`)}</SelectValue>
492
- </SelectTrigger>
493
- <SelectContent align="end">
494
- {ROLE_OPTIONS.map((opt) => (
495
- <SelectItem key={opt.value} value={opt.value}>
496
- {t(`shareUi.roles.${opt.value}`)}
497
- </SelectItem>
498
- ))}
499
- </SelectContent>
500
- </Select>
501
- </div>
502
- <Button
503
- type="button"
504
- size="icon-sm"
505
- onClick={handleAdd}
506
- disabled={!hasInviteEmail || share.isPending}
507
- aria-label={t("shareUi.invite")}
508
- title={t("shareUi.invite")}
509
- className="shrink-0"
510
- >
511
- <IconSend2 size={16} />
512
- </Button>
513
- </div>
514
- {hasInviteEmail ? (
515
- <label className="flex items-center gap-2 text-xs text-muted-foreground">
516
- <Checkbox
517
- checked={notifyPeople}
518
- onCheckedChange={(checked) => setNotifyPeople(checked === true)}
519
- />
520
- {t("shareUi.notifyPeople")}
521
- </label>
522
- ) : null}
523
- </div>
524
- );
525
- }
526
-
527
- export function PeopleAccessSection({
528
- resourceType,
529
- resourceId,
530
- sharesQuery,
531
- canManage,
532
- roleCopy,
533
- onError,
534
- }: {
535
- resourceType: string;
536
- resourceId: string;
537
- sharesQuery: SharesQuery;
538
- canManage: boolean;
539
- roleCopy?: Partial<Record<Role, RoleCopy>>;
540
- onError?: (err: unknown, action: "permission" | "remove") => void;
541
- }) {
542
- const t = useT();
543
- const data = sharesQuery.data;
544
- const people = useMemo(
545
- () => [
546
- ...(data?.ownerEmail ? [data.ownerEmail] : []),
547
- ...(data?.shares.map((s) => s.principalId) ?? []),
548
- ],
549
- [data],
550
- );
551
- const [first, ...rest] = people;
552
- const [open, setOpen] = useState(false);
553
-
554
- const firstShare = data?.shares.find((s) => s.principalId === first);
555
- const firstRole = firstShare
556
- ? (roleCopy?.[firstShare.role]?.label ??
557
- t(`shareUi.roles.${firstShare.role}`))
558
- : t("shareUi.ownerRole");
559
-
560
- return (
561
- <AccessAccordionRow
562
- icon={
563
- first ? (
564
- <Avatar label={first} />
565
- ) : (
566
- <span className="inline-block size-6 shrink-0 rounded-full bg-muted" />
567
- )
568
- }
569
- label={
570
- !first
571
- ? t("shareUi.onlyYou")
572
- : open || rest.length === 0
573
- ? first
574
- : t("shareUi.othersCount", { count: rest.length, email: first })
575
- }
576
- meta={
577
- first && (open || rest.length === 0)
578
- ? firstRole
579
- : t("shareUi.canAccess")
580
- }
581
- disabled={sharesQuery.isLoading}
582
- open={open}
583
- onOpenChange={setOpen}
584
- >
585
- {rest.length > 0 ? (
586
- <PeopleAccessSettingsBody
587
- resourceType={resourceType}
588
- resourceId={resourceId}
589
- sharesQuery={sharesQuery}
590
- canManage={canManage}
591
- roleCopy={roleCopy}
592
- onError={onError}
593
- excludePrincipalId={first}
594
- />
595
- ) : null}
596
- </AccessAccordionRow>
597
- );
598
- }
599
-
600
- export function PeopleAccessSettingsBody({
601
- resourceType,
602
- resourceId,
603
- sharesQuery,
604
- canManage,
605
- roleCopy,
606
- onError,
607
- excludePrincipalId,
608
- }: {
609
- resourceType: string;
610
- resourceId: string;
611
- sharesQuery: SharesQuery;
612
- canManage: boolean;
613
- roleCopy?: Partial<Record<Role, RoleCopy>>;
614
- onError?: (err: unknown, action: "permission" | "remove") => void;
615
- excludePrincipalId?: string;
616
- }) {
617
- const t = useT();
618
- const share = useActionMutation("share-resource");
619
- const unshare = useActionMutation("unshare-resource");
620
- const data = sharesQuery.data;
621
- const ownerEmail = data?.ownerEmail ?? null;
622
- const showOwner = ownerEmail !== null && ownerEmail !== excludePrincipalId;
623
- const shares = (data?.shares ?? []).filter(
624
- (s) => s.principalId !== excludePrincipalId,
625
- );
626
- const getRoleLabel = (value: Role) =>
627
- roleCopy?.[value]?.label ?? t(`shareUi.roles.${value}`);
628
-
629
- const handleChangeRole = (s: Share, nextRole: Role) => {
630
- if (nextRole === s.role) return;
631
- share.mutate(
632
- {
633
- resourceType,
634
- resourceId,
635
- principalType: s.principalType,
636
- principalId: s.principalId,
637
- role: nextRole,
638
- notify: false,
639
- } as any,
640
- {
641
- onSuccess: () => sharesQuery.refetch(),
642
- onError: (err: unknown) => onError?.(err, "permission"),
643
- },
644
- );
645
- };
646
-
647
- const handleRemove = (s: Share) => {
648
- unshare.mutate(
649
- {
650
- resourceType,
651
- resourceId,
652
- principalType: s.principalType,
653
- principalId: s.principalId,
654
- } as any,
655
- {
656
- onSuccess: () => sharesQuery.refetch(),
657
- onError: (err: unknown) => onError?.(err, "remove"),
658
- },
659
- );
660
- };
661
-
662
- return (
663
- <ul className="flex max-h-72 flex-col gap-1 overflow-y-auto p-0 m-0">
664
- {showOwner ? (
665
- <li className="flex min-h-8 items-center gap-2 px-1.5 py-1 text-sm">
666
- <Avatar label={ownerEmail} />
667
- <span className="min-w-0 flex-1 truncate">{ownerEmail}</span>
668
- <span className="text-xs text-muted-foreground">
669
- {t("shareUi.ownerRole")}
670
- </span>
671
- </li>
672
- ) : null}
673
-
674
- {shares.map((s) => (
675
- <li
676
- key={`${s.principalType}:${s.principalId}`}
677
- className="flex min-h-8 items-center gap-2 px-1.5 py-1 text-sm"
678
- >
679
- <Avatar label={s.principalId} org={s.principalType === "org"} />
680
- <span className="min-w-0 flex-1 truncate">{s.principalId}</span>
681
- {canManage ? (
682
- <Select
683
- value={s.role}
684
- onValueChange={(value) => handleChangeRole(s, value as Role)}
685
- disabled={share.isPending}
686
- >
687
- <SelectTrigger
688
- size="sm"
689
- className="w-auto shrink-0 gap-1 border-0 bg-transparent px-2 text-xs text-muted-foreground shadow-none focus:ring-0"
690
- >
691
- <SelectValue>{getRoleLabel(s.role)}</SelectValue>
692
- </SelectTrigger>
693
- <SelectContent align="end">
694
- {ROLE_OPTIONS.map((opt) => (
695
- <SelectItem key={opt.value} value={opt.value}>
696
- {getRoleLabel(opt.value)}
697
- </SelectItem>
698
- ))}
699
- </SelectContent>
700
- </Select>
701
- ) : (
702
- <span className="shrink-0 text-xs text-muted-foreground">
703
- {getRoleLabel(s.role)}
704
- </span>
705
- )}
706
- {canManage ? (
707
- <Button
708
- type="button"
709
- variant="ghost"
710
- size="icon"
711
- aria-label={t("shareUi.remove")}
712
- onClick={() => handleRemove(s)}
713
- className="h-7 w-7 shrink-0 text-muted-foreground"
714
- >
715
- <IconTrash size={14} />
716
- </Button>
717
- ) : null}
718
- </li>
719
- ))}
720
-
721
- {!shares.length && !showOwner ? (
722
- <li className="px-1 py-1.5 text-sm text-muted-foreground">
723
- {t("shareUi.noAccessYet")}
724
- </li>
725
- ) : null}
726
- </ul>
727
- );
728
- }
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: improved
3
+ date: 2026-10-16
4
+ ---
5
+
6
+ Share dialogs make it easier to see who has access and manage common sharing changes.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: improved
3
+ date: 2026-10-21
4
+ ---
5
+
6
+ Share panels describe general access in a sentence and no longer open an empty people list when you click into them.
@@ -11,7 +11,7 @@
11
11
  "typecheck": "tsc --noEmit"
12
12
  },
13
13
  "dependencies": {
14
- "@agent-native/core": "^0.216.0",
14
+ "@agent-native/core": "^0.218.0",
15
15
  "postgres": "^3.4.9",
16
16
  "qrcode": "^1.5.4",
17
17
  "zod": "^4.6.7"
@@ -244,9 +244,12 @@ supports searching property types by label or machine name.
244
244
  List views can save an item layout (`itemLayout`) that decides what each row
245
245
  shows: a start slot (page icon, a checkbox property, a status property, or
246
246
  nothing), the title weight, line 2 (a text, URL, or non-body Blocks property,
247
- clamped to 1-3 lines), and ordered property IDs for line 3 and the end of the
248
- row; end values move under the title on narrow screens and empty values take
249
- no space. Ticking a row's checkbox writes the property through
247
+ or with `source: "page"` the first lines of each row's page, clamped to 1-3
248
+ lines), and ordered property IDs for line 3 and the end of the row; end values
249
+ move under the title on narrow screens and empty values take no space. While
250
+ any list view shows page text, collection reads give each item an `excerpt`
251
+ with the start of its page as plain text; other collections leave page bodies
252
+ out of row reads. Ticking a row's checkbox writes the property through
250
253
  `set-document-property` and strikes the title through without moving the row.
251
254
  A view without `itemLayout` keeps the default rows. Agents update it with an
252
255
  `update-content-database-view` `update` patch on the list view: pass