@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
@@ -0,0 +1,479 @@
1
+ const COLOR_KEYS = [
2
+ "background",
3
+ "foreground",
4
+ "card",
5
+ "cardForeground",
6
+ "popover",
7
+ "popoverForeground",
8
+ "primary",
9
+ "primaryForeground",
10
+ "secondary",
11
+ "secondaryForeground",
12
+ "muted",
13
+ "mutedForeground",
14
+ "accent",
15
+ "accentForeground",
16
+ "destructive",
17
+ "destructiveForeground",
18
+ "border",
19
+ "input",
20
+ "ring",
21
+ ];
22
+ const SIDEBAR_KEYS = [
23
+ "sidebar",
24
+ "sidebarForeground",
25
+ "sidebarPrimary",
26
+ "sidebarPrimaryForeground",
27
+ "sidebarAccent",
28
+ "sidebarAccentForeground",
29
+ "sidebarSelected",
30
+ "sidebarSelectedForeground",
31
+ "sidebarBorder",
32
+ "sidebarRing",
33
+ ];
34
+ const STATUS_KEYS = [
35
+ "success",
36
+ "successForeground",
37
+ "warning",
38
+ "warningForeground",
39
+ "info",
40
+ "infoForeground",
41
+ "syntaxKey",
42
+ "syntaxString",
43
+ "syntaxNumber",
44
+ "syntaxBoolean",
45
+ ];
46
+ const CHART_KEYS = [
47
+ "chart1",
48
+ "chart2",
49
+ "chart3",
50
+ "chart4",
51
+ "chart5",
52
+ ];
53
+ const TYPOGRAPHY_KEYS = [
54
+ "bodyFont",
55
+ "headingFont",
56
+ "monoFont",
57
+ ];
58
+ const RADIUS_KEYS = ["radius"];
59
+ const APP_KEYS = [
60
+ "codeBlock",
61
+ "codeBlockForeground",
62
+ "workflowDiagramSurface",
63
+ "workflowDiagramLine",
64
+ "workflowDiagramText",
65
+ "workflowDiagramBorder",
66
+ "workflowDiagramCompletedStroke",
67
+ "workflowDiagramCompletedText",
68
+ "workflowDiagramActiveFill",
69
+ "workflowDiagramActiveStroke",
70
+ "workflowDiagramActiveText",
71
+ "workflowDiagramFailedFill",
72
+ "workflowDiagramFailedStroke",
73
+ "workflowDiagramFailedText",
74
+ "workflowDiagramSkippedFill",
75
+ "workflowDiagramSkippedStroke",
76
+ "workflowDiagramSkippedText",
77
+ "workflowDiagramGlow",
78
+ "workflowDiagramShell",
79
+ ];
80
+ const BRANDING_KEYS = [
81
+ "appName",
82
+ "appTitle",
83
+ "logoUrl",
84
+ "darkLogoUrl",
85
+ ];
86
+ function cleanObject(value, keys) {
87
+ if (!value || typeof value !== "object" || Array.isArray(value))
88
+ return undefined;
89
+ const next = {};
90
+ for (const key of keys) {
91
+ const raw = value[key];
92
+ if (typeof raw === "string" && raw.trim()) {
93
+ next[key] = raw.trim();
94
+ }
95
+ }
96
+ return Object.keys(next).length > 0 ? next : undefined;
97
+ }
98
+ function sanitizeThemeDefinition(value) {
99
+ if (!value || typeof value !== "object")
100
+ return {};
101
+ return {
102
+ light: cleanObject(value.light, COLOR_KEYS),
103
+ dark: cleanObject(value.dark, COLOR_KEYS),
104
+ sidebar: {
105
+ light: cleanObject(value.sidebar?.light, SIDEBAR_KEYS),
106
+ dark: cleanObject(value.sidebar?.dark, SIDEBAR_KEYS),
107
+ },
108
+ status: {
109
+ light: cleanObject(value.status?.light, STATUS_KEYS),
110
+ dark: cleanObject(value.status?.dark, STATUS_KEYS),
111
+ },
112
+ charts: {
113
+ light: cleanObject(value.charts?.light, CHART_KEYS),
114
+ dark: cleanObject(value.charts?.dark, CHART_KEYS),
115
+ },
116
+ typography: cleanObject(value.typography, TYPOGRAPHY_KEYS),
117
+ radius: cleanObject(value.radius, RADIUS_KEYS),
118
+ app: {
119
+ light: cleanObject(value.app?.light, APP_KEYS),
120
+ dark: cleanObject(value.app?.dark, APP_KEYS),
121
+ },
122
+ branding: cleanObject(value.branding, BRANDING_KEYS),
123
+ };
124
+ }
125
+ function mergePartial(base, patch) {
126
+ if (!base && !patch)
127
+ return undefined;
128
+ return { ...(base ?? {}), ...(patch ?? {}) };
129
+ }
130
+ export function mergeThemeDefinitions(...definitions) {
131
+ let current = {};
132
+ for (const raw of definitions) {
133
+ const next = sanitizeThemeDefinition(raw);
134
+ current = {
135
+ light: mergePartial(current.light, next.light),
136
+ dark: mergePartial(current.dark, next.dark),
137
+ sidebar: {
138
+ light: mergePartial(current.sidebar?.light, next.sidebar?.light),
139
+ dark: mergePartial(current.sidebar?.dark, next.sidebar?.dark),
140
+ },
141
+ status: {
142
+ light: mergePartial(current.status?.light, next.status?.light),
143
+ dark: mergePartial(current.status?.dark, next.status?.dark),
144
+ },
145
+ charts: {
146
+ light: mergePartial(current.charts?.light, next.charts?.light),
147
+ dark: mergePartial(current.charts?.dark, next.charts?.dark),
148
+ },
149
+ typography: mergePartial(current.typography, next.typography),
150
+ radius: mergePartial(current.radius, next.radius),
151
+ app: {
152
+ light: mergePartial(current.app?.light, next.app?.light),
153
+ dark: mergePartial(current.app?.dark, next.app?.dark),
154
+ },
155
+ branding: mergePartial(current.branding, next.branding),
156
+ };
157
+ }
158
+ return current;
159
+ }
160
+ function toCssVars(colors, sidebar, status, charts, typography, radius, app) {
161
+ return {
162
+ ["--background"]: colors.background,
163
+ ["--foreground"]: colors.foreground,
164
+ ["--card"]: colors.card,
165
+ ["--card-foreground"]: colors.cardForeground,
166
+ ["--popover"]: colors.popover,
167
+ ["--popover-foreground"]: colors.popoverForeground,
168
+ ["--primary"]: colors.primary,
169
+ ["--primary-foreground"]: colors.primaryForeground,
170
+ ["--secondary"]: colors.secondary,
171
+ ["--secondary-foreground"]: colors.secondaryForeground,
172
+ ["--muted"]: colors.muted,
173
+ ["--muted-foreground"]: colors.mutedForeground,
174
+ ["--accent"]: colors.accent,
175
+ ["--accent-foreground"]: colors.accentForeground,
176
+ ["--destructive"]: colors.destructive,
177
+ ["--destructive-foreground"]: colors.destructiveForeground,
178
+ ["--border"]: colors.border,
179
+ ["--input"]: colors.input,
180
+ ["--ring"]: colors.ring,
181
+ ["--sidebar"]: sidebar.sidebar,
182
+ ["--sidebar-foreground"]: sidebar.sidebarForeground,
183
+ ["--sidebar-primary"]: sidebar.sidebarPrimary,
184
+ ["--sidebar-primary-foreground"]: sidebar.sidebarPrimaryForeground,
185
+ ["--sidebar-accent"]: sidebar.sidebarAccent,
186
+ ["--sidebar-accent-foreground"]: sidebar.sidebarAccentForeground,
187
+ ["--sidebar-selected"]: sidebar.sidebarSelected,
188
+ ["--sidebar-selected-foreground"]: sidebar.sidebarSelectedForeground,
189
+ ["--sidebar-border"]: sidebar.sidebarBorder,
190
+ ["--sidebar-ring"]: sidebar.sidebarRing,
191
+ ["--success"]: status.success,
192
+ ["--success-foreground"]: status.successForeground,
193
+ ["--warning"]: status.warning,
194
+ ["--warning-foreground"]: status.warningForeground,
195
+ ["--info"]: status.info,
196
+ ["--info-foreground"]: status.infoForeground,
197
+ ["--syntax-key"]: status.syntaxKey,
198
+ ["--syntax-string"]: status.syntaxString,
199
+ ["--syntax-number"]: status.syntaxNumber,
200
+ ["--syntax-boolean"]: status.syntaxBoolean,
201
+ ["--chart-1"]: charts.chart1,
202
+ ["--chart-2"]: charts.chart2,
203
+ ["--chart-3"]: charts.chart3,
204
+ ["--chart-4"]: charts.chart4,
205
+ ["--chart-5"]: charts.chart5,
206
+ ["--font-body"]: typography.bodyFont,
207
+ ["--font-heading"]: typography.headingFont,
208
+ ["--font-mono"]: typography.monoFont,
209
+ ["--radius"]: radius.radius,
210
+ ["--code-block"]: app.codeBlock,
211
+ ["--code-block-foreground"]: app.codeBlockForeground,
212
+ ["--workflow-diagram-surface"]: app.workflowDiagramSurface,
213
+ ["--workflow-diagram-line"]: app.workflowDiagramLine,
214
+ ["--workflow-diagram-text"]: app.workflowDiagramText,
215
+ ["--workflow-diagram-border"]: app.workflowDiagramBorder,
216
+ ["--workflow-diagram-completed-stroke"]: app.workflowDiagramCompletedStroke,
217
+ ["--workflow-diagram-completed-text"]: app.workflowDiagramCompletedText,
218
+ ["--workflow-diagram-active-fill"]: app.workflowDiagramActiveFill,
219
+ ["--workflow-diagram-active-stroke"]: app.workflowDiagramActiveStroke,
220
+ ["--workflow-diagram-active-text"]: app.workflowDiagramActiveText,
221
+ ["--workflow-diagram-failed-fill"]: app.workflowDiagramFailedFill,
222
+ ["--workflow-diagram-failed-stroke"]: app.workflowDiagramFailedStroke,
223
+ ["--workflow-diagram-failed-text"]: app.workflowDiagramFailedText,
224
+ ["--workflow-diagram-skipped-fill"]: app.workflowDiagramSkippedFill,
225
+ ["--workflow-diagram-skipped-stroke"]: app.workflowDiagramSkippedStroke,
226
+ ["--workflow-diagram-skipped-text"]: app.workflowDiagramSkippedText,
227
+ ["--workflow-diagram-glow"]: app.workflowDiagramGlow,
228
+ ["--workflow-diagram-shell"]: app.workflowDiagramShell,
229
+ };
230
+ }
231
+ export function getEffectiveThemeMode(mode) {
232
+ if (mode === "light" || mode === "dark")
233
+ return mode;
234
+ if (typeof window !== "undefined") {
235
+ return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
236
+ }
237
+ return "light";
238
+ }
239
+ function defaultSidebar(colors) {
240
+ return {
241
+ sidebar: colors.secondary,
242
+ sidebarForeground: colors.foreground,
243
+ sidebarPrimary: colors.primary,
244
+ sidebarPrimaryForeground: colors.primaryForeground,
245
+ sidebarAccent: colors.accent,
246
+ sidebarAccentForeground: colors.accentForeground,
247
+ sidebarSelected: colors.muted,
248
+ sidebarSelectedForeground: colors.foreground,
249
+ sidebarBorder: colors.border,
250
+ sidebarRing: colors.ring,
251
+ };
252
+ }
253
+ function defaultStatus(mode, colors) {
254
+ if (mode === "dark") {
255
+ return {
256
+ success: "oklch(0.72 0.14 155)",
257
+ successForeground: "oklch(0.16 0.01 155)",
258
+ warning: "oklch(0.72 0.13 84)",
259
+ warningForeground: "oklch(0.2 0.03 84)",
260
+ info: colors.primary,
261
+ infoForeground: colors.primaryForeground,
262
+ syntaxKey: "oklch(0.8 0.12 286)",
263
+ syntaxString: "oklch(0.82 0.12 155)",
264
+ syntaxNumber: "oklch(0.78 0.14 245)",
265
+ syntaxBoolean: "oklch(0.79 0.15 84)",
266
+ };
267
+ }
268
+ return {
269
+ success: "oklch(0.58 0.16 155)",
270
+ successForeground: "oklch(1 0 0)",
271
+ warning: "oklch(0.72 0.16 84)",
272
+ warningForeground: "oklch(0.3 0.05 84)",
273
+ info: colors.primary,
274
+ infoForeground: colors.primaryForeground,
275
+ syntaxKey: "oklch(0.48 0.17 286)",
276
+ syntaxString: "oklch(0.5 0.15 155)",
277
+ syntaxNumber: "oklch(0.52 0.16 245)",
278
+ syntaxBoolean: "oklch(0.58 0.15 84)",
279
+ };
280
+ }
281
+ function defaultCharts(mode) {
282
+ if (mode === "dark") {
283
+ return {
284
+ chart1: "oklch(0.72 0.17 286)",
285
+ chart2: "oklch(0.74 0.13 240)",
286
+ chart3: "oklch(0.76 0.12 195)",
287
+ chart4: "oklch(0.79 0.15 84)",
288
+ chart5: "oklch(0.74 0.14 20)",
289
+ };
290
+ }
291
+ return {
292
+ chart1: "oklch(0.55 0.19 286)",
293
+ chart2: "oklch(0.56 0.15 240)",
294
+ chart3: "oklch(0.58 0.13 195)",
295
+ chart4: "oklch(0.7 0.16 84)",
296
+ chart5: "oklch(0.63 0.17 20)",
297
+ };
298
+ }
299
+ function defaultApp(mode, colors) {
300
+ if (mode === "dark") {
301
+ return {
302
+ codeBlock: "oklch(0.16 0.01 286)",
303
+ codeBlockForeground: "oklch(0.92 0.01 286)",
304
+ workflowDiagramSurface: "color-mix(in srgb, var(--background) 84%, var(--primary) 16%)",
305
+ workflowDiagramLine: "color-mix(in srgb, var(--primary) 90%, white 10%)",
306
+ workflowDiagramText: "oklch(0.95 0.01 286)",
307
+ workflowDiagramBorder: "color-mix(in srgb, var(--primary) 34%, var(--border) 66%)",
308
+ workflowDiagramCompletedStroke: "color-mix(in srgb, var(--success) 82%, var(--primary) 18%)",
309
+ workflowDiagramCompletedText: "color-mix(in srgb, var(--foreground) 76%, var(--success) 24%)",
310
+ workflowDiagramActiveFill: "color-mix(in srgb, var(--background) 76%, var(--primary) 24%)",
311
+ workflowDiagramActiveStroke: "color-mix(in srgb, var(--primary) 92%, white 8%)",
312
+ workflowDiagramActiveText: "oklch(0.95 0.01 286)",
313
+ workflowDiagramFailedFill: "color-mix(in srgb, var(--destructive) 22%, var(--background) 78%)",
314
+ workflowDiagramFailedStroke: colors.destructive,
315
+ workflowDiagramFailedText: "color-mix(in srgb, var(--destructive) 58%, white 42%)",
316
+ workflowDiagramSkippedFill: "color-mix(in srgb, var(--muted) 80%, var(--background) 20%)",
317
+ workflowDiagramSkippedStroke: "color-mix(in srgb, var(--muted-foreground) 36%, transparent)",
318
+ workflowDiagramSkippedText: colors.mutedForeground,
319
+ workflowDiagramGlow: "rgba(182, 148, 255, 0.18)",
320
+ workflowDiagramShell: "rgba(182, 148, 255, 0.06)",
321
+ };
322
+ }
323
+ return {
324
+ codeBlock: "oklch(0.2 0 0)",
325
+ codeBlockForeground: "oklch(0.93 0 0)",
326
+ workflowDiagramSurface: "color-mix(in srgb, var(--background) 95%, var(--primary) 5%)",
327
+ workflowDiagramLine: "color-mix(in srgb, var(--primary) 84%, var(--foreground) 16%)",
328
+ workflowDiagramText: "color-mix(in srgb, var(--foreground) 88%, var(--primary) 12%)",
329
+ workflowDiagramBorder: "color-mix(in srgb, var(--primary) 18%, var(--border) 82%)",
330
+ workflowDiagramCompletedStroke: "color-mix(in srgb, var(--success) 78%, var(--primary) 22%)",
331
+ workflowDiagramCompletedText: "color-mix(in srgb, var(--foreground) 82%, var(--success) 18%)",
332
+ workflowDiagramActiveFill: "color-mix(in srgb, var(--background) 90%, var(--primary) 10%)",
333
+ workflowDiagramActiveStroke: colors.primary,
334
+ workflowDiagramActiveText: "color-mix(in srgb, var(--foreground) 86%, var(--primary) 14%)",
335
+ workflowDiagramFailedFill: "color-mix(in srgb, var(--destructive) 8%, var(--background) 92%)",
336
+ workflowDiagramFailedStroke: colors.destructive,
337
+ workflowDiagramFailedText: "color-mix(in srgb, var(--destructive) 62%, var(--foreground) 38%)",
338
+ workflowDiagramSkippedFill: "color-mix(in srgb, var(--muted) 65%, var(--background) 35%)",
339
+ workflowDiagramSkippedStroke: "color-mix(in srgb, var(--muted-foreground) 22%, transparent)",
340
+ workflowDiagramSkippedText: colors.mutedForeground,
341
+ workflowDiagramGlow: "rgba(124, 58, 237, 0.18)",
342
+ workflowDiagramShell: "rgba(124, 58, 237, 0.04)",
343
+ };
344
+ }
345
+ export const FOUNDRY_VIOLET_THEME = {
346
+ light: {
347
+ background: "oklch(100% 0 0)",
348
+ foreground: "oklch(21% 0.006 290)",
349
+ card: "oklch(100% 0 0)",
350
+ cardForeground: "oklch(21% 0.006 290)",
351
+ popover: "oklch(100% 0 0)",
352
+ popoverForeground: "oklch(21% 0.006 290)",
353
+ primary: "oklch(43% 0.24 286)",
354
+ primaryForeground: "oklch(100% 0 0)",
355
+ secondary: "oklch(96% 0.015 290)",
356
+ secondaryForeground: "oklch(35% 0.15 290)",
357
+ muted: "oklch(98% 0 0)",
358
+ mutedForeground: "oklch(45% 0.01 290)",
359
+ accent: "oklch(96% 0.02 290)",
360
+ accentForeground: "oklch(30% 0.1 290)",
361
+ destructive: "oklch(55% 0.18 15)",
362
+ destructiveForeground: "oklch(100% 0 0)",
363
+ border: "oklch(92% 0.008 290)",
364
+ input: "oklch(92% 0.008 290)",
365
+ ring: "oklch(43% 0.24 286)",
366
+ },
367
+ sidebar: {
368
+ light: {
369
+ sidebar: "oklch(99.2% 0 0)",
370
+ sidebarForeground: "oklch(24% 0.004 286)",
371
+ sidebarPrimary: "oklch(43% 0.24 286)",
372
+ sidebarPrimaryForeground: "oklch(100% 0 0)",
373
+ sidebarAccent: "color-mix(in srgb, var(--primary) 4%, var(--background) 96%)",
374
+ sidebarAccentForeground: "color-mix(in srgb, var(--foreground) 92%, var(--primary) 8%)",
375
+ sidebarSelected: "var(--muted)",
376
+ sidebarSelectedForeground: "var(--foreground)",
377
+ sidebarBorder: "color-mix(in srgb, var(--border) 96%, var(--foreground) 4%)",
378
+ sidebarRing: "oklch(43% 0.24 286)",
379
+ },
380
+ dark: {
381
+ sidebar: "oklch(0.18 0.004 286)",
382
+ sidebarForeground: "oklch(0.94 0.004 286)",
383
+ sidebarPrimary: "oklch(0.72 0.18 286)",
384
+ sidebarPrimaryForeground: "oklch(0.98 0 0)",
385
+ sidebarAccent: "color-mix(in srgb, var(--primary) 8%, var(--background) 92%)",
386
+ sidebarAccentForeground: "color-mix(in srgb, var(--foreground) 90%, white 10%)",
387
+ sidebarSelected: "color-mix(in srgb, var(--muted) 78%, var(--background) 22%)",
388
+ sidebarSelectedForeground: "var(--foreground)",
389
+ sidebarBorder: "color-mix(in srgb, var(--border) 90%, white 10%)",
390
+ sidebarRing: "oklch(0.72 0.18 286)",
391
+ },
392
+ },
393
+ dark: {
394
+ background: "oklch(0.145 0.008 286)",
395
+ foreground: "oklch(0.95 0.01 286)",
396
+ card: "oklch(0.19 0.012 286)",
397
+ cardForeground: "oklch(0.95 0.01 286)",
398
+ popover: "oklch(0.19 0.012 286)",
399
+ popoverForeground: "oklch(0.95 0.01 286)",
400
+ primary: "oklch(0.72 0.18 286)",
401
+ primaryForeground: "oklch(0.98 0 0)",
402
+ secondary: "oklch(0.24 0.02 286)",
403
+ secondaryForeground: "oklch(0.92 0.01 286)",
404
+ muted: "oklch(0.22 0.015 286)",
405
+ mutedForeground: "oklch(0.65 0.02 286)",
406
+ accent: "oklch(0.26 0.025 286)",
407
+ accentForeground: "oklch(0.92 0.01 286)",
408
+ destructive: "oklch(0.704 0.191 22.216)",
409
+ destructiveForeground: "oklch(0.985 0 0)",
410
+ border: "oklch(1 0.01 286 / 12%)",
411
+ input: "oklch(1 0.01 286 / 15%)",
412
+ ring: "oklch(0.72 0.18 286)",
413
+ },
414
+ typography: {
415
+ bodyFont: "\"Segoe UI\", ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, sans-serif",
416
+ headingFont: "\"Segoe UI\", ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, sans-serif",
417
+ monoFont: "\"SFMono-Regular\", \"Cascadia Code\", \"JetBrains Mono\", ui-monospace, monospace",
418
+ },
419
+ radius: {
420
+ radius: "0.875rem",
421
+ },
422
+ branding: {
423
+ appName: "Foundry UI",
424
+ appTitle: "Foundry UI",
425
+ },
426
+ };
427
+ export function getThemePreset(name) {
428
+ if (!name || name === "foundry-violet")
429
+ return FOUNDRY_VIOLET_THEME;
430
+ return FOUNDRY_VIOLET_THEME;
431
+ }
432
+ export function resolveThemeRuntime(layers, mode) {
433
+ const effectiveMode = getEffectiveThemeMode(mode);
434
+ const basePreset = layers.find((layer) => layer.basePreset && layer.basePreset.trim())?.basePreset ??
435
+ "foundry-violet";
436
+ const definitions = [
437
+ getThemePreset(basePreset),
438
+ ...layers.map((layer) => layer.definition),
439
+ ];
440
+ const definition = mergeThemeDefinitions(...definitions);
441
+ const colors = {
442
+ ...(effectiveMode === "dark" ? definition.dark : definition.light),
443
+ };
444
+ const sidebar = {
445
+ ...defaultSidebar(colors),
446
+ ...(effectiveMode === "dark" ? definition.sidebar?.dark : definition.sidebar?.light),
447
+ };
448
+ const status = {
449
+ ...defaultStatus(effectiveMode, colors),
450
+ ...(effectiveMode === "dark" ? definition.status?.dark : definition.status?.light),
451
+ };
452
+ const charts = {
453
+ ...defaultCharts(effectiveMode),
454
+ ...(effectiveMode === "dark" ? definition.charts?.dark : definition.charts?.light),
455
+ };
456
+ const typography = {
457
+ ...FOUNDRY_VIOLET_THEME.typography,
458
+ ...definition.typography,
459
+ };
460
+ const radius = {
461
+ ...FOUNDRY_VIOLET_THEME.radius,
462
+ ...definition.radius,
463
+ };
464
+ const app = {
465
+ ...defaultApp(effectiveMode, colors),
466
+ ...(effectiveMode === "dark" ? definition.app?.dark : definition.app?.light),
467
+ };
468
+ const branding = {
469
+ ...FOUNDRY_VIOLET_THEME.branding,
470
+ ...definition.branding,
471
+ };
472
+ return {
473
+ mode: effectiveMode,
474
+ definition,
475
+ branding,
476
+ variables: toCssVars(colors, sidebar, status, charts, typography, radius, app),
477
+ sources: layers,
478
+ };
479
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Theme Store -- Zustand store for dark/light/system theme preference.
3
+ *
4
+ * Persists the user's choice to localStorage and applies the `.dark` class
5
+ * on `<html>`. In "system" mode it tracks the OS preference via matchMedia.
6
+ */
7
+ export type ThemeMode = "light" | "dark" | "system";
8
+ interface ThemeState {
9
+ mode: ThemeMode;
10
+ setMode: (mode: ThemeMode) => void;
11
+ /** Cycle through light -> dark -> system. */
12
+ cycle: () => void;
13
+ }
14
+ export declare const useThemeStore: import("zustand").UseBoundStore<import("zustand").StoreApi<ThemeState>>;
15
+ export {};
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Theme Store -- Zustand store for dark/light/system theme preference.
3
+ *
4
+ * Persists the user's choice to localStorage and applies the `.dark` class
5
+ * on `<html>`. In "system" mode it tracks the OS preference via matchMedia.
6
+ */
7
+ import { create } from "zustand";
8
+ const STORAGE_KEY = "theme";
9
+ const CYCLE_ORDER = ["light", "dark", "system"];
10
+ function getStoredMode() {
11
+ if (typeof window === "undefined")
12
+ return "system";
13
+ const stored = localStorage.getItem(STORAGE_KEY);
14
+ if (stored === "light" || stored === "dark" || stored === "system")
15
+ return stored;
16
+ return "system";
17
+ }
18
+ function prefersDark() {
19
+ if (typeof window === "undefined")
20
+ return false;
21
+ return window.matchMedia("(prefers-color-scheme: dark)").matches;
22
+ }
23
+ function applyTheme(mode) {
24
+ if (typeof document === "undefined")
25
+ return;
26
+ const isDark = mode === "dark" || (mode === "system" && prefersDark());
27
+ document.documentElement.classList.toggle("dark", isDark);
28
+ }
29
+ export const useThemeStore = create((set, get) => {
30
+ const initial = getStoredMode();
31
+ applyTheme(initial);
32
+ // Listen for OS preference changes when in system mode
33
+ if (typeof window !== "undefined") {
34
+ window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", () => {
35
+ if (get().mode === "system")
36
+ applyTheme("system");
37
+ });
38
+ }
39
+ return {
40
+ mode: initial,
41
+ setMode: (mode) => {
42
+ localStorage.setItem(STORAGE_KEY, mode);
43
+ applyTheme(mode);
44
+ set({ mode });
45
+ },
46
+ cycle: () => {
47
+ const current = get().mode;
48
+ const idx = CYCLE_ORDER.indexOf(current);
49
+ const next = CYCLE_ORDER[(idx + 1) % CYCLE_ORDER.length];
50
+ get().setMode(next);
51
+ },
52
+ };
53
+ });
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Tool Panel State Management
3
+ *
4
+ * Zustand store for managing the tool panel (flyout side panel).
5
+ * Allows both UI components and agent tools to control the panel.
6
+ */
7
+ import type { LazyExoticComponent, ComponentType } from "react";
8
+ export interface PdfHighlightRef {
9
+ pageNumber: number;
10
+ polygon: number[];
11
+ }
12
+ export interface ToolPanelContent {
13
+ title: string;
14
+ content: string;
15
+ type: "markdown" | "text" | "page" | "pdf";
16
+ /** PDF highlights for citation overlays (only when type === "pdf") */
17
+ pdfHighlights?: PdfHighlightRef[];
18
+ /** Initial page to scroll to (only when type === "pdf") */
19
+ initialPage?: number;
20
+ /** SPACES entity ID — enables pin and navigate actions in panel header */
21
+ entityId?: string;
22
+ }
23
+ /** Pluggable content renderer for the tool panel — registered by feature modules. */
24
+ export interface PanelRendererEntry {
25
+ /** Check if this renderer handles the given content */
26
+ match: (content: ToolPanelContent) => boolean;
27
+ /** Lazy component to render. Receives content as prop. */
28
+ component: LazyExoticComponent<ComponentType<{
29
+ content: ToolPanelContent;
30
+ }>>;
31
+ }
32
+ interface ToolPanelState {
33
+ isOpen: boolean;
34
+ content: ToolPanelContent | null;
35
+ panelWidth: number;
36
+ useOverlay: boolean;
37
+ isFullscreen: boolean;
38
+ renderers: PanelRendererEntry[];
39
+ openPanel: (content: ToolPanelContent) => void;
40
+ closePanel: () => void;
41
+ setContent: (content: ToolPanelContent) => void;
42
+ updateLayout: () => void;
43
+ toggleFullscreen: () => void;
44
+ /** Register a custom content renderer (e.g., PDF viewer, entity pages). */
45
+ registerRenderer: (entry: PanelRendererEntry) => void;
46
+ }
47
+ export declare const useToolPanelStore: import("zustand").UseBoundStore<import("zustand").StoreApi<ToolPanelState>>;
48
+ export {};
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Tool Panel State Management
3
+ *
4
+ * Zustand store for managing the tool panel (flyout side panel).
5
+ * Allows both UI components and agent tools to control the panel.
6
+ */
7
+ import { create } from "zustand";
8
+ const SIDE_BY_SIDE_BREAKPOINT = 1280;
9
+ const getPanelWidth = () => {
10
+ if (typeof window === "undefined")
11
+ return 800;
12
+ const screenWidth = window.innerWidth;
13
+ if (screenWidth < SIDE_BY_SIDE_BREAKPOINT)
14
+ return screenWidth;
15
+ return Math.min(1000, Math.max(600, screenWidth * 0.5));
16
+ };
17
+ const shouldUseOverlay = () => {
18
+ if (typeof window === "undefined")
19
+ return true;
20
+ return window.innerWidth < SIDE_BY_SIDE_BREAKPOINT;
21
+ };
22
+ export const useToolPanelStore = create((set, get) => ({
23
+ isOpen: false,
24
+ content: null,
25
+ panelWidth: getPanelWidth(),
26
+ useOverlay: shouldUseOverlay(),
27
+ isFullscreen: false,
28
+ renderers: [],
29
+ openPanel: (content) => set({ isOpen: true, content }),
30
+ registerRenderer: (entry) => set((state) => ({ renderers: [...state.renderers, entry] })),
31
+ closePanel: () => set({ isOpen: false, isFullscreen: false }),
32
+ setContent: (content) => set({ content }),
33
+ updateLayout: () => {
34
+ const { isFullscreen } = get();
35
+ if (!isFullscreen) {
36
+ set({
37
+ panelWidth: getPanelWidth(),
38
+ useOverlay: shouldUseOverlay(),
39
+ });
40
+ }
41
+ },
42
+ toggleFullscreen: () => {
43
+ const { isFullscreen } = get();
44
+ if (isFullscreen) {
45
+ set({
46
+ isFullscreen: false,
47
+ panelWidth: getPanelWidth(),
48
+ useOverlay: shouldUseOverlay(),
49
+ });
50
+ }
51
+ else {
52
+ set({
53
+ isFullscreen: true,
54
+ panelWidth: typeof window !== "undefined" ? window.innerWidth : 1200,
55
+ useOverlay: true,
56
+ });
57
+ }
58
+ },
59
+ }));
60
+ // Debounced resize listener
61
+ if (typeof window !== "undefined") {
62
+ let timeout;
63
+ window.addEventListener("resize", () => {
64
+ clearTimeout(timeout);
65
+ timeout = setTimeout(() => {
66
+ useToolPanelStore.getState().updateLayout();
67
+ }, 100);
68
+ });
69
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Shared hook for starting a new conversation.
3
+ * Used by ChatHeader and Sidebar to keep behavior in sync.
4
+ */
5
+ export declare function useNewConversation(options?: {
6
+ navigateToChat?: boolean;
7
+ preserveNavigation?: boolean;
8
+ }): () => void;