@ethisyscore/plugin-ui 1.38.0 → 1.40.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,152 @@
1
+ import { Context } from 'react';
2
+ import { HostSidebarActionsApiShape } from '@ethisyscore/components-react';
3
+
4
+ /** Host-chrome / sidebar-actions contract version (semver). Host MAJOR must equal the SDK
5
+ * MAJOR before any publish/subscribe; otherwise the plugin hook fails closed (WI 5188 batch 2). */
6
+ declare const HOST_CHROME_CONTRACT_VERSION = "2.0.0";
7
+ type HostSidebarActionSlot = "primary" | "overflow" | "sidebar-only";
8
+ type HostSidebarActionVariant = "default" | "danger";
9
+ /** Fields common to every action. */
10
+ interface HostSidebarActionBase {
11
+ id: string;
12
+ label: string;
13
+ icon?: string;
14
+ slot?: HostSidebarActionSlot;
15
+ variant?: HostSidebarActionVariant;
16
+ disabled?: boolean;
17
+ active?: boolean;
18
+ /** Optional host-side double-gate: the mask is resolved against the surface extension groupCode. */
19
+ requiredPermission?: number;
20
+ }
21
+ /** Strictly serializable action the plugin publishes to the host sidebar — NO functions cross
22
+ * the boundary. Discriminated union so `href` is REQUIRED at the type level for a navigate
23
+ * action and FORBIDDEN for a dispatch action (spec-gate MEDIUM R1-M1 — a navigate with a
24
+ * missing href fails typecheck at authoring time rather than being silently dropped by the host).
25
+ * `kind:"dispatch"` is clicked back to the plugin by `id` via the action-emit subscription. */
26
+ type HostSidebarActionDescriptor = (HostSidebarActionBase & {
27
+ kind: "dispatch";
28
+ }) | (HostSidebarActionBase & {
29
+ kind: "navigate";
30
+ href: string;
31
+ });
32
+ /** A navigation leaf the plugin drives into the host detail sidebar. `href` is extension-relative;
33
+ * the host canonicalises + confines it to `/extensions/<slug>/…` (host-owned, never trusted). */
34
+ interface HostSidebarNavItem {
35
+ id: string;
36
+ label: string;
37
+ icon?: string;
38
+ href: string;
39
+ }
40
+ /** The single publish payload. `none` = contribute nothing (do NOT clobber the static manifest
41
+ * actions); `actions` = batch-2 Quick Actions for a detail entity; `detail` = full detail-nav
42
+ * REPLACEMENT (title + nav items + back-arrow + Quick Actions). `identityEpoch` is host-stamped
43
+ * (plan D-1), so it is not part of this plugin-published shape. */
44
+ type HostSidebarContribution = {
45
+ mode: "none";
46
+ } | {
47
+ mode: "actions";
48
+ entityToken: string;
49
+ actions: HostSidebarActionDescriptor[];
50
+ } | {
51
+ mode: "detail";
52
+ entityToken: string;
53
+ title: string;
54
+ navSectionLabel: string;
55
+ navItems: HostSidebarNavItem[];
56
+ backHref: string;
57
+ backLabel: string;
58
+ actions: HostSidebarActionDescriptor[];
59
+ };
60
+ interface HostSidebarActionsCapabilities {
61
+ readonly contractVersion: string;
62
+ }
63
+ /** Host-provided API, passed to a PlatformReact page as the `hostSidebar` prop and read via
64
+ * the plugin-bundled context. Additive-only. */
65
+ interface HostSidebarActionsApi {
66
+ /** Replace the surface's sidebar contribution. The host rejects a publish whose entityToken ≠
67
+ * its current location-derived token, rejects duplicate action ids, and — for mode:"detail" —
68
+ * rejects/atomically-drops an invalid or href-unsafe context (falls back to main nav). */
69
+ publish(contribution: HostSidebarContribution): void;
70
+ /** Revert to the static-manifest fallback (publication state = unpublished). */
71
+ clear(): void;
72
+ /** Subscribe to click dispatch for `kind:"dispatch"` actions. The host emits the clicked
73
+ * action id. Returns an unsubscribe. The plugin bridge subscribes exactly once. */
74
+ subscribe(onAction: (actionId: string) => void): () => void;
75
+ readonly capabilities: HostSidebarActionsCapabilities;
76
+ }
77
+ /** Props the host injects into a page for the sidebar-actions seam (merged into PlatformReactPageProps).
78
+ * Typed against the dependency-neutral `HostSidebarActionsApiShape` — the SAME type
79
+ * `PlatformReactPageProps.hostSidebar` uses in `@ethisyscore/components-react` — so this
80
+ * convenience alias never diverges from the canonical page-props declaration. The concrete
81
+ * `HostSidebarActionsApi` is structurally assignable to the shape; the page bridge narrows to
82
+ * it internally. */
83
+ interface HostSidebarActionsPageProps {
84
+ hostSidebar?: HostSidebarActionsApiShape;
85
+ }
86
+ declare const HostSidebarActionsContext: Context<HostSidebarActionsApi | null>;
87
+ interface HostChromeDiagnostic {
88
+ event: string;
89
+ pageId?: string;
90
+ detail?: unknown;
91
+ }
92
+ type DiagnosticSinkFn = (d: HostChromeDiagnostic) => void;
93
+ declare function setHostChromeDiagnosticSink(sink: DiagnosticSinkFn): void;
94
+ declare function reportHostChromeDiagnostic(d: HostChromeDiagnostic): void;
95
+ /** Major-equality compatibility check; fail-closed on absent/unparseable input. */
96
+ declare function isHostChromeCompatible(hostVersion: string | undefined): boolean;
97
+
98
+ /** Authoring shape: a descriptor plus — ONLY for `kind:"dispatch"` — an inline handler.
99
+ * A distributive union (not a blanket intersection over the whole descriptor union): `onSelect`
100
+ * is permitted only on a dispatch action. A navigate action carries no handler (the host performs
101
+ * the navigation from `href`), so supplying `onSelect` on a navigate action is a typecheck error
102
+ * rather than a silently-ignored footgun. The hook strips `onSelect` before publishing (only
103
+ * serializable descriptors cross to the host). */
104
+ type HostSidebarAction = (Extract<HostSidebarActionDescriptor, {
105
+ kind: "dispatch";
106
+ }> & {
107
+ onSelect?: () => void;
108
+ }) | Extract<HostSidebarActionDescriptor, {
109
+ kind: "navigate";
110
+ }>;
111
+ /** Single source for the discriminant values used across the mode checks, `toContribution`, and
112
+ * the content key — so the "none"/"actions"/"detail" strings live in one place. The union type
113
+ * below intentionally keeps its literal members (they ARE the discriminant + drive IntelliSense);
114
+ * `SIDEBAR_MODE.*` is `as const`, so it is type-identical to those literals. */
115
+ declare const SIDEBAR_MODE: {
116
+ readonly none: "none";
117
+ readonly actions: "actions";
118
+ readonly detail: "detail";
119
+ };
120
+ /** Discriminated input to `useHostSidebarActions`. `mode:"none"` suppresses all plugin-side
121
+ * contributions without clobbering the static manifest actions. `mode:"actions"` is the
122
+ * batch-2 Quick Actions shape. `mode:"detail"` is the full detail-nav replacement with title,
123
+ * navigation items, back-arrow, and Quick Actions. */
124
+ type HostSidebarInput = {
125
+ mode: "none";
126
+ } | {
127
+ mode: "actions";
128
+ entityToken: string;
129
+ actions: HostSidebarAction[];
130
+ } | {
131
+ mode: "detail";
132
+ entityToken: string;
133
+ title: string;
134
+ navSectionLabel: string;
135
+ navItems: HostSidebarNavItem[];
136
+ backHref: string;
137
+ backLabel: string;
138
+ actions: HostSidebarAction[];
139
+ };
140
+ /**
141
+ * Publish contextual sidebar contributions from a PlatformReact page to the host sidebar, and
142
+ * receive click dispatch by id. Accepts a discriminated `HostSidebarInput`:
143
+ * - `mode:"none"` — suppress all plugin contributions without clobbering the static manifest.
144
+ * - `mode:"actions"` — batch-2 Quick Actions for a detail entity (entity token + action list).
145
+ * - `mode:"detail"` — full detail-nav replacement (title, nav items, back-arrow, Quick Actions).
146
+ *
147
+ * Serializable descriptors only cross to the host; the inline `onSelect` handlers stay in a
148
+ * ref-map here and are always the latest closure. Fails closed (no publish/subscribe, no throw)
149
+ * when the host predates or is incompatible with the seam. */
150
+ declare function useHostSidebarActions(input: HostSidebarInput): void;
151
+
152
+ export { HOST_CHROME_CONTRACT_VERSION as H, SIDEBAR_MODE as S, type HostChromeDiagnostic as a, type HostSidebarAction as b, type HostSidebarActionDescriptor as c, type HostSidebarActionSlot as d, type HostSidebarActionVariant as e, type HostSidebarActionsApi as f, type HostSidebarActionsCapabilities as g, HostSidebarActionsContext as h, type HostSidebarActionsPageProps as i, type HostSidebarContribution as j, type HostSidebarInput as k, type HostSidebarNavItem as l, isHostChromeCompatible as m, reportHostChromeDiagnostic as r, setHostChromeDiagnosticSink as s, useHostSidebarActions as u };
@@ -0,0 +1,152 @@
1
+ import { Context } from 'react';
2
+ import { HostSidebarActionsApiShape } from '@ethisyscore/components-react';
3
+
4
+ /** Host-chrome / sidebar-actions contract version (semver). Host MAJOR must equal the SDK
5
+ * MAJOR before any publish/subscribe; otherwise the plugin hook fails closed (WI 5188 batch 2). */
6
+ declare const HOST_CHROME_CONTRACT_VERSION = "2.0.0";
7
+ type HostSidebarActionSlot = "primary" | "overflow" | "sidebar-only";
8
+ type HostSidebarActionVariant = "default" | "danger";
9
+ /** Fields common to every action. */
10
+ interface HostSidebarActionBase {
11
+ id: string;
12
+ label: string;
13
+ icon?: string;
14
+ slot?: HostSidebarActionSlot;
15
+ variant?: HostSidebarActionVariant;
16
+ disabled?: boolean;
17
+ active?: boolean;
18
+ /** Optional host-side double-gate: the mask is resolved against the surface extension groupCode. */
19
+ requiredPermission?: number;
20
+ }
21
+ /** Strictly serializable action the plugin publishes to the host sidebar — NO functions cross
22
+ * the boundary. Discriminated union so `href` is REQUIRED at the type level for a navigate
23
+ * action and FORBIDDEN for a dispatch action (spec-gate MEDIUM R1-M1 — a navigate with a
24
+ * missing href fails typecheck at authoring time rather than being silently dropped by the host).
25
+ * `kind:"dispatch"` is clicked back to the plugin by `id` via the action-emit subscription. */
26
+ type HostSidebarActionDescriptor = (HostSidebarActionBase & {
27
+ kind: "dispatch";
28
+ }) | (HostSidebarActionBase & {
29
+ kind: "navigate";
30
+ href: string;
31
+ });
32
+ /** A navigation leaf the plugin drives into the host detail sidebar. `href` is extension-relative;
33
+ * the host canonicalises + confines it to `/extensions/<slug>/…` (host-owned, never trusted). */
34
+ interface HostSidebarNavItem {
35
+ id: string;
36
+ label: string;
37
+ icon?: string;
38
+ href: string;
39
+ }
40
+ /** The single publish payload. `none` = contribute nothing (do NOT clobber the static manifest
41
+ * actions); `actions` = batch-2 Quick Actions for a detail entity; `detail` = full detail-nav
42
+ * REPLACEMENT (title + nav items + back-arrow + Quick Actions). `identityEpoch` is host-stamped
43
+ * (plan D-1), so it is not part of this plugin-published shape. */
44
+ type HostSidebarContribution = {
45
+ mode: "none";
46
+ } | {
47
+ mode: "actions";
48
+ entityToken: string;
49
+ actions: HostSidebarActionDescriptor[];
50
+ } | {
51
+ mode: "detail";
52
+ entityToken: string;
53
+ title: string;
54
+ navSectionLabel: string;
55
+ navItems: HostSidebarNavItem[];
56
+ backHref: string;
57
+ backLabel: string;
58
+ actions: HostSidebarActionDescriptor[];
59
+ };
60
+ interface HostSidebarActionsCapabilities {
61
+ readonly contractVersion: string;
62
+ }
63
+ /** Host-provided API, passed to a PlatformReact page as the `hostSidebar` prop and read via
64
+ * the plugin-bundled context. Additive-only. */
65
+ interface HostSidebarActionsApi {
66
+ /** Replace the surface's sidebar contribution. The host rejects a publish whose entityToken ≠
67
+ * its current location-derived token, rejects duplicate action ids, and — for mode:"detail" —
68
+ * rejects/atomically-drops an invalid or href-unsafe context (falls back to main nav). */
69
+ publish(contribution: HostSidebarContribution): void;
70
+ /** Revert to the static-manifest fallback (publication state = unpublished). */
71
+ clear(): void;
72
+ /** Subscribe to click dispatch for `kind:"dispatch"` actions. The host emits the clicked
73
+ * action id. Returns an unsubscribe. The plugin bridge subscribes exactly once. */
74
+ subscribe(onAction: (actionId: string) => void): () => void;
75
+ readonly capabilities: HostSidebarActionsCapabilities;
76
+ }
77
+ /** Props the host injects into a page for the sidebar-actions seam (merged into PlatformReactPageProps).
78
+ * Typed against the dependency-neutral `HostSidebarActionsApiShape` — the SAME type
79
+ * `PlatformReactPageProps.hostSidebar` uses in `@ethisyscore/components-react` — so this
80
+ * convenience alias never diverges from the canonical page-props declaration. The concrete
81
+ * `HostSidebarActionsApi` is structurally assignable to the shape; the page bridge narrows to
82
+ * it internally. */
83
+ interface HostSidebarActionsPageProps {
84
+ hostSidebar?: HostSidebarActionsApiShape;
85
+ }
86
+ declare const HostSidebarActionsContext: Context<HostSidebarActionsApi | null>;
87
+ interface HostChromeDiagnostic {
88
+ event: string;
89
+ pageId?: string;
90
+ detail?: unknown;
91
+ }
92
+ type DiagnosticSinkFn = (d: HostChromeDiagnostic) => void;
93
+ declare function setHostChromeDiagnosticSink(sink: DiagnosticSinkFn): void;
94
+ declare function reportHostChromeDiagnostic(d: HostChromeDiagnostic): void;
95
+ /** Major-equality compatibility check; fail-closed on absent/unparseable input. */
96
+ declare function isHostChromeCompatible(hostVersion: string | undefined): boolean;
97
+
98
+ /** Authoring shape: a descriptor plus — ONLY for `kind:"dispatch"` — an inline handler.
99
+ * A distributive union (not a blanket intersection over the whole descriptor union): `onSelect`
100
+ * is permitted only on a dispatch action. A navigate action carries no handler (the host performs
101
+ * the navigation from `href`), so supplying `onSelect` on a navigate action is a typecheck error
102
+ * rather than a silently-ignored footgun. The hook strips `onSelect` before publishing (only
103
+ * serializable descriptors cross to the host). */
104
+ type HostSidebarAction = (Extract<HostSidebarActionDescriptor, {
105
+ kind: "dispatch";
106
+ }> & {
107
+ onSelect?: () => void;
108
+ }) | Extract<HostSidebarActionDescriptor, {
109
+ kind: "navigate";
110
+ }>;
111
+ /** Single source for the discriminant values used across the mode checks, `toContribution`, and
112
+ * the content key — so the "none"/"actions"/"detail" strings live in one place. The union type
113
+ * below intentionally keeps its literal members (they ARE the discriminant + drive IntelliSense);
114
+ * `SIDEBAR_MODE.*` is `as const`, so it is type-identical to those literals. */
115
+ declare const SIDEBAR_MODE: {
116
+ readonly none: "none";
117
+ readonly actions: "actions";
118
+ readonly detail: "detail";
119
+ };
120
+ /** Discriminated input to `useHostSidebarActions`. `mode:"none"` suppresses all plugin-side
121
+ * contributions without clobbering the static manifest actions. `mode:"actions"` is the
122
+ * batch-2 Quick Actions shape. `mode:"detail"` is the full detail-nav replacement with title,
123
+ * navigation items, back-arrow, and Quick Actions. */
124
+ type HostSidebarInput = {
125
+ mode: "none";
126
+ } | {
127
+ mode: "actions";
128
+ entityToken: string;
129
+ actions: HostSidebarAction[];
130
+ } | {
131
+ mode: "detail";
132
+ entityToken: string;
133
+ title: string;
134
+ navSectionLabel: string;
135
+ navItems: HostSidebarNavItem[];
136
+ backHref: string;
137
+ backLabel: string;
138
+ actions: HostSidebarAction[];
139
+ };
140
+ /**
141
+ * Publish contextual sidebar contributions from a PlatformReact page to the host sidebar, and
142
+ * receive click dispatch by id. Accepts a discriminated `HostSidebarInput`:
143
+ * - `mode:"none"` — suppress all plugin contributions without clobbering the static manifest.
144
+ * - `mode:"actions"` — batch-2 Quick Actions for a detail entity (entity token + action list).
145
+ * - `mode:"detail"` — full detail-nav replacement (title, nav items, back-arrow, Quick Actions).
146
+ *
147
+ * Serializable descriptors only cross to the host; the inline `onSelect` handlers stay in a
148
+ * ref-map here and are always the latest closure. Fails closed (no publish/subscribe, no throw)
149
+ * when the host predates or is incompatible with the seam. */
150
+ declare function useHostSidebarActions(input: HostSidebarInput): void;
151
+
152
+ export { HOST_CHROME_CONTRACT_VERSION as H, SIDEBAR_MODE as S, type HostChromeDiagnostic as a, type HostSidebarAction as b, type HostSidebarActionDescriptor as c, type HostSidebarActionSlot as d, type HostSidebarActionVariant as e, type HostSidebarActionsApi as f, type HostSidebarActionsCapabilities as g, HostSidebarActionsContext as h, type HostSidebarActionsPageProps as i, type HostSidebarContribution as j, type HostSidebarInput as k, type HostSidebarNavItem as l, isHostChromeCompatible as m, reportHostChromeDiagnostic as r, setHostChromeDiagnosticSink as s, useHostSidebarActions as u };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ethisyscore/plugin-ui",
3
- "version": "1.38.0",
3
+ "version": "1.40.0",
4
4
  "description": "Plugin-UI umbrella SDK: client bridge + a11y/l10n primitives + brokered-MCP client (WI 4858).",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",