@ai-matrx/alchemy 0.8.59 → 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +36 -0
- package/README.md +2 -0
- package/dist/actions.cjs +1 -1
- package/dist/actions.cjs.map +1 -1
- package/dist/actions.d.cts +300 -3
- package/dist/actions.d.ts +300 -3
- package/dist/actions.js +1 -1
- package/dist/actions.js.map +1 -1
- package/dist/checks.cjs +1 -1
- package/dist/checks.cjs.map +1 -1
- package/dist/checks.d.cts +22 -1
- package/dist/checks.d.ts +22 -1
- package/dist/checks.js +2 -2
- package/dist/checks.js.map +1 -1
- package/dist/core.d.cts +141 -26
- package/dist/core.d.ts +141 -26
- package/dist/declare.cjs +1 -1
- package/dist/declare.cjs.map +1 -1
- package/dist/declare.d.cts +12 -4
- package/dist/declare.d.ts +12 -4
- package/dist/declare.js +1 -1
- package/dist/declare.js.map +1 -1
- package/dist/index.d.cts +141 -26
- package/dist/index.d.ts +141 -26
- package/dist/menu.cjs +1 -1
- package/dist/menu.cjs.map +1 -1
- package/dist/menu.d.cts +109 -2
- package/dist/menu.d.ts +109 -2
- package/dist/menu.js +1 -1
- package/dist/menu.js.map +1 -1
- package/dist/operate-server.d.cts +6 -0
- package/dist/operate-server.d.ts +6 -0
- package/dist/operate.d.cts +141 -26
- package/dist/operate.d.ts +141 -26
- package/dist/ports.cjs.map +1 -1
- package/dist/ports.d.cts +116 -1
- package/dist/ports.d.ts +116 -1
- package/dist/react-bar.cjs +2 -2
- package/dist/react-bar.cjs.map +1 -1
- package/dist/react-bar.d.cts +4 -2
- package/dist/react-bar.d.ts +4 -2
- package/dist/react-bar.js +2 -2
- package/dist/react-bar.js.map +1 -1
- package/dist/react-host.d.cts +124 -3
- package/dist/react-host.d.ts +124 -3
- package/dist/react-menu.cjs +2 -2
- package/dist/react-menu.cjs.map +1 -1
- package/dist/react-menu.d.cts +20 -4
- package/dist/react-menu.d.ts +20 -4
- package/dist/react-menu.js +2 -2
- package/dist/react-menu.js.map +1 -1
- package/dist/react-overflow.cjs +2 -2
- package/dist/react-overflow.cjs.map +1 -1
- package/dist/react-overflow.d.cts +109 -2
- package/dist/react-overflow.d.ts +109 -2
- package/dist/react-overflow.js +2 -2
- package/dist/react-overflow.js.map +1 -1
- package/dist/react-palette.cjs +1 -1
- package/dist/react-palette.cjs.map +1 -1
- package/dist/react-palette.d.cts +4 -2
- package/dist/react-palette.d.ts +4 -2
- package/dist/react-palette.js +1 -1
- package/dist/react-palette.js.map +1 -1
- package/dist/react-selection.cjs +2 -2
- package/dist/react-selection.cjs.map +1 -1
- package/dist/react-selection.d.cts +4 -2
- package/dist/react-selection.d.ts +4 -2
- package/dist/react-selection.js +2 -2
- package/dist/react-selection.js.map +1 -1
- package/dist/react-sheet.cjs +2 -2
- package/dist/react-sheet.cjs.map +1 -1
- package/dist/react-sheet.d.cts +4 -2
- package/dist/react-sheet.d.ts +4 -2
- package/dist/react-sheet.js +2 -2
- package/dist/react-sheet.js.map +1 -1
- package/package.json +3 -3
package/dist/react-host.d.cts
CHANGED
|
@@ -251,6 +251,75 @@ interface ClickTarget {
|
|
|
251
251
|
host?: unknown;
|
|
252
252
|
}
|
|
253
253
|
|
|
254
|
+
/**
|
|
255
|
+
* Surface Actions — the shapes (Applets CONTRACTS §6, FROZEN; exported here as a superset).
|
|
256
|
+
*
|
|
257
|
+
* An Action is one thing a surface can have done to it, by a person, an agent,
|
|
258
|
+
* an applet or an automation: a write target, a client tool, a Kind Action or a
|
|
259
|
+
* row in `ui.ui_surface_action`. All of them project onto `ActionDeclaration`
|
|
260
|
+
* (`./declarations.ts`) and run through ONE runner (`./surface-run.ts`). There is
|
|
261
|
+
* never a second registry: `name` IS the alchemy action id, and `category`
|
|
262
|
+
* defaults to "applet" in alchemy's closed `ActionCategory` union.
|
|
263
|
+
*
|
|
264
|
+
* Types only — no runtime code, no React, no `@ai-matrx/agents`. `/ports`
|
|
265
|
+
* imports from here, so this file imports nothing but local types.
|
|
266
|
+
*/
|
|
267
|
+
|
|
268
|
+
/** Who started a run. */
|
|
269
|
+
type ActionCaller = "person" | "agent" | "applet" | "automation";
|
|
270
|
+
/** Who may run it without a click: "manual" = only a person; "ask" = proposed first; "auto" = runs. */
|
|
271
|
+
type ActionPolicy = "ask" | "auto" | "manual";
|
|
272
|
+
interface ActionContext {
|
|
273
|
+
runId: string;
|
|
274
|
+
by: ActionCaller;
|
|
275
|
+
viewerId: string | null;
|
|
276
|
+
surfaceName?: string;
|
|
277
|
+
policy?: ActionPolicy;
|
|
278
|
+
}
|
|
279
|
+
/** The system's own sentence, never thrown into a UI. Superset of RecordsError (CONTRACTS §0 `AppletError`). */
|
|
280
|
+
interface ActionError {
|
|
281
|
+
code: string;
|
|
282
|
+
message: string;
|
|
283
|
+
retryable: boolean;
|
|
284
|
+
diagnostic?: string;
|
|
285
|
+
}
|
|
286
|
+
/** CONTRACTS §0 `Result<T>`. */
|
|
287
|
+
type ActionResult<T = unknown> = {
|
|
288
|
+
ok: true;
|
|
289
|
+
data: T;
|
|
290
|
+
} | {
|
|
291
|
+
ok: false;
|
|
292
|
+
error: ActionError;
|
|
293
|
+
};
|
|
294
|
+
/** `POST /actions/run` (aidream) — the request. */
|
|
295
|
+
interface ServerActionRunRequest {
|
|
296
|
+
name: string;
|
|
297
|
+
input: Json$1;
|
|
298
|
+
by: ActionCaller;
|
|
299
|
+
surface_name?: string;
|
|
300
|
+
policy?: ActionPolicy;
|
|
301
|
+
}
|
|
302
|
+
/** `POST /actions/run` (aidream) — the response. */
|
|
303
|
+
interface ServerActionRunResponse {
|
|
304
|
+
status: "applied" | "proposed" | "refused";
|
|
305
|
+
message: string;
|
|
306
|
+
receipts: Json$1[];
|
|
307
|
+
proposal?: Json$1;
|
|
308
|
+
}
|
|
309
|
+
/** A mandate run request: by alias (an Action's `target`) or by key. */
|
|
310
|
+
type MandateRunRequest = ({
|
|
311
|
+
alias: string;
|
|
312
|
+
key?: never;
|
|
313
|
+
} | {
|
|
314
|
+
key: string;
|
|
315
|
+
alias?: never;
|
|
316
|
+
}) & {
|
|
317
|
+
variables: Record<string, Json$1>;
|
|
318
|
+
userInput?: string;
|
|
319
|
+
by: ActionCaller;
|
|
320
|
+
policy: ActionPolicy;
|
|
321
|
+
};
|
|
322
|
+
|
|
254
323
|
/**
|
|
255
324
|
* `@ai-matrx/alchemy/ports` — the host ports (Matrx Alchemy CONTRACT §2.2).
|
|
256
325
|
*
|
|
@@ -299,6 +368,12 @@ interface ClickTarget {
|
|
|
299
368
|
* to an overlay carrying the session as data)
|
|
300
369
|
* transferKnobs absent → no organization default recipe; a person's own
|
|
301
370
|
* default (persistence) or the package's Full applies
|
|
371
|
+
* serverActions absent → `runs: "server"` Actions refuse with "not available here"
|
|
372
|
+
* mandates absent → `runs: "mandate"` Actions refuse the same way
|
|
373
|
+
* pageActions absent → `runs: "page"` Actions refuse the same way
|
|
374
|
+
* approvals absent → a policy "ask" Action started by an agent, applet or automation is refused
|
|
375
|
+
* ("needs a person's approval"); a person's own click is the approval
|
|
376
|
+
* (`runs: "navigate"` goes through `overlay.navigate`; overlay absent → refused)
|
|
302
377
|
*
|
|
303
378
|
* Types only: this entry has no runtime code.
|
|
304
379
|
*/
|
|
@@ -444,6 +519,36 @@ interface AlchemyHostPorts {
|
|
|
444
519
|
window?: WindowPort;
|
|
445
520
|
/** Organization default recipes, resolved by the host's Feature Knob ladder (platform → organization). */
|
|
446
521
|
transferKnobs?: TransferKnobsPort;
|
|
522
|
+
/** aidream `POST /actions/run`: a registered server action by name, as the caller, under the apply-policy cascade. */
|
|
523
|
+
serverActions?: ServerActionPort;
|
|
524
|
+
/** Runs a mandate by alias or key (the host binds `@ai-matrx/agents`; alchemy never imports it). */
|
|
525
|
+
mandates?: MandatePort;
|
|
526
|
+
/** The page's own handlers for `runs: "page"` Actions (in an applet frame: routed as `{ action, input, runId }`). */
|
|
527
|
+
pageActions?: PageActionPort;
|
|
528
|
+
/** Asks a person, in place, to approve an `ask` Action that an agent, applet or automation started. */
|
|
529
|
+
approvals?: ApprovalPort;
|
|
530
|
+
}
|
|
531
|
+
interface ServerActionPort {
|
|
532
|
+
run(request: ServerActionRunRequest): Promise<ServerActionRunResponse>;
|
|
533
|
+
}
|
|
534
|
+
interface MandatePort {
|
|
535
|
+
/** Resolves with the run's result (a kind envelope or JSON); rejects with the system's sentence. */
|
|
536
|
+
run(request: MandateRunRequest): Promise<unknown>;
|
|
537
|
+
}
|
|
538
|
+
interface ApprovalRequest {
|
|
539
|
+
action: string;
|
|
540
|
+
label: string;
|
|
541
|
+
description: string;
|
|
542
|
+
input: Json;
|
|
543
|
+
by: "agent" | "applet" | "automation";
|
|
544
|
+
surfaceName: string;
|
|
545
|
+
}
|
|
546
|
+
interface ApprovalPort {
|
|
547
|
+
/** Resolves true when the person approves; false when they decline or dismiss. */
|
|
548
|
+
ask(request: ApprovalRequest): Promise<boolean>;
|
|
549
|
+
}
|
|
550
|
+
interface PageActionPort {
|
|
551
|
+
dispatch(name: string, input: unknown, context: ActionContext): Promise<ActionResult<unknown>>;
|
|
447
552
|
}
|
|
448
553
|
/**
|
|
449
554
|
* Why a port and not `OverlayHostPort`: an overlay's `data` is `Json`, and a live preparation
|
|
@@ -597,8 +702,10 @@ type Eligibility = {
|
|
|
597
702
|
status: "unavailable";
|
|
598
703
|
sentence: string;
|
|
599
704
|
};
|
|
600
|
-
/** rich-document's ActionCategory, unchanged, plus the three the context menu groups by. */
|
|
601
|
-
type ActionCategory = "feedback" | "copy" | "export" | "save" | "edit" | "share" | "creator" | "app" | "listen" | "study" | "ask" | "ai" | "admin" | "clipboard" | "history" | "surface-info"
|
|
705
|
+
/** rich-document's ActionCategory, unchanged, plus the three the context menu groups by, plus "applet" (surface Actions). */
|
|
706
|
+
type ActionCategory = "feedback" | "copy" | "export" | "save" | "edit" | "share" | "creator" | "app" | "listen" | "study" | "ask" | "ai" | "admin" | "clipboard" | "history" | "surface-info"
|
|
707
|
+
/** Surface Actions (Applets CONTRACTS §6): the default category of an `ActionDeclaration`. */
|
|
708
|
+
| "applet";
|
|
602
709
|
/**
|
|
603
710
|
* An optional named section inside the action's group (a grid's cell / row /
|
|
604
711
|
* column). `primary` marks the thing the person clicked: every layout renders
|
|
@@ -866,6 +973,16 @@ declare namespace __sheet {
|
|
|
866
973
|
export { __sheet_ActionSheet as ActionSheet, type __sheet_ActionSheetProps as ActionSheetProps, ActionSheet as default, __sheet_sheetHeading as sheetHeading };
|
|
867
974
|
}
|
|
868
975
|
|
|
976
|
+
/**
|
|
977
|
+
* Menu size — "standard" (the original 288 px menu) or "large": the Google Docs / Sheets class of
|
|
978
|
+
* menu for a feature-heavy app (Arman, 2026-10-02: "our menu is too small… the one place where we
|
|
979
|
+
* have essentially unlimited space, we're suddenly cheap about it"). Measured on Google Sheets:
|
|
980
|
+
* 322 px wide, 32 px rows, 14 px text, 18 px icons. Large goes one step past it: 360 px, 36 px rows,
|
|
981
|
+
* 15 px text. A context, so submenus (portalled) draw at the same size as the menu they open from.
|
|
982
|
+
*/
|
|
983
|
+
|
|
984
|
+
type MenuSize = "standard" | "large";
|
|
985
|
+
|
|
869
986
|
/**
|
|
870
987
|
* `@ai-matrx/alchemy/react/menu` — the right-click (context) layout, T1.
|
|
871
988
|
* Reached only through the T0 shell's dynamic import (`/react/host`); it
|
|
@@ -890,8 +1007,12 @@ interface ContextMenuPanelProps extends MenuEngineOptions {
|
|
|
890
1007
|
* one "<subject> ▸" submenu (`foldUnderSubject`). Omit for a normal menu.
|
|
891
1008
|
*/
|
|
892
1009
|
subjectFold?: string;
|
|
1010
|
+
/** "large": the 360 px, 36 px-row menu (`menu-size.tsx`). Default "standard". */
|
|
1011
|
+
size?: MenuSize;
|
|
1012
|
+
/** Draw no header line ("Row: …", "Table: …"): the menu starts at its icons. */
|
|
1013
|
+
hideHeader?: boolean;
|
|
893
1014
|
}
|
|
894
|
-
declare function ContextMenuPanel({ target, point, open, onOpenChange, arrangement, density, subjectFold, ...options }: ContextMenuPanelProps): React.ReactElement;
|
|
1015
|
+
declare function ContextMenuPanel({ target, point, open, onOpenChange, arrangement, density, subjectFold, size, hideHeader, ...options }: ContextMenuPanelProps): React.ReactElement;
|
|
895
1016
|
|
|
896
1017
|
declare const __menu_ContextMenuPanel: typeof ContextMenuPanel;
|
|
897
1018
|
type __menu_ContextMenuPanelProps = ContextMenuPanelProps;
|
package/dist/react-host.d.ts
CHANGED
|
@@ -251,6 +251,75 @@ interface ClickTarget {
|
|
|
251
251
|
host?: unknown;
|
|
252
252
|
}
|
|
253
253
|
|
|
254
|
+
/**
|
|
255
|
+
* Surface Actions — the shapes (Applets CONTRACTS §6, FROZEN; exported here as a superset).
|
|
256
|
+
*
|
|
257
|
+
* An Action is one thing a surface can have done to it, by a person, an agent,
|
|
258
|
+
* an applet or an automation: a write target, a client tool, a Kind Action or a
|
|
259
|
+
* row in `ui.ui_surface_action`. All of them project onto `ActionDeclaration`
|
|
260
|
+
* (`./declarations.ts`) and run through ONE runner (`./surface-run.ts`). There is
|
|
261
|
+
* never a second registry: `name` IS the alchemy action id, and `category`
|
|
262
|
+
* defaults to "applet" in alchemy's closed `ActionCategory` union.
|
|
263
|
+
*
|
|
264
|
+
* Types only — no runtime code, no React, no `@ai-matrx/agents`. `/ports`
|
|
265
|
+
* imports from here, so this file imports nothing but local types.
|
|
266
|
+
*/
|
|
267
|
+
|
|
268
|
+
/** Who started a run. */
|
|
269
|
+
type ActionCaller = "person" | "agent" | "applet" | "automation";
|
|
270
|
+
/** Who may run it without a click: "manual" = only a person; "ask" = proposed first; "auto" = runs. */
|
|
271
|
+
type ActionPolicy = "ask" | "auto" | "manual";
|
|
272
|
+
interface ActionContext {
|
|
273
|
+
runId: string;
|
|
274
|
+
by: ActionCaller;
|
|
275
|
+
viewerId: string | null;
|
|
276
|
+
surfaceName?: string;
|
|
277
|
+
policy?: ActionPolicy;
|
|
278
|
+
}
|
|
279
|
+
/** The system's own sentence, never thrown into a UI. Superset of RecordsError (CONTRACTS §0 `AppletError`). */
|
|
280
|
+
interface ActionError {
|
|
281
|
+
code: string;
|
|
282
|
+
message: string;
|
|
283
|
+
retryable: boolean;
|
|
284
|
+
diagnostic?: string;
|
|
285
|
+
}
|
|
286
|
+
/** CONTRACTS §0 `Result<T>`. */
|
|
287
|
+
type ActionResult<T = unknown> = {
|
|
288
|
+
ok: true;
|
|
289
|
+
data: T;
|
|
290
|
+
} | {
|
|
291
|
+
ok: false;
|
|
292
|
+
error: ActionError;
|
|
293
|
+
};
|
|
294
|
+
/** `POST /actions/run` (aidream) — the request. */
|
|
295
|
+
interface ServerActionRunRequest {
|
|
296
|
+
name: string;
|
|
297
|
+
input: Json$1;
|
|
298
|
+
by: ActionCaller;
|
|
299
|
+
surface_name?: string;
|
|
300
|
+
policy?: ActionPolicy;
|
|
301
|
+
}
|
|
302
|
+
/** `POST /actions/run` (aidream) — the response. */
|
|
303
|
+
interface ServerActionRunResponse {
|
|
304
|
+
status: "applied" | "proposed" | "refused";
|
|
305
|
+
message: string;
|
|
306
|
+
receipts: Json$1[];
|
|
307
|
+
proposal?: Json$1;
|
|
308
|
+
}
|
|
309
|
+
/** A mandate run request: by alias (an Action's `target`) or by key. */
|
|
310
|
+
type MandateRunRequest = ({
|
|
311
|
+
alias: string;
|
|
312
|
+
key?: never;
|
|
313
|
+
} | {
|
|
314
|
+
key: string;
|
|
315
|
+
alias?: never;
|
|
316
|
+
}) & {
|
|
317
|
+
variables: Record<string, Json$1>;
|
|
318
|
+
userInput?: string;
|
|
319
|
+
by: ActionCaller;
|
|
320
|
+
policy: ActionPolicy;
|
|
321
|
+
};
|
|
322
|
+
|
|
254
323
|
/**
|
|
255
324
|
* `@ai-matrx/alchemy/ports` — the host ports (Matrx Alchemy CONTRACT §2.2).
|
|
256
325
|
*
|
|
@@ -299,6 +368,12 @@ interface ClickTarget {
|
|
|
299
368
|
* to an overlay carrying the session as data)
|
|
300
369
|
* transferKnobs absent → no organization default recipe; a person's own
|
|
301
370
|
* default (persistence) or the package's Full applies
|
|
371
|
+
* serverActions absent → `runs: "server"` Actions refuse with "not available here"
|
|
372
|
+
* mandates absent → `runs: "mandate"` Actions refuse the same way
|
|
373
|
+
* pageActions absent → `runs: "page"` Actions refuse the same way
|
|
374
|
+
* approvals absent → a policy "ask" Action started by an agent, applet or automation is refused
|
|
375
|
+
* ("needs a person's approval"); a person's own click is the approval
|
|
376
|
+
* (`runs: "navigate"` goes through `overlay.navigate`; overlay absent → refused)
|
|
302
377
|
*
|
|
303
378
|
* Types only: this entry has no runtime code.
|
|
304
379
|
*/
|
|
@@ -444,6 +519,36 @@ interface AlchemyHostPorts {
|
|
|
444
519
|
window?: WindowPort;
|
|
445
520
|
/** Organization default recipes, resolved by the host's Feature Knob ladder (platform → organization). */
|
|
446
521
|
transferKnobs?: TransferKnobsPort;
|
|
522
|
+
/** aidream `POST /actions/run`: a registered server action by name, as the caller, under the apply-policy cascade. */
|
|
523
|
+
serverActions?: ServerActionPort;
|
|
524
|
+
/** Runs a mandate by alias or key (the host binds `@ai-matrx/agents`; alchemy never imports it). */
|
|
525
|
+
mandates?: MandatePort;
|
|
526
|
+
/** The page's own handlers for `runs: "page"` Actions (in an applet frame: routed as `{ action, input, runId }`). */
|
|
527
|
+
pageActions?: PageActionPort;
|
|
528
|
+
/** Asks a person, in place, to approve an `ask` Action that an agent, applet or automation started. */
|
|
529
|
+
approvals?: ApprovalPort;
|
|
530
|
+
}
|
|
531
|
+
interface ServerActionPort {
|
|
532
|
+
run(request: ServerActionRunRequest): Promise<ServerActionRunResponse>;
|
|
533
|
+
}
|
|
534
|
+
interface MandatePort {
|
|
535
|
+
/** Resolves with the run's result (a kind envelope or JSON); rejects with the system's sentence. */
|
|
536
|
+
run(request: MandateRunRequest): Promise<unknown>;
|
|
537
|
+
}
|
|
538
|
+
interface ApprovalRequest {
|
|
539
|
+
action: string;
|
|
540
|
+
label: string;
|
|
541
|
+
description: string;
|
|
542
|
+
input: Json;
|
|
543
|
+
by: "agent" | "applet" | "automation";
|
|
544
|
+
surfaceName: string;
|
|
545
|
+
}
|
|
546
|
+
interface ApprovalPort {
|
|
547
|
+
/** Resolves true when the person approves; false when they decline or dismiss. */
|
|
548
|
+
ask(request: ApprovalRequest): Promise<boolean>;
|
|
549
|
+
}
|
|
550
|
+
interface PageActionPort {
|
|
551
|
+
dispatch(name: string, input: unknown, context: ActionContext): Promise<ActionResult<unknown>>;
|
|
447
552
|
}
|
|
448
553
|
/**
|
|
449
554
|
* Why a port and not `OverlayHostPort`: an overlay's `data` is `Json`, and a live preparation
|
|
@@ -597,8 +702,10 @@ type Eligibility = {
|
|
|
597
702
|
status: "unavailable";
|
|
598
703
|
sentence: string;
|
|
599
704
|
};
|
|
600
|
-
/** rich-document's ActionCategory, unchanged, plus the three the context menu groups by. */
|
|
601
|
-
type ActionCategory = "feedback" | "copy" | "export" | "save" | "edit" | "share" | "creator" | "app" | "listen" | "study" | "ask" | "ai" | "admin" | "clipboard" | "history" | "surface-info"
|
|
705
|
+
/** rich-document's ActionCategory, unchanged, plus the three the context menu groups by, plus "applet" (surface Actions). */
|
|
706
|
+
type ActionCategory = "feedback" | "copy" | "export" | "save" | "edit" | "share" | "creator" | "app" | "listen" | "study" | "ask" | "ai" | "admin" | "clipboard" | "history" | "surface-info"
|
|
707
|
+
/** Surface Actions (Applets CONTRACTS §6): the default category of an `ActionDeclaration`. */
|
|
708
|
+
| "applet";
|
|
602
709
|
/**
|
|
603
710
|
* An optional named section inside the action's group (a grid's cell / row /
|
|
604
711
|
* column). `primary` marks the thing the person clicked: every layout renders
|
|
@@ -866,6 +973,16 @@ declare namespace __sheet {
|
|
|
866
973
|
export { __sheet_ActionSheet as ActionSheet, type __sheet_ActionSheetProps as ActionSheetProps, ActionSheet as default, __sheet_sheetHeading as sheetHeading };
|
|
867
974
|
}
|
|
868
975
|
|
|
976
|
+
/**
|
|
977
|
+
* Menu size — "standard" (the original 288 px menu) or "large": the Google Docs / Sheets class of
|
|
978
|
+
* menu for a feature-heavy app (Arman, 2026-10-02: "our menu is too small… the one place where we
|
|
979
|
+
* have essentially unlimited space, we're suddenly cheap about it"). Measured on Google Sheets:
|
|
980
|
+
* 322 px wide, 32 px rows, 14 px text, 18 px icons. Large goes one step past it: 360 px, 36 px rows,
|
|
981
|
+
* 15 px text. A context, so submenus (portalled) draw at the same size as the menu they open from.
|
|
982
|
+
*/
|
|
983
|
+
|
|
984
|
+
type MenuSize = "standard" | "large";
|
|
985
|
+
|
|
869
986
|
/**
|
|
870
987
|
* `@ai-matrx/alchemy/react/menu` — the right-click (context) layout, T1.
|
|
871
988
|
* Reached only through the T0 shell's dynamic import (`/react/host`); it
|
|
@@ -890,8 +1007,12 @@ interface ContextMenuPanelProps extends MenuEngineOptions {
|
|
|
890
1007
|
* one "<subject> ▸" submenu (`foldUnderSubject`). Omit for a normal menu.
|
|
891
1008
|
*/
|
|
892
1009
|
subjectFold?: string;
|
|
1010
|
+
/** "large": the 360 px, 36 px-row menu (`menu-size.tsx`). Default "standard". */
|
|
1011
|
+
size?: MenuSize;
|
|
1012
|
+
/** Draw no header line ("Row: …", "Table: …"): the menu starts at its icons. */
|
|
1013
|
+
hideHeader?: boolean;
|
|
893
1014
|
}
|
|
894
|
-
declare function ContextMenuPanel({ target, point, open, onOpenChange, arrangement, density, subjectFold, ...options }: ContextMenuPanelProps): React.ReactElement;
|
|
1015
|
+
declare function ContextMenuPanel({ target, point, open, onOpenChange, arrangement, density, subjectFold, size, hideHeader, ...options }: ContextMenuPanelProps): React.ReactElement;
|
|
895
1016
|
|
|
896
1017
|
declare const __menu_ContextMenuPanel: typeof ContextMenuPanel;
|
|
897
1018
|
type __menu_ContextMenuPanelProps = ContextMenuPanelProps;
|
package/dist/react-menu.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
"use strict";var __create=Object.create;var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __getProtoOf=Object.getPrototypeOf,__hasOwnProp=Object.prototype.hasOwnProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:!0})},__copyProps=(to,from,except,desc)=>{if(from&&typeof from=="object"||typeof from=="function")for(let key of __getOwnPropNames(from))!__hasOwnProp.call(to,key)&&key!==except&&__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable});return to};var __toESM=(mod,isNodeMode,target)=>(target=mod!=null?__create(__getProtoOf(mod)):{},__copyProps(isNodeMode||!mod||!mod.__esModule?__defProp(target,"default",{value:mod,enumerable:!0}):target,mod)),__toCommonJS=mod=>__copyProps(__defProp({},"__esModule",{value:!0}),mod);var react_menu_exports={};__export(react_menu_exports,{ContextMenuPanel:()=>ContextMenuPanel});module.exports=__toCommonJS(react_menu_exports);var React5=__toESM(require("react"),1),import_react_dom=require("react-dom"),import_design_system2=require("@ai-matrx/design-system");function sectionLabel(section){return section.label??null}function isLeaf(node){return node.kind==="item"||node.kind==="checkbox"||node.kind==="link"}function fold(section){return{kind:"submenu",id:`${section.id}:fold`,label:section.label,...section.icon!==void 0?{icon:section.icon}:{},children:section.nodes}}function rowCount(nodes){return nodes.filter(n=>n.kind!=="separator"&&n.kind!=="label").length}function stripOf(model){let clipboard=model.sections.find(s=>s.group==="clipboard"&&!s.primary);return clipboard?clipboard.nodes.filter(isLeaf):[]}function clipboardRest(model){let clipboard=model.sections.find(s=>s.group==="clipboard"&&!s.primary);return clipboard?clipboard.nodes.filter(n=>!isLeaf(n)&&n.kind==="submenu"):[]}function classic(model){return{strip:[],sections:model.sections,filterable:!1}}function tiered(model,filterable){let strip=stripOf(model),sections=[],rest=clipboardRest(model);for(let s of model.sections){if(s.group==="clipboard"&&!s.primary){rest.length&§ions.push({...s,nodes:rest});continue}if(s.primary){sections.push(s);continue}if(!s.label||s.group==="surface-info"||rowCount(s.nodes)<=3){sections.push(s);continue}sections.push({id:s.id,group:s.group,nodes:[fold({...s,label:s.label})]})}return{strip,sections,filterable}}function context(model,arrangement){return arrangement==="classic"?classic(model):tiered(model,arrangement==="command")}function foldUnderSubject(arranged,subject){let label=subject.trim(),primary=arranged.sections.filter(s=>s.primary),rest=arranged.sections.filter(s=>!s.primary);if(!label||primary.length===0||rest.length===0&&arranged.strip.length===0)return arranged;let children=[];arranged.strip.length&&children.push(...arranged.strip);for(let s of rest)rowCount(s.nodes)!==0&&(children.length&&children.push({kind:"separator",id:`${s.id}:subject-sep`}),s.label&&children.push({kind:"label",id:`${s.id}:subject-label`,label:s.label}),children.push(...s.nodes));return rowCount(children)===0?{...arranged,strip:[]}:{strip:[],filterable:!1,sections:[...primary,{id:"subject",group:rest[0]?.group??primary[0].group,nodes:[{kind:"submenu",id:"subject:fold",label,children}]}]}}function palette(model){let leaves=[],walk=(nodes,trail)=>{for(let n of nodes)isLeaf(n)?leaves.push({node:n,breadcrumb:trail}):n.kind==="submenu"&&(n.lazy?leaves.push({node:n,breadcrumb:trail}):walk(n.children,[...trail,n.label]))};for(let s of model.sections)walk(s.nodes,s.label?[s.label]:[]);return{leaves}}function lazySubmenuIds(model){if(!model)return[];let out=[],walk=nodes=>{for(let n of nodes)n.kind==="submenu"&&(n.lazy?n.loading||out.push(n.id):walk(n.children))};for(let s of model.sections)walk(s.nodes);return out}function paletteStillOpening(model){if(!model)return!0;let walk=nodes=>nodes.some(n=>n.kind==="submenu"&&(n.lazy||n.loading||n.pending||walk(n.children)));return model.sections.some(s=>walk(s.nodes))}function filterPalette(arranged,query){let words=query.toLowerCase().split(/\s+/).filter(Boolean);return words.length?{leaves:arranged.leaves.filter(l=>{let hay=`${l.node.label} ${l.breadcrumb.join(" ")}`.toLowerCase();return words.every(w=>hay.includes(w))})}:arranged}var React2=__toESM(require("react"),1);var DEFAULT_SENSITIVITY=Object.freeze({exportable:!0,classification:"ordinary",includedByDefault:!0});function resolveSensitivity(value){return{exportable:value.sensitivity?.exportable??DEFAULT_SENSITIVITY.exportable,classification:value.sensitivity?.classification??DEFAULT_SENSITIVITY.classification,includedByDefault:value.sensitivity?.includedByDefault??DEFAULT_SENSITIVITY.includedByDefault}}function toJson(value){if(!(value===void 0||typeof value=="function"||typeof value=="symbol")){if(value===null||typeof value=="string"||typeof value=="boolean")return value;if(typeof value=="number")return Number.isFinite(value)?value:null;if(typeof value=="bigint")return value.toString();if(value instanceof Date)return value.toISOString();if(Array.isArray(value))return value.map(v=>toJson(v)??null);if(typeof value=="object"){let out={};for(let[k,v]of Object.entries(value)){let j=toJson(v);j!==void 0&&(out[k]=j)}return out}}}function projectValues(raw,declared,pathPrefix=""){let byName=new Map(declared.map(d=>[d.name,d])),values={},omissions=[];for(let[name,value]of Object.entries(raw)){let path=pathPrefix?`${pathPrefix}.${name}`:name,decl=byName.get(name);if(!decl){omissions.push({path,reason:"filtered"});continue}let sensitivity=resolveSensitivity(decl);if(sensitivity.classification!=="ordinary"){omissions.push({path,reason:"excluded",classification:sensitivity.classification});continue}if(!sensitivity.exportable){omissions.push({path,reason:"excluded"});continue}let json=toJson(value);json!==void 0&&(values[name]=json)}return{values,omissions}}function createProjectedReads(source){return{async values(signal){if(!source.surface||!source.declaration)return{values:{},omissions:[]};let raw=await source.surface.readValues(signal),screenValues=source.declaration.values;return projectValues(raw,screenValues)},async item(signal){let item=source.item;if(!item||!source.declaration)return null;let type=source.declaration.itemTypes?.find(t=>t.name===item.itemType);if(!type)return{values:{},omissions:[{path:item.itemType,reason:"filtered"}]};let raw=await item.readValues(signal);return projectValues(raw,type.values,item.itemType)},async live(signal){return source.surface?.readLive?source.surface.readLive(signal):{}}}}async function runAction(action,target,options){let{ports}=options;if(action.requiresAuth&&!target.auth.authenticated)return ports.auth?(ports.auth.signInThenResume({actionId:action.id,contentFingerprint:options.contentFingerprint??action.id}),{status:"auth-pending"}):(ports.diagnostics.capture(new Error(`requiresAuth action "${action.id}" ran signed out with no auth port`),{area:"actions",detail:{actionId:action.id}}),{status:"failed",error:new Error("sign-in unavailable")});let reads=createProjectedReads(options.source??{surface:null,declaration:target.declaration,item:null}),signal=options.signal??new AbortController().signal;try{return{status:"ran",outcome:await action.run(target,{reads,ports,signal})}}catch(error){ports.diagnostics.capture(error,{area:"actions",detail:{actionId:action.id,stage:"run"}});let label=typeof action.label=="string"?action.label:action.id;return ports.notify?.error(`${label} did not finish.`,"Try again; if it keeps failing, report it from the feedback button."),{status:"failed",error}}}var APPROVED_HEADINGS=new Set(["Save","Copy as","Export","Edit","Creator tools","Admin","App","Compare","History"]),CONTAINER_WORD=/^(more|more…|more\.\.\.|other|others|misc|miscellaneous|additional|extra|extras|actions|options|advanced|stuff|everything else)$/i,TARGET_SHAPE=/^(Cell|Row|Column|Table|Range|Selection|Record) · .+$/;function isContainerWord(label){return CONTAINER_WORD.test(label.trim())}function isApprovedHeading(label,kind="group",approved=APPROVED_HEADINGS){let l=label.trim();return!l||isContainerWord(l)?!1:approved.has(l)?!0:kind==="target"||TARGET_SHAPE.test(l)}function defaultHeadingPolicy(){return globalThis.process?.env?.NODE_ENV==="production"?"inline":"throw"}var UnapprovedHeadingError=class extends Error{heading;constructor(heading,where){super(`Menu heading "${heading}" (${where}) is not an approved heading. Remedy: show these rows inline \u2014 declare no section (or kind "target" for the clicked thing's own label) \u2014 or ask Arman to add the name to APPROVED_HEADINGS in @ai-matrx/alchemy/menu. A generic container word ("More\u2026", "Other") is never approved.`),this.name="UnapprovedHeadingError",this.heading=heading}};var CATEGORY_GROUP={clipboard:"clipboard",copy:"transfer",export:"transfer",save:"document",share:"document",edit:"editable",history:"history",ai:"ai",ask:"ai",listen:"tools",study:"tools",app:"tools",feedback:"quick",creator:"admin",admin:"admin","surface-info":"surface-info"},GROUP_ORDER=["clipboard","editable","transfer","document","history","ai","tools","quick","surface","admin","surface-info"],CATEGORY_ORDER=["clipboard","edit","copy","export","save","share","history","ask","ai","listen","study","app","feedback","creator","admin","surface-info"];function translate(i18n,key,fallback){if(!i18n)return fallback;try{return i18n.t(key,fallback)}catch{return fallback}}function actionToNode(resolved,target,options={}){let{action,eligibility}=resolved,rawLabel=typeof action.label=="function"?action.label(target):action.label,label=translate(options.i18n,action.labelKey??action.id,rawLabel),base={id:action.id,actionId:action.id,...action.icon!==void 0?{icon:action.icon}:{},...action.placement!==void 0?{placement:action.placement}:{}};if(action.expand)return{...base,kind:"submenu",label,lazy:!0,loading:!1,...action.pending?.(target)?{pending:!0}:{},children:[],...action.emptyLabel!==void 0?{emptyLabel:action.emptyLabel}:{}};if(action.href!==void 0){let href=typeof action.href=="function"?action.href(target):action.href;return{...base,kind:"link",label,href}}if(action.toggle)return{...base,kind:"checkbox",label,checked:action.pressed?.(target)??!1,...action.description!==void 0?{description:action.description}:{}};let state=action.stateIcon?.(target)??null,pressed=action.pressed?.(target),hint=action.hint!==void 0?translate(options.i18n,action.hintKey??`${action.id}.hint`,action.hint):void 0;return{...base,kind:"item",label,...action.iconTone!==void 0?{iconTone:action.iconTone}:{},...state?{stateIcon:state}:{},...action.description!==void 0?{description:action.description}:{},...hint!==void 0?{hint}:{},...pressed!==void 0?{pressed}:{},...action.destructive?{destructive:!0}:{},...action.preserveSelection?{preserveSelection:!0}:{},...action.keepsMenuOpen?{keepsMenuOpen:!0}:{},...eligibility.status==="unavailable-verb"||eligibility.status==="unavailable"?{unavailable:{sentence:eligibility.sentence}}:{}}}function buildMenuModel(target,resolved,options={}){let policy=options.headingPolicy??defaultHeadingPolicy();resolved=resolved.map(r=>{let sec=r.action.section;if(r.action.expand&&isContainerWord(typeof r.action.label=="string"?r.action.label:"")&&policy==="throw")throw new UnapprovedHeadingError(r.action.label,`submenu of ${r.action.id}`);if(!sec)return r;let kind=sec.kind??(sec.primary?"target":"group");if(isApprovedHeading(sec.label,kind))return r;if(policy==="throw")throw new UnapprovedHeadingError(sec.label,`section of ${r.action.id}`);let{section:_dropped,...rest}=r.action;return{...r,action:rest}});let ordered=resolved.map((r,index)=>({r,index})).sort((a,b)=>{let ca=CATEGORY_ORDER.indexOf(a.r.action.category),cb=CATEGORY_ORDER.indexOf(b.r.action.category);if(ca!==cb)return ca-cb;let oa=a.r.action.order??0,ob=b.r.action.order??0;return oa!==ob?oa-ob:a.index-b.index}).map(x=>x.r),sections=new Map,roles={},explicit=new Map;resolved.forEach((r,index)=>{let sec=r.action.section;if(!sec)return;let entry=explicit.get(sec.id)??{group:CATEGORY_GROUP[r.action.category],rows:[]};entry.rows.push({r,index}),explicit.set(sec.id,entry)});let placed=new Set;for(let r of ordered){let sec=r.action.section;if(sec&&placed.has(sec.id))continue;let group=sec?explicit.get(sec.id)?.group??CATEGORY_GROUP[r.action.category]:CATEGORY_GROUP[r.action.category],sectionId=sec?`section:${sec.id}`:group,section=sections.get(sectionId);section||(section={id:sectionId,group,nodes:[],...sec?{label:translate(options.i18n,sec.labelKey??`section.${sec.id}`,sec.label)}:{},...sec?.icon!==void 0?{icon:sec.icon}:{},...sec?.primary?{primary:!0}:{},...sec&&(sec.kind??(sec.primary?"target":"group"))==="target"?{target:!0}:{}},sections.set(sectionId,section));let rows=sec?(explicit.get(sec.id)?.rows??[]).sort((x,y)=>(x.r.action.order??0)-(y.r.action.order??0)||x.index-y.index).map(x=>x.r):[r];sec&&placed.add(sec.id);for(let row of rows)row.action.startsGroup&§ion.nodes.length>0&§ion.nodes.push({kind:"separator",id:`${row.action.id}:group`}),section.nodes.push(actionToNode(row,target,options)),row.action.verb&&(roles[row.action.verb]=row.action.id)}let list=[...sections.values()].sort((a,b)=>!!a.primary!=!!b.primary?a.primary?-1:1:GROUP_ORDER.indexOf(a.group)-GROUP_ORDER.indexOf(b.group)),selected=target.selection?.text?.trim(),content=options.content?.trim(),fieldName=options.contentLabel?.trim();return{header:selected?{label:"Selected",text:target.selection?.text??""}:fieldName?{label:fieldName,text:options.content??""}:content?{label:"Content",text:options.content??""}:null,sections:list,roles}}function withGroupDividers(children,nodes){let out=[];return children.forEach((child,i)=>{let node=nodes[i];node&&(i>0&&(child.startsGroup||(children[i-1].section?.id??null)!==(child.section?.id??null))&&out.push({kind:"separator",id:`${child.id}:group`}),out.push(node))}),out}function withExpandedChildren(model,nodeId,children){let visit=nodes=>nodes.map(n=>n.kind!=="submenu"?n:n.id===nodeId?children==="loading"?{...n,loading:!0}:{...n,lazy:!1,loading:!1,pending:!1,children}:{...n,children:visit(n.children)});return{...model,sections:model.sections.map(s=>({...s,nodes:visit(s.nodes)}))}}function findNode(nodes,id){for(let n of nodes){if(n.id===id)return n;if(n.kind==="submenu"){let hit=findNode(n.children,id);if(hit)return hit}}return null}var React=__toESM(require("react"),1),KEY=Symbol.for("ai-matrx.alchemy.actions-context"),AlchemyActionsContext=globalThis[KEY]??=React.createContext(null);function useAlchemyActions(){let value=React.useContext(AlchemyActionsContext);if(!value)throw new Error("Alchemy actions: render inside <AlchemyActionsProvider> (@ai-matrx/alchemy/react/host).");return value}function isLatestExpansion(capturedTargetEpoch,currentTargetEpoch,capturedNodeSequence,currentNodeSequence){return capturedTargetEpoch===currentTargetEpoch&&capturedNodeSequence===currentNodeSequence}var import_jsx_runtime=require("react/jsx-runtime");function nodeInModel(model,id){for(let s of model.sections){let hit=findNode(s.nodes,id);if(hit)return hit}return null}function hasLoadedRows(model,id){let n=nodeInModel(model,id);return!!(n&&n.kind==="submenu"&&!n.lazy&&!n.loading)}function loadedChildren(model,id){let n=nodeInModel(model,id);return n&&n.kind==="submenu"&&!n.lazy?n.children:[]}function carryOpened(prev,next,opened){return next.map(n=>{if(n.kind!=="submenu")return n;let old=prev.find(o=>o.id===n.id);return!old||old.kind!=="submenu"||old.lazy?n:n.lazy?opened.has(n.id)?{...n,lazy:!1,loading:!1,pending:!1,children:old.children}:n:{...n,children:carryOpened(old.children,n.children,opened)}})}function carryOpenedModel(prev,next,opened){if(opened.size===0)return next;let prevNodes=prev.sections.flatMap(s=>s.nodes);return{...next,sections:next.sections.map(s=>({...s,nodes:carryOpened(prevNodes,s.nodes,opened)}))}}function useMenuEngine(target,options={}){let{registry,ports}=useAlchemyActions(),[resolved,setResolved]=React2.useState([]),[model,setModel]=React2.useState(null),[tick,setTick]=React2.useState(0),expanded=React2.useRef(new Map),opened=React2.useRef(new Set),expandSeq=React2.useRef(new Map),targetEpoch=React2.useRef(0),currentTarget=React2.useRef(target);currentTarget.current!==target&&(currentTarget.current=target,targetEpoch.current+=1);let active=options.active??!0,optionsRef=React2.useRef(options);optionsRef.current=options,React2.useEffect(()=>registry.subscribe(()=>setTick(t=>t+1)),[registry]);let expandAction=React2.useCallback(async(action,nodeId)=>{if(!target||!action.expand)return;let epoch=targetEpoch.current,seq=(expandSeq.current.get(nodeId)??0)+1;expandSeq.current.set(nodeId,seq);let latest=()=>isLatestExpansion(epoch,targetEpoch.current,seq,expandSeq.current.get(nodeId));setModel(m=>m&&!hasLoadedRows(m,nodeId)?withExpandedChildren(m,nodeId,"loading"):m);try{let children=await action.expand(target,new AbortController().signal);if(!latest())return;let nodes=withGroupDividers(children,children.map(child=>(expanded.current.set(child.id,child),actionToNode({action:child,eligibility:{status:"available"}},target,ports.i18n?{i18n:ports.i18n}:{}))));setModel(m=>m&&withExpandedChildren(m,nodeId,carryOpened(loadedChildren(m,nodeId),nodes,opened.current)));for(let child of children)child.expand&&opened.current.has(child.id)&&expandAction(child,child.id)}catch(error){if(!latest())return;ports.diagnostics.capture(error,{area:"menu",detail:{nodeId,stage:"expand"}}),setModel(m=>m&&withExpandedChildren(m,nodeId,[]))}},[target,ports]);React2.useEffect(()=>{expanded.current.clear(),opened.current.clear()},[target]),React2.useEffect(()=>{if(!target||!active)return;let live=!0;return registry.resolve(target,optionsRef.current.restrict).then(list=>{if(!live)return;setResolved(list);let built=buildMenuModel(target,list,{...ports.i18n?{i18n:ports.i18n}:{},content:optionsRef.current.content??null,contentLabel:optionsRef.current.contentLabel??null});setModel(prev=>prev?carryOpenedModel(prev,built,opened.current):built);for(let{action}of list)opened.current.has(action.id)&&action.expand&&expandAction(action,action.id)}),()=>{live=!1}},[registry,ports,target,active,tick,options.revision,expandAction]);let resolvedRef=React2.useRef(resolved);resolvedRef.current=resolved;let subscribedIds=resolved.map(r=>r.action.id).join(`
|
|
3
|
-
`);React2.useEffect(()=>{if(!target)return;let subscribing=!0,onChange=()=>{subscribing||setTick(t=>t+1)},offs=resolvedRef.current.map(r=>r.action.subscribe?.(onChange,target)).filter(off=>typeof off=="function");return subscribing=!1,()=>offs.forEach(off=>off())},[subscribedIds,target]);let findAction=React2.useCallback(id=>resolved.find(r=>r.action.id===id)?.action??expanded.current.get(id)??void 0,[resolved]),run=React2.useCallback(async nodeId=>{if(!target||!model)return null;let node=model.sections.map(s=>findNode(s.nodes,nodeId)).find(Boolean)??null,action=findAction(node&&"actionId"in node&&node.actionId?node.actionId:nodeId);if(!action)return null;let o=optionsRef.current,result=await runAction(action,target,{ports,...o.source?{source:o.source}:{},...o.contentFingerprint?{contentFingerprint:o.contentFingerprint}:{}});return o.onRan?.(nodeId,result,{keepOpen:!!action.keepsMenuOpen}),result},[target,model,findAction,ports]),expand=React2.useCallback(async nodeId=>{let action=findAction(nodeId);!target||!action?.expand||(opened.current.add(nodeId),await expandAction(action,nodeId))},[findAction,target,expandAction]),icon=React2.useCallback((key,tone)=>{if(!key||!ports.icons)return null;let Resolved=ports.icons.resolve(key);return Resolved?(0,import_jsx_runtime.jsx)(Resolved,{className:`h-4 w-4 shrink-0 ${tone??""}`,"aria-hidden":!0}):null},[ports.icons]),explain=React2.useCallback(sentence=>{ports.notify?ports.notify.info(sentence):ports.diagnostics.capture(new Error(`No notify port to explain: ${sentence}`),{area:"menu",detail:{sentence}})},[ports]);return{model,resolved,run,expand,icon,explain}}var React3=__toESM(require("react"),1),import_design_system=require("@ai-matrx/design-system");var import_jsx_runtime2=require("react/jsx-runtime");function NodeList({nodes,engine}){return(0,import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment,{children:nodes.map(node=>(0,import_jsx_runtime2.jsx)(MenuNodeView,{node,engine},node.id))})}function SectionList({sections,engine}){return(0,import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment,{children:sections.map((section,index)=>(0,import_jsx_runtime2.jsxs)(React3.Fragment,{children:[index>0?(0,import_jsx_runtime2.jsx)(import_design_system.DropdownMenuSeparator,{}):null,sectionLabel(section)?(0,import_jsx_runtime2.jsx)(import_design_system.DropdownMenuLabel,{className:"text-xs font-medium text-muted-foreground",children:sectionLabel(section)}):null,(0,import_jsx_runtime2.jsx)(NodeList,{nodes:section.nodes,engine})]},section.id))})}function iconOf(node,engine){if(node.kind!=="item")return"icon"in node?engine.icon(node.icon):null;if(node.stateIcon){let glyph=engine.icon(node.stateIcon.icon);return node.stateIcon.spin?(0,import_jsx_runtime2.jsx)("span",{className:"inline-flex animate-spin",children:glyph}):glyph}if(!("icon"in node))return null;let tone=node.pressed===!1?void 0:node.iconTone;return engine.icon(node.icon,tone)}function MenuNodeView({node,engine}){switch(node.kind){case"separator":return(0,import_jsx_runtime2.jsx)(import_design_system.DropdownMenuSeparator,{});case"label":return(0,import_jsx_runtime2.jsx)(import_design_system.DropdownMenuLabel,{className:"text-xs font-medium text-muted-foreground",children:node.label});case"submenu":return(0,import_jsx_runtime2.jsx)(SubmenuView,{node,engine});case"checkbox":return(0,import_jsx_runtime2.jsxs)(import_design_system.DropdownMenuCheckboxItem,{"data-alchemy-node":node.id,checked:node.checked,onSelect:()=>{engine.run(node.id)},className:"gap-2",children:[iconOf(node,engine),(0,import_jsx_runtime2.jsx)("span",{className:"truncate",children:node.label})]});case"link":return(0,import_jsx_runtime2.jsx)(import_design_system.DropdownMenuItem,{asChild:!0,"data-alchemy-node":node.id,children:(0,import_jsx_runtime2.jsxs)("a",{href:node.href,target:node.target,className:"gap-2",children:[iconOf(node,engine),(0,import_jsx_runtime2.jsx)("span",{className:"truncate",children:node.label})]})});case"item":return(0,import_jsx_runtime2.jsx)(LeafItem,{node,engine})}}function SubmenuView({node,engine}){let triggerRef=React3.useRef(null);return(0,import_jsx_runtime2.jsxs)(import_design_system.DropdownMenuSub,{onOpenChange:open=>{open&&node.lazy&&!node.loading&&engine.expand(node.id)},children:[(0,import_jsx_runtime2.jsxs)(import_design_system.DropdownMenuSubTrigger,{ref:triggerRef,"data-alchemy-node":node.id,className:"gap-2","aria-busy":node.pending?!0:void 0,children:[iconOf(node,engine),(0,import_jsx_runtime2.jsx)("span",{className:"truncate",children:node.label}),node.pending?(0,import_jsx_runtime2.jsx)("span",{className:"ml-auto text-xs text-muted-foreground",children:"Loading\u2026"}):null]}),(0,import_jsx_runtime2.jsx)(import_design_system.DropdownMenuSubContent,{"data-alchemy-submenu":node.id,onFocusOutside:event=>{let to=event.target,trigger=triggerRef.current;to instanceof Element&&trigger&&to.getAttribute("role")==="menu"&&to.contains(trigger)&&event.preventDefault()},className:"w-72 max-w-[calc(100vw-1rem)] max-h-[var(--radix-dropdown-menu-content-available-height)] overflow-y-auto",children:node.loading?(0,import_jsx_runtime2.jsx)(import_design_system.DropdownMenuLabel,{className:"text-xs text-muted-foreground",children:"Loading\u2026"}):node.children.length===0&&!node.lazy?(0,import_jsx_runtime2.jsx)(import_design_system.DropdownMenuLabel,{className:"text-xs text-muted-foreground",children:node.emptyLabel??"Nothing here yet"}):(0,import_jsx_runtime2.jsx)(NodeList,{nodes:node.children,engine})})]})}function LeafItem({node,engine}){let row=(0,import_jsx_runtime2.jsxs)(import_design_system.DropdownMenuItem,{"data-alchemy-node":node.id,"aria-disabled":node.unavailable?!0:void 0,"aria-pressed":node.pressed,onSelect:event=>{if(node.unavailable){event.preventDefault();return}node.keepsMenuOpen&&event.preventDefault(),engine.run(node.id)},className:`gap-2 ${node.unavailable?"opacity-50":""} ${node.destructive?"text-destructive":""}`,children:[iconOf(node,engine),(0,import_jsx_runtime2.jsxs)("span",{className:"flex min-w-0 flex-1 flex-col",children:[(0,import_jsx_runtime2.jsx)("span",{className:"truncate",children:node.label}),node.description?(0,import_jsx_runtime2.jsx)("span",{className:"truncate text-xs text-muted-foreground",children:node.description}):null]}),node.hint?(0,import_jsx_runtime2.jsx)("span",{className:"ml-auto text-xs text-muted-foreground",children:node.hint}):null]});return node.unavailable?(0,import_jsx_runtime2.jsxs)(import_design_system.Tooltip,{children:[(0,import_jsx_runtime2.jsx)(import_design_system.TooltipTrigger,{asChild:!0,children:row}),(0,import_jsx_runtime2.jsx)(import_design_system.TooltipContent,{children:node.unavailable.sentence})]}):row}function LeafButton({node,engine,showLabel}){if(node.kind!=="item"&&node.kind!=="checkbox"&&node.kind!=="link")return null;let unavailable=node.kind==="item"?node.unavailable:void 0,pressed=node.kind==="item"?node.pressed:node.kind==="checkbox"?node.checked:void 0,glyph=iconOf(node,engine),button=(0,import_jsx_runtime2.jsxs)("button",{type:"button","data-alchemy-node":node.id,"data-matrx-button":"","data-tap-floor":"","data-tap-floor-square":"","aria-label":node.label,"aria-disabled":unavailable?!0:void 0,"aria-pressed":pressed,onMouseDown:e=>{node.kind==="item"&&node.preserveSelection&&e.preventDefault()},onClick:()=>{if(unavailable){engine.explain(unavailable.sentence);return}if(node.kind==="link"){window.location.assign(node.href);return}engine.run(node.id)},className:`inline-flex h-7 min-w-7 pointer-coarse:h-11 pointer-coarse:min-w-11 shrink-0 items-center justify-center gap-1.5 rounded-md px-1.5 text-sm text-muted-foreground hover:bg-accent hover:text-foreground ${unavailable?"cursor-default opacity-50 hover:bg-transparent":""} ${pressed?"text-foreground":""}`,children:[glyph,showLabel||!glyph?(0,import_jsx_runtime2.jsx)("span",{className:"whitespace-nowrap",children:node.label}):null]});return(0,import_jsx_runtime2.jsxs)(import_design_system.Tooltip,{children:[(0,import_jsx_runtime2.jsx)(import_design_system.TooltipTrigger,{asChild:!0,children:button}),(0,import_jsx_runtime2.jsx)(import_design_system.TooltipContent,{children:unavailable?unavailable.sentence:node.label})]})}var NO_LONGER="Nothing here right now.";function kept(node){if(node.kind==="separator"||node.kind==="label")return node;let label="label"in node?node.label:"",icon="icon"in node?node.icon:void 0,sentence=node.kind==="submenu"?node.emptyLabel??NO_LONGER:NO_LONGER;return{kind:"item",id:node.id,label,...icon!==void 0?{icon}:{},unavailable:{sentence}}}var LATE="__arrived_after_open";function isLoading(node){return node.kind==="submenu"&&!!node.pending}function keepSlotsWhileOpen(shown,current){if(!shown)return{sections:current.map(s=>({...s,nodes:[...s.nodes]}))};let now=new Map,nowSection=new Map;for(let section of current){nowSection.set(section.id,section);for(let node of section.nodes)now.set(node.id,node)}let drawn=new Set,sections=[];for(let section of shown.sections){let fresh=nowSection.get(section.id),nodes=[];for(let node of section.nodes){drawn.add(node.id);let live=now.get(node.id);live?nodes.push(live):isLoading(node)||nodes.push(kept(node))}nodes.length===0&§ion.nodes.length>0||sections.push({...fresh??section,nodes})}let late=[];for(let section of current)for(let node of section.nodes)drawn.has(node.id)||late.push(node);if(late.length){let lateSection=sections.find(s=>s.id===LATE);lateSection?lateSection.nodes.push(...late):sections.push({id:LATE,group:sections[sections.length-1]?.group??"more",nodes:late})}return{sections}}var React4=__toESM(require("react"),1);function useSearchOpensLibraries(engine,searching){let{model,expand}=engine;React4.useEffect(()=>{if(searching)for(let id of lazySubmenuIds(model))expand(id)},[searching,model,expand])}var import_jsx_runtime3=require("react/jsx-runtime");function ContextMenuPanel({target,point,open,onOpenChange,arrangement="command",density="comfortable",subjectFold,...options}){let engine=useMenuEngine(target,{...options,onRan:(id,r,ran)=>{options.onRan?.(id,r,ran),ran?.keepOpen||onOpenChange(!1)}}),[query,setQuery]=React5.useState(""),laidOut=engine.model?context(engine.model,arrangement):null,arranged=laidOut&&subjectFold?foldUnderSubject(laidOut,subjectFold):laidOut,slots=React5.useRef({at:"",shown:null}),at=`${point.x},${point.y}`;(!open||slots.current.at!==at)&&(slots.current={at,shown:null});let sections=arranged&&open?(slots.current.shown=keepSlotsWhileOpen(slots.current.shown,arranged.sections)).sections:arranged?.sections??[],filtered=engine.model&&query.trim()?filterPalette(palette(engine.model),query):null;useSearchOpensLibraries(engine,open&&query.trim().length>0);let anchor=(0,import_jsx_runtime3.jsx)(import_design_system2.DropdownMenuTrigger,{asChild:!0,children:(0,import_jsx_runtime3.jsx)("span",{"aria-hidden":!0,"data-alchemy-anchor":"context",style:{position:"fixed",left:point.x,top:point.y,width:0,height:0,pointerEvents:"none"}})});return(0,import_jsx_runtime3.jsxs)(import_design_system2.DropdownMenu,{open,onOpenChange,modal:!1,children:[typeof document>"u"?anchor:(0,import_react_dom.createPortal)(anchor,document.body),(0,import_jsx_runtime3.jsx)(import_design_system2.DropdownMenuContent,{side:"right",align:"start",sideOffset:2,collisionPadding:8,"data-alchemy-layout":`context-${arrangement}`,onPointerUpCapture:event=>{event.button===2&&event.preventDefault()},className:`w-72 max-h-[min(var(--radix-dropdown-menu-content-available-height),32rem)] overflow-y-auto ${density==="compact"?"text-xs":""}`,children:(0,import_jsx_runtime3.jsxs)(import_design_system2.TooltipProvider,{children:[engine.model?.header?(0,import_jsx_runtime3.jsxs)(import_design_system2.DropdownMenuLabel,{className:"truncate text-xs font-normal text-muted-foreground",title:engine.model.header.text,children:[engine.model.header.label,engine.model.header.text.trim()?`: ${engine.model.header.text}`:null]}):null,arranged?(0,import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment,{children:[arranged.strip.length?(0,import_jsx_runtime3.jsx)("div",{role:"toolbar","aria-label":"Clipboard",className:"flex items-center gap-0.5 px-1 py-1",children:arranged.strip.map(node=>(0,import_jsx_runtime3.jsx)(LeafButton,{node,engine,showLabel:!1},node.id))}):null,arranged.filterable?(0,import_jsx_runtime3.jsx)("div",{className:"px-1 pb-1",children:(0,import_jsx_runtime3.jsx)("input",{"aria-label":"Filter actions",placeholder:"Type to filter\u2026",value:query,onChange:e=>setQuery(e.target.value),onKeyDown:e=>{e.stopPropagation(),e.key==="Enter"&&filtered?.leaves[0]&&engine.run(filtered.leaves[0].node.id)},className:"h-7 w-full rounded-md border border-border bg-transparent px-2 text-sm outline-none"})}):null,(arranged.strip.length||arranged.filterable)&§ions.length?(0,import_jsx_runtime3.jsx)(import_design_system2.DropdownMenuSeparator,{}):null,filtered?filtered.leaves.length?filtered.leaves.map(({node,breadcrumb})=>(0,import_jsx_runtime3.jsxs)(import_design_system2.DropdownMenuItem,{"data-alchemy-node":node.id,onSelect:event=>{node.kind==="item"&&node.keepsMenuOpen&&event.preventDefault(),node.kind==="submenu"?engine.expand(node.id):engine.run(node.id)},className:"flex-col items-start gap-0",children:[(0,import_jsx_runtime3.jsx)("span",{children:node.label}),(0,import_jsx_runtime3.jsx)("span",{className:"text-xs text-muted-foreground",children:breadcrumb.join(" \u203A ")})]},node.id)):paletteStillOpening(engine.model)?(0,import_jsx_runtime3.jsx)("div",{className:"px-2 py-1.5 text-xs text-muted-foreground",children:"Searching\u2026"}):(0,import_jsx_runtime3.jsxs)("div",{className:"px-2 py-1.5 text-xs text-muted-foreground",children:["No action matches \u201C",query,"\u201D."]}):(0,import_jsx_runtime3.jsx)(SectionList,{sections,engine})]}):(0,import_jsx_runtime3.jsx)("div",{className:"px-2 py-1.5 text-xs text-muted-foreground",children:"Loading\u2026"})]})})]})}
|
|
2
|
+
"use strict";var __create=Object.create;var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __getProtoOf=Object.getPrototypeOf,__hasOwnProp=Object.prototype.hasOwnProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:!0})},__copyProps=(to,from,except,desc)=>{if(from&&typeof from=="object"||typeof from=="function")for(let key of __getOwnPropNames(from))!__hasOwnProp.call(to,key)&&key!==except&&__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable});return to};var __toESM=(mod,isNodeMode,target)=>(target=mod!=null?__create(__getProtoOf(mod)):{},__copyProps(isNodeMode||!mod||!mod.__esModule?__defProp(target,"default",{value:mod,enumerable:!0}):target,mod)),__toCommonJS=mod=>__copyProps(__defProp({},"__esModule",{value:!0}),mod);var react_menu_exports={};__export(react_menu_exports,{ContextMenuPanel:()=>ContextMenuPanel});module.exports=__toCommonJS(react_menu_exports);var React6=__toESM(require("react"),1),import_react_dom=require("react-dom"),import_design_system2=require("@ai-matrx/design-system");function sectionLabel(section){return section.label??null}function isLeaf(node){return node.kind==="item"||node.kind==="checkbox"||node.kind==="link"}function fold(section){return{kind:"submenu",id:`${section.id}:fold`,label:section.label,...section.icon!==void 0?{icon:section.icon}:{},children:section.nodes}}function rowCount(nodes){return nodes.filter(n=>n.kind!=="separator"&&n.kind!=="label").length}function stripOf(model){let clipboard=model.sections.find(s=>s.group==="clipboard"&&!s.primary);return clipboard?clipboard.nodes.filter(isLeaf):[]}function clipboardRest(model){let clipboard=model.sections.find(s=>s.group==="clipboard"&&!s.primary);return clipboard?clipboard.nodes.filter(n=>!isLeaf(n)&&n.kind==="submenu"):[]}function classic(model){return{strip:[],sections:model.sections,filterable:!1}}function tiered(model,filterable){let strip=stripOf(model),sections=[],rest=clipboardRest(model);for(let s of model.sections){if(s.group==="clipboard"&&!s.primary){rest.length&§ions.push({...s,nodes:rest});continue}if(s.primary){sections.push(s);continue}if(!s.label||s.group==="surface-info"||rowCount(s.nodes)<=3){sections.push(s);continue}sections.push({id:s.id,group:s.group,nodes:[fold({...s,label:s.label})]})}return{strip,sections,filterable}}function context(model,arrangement){return arrangement==="classic"?classic(model):tiered(model,arrangement==="command")}function foldUnderSubject(arranged,subject){let label=subject.trim(),primary=arranged.sections.filter(s=>s.primary),rest=arranged.sections.filter(s=>!s.primary);if(!label||primary.length===0||rest.length===0&&arranged.strip.length===0)return arranged;let children=[];arranged.strip.length&&children.push(...arranged.strip);for(let s of rest)rowCount(s.nodes)!==0&&(children.length&&children.push({kind:"separator",id:`${s.id}:subject-sep`}),s.label&&children.push({kind:"label",id:`${s.id}:subject-label`,label:s.label}),children.push(...s.nodes));return rowCount(children)===0?{...arranged,strip:[]}:{strip:[],filterable:!1,sections:[...primary,{id:"subject",group:rest[0]?.group??primary[0].group,nodes:[{kind:"submenu",id:"subject:fold",label,children}]}]}}function palette(model){let leaves=[],walk=(nodes,trail)=>{for(let n of nodes)isLeaf(n)?leaves.push({node:n,breadcrumb:trail}):n.kind==="submenu"&&(n.lazy?leaves.push({node:n,breadcrumb:trail}):walk(n.children,[...trail,n.label]))};for(let s of model.sections)walk(s.nodes,s.label?[s.label]:[]);return{leaves}}function lazySubmenuIds(model){if(!model)return[];let out=[],walk=nodes=>{for(let n of nodes)n.kind==="submenu"&&(n.lazy?n.loading||out.push(n.id):walk(n.children))};for(let s of model.sections)walk(s.nodes);return out}function paletteStillOpening(model){if(!model)return!0;let walk=nodes=>nodes.some(n=>n.kind==="submenu"&&(n.lazy||n.loading||n.pending||walk(n.children)));return model.sections.some(s=>walk(s.nodes))}function filterPalette(arranged,query){let words=query.toLowerCase().split(/\s+/).filter(Boolean);return words.length?{leaves:arranged.leaves.filter(l=>{let hay=`${l.node.label} ${l.breadcrumb.join(" ")}`.toLowerCase();return words.every(w=>hay.includes(w))})}:arranged}var React2=__toESM(require("react"),1);var DEFAULT_SENSITIVITY=Object.freeze({exportable:!0,classification:"ordinary",includedByDefault:!0});function resolveSensitivity(value){return{exportable:value.sensitivity?.exportable??DEFAULT_SENSITIVITY.exportable,classification:value.sensitivity?.classification??DEFAULT_SENSITIVITY.classification,includedByDefault:value.sensitivity?.includedByDefault??DEFAULT_SENSITIVITY.includedByDefault}}function toJson(value){if(!(value===void 0||typeof value=="function"||typeof value=="symbol")){if(value===null||typeof value=="string"||typeof value=="boolean")return value;if(typeof value=="number")return Number.isFinite(value)?value:null;if(typeof value=="bigint")return value.toString();if(value instanceof Date)return value.toISOString();if(Array.isArray(value))return value.map(v=>toJson(v)??null);if(typeof value=="object"){let out={};for(let[k,v]of Object.entries(value)){let j=toJson(v);j!==void 0&&(out[k]=j)}return out}}}function projectValues(raw,declared,pathPrefix=""){let byName=new Map(declared.map(d=>[d.name,d])),values={},omissions=[];for(let[name,value]of Object.entries(raw)){let path=pathPrefix?`${pathPrefix}.${name}`:name,decl=byName.get(name);if(!decl){omissions.push({path,reason:"filtered"});continue}let sensitivity=resolveSensitivity(decl);if(sensitivity.classification!=="ordinary"){omissions.push({path,reason:"excluded",classification:sensitivity.classification});continue}if(!sensitivity.exportable){omissions.push({path,reason:"excluded"});continue}let json=toJson(value);json!==void 0&&(values[name]=json)}return{values,omissions}}function createProjectedReads(source){return{async values(signal){if(!source.surface||!source.declaration)return{values:{},omissions:[]};let raw=await source.surface.readValues(signal),screenValues=source.declaration.values;return projectValues(raw,screenValues)},async item(signal){let item=source.item;if(!item||!source.declaration)return null;let type=source.declaration.itemTypes?.find(t=>t.name===item.itemType);if(!type)return{values:{},omissions:[{path:item.itemType,reason:"filtered"}]};let raw=await item.readValues(signal);return projectValues(raw,type.values,item.itemType)},async live(signal){return source.surface?.readLive?source.surface.readLive(signal):{}}}}async function runAction(action,target,options){let{ports}=options;if(action.requiresAuth&&!target.auth.authenticated)return ports.auth?(ports.auth.signInThenResume({actionId:action.id,contentFingerprint:options.contentFingerprint??action.id}),{status:"auth-pending"}):(ports.diagnostics.capture(new Error(`requiresAuth action "${action.id}" ran signed out with no auth port`),{area:"actions",detail:{actionId:action.id}}),{status:"failed",error:new Error("sign-in unavailable")});let reads=createProjectedReads(options.source??{surface:null,declaration:target.declaration,item:null}),signal=options.signal??new AbortController().signal;try{return{status:"ran",outcome:await action.run(target,{reads,ports,signal})}}catch(error){ports.diagnostics.capture(error,{area:"actions",detail:{actionId:action.id,stage:"run"}});let label=typeof action.label=="string"?action.label:action.id;return ports.notify?.error(`${label} did not finish.`,"Try again; if it keeps failing, report it from the feedback button."),{status:"failed",error}}}var APPROVED_HEADINGS=new Set(["Save","Copy as","Export","Edit","Creator tools","Admin","App","Compare","History"]),CONTAINER_WORD=/^(more|more…|more\.\.\.|other|others|misc|miscellaneous|additional|extra|extras|actions|options|advanced|stuff|everything else)$/i,TARGET_SHAPE=/^(Cell|Row|Column|Table|Range|Selection|Record) · .+$/;function isContainerWord(label){return CONTAINER_WORD.test(label.trim())}function isApprovedHeading(label,kind="group",approved=APPROVED_HEADINGS){let l=label.trim();return!l||isContainerWord(l)?!1:approved.has(l)?!0:kind==="target"||TARGET_SHAPE.test(l)}function defaultHeadingPolicy(){return globalThis.process?.env?.NODE_ENV==="production"?"inline":"throw"}var UnapprovedHeadingError=class extends Error{heading;constructor(heading,where){super(`Menu heading "${heading}" (${where}) is not an approved heading. Remedy: show these rows inline \u2014 declare no section (or kind "target" for the clicked thing's own label) \u2014 or ask Arman to add the name to APPROVED_HEADINGS in @ai-matrx/alchemy/menu. A generic container word ("More\u2026", "Other") is never approved.`),this.name="UnapprovedHeadingError",this.heading=heading}};var CATEGORY_GROUP={clipboard:"clipboard",copy:"transfer",export:"transfer",save:"document",share:"document",edit:"editable",history:"history",ai:"ai",ask:"ai",listen:"tools",study:"tools",app:"tools",applet:"tools",feedback:"quick",creator:"admin",admin:"admin","surface-info":"surface-info"},GROUP_ORDER=["clipboard","editable","transfer","document","history","ai","tools","quick","surface","admin","surface-info"],CATEGORY_ORDER=["clipboard","edit","copy","export","save","share","history","ask","ai","listen","study","app","applet","feedback","creator","admin","surface-info"];function translate(i18n,key,fallback){if(!i18n)return fallback;try{return i18n.t(key,fallback)}catch{return fallback}}function actionToNode(resolved,target,options={}){let{action,eligibility}=resolved,rawLabel=typeof action.label=="function"?action.label(target):action.label,label=translate(options.i18n,action.labelKey??action.id,rawLabel),base={id:action.id,actionId:action.id,...action.icon!==void 0?{icon:action.icon}:{},...action.placement!==void 0?{placement:action.placement}:{}};if(action.expand)return{...base,kind:"submenu",label,lazy:!0,loading:!1,...action.pending?.(target)?{pending:!0}:{},children:[],...action.emptyLabel!==void 0?{emptyLabel:action.emptyLabel}:{}};if(action.href!==void 0){let href=typeof action.href=="function"?action.href(target):action.href;return{...base,kind:"link",label,href}}if(action.toggle)return{...base,kind:"checkbox",label,checked:action.pressed?.(target)??!1,...action.description!==void 0?{description:action.description}:{}};let state=action.stateIcon?.(target)??null,pressed=action.pressed?.(target),hint=action.hint!==void 0?translate(options.i18n,action.hintKey??`${action.id}.hint`,action.hint):void 0;return{...base,kind:"item",label,...action.iconTone!==void 0?{iconTone:action.iconTone}:{},...state?{stateIcon:state}:{},...action.description!==void 0?{description:action.description}:{},...hint!==void 0?{hint}:{},...pressed!==void 0?{pressed}:{},...action.destructive?{destructive:!0}:{},...action.preserveSelection?{preserveSelection:!0}:{},...action.keepsMenuOpen?{keepsMenuOpen:!0}:{},...eligibility.status==="unavailable-verb"||eligibility.status==="unavailable"?{unavailable:{sentence:eligibility.sentence}}:{}}}function buildMenuModel(target,resolved,options={}){let policy=options.headingPolicy??defaultHeadingPolicy();resolved=resolved.map(r=>{let sec=r.action.section;if(r.action.expand&&isContainerWord(typeof r.action.label=="string"?r.action.label:"")&&policy==="throw")throw new UnapprovedHeadingError(r.action.label,`submenu of ${r.action.id}`);if(!sec)return r;let kind=sec.kind??(sec.primary?"target":"group");if(isApprovedHeading(sec.label,kind))return r;if(policy==="throw")throw new UnapprovedHeadingError(sec.label,`section of ${r.action.id}`);let{section:_dropped,...rest}=r.action;return{...r,action:rest}});let ordered=resolved.map((r,index)=>({r,index})).sort((a,b)=>{let ca=CATEGORY_ORDER.indexOf(a.r.action.category),cb=CATEGORY_ORDER.indexOf(b.r.action.category);if(ca!==cb)return ca-cb;let oa=a.r.action.order??0,ob=b.r.action.order??0;return oa!==ob?oa-ob:a.index-b.index}).map(x=>x.r),sections=new Map,roles={},explicit=new Map;resolved.forEach((r,index)=>{let sec=r.action.section;if(!sec)return;let entry=explicit.get(sec.id)??{group:CATEGORY_GROUP[r.action.category],rows:[]};entry.rows.push({r,index}),explicit.set(sec.id,entry)});let placed=new Set;for(let r of ordered){let sec=r.action.section;if(sec&&placed.has(sec.id))continue;let group=sec?explicit.get(sec.id)?.group??CATEGORY_GROUP[r.action.category]:CATEGORY_GROUP[r.action.category],sectionId=sec?`section:${sec.id}`:group,section=sections.get(sectionId);section||(section={id:sectionId,group,nodes:[],...sec?{label:translate(options.i18n,sec.labelKey??`section.${sec.id}`,sec.label)}:{},...sec?.icon!==void 0?{icon:sec.icon}:{},...sec?.primary?{primary:!0}:{},...sec&&(sec.kind??(sec.primary?"target":"group"))==="target"?{target:!0}:{}},sections.set(sectionId,section));let rows=sec?(explicit.get(sec.id)?.rows??[]).sort((x,y)=>(x.r.action.order??0)-(y.r.action.order??0)||x.index-y.index).map(x=>x.r):[r];sec&&placed.add(sec.id);for(let row of rows)row.action.startsGroup&§ion.nodes.length>0&§ion.nodes.push({kind:"separator",id:`${row.action.id}:group`}),section.nodes.push(actionToNode(row,target,options)),row.action.verb&&(roles[row.action.verb]=row.action.id)}let list=[...sections.values()].sort((a,b)=>!!a.primary!=!!b.primary?a.primary?-1:1:GROUP_ORDER.indexOf(a.group)-GROUP_ORDER.indexOf(b.group)),selected=target.selection?.text?.trim(),content=options.content?.trim(),fieldName=options.contentLabel?.trim();return{header:selected?{label:"Selected",text:target.selection?.text??""}:fieldName?{label:fieldName,text:options.content??""}:content?{label:"Content",text:options.content??""}:null,sections:list,roles}}function withGroupDividers(children,nodes){let out=[];return children.forEach((child,i)=>{let node=nodes[i];node&&(i>0&&(child.startsGroup||(children[i-1].section?.id??null)!==(child.section?.id??null))&&out.push({kind:"separator",id:`${child.id}:group`}),out.push(node))}),out}function withExpandedChildren(model,nodeId,children){let visit=nodes=>nodes.map(n=>n.kind!=="submenu"?n:n.id===nodeId?children==="loading"?{...n,loading:!0}:{...n,lazy:!1,loading:!1,pending:!1,children}:{...n,children:visit(n.children)});return{...model,sections:model.sections.map(s=>({...s,nodes:visit(s.nodes)}))}}function findNode(nodes,id){for(let n of nodes){if(n.id===id)return n;if(n.kind==="submenu"){let hit=findNode(n.children,id);if(hit)return hit}}return null}var React=__toESM(require("react"),1),KEY=Symbol.for("ai-matrx.alchemy.actions-context"),AlchemyActionsContext=globalThis[KEY]??=React.createContext(null);function useAlchemyActions(){let value=React.useContext(AlchemyActionsContext);if(!value)throw new Error("Alchemy actions: render inside <AlchemyActionsProvider> (@ai-matrx/alchemy/react/host).");return value}function isLatestExpansion(capturedTargetEpoch,currentTargetEpoch,capturedNodeSequence,currentNodeSequence){return capturedTargetEpoch===currentTargetEpoch&&capturedNodeSequence===currentNodeSequence}var import_jsx_runtime=require("react/jsx-runtime");function nodeInModel(model,id){for(let s of model.sections){let hit=findNode(s.nodes,id);if(hit)return hit}return null}function hasLoadedRows(model,id){let n=nodeInModel(model,id);return!!(n&&n.kind==="submenu"&&!n.lazy&&!n.loading)}function loadedChildren(model,id){let n=nodeInModel(model,id);return n&&n.kind==="submenu"&&!n.lazy?n.children:[]}function carryOpened(prev,next,opened){return next.map(n=>{if(n.kind!=="submenu")return n;let old=prev.find(o=>o.id===n.id);return!old||old.kind!=="submenu"||old.lazy?n:n.lazy?opened.has(n.id)?{...n,lazy:!1,loading:!1,pending:!1,children:old.children}:n:{...n,children:carryOpened(old.children,n.children,opened)}})}function carryOpenedModel(prev,next,opened){if(opened.size===0)return next;let prevNodes=prev.sections.flatMap(s=>s.nodes);return{...next,sections:next.sections.map(s=>({...s,nodes:carryOpened(prevNodes,s.nodes,opened)}))}}function useMenuEngine(target,options={}){let{registry,ports}=useAlchemyActions(),[resolved,setResolved]=React2.useState([]),[model,setModel]=React2.useState(null),[tick,setTick]=React2.useState(0),expanded=React2.useRef(new Map),opened=React2.useRef(new Set),expandSeq=React2.useRef(new Map),targetEpoch=React2.useRef(0),currentTarget=React2.useRef(target);currentTarget.current!==target&&(currentTarget.current=target,targetEpoch.current+=1);let active=options.active??!0,optionsRef=React2.useRef(options);optionsRef.current=options,React2.useEffect(()=>registry.subscribe(()=>setTick(t=>t+1)),[registry]);let expandAction=React2.useCallback(async(action,nodeId)=>{if(!target||!action.expand)return;let epoch=targetEpoch.current,seq=(expandSeq.current.get(nodeId)??0)+1;expandSeq.current.set(nodeId,seq);let latest=()=>isLatestExpansion(epoch,targetEpoch.current,seq,expandSeq.current.get(nodeId));setModel(m=>m&&!hasLoadedRows(m,nodeId)?withExpandedChildren(m,nodeId,"loading"):m);try{let children=await action.expand(target,new AbortController().signal);if(!latest())return;let nodes=withGroupDividers(children,children.map(child=>(expanded.current.set(child.id,child),actionToNode({action:child,eligibility:{status:"available"}},target,ports.i18n?{i18n:ports.i18n}:{}))));setModel(m=>m&&withExpandedChildren(m,nodeId,carryOpened(loadedChildren(m,nodeId),nodes,opened.current)));for(let child of children)child.expand&&opened.current.has(child.id)&&expandAction(child,child.id)}catch(error){if(!latest())return;ports.diagnostics.capture(error,{area:"menu",detail:{nodeId,stage:"expand"}}),setModel(m=>m&&withExpandedChildren(m,nodeId,[]))}},[target,ports]);React2.useEffect(()=>{expanded.current.clear(),opened.current.clear()},[target]),React2.useEffect(()=>{if(!target||!active)return;let live=!0;return registry.resolve(target,optionsRef.current.restrict).then(list=>{if(!live)return;setResolved(list);let built=buildMenuModel(target,list,{...ports.i18n?{i18n:ports.i18n}:{},content:optionsRef.current.content??null,contentLabel:optionsRef.current.contentLabel??null});setModel(prev=>prev?carryOpenedModel(prev,built,opened.current):built);for(let{action}of list)opened.current.has(action.id)&&action.expand&&expandAction(action,action.id)}),()=>{live=!1}},[registry,ports,target,active,tick,options.revision,expandAction]);let resolvedRef=React2.useRef(resolved);resolvedRef.current=resolved;let subscribedIds=resolved.map(r=>r.action.id).join(`
|
|
3
|
+
`);React2.useEffect(()=>{if(!target)return;let subscribing=!0,onChange=()=>{subscribing||setTick(t=>t+1)},offs=resolvedRef.current.map(r=>r.action.subscribe?.(onChange,target)).filter(off=>typeof off=="function");return subscribing=!1,()=>offs.forEach(off=>off())},[subscribedIds,target]);let findAction=React2.useCallback(id=>resolved.find(r=>r.action.id===id)?.action??expanded.current.get(id)??void 0,[resolved]),run=React2.useCallback(async nodeId=>{if(!target||!model)return null;let node=model.sections.map(s=>findNode(s.nodes,nodeId)).find(Boolean)??null,action=findAction(node&&"actionId"in node&&node.actionId?node.actionId:nodeId);if(!action)return null;let o=optionsRef.current,result=await runAction(action,target,{ports,...o.source?{source:o.source}:{},...o.contentFingerprint?{contentFingerprint:o.contentFingerprint}:{}});return o.onRan?.(nodeId,result,{keepOpen:!!action.keepsMenuOpen}),result},[target,model,findAction,ports]),expand=React2.useCallback(async nodeId=>{let action=findAction(nodeId);!target||!action?.expand||(opened.current.add(nodeId),await expandAction(action,nodeId))},[findAction,target,expandAction]),icon=React2.useCallback((key,tone)=>{if(!key||!ports.icons)return null;let Resolved=ports.icons.resolve(key);return Resolved?(0,import_jsx_runtime.jsx)(Resolved,{className:`h-4 w-4 shrink-0 ${tone??""}`,"aria-hidden":!0}):null},[ports.icons]),explain=React2.useCallback(sentence=>{ports.notify?ports.notify.info(sentence):ports.diagnostics.capture(new Error(`No notify port to explain: ${sentence}`),{area:"menu",detail:{sentence}})},[ports]);return{model,resolved,run,expand,icon,explain}}var React4=__toESM(require("react"),1),import_design_system=require("@ai-matrx/design-system");var React3=__toESM(require("react"),1),MenuSizeContext=React3.createContext("standard");function useMenuSize(){return React3.useContext(MenuSizeContext)}var MENU_SIZE_CLASSES={standard:{panel:"w-72",row:"gap-2",strip:"flex items-center gap-0.5 px-1 py-1",stripButton:"h-7 min-w-7 px-1.5",label:"text-xs",filter:"h-7 text-sm",hint:"text-xs"},large:{panel:"w-[22.5rem] [&_svg]:size-[18px]",row:"gap-3 min-h-9 px-3 text-[15px]",strip:"flex items-center justify-between gap-1 px-2 py-1.5",stripButton:"h-9 min-w-9 px-2",label:"text-[13px]",filter:"h-9 text-[15px]",hint:"text-[13px]"}};var import_jsx_runtime2=require("react/jsx-runtime");function NodeList({nodes,engine}){return(0,import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment,{children:nodes.map(node=>(0,import_jsx_runtime2.jsx)(MenuNodeView,{node,engine},node.id))})}function SectionList({sections,engine}){let size=MENU_SIZE_CLASSES[useMenuSize()];return(0,import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment,{children:sections.map((section,index)=>(0,import_jsx_runtime2.jsxs)(React4.Fragment,{children:[index>0?(0,import_jsx_runtime2.jsx)(import_design_system.DropdownMenuSeparator,{}):null,sectionLabel(section)?(0,import_jsx_runtime2.jsx)(import_design_system.DropdownMenuLabel,{className:`${size.label} font-medium text-muted-foreground`,children:sectionLabel(section)}):null,(0,import_jsx_runtime2.jsx)(NodeList,{nodes:section.nodes,engine})]},section.id))})}function iconOf(node,engine){if(node.kind!=="item")return"icon"in node?engine.icon(node.icon):null;if(node.stateIcon){let glyph=engine.icon(node.stateIcon.icon);return node.stateIcon.spin?(0,import_jsx_runtime2.jsx)("span",{className:"inline-flex animate-spin",children:glyph}):glyph}if(!("icon"in node))return null;let tone=node.pressed===!1?void 0:node.iconTone;return engine.icon(node.icon,tone)}function MenuNodeView({node,engine}){let size=MENU_SIZE_CLASSES[useMenuSize()];switch(node.kind){case"separator":return(0,import_jsx_runtime2.jsx)(import_design_system.DropdownMenuSeparator,{});case"label":return(0,import_jsx_runtime2.jsx)(import_design_system.DropdownMenuLabel,{className:`${size.label} font-medium text-muted-foreground`,children:node.label});case"submenu":return(0,import_jsx_runtime2.jsx)(SubmenuView,{node,engine});case"checkbox":return(0,import_jsx_runtime2.jsxs)(import_design_system.DropdownMenuCheckboxItem,{"data-alchemy-node":node.id,checked:node.checked,onSelect:()=>{engine.run(node.id)},className:size.row,children:[iconOf(node,engine),(0,import_jsx_runtime2.jsx)("span",{className:"truncate",children:node.label})]});case"link":return(0,import_jsx_runtime2.jsx)(import_design_system.DropdownMenuItem,{asChild:!0,"data-alchemy-node":node.id,children:(0,import_jsx_runtime2.jsxs)("a",{href:node.href,target:node.target,className:size.row,children:[iconOf(node,engine),(0,import_jsx_runtime2.jsx)("span",{className:"truncate",children:node.label})]})});case"item":return(0,import_jsx_runtime2.jsx)(LeafItem,{node,engine})}}function SubmenuView({node,engine}){let triggerRef=React4.useRef(null),size=MENU_SIZE_CLASSES[useMenuSize()];return(0,import_jsx_runtime2.jsxs)(import_design_system.DropdownMenuSub,{onOpenChange:open=>{open&&node.lazy&&!node.loading&&engine.expand(node.id)},children:[(0,import_jsx_runtime2.jsxs)(import_design_system.DropdownMenuSubTrigger,{ref:triggerRef,"data-alchemy-node":node.id,className:size.row,"aria-busy":node.pending?!0:void 0,children:[iconOf(node,engine),(0,import_jsx_runtime2.jsx)("span",{className:"truncate",children:node.label}),node.pending?(0,import_jsx_runtime2.jsx)("span",{className:"ml-auto text-xs text-muted-foreground",children:"Loading\u2026"}):null]}),(0,import_jsx_runtime2.jsx)(import_design_system.DropdownMenuSubContent,{"data-alchemy-submenu":node.id,onFocusOutside:event=>{let to=event.target,trigger=triggerRef.current;to instanceof Element&&trigger&&to.getAttribute("role")==="menu"&&to.contains(trigger)&&event.preventDefault()},className:`${size.panel} max-w-[calc(100vw-1rem)] max-h-[var(--radix-dropdown-menu-content-available-height)] overflow-y-auto`,children:node.loading?(0,import_jsx_runtime2.jsx)(import_design_system.DropdownMenuLabel,{className:"text-xs text-muted-foreground",children:"Loading\u2026"}):node.children.length===0&&!node.lazy?(0,import_jsx_runtime2.jsx)(import_design_system.DropdownMenuLabel,{className:"text-xs text-muted-foreground",children:node.emptyLabel??"Nothing here yet"}):(0,import_jsx_runtime2.jsx)(NodeList,{nodes:node.children,engine})})]})}function LeafItem({node,engine}){let size=MENU_SIZE_CLASSES[useMenuSize()],row=(0,import_jsx_runtime2.jsxs)(import_design_system.DropdownMenuItem,{"data-alchemy-node":node.id,"aria-disabled":node.unavailable?!0:void 0,"aria-pressed":node.pressed,onSelect:event=>{if(node.unavailable){event.preventDefault();return}node.keepsMenuOpen&&event.preventDefault(),engine.run(node.id)},className:`${size.row} ${node.unavailable?"opacity-50":""} ${node.destructive?"text-destructive":""}`,children:[iconOf(node,engine),(0,import_jsx_runtime2.jsxs)("span",{className:"flex min-w-0 flex-1 flex-col",children:[(0,import_jsx_runtime2.jsx)("span",{className:"truncate",children:node.label}),node.description?(0,import_jsx_runtime2.jsx)("span",{className:"truncate text-xs text-muted-foreground",children:node.description}):null]}),node.hint?(0,import_jsx_runtime2.jsx)("span",{className:`ml-auto ${size.hint} text-muted-foreground`,children:node.hint}):null]});return node.unavailable?(0,import_jsx_runtime2.jsxs)(import_design_system.Tooltip,{children:[(0,import_jsx_runtime2.jsx)(import_design_system.TooltipTrigger,{asChild:!0,children:row}),(0,import_jsx_runtime2.jsx)(import_design_system.TooltipContent,{children:node.unavailable.sentence})]}):row}function LeafButton({node,engine,showLabel}){if(node.kind!=="item"&&node.kind!=="checkbox"&&node.kind!=="link")return null;let unavailable=node.kind==="item"?node.unavailable:void 0,pressed=node.kind==="item"?node.pressed:node.kind==="checkbox"?node.checked:void 0,glyph=iconOf(node,engine),size=MENU_SIZE_CLASSES[useMenuSize()],destructive=node.kind==="item"&&node.destructive,button=(0,import_jsx_runtime2.jsxs)("button",{type:"button","data-alchemy-node":node.id,"data-matrx-button":"","data-tap-floor":"","data-tap-floor-square":"","aria-label":node.label,"aria-disabled":unavailable?!0:void 0,"aria-pressed":pressed,onMouseDown:e=>{node.kind==="item"&&node.preserveSelection&&e.preventDefault()},onClick:()=>{if(unavailable){engine.explain(unavailable.sentence);return}if(node.kind==="link"){window.location.assign(node.href);return}engine.run(node.id)},className:`inline-flex ${size.stripButton} pointer-coarse:h-11 pointer-coarse:min-w-11 shrink-0 items-center justify-center gap-1.5 rounded-md text-sm ${destructive?"text-destructive hover:bg-destructive/10":"text-muted-foreground hover:bg-accent hover:text-foreground"} ${unavailable?"cursor-default opacity-50 hover:bg-transparent":""} ${pressed?"text-foreground":""}`,children:[glyph,showLabel||!glyph?(0,import_jsx_runtime2.jsx)("span",{className:"whitespace-nowrap",children:node.label}):null]});return(0,import_jsx_runtime2.jsxs)(import_design_system.Tooltip,{children:[(0,import_jsx_runtime2.jsx)(import_design_system.TooltipTrigger,{asChild:!0,children:button}),(0,import_jsx_runtime2.jsx)(import_design_system.TooltipContent,{children:unavailable?unavailable.sentence:node.label})]})}var NO_LONGER="Nothing here right now.";function kept(node){if(node.kind==="separator"||node.kind==="label")return node;let label="label"in node?node.label:"",icon="icon"in node?node.icon:void 0,sentence=node.kind==="submenu"?node.emptyLabel??NO_LONGER:NO_LONGER;return{kind:"item",id:node.id,label,...icon!==void 0?{icon}:{},unavailable:{sentence}}}var LATE="__arrived_after_open";function isLoading(node){return node.kind==="submenu"&&!!node.pending}function keepSlotsWhileOpen(shown,current){if(!shown)return{sections:current.map(s=>({...s,nodes:[...s.nodes]}))};let now=new Map,nowSection=new Map;for(let section of current){nowSection.set(section.id,section);for(let node of section.nodes)now.set(node.id,node)}let drawn=new Set,sections=[];for(let section of shown.sections){let fresh=nowSection.get(section.id),nodes=[];for(let node of section.nodes){drawn.add(node.id);let live=now.get(node.id);live?nodes.push(live):isLoading(node)||nodes.push(kept(node))}nodes.length===0&§ion.nodes.length>0||sections.push({...fresh??section,nodes})}let late=[];for(let section of current)for(let node of section.nodes)drawn.has(node.id)||late.push(node);if(late.length){let lateSection=sections.find(s=>s.id===LATE);lateSection?lateSection.nodes.push(...late):sections.push({id:LATE,group:sections[sections.length-1]?.group??"more",nodes:late})}return{sections}}var React5=__toESM(require("react"),1);function useSearchOpensLibraries(engine,searching){let{model,expand}=engine;React5.useEffect(()=>{if(searching)for(let id of lazySubmenuIds(model))expand(id)},[searching,model,expand])}var import_jsx_runtime3=require("react/jsx-runtime");function ContextMenuPanel({target,point,open,onOpenChange,arrangement="command",density="comfortable",subjectFold,size="standard",hideHeader=!1,...options}){let sized=MENU_SIZE_CLASSES[size],engine=useMenuEngine(target,{...options,onRan:(id,r,ran)=>{options.onRan?.(id,r,ran),ran?.keepOpen||onOpenChange(!1)}}),[query,setQuery]=React6.useState(""),laidOut=engine.model?context(engine.model,arrangement):null,arranged=laidOut&&subjectFold?foldUnderSubject(laidOut,subjectFold):laidOut,slots=React6.useRef({at:"",shown:null}),at=`${point.x},${point.y}`;(!open||slots.current.at!==at)&&(slots.current={at,shown:null});let sections=arranged&&open?(slots.current.shown=keepSlotsWhileOpen(slots.current.shown,arranged.sections)).sections:arranged?.sections??[],filtered=engine.model&&query.trim()?filterPalette(palette(engine.model),query):null;useSearchOpensLibraries(engine,open&&query.trim().length>0);let anchor=(0,import_jsx_runtime3.jsx)(import_design_system2.DropdownMenuTrigger,{asChild:!0,children:(0,import_jsx_runtime3.jsx)("span",{"aria-hidden":!0,"data-alchemy-anchor":"context",style:{position:"fixed",left:point.x,top:point.y,width:0,height:0,pointerEvents:"none"}})});return(0,import_jsx_runtime3.jsxs)(import_design_system2.DropdownMenu,{open,onOpenChange,modal:!1,children:[typeof document>"u"?anchor:(0,import_react_dom.createPortal)(anchor,document.body),(0,import_jsx_runtime3.jsx)(import_design_system2.DropdownMenuContent,{side:"right",align:"start",sideOffset:2,collisionPadding:8,"data-alchemy-layout":`context-${arrangement}`,onPointerUpCapture:event=>{event.button===2&&event.preventDefault()},"data-alchemy-size":size,className:`${sized.panel} ${size==="large"?"max-h-[min(var(--radix-dropdown-menu-content-available-height),40rem)]":"max-h-[min(var(--radix-dropdown-menu-content-available-height),32rem)]"} overflow-y-auto ${density==="compact"?"text-xs":""}`,children:(0,import_jsx_runtime3.jsx)(MenuSizeContext.Provider,{value:size,children:(0,import_jsx_runtime3.jsxs)(import_design_system2.TooltipProvider,{children:[engine.model?.header&&!hideHeader?(0,import_jsx_runtime3.jsxs)(import_design_system2.DropdownMenuLabel,{className:"truncate text-xs font-normal text-muted-foreground",title:engine.model.header.text,children:[engine.model.header.label,engine.model.header.text.trim()?`: ${engine.model.header.text}`:null]}):null,arranged?(0,import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment,{children:[arranged.strip.length?(0,import_jsx_runtime3.jsx)("div",{role:"toolbar","aria-label":"Clipboard",className:sized.strip,children:arranged.strip.map(node=>(0,import_jsx_runtime3.jsx)(LeafButton,{node,engine,showLabel:!1},node.id))}):null,arranged.filterable?(0,import_jsx_runtime3.jsx)("div",{className:"px-1 pb-1",children:(0,import_jsx_runtime3.jsx)("input",{"aria-label":"Filter actions",placeholder:"Type to filter\u2026",value:query,onChange:e=>setQuery(e.target.value),onKeyDown:e=>{e.stopPropagation(),e.key==="Enter"&&filtered?.leaves[0]&&engine.run(filtered.leaves[0].node.id)},className:`${sized.filter} w-full rounded-md border border-border bg-transparent px-2 outline-none`})}):null,(arranged.strip.length||arranged.filterable)&§ions.length?(0,import_jsx_runtime3.jsx)(import_design_system2.DropdownMenuSeparator,{}):null,filtered?filtered.leaves.length?filtered.leaves.map(({node,breadcrumb})=>(0,import_jsx_runtime3.jsxs)(import_design_system2.DropdownMenuItem,{"data-alchemy-node":node.id,onSelect:event=>{node.kind==="item"&&node.keepsMenuOpen&&event.preventDefault(),node.kind==="submenu"?engine.expand(node.id):engine.run(node.id)},className:"flex-col items-start gap-0",children:[(0,import_jsx_runtime3.jsx)("span",{children:node.label}),(0,import_jsx_runtime3.jsx)("span",{className:"text-xs text-muted-foreground",children:breadcrumb.join(" \u203A ")})]},node.id)):paletteStillOpening(engine.model)?(0,import_jsx_runtime3.jsx)("div",{className:"px-2 py-1.5 text-xs text-muted-foreground",children:"Searching\u2026"}):(0,import_jsx_runtime3.jsxs)("div",{className:"px-2 py-1.5 text-xs text-muted-foreground",children:["No action matches \u201C",query,"\u201D."]}):(0,import_jsx_runtime3.jsx)(SectionList,{sections,engine})]}):(0,import_jsx_runtime3.jsx)("div",{className:"px-2 py-1.5 text-xs text-muted-foreground",children:"Loading\u2026"})]})})})]})}
|
|
4
4
|
//# sourceMappingURL=react-menu.cjs.map
|