@cosmicdrift/kumiko-types 0.349.0 → 0.351.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.
@@ -1,4 +1,4 @@
1
- import type { Temporal } from "temporal-polyfill";
1
+ import type { Temporal } from "./temporal.js";
2
2
  export type RateLimitDecision = {
3
3
  readonly allowed: boolean;
4
4
  readonly limit: number;
package/dist/screen.d.ts CHANGED
@@ -152,9 +152,12 @@ export type RowFieldExtractor = {
152
152
  /** How a row action renders inline in the row-action column. `"button"` is a
153
153
  * bordered button (its colour follows the action's `style`), `"link"` a text
154
154
  * link, `"icon"` an icon-only button (needs a resolved icon, falls back to
155
- * `"link"` without one). Unset: the renderer decides (primary action as link,
156
- * the rest in the kebab menu). */
157
- export type RowActionDisplay = "button" | "link" | "icon";
155
+ * `"link"` without one). `"responsive"` is a `"button"` with icon and label
156
+ * from tablet width up and an icon-only button below it, the label staying the
157
+ * accessible name (needs a resolved icon, falls back to `"button"` without
158
+ * one). Unset: the renderer decides (primary action as link, the rest in the
159
+ * kebab menu). */
160
+ export type RowActionDisplay = "button" | "link" | "icon" | "responsive";
158
161
  /** Row-action column layout. `"adaptive"` (default): primary action as link,
159
162
  * the rest in a kebab menu — except actions with an explicit `display`, which
160
163
  * stay inline. `"inline"`: every action inline, no kebab. */
@@ -688,6 +691,9 @@ export type DashboardPanelQueryOptions = {
688
691
  * `timeRange` still is. */
689
692
  readonly ignoreScreenFilter?: boolean;
690
693
  };
694
+ export type DashboardPanelGate = {
695
+ readonly visibleWhen?: DashboardPanelVisibility;
696
+ };
691
697
  export type DashboardPanelSpan = "half" | "full";
692
698
  export type DashboardPanelEmptyState = {
693
699
  readonly span?: DashboardPanelSpan;
@@ -695,11 +701,11 @@ export type DashboardPanelEmptyState = {
695
701
  /** Second line under `emptyLabel`. */
696
702
  readonly emptyHint?: string;
697
703
  };
698
- export type DashboardStatPanel = DashboardPanelQueryOptions & {
704
+ export type DashboardStatPanel = DashboardPanelQueryOptions & DashboardPanelGate & {
699
705
  readonly kind: "stat";
700
706
  /** Stable id: kebab-case, unique within the panel set. */
701
707
  readonly id: string;
702
- /** Anzeige-Text (i18n-Key). */
708
+ /** Display text (i18n key). */
703
709
  readonly label: string;
704
710
  readonly query: string;
705
711
  readonly valueField: string;
@@ -712,29 +718,46 @@ export type DashboardStatPanel = DashboardPanelQueryOptions & {
712
718
  /** Record field holding `{ atMs, value | null }[]` (MetricResult.points),
713
719
  * drawn as a sparkline next to the value. */
714
720
  readonly sparklineField?: string;
715
- /** Optionaler Delta-Chip (z.B. "↓23 %") neben dem Label. Nur wenn BEIDE
716
- * Felder gesetzt sind UND der Query-Handler sie liefert, rendert der Chip
717
- * — sonst bleibt die Kachel wie ohne Delta. `deltaToneField` fällt auf
718
- * `toneField`/"default" zurück, wenn ungesetzt. */
721
+ /** Delta chip (e.g. "↓23 %") next to the label. It renders only when BOTH
722
+ * fields are set AND the query handler returns them; otherwise the tile
723
+ * looks as it does without a delta. `deltaToneField` falls back to
724
+ * `toneField`/"default" when unset. */
719
725
  readonly deltaField?: string;
720
726
  readonly deltaDirectionField?: string;
721
727
  readonly deltaToneField?: string;
722
- /** Statisches Icon neben dem Label — anders als value/sub/delta variiert
723
- * das Icon nicht pro Query-Result, sondern ist eine Author-Entscheidung
724
- * wie das Panel selbst. Aufgelöst über dieselbe extensionSectionComponents-
725
- * Registry wie custom-Panels; die registrierte Komponente ignoriert
726
- * typischerweise entityName/entityId/filterParams (kein Entity-Kontext
727
- * für ein reines Icon). */
728
+ /** Static icon next to the label. Unlike value/sub/delta it does not vary
729
+ * per query result; it is an author decision like the panel itself.
730
+ * Resolved through the same extensionSectionComponents registry as custom
731
+ * panels; the registered component usually ignores
732
+ * entityName/entityId/filterParams (a plain icon has no entity context). */
728
733
  readonly icon?: PlatformComponent;
729
- /** Statischer CSS-Farbwert (z.B. "var(--color-debt)") für den Icon-Chip —
730
- * Passthrough an die Kachel, keine Registry, kein Lookup. Wirkt NUR wenn
731
- * `icon` gesetzt ist (StatCard rendert den Chip nur zusammen mit einem
732
- * Icon) — ohne icon wird der Wert still verworfen. */
734
+ /** Static CSS color value (e.g. "var(--color-debt)") for the icon chip,
735
+ * passed straight to the tile without a registry lookup. Applies ONLY when
736
+ * `icon` is set (StatCard renders the chip only together with an icon);
737
+ * without an icon the value is silently dropped. */
733
738
  readonly accentColor?: string;
734
739
  };
735
740
  export type DashboardChartKind = "timeseries" | "stacked-bars" | "segment-bars" | "stacked-area";
736
741
  export type DashboardChartTone = "positive" | "negative" | "active" | "neutral";
737
- export type DashboardChartPanel = DashboardPanelQueryOptions & DashboardPanelEmptyState & {
742
+ /** Look of the markers whose `kind` matches: a dashed guide line through the
743
+ * plot plus a colored pin. `color` (raw CSS color) wins over `tone`. */
744
+ export type DashboardChartMarkerKind = {
745
+ readonly tone?: DashboardChartTone;
746
+ readonly color?: string;
747
+ };
748
+ /** One option of a stacked-area range switch. Without `months` the option
749
+ * shows every bucket; with it, a window of that many months anchored at
750
+ * `todayMs` (or the last bucket). `label` is an i18n key. */
751
+ export type DashboardChartRangeOption = {
752
+ readonly value: string;
753
+ readonly label: string;
754
+ readonly months?: number;
755
+ };
756
+ export type DashboardChartRanges = {
757
+ readonly options: readonly DashboardChartRangeOption[];
758
+ readonly default: string;
759
+ };
760
+ export type DashboardChartPanel = DashboardPanelQueryOptions & DashboardPanelEmptyState & DashboardPanelGate & {
738
761
  readonly kind: "chart";
739
762
  readonly id: string;
740
763
  readonly label: string;
@@ -742,34 +765,46 @@ export type DashboardChartPanel = DashboardPanelQueryOptions & DashboardPanelEmp
742
765
  readonly query: string;
743
766
  /** i18n key under the title, e.g. "7 days, by creation day". */
744
767
  readonly subtitle?: string;
745
- /** Series/segment key -> tone; unmapped keys fall back to a palette. */
768
+ /** Series/segment/line key -> tone; unmapped keys fall back to a palette. */
746
769
  readonly seriesTones?: Readonly<Record<string, DashboardChartTone>>;
770
+ /** Series/segment/line key -> raw CSS color (e.g. "var(--color-debt)"); wins over `seriesTones`. */
771
+ readonly seriesColors?: Readonly<Record<string, string>>;
747
772
  /** Formats values as currency (minor units): y ticks, legend totals and tooltips on
748
773
  * stacked-bars/segment-bars/stacked-area, only the y ticks on timeseries. */
749
774
  readonly valueFormat?: DashboardValueFormat;
750
775
  /** Only for chart "stacked-area": fixed width per bucket, plot scrolls horizontally. */
751
776
  readonly scrollable?: boolean;
777
+ /** Only for chart "stacked-area": marker `kind` -> look. Markers without a
778
+ * declared kind keep the neutral numbered pin. */
779
+ readonly markerKinds?: Readonly<Record<string, DashboardChartMarkerKind>>;
780
+ /** Only for chart "stacked-area": false hides the per-series sums in the
781
+ * legend (they mean nothing for balances). Default true. */
782
+ readonly legendTotals?: boolean;
783
+ /** Only for chart "stacked-area": range switch in the panel header. */
784
+ readonly ranges?: DashboardChartRanges;
752
785
  };
753
- export type DashboardListPanel = DashboardPanelQueryOptions & DashboardPanelEmptyState & {
786
+ export type DashboardListPanel = DashboardPanelQueryOptions & DashboardPanelEmptyState & DashboardPanelGate & {
754
787
  readonly kind: "list";
755
788
  readonly id: string;
756
789
  readonly label: string;
757
790
  readonly query: string;
758
791
  readonly columns: readonly ListColumnSpec[];
759
792
  };
760
- export type DashboardStatGroupPanel = {
793
+ export type DashboardStatGroupPanel = DashboardPanelGate & {
761
794
  readonly kind: "stat-group";
762
795
  readonly id: string;
763
796
  readonly label?: string;
797
+ /** i18n key, a line under `label`; the boot validator requires `label`. */
798
+ readonly subtitle?: string;
764
799
  readonly stats: readonly DashboardStatPanel[];
765
800
  };
766
- export type DashboardFeedPanel = DashboardPanelQueryOptions & DashboardPanelEmptyState & {
801
+ export type DashboardFeedPanel = DashboardPanelQueryOptions & DashboardPanelEmptyState & DashboardPanelGate & {
767
802
  readonly kind: "feed";
768
803
  readonly id: string;
769
804
  readonly label: string;
770
805
  readonly query: string;
771
806
  };
772
- export type DashboardProgressListPanel = DashboardPanelQueryOptions & DashboardPanelEmptyState & {
807
+ export type DashboardProgressListPanel = DashboardPanelQueryOptions & DashboardPanelEmptyState & DashboardPanelGate & {
773
808
  readonly kind: "progress-list";
774
809
  readonly id: string;
775
810
  readonly label: string;
@@ -8,8 +8,9 @@ export declare function createSecret<T>(value: T): Secret<T>;
8
8
  export declare function isSecret(v: unknown): v is Secret<unknown>;
9
9
  type Primitive = string | number | boolean | bigint | symbol | null | undefined;
10
10
  type SafeLeaf = Date | RegExp | Temporal.Instant | Temporal.ZonedDateTime | Temporal.PlainDate | Temporal.PlainDateTime | Temporal.PlainTime | Temporal.PlainYearMonth | Temporal.PlainMonthDay | Temporal.Duration | Map<unknown, unknown> | Set<unknown>;
11
- export type ContainsSecret<T> = [T] extends [never] ? false : unknown extends T ? false : T extends Secret<unknown> ? true : T extends Primitive ? false : T extends SafeLeaf ? false : T extends readonly (infer U)[] ? ContainsSecret<U> : T extends object ? true extends {
12
- [K in keyof T]-?: ContainsSecret<T[K]>;
11
+ type MaxSecretDepth = 8;
12
+ export type ContainsSecret<T, Depth extends readonly unknown[] = []> = [T] extends [never] ? false : unknown extends T ? false : Depth["length"] extends MaxSecretDepth ? false : T extends Secret<unknown> ? true : T extends Primitive ? false : T extends SafeLeaf ? false : T extends readonly (infer U)[] ? ContainsSecret<U, [...Depth, unknown]> : T extends object ? true extends {
13
+ [K in keyof T]-?: ContainsSecret<T[K], [...Depth, unknown]>;
13
14
  }[keyof T] ? true : false : false;
14
15
  export type SecretAuditContext = {
15
16
  readonly userId: string;
@@ -0,0 +1,49 @@
1
+ /// <reference types="temporal-polyfill/global" preserve="true" />
2
+ export type TemporalApi = typeof globalThis.Temporal;
3
+ export declare const Temporal: TemporalApi;
4
+ export declare namespace Temporal {
5
+ type ComparisonResult = globalThis.Temporal.ComparisonResult;
6
+ type RoundingMode = globalThis.Temporal.RoundingMode;
7
+ type AssignmentOptions = globalThis.Temporal.AssignmentOptions;
8
+ type DurationOptions = globalThis.Temporal.DurationOptions;
9
+ type ToInstantOptions = globalThis.Temporal.ToInstantOptions;
10
+ type OffsetDisambiguationOptions = globalThis.Temporal.OffsetDisambiguationOptions;
11
+ type ZonedDateTimeAssignmentOptions = globalThis.Temporal.ZonedDateTimeAssignmentOptions;
12
+ type ArithmeticOptions = globalThis.Temporal.ArithmeticOptions;
13
+ type DateUnit = globalThis.Temporal.DateUnit;
14
+ type TimeUnit = globalThis.Temporal.TimeUnit;
15
+ type DateTimeUnit = globalThis.Temporal.DateTimeUnit;
16
+ type ToStringPrecisionOptions = globalThis.Temporal.ToStringPrecisionOptions;
17
+ type ShowCalendarOption = globalThis.Temporal.ShowCalendarOption;
18
+ type CalendarTypeToStringOptions = globalThis.Temporal.CalendarTypeToStringOptions;
19
+ type ZonedDateTimeToStringOptions = globalThis.Temporal.ZonedDateTimeToStringOptions;
20
+ type InstantToStringOptions = globalThis.Temporal.InstantToStringOptions;
21
+ type TransitionDirection = globalThis.Temporal.TransitionDirection;
22
+ type DurationLike = globalThis.Temporal.DurationLike;
23
+ type DurationFormatOptions = globalThis.Temporal.DurationFormatOptions;
24
+ type Duration = globalThis.Temporal.Duration;
25
+ type Instant = globalThis.Temporal.Instant;
26
+ type CalendarLike = globalThis.Temporal.CalendarLike;
27
+ type PlainDateLike = globalThis.Temporal.PlainDateLike;
28
+ type PlainDate = globalThis.Temporal.PlainDate;
29
+ type PlainDateTimeLike = globalThis.Temporal.PlainDateTimeLike;
30
+ type PlainDateTime = globalThis.Temporal.PlainDateTime;
31
+ type PlainMonthDayLike = globalThis.Temporal.PlainMonthDayLike;
32
+ type PlainMonthDay = globalThis.Temporal.PlainMonthDay;
33
+ type PlainTimeLike = globalThis.Temporal.PlainTimeLike;
34
+ type PlainTime = globalThis.Temporal.PlainTime;
35
+ type TimeZoneLike = globalThis.Temporal.TimeZoneLike;
36
+ type PlainYearMonthLike = globalThis.Temporal.PlainYearMonthLike;
37
+ type PlainYearMonth = globalThis.Temporal.PlainYearMonth;
38
+ type ZonedDateTimeLike = globalThis.Temporal.ZonedDateTimeLike;
39
+ type ZonedDateTime = globalThis.Temporal.ZonedDateTime;
40
+ type DurationArithmeticOptions = globalThis.Temporal.DurationArithmeticOptions;
41
+ type DurationRoundTo = globalThis.Temporal.DurationRoundTo;
42
+ type DurationTotalOf = globalThis.Temporal.DurationTotalOf;
43
+ type PluralUnit<T extends globalThis.Temporal.DateTimeUnit> = globalThis.Temporal.PluralUnit<T>;
44
+ type LargestUnit<T extends globalThis.Temporal.DateTimeUnit> = globalThis.Temporal.LargestUnit<T>;
45
+ type SmallestUnit<T extends globalThis.Temporal.DateTimeUnit> = globalThis.Temporal.SmallestUnit<T>;
46
+ type TotalUnit<T extends globalThis.Temporal.DateTimeUnit> = globalThis.Temporal.TotalUnit<T>;
47
+ type DifferenceOptions<T extends globalThis.Temporal.DateTimeUnit> = globalThis.Temporal.DifferenceOptions<T>;
48
+ type RoundTo<T extends globalThis.Temporal.DateTimeUnit> = globalThis.Temporal.RoundTo<T>;
49
+ }
@@ -0,0 +1,12 @@
1
+ /// <reference types="temporal-polyfill/global" preserve="true" />
2
+ import { Temporal as TemporalPolyfill } from "temporal-polyfill";
3
+ function resolveTemporal() {
4
+ // System boundary: same TC39 API, only the typings differ.
5
+ const native = globalThis.Temporal;
6
+ if (native !== undefined)
7
+ return native;
8
+ const polyfill = TemporalPolyfill;
9
+ Object.assign(globalThis, { Temporal: polyfill });
10
+ return polyfill;
11
+ }
12
+ export const Temporal = resolveTemporal();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cosmicdrift/kumiko-types",
3
- "version": "0.349.0",
3
+ "version": "0.351.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": "BUSL-1.1",
6
6
  "author": "Marc Frost <marc@cosmicdriftgamestudio.com>",
@@ -261,6 +261,10 @@
261
261
  "./agent-exposure": {
262
262
  "types": "./dist/agent-exposure.d.ts",
263
263
  "default": "./dist/agent-exposure.js"
264
+ },
265
+ "./temporal": {
266
+ "types": "./dist/temporal.d.ts",
267
+ "default": "./dist/temporal.js"
264
268
  }
265
269
  },
266
270
  "devDependencies": {
@@ -524,6 +528,10 @@
524
528
  "./agent-exposure": {
525
529
  "types": "./dist/agent-exposure.d.ts",
526
530
  "default": "./dist/agent-exposure.js"
531
+ },
532
+ "./temporal": {
533
+ "types": "./dist/temporal.d.ts",
534
+ "default": "./dist/temporal.js"
527
535
  }
528
536
  }
529
537
  },
package/src/changes.json CHANGED
@@ -1,4 +1,17 @@
1
1
  [
2
+ {
3
+ "version": "0.351.0",
4
+ "type": "fix",
5
+ "title": "ContainsSecret no longer fails with TS2615 on recursive types such as DashboardI18nText",
6
+ "detail": "ContainsSecret works on recursive types\n`ContainsSecret<T>` stops after eight levels of nesting. Query handlers whose output contains `DashboardI18nText` (which refers to itself through `i18nParams`) no longer fail to compile with TS2615. A secret nested deeper than that is still caught by the runtime leak guard."
7
+ },
8
+ {
9
+ "version": "0.351.0",
10
+ "type": "improvement",
11
+ "title": "New @cosmicdrift/kumiko-types/temporal export resolves one Temporal (native first, polyfill as fallback) for framework and app code",
12
+ "detail": "One Temporal implementation: `@cosmicdrift/kumiko-types/temporal`\nThe new export returns the native `globalThis.Temporal` when the runtime has it (Bun 1.4, current browsers) and falls back to `temporal-polyfill` otherwise, installing it on `globalThis`. Framework, bundled features and renderers import from there, so values made by the framework pass `instanceof` and `z.instanceof(Temporal.Instant)` checks in app code. `ensureTemporalPolyfill()` puts the same instance on the global. Apps should import `Temporal` from `@cosmicdrift/kumiko-types/temporal` instead of `temporal-polyfill`.",
13
+ "migration": "Replace imports from \"temporal-polyfill\" with \"@cosmicdrift/kumiko-types/temporal\" so app code and framework share one set of Temporal classes."
14
+ },
2
15
  {
3
16
  "version": "0.340.0",
4
17
  "type": "improvement",