@cosmicdrift/kumiko-types 0.410.0 → 0.411.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.
@@ -12,6 +12,14 @@ import type { KmsAdapter } from "./kms-adapter-types.ts";
12
12
  import type { RateLimitResolver } from "./rate-limit-types.ts";
13
13
  import type { SearchAdapter } from "./search-adapter.ts";
14
14
  import type { MasterKeyProvider, SecretsContext } from "./secrets-types.ts";
15
+ /** Addressed live signal: the SSE frame reaches only the listed users of the caller's own tenant. */
16
+ export type UserLiveSignals = {
17
+ push(userIds: readonly string[], signal: {
18
+ readonly type: string;
19
+ readonly entity?: string;
20
+ readonly id?: string;
21
+ }): Promise<void>;
22
+ };
15
23
  /**
16
24
  * Infrastructure the app wired at boot, as the handler or job sees it. extraContext keys the
17
25
  * framework does not know land in `extensions`.
@@ -19,6 +27,7 @@ import type { MasterKeyProvider, SecretsContext } from "./secrets-types.ts";
19
27
  export type ContextServices = {
20
28
  readonly redis?: Redis;
21
29
  readonly cacheSync?: CacheSyncBus;
30
+ readonly userLiveSignals?: UserLiveSignals;
22
31
  readonly jobRunner?: JobRunnerRef;
23
32
  readonly searchAdapter?: SearchAdapter;
24
33
  readonly entityCache?: EntityCache;
@@ -12,14 +12,14 @@ import type { FileContext } from "./file-handle-types.ts";
12
12
  import type { FileProviderResolver } from "./file-provider-resolver-types.ts";
13
13
  import type { GeoTzProvider } from "./geo-tz.ts";
14
14
  import type { BeforeTransactionContext, HandlerAuth, HandlerDb, HandlerDispatch, HandlerEvents, HandlerObservability, JobDispatch, JobEvents, JobObservability, ReservationContext } from "./handler-context-facets.ts";
15
- import type { ContextServices, HandlerLifecycle, HandlerTenants, JobLifecycle } from "./handler-context-services.ts";
15
+ import type { ContextServices, HandlerLifecycle, HandlerTenants, JobLifecycle, UserLiveSignals } from "./handler-context-services.ts";
16
16
  import type { Logger } from "./logger.ts";
17
17
  import type { Meter, Tracer } from "./observability/index.ts";
18
18
  import type { SearchAdapter } from "./search-adapter.ts";
19
19
  import type { CrossTenantReads, TenantDb } from "./tenant-db-types.ts";
20
20
  import type { Clock, TzContext } from "./tz-context.ts";
21
21
  export type { BeforeTransactionContext, HandlerAuth, HandlerDb, HandlerDispatch, HandlerEvents, HandlerObservability, JobDispatch, JobEvents, JobObservability, ReservationContext, } from "./handler-context-facets.ts";
22
- export type { ContextServices, HandlerLifecycle, HandlerTenants, JobLifecycle, } from "./handler-context-services.ts";
22
+ export type { ContextServices, HandlerLifecycle, HandlerTenants, JobLifecycle, UserLiveSignals, } from "./handler-context-services.ts";
23
23
  import type { AgentHandlerHints } from "./agent-hints.ts";
24
24
  export type OpenToAllPersonalData = "tenant-members";
25
25
  export type OpenToAllDeclaration = {
@@ -222,6 +222,7 @@ export type TenantWriteTarget = {
222
222
  type SharedContextFields = {
223
223
  readonly redis?: Redis;
224
224
  readonly cacheSync?: CacheSyncBus;
225
+ readonly userLiveSignals?: UserLiveSignals;
225
226
  readonly jobRunner?: JobRunnerRef;
226
227
  readonly configResolver?: ConfigResolver;
227
228
  readonly config?: ConfigAccessor;
@@ -0,0 +1,42 @@
1
+ export declare const PRESENCE_FEATURE: "presence";
2
+ export declare const PRESENCE_WRITES: {
3
+ readonly heartbeat: "presence:write:heartbeat";
4
+ readonly leave: "presence:write:leave";
5
+ };
6
+ export declare const PRESENCE_QUERIES: {
7
+ readonly list: "presence:query:list";
8
+ };
9
+ export declare const PRESENCE_CHANGED_EVENT: "presence:event:changed";
10
+ export declare const PRESENCE_HEARTBEAT_INTERVAL_MS = 15000;
11
+ export declare const PRESENCE_LIST_REFETCH_INTERVAL_MS = 25000;
12
+ export declare const PRESENCE_FOCUS_MAX_LENGTH = 128;
13
+ export declare const PRESENCE_LIST_MAX_IDS = 100;
14
+ export type PresenceActivity = "viewing" | "editing";
15
+ export type PresenceEntry = {
16
+ readonly userId: string;
17
+ readonly displayName: string;
18
+ readonly activity: PresenceActivity;
19
+ readonly focus?: string;
20
+ /** ISO timestamp from which the user has been in this activity and focus. */
21
+ readonly since: string;
22
+ };
23
+ export type PresenceHeartbeatPayload = {
24
+ readonly entity: string;
25
+ readonly id: string;
26
+ readonly activity: PresenceActivity;
27
+ readonly focus?: string;
28
+ };
29
+ export type PresenceLeavePayload = {
30
+ readonly entity: string;
31
+ readonly id: string;
32
+ };
33
+ export type PresenceListPayload = {
34
+ readonly entity: string;
35
+ readonly ids: readonly string[];
36
+ };
37
+ export type PresenceHeartbeatResult = {
38
+ readonly others: readonly PresenceEntry[];
39
+ };
40
+ export type PresenceListResult = {
41
+ readonly byId: Readonly<Record<string, readonly PresenceEntry[]>>;
42
+ };
@@ -0,0 +1,15 @@
1
+ // Contract between the presence feature (server) and the presence hooks and widgets in the
2
+ // renderer. The renderer must not import bundled-features, so both sides share this file.
3
+ export const PRESENCE_FEATURE = "presence";
4
+ export const PRESENCE_WRITES = {
5
+ heartbeat: "presence:write:heartbeat",
6
+ leave: "presence:write:leave",
7
+ };
8
+ export const PRESENCE_QUERIES = {
9
+ list: "presence:query:list",
10
+ };
11
+ export const PRESENCE_CHANGED_EVENT = "presence:event:changed";
12
+ export const PRESENCE_HEARTBEAT_INTERVAL_MS = 15_000;
13
+ export const PRESENCE_LIST_REFETCH_INTERVAL_MS = 25_000;
14
+ export const PRESENCE_FOCUS_MAX_LENGTH = 128;
15
+ export const PRESENCE_LIST_MAX_IDS = 100;
@@ -127,6 +127,10 @@ type EditFieldsSectionBase = {
127
127
  * and in the "up next" box. Wizard layouts only; unlike `description` it
128
128
  * is not shown inside the step. */
129
129
  readonly subtitle?: string;
130
+ /** Wizard layouts only: text under this step's title in the "up next" box while the step before it is active; falls back to `subtitle`. */
131
+ readonly upNextHint?: string;
132
+ /** Wizard layouts only: field of this section whose formatted value shows under the step label in the step rail once the step is done. Needs a field of this section. */
133
+ readonly summaryField?: string;
130
134
  /** Rendered top-right in the section's Card title row — same
131
135
  * navigate/drawer/writeHandler dispatch as `ProjectionDetailScreenDefinition.actions`,
132
136
  * evaluated against the same record. Every action must resolve an icon
@@ -154,6 +158,14 @@ export type EditExtensionSection = {
154
158
  readonly id?: string;
155
159
  readonly kind: "extension";
156
160
  readonly title: string;
161
+ /** Wizard layouts only: intro text above the step, same slot as `EditFieldsSection.description`. */
162
+ readonly description?: string;
163
+ /** Wizard layouts only: short line under this step's title in the step rail and the "up next" box. */
164
+ readonly subtitle?: string;
165
+ /** Wizard layouts only: text under this step's title in the "up next" box while the step before it is active; falls back to `subtitle`. */
166
+ readonly upNextHint?: string;
167
+ /** Wizard layouts only: field whose formatted value shows under the step label once the step is done. On an `actionForm` it names a field of the screen's `fields`; elsewhere a field of a fields section of the layout. */
168
+ readonly summaryField?: string;
157
169
  readonly component: PlatformComponent;
158
170
  /** When true, the extension registers via `useExtensionFormSubmit` and the
159
171
  * surrounding form's Save button should activate for its dirty state.
@@ -374,16 +386,24 @@ export type EditLayout = {
374
386
  * list of independent preferences rather than one record form. Default
375
387
  * "form" keeps the grid of cells. */
376
388
  readonly variant?: "form" | "settings-list";
389
+ /** Hides the asterisk after required field labels. Default false (shown). */
390
+ readonly hideRequiredMarker?: boolean;
377
391
  /** Persists in-progress wizard state as a resumable draft instead of
378
392
  * discarding it on navigation away. */
379
393
  readonly draft?: boolean;
380
- /** Wizard layouts only. `upNext: true` adds an "up next" box to the step
381
- * rail with the following step's title and `subtitle`; the last step
382
- * shows none. */
394
+ /** Wizard layouts only. `aside.upNext: true` adds an "up next" box to the step
395
+ * rail with the following step's title and its `upNextHint` (else `subtitle`) only.
396
+ * The last step shows the box only with `finishDescription` (i18n key): the
397
+ * finish action as title, that text under it. */
383
398
  readonly wizard?: {
384
399
  readonly aside?: {
385
400
  readonly upNext: true;
401
+ readonly finishDescription?: string;
386
402
  };
403
+ /** Also offers "Save and close" while creating a record (default: update mode only). */
404
+ readonly saveAndCloseOnCreate?: boolean;
405
+ /** Disables the finish button (and blocks the submit) while the condition holds on the form values. */
406
+ readonly submitDisabledWhen?: FieldCondition;
387
407
  };
388
408
  };
