@iloveagents/foundry-web-ui 0.3.1 → 0.5.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 (227) hide show
  1. package/README.md +13 -4
  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 +94 -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 +105 -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 +13 -0
  51. package/dist/components/loading-indicator.js +35 -0
  52. package/dist/components/markdown-text.d.ts +13 -0
  53. package/dist/components/markdown-text.js +221 -0
  54. package/dist/components/message-error.d.ts +10 -0
  55. package/dist/components/message-error.js +10 -0
  56. package/dist/components/message-timestamp.d.ts +10 -0
  57. package/dist/components/message-timestamp.js +18 -0
  58. package/dist/components/name-dialog.d.ts +16 -0
  59. package/dist/components/name-dialog.js +23 -0
  60. package/dist/components/selection-popover.d.ts +12 -0
  61. package/dist/components/selection-popover.js +111 -0
  62. package/dist/components/show-document-tool-ui.d.ts +1 -0
  63. package/dist/components/show-document-tool-ui.js +53 -0
  64. package/dist/components/sidebar.d.ts +4 -0
  65. package/dist/components/sidebar.js +904 -0
  66. package/dist/components/surface-card.d.ts +9 -0
  67. package/dist/components/surface-card.js +33 -0
  68. package/dist/components/theme-runtime-provider.d.ts +15 -0
  69. package/dist/components/theme-runtime-provider.js +48 -0
  70. package/dist/components/theme-toggle.d.ts +2 -0
  71. package/dist/components/theme-toggle.js +19 -0
  72. package/dist/components/tool-call-card.d.ts +27 -0
  73. package/dist/components/tool-call-card.js +13 -0
  74. package/dist/components/tool-fallback.d.ts +26 -0
  75. package/dist/components/tool-fallback.js +129 -0
  76. package/dist/components/tool-panel-layout.d.ts +10 -0
  77. package/dist/components/tool-panel-layout.js +12 -0
  78. package/dist/components/tool-panel.d.ts +1 -0
  79. package/dist/components/tool-panel.js +89 -0
  80. package/dist/components/tooltip-icon-button.d.ts +7 -0
  81. package/dist/components/tooltip-icon-button.js +9 -0
  82. package/dist/components/user-menu.d.ts +2 -0
  83. package/dist/components/user-menu.js +14 -0
  84. package/dist/index.d.ts +68 -0
  85. package/dist/index.js +83 -0
  86. package/dist/lib/ag-ui-adapter.d.ts +29 -0
  87. package/dist/lib/ag-ui-adapter.js +382 -0
  88. package/dist/lib/app-store.d.ts +115 -0
  89. package/dist/lib/app-store.js +199 -0
  90. package/dist/lib/attachment-adapter.d.ts +20 -0
  91. package/dist/lib/attachment-adapter.js +99 -0
  92. package/dist/lib/auth-provider.d.ts +16 -0
  93. package/dist/lib/auth-provider.js +88 -0
  94. package/dist/lib/chat-bubble-store.d.ts +30 -0
  95. package/dist/lib/chat-bubble-store.js +23 -0
  96. package/dist/lib/chat-lifecycle-store.d.ts +10 -0
  97. package/{src/lib/chat-lifecycle-store.ts → dist/lib/chat-lifecycle-store.js} +3 -13
  98. package/dist/lib/client-tools.d.ts +11 -0
  99. package/dist/lib/client-tools.js +274 -0
  100. package/dist/lib/composer-submit-store.d.ts +12 -0
  101. package/dist/lib/composer-submit-store.js +17 -0
  102. package/dist/lib/dev-store.d.ts +38 -0
  103. package/dist/lib/dev-store.js +32 -0
  104. package/dist/lib/nav-config.d.ts +159 -0
  105. package/dist/lib/nav-config.js +162 -0
  106. package/dist/lib/nav-dnd.d.ts +8 -0
  107. package/dist/lib/nav-dnd.js +9 -0
  108. package/dist/lib/nav-store.d.ts +45 -0
  109. package/dist/lib/nav-store.js +49 -0
  110. package/dist/lib/selection-context.d.ts +21 -0
  111. package/dist/lib/selection-context.js +34 -0
  112. package/dist/lib/sidebar-store.d.ts +23 -0
  113. package/dist/lib/sidebar-store.js +98 -0
  114. package/dist/lib/theme-runtime.d.ts +130 -0
  115. package/dist/lib/theme-runtime.js +479 -0
  116. package/dist/lib/theme-store.d.ts +15 -0
  117. package/dist/lib/theme-store.js +53 -0
  118. package/dist/lib/tool-panel-store.d.ts +48 -0
  119. package/dist/lib/tool-panel-store.js +69 -0
  120. package/dist/lib/use-new-conversation.d.ts +8 -0
  121. package/dist/lib/use-new-conversation.js +62 -0
  122. package/dist/lib/use-page-tools.d.ts +27 -0
  123. package/{src/lib/use-page-tools.ts → dist/lib/use-page-tools.js} +11 -13
  124. package/dist/styles.css +142 -0
  125. package/dist/ui/collapsible.d.ts +5 -0
  126. package/{src/ui/collapsible.tsx → dist/ui/collapsible.js} +0 -2
  127. package/dist/ui/dialog.d.ts +15 -0
  128. package/dist/ui/dialog.js +25 -0
  129. package/dist/ui/dropdown-menu.d.ts +7 -0
  130. package/dist/ui/dropdown-menu.js +19 -0
  131. package/dist/ui/popover.d.ts +7 -0
  132. package/dist/ui/popover.js +10 -0
  133. package/dist/ui/select.d.ts +4 -0
  134. package/dist/ui/select.js +9 -0
  135. package/dist/ui/tooltip.d.ts +7 -0
  136. package/dist/ui/tooltip.js +10 -0
  137. package/package.json +31 -12
  138. package/AGENTS.md +0 -59
  139. package/CHANGELOG.md +0 -211
  140. package/CLAUDE.md +0 -1
  141. package/src/__tests__/no-spaces-imports.test.ts +0 -59
  142. package/src/__tests__/open-core-guards.test.ts +0 -307
  143. package/src/__tests__/theme-runtime.test.ts +0 -81
  144. package/src/__tests__/tool-fallback.test.tsx +0 -109
  145. package/src/components/__tests__/context-bar.test.ts +0 -112
  146. package/src/components/ag-ui-runtime-provider.tsx +0 -170
  147. package/src/components/app-brand.tsx +0 -38
  148. package/src/components/assistant-chat.tsx +0 -461
  149. package/src/components/chat-attachments.tsx +0 -68
  150. package/src/components/chat-bubble.tsx +0 -373
  151. package/src/components/chat-header.tsx +0 -44
  152. package/src/components/client-tool-executor.tsx +0 -230
  153. package/src/components/collection-empty-state.tsx +0 -37
  154. package/src/components/collection-filter-bar.tsx +0 -168
  155. package/src/components/collection-search-input.tsx +0 -41
  156. package/src/components/collection-skeleton.tsx +0 -55
  157. package/src/components/collection-sort-menu.tsx +0 -62
  158. package/src/components/collection-surface.tsx +0 -46
  159. package/src/components/collection-toolbar.tsx +0 -33
  160. package/src/components/collection-view-toggle.tsx +0 -61
  161. package/src/components/composer-submit-bridge.tsx +0 -19
  162. package/src/components/confirm-dialog.tsx +0 -49
  163. package/src/components/confirmation-card.tsx +0 -32
  164. package/src/components/context-badges.tsx +0 -136
  165. package/src/components/context-bar.tsx +0 -238
  166. package/src/components/form-dialog.tsx +0 -56
  167. package/src/components/global-selection-popover.tsx +0 -266
  168. package/src/components/infinite-scroll-sentinel.tsx +0 -48
  169. package/src/components/json-viewer.tsx +0 -232
  170. package/src/components/loading-indicator.tsx +0 -40
  171. package/src/components/markdown-text-citations.test.tsx +0 -108
  172. package/src/components/markdown-text.tsx +0 -508
  173. package/src/components/name-dialog.tsx +0 -87
  174. package/src/components/selection-popover.tsx +0 -156
  175. package/src/components/show-document-tool-ui.tsx +0 -90
  176. package/src/components/sidebar.test.tsx +0 -611
  177. package/src/components/sidebar.tsx +0 -1689
  178. package/src/components/surface-card.tsx +0 -45
  179. package/src/components/theme-runtime-provider.tsx +0 -93
  180. package/src/components/theme-toggle.tsx +0 -27
  181. package/src/components/tool-call-card.tsx +0 -126
  182. package/src/components/tool-fallback.tsx +0 -169
  183. package/src/components/tool-panel-layout.tsx +0 -36
  184. package/src/components/tool-panel.tsx +0 -233
  185. package/src/components/tooltip-icon-button.tsx +0 -28
  186. package/src/components/user-menu.tsx +0 -60
  187. package/src/index.ts +0 -185
  188. package/src/lib/__tests__/ag-ui-adapter.test.ts +0 -279
  189. package/src/lib/__tests__/app-store.test.ts +0 -405
  190. package/src/lib/__tests__/attachment-adapter.test.ts +0 -48
  191. package/src/lib/__tests__/chat-bubble-store.test.ts +0 -67
  192. package/src/lib/__tests__/client-tools.test.ts +0 -124
  193. package/src/lib/__tests__/dev-store.test.ts +0 -78
  194. package/src/lib/__tests__/nav-config.test.ts +0 -135
  195. package/src/lib/__tests__/nav-dnd.test.ts +0 -24
  196. package/src/lib/__tests__/nav-store.test.ts +0 -59
  197. package/src/lib/__tests__/selection-context.test.ts +0 -114
  198. package/src/lib/__tests__/sidebar-store.test.ts +0 -144
  199. package/src/lib/__tests__/theme-store.test.ts +0 -83
  200. package/src/lib/__tests__/tool-panel-store.test.ts +0 -61
  201. package/src/lib/__tests__/use-page-context.test.ts +0 -58
  202. package/src/lib/ag-ui-adapter.ts +0 -426
  203. package/src/lib/app-store.ts +0 -361
  204. package/src/lib/attachment-adapter.ts +0 -92
  205. package/src/lib/auth-provider.tsx +0 -144
  206. package/src/lib/chat-bubble-store.ts +0 -46
  207. package/src/lib/client-tools.ts +0 -293
  208. package/src/lib/composer-submit-store.ts +0 -32
  209. package/src/lib/dev-store.ts +0 -69
  210. package/src/lib/nav-config.ts +0 -329
  211. package/src/lib/nav-dnd.ts +0 -14
  212. package/src/lib/nav-store.ts +0 -89
  213. package/src/lib/selection-context.ts +0 -65
  214. package/src/lib/sidebar-store.ts +0 -113
  215. package/src/lib/theme-runtime.ts +0 -660
  216. package/src/lib/theme-store.ts +0 -67
  217. package/src/lib/tool-panel-store.ts +0 -121
  218. package/src/lib/use-new-conversation.test.tsx +0 -168
  219. package/src/lib/use-new-conversation.ts +0 -64
  220. package/src/ui/dialog.tsx +0 -109
  221. package/src/ui/dropdown-menu.tsx +0 -75
  222. package/src/ui/popover.tsx +0 -34
  223. package/src/ui/select.tsx +0 -15
  224. package/src/ui/tooltip.tsx +0 -30
  225. package/src/vite-env.d.ts +0 -1
  226. package/tsconfig.json +0 -16
  227. package/vitest.config.ts +0 -8
