react-semaphor 0.1.545 → 0.1.547

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.
Files changed (159) hide show
  1. package/dist/analytics-protocol/index.js +408 -442
  2. package/dist/assistant-context/index.js +1 -1
  3. package/dist/assistant-protocol/index.js +100 -76
  4. package/dist/brand-studio/index.js +4 -4
  5. package/dist/briefings/index.js +6 -6
  6. package/dist/chunks/{add-to-dashboard-BuAqfA2Y.js → add-to-dashboard-BQRAAnc3.js} +55 -33
  7. package/dist/chunks/{analytics-base-schemas-BFAoRlkU.js → analytics-base-schemas-BKs3flFS.js} +2 -2
  8. package/dist/chunks/applied-constraints-DU-wndZ7.js +47 -0
  9. package/dist/chunks/{assistant-chat-D7sWTypJ.js → assistant-chat-CK84cPAB.js} +2826 -2595
  10. package/dist/chunks/{bookmark-state-CXw7lZ50.js → bookmark-state-Cu-a5ie_.js} +8 -15
  11. package/dist/chunks/comparison-window-caption-C2xF-eWw.js +1433 -0
  12. package/dist/chunks/{context-ClREvqCZ.js → context-BerEBuFR.js} +11 -6
  13. package/dist/chunks/custom-visual-inputs-ChL54gGm.js +295 -0
  14. package/dist/chunks/{dashboard-B1tMju0u.js → dashboard-DCk26-6i.js} +1 -1
  15. package/dist/chunks/{dashboard-briefing-launcher-CePgIu0Z.js → dashboard-briefing-launcher-CQ1eYsGy.js} +1291 -1277
  16. package/dist/chunks/dashboard-controls-BMeZjF7r.js +2307 -0
  17. package/dist/chunks/{dashboard-json-CoYRPqxx.js → dashboard-json-BZqCoanC.js} +5 -5
  18. package/dist/chunks/{document-dashboard-inputs-BesAHZvB.js → document-dashboard-inputs-tYd7ao0o.js} +877 -979
  19. package/dist/chunks/{edit-dashboard-visual-JPtNfJRb.js → edit-dashboard-visual-Bv3MHM_G.js} +2157 -2243
  20. package/dist/chunks/filter-reach-copy-CGWsL_ez.js +3480 -0
  21. package/dist/chunks/{filter-value-text-ff7osJr7.js → filter-value-text-Ddf55Ku1.js} +9 -9
  22. package/dist/chunks/global-date-filter-utils-BhAu8zIM.js +12137 -0
  23. package/dist/chunks/index-CtoK1Lgu.js +586 -0
  24. package/dist/chunks/{index-DRWiuqyd.js → index-DmrLP5Ro.js} +105 -104
  25. package/dist/chunks/list-filter-DsaTbM3J.js +15 -0
  26. package/dist/chunks/matrix-analytical-definition-B9vW-osb.js +717 -0
  27. package/dist/chunks/{matrix-card-DjwWcCo8.js → matrix-card-LiMEipvq.js} +3 -3
  28. package/dist/chunks/{matrix-formatter-DnCyRXJE.js → matrix-formatter-DWEeC0_c.js} +44 -44
  29. package/dist/chunks/{matrix-member-presentation-CQGdVks6.js → matrix-member-presentation-DqzG-UhQ.js} +1 -1
  30. package/dist/chunks/{matrix-operation-contract-8OIO4gob.js → matrix-operation-contract-D6vYkZK4.js} +72 -72
  31. package/dist/chunks/{metric-comparison-DEwi9uc2.js → metric-comparison-zpGw4lD6.js} +2 -2
  32. package/dist/chunks/normalize-dashboard-for-dirty-check-XKgH3GFX.js +119 -0
  33. package/dist/chunks/{pivot-header-presentation-DHcx1XGQ.js → pivot-header-presentation-CQnIDtUv.js} +1 -1
  34. package/dist/chunks/{pivot-result-identity-DJhXXcns.js → pivot-result-identity-C-Q1j1Wb.js} +1 -1
  35. package/dist/chunks/{pivot-result-lifecycle-DM4CyGKs.js → pivot-result-lifecycle-pwq3b7LC.js} +571 -380
  36. package/dist/chunks/{raw-temporal-contract-C51YG48G.js → raw-temporal-contract-WuXA8jBP.js} +1 -1
  37. package/dist/chunks/{raw-temporal-presentation-C3mUgnEx.js → raw-temporal-presentation-DypB7sMX.js} +8 -8
  38. package/dist/chunks/{report-preferences-dialog-DUtuUL_5.js → report-preferences-dialog-DoVyriYC.js} +154 -155
  39. package/dist/chunks/{report-runtime-context-Dq8XyODK.js → report-runtime-context-hWiTCzFV.js} +2 -2
  40. package/dist/chunks/resolve-dashboard-input-context-D0JDUa4h.js +5576 -0
  41. package/dist/chunks/{saved-dashboard-context-LrF_kW0l.js → saved-dashboard-context-BfAH5j4L.js} +34 -34
  42. package/dist/chunks/{selection-reducer-Dj_8xD69.js → selection-reducer-CJzkTZio.js} +15 -15
  43. package/dist/chunks/{semaphor-ready-indicator-BxF96Yhv.js → semaphor-ready-indicator-CRm17oIP.js} +51771 -52574
  44. package/dist/chunks/{shelf-drop-preview-context-CNaM_Gmh.js → shelf-drop-preview-context-vy6P9THz.js} +7 -7
  45. package/dist/chunks/{source-entity-resolution-BYn9giz3.js → source-entity-resolution-BIGRvtbG.js} +13 -13
  46. package/dist/chunks/{switch-uDtPgQlQ.js → switch-CEBOR4n7.js} +3 -3
  47. package/dist/chunks/{table-export-sheet-YzMioA7Y.js → table-export-sheet-4X9mAG3V.js} +1 -1
  48. package/dist/chunks/table-settings-WysCBj62.js +614 -0
  49. package/dist/chunks/{temporal-bucket-D7NBrrtL.js → temporal-bucket-CQOSbv9-.js} +26 -26
  50. package/dist/chunks/{token-types-DBbZVQsm.js → token-types-BMqRmT-C.js} +1 -1
  51. package/dist/chunks/{use-create-flow-overlay-state-CjB7ig1o.js → use-create-flow-overlay-state-Csx_Xjsh.js} +101 -101
  52. package/dist/chunks/{validators-DMHTpf7a.js → validators-C-aOQlTB.js} +713 -658
  53. package/dist/chunks/{relative-date-label-Bk2j94pA.js → zoned-wall-clock-MulfA26h.js} +64 -21
  54. package/dist/dashboard/index.js +2 -2
  55. package/dist/dashboard-authoring/index.js +1895 -1163
  56. package/dist/data-app-sdk/index.js +6 -6
  57. package/dist/data-app-sdk-adapters/index.js +3 -3
  58. package/dist/data-app-sdk-validation/index.js +14 -14
  59. package/dist/format-utils/index.js +133 -133
  60. package/dist/index.js +192 -186
  61. package/dist/layouts/index.js +5 -242
  62. package/dist/report-runtime-context/index.js +2 -2
  63. package/dist/shared/index.js +4 -5
  64. package/dist/style.css +1 -1
  65. package/dist/surfboard/index.js +2 -2
  66. package/dist/types/components/index.d.ts +2 -0
  67. package/dist/types/components/surfboard/arrange-layout-button.d.ts +8 -0
  68. package/dist/types/components/surfboard/filter/types.d.ts +7 -0
  69. package/dist/types/components/surfboard/screen-size-preview-button.d.ts +10 -0
  70. package/dist/types/components/visual/matrix-table/matrix-card-view.d.ts +3 -0
  71. package/dist/types/index.js +6 -6
  72. package/dist/types/lib/charts/table-chart-types.d.ts +4 -0
  73. package/dist/types/lib/charts/types.d.ts +2 -2
  74. package/dist/types/lib/dashboard-inputs/dashboard-filter-mapping-authoring.d.ts +346 -21
  75. package/dist/types/lib/dashboard-inputs/dashboard-filter-value-identity.d.ts +65 -0
  76. package/dist/types/lib/dashboard-inputs/dashboard-input-values.d.ts +6 -0
  77. package/dist/types/lib/dashboard-inputs/filter-settings.d.ts +2 -0
  78. package/dist/types/lib/dashboard-inputs/prepare-loaded-dashboard.d.ts +15 -0
  79. package/dist/types/lib/dashboard-inputs/resolve-selection-input.d.ts +3 -3
  80. package/dist/types/lib/hooks/use-dashboard-card.d.ts +2 -0
  81. package/dist/types/lib/matrix-table/matrix-delivery-policy.d.ts +1 -1
  82. package/dist/types/lib/matrix-table/matrix-editor.d.ts +52 -0
  83. package/dist/types/lib/matrix-table/matrix-runtime-types.d.ts +9 -1
  84. package/dist/types/lib/matrix-table/matrix-runtime.d.ts +5 -1
  85. package/dist/types/lib/query-context/dashboard-filter-mapping-resolution.d.ts +149 -10
  86. package/dist/types/lib/stores/dashboard-store.d.ts +137 -6
  87. package/dist/types/lib/types/common-types.d.ts +8 -0
  88. package/dist/types/lib/types/explorer-types.d.ts +10 -0
  89. package/dist/types/lib/types/semantic-types.d.ts +84 -0
  90. package/dist/types/lib/utils/build-saved-editor-card.d.ts +20 -0
  91. package/dist/types/lib/utils/card-type-change.d.ts +16 -0
  92. package/dist/types/lib/utils/field-availability-context.d.ts +25 -0
  93. package/dist/types/lib/utils/field-placement.d.ts +96 -0
  94. package/dist/types/lib/utils/field-state-calculator.d.ts +161 -0
  95. package/dist/types/lib/utils/qualified-entity-name.d.ts +2 -0
  96. package/dist/types/shared/analytics-protocol/applied-constraints.d.ts +57 -1
  97. package/dist/types/shared/analytics-protocol/field-provenance.d.ts +89 -0
  98. package/dist/types/shared/analytics-protocol/index.d.ts +2 -0
  99. package/dist/types/shared/analytics-protocol/query-policies.d.ts +52 -0
  100. package/dist/types/shared/analytics-protocol/time-window-schema.d.ts +1 -1
  101. package/dist/types/shared/analytics-protocol/time-window.d.ts +40 -1
  102. package/dist/types/shared/assistant-context/saved-dashboard-context.d.ts +4 -1
  103. package/dist/types/shared/assistant-protocol/answer-text.d.ts +20 -0
  104. package/dist/types/shared/assistant-protocol/context.d.ts +29 -29
  105. package/dist/types/shared/assistant-protocol/index.d.ts +1 -0
  106. package/dist/types/shared/assistant-protocol/limits.d.ts +6 -1
  107. package/dist/types/shared/assistant-protocol/parts.d.ts +43 -3
  108. package/dist/types/shared/assistant-protocol/request.d.ts +14 -2
  109. package/dist/types/shared/dashboard-authoring/calculated-field-identity.d.ts +3 -0
  110. package/dist/types/shared/dashboard-authoring/changes/card-query-part.d.ts +487 -0
  111. package/dist/types/shared/dashboard-authoring/changes/card-types.d.ts +34 -0
  112. package/dist/types/shared/dashboard-authoring/changes/dashboard-change.d.ts +7886 -0
  113. package/dist/types/shared/dashboard-authoring/changes/diagnostics.d.ts +45 -0
  114. package/dist/types/shared/dashboard-authoring/changes/read-card-query.d.ts +54 -0
  115. package/dist/types/shared/dashboard-authoring/changes/resolve-dashboard-changes.d.ts +96 -0
  116. package/dist/types/shared/dashboard-authoring/click-to-filter-settings.d.ts +3 -3
  117. package/dist/types/shared/dashboard-authoring/column-catalog.d.ts +32 -0
  118. package/dist/types/shared/dashboard-authoring/contracts.d.ts +0 -55
  119. package/dist/types/shared/dashboard-authoring/control-execution-contract.d.ts +24 -14
  120. package/dist/types/shared/dashboard-authoring/dashboard-card-source-index.d.ts +9 -1
  121. package/dist/types/shared/dashboard-authoring/dashboard-filter-automatic-target.d.ts +4 -4
  122. package/dist/types/shared/dashboard-authoring/dashboard-filter-mapping-contract.d.ts +3 -1
  123. package/dist/types/shared/dashboard-authoring/dashboard-filter-mapping-types.d.ts +27 -1
  124. package/dist/types/shared/dashboard-authoring/dashboard-filter-value-compatibility.d.ts +12 -3
  125. package/dist/types/shared/dashboard-authoring/dashboard-input-scope.d.ts +26 -0
  126. package/dist/types/shared/dashboard-authoring/filter-applicability.d.ts +75 -0
  127. package/dist/types/shared/dashboard-authoring/filter-reach-copy.d.ts +18 -0
  128. package/dist/types/shared/dashboard-authoring/filter-reach-preview.d.ts +97 -0
  129. package/dist/types/shared/dashboard-authoring/index.d.ts +22 -2
  130. package/dist/types/shared/dashboard-authoring/operations/apply-dashboard-operations.d.ts +10 -37
  131. package/dist/types/shared/dashboard-authoring/operations/operation-types.d.ts +189 -0
  132. package/dist/types/shared/dashboard-authoring/outline/outline-dashboard.d.ts +101 -0
  133. package/dist/types/shared/dashboard-authoring/outline/outline-filters.d.ts +100 -0
  134. package/dist/types/shared/dashboard-authoring/semantic-auto-join-card.d.ts +22 -0
  135. package/dist/types/shared/dashboard-authoring/validators.d.ts +1 -2
  136. package/dist/types/shared/layouts/engine/grid.d.ts +25 -0
  137. package/dist/types/shared/layouts/engine/index.d.ts +4 -0
  138. package/dist/types/shared/layouts/engine/sheet-layout.d.ts +7 -0
  139. package/dist/types/shared/layouts/engine/types.d.ts +125 -0
  140. package/dist/types/shared/layouts/index.d.ts +1 -2
  141. package/package.json +2 -2
  142. package/dist/chunks/apply-dashboard-operations-CZEMsx8E.js +0 -2080
  143. package/dist/chunks/calendar-day-equality-dvoQp1xW.js +0 -410
  144. package/dist/chunks/comparison-window-caption-D4E6IHPD.js +0 -1624
  145. package/dist/chunks/custom-visual-inputs-DLCD9Y5V.js +0 -329
  146. package/dist/chunks/dashboard-controls-Cq05n3e0.js +0 -2315
  147. package/dist/chunks/dashboard-filter-value-compatibility-CwQ_iSNb.js +0 -108
  148. package/dist/chunks/matrix-analytical-definition-C7Gb0e12.js +0 -117
  149. package/dist/chunks/normalize-dashboard-for-dirty-check-Bk3VYv_q.js +0 -67
  150. package/dist/chunks/numeric-presentation-7X_IrD58.js +0 -5226
  151. package/dist/chunks/resolve-dashboard-input-context-DJ2tICwz.js +0 -9415
  152. package/dist/chunks/stable-serialize-CfqXeiBP.js +0 -6
  153. package/dist/chunks/table-settings-CLZocegs.js +0 -501
  154. package/dist/chunks/use-debounced-dirty-check-BwAbnX_5.js +0 -59
  155. package/dist/chunks/zoned-wall-clock-BkxV9jS2.js +0 -46
  156. package/dist/types/shared/dashboard-authoring/change-compiler.d.ts +0 -7
  157. package/dist/types/shared/dashboard-authoring/layout-compiler.d.ts +0 -2
  158. package/dist/types/shared/layouts/create-frame-layouts.d.ts +0 -27
  159. package/dist/types/shared/layouts/frame-layouts.d.ts +0 -23
