@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.
- package/README.md +14 -5
- package/dist/components/ag-ui-runtime-provider.d.ts +64 -0
- package/dist/components/ag-ui-runtime-provider.js +71 -0
- package/dist/components/app-brand.d.ts +6 -0
- package/dist/components/app-brand.js +13 -0
- package/dist/components/assistant-chat.d.ts +26 -0
- package/dist/components/assistant-chat.js +93 -0
- package/dist/components/chat-attachments.d.ts +25 -0
- package/dist/components/chat-attachments.js +20 -0
- package/dist/components/chat-bubble.d.ts +1 -0
- package/dist/components/chat-bubble.js +103 -0
- package/dist/components/chat-header.d.ts +2 -0
- package/dist/components/chat-header.js +16 -0
- package/dist/components/client-tool-executor.d.ts +12 -0
- package/dist/components/client-tool-executor.js +108 -0
- package/dist/components/collection-empty-state.d.ts +9 -0
- package/dist/components/collection-empty-state.js +6 -0
- package/dist/components/collection-filter-bar.d.ts +19 -0
- package/dist/components/collection-filter-bar.js +28 -0
- package/dist/components/collection-search-input.d.ts +6 -0
- package/dist/components/collection-search-input.js +8 -0
- package/dist/components/collection-skeleton.d.ts +6 -0
- package/dist/components/collection-skeleton.js +10 -0
- package/dist/components/collection-sort-menu.d.ts +10 -0
- package/dist/components/collection-sort-menu.js +9 -0
- package/dist/components/collection-surface.d.ts +8 -0
- package/dist/components/collection-surface.js +5 -0
- package/dist/components/collection-toolbar.d.ts +9 -0
- package/dist/components/collection-toolbar.js +5 -0
- package/dist/components/collection-view-toggle.d.ts +7 -0
- package/dist/components/collection-view-toggle.js +17 -0
- package/dist/components/composer-submit-bridge.d.ts +1 -0
- package/dist/components/composer-submit-bridge.js +15 -0
- package/dist/components/confirm-dialog.d.ts +11 -0
- package/dist/components/confirm-dialog.js +6 -0
- package/dist/components/confirmation-card.d.ts +14 -0
- package/dist/components/confirmation-card.js +12 -0
- package/dist/components/context-badges.d.ts +16 -0
- package/dist/components/context-badges.js +56 -0
- package/dist/components/context-bar.d.ts +41 -0
- package/dist/components/context-bar.js +123 -0
- package/dist/components/form-dialog.d.ts +12 -0
- package/dist/components/form-dialog.js +13 -0
- package/dist/components/global-selection-popover.d.ts +7 -0
- package/dist/components/global-selection-popover.js +167 -0
- package/dist/components/infinite-scroll-sentinel.d.ts +6 -0
- package/dist/components/infinite-scroll-sentinel.js +25 -0
- package/dist/components/json-viewer.d.ts +10 -0
- package/dist/components/json-viewer.js +80 -0
- package/dist/components/loading-indicator.d.ts +4 -0
- package/dist/components/loading-indicator.js +22 -0
- package/dist/components/markdown-text.d.ts +13 -0
- package/dist/components/markdown-text.js +221 -0
- package/dist/components/name-dialog.d.ts +16 -0
- package/dist/components/name-dialog.js +23 -0
- package/dist/components/selection-popover.d.ts +12 -0
- package/dist/components/selection-popover.js +111 -0
- package/dist/components/show-document-tool-ui.d.ts +1 -0
- package/dist/components/show-document-tool-ui.js +53 -0
- package/dist/components/sidebar.d.ts +4 -0
- package/dist/components/sidebar.js +904 -0
- package/dist/components/surface-card.d.ts +9 -0
- package/dist/components/surface-card.js +33 -0
- package/dist/components/theme-runtime-provider.d.ts +15 -0
- package/dist/components/theme-runtime-provider.js +48 -0
- package/dist/components/theme-toggle.d.ts +2 -0
- package/dist/components/theme-toggle.js +19 -0
- package/dist/components/tool-call-card.d.ts +27 -0
- package/dist/components/tool-call-card.js +13 -0
- package/dist/components/tool-fallback.d.ts +26 -0
- package/dist/components/tool-fallback.js +129 -0
- package/dist/components/tool-panel-layout.d.ts +10 -0
- package/dist/components/tool-panel-layout.js +12 -0
- package/dist/components/tool-panel.d.ts +1 -0
- package/dist/components/tool-panel.js +89 -0
- package/dist/components/tooltip-icon-button.d.ts +7 -0
- package/dist/components/tooltip-icon-button.js +9 -0
- package/dist/components/user-menu.d.ts +2 -0
- package/dist/components/user-menu.js +14 -0
- package/dist/index.d.ts +68 -0
- package/dist/index.js +83 -0
- package/dist/lib/ag-ui-adapter.d.ts +29 -0
- package/dist/lib/ag-ui-adapter.js +373 -0
- package/dist/lib/app-store.d.ts +115 -0
- package/dist/lib/app-store.js +199 -0
- package/dist/lib/attachment-adapter.d.ts +20 -0
- package/dist/lib/attachment-adapter.js +99 -0
- package/dist/lib/auth-provider.d.ts +16 -0
- package/dist/lib/auth-provider.js +88 -0
- package/dist/lib/chat-bubble-store.d.ts +30 -0
- package/dist/lib/chat-bubble-store.js +23 -0
- package/dist/lib/chat-lifecycle-store.d.ts +10 -0
- package/{src/lib/chat-lifecycle-store.ts → dist/lib/chat-lifecycle-store.js} +3 -13
- package/dist/lib/client-tools.d.ts +11 -0
- package/dist/lib/client-tools.js +274 -0
- package/dist/lib/composer-submit-store.d.ts +12 -0
- package/dist/lib/composer-submit-store.js +17 -0
- package/dist/lib/dev-store.d.ts +38 -0
- package/dist/lib/dev-store.js +32 -0
- package/dist/lib/nav-config.d.ts +159 -0
- package/dist/lib/nav-config.js +162 -0
- package/dist/lib/nav-dnd.d.ts +8 -0
- package/dist/lib/nav-dnd.js +9 -0
- package/dist/lib/nav-store.d.ts +45 -0
- package/dist/lib/nav-store.js +49 -0
- package/dist/lib/selection-context.d.ts +21 -0
- package/dist/lib/selection-context.js +34 -0
- package/dist/lib/sidebar-store.d.ts +23 -0
- package/dist/lib/sidebar-store.js +98 -0
- package/dist/lib/theme-runtime.d.ts +130 -0
- package/dist/lib/theme-runtime.js +479 -0
- package/dist/lib/theme-store.d.ts +15 -0
- package/dist/lib/theme-store.js +53 -0
- package/dist/lib/tool-panel-store.d.ts +48 -0
- package/dist/lib/tool-panel-store.js +69 -0
- package/dist/lib/use-new-conversation.d.ts +8 -0
- package/dist/lib/use-new-conversation.js +62 -0
- package/dist/lib/use-page-tools.d.ts +27 -0
- package/{src/lib/use-page-tools.ts → dist/lib/use-page-tools.js} +11 -13
- package/dist/styles.css +142 -0
- package/dist/ui/collapsible.d.ts +5 -0
- package/{src/ui/collapsible.tsx → dist/ui/collapsible.js} +0 -2
- package/dist/ui/dialog.d.ts +15 -0
- package/dist/ui/dialog.js +25 -0
- package/dist/ui/dropdown-menu.d.ts +7 -0
- package/dist/ui/dropdown-menu.js +19 -0
- package/dist/ui/popover.d.ts +7 -0
- package/dist/ui/popover.js +10 -0
- package/dist/ui/select.d.ts +4 -0
- package/dist/ui/select.js +9 -0
- package/dist/ui/tooltip.d.ts +7 -0
- package/dist/ui/tooltip.js +10 -0
- package/package.json +31 -12
- package/AGENTS.md +0 -59
- package/CHANGELOG.md +0 -203
- package/CLAUDE.md +0 -1
- package/src/__tests__/no-spaces-imports.test.ts +0 -59
- package/src/__tests__/open-core-guards.test.ts +0 -307
- package/src/__tests__/theme-runtime.test.ts +0 -81
- package/src/__tests__/tool-fallback.test.tsx +0 -109
- package/src/components/__tests__/context-bar.test.ts +0 -112
- package/src/components/ag-ui-runtime-provider.tsx +0 -170
- package/src/components/app-brand.tsx +0 -38
- package/src/components/assistant-chat.tsx +0 -461
- package/src/components/chat-attachments.tsx +0 -68
- package/src/components/chat-bubble.tsx +0 -373
- package/src/components/chat-header.tsx +0 -44
- package/src/components/client-tool-executor.tsx +0 -230
- package/src/components/collection-empty-state.tsx +0 -37
- package/src/components/collection-filter-bar.tsx +0 -168
- package/src/components/collection-search-input.tsx +0 -41
- package/src/components/collection-skeleton.tsx +0 -55
- package/src/components/collection-sort-menu.tsx +0 -62
- package/src/components/collection-surface.tsx +0 -46
- package/src/components/collection-toolbar.tsx +0 -33
- package/src/components/collection-view-toggle.tsx +0 -61
- package/src/components/composer-submit-bridge.tsx +0 -19
- package/src/components/confirm-dialog.tsx +0 -49
- package/src/components/confirmation-card.tsx +0 -32
- package/src/components/context-badges.tsx +0 -136
- package/src/components/context-bar.tsx +0 -238
- package/src/components/form-dialog.tsx +0 -56
- package/src/components/global-selection-popover.tsx +0 -266
- package/src/components/infinite-scroll-sentinel.tsx +0 -48
- package/src/components/json-viewer.tsx +0 -232
- package/src/components/loading-indicator.tsx +0 -40
- package/src/components/markdown-text-citations.test.tsx +0 -108
- package/src/components/markdown-text.tsx +0 -508
- package/src/components/name-dialog.tsx +0 -87
- package/src/components/selection-popover.tsx +0 -156
- package/src/components/show-document-tool-ui.tsx +0 -90
- package/src/components/sidebar.test.tsx +0 -611
- package/src/components/sidebar.tsx +0 -1689
- package/src/components/surface-card.tsx +0 -45
- package/src/components/theme-runtime-provider.tsx +0 -93
- package/src/components/theme-toggle.tsx +0 -27
- package/src/components/tool-call-card.tsx +0 -126
- package/src/components/tool-fallback.tsx +0 -169
- package/src/components/tool-panel-layout.tsx +0 -36
- package/src/components/tool-panel.tsx +0 -233
- package/src/components/tooltip-icon-button.tsx +0 -28
- package/src/components/user-menu.tsx +0 -60
- package/src/index.ts +0 -185
- package/src/lib/__tests__/ag-ui-adapter.test.ts +0 -273
- package/src/lib/__tests__/app-store.test.ts +0 -405
- package/src/lib/__tests__/attachment-adapter.test.ts +0 -48
- package/src/lib/__tests__/chat-bubble-store.test.ts +0 -67
- package/src/lib/__tests__/client-tools.test.ts +0 -124
- package/src/lib/__tests__/dev-store.test.ts +0 -78
- package/src/lib/__tests__/nav-config.test.ts +0 -135
- package/src/lib/__tests__/nav-dnd.test.ts +0 -24
- package/src/lib/__tests__/nav-store.test.ts +0 -59
- package/src/lib/__tests__/selection-context.test.ts +0 -114
- package/src/lib/__tests__/sidebar-store.test.ts +0 -144
- package/src/lib/__tests__/theme-store.test.ts +0 -83
- package/src/lib/__tests__/tool-panel-store.test.ts +0 -61
- package/src/lib/__tests__/use-page-context.test.ts +0 -58
- package/src/lib/ag-ui-adapter.ts +0 -412
- package/src/lib/app-store.ts +0 -361
- package/src/lib/attachment-adapter.ts +0 -92
- package/src/lib/auth-provider.tsx +0 -144
- package/src/lib/chat-bubble-store.ts +0 -46
- package/src/lib/client-tools.ts +0 -293
- package/src/lib/composer-submit-store.ts +0 -32
- package/src/lib/dev-store.ts +0 -69
- package/src/lib/nav-config.ts +0 -329
- package/src/lib/nav-dnd.ts +0 -14
- package/src/lib/nav-store.ts +0 -89
- package/src/lib/selection-context.ts +0 -65
- package/src/lib/sidebar-store.ts +0 -113
- package/src/lib/theme-runtime.ts +0 -660
- package/src/lib/theme-store.ts +0 -67
- package/src/lib/tool-panel-store.ts +0 -121
- package/src/lib/use-new-conversation.test.tsx +0 -168
- package/src/lib/use-new-conversation.ts +0 -64
- package/src/ui/dialog.tsx +0 -109
- package/src/ui/dropdown-menu.tsx +0 -75
- package/src/ui/popover.tsx +0 -34
- package/src/ui/select.tsx +0 -15
- package/src/ui/tooltip.tsx +0 -30
- package/src/vite-env.d.ts +0 -1
- package/tsconfig.json +0 -16
- package/vitest.config.ts +0 -8
package/src/lib/theme-store.ts
DELETED
|
@@ -1,67 +0,0 @@
|
|
|
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
|
-
|
|
8
|
-
import { create } from "zustand";
|
|
9
|
-
|
|
10
|
-
export type ThemeMode = "light" | "dark" | "system";
|
|
11
|
-
|
|
12
|
-
interface ThemeState {
|
|
13
|
-
mode: ThemeMode;
|
|
14
|
-
setMode: (mode: ThemeMode) => void;
|
|
15
|
-
/** Cycle through light -> dark -> system. */
|
|
16
|
-
cycle: () => void;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const STORAGE_KEY = "theme";
|
|
20
|
-
const CYCLE_ORDER: ThemeMode[] = ["light", "dark", "system"];
|
|
21
|
-
|
|
22
|
-
function getStoredMode(): ThemeMode {
|
|
23
|
-
if (typeof window === "undefined") return "system";
|
|
24
|
-
const stored = localStorage.getItem(STORAGE_KEY);
|
|
25
|
-
if (stored === "light" || stored === "dark" || stored === "system") return stored;
|
|
26
|
-
return "system";
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
function prefersDark(): boolean {
|
|
30
|
-
if (typeof window === "undefined") return false;
|
|
31
|
-
return window.matchMedia("(prefers-color-scheme: dark)").matches;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
function applyTheme(mode: ThemeMode) {
|
|
35
|
-
if (typeof document === "undefined") return;
|
|
36
|
-
const isDark = mode === "dark" || (mode === "system" && prefersDark());
|
|
37
|
-
document.documentElement.classList.toggle("dark", isDark);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export const useThemeStore = create<ThemeState>((set, get) => {
|
|
41
|
-
const initial = getStoredMode();
|
|
42
|
-
applyTheme(initial);
|
|
43
|
-
|
|
44
|
-
// Listen for OS preference changes when in system mode
|
|
45
|
-
if (typeof window !== "undefined") {
|
|
46
|
-
window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", () => {
|
|
47
|
-
if (get().mode === "system") applyTheme("system");
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
return {
|
|
52
|
-
mode: initial,
|
|
53
|
-
|
|
54
|
-
setMode: (mode) => {
|
|
55
|
-
localStorage.setItem(STORAGE_KEY, mode);
|
|
56
|
-
applyTheme(mode);
|
|
57
|
-
set({ mode });
|
|
58
|
-
},
|
|
59
|
-
|
|
60
|
-
cycle: () => {
|
|
61
|
-
const current = get().mode;
|
|
62
|
-
const idx = CYCLE_ORDER.indexOf(current);
|
|
63
|
-
const next = CYCLE_ORDER[(idx + 1) % CYCLE_ORDER.length];
|
|
64
|
-
get().setMode(next);
|
|
65
|
-
},
|
|
66
|
-
};
|
|
67
|
-
});
|
|
@@ -1,121 +0,0 @@
|
|
|
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
|
-
|
|
8
|
-
import { create } from "zustand";
|
|
9
|
-
import type { LazyExoticComponent, ComponentType } from "react";
|
|
10
|
-
|
|
11
|
-
export interface PdfHighlightRef {
|
|
12
|
-
pageNumber: number;
|
|
13
|
-
polygon: number[];
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export interface ToolPanelContent {
|
|
17
|
-
title: string;
|
|
18
|
-
content: string;
|
|
19
|
-
type: "markdown" | "text" | "page" | "pdf";
|
|
20
|
-
/** PDF highlights for citation overlays (only when type === "pdf") */
|
|
21
|
-
pdfHighlights?: PdfHighlightRef[];
|
|
22
|
-
/** Initial page to scroll to (only when type === "pdf") */
|
|
23
|
-
initialPage?: number;
|
|
24
|
-
/** SPACES entity ID — enables pin and navigate actions in panel header */
|
|
25
|
-
entityId?: string;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/** Pluggable content renderer for the tool panel — registered by feature modules. */
|
|
29
|
-
export interface PanelRendererEntry {
|
|
30
|
-
/** Check if this renderer handles the given content */
|
|
31
|
-
match: (content: ToolPanelContent) => boolean;
|
|
32
|
-
/** Lazy component to render. Receives content as prop. */
|
|
33
|
-
component: LazyExoticComponent<ComponentType<{ content: ToolPanelContent }>>;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const SIDE_BY_SIDE_BREAKPOINT = 1280;
|
|
37
|
-
|
|
38
|
-
const getPanelWidth = (): number => {
|
|
39
|
-
if (typeof window === "undefined") return 800;
|
|
40
|
-
const screenWidth = window.innerWidth;
|
|
41
|
-
if (screenWidth < SIDE_BY_SIDE_BREAKPOINT) return screenWidth;
|
|
42
|
-
return Math.min(1000, Math.max(600, screenWidth * 0.5));
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
const shouldUseOverlay = (): boolean => {
|
|
46
|
-
if (typeof window === "undefined") return true;
|
|
47
|
-
return window.innerWidth < SIDE_BY_SIDE_BREAKPOINT;
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
interface ToolPanelState {
|
|
51
|
-
isOpen: boolean;
|
|
52
|
-
content: ToolPanelContent | null;
|
|
53
|
-
|
|
54
|
-
// Layout state
|
|
55
|
-
panelWidth: number;
|
|
56
|
-
useOverlay: boolean;
|
|
57
|
-
isFullscreen: boolean;
|
|
58
|
-
|
|
59
|
-
// Pluggable content renderers (registered by feature modules)
|
|
60
|
-
renderers: PanelRendererEntry[];
|
|
61
|
-
|
|
62
|
-
// Actions
|
|
63
|
-
openPanel: (content: ToolPanelContent) => void;
|
|
64
|
-
closePanel: () => void;
|
|
65
|
-
setContent: (content: ToolPanelContent) => void;
|
|
66
|
-
updateLayout: () => void;
|
|
67
|
-
toggleFullscreen: () => void;
|
|
68
|
-
/** Register a custom content renderer (e.g., PDF viewer, entity pages). */
|
|
69
|
-
registerRenderer: (entry: PanelRendererEntry) => void;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
export const useToolPanelStore = create<ToolPanelState>((set, get) => ({
|
|
73
|
-
isOpen: false,
|
|
74
|
-
content: null,
|
|
75
|
-
panelWidth: getPanelWidth(),
|
|
76
|
-
useOverlay: shouldUseOverlay(),
|
|
77
|
-
isFullscreen: false,
|
|
78
|
-
renderers: [],
|
|
79
|
-
|
|
80
|
-
openPanel: (content) => set({ isOpen: true, content }),
|
|
81
|
-
registerRenderer: (entry) =>
|
|
82
|
-
set((state) => ({ renderers: [...state.renderers, entry] })),
|
|
83
|
-
closePanel: () => set({ isOpen: false, isFullscreen: false }),
|
|
84
|
-
setContent: (content) => set({ content }),
|
|
85
|
-
updateLayout: () => {
|
|
86
|
-
const { isFullscreen } = get();
|
|
87
|
-
if (!isFullscreen) {
|
|
88
|
-
set({
|
|
89
|
-
panelWidth: getPanelWidth(),
|
|
90
|
-
useOverlay: shouldUseOverlay(),
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
|
-
},
|
|
94
|
-
toggleFullscreen: () => {
|
|
95
|
-
const { isFullscreen } = get();
|
|
96
|
-
if (isFullscreen) {
|
|
97
|
-
set({
|
|
98
|
-
isFullscreen: false,
|
|
99
|
-
panelWidth: getPanelWidth(),
|
|
100
|
-
useOverlay: shouldUseOverlay(),
|
|
101
|
-
});
|
|
102
|
-
} else {
|
|
103
|
-
set({
|
|
104
|
-
isFullscreen: true,
|
|
105
|
-
panelWidth: typeof window !== "undefined" ? window.innerWidth : 1200,
|
|
106
|
-
useOverlay: true,
|
|
107
|
-
});
|
|
108
|
-
}
|
|
109
|
-
},
|
|
110
|
-
}));
|
|
111
|
-
|
|
112
|
-
// Debounced resize listener
|
|
113
|
-
if (typeof window !== "undefined") {
|
|
114
|
-
let timeout: ReturnType<typeof setTimeout>;
|
|
115
|
-
window.addEventListener("resize", () => {
|
|
116
|
-
clearTimeout(timeout);
|
|
117
|
-
timeout = setTimeout(() => {
|
|
118
|
-
useToolPanelStore.getState().updateLayout();
|
|
119
|
-
}, 100);
|
|
120
|
-
});
|
|
121
|
-
}
|
|
@@ -1,168 +0,0 @@
|
|
|
1
|
-
import { act } from "react";
|
|
2
|
-
import { createRoot, type Root } from "react-dom/client";
|
|
3
|
-
import { MemoryRouter, useLocation } from "react-router";
|
|
4
|
-
import { beforeEach, describe, expect, it, vi, afterEach } from "vitest";
|
|
5
|
-
import { useAppStore } from "./app-store.ts";
|
|
6
|
-
import { citationStore } from "@iloveagents/foundry-agent";
|
|
7
|
-
import { useSidebarStore } from "./sidebar-store.ts";
|
|
8
|
-
import { useToolPanelStore } from "./tool-panel-store.ts";
|
|
9
|
-
import { useNewConversation } from "./use-new-conversation.ts";
|
|
10
|
-
|
|
11
|
-
const switchToNewThread = vi.fn();
|
|
12
|
-
const resetThread = vi.fn();
|
|
13
|
-
|
|
14
|
-
vi.mock("@assistant-ui/react", () => ({
|
|
15
|
-
useAui: () => ({
|
|
16
|
-
threads: () => ({
|
|
17
|
-
switchToNewThread,
|
|
18
|
-
}),
|
|
19
|
-
}),
|
|
20
|
-
}));
|
|
21
|
-
|
|
22
|
-
vi.mock("../components/ag-ui-runtime-provider.tsx", () => ({
|
|
23
|
-
useAGUIAdapter: () => ({
|
|
24
|
-
resetThread,
|
|
25
|
-
}),
|
|
26
|
-
}));
|
|
27
|
-
|
|
28
|
-
function LocationProbe() {
|
|
29
|
-
const location = useLocation();
|
|
30
|
-
return <div data-testid="location">{location.pathname}</div>;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
function Trigger() {
|
|
34
|
-
const handleNewConversation = useNewConversation();
|
|
35
|
-
return (
|
|
36
|
-
<button type="button" onClick={handleNewConversation}>
|
|
37
|
-
New Thread
|
|
38
|
-
</button>
|
|
39
|
-
);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
function PreserveNavigationTrigger() {
|
|
43
|
-
const handleNewConversation = useNewConversation({
|
|
44
|
-
navigateToChat: false,
|
|
45
|
-
preserveNavigation: true,
|
|
46
|
-
});
|
|
47
|
-
return (
|
|
48
|
-
<button type="button" onClick={handleNewConversation}>
|
|
49
|
-
New Bubble Thread
|
|
50
|
-
</button>
|
|
51
|
-
);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
describe("useNewConversation", () => {
|
|
55
|
-
let container: HTMLDivElement;
|
|
56
|
-
let root: Root;
|
|
57
|
-
let originalActEnvironment: boolean | undefined;
|
|
58
|
-
|
|
59
|
-
beforeEach(() => {
|
|
60
|
-
originalActEnvironment = globalThis.IS_REACT_ACT_ENVIRONMENT;
|
|
61
|
-
globalThis.IS_REACT_ACT_ENVIRONMENT = true;
|
|
62
|
-
switchToNewThread.mockReset();
|
|
63
|
-
resetThread.mockReset();
|
|
64
|
-
useToolPanelStore.setState({ isOpen: true });
|
|
65
|
-
useSidebarStore.setState({ isMobileOpen: true });
|
|
66
|
-
citationStore.setState({
|
|
67
|
-
results: [
|
|
68
|
-
{
|
|
69
|
-
chunk_id: "chunk-1",
|
|
70
|
-
entity_id: "file-1",
|
|
71
|
-
entity_name: "Test File",
|
|
72
|
-
content: "Excerpt",
|
|
73
|
-
page_number: 1,
|
|
74
|
-
bounding_regions: "[]",
|
|
75
|
-
score: 1,
|
|
76
|
-
},
|
|
77
|
-
],
|
|
78
|
-
handler: { openCitation: vi.fn() },
|
|
79
|
-
});
|
|
80
|
-
useAppStore.setState({
|
|
81
|
-
threadActive: true,
|
|
82
|
-
currentPage: "/spaces/demo",
|
|
83
|
-
navContext: {
|
|
84
|
-
group: "Workspaces",
|
|
85
|
-
groupDescription: null,
|
|
86
|
-
groupMeta: {},
|
|
87
|
-
label: "Demo",
|
|
88
|
-
description: null,
|
|
89
|
-
meta: {},
|
|
90
|
-
contextInstructions: null,
|
|
91
|
-
},
|
|
92
|
-
selectedItemId: "entity-1",
|
|
93
|
-
content: { title: "Draft" },
|
|
94
|
-
highlights: [{ entityId: "entity-1", blockId: "block-1" }],
|
|
95
|
-
contextItems: [],
|
|
96
|
-
sentContext: {},
|
|
97
|
-
});
|
|
98
|
-
container = document.createElement("div");
|
|
99
|
-
document.body.appendChild(container);
|
|
100
|
-
root = createRoot(container);
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
afterEach(() => {
|
|
104
|
-
act(() => {
|
|
105
|
-
root.unmount();
|
|
106
|
-
});
|
|
107
|
-
container.remove();
|
|
108
|
-
globalThis.IS_REACT_ACT_ENVIRONMENT = originalActEnvironment;
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
it("navigates to chat and resets thread state", async () => {
|
|
112
|
-
await act(async () => {
|
|
113
|
-
root.render(
|
|
114
|
-
<MemoryRouter initialEntries={["/spaces/demo"]}>
|
|
115
|
-
<Trigger />
|
|
116
|
-
<LocationProbe />
|
|
117
|
-
</MemoryRouter>,
|
|
118
|
-
);
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
const button = container.querySelector("button");
|
|
122
|
-
expect(button).toBeTruthy();
|
|
123
|
-
|
|
124
|
-
await act(async () => {
|
|
125
|
-
button?.dispatchEvent(new MouseEvent("click", { bubbles: true }));
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
expect(container.querySelector('[data-testid="location"]')?.textContent).toBe("/");
|
|
129
|
-
expect(switchToNewThread).toHaveBeenCalledTimes(1);
|
|
130
|
-
expect(resetThread).toHaveBeenCalledTimes(1);
|
|
131
|
-
expect(useToolPanelStore.getState().isOpen).toBe(false);
|
|
132
|
-
expect(useSidebarStore.getState().isMobileOpen).toBe(false);
|
|
133
|
-
expect(citationStore.getState().results).toEqual([]);
|
|
134
|
-
// Handler is module-level state registered once at app boot by
|
|
135
|
-
// feature modules (e.g. SPACES' ``registerSpacesCitationHandler``)
|
|
136
|
-
// and MUST survive per-conversation resets — wiping it here would
|
|
137
|
-
// make every ``[n]`` marker inert for the rest of the session,
|
|
138
|
-
// since the registration guard suppresses re-binding. See
|
|
139
|
-
// ``packages/agent/src/store/citation-store.ts``.
|
|
140
|
-
expect(citationStore.getState().handler).not.toBeNull();
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
it("can reset the thread without leaving the current page", async () => {
|
|
144
|
-
await act(async () => {
|
|
145
|
-
root.render(
|
|
146
|
-
<MemoryRouter initialEntries={["/spaces/demo"]}>
|
|
147
|
-
<PreserveNavigationTrigger />
|
|
148
|
-
<LocationProbe />
|
|
149
|
-
</MemoryRouter>,
|
|
150
|
-
);
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
const button = container.querySelector("button");
|
|
154
|
-
expect(button).toBeTruthy();
|
|
155
|
-
|
|
156
|
-
await act(async () => {
|
|
157
|
-
button?.dispatchEvent(new MouseEvent("click", { bubbles: true }));
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
expect(container.querySelector('[data-testid="location"]')?.textContent).toBe("/spaces/demo");
|
|
161
|
-
expect(switchToNewThread).toHaveBeenCalledTimes(1);
|
|
162
|
-
expect(resetThread).toHaveBeenCalledTimes(1);
|
|
163
|
-
expect(useAppStore.getState().currentPage).toBe("/spaces/demo");
|
|
164
|
-
expect(useAppStore.getState().navContext.label).toBe("Demo");
|
|
165
|
-
expect(useAppStore.getState().threadActive).toBe(false);
|
|
166
|
-
expect(useAppStore.getState().contextItems).toEqual([]);
|
|
167
|
-
});
|
|
168
|
-
});
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import { useCallback } from "react";
|
|
2
|
-
import { useNavigate } from "react-router";
|
|
3
|
-
import { useAui } from "@assistant-ui/react";
|
|
4
|
-
import { useStore } from "zustand";
|
|
5
|
-
import { citationStore } from "@iloveagents/foundry-agent";
|
|
6
|
-
import { useAGUIAdapter } from "../components/ag-ui-runtime-provider.tsx";
|
|
7
|
-
import { useToolPanelStore } from "./tool-panel-store.ts";
|
|
8
|
-
import { useAppStore } from "./app-store.ts";
|
|
9
|
-
import { useSidebarStore } from "./sidebar-store.ts";
|
|
10
|
-
import { useChatLifecycleStore } from "./chat-lifecycle-store.ts";
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Shared hook for starting a new conversation.
|
|
14
|
-
* Used by ChatHeader and Sidebar to keep behavior in sync.
|
|
15
|
-
*/
|
|
16
|
-
export function useNewConversation(options?: { navigateToChat?: boolean; preserveNavigation?: boolean }) {
|
|
17
|
-
const aui = useAui();
|
|
18
|
-
const { resetThread } = useAGUIAdapter();
|
|
19
|
-
const navigate = useNavigate();
|
|
20
|
-
const closePanel = useToolPanelStore((s) => s.closePanel);
|
|
21
|
-
const resetApp = useAppStore((s) => s.resetAll);
|
|
22
|
-
const closeMobile = useSidebarStore((s) => s.closeMobile);
|
|
23
|
-
const clearCitations = useStore(citationStore, (s) => s.clear);
|
|
24
|
-
|
|
25
|
-
return useCallback(() => {
|
|
26
|
-
const preserved = options?.preserveNavigation
|
|
27
|
-
? {
|
|
28
|
-
currentPage: useAppStore.getState().currentPage,
|
|
29
|
-
navContext: useAppStore.getState().navContext,
|
|
30
|
-
}
|
|
31
|
-
: null;
|
|
32
|
-
closePanel();
|
|
33
|
-
resetApp();
|
|
34
|
-
if (preserved) {
|
|
35
|
-
useAppStore.setState(preserved);
|
|
36
|
-
}
|
|
37
|
-
closeMobile();
|
|
38
|
-
clearCitations();
|
|
39
|
-
// Notify the host app that a new thread is starting. Spaces wires
|
|
40
|
-
// this to clear its active-chat sticky id so the AGUIRuntimeProvider's
|
|
41
|
-
// ``effectiveThreadId`` advances to a freshly-minted UUID instead of
|
|
42
|
-
// staying pinned to the previous chat. Must fire BEFORE ``resetThread``
|
|
43
|
-
// so the next render's history adapter binds to the new id and
|
|
44
|
-
// doesn't re-hydrate the prior chat's messages — the exact bug this
|
|
45
|
-
// wiring fixes for the popover (``navigateToChat: false``) path,
|
|
46
|
-
// where there is no ``/`` navigation to clear sticky for us.
|
|
47
|
-
useChatLifecycleStore.getState().onNewConversation?.();
|
|
48
|
-
resetThread();
|
|
49
|
-
aui.threads().switchToNewThread();
|
|
50
|
-
if (options?.navigateToChat ?? true) {
|
|
51
|
-
navigate("/");
|
|
52
|
-
}
|
|
53
|
-
}, [
|
|
54
|
-
closePanel,
|
|
55
|
-
resetApp,
|
|
56
|
-
options?.preserveNavigation,
|
|
57
|
-
closeMobile,
|
|
58
|
-
clearCitations,
|
|
59
|
-
resetThread,
|
|
60
|
-
aui,
|
|
61
|
-
options?.navigateToChat,
|
|
62
|
-
navigate,
|
|
63
|
-
]);
|
|
64
|
-
}
|
package/src/ui/dialog.tsx
DELETED
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
import * as DialogPrimitive from "@radix-ui/react-dialog";
|
|
3
|
-
import { X } from "lucide-react";
|
|
4
|
-
|
|
5
|
-
import { cn } from "@iloveagents/foundry-web-primitives";
|
|
6
|
-
import { ThemeScope } from "../components/theme-runtime-provider.tsx";
|
|
7
|
-
|
|
8
|
-
const Dialog = DialogPrimitive.Root;
|
|
9
|
-
const DialogTrigger = DialogPrimitive.Trigger;
|
|
10
|
-
const DialogPortal = DialogPrimitive.Portal;
|
|
11
|
-
const DialogClose = DialogPrimitive.Close;
|
|
12
|
-
|
|
13
|
-
const DialogOverlay = React.forwardRef<
|
|
14
|
-
React.ElementRef<typeof DialogPrimitive.Overlay>,
|
|
15
|
-
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>
|
|
16
|
-
>(({ className, ...props }, ref) => (
|
|
17
|
-
<DialogPrimitive.Overlay
|
|
18
|
-
ref={ref}
|
|
19
|
-
className={cn(
|
|
20
|
-
"fixed inset-0 z-50 bg-black/55 backdrop-blur-sm",
|
|
21
|
-
"data-[state=open]:animate-in data-[state=closed]:animate-out",
|
|
22
|
-
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
23
|
-
className,
|
|
24
|
-
)}
|
|
25
|
-
{...props}
|
|
26
|
-
/>
|
|
27
|
-
));
|
|
28
|
-
DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
|
|
29
|
-
|
|
30
|
-
const DialogContent = React.forwardRef<
|
|
31
|
-
React.ElementRef<typeof DialogPrimitive.Content>,
|
|
32
|
-
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content> & {
|
|
33
|
-
showCloseButton?: boolean;
|
|
34
|
-
}
|
|
35
|
-
>(({ className, children, showCloseButton = true, ...props }, ref) => (
|
|
36
|
-
<DialogPortal>
|
|
37
|
-
<DialogOverlay />
|
|
38
|
-
<DialogPrimitive.Content
|
|
39
|
-
ref={ref}
|
|
40
|
-
className={cn(
|
|
41
|
-
"fixed left-1/2 top-1/2 z-50 grid w-[calc(100%-2rem)] max-w-lg -translate-x-1/2 -translate-y-1/2 gap-4",
|
|
42
|
-
"rounded-[2rem] border border-border bg-background/95 p-6 shadow-2xl duration-200",
|
|
43
|
-
"data-[state=open]:animate-in data-[state=closed]:animate-out",
|
|
44
|
-
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
45
|
-
"data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
|
|
46
|
-
className,
|
|
47
|
-
)}
|
|
48
|
-
{...props}
|
|
49
|
-
>
|
|
50
|
-
{/* ThemeScope ensures portaled dialogs inherit the active theme */}
|
|
51
|
-
<ThemeScope style={{ display: "contents" }}>
|
|
52
|
-
{children}
|
|
53
|
-
</ThemeScope>
|
|
54
|
-
{showCloseButton ? (
|
|
55
|
-
<DialogPrimitive.Close
|
|
56
|
-
className={cn(
|
|
57
|
-
"absolute right-5 top-5 rounded-md p-1 transition-colors hover:bg-muted",
|
|
58
|
-
"focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
59
|
-
)}
|
|
60
|
-
aria-label="Close"
|
|
61
|
-
>
|
|
62
|
-
<X className="size-4 text-muted-foreground" />
|
|
63
|
-
</DialogPrimitive.Close>
|
|
64
|
-
) : null}
|
|
65
|
-
</DialogPrimitive.Content>
|
|
66
|
-
</DialogPortal>
|
|
67
|
-
));
|
|
68
|
-
DialogContent.displayName = DialogPrimitive.Content.displayName;
|
|
69
|
-
|
|
70
|
-
function DialogHeader({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {
|
|
71
|
-
return <div className={cn("flex flex-col gap-1.5 pr-10", className)} {...props} />;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
function DialogFooter({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {
|
|
75
|
-
return <div className={cn("flex justify-end gap-2", className)} {...props} />;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
const DialogTitle = React.forwardRef<
|
|
79
|
-
React.ElementRef<typeof DialogPrimitive.Title>,
|
|
80
|
-
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>
|
|
81
|
-
>(({ className, ...props }, ref) => (
|
|
82
|
-
<DialogPrimitive.Title ref={ref} className={cn("text-lg font-semibold", className)} {...props} />
|
|
83
|
-
));
|
|
84
|
-
DialogTitle.displayName = DialogPrimitive.Title.displayName;
|
|
85
|
-
|
|
86
|
-
const DialogDescription = React.forwardRef<
|
|
87
|
-
React.ElementRef<typeof DialogPrimitive.Description>,
|
|
88
|
-
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description>
|
|
89
|
-
>(({ className, ...props }, ref) => (
|
|
90
|
-
<DialogPrimitive.Description
|
|
91
|
-
ref={ref}
|
|
92
|
-
className={cn("text-sm text-muted-foreground", className)}
|
|
93
|
-
{...props}
|
|
94
|
-
/>
|
|
95
|
-
));
|
|
96
|
-
DialogDescription.displayName = DialogPrimitive.Description.displayName;
|
|
97
|
-
|
|
98
|
-
export {
|
|
99
|
-
Dialog,
|
|
100
|
-
DialogPortal,
|
|
101
|
-
DialogOverlay,
|
|
102
|
-
DialogTrigger,
|
|
103
|
-
DialogClose,
|
|
104
|
-
DialogContent,
|
|
105
|
-
DialogHeader,
|
|
106
|
-
DialogFooter,
|
|
107
|
-
DialogTitle,
|
|
108
|
-
DialogDescription,
|
|
109
|
-
};
|
package/src/ui/dropdown-menu.tsx
DELETED
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
|
|
2
|
-
import { type ComponentPropsWithRef, forwardRef } from "react";
|
|
3
|
-
import { cn } from "@iloveagents/foundry-web-primitives";
|
|
4
|
-
|
|
5
|
-
export const DropdownMenu = DropdownMenuPrimitive.Root;
|
|
6
|
-
export const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;
|
|
7
|
-
|
|
8
|
-
export const DropdownMenuContent = forwardRef<
|
|
9
|
-
HTMLDivElement,
|
|
10
|
-
ComponentPropsWithRef<typeof DropdownMenuPrimitive.Content>
|
|
11
|
-
>(({ className, sideOffset = 4, ...props }, ref) => (
|
|
12
|
-
<DropdownMenuPrimitive.Portal>
|
|
13
|
-
<DropdownMenuPrimitive.Content
|
|
14
|
-
ref={ref}
|
|
15
|
-
sideOffset={sideOffset}
|
|
16
|
-
className={cn(
|
|
17
|
-
"z-50 min-w-[8rem] overflow-hidden rounded-md border border-border",
|
|
18
|
-
"bg-popover p-1 text-popover-foreground shadow-md",
|
|
19
|
-
"data-[state=open]:animate-in data-[state=closed]:animate-out",
|
|
20
|
-
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
21
|
-
"data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
|
|
22
|
-
"data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2",
|
|
23
|
-
"data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
|
24
|
-
className,
|
|
25
|
-
)}
|
|
26
|
-
{...props}
|
|
27
|
-
/>
|
|
28
|
-
</DropdownMenuPrimitive.Portal>
|
|
29
|
-
));
|
|
30
|
-
DropdownMenuContent.displayName = "DropdownMenuContent";
|
|
31
|
-
|
|
32
|
-
export const DropdownMenuItem = forwardRef<
|
|
33
|
-
HTMLDivElement,
|
|
34
|
-
ComponentPropsWithRef<typeof DropdownMenuPrimitive.Item>
|
|
35
|
-
>(({ className, ...props }, ref) => (
|
|
36
|
-
<DropdownMenuPrimitive.Item
|
|
37
|
-
ref={ref}
|
|
38
|
-
className={cn(
|
|
39
|
-
// ``gap-2`` is the same icon-to-text spacing the framework's
|
|
40
|
-
// Button primitive uses, so a ``<lucide-icon /> Label`` pattern
|
|
41
|
-
// inside any menu item renders consistently everywhere without
|
|
42
|
-
// the consumer needing to remember the override.
|
|
43
|
-
"relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none",
|
|
44
|
-
"transition-colors focus:bg-accent focus:text-accent-foreground",
|
|
45
|
-
"data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
|
46
|
-
className,
|
|
47
|
-
)}
|
|
48
|
-
{...props}
|
|
49
|
-
/>
|
|
50
|
-
));
|
|
51
|
-
DropdownMenuItem.displayName = "DropdownMenuItem";
|
|
52
|
-
|
|
53
|
-
export const DropdownMenuSeparator = forwardRef<
|
|
54
|
-
HTMLDivElement,
|
|
55
|
-
ComponentPropsWithRef<typeof DropdownMenuPrimitive.Separator>
|
|
56
|
-
>(({ className, ...props }, ref) => (
|
|
57
|
-
<DropdownMenuPrimitive.Separator
|
|
58
|
-
ref={ref}
|
|
59
|
-
className={cn("-mx-1 my-1 h-px bg-border", className)}
|
|
60
|
-
{...props}
|
|
61
|
-
/>
|
|
62
|
-
));
|
|
63
|
-
DropdownMenuSeparator.displayName = "DropdownMenuSeparator";
|
|
64
|
-
|
|
65
|
-
export const DropdownMenuLabel = forwardRef<
|
|
66
|
-
HTMLDivElement,
|
|
67
|
-
ComponentPropsWithRef<typeof DropdownMenuPrimitive.Label>
|
|
68
|
-
>(({ className, ...props }, ref) => (
|
|
69
|
-
<DropdownMenuPrimitive.Label
|
|
70
|
-
ref={ref}
|
|
71
|
-
className={cn("px-2 py-1.5 text-sm font-semibold", className)}
|
|
72
|
-
{...props}
|
|
73
|
-
/>
|
|
74
|
-
));
|
|
75
|
-
DropdownMenuLabel.displayName = "DropdownMenuLabel";
|
package/src/ui/popover.tsx
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
import * as PopoverPrimitive from "@radix-ui/react-popover";
|
|
3
|
-
|
|
4
|
-
import { cn } from "@iloveagents/foundry-web-primitives";
|
|
5
|
-
|
|
6
|
-
const Popover = PopoverPrimitive.Root;
|
|
7
|
-
const PopoverTrigger = PopoverPrimitive.Trigger;
|
|
8
|
-
const PopoverAnchor = PopoverPrimitive.Anchor;
|
|
9
|
-
|
|
10
|
-
const PopoverContent = React.forwardRef<
|
|
11
|
-
React.ElementRef<typeof PopoverPrimitive.Content>,
|
|
12
|
-
React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>
|
|
13
|
-
>(({ className, align = "center", sideOffset = 8, ...props }, ref) => (
|
|
14
|
-
<PopoverPrimitive.Portal>
|
|
15
|
-
<PopoverPrimitive.Content
|
|
16
|
-
ref={ref}
|
|
17
|
-
align={align}
|
|
18
|
-
sideOffset={sideOffset}
|
|
19
|
-
className={cn(
|
|
20
|
-
"z-50 rounded-2xl border border-border bg-popover p-3 text-popover-foreground shadow-xl outline-none",
|
|
21
|
-
"data-[state=open]:animate-in data-[state=closed]:animate-out",
|
|
22
|
-
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
23
|
-
"data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
|
|
24
|
-
"data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2",
|
|
25
|
-
"data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
|
26
|
-
className,
|
|
27
|
-
)}
|
|
28
|
-
{...props}
|
|
29
|
-
/>
|
|
30
|
-
</PopoverPrimitive.Portal>
|
|
31
|
-
));
|
|
32
|
-
PopoverContent.displayName = PopoverPrimitive.Content.displayName;
|
|
33
|
-
|
|
34
|
-
export { Popover, PopoverTrigger, PopoverAnchor, PopoverContent };
|
package/src/ui/select.tsx
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
|
|
3
|
-
import { cn } from "@iloveagents/foundry-web-primitives";
|
|
4
|
-
|
|
5
|
-
const selectClassName =
|
|
6
|
-
"flex h-10 w-full rounded-xl border border-border bg-background px-3 py-2 text-sm outline-none transition focus:border-primary focus:ring-2 focus:ring-primary/15 disabled:cursor-not-allowed disabled:opacity-50";
|
|
7
|
-
|
|
8
|
-
const Select = React.forwardRef<HTMLSelectElement, React.ComponentProps<"select">>(
|
|
9
|
-
({ className, ...props }, ref) => {
|
|
10
|
-
return <select ref={ref} className={cn(selectClassName, className)} {...props} />;
|
|
11
|
-
},
|
|
12
|
-
);
|
|
13
|
-
Select.displayName = "Select";
|
|
14
|
-
|
|
15
|
-
export { Select, selectClassName };
|
package/src/ui/tooltip.tsx
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
|
|
3
|
-
|
|
4
|
-
import { cn } from "@iloveagents/foundry-web-primitives";
|
|
5
|
-
|
|
6
|
-
const TooltipProvider = TooltipPrimitive.Provider;
|
|
7
|
-
|
|
8
|
-
const Tooltip = TooltipPrimitive.Root;
|
|
9
|
-
|
|
10
|
-
const TooltipTrigger = TooltipPrimitive.Trigger;
|
|
11
|
-
|
|
12
|
-
const TooltipContent = React.forwardRef<
|
|
13
|
-
React.ElementRef<typeof TooltipPrimitive.Content>,
|
|
14
|
-
React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>
|
|
15
|
-
>(({ className, sideOffset = 4, ...props }, ref) => (
|
|
16
|
-
<TooltipPrimitive.Portal>
|
|
17
|
-
<TooltipPrimitive.Content
|
|
18
|
-
ref={ref}
|
|
19
|
-
sideOffset={sideOffset}
|
|
20
|
-
className={cn(
|
|
21
|
-
"z-50 overflow-hidden rounded-md bg-primary px-3 py-1.5 text-xs text-primary-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
|
22
|
-
className,
|
|
23
|
-
)}
|
|
24
|
-
{...props}
|
|
25
|
-
/>
|
|
26
|
-
</TooltipPrimitive.Portal>
|
|
27
|
-
));
|
|
28
|
-
TooltipContent.displayName = TooltipPrimitive.Content.displayName;
|
|
29
|
-
|
|
30
|
-
export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider };
|
package/src/vite-env.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
/// <reference types="vite/client" />
|