elowen-plugin-ui-kit 0.11.0 → 0.13.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.d.ts CHANGED
@@ -11,7 +11,7 @@ import type { ComponentType } from 'react';
11
11
  * Deliberately a LITERAL type: the web app re-declares the value and annotates it with
12
12
  * `typeof PLUGIN_UI_API_VERSION`, so a kit bump that forgets the host fails the web typecheck instead
13
13
  * of drifting silently. */
14
- export declare const PLUGIN_UI_API_VERSION: 16;
14
+ export declare const PLUGIN_UI_API_VERSION: 18;
15
15
 
16
16
  /** Public props of `ElowenUiRuntime.components.Slider`. */
17
17
  export interface SliderProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'value' | 'onChange' | 'min' | 'max' | 'step' | 'type'> {
@@ -37,6 +37,16 @@ export interface ProjectIconProps {
37
37
  className?: string;
38
38
  }
39
39
 
40
+ /** `ElowenUiRuntime.components.Calendar` (API 17) is the host's shadcn Calendar, built on
41
+ * `react-day-picker` v9, and its props ARE that library's: a controlled `month`, `selected`,
42
+ * `modifiers`, `components.DayButton`, `locale`, `hidden`/`disabled`, `onSelect`. v9 has NO
43
+ * `DayContent`: a caller replaces the day's own button, and has to forward every prop the library
44
+ * computed and honour `modifiers.focused`, or the grid's arrow keys stop moving. Deliberately not
45
+ * re-declared here as a second interface: the truth is one `import type { DayPicker } from
46
+ * 'react-day-picker'` away in the bundle's own runtime type, while dragging the dependency into this
47
+ * kit would make every plugin build install it just to host-render one grid. A bundle types the
48
+ * element it destructures off `runtime().components.Calendar` with the props it actually passes. */
49
+
40
50
  export interface PluginConfigField {
41
51
  key: string;
42
52
  label: string;
@@ -54,6 +64,7 @@ export interface PluginConfigField {
54
64
  browse?: 'directory';
55
65
  default?: string | number | boolean | string[];
56
66
  providerType?: string | string[];
67
+ modelKind?: 'image';
57
68
  options?: { value: string; label: string }[];
58
69
  language?: string;
59
70
  help?: string;
@@ -182,8 +193,56 @@ export interface PluginUiProject {
182
193
  path: string;
183
194
  notes: string;
184
195
  icon?: string;
196
+ executionKind?: 'host' | 'managed';
197
+ guestRoot?: string;
198
+ }
199
+
200
+ /** One plugin-owned action on a core Project register card. */
201
+ export interface PluginProjectRowAction {
202
+ id: string;
203
+ label: string;
204
+ icon?: string;
205
+ disabled?: boolean;
206
+ tone?: 'danger';
207
+ onSelect: () => void;
208
+ }
209
+
210
+ /** One plugin-owned resource status on a core Project register card. */
211
+ export interface PluginProjectRowStatus {
212
+ label: string;
213
+ icon?: string;
214
+ tone?: 'muted' | 'accent' | 'success' | 'warning' | 'danger';
215
+ busy?: boolean;
185
216
  }
186
217
 
218
+ /** One plugin-owned resource metric. Percent is valid only for a real configured ceiling. */
219
+ export interface PluginProjectRowMetric {
220
+ id: string;
221
+ label: string;
222
+ value: string;
223
+ valueText?: string;
224
+ description?: string;
225
+ percent?: number;
226
+ state: 'ready' | 'absolute' | 'unknown' | 'stopped' | 'unavailable';
227
+ }
228
+
229
+ /** A plugin's contribution to the Project register. Core owns the rows and only renders these optional
230
+ * projections and the plugin-owned overlay. */
231
+ export interface PluginProjectRowContribution {
232
+ status?: Record<number, PluginProjectRowStatus>;
233
+ metrics?: Record<number, {
234
+ label: string;
235
+ items: PluginProjectRowMetric[];
236
+ refreshing?: boolean;
237
+ stale?: boolean;
238
+ staleLabel?: string;
239
+ }>;
240
+ actions?: Record<number, PluginProjectRowAction[]>;
241
+ overlay?: React.ReactNode;
242
+ }
243
+
244
+ export type PluginProjectRowsHook = (input: { projects: PluginUiProject[] }) => PluginProjectRowContribution;
245
+
187
246
  /** The selected core User DTO exposed only to administrator user-detail panels. Compatibility fields stay
188
247
  * present because plugins receive the same object as the host Users screen, not a second partial identity. */
189
248
  export interface PluginUiUser {
@@ -308,11 +367,91 @@ export interface PluginChatArtifactProps {
308
367
  narration?: string;
309
368
  }
310
369
 
370
+ /** Dashboard metric input shared by plugin metric tiles. */
371
+ export interface DashboardMetricProps {
372
+ now: number;
373
+ locale: string;
374
+ monthCostUsd: number | null;
375
+ monthTokens: number;
376
+ }
377
+
378
+ /** A generic card emitted by a plugin tool. The host keeps this wire shape opaque to slot renderers. */
379
+ export interface BrainCard {
380
+ id: string;
381
+ title?: string;
382
+ items?: readonly {
383
+ text: string;
384
+ status?: 'pending' | 'in_progress' | 'completed';
385
+ startedAt?: number;
386
+ id?: string;
387
+ label?: string;
388
+ owner?: string;
389
+ blockedBy?: readonly string[];
390
+ }[];
391
+ body?: string;
392
+ pinned?: boolean;
393
+ }
394
+
395
+ /** The core conversation row handed to a history branch renderer. */
396
+ export interface ConversationRow {
397
+ id: string;
398
+ title: string;
399
+ model: string;
400
+ updated_at: string;
401
+ running: boolean;
402
+ kind: 'conversation' | 'channel' | 'task';
403
+ tokens?: number;
404
+ ownerId?: number;
405
+ ownerLabel?: string;
406
+ platform?: string | null;
407
+ direct?: boolean;
408
+ lastWriterId?: number | null;
409
+ lastWriterLabel?: string | null;
410
+ parentSessionId?: string | null;
411
+ }
412
+
413
+ export interface PluginChatPickerProps {
414
+ plugin: string;
415
+ command: string;
416
+ sessionId: string | null;
417
+ argument?: string;
418
+ send: (text: string) => void;
419
+ close: () => void;
420
+ }
421
+
422
+ export interface PluginChatCardProps {
423
+ card: BrainCard;
424
+ sessionId: string | null;
425
+ live: boolean;
426
+ open: (command?: string) => void;
427
+ }
428
+
429
+ export interface PluginChatRailSectionProps {
430
+ variant: 'expanded' | 'compact';
431
+ sessionId: string | null;
432
+ data: unknown;
433
+ open: (target: string) => void;
434
+ closeMobile?: () => void;
435
+ }
436
+
437
+ export interface PluginHistoryBranchProps {
438
+ parent: ConversationRow;
439
+ items: readonly unknown[];
440
+ expanded: boolean;
441
+ toggle: () => void;
442
+ open: (target: string) => void;
443
+ }
444
+
311
445
  /** What a bundle hands to window.__elowenRegisterPluginUi. Routes are `/`-joined segment patterns
312
446
  * (`''` = the root page, `detail/:id` captures params). Contextual component maps are keyed by their
313
447
  * matching manifest panel ids and mount only in the corresponding host surface. */
314
448
  export interface PluginUiRegistration {
315
449
  requiresApiVersion: number;
450
+ dashboardMetrics?: Record<string, ComponentType<DashboardMetricProps>>;
451
+ chatPickers?: Record<string, ComponentType<PluginChatPickerProps>>;
452
+ chatCards?: Record<string, ComponentType<PluginChatCardProps>>;
453
+ chatRailSections?: Record<string, ComponentType<PluginChatRailSectionProps>>;
454
+ historyBranches?: Record<string, ComponentType<PluginHistoryBranchProps>>;
316
455
  pages?: Record<string, ComponentType<PluginPageProps>>;
317
456
  account?: Record<string, ComponentType<PluginPageProps>>;
318
457
  /** For an `account` entry placed as `linkedAccount`: its one-line claim in the CLOSED Linked accounts
@@ -323,6 +462,8 @@ export interface PluginUiRegistration {
323
462
  accountChip?: Record<string, ComponentType<PluginPageProps>>;
324
463
  user?: Record<string, ComponentType<PluginUserPanelProps>>;
325
464
  project?: Record<string, ComponentType<PluginProjectPanelProps>>;
465
+ /** Actions and overlays contributed to the core Projects register. */
466
+ projectRows?: PluginProjectRowsHook;
326
467
  /** Inline chat views keyed by the artifact `view` selected by the publishing plugin. */
327
468
  chatArtifacts?: Record<string, ComponentType<PluginChatArtifactProps>>;
328
469
  settings?: Record<string, ComponentType<PluginPageProps>>;
@@ -342,6 +483,43 @@ export interface PluginUiRegistration {
342
483
  ownsPageFrame?: string[];
343
484
  }
344
485
 
486
+ /** Every component name `window.ElowenUiRuntime.components` actually carries.
487
+ *
488
+ * This used to be `Record<string, …>`, and an open record is how `C.Progress` reached production: the
489
+ * todo rail asked for a primitive the host had never published, the bundle's own typecheck was happy
490
+ * because any string is a key of an open record, and React was handed `undefined` at render time —
491
+ * which the chat rail shows as "the plugin interface hit an error", naming nothing. The host asserts
492
+ * itself against this union (`web/lib/pluginUi.tsx`), so publishing a primitive without listing it
493
+ * here, or listing one the host does not publish, is a type error on the host side rather than a
494
+ * crash on a user's screen.
495
+ *
496
+ * A bundle that declares its own narrowed view of the runtime — which is the recommended shape, since
497
+ * the runtime cannot publish prop types — runs its key names through `AssertPublished` to get the same
498
+ * check in its own repository. */
499
+ export type PluginUiComponentName =
500
+ | 'ActionMenu' | 'AutoSaveStatus' | 'Avatar' | 'BackendPicker' | 'Badge' | 'BrainModelField'
501
+ | 'Button' | 'Calendar' | 'ChangeStrip' | 'Checkbox' | 'ChoiceField' | 'CompactWorkspaceHeader'
502
+ | 'ConfirmDialog' | 'ContextMenu' | 'ControlSurfaceDocument' | 'ControlSurfaceRegister'
503
+ | 'ControlSurfaceState' | 'ControlSurfaceToolbar' | 'DataTable' | 'DataTableCell'
504
+ | 'DataTableChevronCell' | 'DataTableRow' | 'DataTableSelectCell' | 'DateRangeFilter'
505
+ | 'DetailBlock' | 'DirectoryPicker' | 'EmptyState' | 'EntityList' | 'EntityRow' | 'ErrorState'
506
+ | 'ExecutorPicker' | 'Field' | 'HelpTip' | 'IconButton' | 'Input' | 'LinkedAccountRow' | 'LiveTail'
507
+ | 'LoadingLine' | 'LoadingState' | 'ManageSelectionModal' | 'MarkdownAssetEditor' | 'Modal'
508
+ | 'ModalBody' | 'ModalFooter' | 'ModelCatalogField' | 'ModelIcon' | 'ModuleHeader' | 'MotionLayout'
509
+ | 'MotionLayoutItem' | 'MotionPresence' | 'OperationProgressDialog' | 'OutcomeBadge' | 'PageFilters'
510
+ | 'PageToolbar' | 'Pager' | 'PatchView' | 'PluginConfigEditor' | 'PluginPageFrame'
511
+ | 'PluginPageHeader' | 'PluginSection' | 'Progress' | 'ProgressRibbon' | 'ProjectFilterPills'
512
+ | 'ProjectIcon' | 'ProjectPill' | 'RailSectionHead' | 'ProviderLogo' | 'ProviderPicker' | 'RegisterSearch' | 'Segmented'
513
+ | 'SelectMenu' | 'SelectionSummary' | 'SettingsDocument' | 'SettingsGroup' | 'SettingsRow' | 'Slider'
514
+ | 'SpatialIdentity' | 'SpatialWorkspaceLayout' | 'Spinner' | 'SummaryChip' | 'TimeSeriesChart'
515
+ | 'Toggle' | 'WorkspaceDetailRail' | 'WorkspaceHero' | 'WorkspaceMetric' | 'WorkspacePage'
516
+ | 'WorkspaceShell' | 'WorkspaceTakeover';
517
+
518
+ /** Fails the bundle's own typecheck when it names a component the host does not publish. Used as
519
+ * `export type ComponentName = AssertPublished<keyof Components>` beside a bundle's narrowed runtime
520
+ * declaration, where `Components` carries the real prop types the bundle passes. */
521
+ export type AssertPublished<N extends PluginUiComponentName> = N;
522
+
345
523
  /** The host API surface a bundle finds on `window.ElowenUiRuntime`: the HOST's React instance (a
346
524
  * bundle must never ship its own — the build aliases `react` imports here), a curated set of the
347
525
  * app's UI components, an authenticated same-origin `api` fetch, and SPA navigation. */
@@ -350,7 +528,7 @@ export interface ElowenUiRuntime {
350
528
  react: typeof React;
351
529
  reactDom: typeof ReactDom;
352
530
  jsxRuntime: typeof JsxRuntime;
353
- components: Record<string, ComponentType<never>> & {
531
+ components: Record<PluginUiComponentName, ComponentType<never>> & {
354
532
  AutoSaveStatus: ComponentType<AutoSaveStatusProps>;
355
533
  ProjectIcon: ComponentType<ProjectIconProps>;
356
534
  };
package/index.js CHANGED
@@ -2,4 +2,4 @@
2
2
  * `window.ElowenUiRuntime` stamped with this number; a bundle whose `requiresApiVersion` is NEWER
3
3
  * renders a placeholder instead of executing against a contract it was not built for. Bump whenever
4
4
  * a released bundle requires a newly published `ElowenUiRuntime` contract (see index.d.ts). */
5
- export const PLUGIN_UI_API_VERSION = 16;
5
+ export const PLUGIN_UI_API_VERSION = 18;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "elowen-plugin-ui-kit",
3
- "version": "0.11.0",
3
+ "version": "0.13.2",
4
4
  "description": "Contract types and esbuild toolchain for building Elowen plugin browser-UI bundles.",
5
5
  "license": "MIT",
6
6
  "type": "module",
package/theme.css CHANGED
@@ -124,7 +124,7 @@
124
124
  --color-success: #32c986;
125
125
  --color-success-foreground: var(--color-primary-foreground);
126
126
  /* Toasts are outcome banners, not tiny status marks. GitHub's Primer success green gives them the
127
- saturated diff/merge signal Filip expects while keeping white body text above AA contrast. */
127
+ saturated diff/merge signal the owner expects while keeping white body text above AA contrast. */
128
128
  --color-toast-success: #1f883d;
129
129
  --color-toast-success-foreground: #ffffff;
130
130
  --color-warning: #edae49;