@@ -0,0 +1,75 @@
1
+ import { SemaphorSkippedConstraintReason } from '../analytics-protocol/index.js';
2
+ import { TFilterValue } from '../../components/surfboard/filter/types.js';
3
+ import { TCard } from '../../lib/types/common-types.js';
4
+ import { CardConfig, DataSource } from '../../lib/types/explorer-types.js';
5
+ /**
6
+ * Whether a dashboard filter's value applies to a card: the one rule (MCP
7
+ * dashboard editing ledger V-44). The query builder runs it on every filter
8
+ * value a card receives (semaphor-app build-query); the dashboard's filter
9
+ * mapping decision (`decideDashboardFilterCardTarget`) and every description
10
+ * of reach (the outline, reach warnings, the change resolver's effect check)
11
+ * read it too, so a filter reaches the same cards whether or not it has card
12
+ * mappings. Moved unchanged from semaphor-app
13
+ * `src/lib/analytics/query/filter-applicability.ts`, which re-exports it.
14
+ */
15
+ /** The protocol's skip reasons: evidence reports them as they are (D3b-4). */
16
+ export type FilterSkipReason = SemaphorSkippedConstraintReason;
17
+ export type SkippedFilter = {
18
+ filterId?: string;
19
+ name?: string;
20
+ reason: FilterSkipReason;
21
+ details?: string;
22
+ };
23
+ export declare function formatSkippedFilterWarnings(skipped: ReadonlyArray<{
24
+ filterId?: string;
25
+ name?: string;
26
+ reason: string;
27
+ }>): string[];
28
+ export type FilterApplicabilityResult = {
29
+ applicableFilters: TFilterValue[];
30
+ skippedFilters: SkippedFilter[];
31
+ };
32
+ export type FilterApplicabilityPhase = 'pre_join' | 'post_join';
33
+ export type FilterApplicabilityContext = {
34
+ cardDataSource?: DataSource | null;
35
+ targetQualifiedTableName?: string;
36
+ allowCalculated?: boolean;
37
+ additionalAllowedIdentifiers?: string[];
38
+ phase?: FilterApplicabilityPhase;
39
+ };
40
+ /** The same explicit join sources participate in early and final applicability. */
41
+ export declare function collectJoinPlanIdentifiers(joinPlan: CardConfig['joinPlan'] | null): string[];
42
+ /** Only for physical cards after structural completeness validation. Semantic
43
+ * cards need current catalog dependencies before deciding applicability. Keep
44
+ * unknown or partially overlapping predicates for the authoritative path. */
45
+ export declare function pruneUnrelatedCalculatedFilters(filters: TFilterValue[], context: FilterApplicabilityContext): FilterApplicabilityResult;
46
+ /**
47
+ * How the rule decides one filter value: applied with dataset proof, applied
48
+ * without it (no datasets to check against, a legacy unqualified name, a
49
+ * calculation with unknown dependencies), or skipped with a reason.
50
+ */
51
+ export type FilterApplicabilityDecision = {
52
+ kind: 'apply';
53
+ proven: boolean;
54
+ } | {
55
+ kind: 'skip';
56
+ reason: FilterSkipReason;
57
+ details?: string;
58
+ };
59
+ export declare function applyFilterApplicability(activeFilters: TFilterValue[] | undefined, context: FilterApplicabilityContext): FilterApplicabilityResult;
60
+ /**
61
+ * The applicability context of a card as the query builder runs it: the
62
+ * card's data source, its join plan's entities, and the join phase.
63
+ */
64
+ export declare function filterApplicabilityContextForCard(card: {
65
+ dataSource?: DataSource | null;
66
+ joinPlan?: CardConfig['joinPlan'] | null;
67
+ }): FilterApplicabilityContext;
68
+ /**
69
+ * Whether a filter value reaches a saved card, by the one rule: `reachable`
70
+ * when the card's data (the datasets it selects or joins) proves it takes the
71
+ * value's field, `unreachable` when the rule skips it, `unknown` when the rule
72
+ * keeps it without proof (nothing to check against, a legacy unqualified
73
+ * name, a calculation with unknown dependencies).
74
+ */
75
+ export declare function filterValueReachForCard(filterValue: TFilterValue, card: Pick<TCard, 'dataSource' | 'config'>): 'reachable' | 'unreachable' | 'unknown';
@@ -0,0 +1,18 @@
1
+ import { SemaphorRelationshipRoute, SemaphorSkippedConstraintReason } from '../analytics-protocol/index.js';
2
+ /** "Project" to "Projects", "Category" to "Categories"; a label ending in "s" stays. */
3
+ export declare function pluralDatasetLabel(label: string): string;
4
+ /**
5
+ * P-8 and P-11: "through Project" for a to-one route; "Projects with at least
6
+ * one matching Dashboard" for a to-many route, where Dashboard is the dataset
7
+ * its first to-many step reaches. A route of more than one step names the
8
+ * datasets it passes through, not the filter's own, which it always ends at
9
+ * ("through Crew" for a Company filter; ledger R-21).
10
+ */
11
+ export declare function describeRelationshipRoute(route: SemaphorRelationshipRoute): string;
12
+ /** P-1: a persisted route the domain no longer has. */
13
+ export declare const RELATIONSHIP_ROUTE_CHANGED_MESSAGE = "The relationship this card used changed; choose it again";
14
+ /** P-2, P-3, P-6, P-7: why a value was not applied to a card. */
15
+ export declare function describeRelationshipSkip(reason: SemaphorSkippedConstraintReason, cardDataset?: {
16
+ name: string;
17
+ label?: string;
18
+ }): string;
@@ -0,0 +1,97 @@
1
+ import { SemaphorRelationshipRoute, SemaphorSkippedConstraintReason } from '../analytics-protocol/index.js';
2
+ import { TFilter } from '../../components/surfboard/filter/types.js';
3
+ import { DashboardFilterOptionSource, DashboardFilterRelationshipTarget } from './dashboard-filter-mapping-types.js';
4
+ /**
5
+ * The Cards tab's relationship preview (relationship filter reach, Phase 3):
6
+ * `POST /api/v1/filter-reach` resolves each in-scope card the way its query
7
+ * will, without a value. Authoring only, never on the card query path.
8
+ */
9
+ export type FilterReachRequest = {
10
+ dashboardId: string;
11
+ /** The filter as staged in the settings popover (unsaved edits included). */
12
+ filter: TFilter;
13
+ /** The draft's Option Source; absent when the draft has none (ledger R-04). */
14
+ optionSource?: DashboardFilterOptionSource;
15
+ /** In-scope cards, each as the draft runs it. */
16
+ cards: FilterReachPreviewCard[];
17
+ };
18
+ /** A card to preview, with the route the draft runs it with (ledger R-02). */
19
+ export type FilterReachPreviewCard = {
20
+ cardId: string;
21
+ /**
22
+ * The card's chosen route as the draft stands (RF-D10): a staged choice,
23
+ * else the saved one unless the author dropped it. Absent: the card has no
24
+ * entry of its own, and the preview says what the domain's relationships do.
25
+ */
26
+ target?: DashboardFilterRelationshipTarget;
27
+ };
28
+ /**
29
+ * What the domain's relationships do for a card as the draft runs it
30
+ * (relationship filter reach S-D).
31
+ */
32
+ export type FilterReachCardOutcome = {
33
+ status: 'applied';
34
+ route: SemaphorRelationshipRoute;
35
+ } | {
36
+ status: 'skipped';
37
+ reason: SemaphorSkippedConstraintReason;
38
+ }
39
+ /** More than one equally preferred path: the card skips the filter until one is chosen (P-7). */
40
+ | {
41
+ status: 'needsPath';
42
+ } | {
43
+ status: 'blocked';
44
+ message: string;
45
+ }
46
+ /**
47
+ * The card applies the value as one of its own filters: the value's dataset
48
+ * is one its query already uses (its own filters included), so no route is
49
+ * needed (ledger R-05).
50
+ */
51
+ | {
52
+ status: 'kept';
53
+ }
54
+ /** Reached another way, or not a semantic auto-join card. */
55
+ | {
56
+ status: 'notRelationship';
57
+ };
58
+ /**
59
+ * One card's preview: the outcome for the decision it answers, and the
60
+ * card's paths. A reader shows the outcome only while the card's decision is
61
+ * still the one named in `answers` (RF-INV-15); the paths don't depend on the
62
+ * decision (RF-D27).
63
+ */
64
+ export type FilterReachCardPreview = {
65
+ cardId: string;
66
+ /** The decision this outcome is for: the path ids the request carried for the card, or none. */
67
+ answers: {
68
+ relationshipIds?: string[];
69
+ };
70
+ outcome: FilterReachCardOutcome;
71
+ /** The card's equally preferred paths, worked out with no path chosen; empty without a tie. */
72
+ paths: FilterReachPathOption[];
73
+ };
74
+ /**
75
+ * One path an author can choose, with the target that saves it: built by the
76
+ * server from the filter's value field in the card's domain, never from the
77
+ * browser's guess of that field (ledger R-16).
78
+ */
79
+ export type FilterReachPathOption = {
80
+ route: SemaphorRelationshipRoute;
81
+ target: DashboardFilterRelationshipTarget;
82
+ };
83
+ export type FilterReachResponse = {
84
+ previews: FilterReachCardPreview[];
85
+ /** Present only when the caller can edit the domain the routes run in. */
86
+ manageRelationships?: {
87
+ href: string;
88
+ };
89
+ };
90
+ /** Whether a preview answers a card's decision as it stands: the same path, or no path for both (RF-INV-15). */
91
+ export declare function filterReachPreviewAnswers(preview: Pick<FilterReachCardPreview, 'answers'>, relationshipIds: readonly string[] | undefined): boolean;
92
+ /**
93
+ * Reads a `/api/v1/filter-reach` response body. A malformed preview is
94
+ * dropped whole: one with no decision it answers, an unknown outcome, a
95
+ * malformed path, or a tie with fewer than two paths.
96
+ */
97
+ export declare function readFilterReachResponse(body: unknown): FilterReachResponse;
@@ -2,9 +2,7 @@ export * from './contracts.js';
2
2
  export * from './comparison-document-migration.js';
