@cosmicdrift/kumiko-renderer 0.41.0 → 0.43.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cosmicdrift/kumiko-renderer",
3
- "version": "0.41.0",
3
+ "version": "0.43.0",
4
4
  "description": "Platform-agnostic React renderer for Kumiko screens. Contains the shared logic — primitives-contract, hooks, KumikoScreen, navigation & SSE abstractions — that any platform-specific renderer (web, native) composes. No DOM, no EventSource, no react-dom.",
5
5
  "license": "BUSL-1.1",
6
6
  "author": "Marc Frost <marc@cosmicdriftgamestudio.com>",
@@ -12,6 +12,7 @@ import type {
12
12
  } from "@cosmicdrift/kumiko-headless";
13
13
  import { computeListViewModel } from "@cosmicdrift/kumiko-headless";
14
14
  import { type ReactNode, useCallback, useEffect, useMemo, useState } from "react";
15
+ import { extensionSectionName, useExtensionSectionComponent } from "../app/extension-sections";
15
16
  import type { ListSort } from "../hooks/use-list-url-state";
16
17
  import { type ReferenceLookupMap, useReferenceLookup } from "../hooks/use-reference-lookup";
17
18
  import { useTranslation } from "../i18n";
@@ -299,6 +300,7 @@ export function RenderList(props: RenderListProps): ReactNode {
299
300
  // ListSort = DataTableSort (use-list-url-state aliased) — kein Cast nötig.
300
301
  return (
301
302
  <>
303
+ <ListHeaderSlotMount screen={screen} />
302
304
  {referenceColumns.map(
303
305
  (rc: { field: string; refEntity: string; refFeature: string; labelField: string }) => (
304
306
  <ReferenceLookupBridge
@@ -332,6 +334,25 @@ export function RenderList(props: RenderListProps): ReactNode {
332
334
  );
333
335
  }
334
336
 
337
+ // Header-Slot über der Liste: `screen.slots.header` ist eine
338
+ // PlatformComponent (`{ react: { __component: "X" } }`), aufgelöst über
339
+ // dieselbe ExtensionSectionsProvider-Registry wie entityEdit-Sections.
340
+ // entityId ist null (Listen-Kontext, keine Row); die Component lädt ihre
341
+ // Daten selbst (z.B. ein Cap-Counter aus einer usage-Query). Eigene
342
+ // Component wegen Rules-of-Hooks — useExtensionSectionComponent darf nicht
343
+ // konditional im RenderList-Body laufen.
344
+ function ListHeaderSlotMount({
345
+ screen,
346
+ }: {
347
+ readonly screen: EntityListScreenDefinition;
348
+ }): ReactNode {
349
+ const header = screen.slots?.header;
350
+ const name = header !== undefined ? extensionSectionName(header) : undefined;
351
+ const Component = useExtensionSectionComponent(name);
352
+ if (Component === undefined) return null;
353
+ return <Component entityName={screen.entity} entityId={null} />;
354
+ }
355
+
335
356
  // Tier 2.7e-4: Bridge-Component pro reference-Spalte. Mounted für jede
336
357
  // Spalte einmal, ruft useReferenceLookup unconditional (Hook-Rules
337
358
  // happy), und published die Map über onMap an den Parent. React