@iloveagents/foundry-web-ui 0.3.0 → 0.4.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.
Files changed (223) hide show
  1. package/README.md +14 -5
  2. package/dist/components/ag-ui-runtime-provider.d.ts +64 -0
  3. package/dist/components/ag-ui-runtime-provider.js +71 -0
  4. package/dist/components/app-brand.d.ts +6 -0
  5. package/dist/components/app-brand.js +13 -0
  6. package/dist/components/assistant-chat.d.ts +26 -0
  7. package/dist/components/assistant-chat.js +93 -0
  8. package/dist/components/chat-attachments.d.ts +25 -0
  9. package/dist/components/chat-attachments.js +20 -0
  10. package/dist/components/chat-bubble.d.ts +1 -0
  11. package/dist/components/chat-bubble.js +103 -0
  12. package/dist/components/chat-header.d.ts +2 -0
  13. package/dist/components/chat-header.js +16 -0
  14. package/dist/components/client-tool-executor.d.ts +12 -0
  15. package/dist/components/client-tool-executor.js +108 -0
  16. package/dist/components/collection-empty-state.d.ts +9 -0
  17. package/dist/components/collection-empty-state.js +6 -0
  18. package/dist/components/collection-filter-bar.d.ts +19 -0
  19. package/dist/components/collection-filter-bar.js +28 -0
  20. package/dist/components/collection-search-input.d.ts +6 -0
  21. package/dist/components/collection-search-input.js +8 -0
  22. package/dist/components/collection-skeleton.d.ts +6 -0
  23. package/dist/components/collection-skeleton.js +10 -0
  24. package/dist/components/collection-sort-menu.d.ts +10 -0
  25. package/dist/components/collection-sort-menu.js +9 -0
  26. package/dist/components/collection-surface.d.ts +8 -0
  27. package/dist/components/collection-surface.js +5 -0
  28. package/dist/components/collection-toolbar.d.ts +9 -0
  29. package/dist/components/collection-toolbar.js +5 -0
  30. package/dist/components/collection-view-toggle.d.ts +7 -0
  31. package/dist/components/collection-view-toggle.js +17 -0
  32. package/dist/components/composer-submit-bridge.d.ts +1 -0
  33. package/dist/components/composer-submit-bridge.js +15 -0
  34. package/dist/components/confirm-dialog.d.ts +11 -0
  35. package/dist/components/confirm-dialog.js +6 -0
  36. package/dist/components/confirmation-card.d.ts +14 -0
  37. package/dist/components/confirmation-card.js +12 -0
  38. package/dist/components/context-badges.d.ts +16 -0
  39. package/dist/components/context-badges.js +56 -0
  40. package/dist/components/context-bar.d.ts +41 -0
  41. package/dist/components/context-bar.js +123 -0
  42. package/dist/components/form-dialog.d.ts +12 -0
  43. package/dist/components/form-dialog.js +13 -0
  44. package/dist/components/global-selection-popover.d.ts +7 -0
  45. package/dist/components/global-selection-popover.js +167 -0
  46. package/dist/components/infinite-scroll-sentinel.d.ts +6 -0
  47. package/dist/components/infinite-scroll-sentinel.js +25 -0
  48. package/dist/components/json-viewer.d.ts +10 -0
  49. package/dist/components/json-viewer.js +80 -0
  50. package/dist/components/loading-indicator.d.ts +4 -0
  51. package/dist/components/loading-indicator.js +22 -0
  52. package/dist/components/markdown-text.d.ts +13 -0
  53. package/dist/components/markdown-text.js +221 -0
  54. package/dist/components/name-dialog.d.ts +16 -0
  55. package/dist/components/name-dialog.js +23 -0
  56. package/dist/components/selection-popover.d.ts +12 -0
  57. package/dist/components/selection-popover.js +111 -0
  58. package/dist/components/show-document-tool-ui.d.ts +1 -0
  59. package/dist/components/show-document-tool-ui.js +53 -0
  60. package/dist/components/sidebar.d.ts +4 -0
  61. package/dist/components/sidebar.js +904 -0
  62. package/dist/components/surface-card.d.ts +9 -0
  63. package/dist/components/surface-card.js +33 -0
  64. package/dist/components/theme-runtime-provider.d.ts +15 -0
  65. package/dist/components/theme-runtime-provider.js +48 -0
  66. package/dist/components/theme-toggle.d.ts +2 -0
  67. package/dist/components/theme-toggle.js +19 -0
  68. package/dist/components/tool-call-card.d.ts +27 -0
  69. package/dist/components/tool-call-card.js +13 -0
  70. package/dist/components/tool-fallback.d.ts +26 -0
  71. package/dist/components/tool-fallback.js +129 -0
  72. package/dist/components/tool-panel-layout.d.ts +10 -0
  73. package/dist/components/tool-panel-layout.js +12 -0
  74. package/dist/components/tool-panel.d.ts +1 -0
  75. package/dist/components/tool-panel.js +89 -0
  76. package/dist/components/tooltip-icon-button.d.ts +7 -0
  77. package/dist/components/tooltip-icon-button.js +9 -0
  78. package/dist/components/user-menu.d.ts +2 -0
  79. package/dist/components/user-menu.js +14 -0
  80. package/dist/index.d.ts +68 -0
  81. package/dist/index.js +83 -0
  82. package/dist/lib/ag-ui-adapter.d.ts +29 -0
  83. package/dist/lib/ag-ui-adapter.js +373 -0
  84. package/dist/lib/app-store.d.ts +115 -0
  85. package/dist/lib/app-store.js +199 -0
  86. package/dist/lib/attachment-adapter.d.ts +20 -0
  87. package/dist/lib/attachment-adapter.js +99 -0
  88. package/dist/lib/auth-provider.d.ts +16 -0
  89. package/dist/lib/auth-provider.js +88 -0
  90. package/dist/lib/chat-bubble-store.d.ts +30 -0
  91. package/dist/lib/chat-bubble-store.js +23 -0
  92. package/dist/lib/chat-lifecycle-store.d.ts +10 -0
  93. package/{src/lib/chat-lifecycle-store.ts → dist/lib/chat-lifecycle-store.js} +3 -13
  94. package/dist/lib/client-tools.d.ts +11 -0
  95. package/dist/lib/client-tools.js +274 -0
  96. package/dist/lib/composer-submit-store.d.ts +12 -0
  97. package/dist/lib/composer-submit-store.js +17 -0
  98. package/dist/lib/dev-store.d.ts +38 -0
  99. package/dist/lib/dev-store.js +32 -0
  100. package/dist/lib/nav-config.d.ts +159 -0
  101. package/dist/lib/nav-config.js +162 -0
  102. package/dist/lib/nav-dnd.d.ts +8 -0
  103. package/dist/lib/nav-dnd.js +9 -0
  104. package/dist/lib/nav-store.d.ts +45 -0
  105. package/dist/lib/nav-store.js +49 -0
  106. package/dist/lib/selection-context.d.ts +21 -0
  107. package/dist/lib/selection-context.js +34 -0
  108. package/dist/lib/sidebar-store.d.ts +23 -0
  109. package/dist/lib/sidebar-store.js +98 -0
  110. package/dist/lib/theme-runtime.d.ts +130 -0
  111. package/dist/lib/theme-runtime.js +479 -0
  112. package/dist/lib/theme-store.d.ts +15 -0
  113. package/dist/lib/theme-store.js +53 -0
  114. package/dist/lib/tool-panel-store.d.ts +48 -0
  115. package/dist/lib/tool-panel-store.js +69 -0
  116. package/dist/lib/use-new-conversation.d.ts +8 -0
  117. package/dist/lib/use-new-conversation.js +62 -0
  118. package/dist/lib/use-page-tools.d.ts +27 -0
  119. package/{src/lib/use-page-tools.ts → dist/lib/use-page-tools.js} +11 -13
  120. package/dist/styles.css +142 -0
  121. package/dist/ui/collapsible.d.ts +5 -0
  122. package/{src/ui/collapsible.tsx → dist/ui/collapsible.js} +0 -2
  123. package/dist/ui/dialog.d.ts +15 -0
  124. package/dist/ui/dialog.js +25 -0
  125. package/dist/ui/dropdown-menu.d.ts +7 -0
  126. package/dist/ui/dropdown-menu.js +19 -0
  127. package/dist/ui/popover.d.ts +7 -0
  128. package/dist/ui/popover.js +10 -0
  129. package/dist/ui/select.d.ts +4 -0
  130. package/dist/ui/select.js +9 -0
  131. package/dist/ui/tooltip.d.ts +7 -0
  132. package/dist/ui/tooltip.js +10 -0
  133. package/package.json +31 -12
  134. package/AGENTS.md +0 -59
  135. package/CHANGELOG.md +0 -203
  136. package/CLAUDE.md +0 -1
  137. package/src/__tests__/no-spaces-imports.test.ts +0 -59
  138. package/src/__tests__/open-core-guards.test.ts +0 -307
  139. package/src/__tests__/theme-runtime.test.ts +0 -81
  140. package/src/__tests__/tool-fallback.test.tsx +0 -109
  141. package/src/components/__tests__/context-bar.test.ts +0 -112
  142. package/src/components/ag-ui-runtime-provider.tsx +0 -170
  143. package/src/components/app-brand.tsx +0 -38
  144. package/src/components/assistant-chat.tsx +0 -461
  145. package/src/components/chat-attachments.tsx +0 -68
  146. package/src/components/chat-bubble.tsx +0 -373
  147. package/src/components/chat-header.tsx +0 -44
  148. package/src/components/client-tool-executor.tsx +0 -230
  149. package/src/components/collection-empty-state.tsx +0 -37
  150. package/src/components/collection-filter-bar.tsx +0 -168
  151. package/src/components/collection-search-input.tsx +0 -41
  152. package/src/components/collection-skeleton.tsx +0 -55
  153. package/src/components/collection-sort-menu.tsx +0 -62
  154. package/src/components/collection-surface.tsx +0 -46
  155. package/src/components/collection-toolbar.tsx +0 -33
  156. package/src/components/collection-view-toggle.tsx +0 -61
  157. package/src/components/composer-submit-bridge.tsx +0 -19
  158. package/src/components/confirm-dialog.tsx +0 -49
  159. package/src/components/confirmation-card.tsx +0 -32
  160. package/src/components/context-badges.tsx +0 -136
  161. package/src/components/context-bar.tsx +0 -238
  162. package/src/components/form-dialog.tsx +0 -56
  163. package/src/components/global-selection-popover.tsx +0 -266
  164. package/src/components/infinite-scroll-sentinel.tsx +0 -48
  165. package/src/components/json-viewer.tsx +0 -232
  166. package/src/components/loading-indicator.tsx +0 -40
  167. package/src/components/markdown-text-citations.test.tsx +0 -108
  168. package/src/components/markdown-text.tsx +0 -508
  169. package/src/components/name-dialog.tsx +0 -87
  170. package/src/components/selection-popover.tsx +0 -156
  171. package/src/components/show-document-tool-ui.tsx +0 -90
  172. package/src/components/sidebar.test.tsx +0 -611
  173. package/src/components/sidebar.tsx +0 -1689
  174. package/src/components/surface-card.tsx +0 -45
  175. package/src/components/theme-runtime-provider.tsx +0 -93
  176. package/src/components/theme-toggle.tsx +0 -27
  177. package/src/components/tool-call-card.tsx +0 -126
  178. package/src/components/tool-fallback.tsx +0 -169
  179. package/src/components/tool-panel-layout.tsx +0 -36
  180. package/src/components/tool-panel.tsx +0 -233
  181. package/src/components/tooltip-icon-button.tsx +0 -28
  182. package/src/components/user-menu.tsx +0 -60
  183. package/src/index.ts +0 -185
  184. package/src/lib/__tests__/ag-ui-adapter.test.ts +0 -273
  185. package/src/lib/__tests__/app-store.test.ts +0 -405
  186. package/src/lib/__tests__/attachment-adapter.test.ts +0 -48
  187. package/src/lib/__tests__/chat-bubble-store.test.ts +0 -67
  188. package/src/lib/__tests__/client-tools.test.ts +0 -124
  189. package/src/lib/__tests__/dev-store.test.ts +0 -78
  190. package/src/lib/__tests__/nav-config.test.ts +0 -135
  191. package/src/lib/__tests__/nav-dnd.test.ts +0 -24
  192. package/src/lib/__tests__/nav-store.test.ts +0 -59
  193. package/src/lib/__tests__/selection-context.test.ts +0 -114
  194. package/src/lib/__tests__/sidebar-store.test.ts +0 -144
  195. package/src/lib/__tests__/theme-store.test.ts +0 -83
  196. package/src/lib/__tests__/tool-panel-store.test.ts +0 -61
  197. package/src/lib/__tests__/use-page-context.test.ts +0 -58
  198. package/src/lib/ag-ui-adapter.ts +0 -412
  199. package/src/lib/app-store.ts +0 -361
  200. package/src/lib/attachment-adapter.ts +0 -92
  201. package/src/lib/auth-provider.tsx +0 -144
  202. package/src/lib/chat-bubble-store.ts +0 -46
  203. package/src/lib/client-tools.ts +0 -293
  204. package/src/lib/composer-submit-store.ts +0 -32
  205. package/src/lib/dev-store.ts +0 -69
  206. package/src/lib/nav-config.ts +0 -329
  207. package/src/lib/nav-dnd.ts +0 -14
  208. package/src/lib/nav-store.ts +0 -89
  209. package/src/lib/selection-context.ts +0 -65
  210. package/src/lib/sidebar-store.ts +0 -113
  211. package/src/lib/theme-runtime.ts +0 -660
  212. package/src/lib/theme-store.ts +0 -67
  213. package/src/lib/tool-panel-store.ts +0 -121
  214. package/src/lib/use-new-conversation.test.tsx +0 -168
  215. package/src/lib/use-new-conversation.ts +0 -64
  216. package/src/ui/dialog.tsx +0 -109
  217. package/src/ui/dropdown-menu.tsx +0 -75
  218. package/src/ui/popover.tsx +0 -34
  219. package/src/ui/select.tsx +0 -15
  220. package/src/ui/tooltip.tsx +0 -30
  221. package/src/vite-env.d.ts +0 -1
  222. package/tsconfig.json +0 -16
  223. package/vitest.config.ts +0 -8
