@ai-matrx/rich-content 0.2.10 → 0.2.16

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 (114) hide show
  1. package/dist/copy/copy-commands.d.ts +42 -0
  2. package/dist/copy/copy-commands.js +119 -0
  3. package/dist/copy/markdown-copy-html.d.ts +3 -0
  4. package/dist/copy/markdown-copy-html.js +8 -0
  5. package/dist/copy/markdown-readable-text.d.ts +4 -0
  6. package/dist/copy/markdown-readable-text.js +62 -0
  7. package/dist/display/chat-markdown/block-registry/BlockComponentRegistry.js +2 -0
  8. package/dist/display/chat-markdown/block-registry/block-dispatch.js +2 -0
  9. package/dist/host/app-bindings.d.ts +30 -0
  10. package/dist/host/app-bindings.js +38 -0
  11. package/dist/host/feedback-subject.d.ts +16 -0
  12. package/dist/host/feedback-subject.js +0 -0
  13. package/dist/host/manual-copy.d.ts +7 -0
  14. package/dist/host/manual-copy.js +11 -0
  15. package/dist/host/registry.d.ts +2 -0
  16. package/dist/host/registry.js +10 -0
  17. package/dist/host/session-knob.d.ts +5 -0
  18. package/dist/host/session-knob.js +7 -0
  19. package/dist/host/types.d.ts +24 -0
  20. package/dist/rich-document/RegistryContextMenu.d.ts +29 -0
  21. package/dist/rich-document/RegistryContextMenu.js +40 -0
  22. package/dist/rich-document/RichDocument.d.ts +78 -0
  23. package/dist/rich-document/RichDocument.js +218 -0
  24. package/dist/rich-document/RichDocumentActionProvider.d.ts +18 -0
  25. package/dist/rich-document/RichDocumentActionProvider.js +18 -0
  26. package/dist/rich-document/RichDocumentActionSurface.d.ts +11 -0
  27. package/dist/rich-document/RichDocumentActionSurface.js +59 -0
  28. package/dist/rich-document/RichDocumentActions.d.ts +12 -0
  29. package/dist/rich-document/RichDocumentActions.js +29 -0
  30. package/dist/rich-document/actions/hostActions.d.ts +5 -0
  31. package/dist/rich-document/actions/hostActions.js +31 -0
  32. package/dist/rich-document/actions/labels.d.ts +9 -0
  33. package/dist/rich-document/actions/labels.js +8 -0
  34. package/dist/rich-document/actions/markdownTable.d.ts +9 -0
  35. package/dist/rich-document/actions/markdownTable.js +39 -0
  36. package/dist/rich-document/actions/provider.d.ts +58 -0
  37. package/dist/rich-document/actions/provider.js +245 -0
  38. package/dist/rich-document/actions/resumePendingAuthAction.d.ts +3 -0
  39. package/dist/rich-document/actions/resumePendingAuthAction.js +31 -0
  40. package/dist/rich-document/actions/sources/index.d.ts +9 -0
  41. package/dist/rich-document/actions/sources/index.js +22 -0
  42. package/dist/rich-document/actions/sources/raw.d.ts +4 -0
  43. package/dist/rich-document/actions/sources/raw.js +35 -0
  44. package/dist/rich-document/actions/useRichDocumentProvider.d.ts +1 -0
  45. package/dist/rich-document/actions/useRichDocumentProvider.js +13 -0
  46. package/dist/rich-document/host-types.d.ts +51 -0
  47. package/dist/rich-document/host-types.js +0 -0
  48. package/dist/rich-document/registrations.d.ts +1 -0
  49. package/dist/rich-document/registrations.js +13 -0
  50. package/dist/rich-document/review/applyTargets.d.ts +16 -0
  51. package/dist/rich-document/review/applyTargets.js +32 -0
  52. package/dist/rich-document/review/proposedEdit.d.ts +22 -0
  53. package/dist/rich-document/review/proposedEdit.js +48 -0
  54. package/dist/rich-document/review/protectedSpans.d.ts +14 -0
  55. package/dist/rich-document/review/protectedSpans.js +61 -0
  56. package/dist/rich-document/runtime/actionSurfacesStore.d.ts +30 -0
  57. package/dist/rich-document/runtime/actionSurfacesStore.js +79 -0
  58. package/dist/rich-document/runtime/contextMenuFor.d.ts +6 -0
  59. package/dist/rich-document/runtime/contextMenuFor.js +7 -0
  60. package/dist/rich-document/runtime/providerBridge.d.ts +20 -0
  61. package/dist/rich-document/runtime/providerBridge.js +23 -0
  62. package/dist/rich-document/runtime/useActionSurfaceProvider.d.ts +33 -0
  63. package/dist/rich-document/runtime/useActionSurfaceProvider.js +214 -0
  64. package/dist/rich-document/search/ContentFindControl.d.ts +8 -0
  65. package/dist/rich-document/search/ContentFindControl.js +46 -0
  66. package/dist/rich-document/search/RenderedFindBar.d.ts +8 -0
  67. package/dist/rich-document/search/RenderedFindBar.js +110 -0
  68. package/dist/rich-document/search/renderedFind.d.ts +1 -0
  69. package/dist/rich-document/search/renderedFind.js +1 -0
  70. package/dist/rich-document/types.d.ts +384 -0
  71. package/dist/rich-document/types.js +0 -0
  72. package/dist/rich-document/variants/ActionBar.d.ts +17 -0
  73. package/dist/rich-document/variants/ActionBar.js +48 -0
  74. package/dist/rich-document/variants/MenuVariant.d.ts +15 -0
  75. package/dist/rich-document/variants/MenuVariant.js +17 -0
  76. package/dist/rich-document/variants/MiniActionBar.d.ts +5 -0
  77. package/dist/rich-document/variants/MiniActionBar.js +11 -0
  78. package/dist/rich-document/variants/RegistryActionList.d.ts +17 -0
  79. package/dist/rich-document/variants/RegistryActionList.js +94 -0
  80. package/dist/rich-document/variants/RegistryActionMenu.d.ts +24 -0
  81. package/dist/rich-document/variants/RegistryActionMenu.js +74 -0
  82. package/dist/rich-document/variants/shared/AlchemyDocumentMenu.d.ts +7 -0
  83. package/dist/rich-document/variants/shared/AlchemyDocumentMenu.js +83 -0
  84. package/dist/rich-document/variants/shared/OpenOneMenuButton.d.ts +9 -0
  85. package/dist/rich-document/variants/shared/OpenOneMenuButton.js +70 -0
  86. package/dist/rich-document/variants/shared/StandaloneOneMenu.d.ts +8 -0
  87. package/dist/rich-document/variants/shared/StandaloneOneMenu.js +32 -0
  88. package/dist/rich-document/variants/shared/categories.d.ts +4 -0
  89. package/dist/rich-document/variants/shared/categories.js +31 -0
  90. package/dist/rich-document/variants/shared/iconMap.d.ts +2 -0
  91. package/dist/rich-document/variants/shared/iconMap.js +73 -0
  92. package/dist/rich-document/variants/shared/menuStructure.d.ts +81 -0
  93. package/dist/rich-document/variants/shared/menuStructure.js +271 -0
  94. package/dist/rich-document/variants/shared/runAction.d.ts +17 -0
  95. package/dist/rich-document/variants/shared/runAction.js +24 -0
  96. package/dist/selection-toolbar/SelectionToolbarFrame.d.ts +64 -0
  97. package/dist/selection-toolbar/SelectionToolbarFrame.js +191 -0
  98. package/dist/selection-toolbar/common-actions.d.ts +2 -0
  99. package/dist/selection-toolbar/common-actions.js +103 -0
  100. package/dist/selection-toolbar/selection-actions.d.ts +126 -0
  101. package/dist/selection-toolbar/selection-actions.js +240 -0
  102. package/dist/selection-toolbar/selection-copy.d.ts +19 -0
  103. package/dist/selection-toolbar/selection-copy.js +98 -0
  104. package/dist/selection-toolbar/selection-shape.d.ts +1 -0
  105. package/dist/selection-toolbar/selection-shape.js +15 -0
  106. package/dist/selection-toolbar/selection-zones.d.ts +90 -0
  107. package/dist/selection-toolbar/selection-zones.js +85 -0
  108. package/dist/selection-toolbar/textarea-caret.d.ts +8 -0
  109. package/dist/selection-toolbar/textarea-caret.js +69 -0
  110. package/dist/utils/alchemy-icon-keys.d.ts +18 -0
  111. package/dist/utils/alchemy-icon-keys.js +29 -0
  112. package/dist/utils/rendered-find.d.ts +9 -0
  113. package/dist/utils/rendered-find.js +68 -0
  114. package/package.json +23 -7