3
3
  export * from './source-matching.js';
4
4
  export * from './validators.js';
5
- export * from './layout-compiler.js';
6
5
  export * from './artifact-compiler.js';
7
- export * from './change-compiler.js';
8
6
  export * from './protocol-adapter.js';
9
7
  export * from './temporal-result-owner.js';
10
8
  export * from './temporal-bucket-authoring.js';
@@ -39,3 +37,25 @@ export { matrixCatalogSources, matrixExecutionSources } from './matrix-control-s
39
37
  export * from './dashboard-option-dependencies.js';
40
38
  export * from './new-card.js';
41
39
  export * from './operations/apply-dashboard-operations.js';
40
+ export * from './changes/card-types.js';
41
+ export * from './changes/diagnostics.js';
42
+ export * from './changes/card-query-part.js';
43
+ export * from './changes/read-card-query.js';
44
+ export * from './changes/dashboard-change.js';
45
+ export * from './changes/resolve-dashboard-changes.js';
46
+ export * from './outline/outline-filters.js';
47
+ export * from './outline/outline-dashboard.js';
48
+ export * from './column-catalog.js';
49
+ export { prepareLoadedDashboard } from '../../lib/dashboard-inputs/prepare-loaded-dashboard.js';
50
+ export { buildFilterInputFromField, buildFilterInputFromDefinition, applyFilterSettingsChange } from '../../lib/dashboard-inputs/filter-settings.js';
51
+ export { relationshipRouteTarget } from '../../lib/dashboard-inputs/dashboard-filter-value-identity.js';
52
+ export type { FilterSettingsChange, FilterValueEffect } from '../../lib/dashboard-inputs/filter-settings.js';
53
+ export { describeDashboardFilterCardReach, describeDashboardFilterCardReachDetail, type DashboardFilterCardReach, type DashboardFilterCardReachDetail, type DashboardRelationshipReachResolver, } from '../../lib/query-context/dashboard-filter-mapping-resolution.js';
54
+ export { changeCardType, sharedCardPreferences, type CardTypeChange, type CardTypeChangeOptions, } from '../../lib/utils/card-type-change.js';
55
+ export { buildSavedEditorCard } from '../../lib/utils/build-saved-editor-card.js';
56
+ export { getCardDefinition, type AuthoredCardFields } from '../../lib/utils/card-definition.js';
57
+ export { changeMatrixEditor, dropMatrixEditorField, matrixEditorCatalogFromFields, } from '../../lib/matrix-table/matrix-editor.js';
58
+ export * from './filter-applicability.js';
59
+ export * from './semantic-auto-join-card.js';
60
+ export * from './filter-reach-preview.js';
61
+ export * from './filter-reach-copy.js';
@@ -1,40 +1,13 @@
1
- import { TDashboard, TFrame } from '../../../lib/types/common-types.js';
1
+ import { TDashboard } from '../../../lib/types/common-types.js';
2
+ import { DashboardOperation, DashboardOperationResult, OperationContext } from './operation-types.js';
3
+ export type { CardUpdate, CreatedEntity, DashboardOperation, DashboardOperationResult, DashboardRuntimeEffect, FrameCommit, FramePlacement, OperationContext, OperationDescription, OperationFailureCode, } from './operation-types.js';
2
4
  /**
3
5
  * Edits to a dashboard as operations on one pure reducer (analytics agent
4
- * Plan 1, AG-D14, Phase 7a). Every writer of these edits calls it: the
5
- * store's actions in the browser, and later an API or MCP edit on the
6
- * server. Callers that differ pass their differences in (placement, ids);
7
- * none keeps its own copy of the edit.
6
+ * Plan 1 AG-D14; MCP dashboard editing SPEC 3.3, 3.8). The one writer of the
7
+ * saved document for these edits: the editor stores, the change resolver's
8
+ * dry run and the server's apply all call it. It writes only the document; it
9
+ * returns what it created, one plain sentence per change, and the runtime
10
+ * effects a live editor applies to its own state (DE-D49). It never mints ids
11
+ * and never reads the clock (S-INV-1).
8
12
  */