@@ -1,660 +0,0 @@
1
- import type { CSSProperties } from "react";
2
- import type { ThemeMode } from "./theme-store.ts";
3
-
4
- export interface ThemeColorSlots {
5
- background?: string;
6
- foreground?: string;
7
- card?: string;
8
- cardForeground?: string;
9
- popover?: string;
10
- popoverForeground?: string;
11
- primary?: string;
12
- primaryForeground?: string;
13
- secondary?: string;
14
- secondaryForeground?: string;
15
- muted?: string;
16
- mutedForeground?: string;
17
- accent?: string;
18
- accentForeground?: string;
19
- destructive?: string;
20
- destructiveForeground?: string;
21
- border?: string;
22
- input?: string;
23
- ring?: string;
24
- }
25
-
26
- export interface ThemeSidebarSlots {
27
- sidebar?: string;
28
- sidebarForeground?: string;
29
- sidebarPrimary?: string;
30
- sidebarPrimaryForeground?: string;
31
- sidebarAccent?: string;
32
- sidebarAccentForeground?: string;
33
- sidebarSelected?: string;
34
- sidebarSelectedForeground?: string;
35
- sidebarBorder?: string;
36
- sidebarRing?: string;
37
- }
38
-
39
- export interface ThemeStatusSlots {
40
- success?: string;
41
- successForeground?: string;
42
- warning?: string;
43
- warningForeground?: string;
44
- info?: string;
45
- infoForeground?: string;
46
- syntaxKey?: string;
47
- syntaxString?: string;
48
- syntaxNumber?: string;
49
- syntaxBoolean?: string;
50
- }
51
-
52
- export interface ThemeChartSlots {
53
- chart1?: string;
54
- chart2?: string;
55
- chart3?: string;
56
- chart4?: string;
57
- chart5?: string;
58
- }
59
-
60
- export interface ThemeTypographySlots {
61
- bodyFont?: string;
62
- headingFont?: string;
63
- monoFont?: string;
64
- }
65
-
66
- export interface ThemeRadiusSlots {
67
- radius?: string;
68
- }
69
-
70
- export interface ThemeAppSlots {
71
- codeBlock?: string;
72
- codeBlockForeground?: string;
73
- workflowDiagramSurface?: string;
74
- workflowDiagramLine?: string;
75
- workflowDiagramText?: string;
76
- workflowDiagramBorder?: string;
77
- workflowDiagramCompletedStroke?: string;
78
- workflowDiagramCompletedText?: string;
79
- workflowDiagramActiveFill?: string;
80
- workflowDiagramActiveStroke?: string;
81
- workflowDiagramActiveText?: string;
82
- workflowDiagramFailedFill?: string;
83
- workflowDiagramFailedStroke?: string;
84
- workflowDiagramFailedText?: string;
85
- workflowDiagramSkippedFill?: string;
86
- workflowDiagramSkippedStroke?: string;
87
- workflowDiagramSkippedText?: string;
88
- workflowDiagramGlow?: string;
89
- workflowDiagramShell?: string;
90
- }
91
-
92
- export interface ThemeBranding {
93
- appName?: string;
94
- appTitle?: string;
95
- logoUrl?: string;
96
- darkLogoUrl?: string;
97
- }
98
-
99
- export interface ThemeDefinition {
100
- light?: ThemeColorSlots;
101
- dark?: ThemeColorSlots;
102
- sidebar?: {
103
- light?: ThemeSidebarSlots;
104
- dark?: ThemeSidebarSlots;
105
- };
106
- status?: {
107
- light?: ThemeStatusSlots;
108
- dark?: ThemeStatusSlots;
109
- };
110
- charts?: {
111
- light?: ThemeChartSlots;
112
- dark?: ThemeChartSlots;
113
- };
114
- typography?: ThemeTypographySlots;
115
- radius?: ThemeRadiusSlots;
116
- app?: {
117
- light?: ThemeAppSlots;
118
- dark?: ThemeAppSlots;
119
- };
120
- branding?: ThemeBranding;
121
- }
122
-
123
- export interface ThemeLayer {
124
- id?: string;
125
- name?: string;
126
- basePreset?: string | null;
127
- definition?: ThemeDefinition | null;
128
- }
129
-
130
- export interface ResolvedThemeRuntime {
131
- mode: "light" | "dark";
132
- definition: ThemeDefinition;
133
- branding: ThemeBranding;
134
- variables: CSSProperties;
135
- sources: ThemeLayer[];
136
- }
137
-
138
- const COLOR_KEYS = [
139
- "background",
140
- "foreground",
141
- "card",
142
- "cardForeground",
143
- "popover",
144
- "popoverForeground",
145
- "primary",
146
- "primaryForeground",
147
- "secondary",
148
- "secondaryForeground",
149
- "muted",
150
- "mutedForeground",
151
- "accent",
152
- "accentForeground",
153
- "destructive",
154
- "destructiveForeground",
155
- "border",
156
- "input",
157
- "ring",
158
- ] as const satisfies readonly (keyof ThemeColorSlots)[];
159
-
160
- const SIDEBAR_KEYS = [
161
- "sidebar",
162
- "sidebarForeground",
163
- "sidebarPrimary",
164
- "sidebarPrimaryForeground",
165
- "sidebarAccent",
166
- "sidebarAccentForeground",
167
- "sidebarSelected",
168
- "sidebarSelectedForeground",
169
- "sidebarBorder",
170
- "sidebarRing",
171
- ] as const satisfies readonly (keyof ThemeSidebarSlots)[];
172
-
173
- const STATUS_KEYS = [
174
- "success",
175
- "successForeground",
176
- "warning",
177
- "warningForeground",
178
- "info",
179
- "infoForeground",
180
- "syntaxKey",
181
- "syntaxString",
182
- "syntaxNumber",
183
- "syntaxBoolean",
184
- ] as const satisfies readonly (keyof ThemeStatusSlots)[];
185
-
186
- const CHART_KEYS = [
187
- "chart1",
188
- "chart2",
189
- "chart3",
190
- "chart4",
191
- "chart5",
192
- ] as const satisfies readonly (keyof ThemeChartSlots)[];
193
-
194
- const TYPOGRAPHY_KEYS = [
195
- "bodyFont",
196
- "headingFont",
197
- "monoFont",
198
- ] as const satisfies readonly (keyof ThemeTypographySlots)[];
199
-
200
- const RADIUS_KEYS = ["radius"] as const satisfies readonly (keyof ThemeRadiusSlots)[];
201
-
202
- const APP_KEYS = [
203
- "codeBlock",
204
- "codeBlockForeground",
205
- "workflowDiagramSurface",
206
- "workflowDiagramLine",
207
- "workflowDiagramText",
208
- "workflowDiagramBorder",
209
- "workflowDiagramCompletedStroke",
210
- "workflowDiagramCompletedText",
211
- "workflowDiagramActiveFill",
212
- "workflowDiagramActiveStroke",
213
- "workflowDiagramActiveText",
214
- "workflowDiagramFailedFill",
215
- "workflowDiagramFailedStroke",
216
- "workflowDiagramFailedText",
217
- "workflowDiagramSkippedFill",
218
- "workflowDiagramSkippedStroke",
219
- "workflowDiagramSkippedText",
220
- "workflowDiagramGlow",
221
- "workflowDiagramShell",
222
- ] as const satisfies readonly (keyof ThemeAppSlots)[];
223
-
224
- const BRANDING_KEYS = [
225
- "appName",
226
- "appTitle",
227
- "logoUrl",
228
- "darkLogoUrl",
229
- ] as const satisfies readonly (keyof ThemeBranding)[];
230
-
231
- function cleanObject<T extends object>(
232
- value: unknown,
233
- keys: readonly (keyof T)[],
234
- ): Partial<T> | undefined {
235
- if (!value || typeof value !== "object" || Array.isArray(value)) return undefined;
236
- const next: Partial<T> = {};
237
- for (const key of keys) {
238
- const raw = (value as Record<string, unknown>)[key as string];
239
- if (typeof raw === "string" && raw.trim()) {
240
- next[key] = raw.trim() as T[keyof T];
241
- }
242
- }
243
- return Object.keys(next).length > 0 ? next : undefined;
244
- }
245
-
246
- function sanitizeThemeDefinition(value: ThemeDefinition | null | undefined): ThemeDefinition {
247
- if (!value || typeof value !== "object") return {};
248
- return {
249
- light: cleanObject<ThemeColorSlots>(value.light, COLOR_KEYS),
250
- dark: cleanObject<ThemeColorSlots>(value.dark, COLOR_KEYS),
251
- sidebar: {
252
- light: cleanObject<ThemeSidebarSlots>(value.sidebar?.light, SIDEBAR_KEYS),
253
- dark: cleanObject<ThemeSidebarSlots>(value.sidebar?.dark, SIDEBAR_KEYS),
254
- },
255
- status: {
256
- light: cleanObject<ThemeStatusSlots>(value.status?.light, STATUS_KEYS),
257
- dark: cleanObject<ThemeStatusSlots>(value.status?.dark, STATUS_KEYS),
258
- },
259
- charts: {
260
- light: cleanObject<ThemeChartSlots>(value.charts?.light, CHART_KEYS),
261
- dark: cleanObject<ThemeChartSlots>(value.charts?.dark, CHART_KEYS),
262
- },
263
- typography: cleanObject<ThemeTypographySlots>(value.typography, TYPOGRAPHY_KEYS),
264
- radius: cleanObject<ThemeRadiusSlots>(value.radius, RADIUS_KEYS),
265
- app: {
266
- light: cleanObject<ThemeAppSlots>(value.app?.light, APP_KEYS),
267
- dark: cleanObject<ThemeAppSlots>(value.app?.dark, APP_KEYS),
268
- },
269
- branding: cleanObject<ThemeBranding>(value.branding, BRANDING_KEYS),
270
- };
271
- }
272
-
273
- function mergePartial<T extends object>(
274
- base: T | undefined,
275
- patch: Partial<T> | undefined,
276
- ): T | undefined {
277
- if (!base && !patch) return undefined;
278
- return { ...(base ?? {}), ...(patch ?? {}) } as T;
279
- }
280
-
281
- export function mergeThemeDefinitions(...definitions: (ThemeDefinition | null | undefined)[]): ThemeDefinition {
282
- let current: ThemeDefinition = {};
283
- for (const raw of definitions) {
284
- const next = sanitizeThemeDefinition(raw);
285
- current = {
286
- light: mergePartial(current.light, next.light),
287
- dark: mergePartial(current.dark, next.dark),
288
- sidebar: {
289
- light: mergePartial(current.sidebar?.light, next.sidebar?.light),
290
- dark: mergePartial(current.sidebar?.dark, next.sidebar?.dark),
291
- },
292
- status: {
293
- light: mergePartial(current.status?.light, next.status?.light),
294
- dark: mergePartial(current.status?.dark, next.status?.dark),
295
- },
296
- charts: {
297
- light: mergePartial(current.charts?.light, next.charts?.light),
298
- dark: mergePartial(current.charts?.dark, next.charts?.dark),
299
- },
300
- typography: mergePartial(current.typography, next.typography),
301
- radius: mergePartial(current.radius, next.radius),
302
- app: {
303
- light: mergePartial(current.app?.light, next.app?.light),
304
- dark: mergePartial(current.app?.dark, next.app?.dark),
305
- },
306
- branding: mergePartial(current.branding, next.branding),
307
- };
308
- }
309
- return current;
310
- }
311
-
312
- function toCssVars(
313
- colors: ThemeColorSlots,
314
- sidebar: ThemeSidebarSlots,
315
- status: ThemeStatusSlots,
316
- charts: ThemeChartSlots,
317
- typography: ThemeTypographySlots,
318
- radius: ThemeRadiusSlots,
319
- app: ThemeAppSlots,
320
- ): CSSProperties {
321
- return {
322
- ["--background" as string]: colors.background,
323
- ["--foreground" as string]: colors.foreground,
324
- ["--card" as string]: colors.card,
325
- ["--card-foreground" as string]: colors.cardForeground,
326
- ["--popover" as string]: colors.popover,
327
- ["--popover-foreground" as string]: colors.popoverForeground,
328
- ["--primary" as string]: colors.primary,
329
- ["--primary-foreground" as string]: colors.primaryForeground,
330
- ["--secondary" as string]: colors.secondary,
331
- ["--secondary-foreground" as string]: colors.secondaryForeground,
332
- ["--muted" as string]: colors.muted,
333
- ["--muted-foreground" as string]: colors.mutedForeground,
334
- ["--accent" as string]: colors.accent,
335
- ["--accent-foreground" as string]: colors.accentForeground,
336
- ["--destructive" as string]: colors.destructive,
337
- ["--destructive-foreground" as string]: colors.destructiveForeground,
338
- ["--border" as string]: colors.border,
339
- ["--input" as string]: colors.input,
340
- ["--ring" as string]: colors.ring,
341
- ["--sidebar" as string]: sidebar.sidebar,
342
- ["--sidebar-foreground" as string]: sidebar.sidebarForeground,
343
- ["--sidebar-primary" as string]: sidebar.sidebarPrimary,
344
- ["--sidebar-primary-foreground" as string]: sidebar.sidebarPrimaryForeground,
345
- ["--sidebar-accent" as string]: sidebar.sidebarAccent,
346
- ["--sidebar-accent-foreground" as string]: sidebar.sidebarAccentForeground,
347
- ["--sidebar-selected" as string]: sidebar.sidebarSelected,
348
- ["--sidebar-selected-foreground" as string]: sidebar.sidebarSelectedForeground,
349
- ["--sidebar-border" as string]: sidebar.sidebarBorder,
350
- ["--sidebar-ring" as string]: sidebar.sidebarRing,
351
- ["--success" as string]: status.success,
352
- ["--success-foreground" as string]: status.successForeground,
353
- ["--warning" as string]: status.warning,
354
- ["--warning-foreground" as string]: status.warningForeground,
355
- ["--info" as string]: status.info,
356
- ["--info-foreground" as string]: status.infoForeground,
357
- ["--syntax-key" as string]: status.syntaxKey,
358
- ["--syntax-string" as string]: status.syntaxString,
359
- ["--syntax-number" as string]: status.syntaxNumber,
360
- ["--syntax-boolean" as string]: status.syntaxBoolean,
361
- ["--chart-1" as string]: charts.chart1,
362
- ["--chart-2" as string]: charts.chart2,
363
- ["--chart-3" as string]: charts.chart3,
364
- ["--chart-4" as string]: charts.chart4,
365
- ["--chart-5" as string]: charts.chart5,
366
- ["--font-body" as string]: typography.bodyFont,
367
- ["--font-heading" as string]: typography.headingFont,
368
- ["--font-mono" as string]: typography.monoFont,
369
- ["--radius" as string]: radius.radius,
370
- ["--code-block" as string]: app.codeBlock,
371
- ["--code-block-foreground" as string]: app.codeBlockForeground,
372
- ["--workflow-diagram-surface" as string]: app.workflowDiagramSurface,
373
- ["--workflow-diagram-line" as string]: app.workflowDiagramLine,
374
- ["--workflow-diagram-text" as string]: app.workflowDiagramText,
375
- ["--workflow-diagram-border" as string]: app.workflowDiagramBorder,
376
- ["--workflow-diagram-completed-stroke" as string]: app.workflowDiagramCompletedStroke,
377
- ["--workflow-diagram-completed-text" as string]: app.workflowDiagramCompletedText,
378
- ["--workflow-diagram-active-fill" as string]: app.workflowDiagramActiveFill,
379
- ["--workflow-diagram-active-stroke" as string]: app.workflowDiagramActiveStroke,
380
- ["--workflow-diagram-active-text" as string]: app.workflowDiagramActiveText,
381
- ["--workflow-diagram-failed-fill" as string]: app.workflowDiagramFailedFill,
382
- ["--workflow-diagram-failed-stroke" as string]: app.workflowDiagramFailedStroke,
383
- ["--workflow-diagram-failed-text" as string]: app.workflowDiagramFailedText,
384
- ["--workflow-diagram-skipped-fill" as string]: app.workflowDiagramSkippedFill,
385
- ["--workflow-diagram-skipped-stroke" as string]: app.workflowDiagramSkippedStroke,
386
- ["--workflow-diagram-skipped-text" as string]: app.workflowDiagramSkippedText,
387
- ["--workflow-diagram-glow" as string]: app.workflowDiagramGlow,
388
- ["--workflow-diagram-shell" as string]: app.workflowDiagramShell,
389
- };
390
- }
391
-
392
- export function getEffectiveThemeMode(mode: ThemeMode): "light" | "dark" {
393
- if (mode === "light" || mode === "dark") return mode;
394
- if (typeof window !== "undefined") {
395
- return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
396
- }
397
- return "light";
398
- }
399
-
400
- function defaultSidebar(colors: ThemeColorSlots): ThemeSidebarSlots {
401
- return {
402
- sidebar: colors.secondary!,
403
- sidebarForeground: colors.foreground!,
404
- sidebarPrimary: colors.primary!,
405
- sidebarPrimaryForeground: colors.primaryForeground!,
406
- sidebarAccent: colors.accent!,
407
- sidebarAccentForeground: colors.accentForeground!,
408
- sidebarSelected: colors.muted!,
409
- sidebarSelectedForeground: colors.foreground!,
410
- sidebarBorder: colors.border!,
411
- sidebarRing: colors.ring!,
412
- };
413
- }
414
-
415
- function defaultStatus(mode: "light" | "dark", colors: ThemeColorSlots): ThemeStatusSlots {
416
- if (mode === "dark") {
417
- return {
418
- success: "oklch(0.72 0.14 155)",
419
- successForeground: "oklch(0.16 0.01 155)",
420
- warning: "oklch(0.72 0.13 84)",
421
- warningForeground: "oklch(0.2 0.03 84)",
422
- info: colors.primary!,
423
- infoForeground: colors.primaryForeground!,
424
- syntaxKey: "oklch(0.8 0.12 286)",
425
- syntaxString: "oklch(0.82 0.12 155)",
426
- syntaxNumber: "oklch(0.78 0.14 245)",
427
- syntaxBoolean: "oklch(0.79 0.15 84)",
428
- };
429
- }
430
- return {
431
- success: "oklch(0.58 0.16 155)",
432
- successForeground: "oklch(1 0 0)",
433
- warning: "oklch(0.72 0.16 84)",
434
- warningForeground: "oklch(0.3 0.05 84)",
435
- info: colors.primary!,
436
- infoForeground: colors.primaryForeground!,
437
- syntaxKey: "oklch(0.48 0.17 286)",
438
- syntaxString: "oklch(0.5 0.15 155)",
439
- syntaxNumber: "oklch(0.52 0.16 245)",
440
- syntaxBoolean: "oklch(0.58 0.15 84)",
441
- };
442
- }
443
-
444
- function defaultCharts(mode: "light" | "dark"): ThemeChartSlots {
445
- if (mode === "dark") {
446
- return {
447
- chart1: "oklch(0.72 0.17 286)",
448
- chart2: "oklch(0.74 0.13 240)",
449
- chart3: "oklch(0.76 0.12 195)",
450
- chart4: "oklch(0.79 0.15 84)",
451
- chart5: "oklch(0.74 0.14 20)",
452
- };
453
- }
454
- return {
455
- chart1: "oklch(0.55 0.19 286)",
456
- chart2: "oklch(0.56 0.15 240)",
457
- chart3: "oklch(0.58 0.13 195)",
458
- chart4: "oklch(0.7 0.16 84)",
459
- chart5: "oklch(0.63 0.17 20)",
460
- };
461
- }
462
-
463
- function defaultApp(mode: "light" | "dark", colors: ThemeColorSlots): ThemeAppSlots {
464
- if (mode === "dark") {
465
- return {
466
- codeBlock: "oklch(0.16 0.01 286)",
467
- codeBlockForeground: "oklch(0.92 0.01 286)",
468
- workflowDiagramSurface: "color-mix(in srgb, var(--background) 84%, var(--primary) 16%)",
469
- workflowDiagramLine: "color-mix(in srgb, var(--primary) 90%, white 10%)",
470
- workflowDiagramText: "oklch(0.95 0.01 286)",
471
- workflowDiagramBorder: "color-mix(in srgb, var(--primary) 34%, var(--border) 66%)",
472
- workflowDiagramCompletedStroke:
473
- "color-mix(in srgb, var(--success) 82%, var(--primary) 18%)",
474
- workflowDiagramCompletedText:
475
- "color-mix(in srgb, var(--foreground) 76%, var(--success) 24%)",
476
- workflowDiagramActiveFill:
477
- "color-mix(in srgb, var(--background) 76%, var(--primary) 24%)",
478
- workflowDiagramActiveStroke: "color-mix(in srgb, var(--primary) 92%, white 8%)",
479
- workflowDiagramActiveText: "oklch(0.95 0.01 286)",
480
- workflowDiagramFailedFill: "color-mix(in srgb, var(--destructive) 22%, var(--background) 78%)",
481
- workflowDiagramFailedStroke: colors.destructive!,
482
- workflowDiagramFailedText: "color-mix(in srgb, var(--destructive) 58%, white 42%)",
483
- workflowDiagramSkippedFill: "color-mix(in srgb, var(--muted) 80%, var(--background) 20%)",
484
- workflowDiagramSkippedStroke: "color-mix(in srgb, var(--muted-foreground) 36%, transparent)",
485
- workflowDiagramSkippedText: colors.mutedForeground!,
486
- workflowDiagramGlow: "rgba(182, 148, 255, 0.18)",
487
- workflowDiagramShell: "rgba(182, 148, 255, 0.06)",
488
- };
489
- }
490
- return {
491
- codeBlock: "oklch(0.2 0 0)",
492
- codeBlockForeground: "oklch(0.93 0 0)",
493
- workflowDiagramSurface: "color-mix(in srgb, var(--background) 95%, var(--primary) 5%)",
494
- workflowDiagramLine: "color-mix(in srgb, var(--primary) 84%, var(--foreground) 16%)",
495
- workflowDiagramText: "color-mix(in srgb, var(--foreground) 88%, var(--primary) 12%)",
496
- workflowDiagramBorder: "color-mix(in srgb, var(--primary) 18%, var(--border) 82%)",
497
- workflowDiagramCompletedStroke:
498
- "color-mix(in srgb, var(--success) 78%, var(--primary) 22%)",
499
- workflowDiagramCompletedText:
500
- "color-mix(in srgb, var(--foreground) 82%, var(--success) 18%)",
501
- workflowDiagramActiveFill:
502
- "color-mix(in srgb, var(--background) 90%, var(--primary) 10%)",
503
- workflowDiagramActiveStroke: colors.primary!,
504
- workflowDiagramActiveText: "color-mix(in srgb, var(--foreground) 86%, var(--primary) 14%)",
505
- workflowDiagramFailedFill: "color-mix(in srgb, var(--destructive) 8%, var(--background) 92%)",
506
- workflowDiagramFailedStroke: colors.destructive!,
507
- workflowDiagramFailedText:
508
- "color-mix(in srgb, var(--destructive) 62%, var(--foreground) 38%)",
509
- workflowDiagramSkippedFill: "color-mix(in srgb, var(--muted) 65%, var(--background) 35%)",
510
- workflowDiagramSkippedStroke: "color-mix(in srgb, var(--muted-foreground) 22%, transparent)",
511
- workflowDiagramSkippedText: colors.mutedForeground!,
512
- workflowDiagramGlow: "rgba(124, 58, 237, 0.18)",
513
- workflowDiagramShell: "rgba(124, 58, 237, 0.04)",
514
- };
515
- }
516
-
517
- export const FOUNDRY_VIOLET_THEME: ThemeDefinition = {
518
- light: {
519
- background: "oklch(100% 0 0)",
520
- foreground: "oklch(21% 0.006 290)",
521
- card: "oklch(100% 0 0)",
522
- cardForeground: "oklch(21% 0.006 290)",
523
- popover: "oklch(100% 0 0)",
524
- popoverForeground: "oklch(21% 0.006 290)",
525
- primary: "oklch(43% 0.24 286)",
526
- primaryForeground: "oklch(100% 0 0)",
527
- secondary: "oklch(96% 0.015 290)",
528
- secondaryForeground: "oklch(35% 0.15 290)",
529
- muted: "oklch(98% 0 0)",
530
- mutedForeground: "oklch(45% 0.01 290)",
531
- accent: "oklch(96% 0.02 290)",
532
- accentForeground: "oklch(30% 0.1 290)",
533
- destructive: "oklch(55% 0.18 15)",
534
- destructiveForeground: "oklch(100% 0 0)",
535
- border: "oklch(92% 0.008 290)",
536
- input: "oklch(92% 0.008 290)",
537
- ring: "oklch(43% 0.24 286)",
538
- },
539
- sidebar: {
540
- light: {
541
- sidebar: "oklch(99.2% 0 0)",
542
- sidebarForeground: "oklch(24% 0.004 286)",
543
- sidebarPrimary: "oklch(43% 0.24 286)",
544
- sidebarPrimaryForeground: "oklch(100% 0 0)",
545
- sidebarAccent: "color-mix(in srgb, var(--primary) 4%, var(--background) 96%)",
546
- sidebarAccentForeground: "color-mix(in srgb, var(--foreground) 92%, var(--primary) 8%)",
547
- sidebarSelected: "var(--muted)",
548
- sidebarSelectedForeground: "var(--foreground)",
549
- sidebarBorder: "color-mix(in srgb, var(--border) 96%, var(--foreground) 4%)",
550
- sidebarRing: "oklch(43% 0.24 286)",
551
- },
552
- dark: {
553
- sidebar: "oklch(0.18 0.004 286)",
554
- sidebarForeground: "oklch(0.94 0.004 286)",
555
- sidebarPrimary: "oklch(0.72 0.18 286)",
556
- sidebarPrimaryForeground: "oklch(0.98 0 0)",
557
- sidebarAccent: "color-mix(in srgb, var(--primary) 8%, var(--background) 92%)",
558
- sidebarAccentForeground: "color-mix(in srgb, var(--foreground) 90%, white 10%)",
559
- sidebarSelected: "color-mix(in srgb, var(--muted) 78%, var(--background) 22%)",
560
- sidebarSelectedForeground: "var(--foreground)",
561
- sidebarBorder: "color-mix(in srgb, var(--border) 90%, white 10%)",
562
- sidebarRing: "oklch(0.72 0.18 286)",
563
- },
564
- },
565
- dark: {
566
- background: "oklch(0.145 0.008 286)",
567
- foreground: "oklch(0.95 0.01 286)",
568
- card: "oklch(0.19 0.012 286)",
569
- cardForeground: "oklch(0.95 0.01 286)",
570
- popover: "oklch(0.19 0.012 286)",
571
- popoverForeground: "oklch(0.95 0.01 286)",
572
- primary: "oklch(0.72 0.18 286)",
573
- primaryForeground: "oklch(0.98 0 0)",
574
- secondary: "oklch(0.24 0.02 286)",
575
- secondaryForeground: "oklch(0.92 0.01 286)",
576
- muted: "oklch(0.22 0.015 286)",
577
- mutedForeground: "oklch(0.65 0.02 286)",
578
- accent: "oklch(0.26 0.025 286)",
579
- accentForeground: "oklch(0.92 0.01 286)",
580
- destructive: "oklch(0.704 0.191 22.216)",
581
- destructiveForeground: "oklch(0.985 0 0)",
582
- border: "oklch(1 0.01 286 / 12%)",
583
- input: "oklch(1 0.01 286 / 15%)",
584
- ring: "oklch(0.72 0.18 286)",
585
- },
586
- typography: {
587
- bodyFont:
588
- "\"Segoe UI\", ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, sans-serif",
589
- headingFont:
590
- "\"Segoe UI\", ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, sans-serif",
591
- monoFont:
592
- "\"SFMono-Regular\", \"Cascadia Code\", \"JetBrains Mono\", ui-monospace, monospace",
593
- },
594
- radius: {
595
- radius: "0.875rem",
596
- },
597
- branding: {
598
- appName: "eomi",
599
- appTitle: "eomi",
600
- },
601
- };
602
-
603
- export function getThemePreset(name?: string | null): ThemeDefinition {
604
- if (!name || name === "foundry-violet") return FOUNDRY_VIOLET_THEME;
605
- return FOUNDRY_VIOLET_THEME;
606
- }
607
-
608
- export function resolveThemeRuntime(
609
- layers: ThemeLayer[],
610
- mode: ThemeMode,
611
- ): ResolvedThemeRuntime {
612
- const effectiveMode = getEffectiveThemeMode(mode);
613
- const basePreset =
614
- layers.find((layer) => layer.basePreset && layer.basePreset.trim())?.basePreset ??
615
- "foundry-violet";
616
- const definitions = [
617
- getThemePreset(basePreset),
618
- ...layers.map((layer) => layer.definition),
619
- ];
620
- const definition = mergeThemeDefinitions(...definitions);
621
- const colors = {
622
- ...(effectiveMode === "dark" ? definition.dark : definition.light),
623
- } as ThemeColorSlots;
624
- const sidebar = {
625
- ...defaultSidebar(colors),
626
- ...(effectiveMode === "dark" ? definition.sidebar?.dark : definition.sidebar?.light),
627
- } as ThemeSidebarSlots;
628
- const status = {
629
- ...defaultStatus(effectiveMode, colors),
630
- ...(effectiveMode === "dark" ? definition.status?.dark : definition.status?.light),
631
- } as ThemeStatusSlots;
632
- const charts = {
633
- ...defaultCharts(effectiveMode),
634
- ...(effectiveMode === "dark" ? definition.charts?.dark : definition.charts?.light),
635
- } as ThemeChartSlots;
636
- const typography = {
637
- ...FOUNDRY_VIOLET_THEME.typography,
638
- ...definition.typography,
639
- } as ThemeTypographySlots;
640
- const radius = {
641
- ...FOUNDRY_VIOLET_THEME.radius,
642
- ...definition.radius,
643
- } as ThemeRadiusSlots;
644
- const app = {
645
- ...defaultApp(effectiveMode, colors),
646
- ...(effectiveMode === "dark" ? definition.app?.dark : definition.app?.light),
647
- } as ThemeAppSlots;
648
- const branding = {
649
- ...FOUNDRY_VIOLET_THEME.branding,
650
- ...definition.branding,
651
- } as ThemeBranding;
652
-
653
- return {
654
- mode: effectiveMode,
655
- definition,
656
- branding,
657
- variables: toCssVars(colors, sidebar, status, charts, typography, radius, app),
658
- sources: layers,
659
- };
660
- }