@ai-matrx/alchemy 0.6.2 → 0.8.2
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.
- package/CHANGELOG.md +58 -0
- package/dist/actions.cjs +374 -0
- package/dist/actions.cjs.map +1 -0
- package/dist/actions.d.cts +773 -0
- package/dist/actions.d.ts +773 -0
- package/dist/actions.js +351 -0
- package/dist/actions.js.map +1 -0
- package/dist/checks.cjs +31 -2
- package/dist/checks.cjs.map +1 -1
- package/dist/checks.d.cts +24 -1
- package/dist/checks.d.ts +24 -1
- package/dist/checks.js +31 -2
- package/dist/checks.js.map +1 -1
- package/dist/core.cjs +1757 -2
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.cts +595 -1
- package/dist/core.d.ts +595 -1
- package/dist/core.js +1749 -2
- package/dist/core.js.map +1 -1
- package/dist/declare.cjs +12 -10
- package/dist/declare.cjs.map +1 -1
- package/dist/declare.d.cts +18 -2
- package/dist/declare.d.ts +18 -2
- package/dist/declare.js +12 -10
- package/dist/declare.js.map +1 -1
- package/dist/index.cjs +1757 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +595 -1
- package/dist/index.d.ts +595 -1
- package/dist/index.js +1749 -2
- package/dist/index.js.map +1 -1
- package/dist/menu.cjs +436 -0
- package/dist/menu.cjs.map +1 -0
- package/dist/menu.d.cts +834 -0
- package/dist/menu.d.ts +834 -0
- package/dist/menu.js +413 -0
- package/dist/menu.js.map +1 -0
- package/dist/operate-document.cjs +163 -0
- package/dist/operate-document.cjs.map +1 -0
- package/dist/operate-document.d.cts +132 -0
- package/dist/operate-document.d.ts +132 -0
- package/dist/operate-document.js +130 -0
- package/dist/operate-document.js.map +1 -0
- package/dist/operate-rich-html.cjs +129 -0
- package/dist/operate-rich-html.cjs.map +1 -0
- package/dist/operate-rich-html.d.cts +136 -0
- package/dist/operate-rich-html.d.ts +136 -0
- package/dist/operate-rich-html.js +96 -0
- package/dist/operate-rich-html.js.map +1 -0
- package/dist/operate-server.cjs +157 -0
- package/dist/operate-server.cjs.map +1 -0
- package/dist/operate-server.d.cts +183 -0
- package/dist/operate-server.d.ts +183 -0
- package/dist/operate-server.js +134 -0
- package/dist/operate-server.js.map +1 -0
- package/dist/operate-xlsx.cjs +248 -0
- package/dist/operate-xlsx.cjs.map +1 -0
- package/dist/operate-xlsx.d.cts +129 -0
- package/dist/operate-xlsx.d.ts +129 -0
- package/dist/operate-xlsx.js +215 -0
- package/dist/operate-xlsx.js.map +1 -0
- package/dist/operate.cjs +1774 -0
- package/dist/operate.cjs.map +1 -0
- package/dist/operate.d.cts +595 -0
- package/dist/operate.d.ts +595 -0
- package/dist/operate.js +1750 -0
- package/dist/operate.js.map +1 -0
- package/dist/ports.cjs.map +1 -1
- package/dist/ports.d.cts +361 -3
- package/dist/ports.d.ts +361 -3
- package/dist/react-bar.cjs +686 -0
- package/dist/react-bar.cjs.map +1 -0
- package/dist/react-bar.d.cts +379 -0
- package/dist/react-bar.d.ts +379 -0
- package/dist/react-bar.js +665 -0
- package/dist/react-bar.js.map +1 -0
- package/dist/react-host.cjs +301 -0
- package/dist/react-host.cjs.map +1 -0
- package/dist/react-host.d.cts +820 -0
- package/dist/react-host.d.ts +820 -0
- package/dist/react-host.js +269 -0
- package/dist/react-host.js.map +1 -0
- package/dist/react-menu.cjs +735 -0
- package/dist/react-menu.cjs.map +1 -0
- package/dist/react-menu.d.cts +370 -0
- package/dist/react-menu.d.ts +370 -0
- package/dist/react-menu.js +722 -0
- package/dist/react-menu.js.map +1 -0
- package/dist/react-overflow.cjs +592 -0
- package/dist/react-overflow.cjs.map +1 -0
- package/dist/react-overflow.d.cts +817 -0
- package/dist/react-overflow.d.ts +817 -0
- package/dist/react-overflow.js +571 -0
- package/dist/react-overflow.js.map +1 -0
- package/dist/react-palette.cjs +489 -0
- package/dist/react-palette.cjs.map +1 -0
- package/dist/react-palette.d.cts +359 -0
- package/dist/react-palette.d.ts +359 -0
- package/dist/react-palette.js +457 -0
- package/dist/react-palette.js.map +1 -0
- package/dist/react-selection.cjs +617 -0
- package/dist/react-selection.cjs.map +1 -0
- package/dist/react-selection.d.cts +357 -0
- package/dist/react-selection.d.ts +357 -0
- package/dist/react-selection.js +596 -0
- package/dist/react-selection.js.map +1 -0
- package/dist/react-sheet.cjs +616 -0
- package/dist/react-sheet.cjs.map +1 -0
- package/dist/react-sheet.d.cts +361 -0
- package/dist/react-sheet.d.ts +361 -0
- package/dist/react-sheet.js +595 -0
- package/dist/react-sheet.js.map +1 -0
- package/package.json +148 -5
|
@@ -0,0 +1,820 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { TransferOutcome } from '@ai-matrx/kit/content-transfer';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Matrx Alchemy — Declare types (CONTRACT §2.1).
|
|
6
|
+
*
|
|
7
|
+
* A declaration is plain JSON data (chair ruling N2): no functions, no classes,
|
|
8
|
+
* no React. Runtime behaviour lives in `MountedSurface` (`/declare/host`) and in
|
|
9
|
+
* handler registrations, never here. Zero React, zero `@ai-matrx/agents`.
|
|
10
|
+
*/
|
|
11
|
+
type Json$1 = null | boolean | number | string | Json$1[] | {
|
|
12
|
+
[key: string]: Json$1;
|
|
13
|
+
};
|
|
14
|
+
/** Unchanged from `ui_surface_value_type_chk`. */
|
|
15
|
+
type ValueType = "string" | "number" | "boolean" | "object" | "array" | "document";
|
|
16
|
+
type Classification = "ordinary" | "secret" | "credential";
|
|
17
|
+
/** Persisted (CONTRACT §2.7). Projection enforces it before any value leaves. */
|
|
18
|
+
interface Sensitivity {
|
|
19
|
+
/** false = never leaves through Operate. Default true. */
|
|
20
|
+
exportable: boolean;
|
|
21
|
+
/** secret/credential are always excluded; no caller can relax this. Default "ordinary". */
|
|
22
|
+
classification: Classification;
|
|
23
|
+
/** Pre-checked in the preparation workspace. Default true. */
|
|
24
|
+
includedByDefault: boolean;
|
|
25
|
+
}
|
|
26
|
+
interface ValueGroup {
|
|
27
|
+
key: string;
|
|
28
|
+
label: string;
|
|
29
|
+
sortOrder: number;
|
|
30
|
+
description?: string;
|
|
31
|
+
}
|
|
32
|
+
/** The four runtime slots a capture fills (absorbs page-capture). */
|
|
33
|
+
type LiveSlot = "selection" | "on-demand" | "errors" | "requests";
|
|
34
|
+
interface DeclaredValue {
|
|
35
|
+
name: string;
|
|
36
|
+
label: string;
|
|
37
|
+
description: string;
|
|
38
|
+
valueType: ValueType;
|
|
39
|
+
/** Registered content-ir kind key (DB: kind_key). */
|
|
40
|
+
valueKind?: string;
|
|
41
|
+
alwaysAvailable: boolean;
|
|
42
|
+
typicalCharCount: number;
|
|
43
|
+
autoContext?: boolean;
|
|
44
|
+
group?: string;
|
|
45
|
+
sortOrder?: number;
|
|
46
|
+
sensitivity?: Partial<Sensitivity>;
|
|
47
|
+
/** Filled at capture time from a live slot instead of the scope. */
|
|
48
|
+
liveSlot?: LiveSlot;
|
|
49
|
+
/** "request" values drop out of "Only the data". Default "data". */
|
|
50
|
+
role?: "data" | "request";
|
|
51
|
+
}
|
|
52
|
+
/** Where a write lands. "stream" = applied live, op by op, into an editable text. */
|
|
53
|
+
type WriteMode = "draft" | "entity" | "ui" | "stream";
|
|
54
|
+
/** Who may apply WITHOUT a click. "queued" = filed for an organization's review. */
|
|
55
|
+
type ApplyPolicy = "manual" | "ask" | "auto" | "queued";
|
|
56
|
+
/** The WidgetHandle text op set, unchanged in meaning. */
|
|
57
|
+
type StreamOp = "replace" | "insert_before" | "insert_after" | "prepend" | "append" | "patch";
|
|
58
|
+
interface WriteTarget {
|
|
59
|
+
name: string;
|
|
60
|
+
label: string;
|
|
61
|
+
description: string;
|
|
62
|
+
valueType: ValueType;
|
|
63
|
+
valueKind?: string;
|
|
64
|
+
/** Read twin (evidence loop). Required when patchable or mode === "stream". */
|
|
65
|
+
updatesValue?: string;
|
|
66
|
+
patchable?: boolean;
|
|
67
|
+
approvalComparison?: "text-replacement";
|
|
68
|
+
mode: WriteMode;
|
|
69
|
+
/** Required iff mode === "stream". */
|
|
70
|
+
streamOps?: readonly StreamOp[];
|
|
71
|
+
/** Default "manual". Binding overrides may only tighten. */
|
|
72
|
+
applyPolicy?: ApplyPolicy;
|
|
73
|
+
destination?: boolean;
|
|
74
|
+
/** Present when the target writes into an item rather than the screen. */
|
|
75
|
+
itemType?: string;
|
|
76
|
+
group?: string;
|
|
77
|
+
sortOrder?: number;
|
|
78
|
+
}
|
|
79
|
+
/** One kind of thing inside a screen (a row, a message, a code block, a card). */
|
|
80
|
+
interface ItemType {
|
|
81
|
+
name: string;
|
|
82
|
+
label: string;
|
|
83
|
+
description: string;
|
|
84
|
+
/** Value names that together identify one item. */
|
|
85
|
+
identity: readonly string[];
|
|
86
|
+
levels?: readonly string[];
|
|
87
|
+
entityType?: string;
|
|
88
|
+
values: readonly DeclaredValue[];
|
|
89
|
+
writeTargets?: readonly WriteTarget[];
|
|
90
|
+
}
|
|
91
|
+
type Readiness = "verified" | "partial" | "stub";
|
|
92
|
+
/** `ui_surface_execution_mode_check`, unchanged. */
|
|
93
|
+
type ExecutionMode = "python-stream" | "nextjs-stream" | "browser-realtime" | "local-runtime";
|
|
94
|
+
interface ConfigNamespaceDeclaration {
|
|
95
|
+
namespace: string;
|
|
96
|
+
label: string;
|
|
97
|
+
description: string;
|
|
98
|
+
}
|
|
99
|
+
interface EvidenceSourceDeclaration {
|
|
100
|
+
kind: "processed_document";
|
|
101
|
+
idValue: string;
|
|
102
|
+
fileIdValue?: string;
|
|
103
|
+
labelValue?: string;
|
|
104
|
+
representation?: "clean" | "raw";
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* One screen's declaration. Owning packages add fields (agent roles, client
|
|
108
|
+
* tools) as EXTENSION SLOTS — by interface extension or declaration merging —
|
|
109
|
+
* and register a `DeclarationExtension` so validation and the sync cover them.
|
|
110
|
+
*/
|
|
111
|
+
interface SurfaceDeclaration {
|
|
112
|
+
surfaceName: string;
|
|
113
|
+
/** REQUIRED. `ui_surface.client_name`; must equal the surfaceName prefix. */
|
|
114
|
+
client: string;
|
|
115
|
+
/** REQUIRED. `ui_surface.execution_mode`. */
|
|
116
|
+
executionMode: ExecutionMode;
|
|
117
|
+
/** REQUIRED. `ui_surface.description` ("" only where the live row is empty). */
|
|
118
|
+
description: string;
|
|
119
|
+
label: string;
|
|
120
|
+
readiness: Readiness;
|
|
121
|
+
readinessNote?: string;
|
|
122
|
+
urlPattern?: string;
|
|
123
|
+
inheritsFrom?: string;
|
|
124
|
+
intro?: string;
|
|
125
|
+
overlayId?: string;
|
|
126
|
+
values: readonly DeclaredValue[];
|
|
127
|
+
groups?: readonly ValueGroup[];
|
|
128
|
+
writeTargets?: readonly WriteTarget[];
|
|
129
|
+
itemTypes?: readonly ItemType[];
|
|
130
|
+
liveSlots?: readonly LiveSlot[];
|
|
131
|
+
configNamespaces?: readonly ConfigNamespaceDeclaration[];
|
|
132
|
+
evidenceSources?: readonly EvidenceSourceDeclaration[];
|
|
133
|
+
skipBaselineValues?: boolean;
|
|
134
|
+
}
|
|
135
|
+
type ValueProvenance = {
|
|
136
|
+
kind: "own";
|
|
137
|
+
} | {
|
|
138
|
+
kind: "inherited";
|
|
139
|
+
from: string;
|
|
140
|
+
} | {
|
|
141
|
+
kind: "baseline";
|
|
142
|
+
};
|
|
143
|
+
type ResolvedValue = DeclaredValue & {
|
|
144
|
+
provenance: ValueProvenance;
|
|
145
|
+
groupKey: string;
|
|
146
|
+
/** Defaults filled. */
|
|
147
|
+
resolvedSensitivity: Sensitivity;
|
|
148
|
+
};
|
|
149
|
+
interface ResolvedSurfaceDeclaration extends SurfaceDeclaration {
|
|
150
|
+
contentHash: string;
|
|
151
|
+
values: readonly ResolvedValue[];
|
|
152
|
+
groups: readonly ValueGroup[];
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* ITEM KEYS. A value or write target is identified by (surfaceName, itemType ?? "", name).
|
|
156
|
+
* The qualified key "<itemType>.<name>" names an item value; a bare name is a screen value.
|
|
157
|
+
*/
|
|
158
|
+
type QualifiedValueKey = string;
|
|
159
|
+
/** Live slot payloads (page-capture's shapes, kept). */
|
|
160
|
+
interface LiveValues {
|
|
161
|
+
selection?: {
|
|
162
|
+
choices: Record<string, Json$1>;
|
|
163
|
+
text: string | null;
|
|
164
|
+
};
|
|
165
|
+
"on-demand"?: readonly OnDemandSection[];
|
|
166
|
+
errors?: readonly string[];
|
|
167
|
+
requests?: readonly RecentRequest[];
|
|
168
|
+
}
|
|
169
|
+
interface OnDemandSection {
|
|
170
|
+
id: string;
|
|
171
|
+
title: string;
|
|
172
|
+
description?: string;
|
|
173
|
+
role: "data" | "request";
|
|
174
|
+
brief?: Json$1;
|
|
175
|
+
load(signal: AbortSignal): Promise<Json$1>;
|
|
176
|
+
}
|
|
177
|
+
interface RecentRequest {
|
|
178
|
+
method: string;
|
|
179
|
+
path: string;
|
|
180
|
+
status: string;
|
|
181
|
+
httpStatus?: number;
|
|
182
|
+
durationMs?: number;
|
|
183
|
+
requestId?: string;
|
|
184
|
+
client?: string;
|
|
185
|
+
requestBody?: Json$1;
|
|
186
|
+
requestBodyNote?: string;
|
|
187
|
+
errorSentence?: string;
|
|
188
|
+
timestamp: number;
|
|
189
|
+
}
|
|
190
|
+
/** RAW-FREE. What leaves the package about a clicked item. */
|
|
191
|
+
interface ResolvedItem {
|
|
192
|
+
itemType: string;
|
|
193
|
+
identity: Record<string, string>;
|
|
194
|
+
level?: string;
|
|
195
|
+
readOnly: boolean;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* The click target (CONTRACT §2.4) in its own module: `/ports` references it,
|
|
200
|
+
* and `/ports` must stay free of every other package (types only).
|
|
201
|
+
*/
|
|
202
|
+
|
|
203
|
+
/** The six universal verbs — the ONLY rows that may grey (R1 c). */
|
|
204
|
+
declare const UNIVERSAL_VERBS: readonly ["copy", "cut", "paste", "undo", "redo", "find"];
|
|
205
|
+
type UniversalVerb = (typeof UNIVERSAL_VERBS)[number];
|
|
206
|
+
/** The transfer Payload's kinds (`actions/types.ts` asserts equality at compile time). */
|
|
207
|
+
type PayloadKind = "text" | "markdown" | "json" | "rows" | "registered";
|
|
208
|
+
/** What eligibility is computed from: everything declared at the click target. */
|
|
209
|
+
interface ClickTarget {
|
|
210
|
+
surface: {
|
|
211
|
+
instanceId: string;
|
|
212
|
+
surfaceName: string;
|
|
213
|
+
} | null;
|
|
214
|
+
/** The resolved declaration (inheritance applied). Eligibility decides by KEY existence over it. */
|
|
215
|
+
declaration: ResolvedSurfaceDeclaration | null;
|
|
216
|
+
/** Declared value keys with a read path here (screen names + qualified item keys). Key existence, not population. */
|
|
217
|
+
valueKeys: ReadonlySet<QualifiedValueKey>;
|
|
218
|
+
/** Scope chain, most general first: ["global", "<domain>", "<surfaceName>"]. */
|
|
219
|
+
scopeChain: readonly string[];
|
|
220
|
+
/** The surface's explicit exclusions (the one override). */
|
|
221
|
+
excludedActionIds: ReadonlySet<string>;
|
|
222
|
+
item: ResolvedItem | null;
|
|
223
|
+
level: string | null;
|
|
224
|
+
/** Offsets + the live range handle, editable or not. */
|
|
225
|
+
selection: {
|
|
226
|
+
text: string;
|
|
227
|
+
type: "editable" | "non-editable";
|
|
228
|
+
start: number;
|
|
229
|
+
end: number;
|
|
230
|
+
/** Opaque host handle (DOM Range / element) used to restore or stream into the selection. */
|
|
231
|
+
handle?: unknown;
|
|
232
|
+
} | null;
|
|
233
|
+
/** Payload kinds a capture of this target would produce (from declared value types/kinds). */
|
|
234
|
+
payloadKinds: readonly PayloadKind[];
|
|
235
|
+
/** Declared targets writable on this target right now. */
|
|
236
|
+
writable: readonly WriteTarget[];
|
|
237
|
+
readOnly: boolean;
|
|
238
|
+
/** True when any declared value here is secret/credential or non-exportable. */
|
|
239
|
+
restricted: boolean;
|
|
240
|
+
organizationId: string | null;
|
|
241
|
+
auth: {
|
|
242
|
+
authenticated: boolean;
|
|
243
|
+
admin: boolean;
|
|
244
|
+
creator: boolean;
|
|
245
|
+
};
|
|
246
|
+
/**
|
|
247
|
+
* Host-owned context a provider reads to act (the rich-document source, the
|
|
248
|
+
* editable field's callbacks). Opaque to the package; never crosses into the
|
|
249
|
+
* model. Providers that need it narrow it themselves.
|
|
250
|
+
*/
|
|
251
|
+
host?: unknown;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* `@ai-matrx/alchemy/ports` — the host ports (Matrx Alchemy CONTRACT §2.2).
|
|
256
|
+
*
|
|
257
|
+
* The app binds these ONCE, at its boundary (where the Alchemy host is
|
|
258
|
+
* mounted). The package never imports the host.
|
|
259
|
+
*
|
|
260
|
+
* ── Ports arrive with the wave that needs them (chair ruling N8) ────────────
|
|
261
|
+
*
|
|
262
|
+
* This entry declares only the ports the current waves use:
|
|
263
|
+
*
|
|
264
|
+
* ALC-13 `kinds` (content-ir's validator, injected), `diagnostics` (required)
|
|
265
|
+
* ALC-14 `identity`, `persistence`
|
|
266
|
+
* ALC-15 `store`, `notify`, `overlay`, `icons`, `knobs`, `i18n`, `auth`, `dialogs`
|
|
267
|
+
*
|
|
268
|
+
* ALC-16 `transport`, `assets`, `server`
|
|
269
|
+
*
|
|
270
|
+
* ALC-17 adds approvals/bodies/receipts.
|
|
271
|
+
*
|
|
272
|
+
* ── Absent-port semantics ───────────────────────────────────────────────────
|
|
273
|
+
*
|
|
274
|
+
* Every port except `diagnostics` is OPTIONAL. A port the host does not bind
|
|
275
|
+
* means that capability is ABSENT: the actions, formats or writes that need
|
|
276
|
+
* it are not offered at all. A missing port is never stubbed, never faked
|
|
277
|
+
* with a default that pretends to work, and never shown as a dead control.
|
|
278
|
+
*
|
|
279
|
+
* kinds absent → kind validation is absent (no value can be checked,
|
|
280
|
+
* so a kind-bearing write is not offered)
|
|
281
|
+
* diagnostics REQUIRED → nothing fails silently; contract breaks land here
|
|
282
|
+
* identity absent → organization-scoped declarations are absent
|
|
283
|
+
* persistence absent → per-person settings are absent (organization and
|
|
284
|
+
* platform defaults apply)
|
|
285
|
+
* store absent → actions that read named host state or run named
|
|
286
|
+
* host commands are absent
|
|
287
|
+
* notify absent → outcomes are not announced (diagnostics still captures)
|
|
288
|
+
* overlay absent → actions that open an overlay or navigate are absent
|
|
289
|
+
* icons absent → rows render label-only (a key is never shown as text)
|
|
290
|
+
* knobs absent → the platform default layout/density applies
|
|
291
|
+
* i18n absent → labels as written
|
|
292
|
+
* auth absent → a signed-out person does not see requiresAuth actions
|
|
293
|
+
* (sign-in-then-resume is the capability that is missing)
|
|
294
|
+
* dialogs absent → actions that need a host dialog are absent
|
|
295
|
+
*
|
|
296
|
+
* Types only: this entry has no runtime code.
|
|
297
|
+
*/
|
|
298
|
+
/** JSON as it crosses a port. */
|
|
299
|
+
type Json = null | boolean | number | string | Json[] | {
|
|
300
|
+
[key: string]: Json;
|
|
301
|
+
};
|
|
302
|
+
/**
|
|
303
|
+
* content-ir's kind validator, injected so Alchemy validates without
|
|
304
|
+
* importing the app or the kind catalog. The host builds it from
|
|
305
|
+
* `@ai-matrx/content-ir`'s `createKindValidator` over its own
|
|
306
|
+
* `SchemaSourcePort` (which content-ir defines and exports; Alchemy never
|
|
307
|
+
* declares it).
|
|
308
|
+
*
|
|
309
|
+
* `unverifiable: true` marks a verdict where the kind could not be checked
|
|
310
|
+
* (not registered, no schema, uncompilable schema, catalog unreachable) — a
|
|
311
|
+
* skip, which is never a pass.
|
|
312
|
+
*/
|
|
313
|
+
interface KindValidatorPort {
|
|
314
|
+
validate(kindKey: string, value: unknown, signal: AbortSignal): Promise<{
|
|
315
|
+
ok: true;
|
|
316
|
+
} | {
|
|
317
|
+
ok: false;
|
|
318
|
+
sentence: string;
|
|
319
|
+
remedy: string;
|
|
320
|
+
unverifiable?: true;
|
|
321
|
+
}>;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/** Where contract breaks are captured. Required: nothing fails silently. */
|
|
325
|
+
interface DiagnosticsPort {
|
|
326
|
+
capture(error: unknown, context: {
|
|
327
|
+
area: "declare" | "operate" | "write" | "actions" | "menu";
|
|
328
|
+
detail: Json;
|
|
329
|
+
}): void;
|
|
330
|
+
}
|
|
331
|
+
/** Who is using the app right now, and in which organization. */
|
|
332
|
+
interface IdentityPort {
|
|
333
|
+
/** `null` while the host has no resolved identity yet. */
|
|
334
|
+
current(): {
|
|
335
|
+
userId: string;
|
|
336
|
+
organizationId: string | null;
|
|
337
|
+
isAuthenticated: boolean;
|
|
338
|
+
isAdmin: boolean;
|
|
339
|
+
} | null;
|
|
340
|
+
/** Called whenever `current()` may answer differently; returns unsubscribe. */
|
|
341
|
+
onChange(listener: () => void): () => void;
|
|
342
|
+
}
|
|
343
|
+
/** Per-person settings (layout, density, transfer preferences), layered by the host's settings system. */
|
|
344
|
+
interface PersistencePort {
|
|
345
|
+
readSetting<T extends Json>(key: string): Promise<T | null>;
|
|
346
|
+
writeSetting(key: string, value: Json): Promise<void>;
|
|
347
|
+
}
|
|
348
|
+
/** Neutral state access: named reads and named commands. No Redux type or dispatch crosses this line. */
|
|
349
|
+
interface StorePort {
|
|
350
|
+
/** A named, typed read the host registered ("activeConversationId", "organizationName"). */
|
|
351
|
+
read<T extends Json>(key: string): T | null;
|
|
352
|
+
/** A named command the host registered ("tasks.setPendingSource"); resolves with its result. */
|
|
353
|
+
command(name: string, input: Json): Promise<Json | void>;
|
|
354
|
+
subscribe(key: string, listener: () => void): () => void;
|
|
355
|
+
}
|
|
356
|
+
interface NotifyPort {
|
|
357
|
+
success(sentence: string): void;
|
|
358
|
+
info(sentence: string): void;
|
|
359
|
+
/** Every failure names its remedy. */
|
|
360
|
+
error(sentence: string, remedy: string): void;
|
|
361
|
+
}
|
|
362
|
+
/** Overlays are dispatched through the host; the menu never renders a modal. */
|
|
363
|
+
interface OverlayHostPort {
|
|
364
|
+
open(overlayId: string, data: Json, instanceId?: string): void;
|
|
365
|
+
close(overlayId: string, instanceId?: string): void;
|
|
366
|
+
navigate(href: string): void;
|
|
367
|
+
}
|
|
368
|
+
/** Icon key → the host's icon component. The model only ever holds keys. */
|
|
369
|
+
interface IconResolverPort {
|
|
370
|
+
resolve(key: string): unknown | null;
|
|
371
|
+
}
|
|
372
|
+
type ContextArrangementKnob = "classic" | "tiered" | "command";
|
|
373
|
+
type DensityKnob = "comfortable" | "compact";
|
|
374
|
+
/** ORGANIZATION defaults only; every method takes the organization. */
|
|
375
|
+
interface MenuKnobsPort {
|
|
376
|
+
/** Replaces the constant PLACEMENT_LABEL_OVERRIDE. */
|
|
377
|
+
placementLabel(placement: string, organizationId: string | null): string | null;
|
|
378
|
+
/** Replaces the constant DEFAULT_PLACEMENT_MODE. */
|
|
379
|
+
placementMode(placement: string, organizationId: string | null): "show" | "hide";
|
|
380
|
+
/** The organization's default layout and density (platform default when null: command / comfortable). */
|
|
381
|
+
layout(organizationId: string | null): {
|
|
382
|
+
context: ContextArrangementKnob;
|
|
383
|
+
density: DensityKnob;
|
|
384
|
+
} | null;
|
|
385
|
+
}
|
|
386
|
+
/** Label translation. Absent = labels as written. */
|
|
387
|
+
interface I18nPort {
|
|
388
|
+
t(key: string, fallback: string): string;
|
|
389
|
+
}
|
|
390
|
+
/** Sign in, then resume the action the person picked. */
|
|
391
|
+
interface AuthResumePort {
|
|
392
|
+
isSignedIn(): boolean;
|
|
393
|
+
/** Stash {actionId, target fingerprint} and open sign-in; after sign-in the next matching menu host resumes it. */
|
|
394
|
+
signInThenResume(pending: {
|
|
395
|
+
actionId: string;
|
|
396
|
+
contentFingerprint: string;
|
|
397
|
+
}): void;
|
|
398
|
+
takePending(contentFingerprint: string): {
|
|
399
|
+
actionId: string;
|
|
400
|
+
} | null;
|
|
401
|
+
}
|
|
402
|
+
/** Per-instance host dialogs (today's RichDocumentActionContextCallbacks). */
|
|
403
|
+
interface HostDialogsPort {
|
|
404
|
+
requestDelete?(target: ClickTarget): void;
|
|
405
|
+
requestConvert?(target: ClickTarget): void;
|
|
406
|
+
requestEditHistory?(target: ClickTarget): void;
|
|
407
|
+
requestFullPrint?(target: ClickTarget): void;
|
|
408
|
+
requestSaveTable?(table: {
|
|
409
|
+
headers: string[];
|
|
410
|
+
rows: string[][];
|
|
411
|
+
}): void;
|
|
412
|
+
requestFlashcard?(answer: string): void;
|
|
413
|
+
}
|
|
414
|
+
/** The ports a host binds. Optional = absent capability when unbound (see above). */
|
|
415
|
+
interface AlchemyHostPorts {
|
|
416
|
+
kinds?: KindValidatorPort;
|
|
417
|
+
/** REQUIRED from ALC-13 (the only non-optional port): contract breaks are captured here. */
|
|
418
|
+
diagnostics: DiagnosticsPort;
|
|
419
|
+
identity?: IdentityPort;
|
|
420
|
+
persistence?: PersistencePort;
|
|
421
|
+
store?: StorePort;
|
|
422
|
+
notify?: NotifyPort;
|
|
423
|
+
overlay?: OverlayHostPort;
|
|
424
|
+
icons?: IconResolverPort;
|
|
425
|
+
/** Organization defaults for menu knobs; a person's own choice is layered over them via persistence (N9). */
|
|
426
|
+
knobs?: MenuKnobsPort;
|
|
427
|
+
i18n?: I18nPort;
|
|
428
|
+
auth?: AuthResumePort;
|
|
429
|
+
dialogs?: HostDialogsPort;
|
|
430
|
+
/** Clipboard and download for this runtime (the browser default ships in /operate). */
|
|
431
|
+
transport?: TransportPort;
|
|
432
|
+
/** Private or signed images → share-safe URLs before HTML is sealed. Absent = images keep their URL. */
|
|
433
|
+
assets?: AssetResolverPort;
|
|
434
|
+
/** Present when the host can reach aidream server operations; absent = server formats are not offered. */
|
|
435
|
+
server?: ServerPort;
|
|
436
|
+
}
|
|
437
|
+
/** A transferable artifact as the transport sees it (structurally `@ai-matrx/alchemy/operate`'s Artifact). */
|
|
438
|
+
interface TransportArtifact {
|
|
439
|
+
format: string;
|
|
440
|
+
plainText: string;
|
|
441
|
+
html?: string;
|
|
442
|
+
file?: {
|
|
443
|
+
filename: string;
|
|
444
|
+
mime: string;
|
|
445
|
+
bytes: Uint8Array;
|
|
446
|
+
};
|
|
447
|
+
}
|
|
448
|
+
type TransportOutcome = {
|
|
449
|
+
status: "success";
|
|
450
|
+
delivered: "clipboard" | "download-started";
|
|
451
|
+
mimeTypes: string[];
|
|
452
|
+
} | {
|
|
453
|
+
status: "degraded";
|
|
454
|
+
delivered: "plain-text";
|
|
455
|
+
reason: string;
|
|
456
|
+
} | {
|
|
457
|
+
status: "cancelled";
|
|
458
|
+
} | {
|
|
459
|
+
status: "error";
|
|
460
|
+
code: string;
|
|
461
|
+
message: string;
|
|
462
|
+
retryable: boolean;
|
|
463
|
+
};
|
|
464
|
+
/** Clipboard and download for a non-browser runtime (MV3 service worker, Tauri — CONTRACT R8). */
|
|
465
|
+
interface TransportPort {
|
|
466
|
+
copy(artifact: TransportArtifact, signal: AbortSignal): Promise<TransportOutcome>;
|
|
467
|
+
download(artifact: TransportArtifact, signal: AbortSignal): Promise<TransportOutcome>;
|
|
468
|
+
}
|
|
469
|
+
interface AssetResolverPort {
|
|
470
|
+
resolve(url: string, signal: AbortSignal): Promise<{
|
|
471
|
+
url: string;
|
|
472
|
+
} | null>;
|
|
473
|
+
}
|
|
474
|
+
type ServerResult = {
|
|
475
|
+
status: "bytes";
|
|
476
|
+
filename: string;
|
|
477
|
+
mime: string;
|
|
478
|
+
bytes: Uint8Array;
|
|
479
|
+
notices: readonly {
|
|
480
|
+
code: string;
|
|
481
|
+
sentence: string;
|
|
482
|
+
remedy: string;
|
|
483
|
+
}[];
|
|
484
|
+
} | {
|
|
485
|
+
status: "receipt";
|
|
486
|
+
receipt: {
|
|
487
|
+
status: string;
|
|
488
|
+
sentence: string;
|
|
489
|
+
remedy?: string;
|
|
490
|
+
};
|
|
491
|
+
};
|
|
492
|
+
interface ServerPort {
|
|
493
|
+
call(operationId: string, input: Json, signal: AbortSignal): Promise<ServerResult>;
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
/**
|
|
497
|
+
* Matrx Alchemy — Actions types (CONTRACT §2.4).
|
|
498
|
+
*
|
|
499
|
+
* One registry of everything a person can do to a thing. Providers plug in;
|
|
500
|
+
* eligibility is computed from what is declared at the click target; duplicate
|
|
501
|
+
* ids are refused; an action that does not apply is ABSENT (chair ruling R1).
|
|
502
|
+
*
|
|
503
|
+
* Framework-neutral: zero React, zero `@ai-matrx/agents`. Icons are string KEYS
|
|
504
|
+
* resolved by the host's `IconResolverPort`; labels go through `I18nPort`.
|
|
505
|
+
*/
|
|
506
|
+
|
|
507
|
+
/**
|
|
508
|
+
* Chair ruling R1: an action that does not apply or cannot run now is ABSENT.
|
|
509
|
+
* Only the six universal verbs may answer "unavailable-verb": greyed in the
|
|
510
|
+
* strip/bar, the sentence as tooltip. `requiresAuth` is NOT unavailability.
|
|
511
|
+
*/
|
|
512
|
+
type Eligibility = {
|
|
513
|
+
status: "absent";
|
|
514
|
+
} | {
|
|
515
|
+
status: "available";
|
|
516
|
+
} | {
|
|
517
|
+
status: "unavailable-verb";
|
|
518
|
+
verb: UniversalVerb;
|
|
519
|
+
sentence: string;
|
|
520
|
+
};
|
|
521
|
+
/** rich-document's ActionCategory, unchanged, plus the three the context menu groups by. */
|
|
522
|
+
type ActionCategory = "feedback" | "copy" | "export" | "save" | "edit" | "share" | "creator" | "app" | "listen" | "study" | "ask" | "ai" | "admin" | "clipboard" | "history" | "surface-info";
|
|
523
|
+
/**
|
|
524
|
+
* An optional named section inside the action's group (a grid's cell / row /
|
|
525
|
+
* column). `primary` marks the thing the person clicked: every layout renders
|
|
526
|
+
* it first, inline, heading kept (context-menu-v3's primary section law).
|
|
527
|
+
*/
|
|
528
|
+
interface ActionSection {
|
|
529
|
+
id: string;
|
|
530
|
+
label: string;
|
|
531
|
+
labelKey?: string;
|
|
532
|
+
icon?: string;
|
|
533
|
+
primary?: boolean;
|
|
534
|
+
}
|
|
535
|
+
interface Action {
|
|
536
|
+
/** Globally unique. A duplicate is refused (never overwritten). */
|
|
537
|
+
id: string;
|
|
538
|
+
/** The provider that registered it — filled by the registry. */
|
|
539
|
+
provider?: string;
|
|
540
|
+
/** Resolved through I18nPort.t(labelKey ?? id, label). */
|
|
541
|
+
label: string | ((target: ClickTarget) => string);
|
|
542
|
+
labelKey?: string;
|
|
543
|
+
/** Icon KEY resolved by IconResolverPort — the model stays framework-neutral. */
|
|
544
|
+
icon?: string;
|
|
545
|
+
/** Host styling hint for the glyph (rich-document iconColor). Renderers may ignore it. */
|
|
546
|
+
iconTone?: string;
|
|
547
|
+
/** Replaces `icon` while a state holds (a spinner while speaking). */
|
|
548
|
+
stateIcon?(target: ClickTarget): {
|
|
549
|
+
icon: string;
|
|
550
|
+
spin?: boolean;
|
|
551
|
+
} | null;
|
|
552
|
+
hint?: string;
|
|
553
|
+
hintKey?: string;
|
|
554
|
+
description?: string;
|
|
555
|
+
category: ActionCategory;
|
|
556
|
+
/** Which universal verb this clipboard action is (addressed by role in every layout). */
|
|
557
|
+
verb?: UniversalVerb;
|
|
558
|
+
order?: number;
|
|
559
|
+
/** Bar layout slot. Default "overflow". */
|
|
560
|
+
placement?: "primary" | "overflow" | "both";
|
|
561
|
+
section?: ActionSection;
|
|
562
|
+
/** A signed-out person still sees it; running goes through AuthResumePort (sign in, then resume). */
|
|
563
|
+
requiresAuth?: boolean;
|
|
564
|
+
/** Declared write targets this action lands through. Absent on a read-only target. */
|
|
565
|
+
writes?: readonly string[];
|
|
566
|
+
destructive?: boolean;
|
|
567
|
+
preserveSelection?: boolean;
|
|
568
|
+
/** Link rows navigate instead of running. */
|
|
569
|
+
href?: string | ((target: ClickTarget) => string);
|
|
570
|
+
eligible(target: ClickTarget): Eligibility;
|
|
571
|
+
/** Toggle/pressed state: a pressed button or a checked row. */
|
|
572
|
+
pressed?(target: ClickTarget): boolean;
|
|
573
|
+
/** Present = the row is a checkbox (pressed is its state). */
|
|
574
|
+
toggle?: boolean;
|
|
575
|
+
subscribe?(onChange: () => void, target: ClickTarget): () => void;
|
|
576
|
+
/** Submenus whose rows load on open (agent lists). */
|
|
577
|
+
expand?(target: ClickTarget, signal: AbortSignal): Promise<readonly Action[]>;
|
|
578
|
+
/** Shown centred when `expand` resolves empty. */
|
|
579
|
+
emptyLabel?: string;
|
|
580
|
+
run(target: ClickTarget, context: ActionRunContext): Promise<TransferOutcome | void> | TransferOutcome | void;
|
|
581
|
+
}
|
|
582
|
+
/** One removed read, recorded (kit content-transfer's omission shape). */
|
|
583
|
+
interface ReadOmission {
|
|
584
|
+
path: string;
|
|
585
|
+
reason: "excluded" | "filtered";
|
|
586
|
+
classification?: "secret" | "credential";
|
|
587
|
+
}
|
|
588
|
+
/**
|
|
589
|
+
* PROJECTION BEFORE PROVIDERS. Providers never receive a raw read. Every read
|
|
590
|
+
* they can make is projected first: secret and credential values, values
|
|
591
|
+
* declared `exportable: false`, and values nobody declared are removed, with an
|
|
592
|
+
* omission recorded. Raw reads never leave the package.
|
|
593
|
+
*/
|
|
594
|
+
interface ProjectedReads {
|
|
595
|
+
values(signal: AbortSignal): Promise<{
|
|
596
|
+
values: Record<string, Json$1>;
|
|
597
|
+
omissions: readonly ReadOmission[];
|
|
598
|
+
}>;
|
|
599
|
+
item(signal: AbortSignal): Promise<{
|
|
600
|
+
values: Record<string, Json$1>;
|
|
601
|
+
omissions: readonly ReadOmission[];
|
|
602
|
+
} | null>;
|
|
603
|
+
live(signal: AbortSignal): Promise<LiveValues>;
|
|
604
|
+
}
|
|
605
|
+
/**
|
|
606
|
+
* What a running action receives. `door` (ALC-17) and `operate` (ALC-16) join
|
|
607
|
+
* with their waves; until then those capabilities are absent (N8).
|
|
608
|
+
*/
|
|
609
|
+
interface ActionRunContext {
|
|
610
|
+
reads: ProjectedReads;
|
|
611
|
+
ports: AlchemyHostPorts;
|
|
612
|
+
signal: AbortSignal;
|
|
613
|
+
}
|
|
614
|
+
interface ActionProvider {
|
|
615
|
+
id: string;
|
|
616
|
+
/** T0 providers are known at mount; T1 providers load with the menu on first open. */
|
|
617
|
+
tier: "T0" | "T1";
|
|
618
|
+
/**
|
|
619
|
+
* The ids this provider can ever yield, when known up front. Lets the
|
|
620
|
+
* registry refuse a duplicate at registration instead of at first open.
|
|
621
|
+
*/
|
|
622
|
+
declaredIds?(): readonly string[];
|
|
623
|
+
actions(target: ClickTarget): readonly Action[] | Promise<readonly Action[]>;
|
|
624
|
+
}
|
|
625
|
+
interface ResolvedAction {
|
|
626
|
+
action: Action;
|
|
627
|
+
eligibility: Exclude<Eligibility, {
|
|
628
|
+
status: "absent";
|
|
629
|
+
}>;
|
|
630
|
+
}
|
|
631
|
+
interface ResolveRestriction {
|
|
632
|
+
exclude?: readonly string[];
|
|
633
|
+
categories?: readonly ActionCategory[];
|
|
634
|
+
}
|
|
635
|
+
interface ActionRegistry {
|
|
636
|
+
/** Throws DuplicateActionError naming both providers; nothing is overwritten. */
|
|
637
|
+
register(provider: ActionProvider): () => void;
|
|
638
|
+
/** restrict: a host may remove ids or categories, never add ineligible ones. */
|
|
639
|
+
resolve(target: ClickTarget, restrict?: ResolveRestriction): Promise<readonly ResolvedAction[]>;
|
|
640
|
+
/** Registered provider ids, in registration order. */
|
|
641
|
+
providers(): readonly string[];
|
|
642
|
+
/** Change notification (a provider registered or unregistered). */
|
|
643
|
+
subscribe(listener: () => void): () => void;
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
/**
|
|
647
|
+
* `@ai-matrx/alchemy/declare/host` — HOST-BINDING types only (CONTRACT §2.1, §2.6).
|
|
648
|
+
* Never imported by providers (`/declare`, `/actions`, `/menu`, `/operate` see only
|
|
649
|
+
* the raw-free `ResolvedItem`). Types only: no runtime code.
|
|
650
|
+
*/
|
|
651
|
+
|
|
652
|
+
interface ItemAnchor {
|
|
653
|
+
/** The host element the person clicked. */
|
|
654
|
+
element: unknown;
|
|
655
|
+
level?: string;
|
|
656
|
+
}
|
|
657
|
+
/** Raw item reads: consumed only by projection and the write handler that owns the target. */
|
|
658
|
+
interface InternalResolvedItem extends ResolvedItem {
|
|
659
|
+
readValues(signal: AbortSignal): Promise<Record<string, unknown>>;
|
|
660
|
+
}
|
|
661
|
+
/** A mounted instance of a declared surface. Structural handle, never a global name lookup. */
|
|
662
|
+
interface MountedSurface {
|
|
663
|
+
instanceId: string;
|
|
664
|
+
surfaceName: string;
|
|
665
|
+
isMounted(): boolean;
|
|
666
|
+
/** Same revision before and after a read, or capture refuses with "surface-changed". */
|
|
667
|
+
getRevision?(): string;
|
|
668
|
+
unsavedChanges?(): boolean;
|
|
669
|
+
readValues(signal: AbortSignal): Promise<Record<string, unknown>>;
|
|
670
|
+
readLive?(signal: AbortSignal): Promise<LiveValues>;
|
|
671
|
+
resolveItem?(anchor: ItemAnchor): InternalResolvedItem | null;
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
interface ProjectionSource {
|
|
675
|
+
surface: MountedSurface | null;
|
|
676
|
+
declaration: ResolvedSurfaceDeclaration | null;
|
|
677
|
+
item: InternalResolvedItem | null;
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
/**
|
|
681
|
+
* The one run path (T1e). Every layout runs an action through here, so the
|
|
682
|
+
* sign-in-then-resume rule, projection and failure capture live once.
|
|
683
|
+
*/
|
|
684
|
+
|
|
685
|
+
type RunResult = {
|
|
686
|
+
status: "ran";
|
|
687
|
+
outcome: TransferOutcome | void;
|
|
688
|
+
} | {
|
|
689
|
+
status: "auth-pending";
|
|
690
|
+
} | {
|
|
691
|
+
status: "failed";
|
|
692
|
+
error: unknown;
|
|
693
|
+
};
|
|
694
|
+
|
|
695
|
+
type ContextArrangement = "classic" | "tiered" | "command";
|
|
696
|
+
type Density = "comfortable" | "compact";
|
|
697
|
+
|
|
698
|
+
/**
|
|
699
|
+
* The React half of T1e: one hook every renderer uses to resolve the registry
|
|
700
|
+
* at a target, build the model and run a node. Handlers never live in a
|
|
701
|
+
* renderer — they live in providers and run through `runAction`.
|
|
702
|
+
*
|
|
703
|
+
* The context object is shared through globalThis so every per-layout entry
|
|
704
|
+
* (each bundled separately) reads the same provider (module state is banned
|
|
705
|
+
* across dual-loader graphs).
|
|
706
|
+
*/
|
|
707
|
+
|
|
708
|
+
interface MenuEngineOptions {
|
|
709
|
+
restrict?: ResolveRestriction;
|
|
710
|
+
/** Raw sources for projection (the host's mounted surface / clicked item). */
|
|
711
|
+
source?: ProjectionSource;
|
|
712
|
+
/** Content the menu acts on when nothing is selected (header text). */
|
|
713
|
+
content?: string | null;
|
|
714
|
+
contentFingerprint?: string;
|
|
715
|
+
/** Called after a node ran (close the menu, announce). */
|
|
716
|
+
onRan?: (nodeId: string, result: RunResult) => void;
|
|
717
|
+
/** Resolve only while true (renderers resolve on open). Default true. */
|
|
718
|
+
active?: boolean;
|
|
719
|
+
/**
|
|
720
|
+
* Re-resolve when this changes even if the target object is the same (a
|
|
721
|
+
* host that keeps one target per mount and reads live state through it).
|
|
722
|
+
*/
|
|
723
|
+
revision?: string | number;
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
/**
|
|
727
|
+
* `@ai-matrx/alchemy/react/sheet` — the mobile bottom-sheet layout, T1m.
|
|
728
|
+
* T1's twin over the SAME model (`sheet(model)`), so mobile can never drift
|
|
729
|
+
* from desktop. Path-based drill-down: a list of submenu ids re-resolved
|
|
730
|
+
* against the live model every render, so loading agents update in place.
|
|
731
|
+
*/
|
|
732
|
+
|
|
733
|
+
interface ActionSheetProps extends MenuEngineOptions {
|
|
734
|
+
target: ClickTarget;
|
|
735
|
+
open: boolean;
|
|
736
|
+
onOpenChange(open: boolean): void;
|
|
737
|
+
title?: string;
|
|
738
|
+
}
|
|
739
|
+
declare function ActionSheet({ target, open, onOpenChange, title, ...options }: ActionSheetProps): React.ReactElement;
|
|
740
|
+
|
|
741
|
+
declare const __sheet_ActionSheet: typeof ActionSheet;
|
|
742
|
+
type __sheet_ActionSheetProps = ActionSheetProps;
|
|
743
|
+
declare namespace __sheet {
|
|
744
|
+
export { __sheet_ActionSheet as ActionSheet, type __sheet_ActionSheetProps as ActionSheetProps, ActionSheet as default };
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
/**
|
|
748
|
+
* `@ai-matrx/alchemy/react/menu` — the right-click (context) layout, T1.
|
|
749
|
+
* Reached only through the T0 shell's dynamic import (`/react/host`); it
|
|
750
|
+
* draws `context(model, arrangement)` at the pointer. classic · tiered ·
|
|
751
|
+
* command (type-to-filter over every leaf with its breadcrumb).
|
|
752
|
+
*/
|
|
753
|
+
|
|
754
|
+
interface ContextMenuPanelProps extends MenuEngineOptions {
|
|
755
|
+
target: ClickTarget;
|
|
756
|
+
/** Viewport coordinates of the gesture. */
|
|
757
|
+
point: {
|
|
758
|
+
x: number;
|
|
759
|
+
y: number;
|
|
760
|
+
};
|
|
761
|
+
open: boolean;
|
|
762
|
+
onOpenChange(open: boolean): void;
|
|
763
|
+
arrangement?: ContextArrangement;
|
|
764
|
+
density?: Density;
|
|
765
|
+
}
|
|
766
|
+
declare function ContextMenuPanel({ target, point, open, onOpenChange, arrangement, density, ...options }: ContextMenuPanelProps): React.ReactElement;
|
|
767
|
+
|
|
768
|
+
declare const __menu_ContextMenuPanel: typeof ContextMenuPanel;
|
|
769
|
+
type __menu_ContextMenuPanelProps = ContextMenuPanelProps;
|
|
770
|
+
declare namespace __menu {
|
|
771
|
+
export { __menu_ContextMenuPanel as ContextMenuPanel, type __menu_ContextMenuPanelProps as ContextMenuPanelProps, ContextMenuPanel as default };
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
/**
|
|
775
|
+
* The shared React context (T0-safe: imports only React and types). Shared
|
|
776
|
+
* through globalThis so every per-layout bundle reads the same provider.
|
|
777
|
+
*/
|
|
778
|
+
|
|
779
|
+
interface AlchemyActionsValue {
|
|
780
|
+
registry: ActionRegistry;
|
|
781
|
+
ports: AlchemyHostPorts;
|
|
782
|
+
}
|
|
783
|
+
declare function useAlchemyActions(): AlchemyActionsValue;
|
|
784
|
+
|
|
785
|
+
interface AlchemyActionsProviderProps {
|
|
786
|
+
ports: AlchemyHostPorts;
|
|
787
|
+
/** Share one registry across providers; default: one per provider mount. */
|
|
788
|
+
registry?: ActionRegistry;
|
|
789
|
+
children: React.ReactNode;
|
|
790
|
+
}
|
|
791
|
+
declare function AlchemyActionsProvider({ ports, registry, children }: AlchemyActionsProviderProps): React.ReactElement;
|
|
792
|
+
/** Register a provider for the lifetime of the calling component. Duplicate ids throw (refused). */
|
|
793
|
+
declare function useRegisterActionProvider(provider: ActionProvider | null): void;
|
|
794
|
+
type MenuModule = typeof __menu;
|
|
795
|
+
type SheetModule = typeof __sheet;
|
|
796
|
+
interface ActionMenuTriggerProps extends MenuEngineOptions {
|
|
797
|
+
/** Build the target at gesture time (selection captured then). */
|
|
798
|
+
resolveTarget(gesture: {
|
|
799
|
+
element: Element;
|
|
800
|
+
selectionText: string;
|
|
801
|
+
editable: boolean;
|
|
802
|
+
}): ClickTarget | null;
|
|
803
|
+
children: React.ReactElement;
|
|
804
|
+
arrangement?: "classic" | "tiered" | "command";
|
|
805
|
+
density?: "comfortable" | "compact";
|
|
806
|
+
/** Force a renderer; default: sheet below 768px or on coarse pointers. */
|
|
807
|
+
mobile?: boolean;
|
|
808
|
+
/**
|
|
809
|
+
* The wrapped surface is an editor that wires text mutation into the menu,
|
|
810
|
+
* so the menu takes its right-click. Otherwise a live text field keeps its
|
|
811
|
+
* native menu (Paste, spellcheck, autofill).
|
|
812
|
+
*/
|
|
813
|
+
editable?: boolean;
|
|
814
|
+
/** Override the lazy loaders (tests, custom bundlers). */
|
|
815
|
+
loadMenu?: () => Promise<Pick<MenuModule, "ContextMenuPanel">>;
|
|
816
|
+
loadSheet?: () => Promise<Pick<SheetModule, "ActionSheet">>;
|
|
817
|
+
}
|
|
818
|
+
declare function ActionMenuTrigger({ resolveTarget, children, arrangement, density, mobile, editable, loadMenu, loadSheet, ...options }: ActionMenuTriggerProps): React.ReactElement;
|
|
819
|
+
|
|
820
|
+
export { ActionMenuTrigger, type ActionMenuTriggerProps, AlchemyActionsProvider, type AlchemyActionsProviderProps, type AlchemyActionsValue, useAlchemyActions, useRegisterActionProvider };
|