389
409
  export type EntityWriteExcludedFields = {
@@ -146,6 +146,8 @@ export type RowActionWriteHandler = {
146
146
  readonly confirmLabel?: string;
147
147
  /** Conditional visibility per row. */
148
148
  readonly visible?: FieldCondition;
149
+ /** projectionDetail header action only: shown while one of these tab (section) ids is active. Needs `layout.mode: "tabs"`; default every tab. */
150
+ readonly showOnTabs?: readonly string[];
149
151
  /** Visual style. "danger" renders red + forces a confirm dialog (even
150
152
  * without an explicit `confirm` key). */
151
153
  readonly style?: "primary" | "secondary" | "danger";
@@ -185,6 +187,8 @@ export type RowActionNavigateBase = {
185
187
  readonly tab?: string;
186
188
  /** Conditional visibility per row. */
187
189
  readonly visible?: FieldCondition;
190
+ /** projectionDetail header action only: shown while one of these tab (section) ids is active. Needs `layout.mode: "tabs"`; default every tab. */
191
+ readonly showOnTabs?: readonly string[];
188
192
  /** Visual style only — unlike the writeHandler variants, "danger" does not
189
193
  * force a confirm dialog here: the target form is the confirmation. */
190
194
  readonly style?: "primary" | "secondary" | "danger";
@@ -228,6 +232,8 @@ export type RowActionDrawer = {
228
232
  readonly params?: RowFieldExtractor;
229
233
  /** Per-row conditional visibility. */
230
234
  readonly visible?: FieldCondition;
235
+ /** projectionDetail header action only: shown while one of these tab (section) ids is active. Needs `layout.mode: "tabs"`; default every tab. */
236
+ readonly showOnTabs?: readonly string[];
231
237
  /** Visual style only — unlike the writeHandler variants, "danger" does not
232
238
  * force a confirm dialog here: the target form is the confirmation. */
233
239
  readonly style?: "primary" | "secondary" | "danger";
@@ -266,6 +272,8 @@ export type RowActionClientAction = {
266
272
  readonly confirmLabel?: string;
267
273
  /** Conditional visibility per row. */
268
274
  readonly visible?: FieldCondition;
275
+ /** projectionDetail header action only: shown while one of these tab (section) ids is active. Needs `layout.mode: "tabs"`; default every tab. */
276
+ readonly showOnTabs?: readonly string[];
269
277
  /** Visual style. "danger" forces a confirm dialog, like a writeHandler. */
270
278
  readonly style?: "primary" | "secondary" | "danger";
271
279
  /** Overrides the id-based default icon, see `RowActionWriteHandler.icon`. */
@@ -3,7 +3,7 @@ export declare const LIST_TABLE_DENSITIES: readonly ["comfortable", "compact"];
3
3
  export type ListTableDensity = (typeof LIST_TABLE_DENSITIES)[number];
4
4
  export declare const LIST_COLUMN_PINS: readonly ["left", "right"];
5
5
  export type ListColumnPin = (typeof LIST_COLUMN_PINS)[number];
6
- export declare const LIST_TABLE_OPTION_KEYS: readonly ["rememberState", "resetAll", "columnPicker", "density", "pinning", "resizing", "keyboardNavigation", "export", "grouping", "totals"];
6
+ export declare const LIST_TABLE_OPTION_KEYS: readonly ["rememberState", "resetAll", "columnPicker", "density", "pinning", "resizing", "keyboardNavigation", "export", "grouping", "totals", "compactHeader"];
7
7
  export declare const LIST_TABLE_GROUPING_KEYS: readonly ["field", "label", "labels", "collapsedWhen", "userChoice", "fields"];
8
8
  export declare const LIST_TABLE_TOTAL_KEYS: readonly ["field", "kind"];
9
9
  export declare const LIST_TABLE_EXPORT_KEYS: readonly ["xlsx", "maxRows"];
@@ -25,6 +25,8 @@ export type ListTableOptions = {
25
25
  readonly resizing?: boolean;
26
26
  /** Rows become one tab stop; ArrowUp/ArrowDown move, Home/End jump, Enter runs the row click. Space stays reserved for selection. */
27
27
  readonly keyboardNavigation?: boolean;
28
+ /** Renders the header row smaller (12px) and semibold. */
29
+ readonly compactHeader?: boolean;
28
30
  readonly density?: {
29
31
  /** Row density on first visit. Default "comfortable". */
30
32
  readonly default?: ListTableDensity;
@@ -11,6 +11,7 @@ export const LIST_TABLE_OPTION_KEYS = [
11
11
  "export",
12
12
  "grouping",
13
13
  "totals",
14
+ "compactHeader",
14
15
  ];
15
16
  export const LIST_TABLE_GROUPING_KEYS = [
16
17
  "field",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cosmicdrift/kumiko-types",
3
- "version": "0.410.0",
3
+ "version": "0.411.0",
4
4
  "description": "Framework-Type-Definitions für Kumiko — FeatureDefinition, BootCheck-Types und die reinen Engine-Types. Erlaubt Downstream-Konsumenten, gegen die Type-Contracts zu bauen, ohne das ganze Framework-Package zu importieren. Enthaelt keine identitaets-sensitiven Runtime-Werte mehr (Error-Klassen leben seit #1629 in kumiko-framework, Brand-Symbole nutzen Symbol.for) und ist deshalb eine plain dependency, keine peerDependency.",
5
5
  "license": "MIT",
6
6
  "author": "Marc Frost <marc@cosmicdriftgamestudio.com>",
@@ -46,6 +46,10 @@
46
46
  "types": "./dist/in-app-notification-types.d.ts",
47
47
  "default": "./dist/in-app-notification-types.js"
48
48
  },
49
+ "./presence-types": {
50
+ "types": "./dist/presence-types.d.ts",
51
+ "default": "./dist/presence-types.js"
52
+ },
49
53
  "./target-ref": {
50
54
  "types": "./dist/target-ref.d.ts",
51
55
  "default": "./dist/target-ref.js"
@@ -349,6 +353,10 @@
349
353
  "types": "./dist/in-app-notification-types.d.ts",
350
354
  "default": "./dist/in-app-notification-types.js"
351
355
  },
356
+ "./presence-types": {
357
+ "types": "./dist/presence-types.d.ts",
358
+ "default": "./dist/presence-types.js"
359
+ },
352
360
  "./target-ref": {
353
361
  "types": "./dist/target-ref.d.ts",
354
362
  "default": "./dist/target-ref.js"