@@ -0,0 +1,78 @@
1
+ import * as React from "react";
2
+ import { type SpecimenMode } from "../display/specimen/SpecimenContext.js";
3
+ import type { ContentSource, RichDocumentAction, RichDocumentActionId, RichDocumentActionsProp, RichDocumentActionsVariant, RichDocumentActionsPosition, RichDocumentActionsBehavior } from "./types.js";
4
+ import type { AnnotationRecord, ServerProcessedBlock } from "./host-types.js";
5
+ import type { TypedStreamEvent } from "../display/chat-markdown/types.js";
6
+ export interface RichDocumentProps {
7
+ content?: string;
8
+ events?: TypedStreamEvent[];
9
+ serverProcessedBlocks?: ServerProcessedBlock[];
10
+ taskId?: string;
11
+ requestId?: string;
12
+ turnId?: string;
13
+ conversationId?: string;
14
+ isStreamActive?: boolean;
15
+ /** Required. Use { type: "raw" } when the source is genuinely unknown. */
16
+ source: ContentSource;
17
+ renderer?: "basic" | "configurable" | "stream";
18
+ actions?: RichDocumentActionsProp;
19
+ actionsVariant?: RichDocumentActionsVariant;
20
+ /** Where the action surface sits. Default "below". */
21
+ actionsPosition?: RichDocumentActionsPosition;
22
+ /** Visibility. Default "always". */
23
+ actionsBehavior?: RichDocumentActionsBehavior;
24
+ /** Required when actionsVariant === "remote". */
25
+ actionsSurfaceId?: string;
26
+ /**
27
+ * DECLARE that this content is a specimen — generated work that is meant to
28
+ * look right and be wrong (the Bad Example probe, a wrong explanation, a
29
+ * decoy option). Suppresses every action surface, the right-click menu, and
30
+ * the actions inside the content itself (table export / workbook / Google
31
+ * Sheet / edit / open-in-window), and prints the specimen banner in their
32
+ * place. Pass `true` for the default wording, or override the two lines.
33
+ * See @ai-matrx/rich-content/display/specimen/SpecimenContext.tsx.
34
+ */
35
+ specimen?: boolean | Partial<SpecimenMode>;
36
+ /**
37
+ * Enable a right-click context menu over the content. Lazy-loaded (the
38
+ * menu chunk only ships after the first right-click) and streaming-safe
39
+ * (yields to the native browser menu while isStreamActive). Pass an object
40
+ * to add context-menu-only `extra` actions or `exclude` specific ones.
41
+ * This is the extension point for future per-surface right-click actions.
42
+ */
43
+ enableContextMenu?: boolean | {
44
+ extra?: RichDocumentAction[];
45
+ exclude?: (RichDocumentActionId | string)[];
46
+ };
47
+ /**
48
+ * The SAVED RECORD this content is, for the reading set (highlight, comment,
49
+ * suggest, link) and its Notes & comments dock. Derived from `source` for a
50
+ * note, a chat answer and a saved working document; pass it when the source
51
+ * does not say (the studio previewing a loaded document), or `null` to turn
52
+ * the reading set off. A read-only copy, a stream in flight and a specimen
53
+ * never get one.
54
+ */
55
+ annotationRecord?: AnnotationRecord | null;
56
+ className?: string;
57
+ contentClassName?: string;
58
+ actionsClassName?: string;
59
+ onContentChange?: (newContent: string) => void;
60
+ applyLocalEdits?: boolean;
61
+ analysisData?: unknown;
62
+ messageId?: string;
63
+ allowFullScreenEditor?: boolean;
64
+ hideCopyButton?: boolean;
65
+ onError?: (error: string) => void;
66
+ onPhaseUpdate?: (phase: string) => void;
67
+ strictServerData?: boolean;
68
+ /**
69
+ * WHO WROTE this content — "ai" (a model), "other" (someone else) or "self"
70
+ * (the viewer). Decides whether remote images load by themselves
71
+ * (components/rich-content/prose/remote-image-policy.tsx, chair ruling
72
+ * 2026-09-25). Declare it at every call site — guard:
73
+ * components/rich-content/__tests__/image-policy-declared.test.ts.
74
+ */
75
+ imagePolicy?: "self" | "other" | "ai" | "inherit";
76
+ }
77
+ export declare function RichDocument(props: RichDocumentProps): React.ReactElement;
78
+ export default RichDocument;
@@ -0,0 +1,218 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { cn } from "@ai-matrx/design-system";
4
+ import { useActionSurfaceProvider } from "./runtime/useActionSurfaceProvider.js";
5
+ import { RegistryContextMenu } from "./RegistryContextMenu.js";
6
+ import { getSourceAdapter } from "./actions/sources/index.js";
7
+ import {
8
+ convertOriginForSource,
9
+ useDocumentDialogsHost,
10
+ RecordAnnotations,
11
+ annotationRecordOf,
12
+ recordKeyOf,
13
+ MarkdownStream
14
+ } from "../host/app-bindings.js";
15
+ import { ActionBar } from "./variants/ActionBar.js";
16
+ import { MiniActionBar } from "./variants/MiniActionBar.js";
17
+ import { MenuVariant } from "./variants/MenuVariant.js";
18
+ import { contextMenuFor } from "./runtime/contextMenuFor.js";
19
+ import {
20
+ SpecimenProvider,
21
+ SpecimenBanner,
22
+ resolveSpecimenMode
23
+ } from "../display/specimen/SpecimenContext.js";
24
+ function RichDocument(props) {
25
+ const {
26
+ source,
27
+ actions: actionsProp,
28
+ actionsVariant = "none",
29
+ actionsPosition = "below",
30
+ actionsBehavior = "always",
31
+ actionsSurfaceId,
32
+ specimen,
33
+ enableContextMenu,
34
+ className,
35
+ contentClassName,
36
+ actionsClassName,
37
+ content,
38
+ events,
39
+ serverProcessedBlocks,
40
+ taskId,
41
+ requestId,
42
+ turnId,
43
+ conversationId,
44
+ isStreamActive,
45
+ onContentChange,
46
+ applyLocalEdits,
47
+ analysisData,
48
+ messageId,
49
+ allowFullScreenEditor,
50
+ hideCopyButton,
51
+ onError,
52
+ onPhaseUpdate,
53
+ strictServerData,
54
+ imagePolicy,
55
+ annotationRecord
56
+ } = props;
57
+ const specimenMode = resolveSpecimenMode(specimen);
58
+ const effectiveActionsVariant = specimenMode ? "none" : actionsVariant;
59
+ const dialogsHost = useDocumentDialogsHost({
60
+ convertOrigin: convertOriginForSource(
61
+ source,
62
+ source.type === "note" ? "Note" : "Chat response"
63
+ ),
64
+ text: content ?? "",
65
+ // Clean up / Help / Custom agent need somewhere to APPLY the result.
66
+ writable: !source.readOnly && Boolean(getSourceAdapter(source.type).edit) && !(actionsProp?.extensions?.type === "chat-message" && (actionsProp.extensions.contentIsStructuredRaw || actionsProp.extensions.role === "user")),
67
+ chatMessage: source.type === "chat-message" && !source.readOnly ? {
68
+ conversationId: source.conversationId,
69
+ messageId: source.messageId,
70
+ surfaceKey: actionsProp?.surfaceKey ?? null
71
+ } : null
72
+ });
73
+ const record = annotationRecord !== void 0 ? annotationRecord : source.readOnly ? null : annotationRecordOf(source);
74
+ const hostedActions = {
75
+ ...actionsProp,
76
+ callbacks: {
77
+ ...dialogsHost.callbacks,
78
+ // A host that names its record explicitly (the studio's loaded document
79
+ // rides a raw source) tells the ⋯ "Notes & comments" row which dock it is.
80
+ ...record && annotationRecord !== void 0 ? { annotationRecordKey: () => recordKeyOf(record) } : {},
81
+ ...actionsProp?.callbacks
82
+ }
83
+ };
84
+ const { ctx, getCtx, resolvedActions, target } = useActionSurfaceProvider({
85
+ content,
86
+ source,
87
+ actions: hostedActions,
88
+ actionsVariant: effectiveActionsVariant,
89
+ actionsSurfaceId
90
+ });
91
+ let variantNode = null;
92
+ switch (effectiveActionsVariant) {
93
+ case "bar":
94
+ variantNode = /* @__PURE__ */ jsx(
95
+ ActionBar,
96
+ {
97
+ actions: resolvedActions,
98
+ getCtx,
99
+ target,
100
+ sourceId: ctx.instanceKey("alchemy")
101
+ }
102
+ );
103
+ break;
104
+ case "mini-bar":
105
+ variantNode = /* @__PURE__ */ jsx(
106
+ MiniActionBar,
107
+ {
108
+ actions: resolvedActions,
109
+ getCtx,
110
+ target,
111
+ sourceId: ctx.instanceKey("alchemy")
112
+ }
113
+ );
114
+ break;
115
+ case "menu":
116
+ case "icon-only":
117
+ variantNode = /* @__PURE__ */ jsx(MenuVariant, { getCtx, target });
118
+ break;
119
+ case "remote":
120
+ case "none":
121
+ default:
122
+ variantNode = null;
123
+ }
124
+ const isAbsolute = actionsPosition === "top-right" || actionsPosition === "top-left" || actionsPosition === "middle-right" || actionsPosition === "middle-left";
125
+ const absolutePositionClass = isAbsolute ? cn(
126
+ "absolute z-10",
127
+ actionsPosition === "top-right" && "right-1 top-1",
128
+ actionsPosition === "top-left" && "left-1 top-1",
129
+ actionsPosition === "middle-right" && "right-1 top-1/2 -translate-y-1/2",
130
+ actionsPosition === "middle-left" && "left-1 top-1/2 -translate-y-1/2"
131
+ ) : null;
132
+ const hoverClass = actionsBehavior === "hover-only" ? "opacity-0 transition-opacity group-hover:opacity-100 focus-within:opacity-100" : null;
133
+ const inFlowClass = !isAbsolute ? actionsPosition === "above" ? "mb-1" : "mt-1" : null;
134
+ const actionsNode = variantNode ? /* @__PURE__ */ jsx(
135
+ "div",
136
+ {
137
+ className: cn(
138
+ absolutePositionClass,
139
+ hoverClass,
140
+ inFlowClass,
141
+ actionsClassName
142
+ ),
143
+ children: variantNode
144
+ }
145
+ ) : null;
146
+ const rootClassName = cn(
147
+ "rich-document",
148
+ (isAbsolute || actionsBehavior === "hover-only") && "relative group",
149
+ className
150
+ );
151
+ const annotationSource = record && !specimenMode && !isStreamActive && typeof content === "string" && content.trim() ? {
152
+ token: record.token,
153
+ id: record.id,
154
+ title: record.title ?? "",
155
+ body: content,
156
+ contentVersion: Math.max(1, record.contentVersion ?? 1),
157
+ ...record.href ? { href: record.href } : {},
158
+ ...record.conversationId ? { conversationId: record.conversationId } : {}
159
+ } : null;
160
+ const engineInner = /* @__PURE__ */ jsx(RecordAnnotations, { record: annotationSource, children: /* @__PURE__ */ jsx("div", { className: cn("rich-document__content", contentClassName), children: /* @__PURE__ */ jsx(
161
+ MarkdownStream,
162
+ {
163
+ imagePolicy,
164
+ content,
165
+ events,
166
+ serverProcessedBlocks,
167
+ taskId,
168
+ requestId,
169
+ turnId,
170
+ conversationId,
171
+ isStreamActive,
172
+ onContentChange,
173
+ applyLocalEdits,
174
+ analysisData,
175
+ messageId,
176
+ allowFullScreenEditor,
177
+ hideCopyButton,
178
+ onError,
179
+ onPhaseUpdate,
180
+ strictServerData
181
+ }
182
+ ) }) });
183
+ let engine = engineInner;
184
+ const contextMenu = contextMenuFor(enableContextMenu, effectiveActionsVariant);
185
+ if (contextMenu && !specimenMode) {
186
+ const cmOptions = typeof contextMenu === "object" ? contextMenu : {};
187
+ engine = /* @__PURE__ */ jsx(
188
+ RegistryContextMenu,
189
+ {
190
+ content: content ?? "",
191
+ source,
192
+ actions: hostedActions,
193
+ extra: cmOptions.extra,
194
+ exclude: cmOptions.exclude,
195
+ suppressed: isStreamActive,
196
+ children: engineInner
197
+ }
198
+ );
199
+ }
200
+ if (specimenMode) {
201
+ return /* @__PURE__ */ jsxs("div", { className: rootClassName, children: [
202
+ /* @__PURE__ */ jsx(SpecimenBanner, { mode: specimenMode }),
203
+ /* @__PURE__ */ jsx(SpecimenProvider, { value: specimenMode, children: engine })
204
+ ] });
205
+ }
206
+ return /* @__PURE__ */ jsxs("div", { className: rootClassName, children: [
207
+ isAbsolute ? actionsNode : null,
208
+ !isAbsolute && actionsPosition === "above" ? actionsNode : null,
209
+ engine,
210
+ !isAbsolute && actionsPosition !== "above" ? actionsNode : null,
211
+ dialogsHost.dialogs
212
+ ] });
213
+ }
214
+ var RichDocument_default = RichDocument;
215
+ export {
216
+ RichDocument,
217
+ RichDocument_default as default
218
+ };
@@ -0,0 +1,18 @@
1
+ import * as React from "react";
2
+ import type { ContentSource, RichDocumentActionsProp } from "./types.js";
3
+ export interface RichDocumentActionProviderProps {
4
+ /** Live content the actions operate on (re-read at click time via the bridge). */
5
+ content: string;
6
+ /** Source identity — drives which actions show + save-to-task parent linking. */
7
+ source: ContentSource;
8
+ /** The surface a <RichDocumentActionSurface/> consumes. Required. */
9
+ surfaceId: string;
10
+ /** Trim/extend the action set + supply host callbacks (same shape as RichDocument). */
11
+ actions?: RichDocumentActionsProp;
12
+ }
13
+ /**
14
+ * Registers a remote RichDocument action provider for `surfaceId`. Renders
15
+ * nothing. See the file header for when to reach for this over RichDocument.
16
+ */
17
+ export declare function RichDocumentActionProvider(props: RichDocumentActionProviderProps): React.ReactElement | null;
18
+ export default RichDocumentActionProvider;
@@ -0,0 +1,18 @@
1
+ "use client";
2
+ import { useActionSurfaceProvider } from "./runtime/useActionSurfaceProvider.js";
3
+ function RichDocumentActionProvider(props) {
4
+ const { content, source, surfaceId, actions } = props;
5
+ useActionSurfaceProvider({
6
+ content,
7
+ source,
8
+ actions,
9
+ actionsVariant: "remote",
10
+ actionsSurfaceId: surfaceId
11
+ });
12
+ return null;
13
+ }
14
+ var RichDocumentActionProvider_default = RichDocumentActionProvider;
15
+ export {
16
+ RichDocumentActionProvider,
17
+ RichDocumentActionProvider_default as default
18
+ };
@@ -0,0 +1,11 @@
1
+ import * as React from "react";
2
+ export interface RichDocumentActionSurfaceProps {
3
+ surfaceId: string;
4
+ /** Which inline variant to render. Defaults to "bar". */
5
+ variant?: "bar" | "mini-bar" | "menu";
6
+ className?: string;
7
+ /** Rendered when no provider is currently registered. */
8
+ fallback?: React.ReactNode;
9
+ }
10
+ export declare function RichDocumentActionSurface(props: RichDocumentActionSurfaceProps): React.ReactElement | null;
11
+ export default RichDocumentActionSurface;
@@ -0,0 +1,59 @@
1
+ "use client";
2
+ import { Fragment, jsx } from "react/jsx-runtime";
3
+ import { cn } from "@ai-matrx/design-system";
4
+ import { useTopProvider } from "./runtime/actionSurfacesStore.js";
5
+ import { getBridge } from "./runtime/providerBridge.js";
6
+ import { ActionBar } from "./variants/ActionBar.js";
7
+ import { MiniActionBar } from "./variants/MiniActionBar.js";
8
+ import { MenuVariant } from "./variants/MenuVariant.js";
9
+ function RichDocumentActionSurface(props) {
10
+ const { surfaceId, variant = "bar", className, fallback = null } = props;
11
+ const provider = useTopProvider(surfaceId);
12
+ if (!provider) {
13
+ return /* @__PURE__ */ jsx(Fragment, { children: fallback });
14
+ }
15
+ const bridge = getBridge(provider.providerId);
16
+ if (!bridge) {
17
+ return /* @__PURE__ */ jsx(Fragment, { children: fallback });
18
+ }
19
+ switch (variant) {
20
+ case "bar":
21
+ return /* @__PURE__ */ jsx(
22
+ ActionBar,
23
+ {
24
+ actions: bridge.resolvedActions,
25
+ getCtx: bridge.getCtx,
26
+ target: bridge.target,
27
+ sourceId: provider.contentSourceId,
28
+ className
29
+ }
30
+ );
31
+ case "mini-bar":
32
+ return /* @__PURE__ */ jsx(
33
+ MiniActionBar,
34
+ {
35
+ actions: bridge.resolvedActions,
36
+ getCtx: bridge.getCtx,
37
+ target: bridge.target,
38
+ sourceId: provider.contentSourceId,
39
+ className
40
+ }
41
+ );
42
+ case "menu":
43
+ return /* @__PURE__ */ jsx(
44
+ MenuVariant,
45
+ {
46
+ target: bridge.target,
47
+ getCtx: bridge.getCtx,
48
+ className: cn(className)
49
+ }
50
+ );
51
+ default:
52
+ return null;
53
+ }
54
+ }
55
+ var RichDocumentActionSurface_default = RichDocumentActionSurface;
56
+ export {
57
+ RichDocumentActionSurface,
58
+ RichDocumentActionSurface_default as default
59
+ };
@@ -0,0 +1,12 @@
1
+ import * as React from "react";
2
+ import type { ContentSource, RichDocumentActionsProp } from "./types.js";
3
+ export interface RichDocumentActionsProps {
4
+ content: string;
5
+ source: ContentSource;
6
+ actions?: RichDocumentActionsProp;
7
+ className?: string;
8
+ /** Hide the ⋯ overflow menu (the primary row still renders). */
9
+ hideOverflow?: boolean;
10
+ }
11
+ export declare function RichDocumentActions(props: RichDocumentActionsProps): React.ReactElement;
12
+ export default RichDocumentActions;
@@ -0,0 +1,29 @@
1
+ "use client";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import { useActionSurfaceProvider } from "./runtime/useActionSurfaceProvider.js";
4
+ import { ActionBar } from "./variants/ActionBar.js";
5
+ function RichDocumentActions(props) {
6
+ const { content, source, actions, className, hideOverflow } = props;
7
+ const { ctx, getCtx, resolvedActions, target } = useActionSurfaceProvider({
8
+ content,
9
+ source,
10
+ actions,
11
+ actionsVariant: "bar"
12
+ });
13
+ return /* @__PURE__ */ jsx(
14
+ ActionBar,
15
+ {
16
+ actions: resolvedActions,
17
+ getCtx,
18
+ target,
19
+ sourceId: ctx.instanceKey("alchemy"),
20
+ className,
21
+ hideOverflow
22
+ }
23
+ );
24
+ }
25
+ var RichDocumentActions_default = RichDocumentActions;
26
+ export {
27
+ RichDocumentActions,
28
+ RichDocumentActions_default as default
29
+ };
@@ -0,0 +1,5 @@
1
+ import type { RichDocumentAction } from "../types.js";
2
+ /** "Clear" — the host empties its own content (a transcript pad). */
3
+ export declare function clearContentAction(onClear: () => void, label?: string): RichDocumentAction;
4
+ /** A host copy that joins more than this content (transcript + cleaned text). */
5
+ export declare function hostCopyAction(id: string, label: string, run: () => void | Promise<void>): RichDocumentAction;
@@ -0,0 +1,31 @@
1
+ import { Files, Trash2 } from "lucide-react";
2
+ function clearContentAction(onClear, label = "Clear") {
3
+ return {
4
+ id: "host:clear-content",
5
+ label,
6
+ icon: Trash2,
7
+ iconColor: "text-muted-foreground",
8
+ category: "edit",
9
+ supportedSources: "*",
10
+ renderSlot: "both",
11
+ order: 90,
12
+ run: () => onClear()
13
+ };
14
+ }
15
+ function hostCopyAction(id, label, run) {
16
+ return {
17
+ id: `host:${id}`,
18
+ label,
19
+ icon: Files,
20
+ iconColor: "text-muted-foreground",
21
+ category: "copy",
22
+ supportedSources: "*",
23
+ renderSlot: "both",
24
+ order: 80,
25
+ run: () => run()
26
+ };
27
+ }
28
+ export {
29
+ clearContentAction,
30
+ hostCopyAction
31
+ };
@@ -0,0 +1,9 @@
1
+ /** The engine half of the rich-document action helpers (the host keeps its handler helpers). */
2
+ import type { RichDocumentActionContext } from "../types.js";
3
+ /** Storage key for "do this action after the person signs in" payloads. */
4
+ export declare const PENDING_ACTION_KEY = "matrx_pending_post_auth_action";
5
+ /**
6
+ * Resolve an action label to a string. Supports both static labels and `(ctx) => string`
7
+ * callbacks so labels like "Edit history (3)" can pull counts from the live context.
8
+ */
9
+ export declare function resolveActionLabel(label: string | ((ctx: RichDocumentActionContext) => string), ctx: RichDocumentActionContext): string;
@@ -0,0 +1,8 @@
1
+ const PENDING_ACTION_KEY = "matrx_pending_post_auth_action";
2
+ function resolveActionLabel(label, ctx) {
3
+ return typeof label === "function" ? label(ctx) : label;
4
+ }
5
+ export {
6
+ PENDING_ACTION_KEY,
7
+ resolveActionLabel
8
+ };
@@ -0,0 +1,9 @@
1
+ export interface ParsedTable {
2
+ headers: string[];
3
+ rows: string[][];
4
+ }
5
+ export declare function cleanCell(text: string): string;
6
+ /** The first markdown table in `content`, or null when there is none. */
7
+ export declare function parseFirstMarkdownTable(content: string): ParsedTable | null;
8
+ /** RFC 4180 CSV (comma) or TSV (tab) text for a parsed table. */
9
+ export declare function tableToDelimited(table: ParsedTable, delimiter: "," | "\t"): string;
@@ -0,0 +1,39 @@
1
+ import { tableToCsv } from "../../display/tables/table-csv.js";
2
+ import { unwrapCodeSpans } from "@ai-matrx/content-ir/source";
3
+ import {
4
+ findTableEnd,
5
+ rowCells,
6
+ tableStartsAt,
7
+ unescapeCellPipes
8
+ } from "../../display/markdown-classification/processors/utils/gfm-table-lines.js";
9
+ function splitRow(line) {
10
+ return rowCells(line).map((cell) => cleanCell(unescapeCellPipes(cell)));
11
+ }
12
+ function cleanCell(text) {
13
+ return unwrapCodeSpans(text).replace(/\*\*([^*]+)\*\*/g, "$1").replace(/__([^_]+)__/g, "$1").replace(/\*([^*]+)\*/g, "$1").replace(/~~([^~]+)~~/g, "$1").replace(/\[([^\]]+)\]\(([^)]+)\)/g, "$1").replace(/<br\s*\/?>/gi, " ").trim();
14
+ }
15
+ function parseFirstMarkdownTable(content) {
16
+ const lines = content.split("\n");
17
+ for (let i = 0; i + 1 < lines.length; i += 1) {
18
+ if (!tableStartsAt(lines, i)) continue;
19
+ const headers = splitRow(lines[i]);
20
+ const rows = [];
21
+ const end = findTableEnd(lines, i);
22
+ for (let j = i + 2; j < end; j += 1) {
23
+ const cells = splitRow(lines[j]);
24
+ rows.push(headers.map((_, k) => cells[k] ?? ""));
25
+ }
26
+ return { headers, rows };
27
+ }
28
+ return null;
29
+ }
30
+ function tableToDelimited(table, delimiter) {
31
+ if (delimiter === ",") return tableToCsv(table.headers, table.rows);
32
+ const flat = (value) => value.replace(/[\t\r\n]+/g, " ");
33
+ return [table.headers, ...table.rows].map((row) => row.map(flat).join(" ")).join("\n");
34
+ }
35
+ export {
36
+ cleanCell,
37
+ parseFirstMarkdownTable,
38
+ tableToDelimited
39
+ };
@@ -0,0 +1,58 @@
1
+ import { type Action, type ActionProvider, type ClickTarget } from "@ai-matrx/alchemy/actions";
2
+ import type { WriteTarget } from "@ai-matrx/alchemy/declare";
3
+ import type { RichDocumentAction, RichDocumentActionContext, RichDocumentActionId } from "../types.js";
4
+ export declare const RICH_DOCUMENT_PROVIDER_ID = "rich-document";
5
+ /** The write target every source adapter serves (edit, delete, regenerate, fork…). */
6
+ export declare const RICH_DOCUMENT_SOURCE_TARGET = "rich_document_source";
7
+ export declare const SOURCE_WRITE_TARGET: WriteTarget;
8
+ /** Register an action at module load. A duplicate id is refused. */
9
+ export declare function registerAction(action: RichDocumentAction): void;
10
+ /** Get one action by ID. Returns undefined if unregistered. */
11
+ export declare function getAction(id: RichDocumentActionId | string): RichDocumentAction | undefined;
12
+ /** Get all registered actions. */
13
+ export declare function getAllActions(): RichDocumentAction[];
14
+ /** The one id for a named menu group, shared with the context-menu provider. */
15
+ export declare function richDocumentSectionId(label: string): string;
16
+ export interface RichDocumentTargetHost {
17
+ kind: "rich-document";
18
+ /** Render-time context: labels, shown/hidden, toggle state. */
19
+ ctx: RichDocumentActionContext;
20
+ /** Click-time context factory: what handlers run against (live content). */
21
+ getCtx: () => RichDocumentActionContext;
22
+ /** This host's own actions (the `actions.extra` prop). */
23
+ extra: readonly RichDocumentAction[];
24
+ }
25
+ /** The rich-document half of a composite host, for hosts that build one. */
26
+ export declare function richDocumentTargetHost(ctx: RichDocumentActionContext, options?: {
27
+ getCtx?: () => RichDocumentActionContext;
28
+ extra?: readonly RichDocumentAction[];
29
+ }): RichDocumentTargetHost;
30
+ /** THE ClickTarget for a rich-document context. */
31
+ export declare function richDocumentClickTarget(ctx: RichDocumentActionContext, options?: {
32
+ getCtx?: () => RichDocumentActionContext;
33
+ exclude?: readonly string[];
34
+ extra?: readonly RichDocumentAction[];
35
+ }): ClickTarget;
36
+ export declare function toAlchemyAction(rd: RichDocumentAction): Action;
37
+ /**
38
+ * Register this provider into the app's one registry, once per registry.
39
+ * Called by the rich-document layouts (the only hosts that need it), so the
40
+ * app's root host never imports the handler graph.
41
+ */
42
+ export declare function ensureRichDocumentProvider(registry: {
43
+ register(p: ActionProvider): () => void;
44
+ }): void;
45
+ /** The provider registered into the app's Alchemy action registry. */
46
+ export declare const richDocumentActionProvider: ActionProvider;
47
+ /** Re-render hook for hosts: the list changed (a handler module loaded). */
48
+ export declare function subscribeRichDocumentActions(listener: () => void): () => void;
49
+ /**
50
+ * The actions eligible for a context — synchronously, through the package's
51
+ * ONE eligibility pass. Used where a host needs the list during render (the
52
+ * remote-surface spec snapshot, the code-block bridge, the parity tests).
53
+ * A host extra whose id collides with a built-in is refused (the built-in wins).
54
+ */
55
+ export declare function resolveActions(ctx: RichDocumentActionContext, options?: {
56
+ exclude?: (RichDocumentActionId | string)[];
57
+ extra?: RichDocumentAction[];
58
+ }): RichDocumentAction[];