@altertable/data-app 0.59.1

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 (174) hide show
  1. package/AGENTS.md +35 -0
  2. package/CONTRIBUTING.md +83 -0
  3. package/LICENSE +21 -0
  4. package/README.md +63 -0
  5. package/dist/bootstrap.js +388 -0
  6. package/dist/chunks/contract-14vxdcrs.js +192 -0
  7. package/dist/chunks/contract-14vxdcrs.js.map +10 -0
  8. package/dist/chunks/contract-8q35dcyh.js +9 -0
  9. package/dist/chunks/contract-8q35dcyh.js.map +10 -0
  10. package/dist/chunks/contract-jksbmt5q.js +133 -0
  11. package/dist/chunks/contract-jksbmt5q.js.map +10 -0
  12. package/dist/chunks/contract-mb5nfzwg.js +375 -0
  13. package/dist/chunks/contract-mb5nfzwg.js.map +12 -0
  14. package/dist/chunks/contract-mev09s5v.js +77 -0
  15. package/dist/chunks/contract-mev09s5v.js.map +10 -0
  16. package/dist/chunks/contract-nt819swq.js +321 -0
  17. package/dist/chunks/contract-nt819swq.js.map +11 -0
  18. package/dist/chunks/contract-ryyf6dme.js +21 -0
  19. package/dist/chunks/contract-ryyf6dme.js.map +10 -0
  20. package/dist/chunks/contract-tkkc28tg.js +213 -0
  21. package/dist/chunks/contract-tkkc28tg.js.map +12 -0
  22. package/dist/chunks/contract-tqrf3ykr.js +232 -0
  23. package/dist/chunks/contract-tqrf3ykr.js.map +11 -0
  24. package/dist/chunks/contract-wz59z8pq.js +8 -0
  25. package/dist/chunks/contract-wz59z8pq.js.map +10 -0
  26. package/dist/client/index.js +27 -0
  27. package/dist/client/index.js.map +9 -0
  28. package/dist/core/appearance.js +12 -0
  29. package/dist/core/appearance.js.map +9 -0
  30. package/dist/core/config.js +8 -0
  31. package/dist/core/config.js.map +9 -0
  32. package/dist/core/contract.js +55 -0
  33. package/dist/core/contract.js.map +9 -0
  34. package/dist/core/format.js +18 -0
  35. package/dist/core/format.js.map +9 -0
  36. package/dist/embed/index.js +91 -0
  37. package/dist/embed/index.js.map +11 -0
  38. package/dist/local.js +332 -0
  39. package/dist/local.js.map +15 -0
  40. package/dist/react/embed/index.js +130 -0
  41. package/dist/react/embed/index.js.map +11 -0
  42. package/dist/react/index.css +4478 -0
  43. package/dist/react/index.js +6105 -0
  44. package/dist/react/index.js.map +90 -0
  45. package/dist/react.css.d.ts +1 -0
  46. package/dist/server.js +231 -0
  47. package/dist/server.js.map +14 -0
  48. package/dist/types/client/iframe.d.ts +39 -0
  49. package/dist/types/client/index.d.ts +42 -0
  50. package/dist/types/client/location.d.ts +15 -0
  51. package/dist/types/client/messages.d.ts +7 -0
  52. package/dist/types/client/navigation.d.ts +14 -0
  53. package/dist/types/client/transport.d.ts +15 -0
  54. package/dist/types/core/appearance.d.ts +28 -0
  55. package/dist/types/core/bridge.d.ts +35 -0
  56. package/dist/types/core/config.d.ts +14 -0
  57. package/dist/types/core/contract.d.ts +139 -0
  58. package/dist/types/core/data-view.d.ts +46 -0
  59. package/dist/types/core/date-range.d.ts +20 -0
  60. package/dist/types/core/dimension.d.ts +60 -0
  61. package/dist/types/core/format.d.ts +40 -0
  62. package/dist/types/core/invariant.d.ts +2 -0
  63. package/dist/types/core/messages.d.ts +77 -0
  64. package/dist/types/core/reading.d.ts +17 -0
  65. package/dist/types/core/variables.d.ts +82 -0
  66. package/dist/types/embed/bootstrap.d.ts +5 -0
  67. package/dist/types/embed/host.d.ts +23 -0
  68. package/dist/types/embed/index.d.ts +11 -0
  69. package/dist/types/embed/navigation.d.ts +6 -0
  70. package/dist/types/embed/shell.d.ts +21 -0
  71. package/dist/types/embed/standalone.d.ts +1 -0
  72. package/dist/types/react/content.d.ts +23 -0
  73. package/dist/types/react/embed/bridge.d.ts +12 -0
  74. package/dist/types/react/embed/index.d.ts +9 -0
  75. package/dist/types/react/embed/shell.d.ts +10 -0
  76. package/dist/types/react/hooks.d.ts +831 -0
  77. package/dist/types/react/index.d.ts +11 -0
  78. package/dist/types/react/mount.d.ts +11 -0
  79. package/dist/types/react/ui/AboutData.d.ts +61 -0
  80. package/dist/types/react/ui/AltertableLogo.d.ts +3 -0
  81. package/dist/types/react/ui/AppFooter.d.ts +7 -0
  82. package/dist/types/react/ui/AppHeader.d.ts +12 -0
  83. package/dist/types/react/ui/AppLayout.d.ts +17 -0
  84. package/dist/types/react/ui/AppScope.d.ts +8 -0
  85. package/dist/types/react/ui/AppToolbar.d.ts +32 -0
  86. package/dist/types/react/ui/Breakdown.d.ts +14 -0
  87. package/dist/types/react/ui/Button.d.ts +12 -0
  88. package/dist/types/react/ui/Checkbox.d.ts +11 -0
  89. package/dist/types/react/ui/Combobox.d.ts +43 -0
  90. package/dist/types/react/ui/ComparisonVisual.d.ts +15 -0
  91. package/dist/types/react/ui/ContentSkeleton.d.ts +8 -0
  92. package/dist/types/react/ui/DataApp.d.ts +56 -0
  93. package/dist/types/react/ui/DataBoundary.d.ts +16 -0
  94. package/dist/types/react/ui/DataSection.d.ts +28 -0
  95. package/dist/types/react/ui/DataTable.d.ts +28 -0
  96. package/dist/types/react/ui/DataViewToast.d.ts +12 -0
  97. package/dist/types/react/ui/DataWidget.d.ts +39 -0
  98. package/dist/types/react/ui/DateRangePicker.d.ts +29 -0
  99. package/dist/types/react/ui/DateTimeTooltip.d.ts +10 -0
  100. package/dist/types/react/ui/DimensionPicker.d.ts +11 -0
  101. package/dist/types/react/ui/EmptyState.d.ts +9 -0
  102. package/dist/types/react/ui/GettingStarted.d.ts +9 -0
  103. package/dist/types/react/ui/GlossaryDefinition.d.ts +8 -0
  104. package/dist/types/react/ui/GlossaryExplanation.d.ts +17 -0
  105. package/dist/types/react/ui/GradientScroll.d.ts +16 -0
  106. package/dist/types/react/ui/Grid.d.ts +13 -0
  107. package/dist/types/react/ui/GridItem.d.ts +7 -0
  108. package/dist/types/react/ui/HelpPopover.d.ts +24 -0
  109. package/dist/types/react/ui/IconButton.d.ts +19 -0
  110. package/dist/types/react/ui/InspectionContext.d.ts +10 -0
  111. package/dist/types/react/ui/Kbd.d.ts +8 -0
  112. package/dist/types/react/ui/LiveControl.d.ts +11 -0
  113. package/dist/types/react/ui/MetricWidget.d.ts +48 -0
  114. package/dist/types/react/ui/PeriodSummary.d.ts +17 -0
  115. package/dist/types/react/ui/PresentStory.d.ts +34 -0
  116. package/dist/types/react/ui/QueryList.d.ts +15 -0
  117. package/dist/types/react/ui/Ranking.d.ts +14 -0
  118. package/dist/types/react/ui/RefreshControl.d.ts +11 -0
  119. package/dist/types/react/ui/RefreshRegion.d.ts +10 -0
  120. package/dist/types/react/ui/RequestHint.d.ts +21 -0
  121. package/dist/types/react/ui/SearchField.d.ts +23 -0
  122. package/dist/types/react/ui/SearchInput.d.ts +9 -0
  123. package/dist/types/react/ui/SearchMatch.d.ts +7 -0
  124. package/dist/types/react/ui/SelectableBarChart.d.ts +16 -0
  125. package/dist/types/react/ui/SelectionMark.d.ts +5 -0
  126. package/dist/types/react/ui/Sheet.d.ts +19 -0
  127. package/dist/types/react/ui/Skeleton.d.ts +6 -0
  128. package/dist/types/react/ui/Stack.d.ts +8 -0
  129. package/dist/types/react/ui/StatusPanel.d.ts +11 -0
  130. package/dist/types/react/ui/TableWidget.d.ts +57 -0
  131. package/dist/types/react/ui/Tabs.d.ts +6 -0
  132. package/dist/types/react/ui/ThemeSelector.d.ts +13 -0
  133. package/dist/types/react/ui/Tooltip.d.ts +23 -0
  134. package/dist/types/react/ui/UpdatedAt.d.ts +10 -0
  135. package/dist/types/react/ui/VariableBar.d.ts +7 -0
  136. package/dist/types/react/ui/VisualizationWidget.d.ts +52 -0
  137. package/dist/types/react/ui/WidgetDisclosure.d.ts +7 -0
  138. package/dist/types/react/ui/WidgetEvidence.d.ts +12 -0
  139. package/dist/types/react/ui/WidgetViewTabs.d.ts +17 -0
  140. package/dist/types/react/ui/chartColor.d.ts +1 -0
  141. package/dist/types/react/ui/classNames.d.ts +1 -0
  142. package/dist/types/react/ui/comparison.d.ts +30 -0
  143. package/dist/types/react/ui/data-context.d.ts +65 -0
  144. package/dist/types/react/ui/data-identifiers.d.ts +33 -0
  145. package/dist/types/react/ui/icons.d.ts +42 -0
  146. package/dist/types/react/ui/index.d.ts +129 -0
  147. package/dist/types/react/ui/metric.d.ts +11 -0
  148. package/dist/types/react/ui/search.d.ts +6 -0
  149. package/dist/types/react/ui/searchItems.d.ts +34 -0
  150. package/dist/types/react/ui/shortcuts.d.ts +32 -0
  151. package/dist/types/react/ui/story.d.ts +20 -0
  152. package/dist/types/react/ui/variables.d.ts +36 -0
  153. package/dist/types/react/ui/widget-views.d.ts +3 -0
  154. package/dist/types/react/view-controls.d.ts +17 -0
  155. package/dist/types/react/view.d.ts +49 -0
  156. package/dist/types/server/handler.d.ts +13 -0
  157. package/dist/types/server/index.d.ts +7 -0
  158. package/dist/types/server/local.d.ts +17 -0
  159. package/docs/app-authoring.md +26 -0
  160. package/docs/appearance.md +30 -0
  161. package/docs/bootstrap.md +76 -0
  162. package/docs/client.md +127 -0
  163. package/docs/config.md +21 -0
  164. package/docs/contract.md +95 -0
  165. package/docs/embed.md +98 -0
  166. package/docs/format.md +29 -0
  167. package/docs/react-embed.md +57 -0
  168. package/docs/react-styles.md +17 -0
  169. package/docs/react.md +248 -0
  170. package/docs/releasing.md +74 -0
  171. package/docs/server-bun.md +26 -0
  172. package/docs/server.md +47 -0
  173. package/docs/starter-agent-instructions.md +51 -0
  174. package/package.json +124 -0