@@ -1,168 +0,0 @@
1
- import { Check, Filter, X } from "lucide-react";
2
-
3
- import { Button } from "@iloveagents/foundry-web-primitives";
4
- import { Checkbox } from "@iloveagents/foundry-web-primitives";
5
- import { Popover, PopoverContent, PopoverTrigger } from "../ui/popover.tsx";
6
- import { cn } from "@iloveagents/foundry-web-primitives";
7
-
8
- export type CollectionFilterValue = string | string[] | boolean | undefined;
9
-
10
- export interface CollectionFilterOption {
11
- value: string;
12
- label: string;
13
- }
14
-
15
- export interface CollectionFilterDefinition {
16
- key: string;
17
- label: string;
18
- type: "single" | "multi" | "boolean";
19
- options?: CollectionFilterOption[];
20
- trueLabel?: string;
21
- }
22
-
23
- function activeCount(value: CollectionFilterValue, type: CollectionFilterDefinition["type"]) {
24
- if (type === "boolean") return value ? 1 : 0;
25
- if (Array.isArray(value)) return value.length;
26
- return value ? 1 : 0;
27
- }
28
-
29
- export function CollectionFilterBar({
30
- filters,
31
- values,
32
- onValueChange,
33
- onClearAll,
34
- className,
35
- }: {
36
- filters: CollectionFilterDefinition[];
37
- values: Record<string, CollectionFilterValue>;
38
- onValueChange: (key: string, value: CollectionFilterValue) => void;
39
- onClearAll?: () => void;
40
- className?: string;
41
- }) {
42
- const hasActiveFilters = filters.some((filter) => activeCount(values[filter.key], filter.type) > 0);
43
-
44
- return (
45
- <div className={cn("flex flex-wrap items-center gap-2", className)}>
46
- {filters.map((filter) => {
47
- const count = activeCount(values[filter.key], filter.type);
48
- return (
49
- <Popover key={filter.key}>
50
- <PopoverTrigger asChild>
51
- <Button
52
- type="button"
53
- variant="outline"
54
- size="sm"
55
- className={cn(
56
- "rounded-xl border-border/45 bg-background/65 shadow-none hover:bg-muted/26",
57
- count > 0 && "border-primary/18 bg-primary/7 text-foreground hover:bg-primary/10",
58
- )}
59
- >
60
- <Filter className="size-4" />
61
- <span>{filter.label}</span>
62
- {count > 0 ? (
63
- <span className="rounded-full bg-primary/10 px-1.5 py-0.5 text-[11px] font-semibold text-primary">
64
- {count}
65
- </span>
66
- ) : null}
67
- </Button>
68
- </PopoverTrigger>
69
- <PopoverContent align="start" className="w-64 rounded-2xl border-border/45 bg-popover/95 p-2 shadow-lg">
70
- <div className="px-2 pb-2 pt-1 text-xs font-semibold uppercase tracking-[0.14em] text-muted-foreground">
71
- {filter.label}
72
- </div>
73
- {filter.type === "boolean" ? (
74
- <button
75
- type="button"
76
- onClick={() => onValueChange(filter.key, values[filter.key] ? undefined : true)}
77
- className={cn(
78
- "flex w-full items-center gap-3 rounded-xl px-3 py-2 text-left text-sm transition-colors",
79
- values[filter.key] ? "bg-primary/8 text-foreground" : "hover:bg-accent",
80
- )}
81
- >
82
- <Checkbox checked={Boolean(values[filter.key])} />
83
- <span>{filter.trueLabel ?? `Only ${filter.label.toLowerCase()}`}</span>
84
- </button>
85
- ) : null}
86
- {filter.type === "single" ? (
87
- <div className="space-y-1">
88
- <button
89
- type="button"
90
- onClick={() => onValueChange(filter.key, undefined)}
91
- className="flex w-full items-center justify-between rounded-xl px-3 py-2 text-left text-sm transition-colors hover:bg-accent"
92
- >
93
- <span>Any</span>
94
- <Check
95
- className={cn(
96
- "size-4 text-primary",
97
- values[filter.key] == null ? "opacity-100" : "opacity-0",
98
- )}
99
- />
100
- </button>
101
- {filter.options?.map((option) => (
102
- <button
103
- key={option.value}
104
- type="button"
105
- onClick={() => onValueChange(filter.key, option.value)}
106
- className="flex w-full items-center justify-between rounded-xl px-3 py-2 text-left text-sm transition-colors hover:bg-accent"
107
- >
108
- <span>{option.label}</span>
109
- <Check
110
- className={cn(
111
- "size-4 text-primary",
112
- values[filter.key] === option.value ? "opacity-100" : "opacity-0",
113
- )}
114
- />
115
- </button>
116
- ))}
117
- </div>
118
- ) : null}
119
- {filter.type === "multi" ? (
120
- <div className="space-y-1">
121
- {filter.options?.map((option) => {
122
- const current = Array.isArray(values[filter.key])
123
- ? (values[filter.key] as string[])
124
- : [];
125
- const checked = current.includes(option.value);
126
- return (
127
- <button
128
- key={option.value}
129
- type="button"
130
- onClick={() =>
131
- onValueChange(
132
- filter.key,
133
- checked
134
- ? current.filter((item: string) => item !== option.value)
135
- : [...current, option.value],
136
- )
137
- }
138
- className={cn(
139
- "flex w-full items-center gap-3 rounded-xl px-3 py-2 text-left text-sm transition-colors",
140
- checked ? "bg-primary/8 text-foreground" : "hover:bg-accent",
141
- )}
142
- >
143
- <Checkbox checked={checked} />
144
- <span>{option.label}</span>
145
- </button>
146
- );
147
- })}
148
- </div>
149
- ) : null}
150
- </PopoverContent>
151
- </Popover>
152
- );
153
- })}
154
- {hasActiveFilters && onClearAll ? (
155
- <Button
156
- type="button"
157
- variant="ghost"
158
- size="sm"
159
- onClick={onClearAll}
160
- className="rounded-xl text-muted-foreground hover:bg-muted/26"
161
- >
162
- <X className="size-4" />
163
- <span>Clear</span>
164
- </Button>
165
- ) : null}
166
- </div>
167
- );
168
- }
@@ -1,41 +0,0 @@
1
- import { Search, X } from "lucide-react";
2
-
3
- import { Button } from "@iloveagents/foundry-web-primitives";
4
- import { Input } from "@iloveagents/foundry-web-primitives";
5
- import { cn } from "@iloveagents/foundry-web-primitives";
6
-
7
- export function CollectionSearchInput({
8
- value,
9
- onValueChange,
10
- placeholder = "Search...",
11
- className,
12
- }: {
13
- value: string;
14
- onValueChange: (value: string) => void;
15
- placeholder?: string;
16
- className?: string;
17
- }) {
18
- return (
19
- <div className={cn("relative min-w-[16rem] flex-1", className)}>
20
- <Search className="pointer-events-none absolute left-3 top-1/2 size-4 -translate-y-1/2 text-muted-foreground" />
21
- <Input
22
- value={value}
23
- onChange={(event) => onValueChange(event.target.value)}
24
- placeholder={placeholder}
25
- className="h-10 rounded-xl border-border/45 bg-background/72 pl-9 pr-10 shadow-none hover:bg-background/82 focus:border-primary/20 focus:ring-primary/10"
26
- />
27
- {value ? (
28
- <Button
29
- type="button"
30
- variant="ghost"
31
- size="icon"
32
- onClick={() => onValueChange("")}
33
- className="absolute right-1 top-1/2 size-8 -translate-y-1/2 rounded-lg text-muted-foreground"
34
- >
35
- <X className="size-4" />
36
- <span className="sr-only">Clear search</span>
37
- </Button>
38
- ) : null}
39
- </div>
40
- );
41
- }
@@ -1,55 +0,0 @@
1
- import { cn } from "@iloveagents/foundry-web-primitives";
2
-
3
- import type { CollectionViewMode } from "./collection-view-toggle.tsx";
4
-
5
- export function CollectionSkeleton({
6
- view,
7
- rows = 8,
8
- className,
9
- }: {
10
- view: CollectionViewMode;
11
- rows?: number;
12
- className?: string;
13
- }) {
14
- if (view === "table") {
15
- return (
16
- <div className={cn("overflow-hidden rounded-[1.5rem] bg-background/65 ring-1 ring-border/35", className)}>
17
- <div className="grid grid-cols-4 gap-4 border-b border-border/40 bg-muted/28 px-5 py-4">
18
- {Array.from({ length: 4 }).map((_, index) => (
19
- <div key={index} className="h-3.5 animate-pulse rounded bg-muted" />
20
- ))}
21
- </div>
22
- <div className="divide-y divide-border/35">
23
- {Array.from({ length: rows }).map((_, index) => (
24
- <div key={index} className="grid grid-cols-4 gap-4 px-5 py-4">
25
- {Array.from({ length: 4 }).map((_, cellIndex) => (
26
- <div key={cellIndex} className="h-4 animate-pulse rounded bg-muted/80" />
27
- ))}
28
- </div>
29
- ))}
30
- </div>
31
- </div>
32
- );
33
- }
34
-
35
- return (
36
- <div
37
- className={cn(
38
- view === "tiles"
39
- ? "grid gap-3 [grid-template-columns:repeat(auto-fit,minmax(min(100%,16rem),1fr))]"
40
- : "grid gap-4 [grid-template-columns:repeat(auto-fit,minmax(min(100%,18rem),1fr))]",
41
- className,
42
- )}
43
- >
44
- {Array.from({ length: rows }).map((_, index) => (
45
- <div
46
- key={index}
47
- className={cn(
48
- "animate-pulse rounded-[1.5rem] bg-card/80 ring-1 ring-border/35",
49
- view === "tiles" ? "h-28" : "h-40",
50
- )}
51
- />
52
- ))}
53
- </div>
54
- );
55
- }
@@ -1,62 +0,0 @@
1
- import { ArrowUpDown, Check } from "lucide-react";
2
-
3
- import {
4
- DropdownMenu,
5
- DropdownMenuContent,
6
- DropdownMenuItem,
7
- DropdownMenuTrigger,
8
- } from "../ui/dropdown-menu.tsx";
9
- import { Button } from "@iloveagents/foundry-web-primitives";
10
- import { cn } from "@iloveagents/foundry-web-primitives";
11
-
12
- export interface CollectionSortOption {
13
- value: string;
14
- label: string;
15
- }
16
-
17
- export function CollectionSortMenu({
18
- options,
19
- value,
20
- onValueChange,
21
- className,
22
- }: {
23
- options: CollectionSortOption[];
24
- value: string;
25
- onValueChange: (value: string) => void;
26
- className?: string;
27
- }) {
28
- const active = options.find((option) => option.value === value) ?? options[0];
29
-
30
- return (
31
- <DropdownMenu>
32
- <DropdownMenuTrigger asChild>
33
- <Button
34
- type="button"
35
- variant="outline"
36
- size="sm"
37
- className={cn(
38
- "rounded-xl border-border/45 bg-background/65 shadow-none hover:bg-muted/26",
39
- className,
40
- )}
41
- >
42
- <ArrowUpDown className="size-4" />
43
- <span>{active?.label ?? "Sort"}</span>
44
- </Button>
45
- </DropdownMenuTrigger>
46
- <DropdownMenuContent align="end" className="w-56 rounded-xl border-border/45 bg-popover/95 shadow-lg">
47
- {options.map((option) => (
48
- <DropdownMenuItem
49
- key={option.value}
50
- onClick={() => onValueChange(option.value)}
51
- className="flex items-center justify-between gap-3"
52
- >
53
- <span>{option.label}</span>
54
- <Check
55
- className={cn("size-4 text-primary", value === option.value ? "opacity-100" : "opacity-0")}
56
- />
57
- </DropdownMenuItem>
58
- ))}
59
- </DropdownMenuContent>
60
- </DropdownMenu>
61
- );
62
- }
@@ -1,46 +0,0 @@
1
- import type { ComponentPropsWithoutRef, ReactNode } from "react";
2
-
3
- import { cn } from "@iloveagents/foundry-web-primitives";
4
-
5
- export function CollectionSurface({
6
- toolbar,
7
- bordered = false,
8
- backgrounded = true,
9
- className,
10
- toolbarClassName,
11
- contentClassName,
12
- children,
13
- ...props
14
- }: ComponentPropsWithoutRef<"section"> & {
15
- toolbar?: ReactNode;
16
- bordered?: boolean;
17
- backgrounded?: boolean;
18
- toolbarClassName?: string;
19
- contentClassName?: string;
20
- }) {
21
- return (
22
- <section
23
- className={cn(
24
- "w-full min-w-0 overflow-hidden rounded-[1.75rem]",
25
- backgrounded && "bg-card/60 shadow-[0_12px_36px_-24px_rgb(15_23_42/0.18)] backdrop-blur-sm",
26
- bordered && "ring-1 ring-border/45",
27
- className,
28
- )}
29
- {...props}
30
- >
31
- {toolbar ? (
32
- <div
33
- className={cn(
34
- "sticky top-0 z-10 px-4 py-4 sm:px-5",
35
- backgrounded && "bg-muted/18 backdrop-blur",
36
- bordered && "border-b border-border/45",
37
- toolbarClassName,
38
- )}
39
- >
40
- {toolbar}
41
- </div>
42
- ) : null}
43
- <div className={cn("p-4 sm:p-5", contentClassName)}>{children}</div>
44
- </section>
45
- );
46
- }
@@ -1,33 +0,0 @@
1
- import type { ReactNode } from "react";
2
-
3
- import { cn } from "@iloveagents/foundry-web-primitives";
4
-
5
- export function CollectionToolbar({
6
- search,
7
- filters,
8
- sort,
9
- viewToggle,
10
- actions,
11
- className,
12
- }: {
13
- search?: ReactNode;
14
- filters?: ReactNode;
15
- sort?: ReactNode;
16
- viewToggle?: ReactNode;
17
- actions?: ReactNode;
18
- className?: string;
19
- }) {
20
- return (
21
- <div className={cn("flex flex-col gap-2.5", className)}>
22
- <div className="flex flex-col gap-2.5 lg:flex-row lg:items-center">
23
- <div className="flex min-w-0 flex-1 items-center gap-3">{search}</div>
24
- <div className="flex flex-wrap items-center gap-2">
25
- {sort}
26
- {viewToggle}
27
- {actions}
28
- </div>
29
- </div>
30
- {filters ? <div className="flex flex-wrap items-center gap-2">{filters}</div> : null}
31
- </div>
32
- );
33
- }
@@ -1,61 +0,0 @@
1
- import { LayoutGrid, Rows3, TableProperties } from "lucide-react";
2
-
3
- import { Button } from "@iloveagents/foundry-web-primitives";
4
- import { cn } from "@iloveagents/foundry-web-primitives";
5
-
6
- export type CollectionViewMode = "table" | "grid" | "tiles";
7
-
8
- const VIEW_OPTIONS: Array<{
9
- value: CollectionViewMode;
10
- label: string;
11
- icon: typeof TableProperties;
12
- }> = [
13
- { value: "table", label: "Table", icon: TableProperties },
14
- { value: "grid", label: "Grid", icon: LayoutGrid },
15
- { value: "tiles", label: "Tiles", icon: Rows3 },
16
- ];
17
-
18
- export function CollectionViewToggle({
19
- value,
20
- onValueChange,
21
- views = ["table", "grid"],
22
- className,
23
- }: {
24
- value: CollectionViewMode;
25
- onValueChange: (value: CollectionViewMode) => void;
26
- views?: CollectionViewMode[];
27
- className?: string;
28
- }) {
29
- return (
30
- <div
31
- className={cn(
32
- "inline-flex items-center rounded-xl bg-muted/26 p-1 ring-1 ring-border/40",
33
- className,
34
- )}
35
- >
36
- {VIEW_OPTIONS.filter((option) => views.includes(option.value)).map((option) => {
37
- const Icon = option.icon;
38
- const active = value === option.value;
39
- return (
40
- <Button
41
- key={option.value}
42
- type="button"
43
- aria-label={option.label}
44
- variant={active ? "secondary" : "ghost"}
45
- size="sm"
46
- onClick={() => onValueChange(option.value)}
47
- className={cn(
48
- "rounded-lg px-2.5 text-muted-foreground hover:bg-background/70 hover:text-foreground",
49
- active &&
50
- "bg-background text-foreground ring-1 ring-primary/35 shadow-[0_1px_2px_rgb(15_23_42/0.08)] hover:bg-background",
51
- )}
52
- >
53
- <Icon className="size-4" />
54
- <span className="hidden sm:inline">{option.label}</span>
55
- <span className="sr-only sm:hidden">{option.label}</span>
56
- </Button>
57
- );
58
- })}
59
- </div>
60
- );
61
- }
@@ -1,19 +0,0 @@
1
- import { useEffect } from "react";
2
- import { useComposerRuntime } from "@assistant-ui/react";
3
- import { useComposerSubmitStore } from "../lib/composer-submit-store.ts";
4
-
5
- export function ComposerSubmitBridge() {
6
- const composerRuntime = useComposerRuntime();
7
- const pending = useComposerSubmitStore((s) => s.pending);
8
-
9
- useEffect(() => {
10
- if (!pending) return;
11
-
12
- composerRuntime.setText(pending.text);
13
- composerRuntime.send({ startRun: true });
14
- useComposerSubmitStore.getState().consume(pending.id);
15
- }, [composerRuntime, pending]);
16
-
17
- return null;
18
- }
19
-
@@ -1,49 +0,0 @@
1
- import { Button } from "@iloveagents/foundry-web-primitives";
2
- import { FormDialog } from "./form-dialog.tsx";
3
-
4
- export function ConfirmDialog({
5
- open,
6
- onOpenChange,
7
- title,
8
- description,
9
- confirmLabel = "Confirm",
10
- cancelLabel = "Cancel",
11
- destructive = false,
12
- onConfirm,
13
- confirming = false,
14
- }: {
15
- open: boolean;
16
- onOpenChange: (open: boolean) => void;
17
- title: string;
18
- description?: string;
19
- confirmLabel?: string;
20
- cancelLabel?: string;
21
- destructive?: boolean;
22
- onConfirm: () => void;
23
- confirming?: boolean;
24
- }) {
25
- return (
26
- <FormDialog
27
- open={open}
28
- onOpenChange={onOpenChange}
29
- title={title}
30
- description={description}
31
- size="sm"
32
- footer={
33
- <>
34
- <Button type="button" variant="ghost" onClick={() => onOpenChange(false)}>
35
- {cancelLabel}
36
- </Button>
37
- <Button
38
- type="button"
39
- variant={destructive ? "destructive" : "default"}
40
- onClick={onConfirm}
41
- disabled={confirming}
42
- >
43
- {confirmLabel}
44
- </Button>
45
- </>
46
- }
47
- />
48
- );
49
- }
@@ -1,32 +0,0 @@
1
- /**
2
- * Confirmation Card — informational UI for the ui_confirm tool.
3
- *
4
- * Renders a card with action description and optional details.
5
- * The user responds by typing their confirmation in the chat.
6
- */
7
-
8
- import { ShieldCheck } from "lucide-react";
9
- import { ToolCallCard, type ToolCallStatus } from "./tool-call-card.tsx";
10
-
11
- interface ConfirmationCardProps {
12
- action: string;
13
- details?: string;
14
- status: ToolCallStatus;
15
- }
16
-
17
- export function ConfirmationCard({ action, details, status }: ConfirmationCardProps) {
18
- return (
19
- <ToolCallCard
20
- icon={<ShieldCheck className="size-3.5" />}
21
- title="Confirmation Required"
22
- description={action}
23
- status={status}
24
- className="w-full"
25
- >
26
- {details && <p className="text-xs text-muted-foreground mt-1">{details}</p>}
27
- <p className="text-xs text-muted-foreground mt-2 italic">
28
- Reply to confirm or reject this action.
29
- </p>
30
- </ToolCallCard>
31
- );
32
- }