9
- /** Where a new frame goes on its sheet: first, last, or right after a frame and beside it. */
10
- export type DashboardFramePlacement = 'start' | 'end' | {
11
- beside: string;
12
- };
13
- export type DashboardOperation = {
14
- op: 'frame.add';
15
- sheetId: string;
16
- /** The frame with its cards, ids included. */
17
- frame: TFrame;
18
- /** Default `end`. */
19
- placement?: DashboardFramePlacement;
20
- };
21
- export type DashboardOperationFailureCode = 'sheet_not_found'
22
- /** A document sheet places cards through its document, not its grid. */
23
- | 'sheet_not_a_grid' | 'frame_id_taken';
24
- export type DashboardOperationResult = {
25
- ok: true;
26
- dashboard: TDashboard;
27
- } | {
28
- ok: false;
29
- failedAt: {
30
- index: number;
31
- op: DashboardOperation['op'];
32
- code: DashboardOperationFailureCode;
33
- message: string;
34
- };
35
- };
36
- /**
37
- * Applies the operations in order, all or nothing. Never changes its input:
38
- * the result shares every sheet it did not touch.
39
- */
40
- export declare function applyDashboardOperations(dashboard: TDashboard, operations: DashboardOperation[]): DashboardOperationResult;
13
+ export declare function applyDashboardOperations(dashboard: TDashboard, operations: readonly DashboardOperation[], context: OperationContext): DashboardOperationResult;
@@ -0,0 +1,189 @@
1
+ import { EmbeddedFilterDashboardInput, TDashboard, TFrame } from '../../../lib/types/common-types.js';
2
+ import { FilterSettingsChange, FilterValueEffect } from '../../../lib/dashboard-inputs/filter-settings.js';
3
+ import { DashboardFilterBoundCardApplication } from '../dashboard-filter-mapping-types.js';
4
+ import { Field } from '../../../lib/types/explorer-types.js';
5
+ import { TChartType } from '../../../lib/charts/types.js';
6
+ import { CalendarContext } from '../../report-runtime-context/index.js';
7
+ import { CardQueryPart, StatedLabel } from '../changes/card-query-part.js';
8
+ import { FramePlacement } from '../../layouts/index.js';
9
+ /**
10
+ * The resolved operations the dashboard reducer applies (MCP dashboard
11
+ * editing SPEC 3.3, 3.8). Every id an operation creates is in it; the reducer
12
+ * never generates ids and never reads the clock (S-INV-1).
13
+ */
14
+ /** Where a new frame goes on its sheet, by intent (responsive layouts SPEC §2.4). Absent: placed by kind. */
15
+ export type { FramePlacement };
16
+ export type CardUpdate =
17
+ /** Inline title and description edits; `description: null` removes it. */
18
+ {
19
+ kind: 'rename';
20
+ title?: string;
21
+ description?: string | null;
22
+ }
23
+ /**
24
+ * A type transition: the editor's `changeCardType`, then the layout resize.
25
+ * `catalog` is the loaded column catalog a Matrix crossing needs; `newIds`
26
+ * every id the conversion mints, in the order it asks for them (DE-D54).
27
+ */
28
+ | {
29
+ kind: 'retype';
30
+ type: TChartType;
31
+ catalog?: readonly Field[];
32
+ newIds: string[];
33
+ }
34
+ /** A new computed part for the card's current type; presentation is carried (SPEC 3.4). */
35
+ | {
36
+ kind: 'requery';
37
+ query: CardQueryPart;
38
+ }
39
+ /** Labels a change states on columns it doesn't rebuild, set in place by the label owner; nothing is recompiled (DE-D61). */
40
+ | {
41
+ kind: 'relabel';
42
+ labels: StatedLabel[];
43
+ };
44
+ /** Everything the editor's "Done", Save & Apply and Apply Local commit persists, as one operation (DE-D13). */
45
+ export type FrameCommit = {
46
+ sheetId: string;
47
+ /** The edited frame as the editor built it. Apply Local passes `visualId: undefined`. */
48
+ frame: TFrame;
49
+ /** Other frames on the sheet rewritten during the edit (calculated-field renames), applied with it. */
50
+ rewrittenFrames?: TFrame[];
51
+ /** Sheet calculated fields from the edited frame, persisted on the sheet. */
52
+ sheetCalculatedFields?: Field[];
53
+ /** Dashboard calculated fields rewritten during the edit. */
54
+ dashboardCalculatedFields?: Field[];
55
+ /** True when committed from the visual editor: resize the frame's layouts if its type changed. */
56
+ resizeLayouts: boolean;
57
+ };
58
+ export type DashboardOperation = ({
59
+ op: 'card.add';
60
+ sheetId: string;
61
+ /** The frame with its cards, ids included. */
62
+ frame: TFrame;
63
+ /** By intent; absent: placed by kind (responsive layouts SPEC §4.2). */
64
+ placement?: FramePlacement;
65
+ } | {
66
+ op: 'card.update';
67
+ cardId: string;
68
+ update: CardUpdate;
69
+ } | {
70
+ op: 'card.remove';
71
+ cardId: string;
72
+ }
73
+ /** Arrange a grid sheet by kind (responsive layouts RL-D7, SPEC §4.4); `keepOrder` keeps the reading order. */
74
+ | {
75
+ op: 'layout.arrange';
76
+ sheetId: string;
77
+ keepOrder?: boolean;
78
+ }
79
+ /** The editor's whole-frame commit; never produced by the resolver. */
80
+ | {
81
+ op: 'frame.commit';
82
+ commit: FrameCommit;
83
+ }
84
+ /** A new filter input, ids included; its defaults are in its definition, as the editor adds one. */
85
+ | {
86
+ op: 'filter.add';
87
+ input: EmbeddedFilterDashboardInput;
88
+ }
89
+ /** Settings through the editor's core (`applyFilterSettingsChange`); `filterId` is the input id. */
90
+ | {
91
+ op: 'filter.update';
92
+ filterId: string;
93
+ settings: FilterSettingsChange;
94
+ } | {
95
+ op: 'filter.remove';
96
+ filterId: string;
97
+ }
98
+ /** The card's bound entry in the filter's mapping, built as the mapping editor builds one. */
99
+ | {
100
+ op: 'filter.bind';
101
+ filterId: string;
102
+ cardId: string;
103
+ binding: DashboardFilterBoundCardApplication;
104
+ } | {
105
+ op: 'filter.exclude';
106
+ filterId: string;
107
+ cardId: string;
108
+ }) & {
109
+ /** Set by the resolver: the public change this operation came from. Descriptions group by it. */
110
+ changeIndex?: number;
111
+ };
112
+ export type OperationContext = {
113
+ /** The report calendar; filter defaults resolve in it. A proposal's has a fixed anchor (DE-D59). */
114
+ calendar: CalendarContext | null;
115
+ };
116
+ export type CreatedEntity = {
117
+ kind: 'card' | 'filter';
118
+ id: string;
119
+ title: string;
120
+ changeIndex?: number;
121
+ };
122
+ export type OperationDescription = {
123
+ /** Operations with the same changeIndex share one description. */
124
+ changeIndex?: number;
125
+ /** Indexes into the operations list. */
126
+ operations: number[];
127
+ sentence: string;
128
+ };
129
+ /** What a live editor must do to its own state after an operation. The server ignores them (DE-D49). */
130
+ export type DashboardRuntimeEffect =
131
+ /** card.remove, and frame.commit dropping tabs: drop live state keyed by these cards. */
132
+ {
133
+ kind: 'cards_removed';
134
+ cardIds: string[];
135
+ }
136
+ /** frame.commit: re-sync inline filter runtime values from the frame before and after. */
137
+ | {
138
+ kind: 'frame_committed';
139
+ sheetId: string;
140
+ before: TFrame;
141
+ after: TFrame;
142
+ }
143
+ /**
144
+ * filter.update: `applyFilterSettingsChange`'s value effects, unchanged. One
145
+ * per update, even with none: the store still re-resolves forced selections,
146
+ * as `saveFilterSettings` always has (ledger P3-02).
147
+ */
148
+ | {
149
+ kind: 'filter_value';
150
+ effects: FilterValueEffect[];
151
+ }
152
+ /** filter.remove: drop the input's live values. */
153
+ | {
154
+ kind: 'input_removed';
155
+ inputId: string;
156
+ };
157
+ export type OperationFailureCode = 'sheet_not_found'
158
+ /** A document sheet places cards through its document, not its grid. */
159
+ | 'sheet_not_a_grid' | 'frame_id_taken' | 'frame_not_found' | 'card_not_found' | 'filter_not_found' | 'filter_id_taken'
160
+ /** The filter settings or mapping fail the input contract; `details.issues` has the core's issues. */
161
+ | 'filter_invalid'
162
+ /** A requery part compiled for another type than the card's. */
163
+ | 'query_type_mismatch'
164
+ /** A requery part that doesn't make a valid card (a Matrix definition the Matrix contract refuses). */
165
+ | 'query_invalid'
166
+ /** A requery would change a part of the card its change doesn't state (DE-D61). */
167
+ | 'query_not_kept'
168
+ /** A conversion asked for more ids than the operation carries. */
169
+ | 'ids_exhausted'
170
+ /** A retype across the Matrix boundary without a catalog. */
171
+ | 'catalog_loading';
172
+ export type DashboardOperationResult = {
173
+ ok: true;
174
+ dashboard: TDashboard;
175
+ created: CreatedEntity[];
176
+ /** One plain sentence per public change (or per operation without a changeIndex). */
177
+ descriptions: OperationDescription[];
178
+ runtimeEffects: DashboardRuntimeEffect[];
179
+ } | {
180
+ ok: false;
181
+ failedAt: {
182
+ index: number;
183
+ op: DashboardOperation['op'];
184
+ code: OperationFailureCode;
185
+ message: string;
186
+ fix?: string;
187
+ details?: Record<string, unknown>;
188
+ };
189
+ };
@@ -0,0 +1,101 @@
1
+ import { DashboardRelationshipReachResolver } from '../../../lib/query-context/dashboard-filter-mapping-resolution.js';
2
+ import { TDashboard } from '../../../lib/types/common-types.js';
3
+ import { FrameWidth } from '../../layouts/index.js';
4
+ import { NotEditableReason, OutlineCardSource } from '../changes/read-card-query.js';
5
+ import { CardQuery, MatrixColumns } from '../changes/dashboard-change.js';
6
+ import { OutlineFilter } from './outline-filters.js';
7
+ import { CalendarContext } from '../../report-runtime-context/index.js';
8
+ /**
9
+ * A dashboard in the change vocabulary (MCP dashboard editing SPEC 3.6,
10
+ * DE-D29, DE-D34): every sheet, every card the shared traversal lists
11
+ * (Document-section cards included, read only), every filter, and what the
12
+ * viewer may do. A pure function of the hydrated dashboard and the viewer
13
+ * (S-INV-8): no clock, no catalog, no network.
14
+ */
15
+ export type OutlineViewer = {
16
+ dashboardId: string;
17
+ /** `Dashboard.updatedAt`, ISO 8601; the staleness token, never called "version" (DE-D37). */
18
+ updatedAt: string;
19
+ access: {
20
+ canEdit: boolean;
21
+ canCopy: boolean;
22
+ };
23
+ sql: boolean;
24
+ sheetIds?: string[];
25
+ cardIds?: string[];
26
+ /** Above this many cards (after narrowing), queries are left out. Default 50 (DE-D34). */
27
+ maxQueryCards?: number;
28
+ /** The report calendar filter defaults are read in; without one, a fixed calendar at `updatedAt` (S-INV-8). */
29
+ calendar?: CalendarContext;
30
+ /**
31
+ * Server side only: resolves relationship reach the way the card query
32
+ * does, with each card's domain preloaded (relationship filter reach RF-D15).
33
+ * Without one, such cards are listed under `relationshipPending`.
34
+ */
35
+ relationshipReach?: DashboardRelationshipReachResolver;
36
+ };
37
+ export type OutlineCard = {
38
+ cardId: string;
39
+ title: string;
40
+ /** The public type name (DE-D43). */
41
+ type: string;
42
+ source: OutlineCardSource;
43
+ /** Shows a library visual; changing it makes it local (DE-D50). */
44
+ linkedVisualId?: string;
45
+ editable: true;
46
+ /** Absent only when the outline is truncated. */
47
+ query?: CardQuery;
48
+ matrix?: MatrixColumns;
49
+ } | {
50
+ cardId: string;
51
+ title: string;
52
+ type: string;
53
+ source?: OutlineCardSource;
54
+ linkedVisualId?: string;
55
+ editable: false;
56
+ notEditable: {
57
+ reason: NotEditableReason;
58
+ message: string;
59
+ detail?: string;
60
+ };
61
+ };
62
+ export type OutlineSheet = {
63
+ sheetId: string;
64
+ title: string;
65
+ /** Cards can be added only to "dashboard" sheets. */
66
+ kind: 'dashboard' | 'document';
67
+ /** On a Document sheet, its sections' cards (never editable). */
68
+ cards: OutlineCard[];
69
+ /**
70
+ * Grid sheets only: the desktop layout as rows, top to bottom, from the
71
+ * layout engine (responsive layouts RL-D10). Always the whole sheet, even
72
+ * when `cardIds` narrows the cards. Absent on Document sheets.
73
+ */
74
+ layout?: OutlineLayoutRow[];
75
+ };
76
+ /** One row of a sheet's desktop layout. A tile is a frame: its cards, active first, and its width by intent. Never coordinates (RL-INV-5). */
77
+ export type OutlineLayoutRow = {
78
+ tiles: Array<{
79
+ cardIds: string[];
80
+ width: FrameWidth;
81
+ }>;
82
+ };
83
+ export type DashboardOutline = {
84
+ dashboardId: string;
85
+ title: string;
86
+ updatedAt: string;
87
+ access: {
88
+ canEdit: boolean;
89
+ canCopy: boolean;
90
+ };
91
+ /** Every dataset a card or filter uses. */
92
+ datasets: Array<{
93
+ domainId: string;
94
+ datasetName: string;
95
+ }>;
96
+ sheets: OutlineSheet[];
97
+ filters: OutlineFilter[];
98
+ /** Queries left out because the dashboard has more than `maxQueryCards` cards (DE-D34). */
99
+ truncated?: true;
100
+ };
101
+ export declare function outlineDashboard(dashboard: TDashboard, viewer: OutlineViewer): DashboardOutline;
@@ -0,0 +1,100 @@
1
+ import { TDashboard } from '../../../lib/types/common-types.js';
2
+ import { DashboardRelationshipReachResolver } from '../../../lib/query-context/dashboard-filter-mapping-resolution.js';
3
+ import { SemaphorSkippedConstraintReason } from '../../analytics-protocol/index.js';
4
+ import { FilterInputEntry } from '../filter-model/index.js';
5
+ import { CalendarContext } from '../../report-runtime-context/index.js';
6
+ import { FilterValue, TimeWindow } from '../changes/dashboard-change.js';
7
+ /**
8
+ * Every dashboard filter in the change vocabulary (MCP dashboard editing
9
+ * DE-D58, SPEC 3.6). A field filter on one semantic dataset shown on every
10
+ * grid sheet or a list of sheets is editable; any other filter is a
11
+ * read-only summary with its reach and a reason, never left out and never
12
+ * given invented coordinates. Reach is read the way each card runs the
13
+ * filter (`describeDashboardFilterCardReach`).
14
+ */
15
+ export type FilterNotEditableReason = 'global_date' | 'not_semantic' | 'scope_not_expressible';
16
+ export type OutlineFilter = {
17
+ filterId: string;
18
+ label: string;
19
+ editable: true;
20
+ domainId: string;
21
+ datasetName: string;
22
+ field: string;
23
+ selection: 'single' | 'multiple';
24
+ /** The values it loads with, read through the default owner (a saved default first, else the definition). */
25
+ defaultValues?: FilterValue[];
26
+ /** The window it loads with, only when the loaded default keeps one (a day picker clamps a wider window to a day). */
27
+ defaultPeriod?: TimeWindow;
28
+ /** For a date filter, the picker a viewer gets: one day, one month, or a range. */
29
+ datePicker?: 'day' | 'month' | 'range';
30
+ /** "all": every grid sheet. */
31
+ sheetIds: string[] | 'all';
32
+ /** With "all": the sheets it leaves out ("every sheet except"); a sheet added later is reached. */
33
+ exceptSheetIds?: string[];
34
+ /** With "all": it also shows on Document sheets (their sections' cards). */
35
+ includesDocumentSheets?: true;
36
+ /** Card ids the filter applies to. */
37
+ reaches: string[];
38
+ /** Card ids excluded explicitly. */
39
+ excluded: string[];
40
+ /** In scope, not matched; with a resolver (server side), the reason relationship reach gave. */
41
+ notReached: Array<{
42
+ cardId: string;
43
+ title: string;
44
+ datasetName?: string;
45
+ reason?: SemaphorSkippedConstraintReason;
46
+ }>;
47
+ /** In scope, and blocked when the filter has a value: a binding the card can't run, or two fields it could take. */
48
+ blocked?: Array<{
49
+ cardId: string;
50
+ title: string;
51
+ reason: 'blocked' | 'ambiguous';
52
+ }>;
53
+ /**
54
+ * In scope, on another dataset of the card's domain: the server decides
55
+ * when the card runs, through the domain's relationships, whether the
56
+ * filter applies. Never counted as reached.
57
+ */
58
+ relationshipPending?: Array<{
59
+ cardId: string;
60
+ title: string;
61
+ datasetName?: string;
62
+ }>;
63
+ } | {
64
+ filterId: string;
65
+ label: string;
66
+ editable: false;
67
+ kind: 'global_date' | 'field' | 'other';
68
+ notEditable: {
69
+ reason: FilterNotEditableReason;
70
+ message: string;
71
+ };
72
+ reaches: string[];
73
+ excluded: string[];
74
+ blocked?: Array<{
75
+ cardId: string;
76
+ title: string;
77
+ reason: 'blocked' | 'ambiguous';
78
+ }>;
79
+ relationshipPending?: Array<{
80
+ cardId: string;
81
+ title: string;
82
+ datasetName?: string;
83
+ }>;
84
+ };
85
+ /** Server-side readers resolve relationship reach the way the card query does (RF-D15). */
86
+ export type OutlineReachOptions = {
87
+ relationshipReach?: DashboardRelationshipReachResolver;
88
+ };
89
+ /**
90
+ * The calendar a summary reads defaults in: the report's, else a fixed one at
91
+ * the dashboard's own time, so a summary stays a pure function of its inputs.
92
+ * Only whether a default keeps its window is reported, never the dates it
93
+ * resolves to.
94
+ */
95
+ export declare function outlineCalendar(calendar: CalendarContext | undefined, updatedAt: string | undefined): CalendarContext;
96
+ export declare function summarizeFilter(dashboard: TDashboard, entry: FilterInputEntry, calendar?: CalendarContext, options?: OutlineReachOptions): OutlineFilter;
97
+ /** Every filter on the dashboard, in the filter model's order. */
98
+ export declare function outlineFilters(dashboard: TDashboard, calendar?: CalendarContext, options?: OutlineReachOptions): OutlineFilter[];
99
+ /** One filter by its input id, or undefined. */
100
+ export declare function outlineFilter(dashboard: TDashboard, filterId: string, calendar?: CalendarContext, options?: OutlineReachOptions): OutlineFilter | undefined;