@@ -0,0 +1,192 @@
1
+ import {
2
+ invariant
3
+ } from "./contract-8q35dcyh.js";
4
+
5
+ // src/core/appearance.ts
6
+ var defaults = {
7
+ mode: "light",
8
+ baseColor: "neutral",
9
+ accentColor: "#405d47",
10
+ darkAccentColor: "#a6c4ad",
11
+ chartColors: [
12
+ "#285fc0",
13
+ "#a95319",
14
+ "#147862",
15
+ "#7243aa",
16
+ "#aa3958",
17
+ "#475569"
18
+ ],
19
+ density: "comfortable",
20
+ cornerRadius: "medium",
21
+ elevation: "subtle",
22
+ typography: { body: "system", heading: "system" }
23
+ };
24
+ function record(value) {
25
+ return typeof value === "object" && value !== null && !Array.isArray(value);
26
+ }
27
+ function oneOf(value, options) {
28
+ return typeof value === "string" && options.includes(value);
29
+ }
30
+ function color(value) {
31
+ return typeof value === "string" && /^#[0-9a-fA-F]{6}$/.test(value);
32
+ }
33
+ function font(value) {
34
+ return typeof value === "string" && value.length > 0 && value.length <= 120 && !/[;{}()]/.test(value);
35
+ }
36
+ function parseAppearance2(value) {
37
+ if (value === undefined)
38
+ return {
39
+ ...defaults,
40
+ chartColors: [...defaults.chartColors],
41
+ typography: { ...defaults.typography }
42
+ };
43
+ invariant(record(value) && Object.keys(value).every((key) => [
44
+ "mode",
45
+ "baseColor",
46
+ "accentColor",
47
+ "darkAccentColor",
48
+ "chartColors",
49
+ "density",
50
+ "cornerRadius",
51
+ "elevation",
52
+ "typography"
53
+ ].includes(key)), "Invalid appearance settings.");
54
+ const typography = value.typography;
55
+ const validFields = (value.mode === undefined || oneOf(value.mode, ["light", "dark", "system"])) && (value.baseColor === undefined || oneOf(value.baseColor, ["neutral", "slate", "warm"])) && (value.accentColor === undefined || color(value.accentColor)) && (value.darkAccentColor === undefined || color(value.darkAccentColor)) && (value.chartColors === undefined || Array.isArray(value.chartColors) && value.chartColors.length >= 1 && value.chartColors.length <= 8 && value.chartColors.every(color)) && (value.density === undefined || oneOf(value.density, ["compact", "comfortable", "spacious"])) && (value.cornerRadius === undefined || oneOf(value.cornerRadius, ["none", "small", "medium", "large"])) && (value.elevation === undefined || oneOf(value.elevation, ["flat", "subtle", "raised"])) && (typography === undefined || record(typography) && Object.keys(typography).every((key) => key === "body" || key === "heading") && (typography.body === undefined || font(typography.body)) && (typography.heading === undefined || font(typography.heading)));
56
+ invariant(validFields, "Invalid appearance settings.");
57
+ return {
58
+ mode: value.mode ?? defaults.mode,
59
+ baseColor: value.baseColor ?? defaults.baseColor,
60
+ accentColor: value.accentColor ?? defaults.accentColor,
61
+ darkAccentColor: value.darkAccentColor ?? (value.accentColor === undefined ? defaults.darkAccentColor : undefined),
62
+ chartColors: value.chartColors ?? defaults.chartColors,
63
+ density: value.density ?? defaults.density,
64
+ cornerRadius: value.cornerRadius ?? defaults.cornerRadius,
65
+ elevation: value.elevation ?? defaults.elevation,
66
+ typography: {
67
+ body: record(typography) && typeof typography.body === "string" ? typography.body : defaults.typography.body,
68
+ heading: record(typography) && typeof typography.heading === "string" ? typography.heading : defaults.typography.heading
69
+ }
70
+ };
71
+ }
72
+ var palettes = {
73
+ neutral: {
74
+ light: ["#ffffff", "#ffffff", "#f6f7f7", "#202124", "#687078", "#e3e6e8"],
75
+ dark: ["#151719", "#202326", "#292d31", "#f2f3f4", "#aeb5bc", "#3b4248"]
76
+ },
77
+ slate: {
78
+ light: ["#f8fafc", "#ffffff", "#f1f5f9", "#17212f", "#607083", "#dce3ea"],
79
+ dark: ["#111820", "#1b2530", "#263340", "#f0f4f8", "#a8b5c3", "#3a4857"]
80
+ },
81
+ warm: {
82
+ light: ["#fbfaf8", "#ffffff", "#f5f2ed", "#292723", "#736e66", "#e8e2da"],
83
+ dark: ["#1b1916", "#25221e", "#302c27", "#f5f1eb", "#bcb3a8", "#494239"]
84
+ }
85
+ };
86
+ var spaces = {
87
+ compact: ["4px", "8px", "12px", "18px", "24px"],
88
+ comfortable: ["5px", "10px", "16px", "24px", "32px"],
89
+ spacious: ["6px", "12px", "20px", "30px", "40px"]
90
+ };
91
+ var radii = {
92
+ none: ["0px", "0px", "0px"],
93
+ small: ["4px", "7px", "9px"],
94
+ medium: ["7px", "12px", "16px"],
95
+ large: ["10px", "18px", "24px"]
96
+ };
97
+ function fontStack(family) {
98
+ return family === "system" ? "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, ui-sans-serif, sans-serif" : `${JSON.stringify(family)}, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, ui-sans-serif, sans-serif`;
99
+ }
100
+ function applyAppearance2(value) {
101
+ const settings = parseAppearance2(value);
102
+ const root = document.documentElement;
103
+ const preference = window.matchMedia("(prefers-color-scheme: dark)");
104
+ const [xs, sm, md, lg, xl] = spaces[settings.density];
105
+ const [control, surface, overlay] = radii[settings.cornerRadius];
106
+ const tokens = {
107
+ "--at-font": fontStack(settings.typography.body),
108
+ "--at-font-heading": fontStack(settings.typography.heading),
109
+ "--at-space-xs": xs,
110
+ "--at-space-sm": sm,
111
+ "--at-space-md": md,
112
+ "--at-space-lg": lg,
113
+ "--at-space-xl": xl,
114
+ "--at-layout-gap": `clamp(${md}, 2.5vw, ${lg})`,
115
+ "--at-radius-control": control,
116
+ "--at-radius-surface": surface,
117
+ "--at-radius-overlay": overlay,
118
+ "--at-shadow-overlay": settings.elevation === "flat" ? "none" : settings.elevation === "raised" ? "0 24px 72px rgb(0 0 0 / 24%)" : "0 18px 50px rgb(0 0 0 / 16%)",
119
+ "--at-shadow-surface": settings.elevation === "flat" ? "none" : settings.elevation === "raised" ? "0 8px 28px rgb(20 28 40 / 10%)" : "0 3px 16px rgb(20 28 40 / 5%)"
120
+ };
121
+ function applyColors() {
122
+ const dark = settings.mode === "dark" || settings.mode === "system" && preference.matches;
123
+ const [background, surfaceColor, subtle, text, muted, border] = palettes[settings.baseColor][dark ? "dark" : "light"];
124
+ const accent = dark ? settings.darkAccentColor ?? `color-mix(in srgb, ${settings.accentColor} 50%, white)` : settings.accentColor;
125
+ settings.chartColors.forEach((chartColor, index) => {
126
+ tokens[`--at-chart-${index + 1}`] = dark ? `color-mix(in srgb, ${chartColor} 60%, white)` : chartColor;
127
+ });
128
+ Object.assign(tokens, {
129
+ "--at-background": background,
130
+ "--at-surface": surfaceColor,
131
+ "--at-subtle": subtle,
132
+ "--at-text": text,
133
+ "--at-muted": muted,
134
+ "--at-border": border,
135
+ "--at-accent": accent,
136
+ "--at-focus-color": muted,
137
+ "--at-control-hover-border": `color-mix(in srgb, ${muted} 45%, ${border})`,
138
+ "--at-accent-hover": `color-mix(in srgb, ${accent} 80%, ${dark ? "white" : "black"})`,
139
+ "--at-accent-subtle": `color-mix(in srgb, ${accent} ${dark ? 22 : 12}%, ${surfaceColor})`,
140
+ "--at-on-accent": dark ? background : "#ffffff",
141
+ "--at-danger": dark ? "#f97066" : "#b42318",
142
+ "--at-backdrop": dark ? "rgb(0 0 0 / 55%)" : "rgb(15 23 30 / 22%)",
143
+ "--at-code-surface": dark ? "#242a31" : "#f4f6f9",
144
+ "--at-code-text": dark ? "#e5e9ef" : "#273242"
145
+ });
146
+ root.style.colorScheme = dark ? "dark" : "light";
147
+ for (const [name, token] of Object.entries(tokens))
148
+ root.style.setProperty(name, token);
149
+ }
150
+ applyColors();
151
+ if (settings.mode === "system")
152
+ preference.addEventListener("change", applyColors);
153
+ return () => {
154
+ preference.removeEventListener("change", applyColors);
155
+ };
156
+ }
157
+ function createThemeController2(value) {
158
+ const settings = parseAppearance2(value);
159
+ const storageKey = "altertable.data-app.theme-mode";
160
+ let mode = settings.mode;
161
+ try {
162
+ const saved = window.localStorage.getItem(storageKey);
163
+ if (oneOf(saved, ["light", "dark", "system"]))
164
+ mode = saved;
165
+ } catch {}
166
+ let stopAppearance = applyAppearance2({ ...settings, mode });
167
+ const listeners = new Set;
168
+ return {
169
+ getMode() {
170
+ return mode;
171
+ },
172
+ setMode(nextMode) {
173
+ if (nextMode === mode)
174
+ return;
175
+ stopAppearance();
176
+ mode = nextMode;
177
+ stopAppearance = applyAppearance2({ ...settings, mode });
178
+ try {
179
+ window.localStorage.setItem(storageKey, mode);
180
+ } catch {}
181
+ listeners.forEach((listener) => listener());
182
+ },
183
+ subscribe(listener) {
184
+ listeners.add(listener);
185
+ return () => listeners.delete(listener);
186
+ }
187
+ };
188
+ }
189
+
190
+ export { parseAppearance2, applyAppearance2, createThemeController2 };
191
+
192
+ //# debugId=88E94DEE7384735E64756E2164756E21
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/core/appearance.ts"],
4
+ "sourcesContent": [
5
+ "/**\n * Brand settings; parsing is portable, while theme application requires the browser.\n * @module @altertable/data-app/appearance\n * @see https://github.com/altertable-ai/data-app/blob/main/docs/appearance.md\n */\nimport { invariant } from '@/src/core/invariant';\n\nexport type AppearanceSettings = {\n mode: 'light' | 'dark' | 'system';\n baseColor: 'neutral' | 'slate' | 'warm';\n accentColor: string;\n darkAccentColor?: string;\n chartColors: string[];\n density: 'compact' | 'comfortable' | 'spacious';\n cornerRadius: 'none' | 'small' | 'medium' | 'large';\n elevation: 'flat' | 'subtle' | 'raised';\n typography: { body: string; heading: string };\n};\n\nexport type ThemeMode = AppearanceSettings['mode'];\n\nexport type ThemeController = {\n getMode: () => ThemeMode;\n setMode: (mode: ThemeMode) => void;\n subscribe: (listener: () => void) => () => void;\n};\n\nconst defaults: AppearanceSettings = {\n mode: 'light',\n baseColor: 'neutral',\n accentColor: '#405d47',\n darkAccentColor: '#a6c4ad',\n chartColors: [\n '#285fc0',\n '#a95319',\n '#147862',\n '#7243aa',\n '#aa3958',\n '#475569',\n ],\n density: 'comfortable',\n cornerRadius: 'medium',\n elevation: 'subtle',\n typography: { body: 'system', heading: 'system' },\n};\n\nfunction record(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction oneOf<T extends string>(\n value: unknown,\n options: readonly T[]\n): value is T {\n return typeof value === 'string' && options.includes(value as T);\n}\n\nfunction color(value: unknown): value is string {\n return typeof value === 'string' && /^#[0-9a-fA-F]{6}$/.test(value);\n}\n\nfunction font(value: unknown): value is string {\n return (\n typeof value === 'string' &&\n value.length > 0 &&\n value.length <= 120 &&\n !/[;{}()]/.test(value)\n );\n}\n\nexport function parseAppearance(value: unknown): AppearanceSettings {\n if (value === undefined)\n return {\n ...defaults,\n chartColors: [...defaults.chartColors],\n typography: { ...defaults.typography },\n };\n invariant(\n record(value) &&\n Object.keys(value).every(key =>\n [\n 'mode',\n 'baseColor',\n 'accentColor',\n 'darkAccentColor',\n 'chartColors',\n 'density',\n 'cornerRadius',\n 'elevation',\n 'typography',\n ].includes(key)\n ),\n 'Invalid appearance settings.'\n );\n const typography = value.typography;\n const validFields =\n (value.mode === undefined ||\n oneOf(value.mode, ['light', 'dark', 'system'])) &&\n (value.baseColor === undefined ||\n oneOf(value.baseColor, ['neutral', 'slate', 'warm'])) &&\n (value.accentColor === undefined || color(value.accentColor)) &&\n (value.darkAccentColor === undefined || color(value.darkAccentColor)) &&\n (value.chartColors === undefined ||\n (Array.isArray(value.chartColors) &&\n value.chartColors.length >= 1 &&\n value.chartColors.length <= 8 &&\n value.chartColors.every(color))) &&\n (value.density === undefined ||\n oneOf(value.density, ['compact', 'comfortable', 'spacious'])) &&\n (value.cornerRadius === undefined ||\n oneOf(value.cornerRadius, ['none', 'small', 'medium', 'large'])) &&\n (value.elevation === undefined ||\n oneOf(value.elevation, ['flat', 'subtle', 'raised'])) &&\n (typography === undefined ||\n (record(typography) &&\n Object.keys(typography).every(\n key => key === 'body' || key === 'heading'\n ) &&\n (typography.body === undefined || font(typography.body)) &&\n (typography.heading === undefined || font(typography.heading))));\n invariant(validFields, 'Invalid appearance settings.');\n\n return {\n mode: (value.mode ?? defaults.mode) as AppearanceSettings['mode'],\n baseColor: (value.baseColor ??\n defaults.baseColor) as AppearanceSettings['baseColor'],\n accentColor: (value.accentColor ?? defaults.accentColor) as string,\n darkAccentColor: (value.darkAccentColor ??\n (value.accentColor === undefined\n ? defaults.darkAccentColor\n : undefined)) as string | undefined,\n chartColors: (value.chartColors ?? defaults.chartColors) as string[],\n density: (value.density ??\n defaults.density) as AppearanceSettings['density'],\n cornerRadius: (value.cornerRadius ??\n defaults.cornerRadius) as AppearanceSettings['cornerRadius'],\n elevation: (value.elevation ??\n defaults.elevation) as AppearanceSettings['elevation'],\n typography: {\n body:\n record(typography) && typeof typography.body === 'string'\n ? typography.body\n : defaults.typography.body,\n heading:\n record(typography) && typeof typography.heading === 'string'\n ? typography.heading\n : defaults.typography.heading,\n },\n };\n}\n\nconst palettes = {\n neutral: {\n light: ['#ffffff', '#ffffff', '#f6f7f7', '#202124', '#687078', '#e3e6e8'],\n dark: ['#151719', '#202326', '#292d31', '#f2f3f4', '#aeb5bc', '#3b4248'],\n },\n slate: {\n light: ['#f8fafc', '#ffffff', '#f1f5f9', '#17212f', '#607083', '#dce3ea'],\n dark: ['#111820', '#1b2530', '#263340', '#f0f4f8', '#a8b5c3', '#3a4857'],\n },\n warm: {\n light: ['#fbfaf8', '#ffffff', '#f5f2ed', '#292723', '#736e66', '#e8e2da'],\n dark: ['#1b1916', '#25221e', '#302c27', '#f5f1eb', '#bcb3a8', '#494239'],\n },\n} as const;\n\nconst spaces = {\n compact: ['4px', '8px', '12px', '18px', '24px'],\n comfortable: ['5px', '10px', '16px', '24px', '32px'],\n spacious: ['6px', '12px', '20px', '30px', '40px'],\n} as const;\n\nconst radii = {\n none: ['0px', '0px', '0px'],\n small: ['4px', '7px', '9px'],\n medium: ['7px', '12px', '16px'],\n large: ['10px', '18px', '24px'],\n} as const;\n\nfunction fontStack(family: string): string {\n return family === 'system'\n ? \"-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, ui-sans-serif, sans-serif\"\n : `${JSON.stringify(family)}, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, ui-sans-serif, sans-serif`;\n}\n\n/**\n * Install semantic tokens on the document root, including portaled UI. Returns a cleanup for\n * system-theme listening.\n */\nexport function applyAppearance(value: unknown): () => void {\n const settings = parseAppearance(value);\n const root = document.documentElement;\n const preference = window.matchMedia('(prefers-color-scheme: dark)');\n const [xs, sm, md, lg, xl] = spaces[settings.density];\n const [control, surface, overlay] = radii[settings.cornerRadius];\n const tokens: Record<string, string> = {\n '--at-font': fontStack(settings.typography.body),\n '--at-font-heading': fontStack(settings.typography.heading),\n '--at-space-xs': xs,\n '--at-space-sm': sm,\n '--at-space-md': md,\n '--at-space-lg': lg,\n '--at-space-xl': xl,\n '--at-layout-gap': `clamp(${md}, 2.5vw, ${lg})`,\n '--at-radius-control': control,\n '--at-radius-surface': surface,\n '--at-radius-overlay': overlay,\n '--at-shadow-overlay':\n settings.elevation === 'flat'\n ? 'none'\n : settings.elevation === 'raised'\n ? '0 24px 72px rgb(0 0 0 / 24%)'\n : '0 18px 50px rgb(0 0 0 / 16%)',\n '--at-shadow-surface':\n settings.elevation === 'flat'\n ? 'none'\n : settings.elevation === 'raised'\n ? '0 8px 28px rgb(20 28 40 / 10%)'\n : '0 3px 16px rgb(20 28 40 / 5%)',\n };\n\n function applyColors(): void {\n const dark =\n settings.mode === 'dark' ||\n (settings.mode === 'system' && preference.matches);\n const [background, surfaceColor, subtle, text, muted, border] =\n palettes[settings.baseColor][dark ? 'dark' : 'light'];\n const accent = dark\n ? (settings.darkAccentColor ??\n `color-mix(in srgb, ${settings.accentColor} 50%, white)`)\n : settings.accentColor;\n settings.chartColors.forEach((chartColor, index) => {\n tokens[`--at-chart-${index + 1}`] = dark\n ? `color-mix(in srgb, ${chartColor} 60%, white)`\n : chartColor;\n });\n Object.assign(tokens, {\n '--at-background': background,\n '--at-surface': surfaceColor,\n '--at-subtle': subtle,\n '--at-text': text,\n '--at-muted': muted,\n '--at-border': border,\n '--at-accent': accent,\n '--at-focus-color': muted,\n '--at-control-hover-border': `color-mix(in srgb, ${muted} 45%, ${border})`,\n '--at-accent-hover': `color-mix(in srgb, ${accent} 80%, ${dark ? 'white' : 'black'})`,\n '--at-accent-subtle': `color-mix(in srgb, ${accent} ${dark ? 22 : 12}%, ${surfaceColor})`,\n '--at-on-accent': dark ? background : '#ffffff',\n '--at-danger': dark ? '#f97066' : '#b42318',\n '--at-backdrop': dark ? 'rgb(0 0 0 / 55%)' : 'rgb(15 23 30 / 22%)',\n '--at-code-surface': dark ? '#242a31' : '#f4f6f9',\n '--at-code-text': dark ? '#e5e9ef' : '#273242',\n });\n root.style.colorScheme = dark ? 'dark' : 'light';\n for (const [name, token] of Object.entries(tokens))\n root.style.setProperty(name, token);\n }\n applyColors();\n if (settings.mode === 'system')\n preference.addEventListener('change', applyColors);\n\n return () => {\n preference.removeEventListener('change', applyColors);\n };\n}\n\n/** Viewer color mode persists independently of app-authored brand tokens. */\nexport function createThemeController(value: unknown): ThemeController {\n const settings = parseAppearance(value);\n const storageKey = 'altertable.data-app.theme-mode';\n let mode = settings.mode;\n try {\n const saved = window.localStorage.getItem(storageKey);\n if (oneOf(saved, ['light', 'dark', 'system'])) mode = saved;\n } catch {\n // Storage can be unavailable in private browsing or embedded contexts.\n }\n let stopAppearance = applyAppearance({ ...settings, mode });\n const listeners = new Set<() => void>();\n\n return {\n getMode() {\n return mode;\n },\n setMode(nextMode) {\n if (nextMode === mode) return;\n stopAppearance();\n mode = nextMode;\n stopAppearance = applyAppearance({ ...settings, mode });\n try {\n window.localStorage.setItem(storageKey, mode);\n } catch {\n // The selection still applies to this page.\n }\n listeners.forEach(listener => listener());\n },\n subscribe(listener) {\n listeners.add(listener);\n\n return () => listeners.delete(listener);\n },\n };\n}\n"
6
+ ],
7
+ "mappings": "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",
8
+ "debugId": "88E94DEE7384735E64756E2164756E21",
9
+ "names": []
10
+ }
@@ -0,0 +1,9 @@
1
+ // src/core/invariant.ts
2
+ function invariant(condition, message) {
3
+ if (!condition)
4
+ throw new Error(`Invariant failed: ${message}`);
5
+ }
6
+
7
+ export { invariant };
8
+
9
+ //# debugId=C54A6511BB27C13E64756E2164756E21
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/core/invariant.ts"],
4
+ "sourcesContent": [
5
+ "/** Assert an author or data contract while preserving a useful failure message. */\nexport function invariant(\n condition: unknown,\n message: string\n): asserts condition {\n if (!condition) throw new Error(`Invariant failed: ${message}`);\n}\n"
6
+ ],
7
+ "mappings": ";AACO,SAAS,SAAS,CACvB,WACA,SACmB;AAAA,EACnB,IAAI,CAAC;AAAA,IAAW,MAAM,IAAI,MAAM,qBAAqB,SAAS;AAAA;",
8
+ "debugId": "C54A6511BB27C13E64756E2164756E21",
9
+ "names": []
10
+ }
@@ -0,0 +1,133 @@
1
+ // src/core/messages.ts
2
+ var errorBrand = Symbol.for("@altertable/data-app/MessageRoutingError");
3
+
4
+ class MessageRoutingError2 extends Error {
5
+ code;
6
+ requestId;
7
+ [errorBrand] = true;
8
+ static [Symbol.hasInstance](value) {
9
+ return value instanceof Error && value[errorBrand] === true;
10
+ }
11
+ constructor(code, message, requestId) {
12
+ super(message);
13
+ this.code = code;
14
+ this.requestId = requestId;
15
+ this.name = "MessageRoutingError";
16
+ }
17
+ }
18
+ function defineMessageRoute2(route) {
19
+ return route;
20
+ }
21
+ function createMessageRouter2(routes, handlers) {
22
+ const registered = new Map(Object.entries(routes).map(([name, contract]) => {
23
+ const handler = handlers[name];
24
+ if (!name || name.length > 256 || typeof handler !== "function")
25
+ throw new Error("Each message route requires a handler and a bounded name.");
26
+ return [name, { contract, handler }];
27
+ }));
28
+ async function dispatch(value, context) {
29
+ if (!value || typeof value !== "object" || typeof value.route !== "string")
30
+ throw new MessageRoutingError2("invalid_message", "Invalid routed message.");
31
+ const message = value;
32
+ const entry = registered.get(message.route);
33
+ if (!entry)
34
+ throw new MessageRoutingError2("unknown_route", "Unknown message route.");
35
+ let payload;
36
+ try {
37
+ payload = entry.contract.input(message.payload);
38
+ } catch {
39
+ throw new MessageRoutingError2("invalid_payload", "Invalid message payload.");
40
+ }
41
+ context.signal.throwIfAborted();
42
+ let result;
43
+ try {
44
+ result = await entry.handler(payload, context);
45
+ } catch (error) {
46
+ if (context.signal.aborted)
47
+ throw context.signal.reason;
48
+ if (error instanceof MessageRoutingError2)
49
+ throw error;
50
+ throw new MessageRoutingError2("request_failed", "The message request failed. Retry the request.");
51
+ }
52
+ context.signal.throwIfAborted();
53
+ try {
54
+ return entry.contract.output(result, payload);
55
+ } catch (error) {
56
+ if (error instanceof MessageRoutingError2)
57
+ throw error;
58
+ throw new MessageRoutingError2("invalid_response", "Invalid message response.");
59
+ }
60
+ }
61
+ return { dispatch };
62
+ }
63
+ function defineDataQueryRoute2(operations) {
64
+ return {
65
+ operations,
66
+ input(value) {
67
+ if (!value || typeof value !== "object")
68
+ throw new Error("Invalid query.");
69
+ const request = value;
70
+ if (typeof request.operation !== "string" || !request.operation || request.operation.length > 256 || request.operation.includes("/"))
71
+ throw new Error("Invalid operation.");
72
+ const operation = operations && Object.hasOwn(operations, request.operation) ? operations[request.operation] : undefined;
73
+ if (operations && !operation)
74
+ throw new Error("Unknown operation.");
75
+ return {
76
+ operation: request.operation,
77
+ input: operation ? operation.input(request.input) : request.input
78
+ };
79
+ },
80
+ output(value, input) {
81
+ if (!value || typeof value !== "object")
82
+ throw new Error("Invalid data response.");
83
+ const response = value;
84
+ if (!Number.isInteger(response.status) || response.status < 100 || response.status > 599 || !response.body || typeof response.body !== "object")
85
+ throw new Error("Invalid data response.");
86
+ const body = response.body;
87
+ if (response.status < 200 || response.status >= 300) {
88
+ const failure = body.error;
89
+ throw new MessageRoutingError2(typeof failure?.code === "string" ? failure.code : "request_failed", typeof failure?.message === "string" ? failure.message : "Could not load data.", typeof failure?.requestId === "string" ? failure.requestId : undefined);
90
+ }
91
+ if (!("data" in body) || typeof body.requestId !== "string" || typeof body.queriedAt !== "string" || !Array.isArray(body.queryIds) || !body.queryIds.every((id) => typeof id === "string"))
92
+ throw new Error("Invalid data envelope.");
93
+ if (body.queries !== undefined && (!Array.isArray(body.queries) || !body.queries.every((query) => query && typeof query === "object" && typeof query.name === "string" && typeof query.statement === "string" && (query.queryId === undefined || typeof query.queryId === "string"))))
94
+ throw new Error("Invalid query evidence.");
95
+ const operation = operations?.[input.operation];
96
+ return {
97
+ status: response.status,
98
+ body: {
99
+ ...body,
100
+ data: operation ? operation.output(body.data) : body.data
101
+ }
102
+ };
103
+ }
104
+ };
105
+ }
106
+ var navigationUpdateRoute2 = /* @__PURE__ */ defineMessageRoute2({
107
+ input(value) {
108
+ if (!value || typeof value !== "object")
109
+ throw new Error("Invalid navigation.");
110
+ const input = value;
111
+ if (typeof input.search !== "string" || input.search.length > 16384 || input.search !== "" && !input.search.startsWith("?") || typeof input.hash !== "string" || input.hash.length > 4096 || input.hash !== "" && !input.hash.startsWith("#") || input.mode !== "push" && input.mode !== "replace" || input.title !== undefined && (typeof input.title !== "string" || input.title.length > 512))
112
+ throw new Error("Invalid navigation.");
113
+ return {
114
+ search: input.search,
115
+ hash: input.hash,
116
+ mode: input.mode,
117
+ ...input.title === undefined ? {} : { title: input.title }
118
+ };
119
+ },
120
+ output(value) {
121
+ if (value !== null)
122
+ throw new Error("Invalid navigation response.");
123
+ return null;
124
+ }
125
+ });
126
+ var dataAppRoutes2 = {
127
+ "data.query": /* @__PURE__ */ defineDataQueryRoute2(),
128
+ "navigation.update": navigationUpdateRoute2
129
+ };
130
+
131
+ export { MessageRoutingError2, defineMessageRoute2, createMessageRouter2, defineDataQueryRoute2, navigationUpdateRoute2, dataAppRoutes2 };
132
+
133
+ //# debugId=6376725AC558B20364756E2164756E21
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/core/messages.ts"],
4
+ "sourcesContent": [
5
+ "import type { TransportResponse } from '@/src/core/bridge';\nimport type { DisclosedQuery } from '@/src/core/contract';\n\nexport type MessageContext = { signal: AbortSignal };\nexport type RoutedMessage = { route: string; payload: unknown };\nexport type MessageDispatcher = (\n message: unknown,\n context: MessageContext\n) => Promise<unknown>;\nexport type MessageTransport = (\n message: RoutedMessage,\n signal?: AbortSignal\n) => Promise<unknown>;\nexport type MessageRoute<Input, Output> = {\n input: (value: unknown) => Input;\n output: (value: unknown, input: Input) => Output;\n};\nexport type MessageRoutes = Record<\n string,\n {\n input: (value: unknown) => unknown;\n output: (value: unknown, input: never) => unknown;\n }\n>;\nexport type MessageInput<Route extends MessageRoutes[string]> = ReturnType<\n Route['input']\n>;\nexport type MessageHandlers<Routes extends MessageRoutes> = {\n [Name in keyof Routes]: (\n payload: MessageInput<Routes[Name]>,\n context: MessageContext\n ) =>\n | ReturnType<Routes[Name]['output']>\n | Promise<ReturnType<Routes[Name]['output']>>;\n};\n\n// A bootstrap and its app may bundle independent copies in the same window.\nconst errorBrand = Symbol.for('@altertable/data-app/MessageRoutingError');\n\n/** Only these deliberate, public failures cross the message boundary. Other errors stay private. */\nexport class MessageRoutingError extends Error {\n readonly [errorBrand] = true;\n\n static [Symbol.hasInstance](value: unknown): boolean {\n return (\n value instanceof Error &&\n (value as { [errorBrand]?: unknown })[errorBrand] === true\n );\n }\n\n constructor(\n public readonly code: string,\n message: string,\n public readonly requestId?: string\n ) {\n super(message);\n this.name = 'MessageRoutingError';\n }\n}\n\nexport function defineMessageRoute<Input, Output>(\n route: MessageRoute<Input, Output>\n): MessageRoute<Input, Output> {\n return route;\n}\n\n/** Contracts are shared; handlers are supplied by the host and never belong in the app bundle. */\nexport function createMessageRouter<const Routes extends MessageRoutes>(\n routes: Routes,\n handlers: MessageHandlers<NoInfer<Routes>>\n) {\n const registered = new Map(\n Object.entries(routes).map(([name, contract]) => {\n const handler = handlers[name];\n if (!name || name.length > 256 || typeof handler !== 'function')\n throw new Error(\n 'Each message route requires a handler and a bounded name.'\n );\n\n return [name, { contract, handler }] as const;\n })\n );\n\n async function dispatch(\n value: unknown,\n context: MessageContext\n ): Promise<unknown> {\n if (\n !value ||\n typeof value !== 'object' ||\n typeof (value as RoutedMessage).route !== 'string'\n )\n throw new MessageRoutingError(\n 'invalid_message',\n 'Invalid routed message.'\n );\n const message = value as RoutedMessage;\n const entry = registered.get(message.route);\n if (!entry)\n throw new MessageRoutingError('unknown_route', 'Unknown message route.');\n let payload: unknown;\n try {\n payload = entry.contract.input(message.payload);\n } catch {\n throw new MessageRoutingError(\n 'invalid_payload',\n 'Invalid message payload.'\n );\n }\n context.signal.throwIfAborted();\n let result: unknown;\n try {\n result = await entry.handler(payload as never, context);\n } catch (error) {\n if (context.signal.aborted) throw context.signal.reason;\n if (error instanceof MessageRoutingError) throw error;\n throw new MessageRoutingError(\n 'request_failed',\n 'The message request failed. Retry the request.'\n );\n }\n context.signal.throwIfAborted();\n try {\n return entry.contract.output(result, payload as never);\n } catch (error) {\n if (error instanceof MessageRoutingError) throw error;\n throw new MessageRoutingError(\n 'invalid_response',\n 'Invalid message response.'\n );\n }\n }\n\n return { dispatch };\n}\n\nexport type OperationContracts = Record<\n string,\n {\n input: (value: unknown) => unknown;\n output: (value: unknown) => unknown;\n }\n>;\nexport type DataQueryInput<Operations extends OperationContracts> = {\n [Name in keyof Operations & string]: {\n operation: Name;\n input: ReturnType<Operations[Name]['input']>;\n };\n}[keyof Operations & string];\nexport type DataQueryBody<Output> = {\n data: Output;\n requestId: string;\n queriedAt: string;\n queryIds: string[];\n queries?: DisclosedQuery[];\n};\nexport type DataQueryRoute<Operations extends OperationContracts> =\n MessageRoute<DataQueryInput<Operations>, TransportResponse> & {\n operations: Operations | undefined;\n };\nexport type MessageOutput<Route extends MessageRoutes[string], Input> =\n Route extends DataQueryRoute<infer Operations>\n ? Input extends { operation: infer Name extends keyof Operations }\n ? {\n status: number;\n body: DataQueryBody<ReturnType<Operations[Name]['output']>>;\n }\n : never\n : ReturnType<Route['output']>;\n\n/** Omit contracts only in generic hosts such as the CLI shell, where Bun validates operations. */\nexport function defineDataQueryRoute<\n Operations extends OperationContracts = OperationContracts,\n>(operations?: Operations): DataQueryRoute<Operations> {\n return {\n operations,\n input(value) {\n if (!value || typeof value !== 'object')\n throw new Error('Invalid query.');\n const request = value as { operation?: unknown; input?: unknown };\n if (\n typeof request.operation !== 'string' ||\n !request.operation ||\n request.operation.length > 256 ||\n request.operation.includes('/')\n )\n throw new Error('Invalid operation.');\n const operation =\n operations && Object.hasOwn(operations, request.operation)\n ? operations[request.operation]\n : undefined;\n if (operations && !operation) throw new Error('Unknown operation.');\n\n return {\n operation: request.operation,\n input: operation ? operation.input(request.input) : request.input,\n } as DataQueryInput<Operations>;\n },\n output(value, input) {\n if (!value || typeof value !== 'object')\n throw new Error('Invalid data response.');\n const response = value as TransportResponse;\n if (\n !Number.isInteger(response.status) ||\n response.status < 100 ||\n response.status > 599 ||\n !response.body ||\n typeof response.body !== 'object'\n )\n throw new Error('Invalid data response.');\n const body = response.body as DataQueryBody<unknown> & {\n error?: { code?: unknown; message?: unknown; requestId?: unknown };\n };\n if (response.status < 200 || response.status >= 300) {\n const failure = body.error;\n throw new MessageRoutingError(\n typeof failure?.code === 'string' ? failure.code : 'request_failed',\n typeof failure?.message === 'string'\n ? failure.message\n : 'Could not load data.',\n typeof failure?.requestId === 'string' ? failure.requestId : undefined\n );\n }\n if (\n !('data' in body) ||\n typeof body.requestId !== 'string' ||\n typeof body.queriedAt !== 'string' ||\n !Array.isArray(body.queryIds) ||\n !body.queryIds.every(id => typeof id === 'string')\n )\n throw new Error('Invalid data envelope.');\n if (\n body.queries !== undefined &&\n (!Array.isArray(body.queries) ||\n !body.queries.every(\n query =>\n query &&\n typeof query === 'object' &&\n typeof query.name === 'string' &&\n typeof query.statement === 'string' &&\n (query.queryId === undefined || typeof query.queryId === 'string')\n ))\n )\n throw new Error('Invalid query evidence.');\n const operation = operations?.[input.operation];\n\n return {\n status: response.status,\n body: {\n ...body,\n data: operation ? operation.output(body.data) : body.data,\n },\n };\n },\n };\n}\n\nexport type NavigationUpdate = {\n search: string;\n hash: string;\n mode: 'push' | 'replace';\n title?: string;\n};\nexport const navigationUpdateRoute = /* @__PURE__ */ defineMessageRoute({\n input(value: unknown): NavigationUpdate {\n if (!value || typeof value !== 'object')\n throw new Error('Invalid navigation.');\n const input = value as NavigationUpdate;\n if (\n typeof input.search !== 'string' ||\n input.search.length > 16_384 ||\n (input.search !== '' && !input.search.startsWith('?')) ||\n typeof input.hash !== 'string' ||\n input.hash.length > 4096 ||\n (input.hash !== '' && !input.hash.startsWith('#')) ||\n (input.mode !== 'push' && input.mode !== 'replace') ||\n (input.title !== undefined &&\n (typeof input.title !== 'string' || input.title.length > 512))\n )\n throw new Error('Invalid navigation.');\n\n return {\n search: input.search,\n hash: input.hash,\n mode: input.mode,\n ...(input.title === undefined ? {} : { title: input.title }),\n };\n },\n output(value: unknown): null {\n if (value !== null) throw new Error('Invalid navigation response.');\n\n return null;\n },\n});\nexport const dataAppRoutes = {\n 'data.query': /* @__PURE__ */ defineDataQueryRoute(),\n 'navigation.update': navigationUpdateRoute,\n};\n"
6
+ ],
7
+ "mappings": "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",
8
+ "debugId": "6376725AC558B20364756E2164756E21",
9
+ "names": []
10
+ }