team-connect 0.1.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 (51) hide show
  1. package/README.md +315 -0
  2. package/dist/components/AuthBar.d.ts +6 -0
  3. package/dist/components/AuthBar.d.ts.map +1 -0
  4. package/dist/components/AuthBar.js +16 -0
  5. package/dist/components/AuthBar.js.map +1 -0
  6. package/dist/components/Breadcrumbs.d.ts +8 -0
  7. package/dist/components/Breadcrumbs.d.ts.map +1 -0
  8. package/dist/components/Breadcrumbs.js +6 -0
  9. package/dist/components/Breadcrumbs.js.map +1 -0
  10. package/dist/components/FileBrowser.d.ts +7 -0
  11. package/dist/components/FileBrowser.d.ts.map +1 -0
  12. package/dist/components/FileBrowser.js +47 -0
  13. package/dist/components/FileBrowser.js.map +1 -0
  14. package/dist/components/FileList.d.ts +11 -0
  15. package/dist/components/FileList.d.ts.map +1 -0
  16. package/dist/components/FileList.js +25 -0
  17. package/dist/components/FileList.js.map +1 -0
  18. package/dist/components/SearchBar.d.ts +7 -0
  19. package/dist/components/SearchBar.d.ts.map +1 -0
  20. package/dist/components/SearchBar.js +29 -0
  21. package/dist/components/SearchBar.js.map +1 -0
  22. package/dist/components/UploadZone.d.ts +7 -0
  23. package/dist/components/UploadZone.d.ts.map +1 -0
  24. package/dist/components/UploadZone.js +19 -0
  25. package/dist/components/UploadZone.js.map +1 -0
  26. package/dist/hooks/useFiles.d.ts +16 -0
  27. package/dist/hooks/useFiles.d.ts.map +1 -0
  28. package/dist/hooks/useFiles.js +99 -0
  29. package/dist/hooks/useFiles.js.map +1 -0
  30. package/dist/index.d.ts +12 -0
  31. package/dist/index.d.ts.map +1 -0
  32. package/dist/index.js +16 -0
  33. package/dist/index.js.map +1 -0
  34. package/dist/lib/sp-client.d.ts +9 -0
  35. package/dist/lib/sp-client.d.ts.map +1 -0
  36. package/dist/lib/sp-client.js +140 -0
  37. package/dist/lib/sp-client.js.map +1 -0
  38. package/dist/lib/utils.d.ts +9 -0
  39. package/dist/lib/utils.d.ts.map +1 -0
  40. package/dist/lib/utils.js +71 -0
  41. package/dist/lib/utils.js.map +1 -0
  42. package/dist/types/index.d.ts +19 -0
  43. package/dist/types/index.d.ts.map +1 -0
  44. package/dist/types/index.js +2 -0
  45. package/dist/types/index.js.map +1 -0
  46. package/package.json +58 -0
  47. package/proxy/config/private.json +3 -0
  48. package/proxy/go.mod +34 -0
  49. package/proxy/go.sum +116 -0
  50. package/proxy/main.go +134 -0
  51. package/proxy/team-connect-proxy +0 -0
package/README.md ADDED
@@ -0,0 +1,315 @@
1
+ # team-connect
2
+
3
+ SharePoint file browser for React / Next.js — browse, upload, download and manage files through a local Go proxy.
4
+ **No Azure AD app registration required.** Auth is handled by [gosip](https://github.com/koltyakov/gosip)'s interactive browser login (FedAuth cookies).
5
+
6
+ ---
7
+
8
+ ## How it works
9
+
10
+ ```
11
+ ┌──────────────┐ ┌──────────────┐ ┌───────────────────┐
12
+ │ React app │──────▶│ Go proxy │──────▶│ SharePoint REST │
13
+ │ (port 3000) │ HTTP │ (port 8080) │ Auth │ API (/_api/web) │
14
+ └──────────────┘ └──────────────┘ └───────────────────┘
15
+ ```
16
+
17
+ 1. The **Go proxy** starts, opens Chrome, you log in with SSO — gosip captures the FedAuth cookie.
18
+ 2. All SharePoint REST calls from your React app go through `http://localhost:8080/sp/…`.
19
+ 3. The proxy injects auth headers and forwards requests to SharePoint.
20
+
21
+ ---
22
+
23
+ ## Quick start
24
+
25
+ ### 1. Install
26
+
27
+ ```bash
28
+ npm install team-connect
29
+ ```
30
+
31
+ ### 2. Set up the Go proxy
32
+
33
+ **Prerequisites:** Go 1.19+
34
+
35
+ ```bash
36
+ # Clone gosip-sandbox (provides the ondemand auth strategy)
37
+ git clone https://github.com/koltyakov/gosip-sandbox.git
38
+
39
+ # Copy the proxy from the package (or from the repo)
40
+ cp -r node_modules/team-connect/proxy ./team-connect-proxy
41
+ cd team-connect-proxy
42
+ ```
43
+
44
+ Edit `config/private.json` with your SharePoint site URL:
45
+
46
+ ```json
47
+ {
48
+ "siteUrl": "https://yourtenant.sharepoint.com/sites/YourSite"
49
+ }
50
+ ```
51
+
52
+ Update the `replace` directive in `go.mod` to point to your local gosip-sandbox path:
53
+
54
+ ```
55
+ replace github.com/koltyakov/gosip-sandbox => /path/to/gosip-sandbox
56
+ ```
57
+
58
+ Build and run:
59
+
60
+ ```bash
61
+ go build -o proxy .
62
+ ./proxy
63
+ ```
64
+
65
+ Chrome will open — log in with your org account. The proxy will confirm:
66
+
67
+ ```
68
+ Connected to: Your Site (https://yourtenant.sharepoint.com/sites/YourSite)
69
+ Proxy listening on http://localhost:8080
70
+ ```
71
+
72
+ ### 3. Add environment variables
73
+
74
+ In your Next.js `.env.local`:
75
+
76
+ ```env
77
+ NEXT_PUBLIC_PROXY_URL=http://localhost:8080
78
+ NEXT_PUBLIC_SHAREPOINT_DOCUMENT_LIBRARY=Shared Documents
79
+ NEXT_PUBLIC_SHAREPOINT_FOLDER_PATH=Your Folder Name
80
+ ```
81
+
82
+ ### 4. Use in your app
83
+
84
+ #### Option A: Drop-in file browser (full UI)
85
+
86
+ ```tsx
87
+ "use client";
88
+
89
+ import { useEffect } from "react";
90
+ import { useFiles, AuthBar, FileBrowser } from "team-connect";
91
+
92
+ export default function Page() {
93
+ const fileState = useFiles();
94
+
95
+ useEffect(() => {
96
+ fileState.checkConnection().then((ok) => {
97
+ if (ok) fileState.fetchFiles("");
98
+ });
99
+ }, []);
100
+
101
+ return (
102
+ <div>
103
+ <AuthBar proxyConnected={fileState.proxyConnected} />
104
+ <FileBrowser fileState={fileState} />
105
+ </div>
106
+ );
107
+ }
108
+ ```
109
+
110
+ #### Option B: Headless — just the hook
111
+
112
+ ```tsx
113
+ "use client";
114
+
115
+ import { useFiles } from "team-connect";
116
+
117
+ export default function MyComponent() {
118
+ const {
119
+ files,
120
+ loading,
121
+ currentPath,
122
+ proxyConnected,
123
+ checkConnection,
124
+ fetchFiles,
125
+ uploadFile,
126
+ createNewFolder,
127
+ deleteFile,
128
+ downloadFile,
129
+ search,
130
+ } = useFiles();
131
+
132
+ // Build your own UI using the file state and actions
133
+ }
134
+ ```
135
+
136
+ #### Option C: Direct API (no React)
137
+
138
+ ```ts
139
+ import {
140
+ checkProxyHealth,
141
+ listFiles,
142
+ uploadFile,
143
+ downloadFile,
144
+ createFolder,
145
+ deleteItem,
146
+ searchFiles,
147
+ } from "team-connect";
148
+
149
+ // Check proxy is running
150
+ const ok = await checkProxyHealth();
151
+
152
+ // List files in a subfolder
153
+ const files = await listFiles("Reports/Q1");
154
+
155
+ // Upload a file
156
+ await uploadFile(myFile, "Reports/Q1");
157
+
158
+ // Download
159
+ await downloadFile("/sites/MySite/Shared Documents/report.pdf", "report.pdf");
160
+
161
+ // Create folder
162
+ await createFolder("Q2", "Reports");
163
+
164
+ // Delete
165
+ await deleteItem("/sites/MySite/Shared Documents/old.xlsx", false);
166
+
167
+ // Search
168
+ const results = await searchFiles("invoice");
169
+ ```
170
+
171
+ ---
172
+
173
+ ## Components
174
+
175
+ | Component | Props | Description |
176
+ |-----------|-------|-------------|
177
+ | `AuthBar` | `proxyConnected: boolean \| null` | Top bar with connection status indicator (green/yellow/red) |
178
+ | `FileBrowser` | `fileState: UseFilesReturn` | Full file browser with breadcrumbs, search, upload zone, file list |
179
+ | `FileList` | `files, loading, onFolderClick, onDownload, onDelete` | Table of files and folders with actions |
180
+ | `Breadcrumbs` | `items: BreadcrumbItem[], onNavigate` | Clickable path breadcrumbs |
181
+ | `SearchBar` | `onSearch, onClear` | Debounced search input |
182
+ | `UploadZone` | `onUpload, uploading?` | Drag-and-drop file upload area |
183
+
184
+ All components use Tailwind CSS classes. Make sure Tailwind is configured in your project.
185
+
186
+ ---
187
+
188
+ ## Hook: `useFiles()`
189
+
190
+ Returns:
191
+
192
+ | Property | Type | Description |
193
+ |----------|------|-------------|
194
+ | `files` | `FileItem[]` | Current file listing |
195
+ | `loading` | `boolean` | Loading state |
196
+ | `currentPath` | `string` | Current subfolder path |
197
+ | `proxyConnected` | `boolean \| null` | Proxy status (`null` = checking) |
198
+ | `checkConnection()` | `() => Promise<boolean>` | Ping the proxy health endpoint |
199
+ | `fetchFiles(path)` | `(path: string) => Promise<void>` | Load files at path |
200
+ | `uploadFile(file, path)` | `(file: File, path: string) => Promise<void>` | Upload a file |
201
+ | `createNewFolder(name, path)` | `(name: string, path: string) => Promise<void>` | Create a folder |
202
+ | `deleteFile(url, name, isFolder)` | `(...) => Promise<void>` | Delete a file or folder |
203
+ | `downloadFile(url, name)` | `(...) => Promise<void>` | Download a file |
204
+ | `search(query)` | `(query: string) => Promise<void>` | Search files by name |
205
+
206
+ ---
207
+
208
+ ## Types
209
+
210
+ ```ts
211
+ interface FileItem {
212
+ id: string;
213
+ name: string;
214
+ size: number;
215
+ lastModifiedDateTime: string;
216
+ lastModifiedBy: { displayName: string; email?: string };
217
+ webUrl: string;
218
+ serverRelativeUrl: string;
219
+ isFolder: boolean;
220
+ mimeType?: string;
221
+ }
222
+
223
+ interface BreadcrumbItem {
224
+ name: string;
225
+ path: string;
226
+ }
227
+ ```
228
+
229
+ ---
230
+
231
+ ## Proxy API
232
+
233
+ The Go proxy exposes two endpoints:
234
+
235
+ | Endpoint | Description |
236
+ |----------|-------------|
237
+ | `GET /health` | Returns `{ status, siteUrl, serverRelativeUrl }` |
238
+ | `* /sp/…` | Proxies any request to `{siteUrl}/…` with auth injected |
239
+
240
+ ### Proxy flags
241
+
242
+ ```bash
243
+ ./proxy --strategy ondemand --config ./config/private.json --port 8080
244
+ ```
245
+
246
+ | Flag | Default | Description |
247
+ |------|---------|-------------|
248
+ | `--strategy` | `ondemand` | gosip auth strategy |
249
+ | `--config` | `./config/private.json` | Path to auth config |
250
+ | `--port` | `8080` | Proxy listen port |
251
+
252
+ ---
253
+
254
+ ## Styling
255
+
256
+ Components use Tailwind CSS utility classes. Ensure your project has Tailwind configured. The components use only standard Tailwind classes — no custom theme extensions required.
257
+
258
+ ---
259
+
260
+ ## Project structure
261
+
262
+ ```
263
+ team-connect/
264
+ ├── index.ts # Library entry point
265
+ ├── types/index.ts # TypeScript types
266
+ ├── lib/
267
+ │ ├── sp-client.ts # SharePoint REST API client
268
+ │ └── utils.ts # Formatting helpers
269
+ ├── hooks/
270
+ │ └── useFiles.ts # React hook
271
+ ├── components/
272
+ │ ├── AuthBar.tsx # Connection status bar
273
+ │ ├── Breadcrumbs.tsx # Path navigation
274
+ │ ├── FileBrowser.tsx # Main file browser
275
+ │ ├── FileList.tsx # File table
276
+ │ ├── SearchBar.tsx # Search input
277
+ │ └── UploadZone.tsx # Drag-and-drop upload
278
+ ├── proxy/
279
+ │ ├── main.go # Go proxy server
280
+ │ ├── go.mod
281
+ │ └── config/
282
+ │ └── private.json # SharePoint site URL
283
+ ├── app/ # Demo Next.js app
284
+ │ ├── page.tsx
285
+ │ └── layout.tsx
286
+ └── smoke-test.sh # Connectivity test
287
+ ```
288
+
289
+ ---
290
+
291
+ ## Running the demo app
292
+
293
+ ```bash
294
+ # Terminal 1: Start the proxy
295
+ cd proxy && ./team-connect-proxy
296
+
297
+ # Terminal 2: Start Next.js
298
+ npm run dev
299
+ # Open http://localhost:3000
300
+ ```
301
+
302
+ ---
303
+
304
+ ## Smoke test
305
+
306
+ ```bash
307
+ # With the proxy running:
308
+ bash smoke-test.sh
309
+ ```
310
+
311
+ ---
312
+
313
+ ## License
314
+
315
+ MIT
@@ -0,0 +1,6 @@
1
+ interface AuthBarProps {
2
+ proxyConnected: boolean | null;
3
+ }
4
+ export default function AuthBar({ proxyConnected }: AuthBarProps): import("react/jsx-runtime").JSX.Element;
5
+ export {};
6
+ //# sourceMappingURL=AuthBar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AuthBar.d.ts","sourceRoot":"","sources":["../../components/AuthBar.tsx"],"names":[],"mappings":"AAGA,UAAU,YAAY;IACpB,cAAc,EAAE,OAAO,GAAG,IAAI,CAAC;CAChC;AAED,MAAM,CAAC,OAAO,UAAU,OAAO,CAAC,EAAE,cAAc,EAAE,EAAE,YAAY,2CA+B/D"}
@@ -0,0 +1,16 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ export default function AuthBar({ proxyConnected }) {
4
+ const statusColor = proxyConnected === null
5
+ ? "bg-yellow-400"
6
+ : proxyConnected
7
+ ? "bg-green-400"
8
+ : "bg-red-500";
9
+ const statusLabel = proxyConnected === null
10
+ ? "Checking…"
11
+ : proxyConnected
12
+ ? "Connected"
13
+ : "Disconnected";
14
+ return (_jsxs("div", { className: "flex items-center justify-between px-6 py-3 bg-gray-900 text-white", children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsx("h1", { className: "text-lg font-semibold tracking-tight", children: "Team Connect" }), _jsx("span", { className: "text-gray-400 text-sm", children: "|" }), _jsx("span", { className: "text-gray-400 text-sm", children: process.env.NEXT_PUBLIC_SHAREPOINT_FOLDER_PATH || "SharePoint" })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: `w-2.5 h-2.5 rounded-full ${statusColor}` }), _jsx("span", { className: "text-sm text-gray-300", children: statusLabel })] })] }));
15
+ }
16
+ //# sourceMappingURL=AuthBar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AuthBar.js","sourceRoot":"","sources":["../../components/AuthBar.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAOb,MAAM,CAAC,OAAO,UAAU,OAAO,CAAC,EAAE,cAAc,EAAgB;IAC9D,MAAM,WAAW,GACf,cAAc,KAAK,IAAI;QACrB,CAAC,CAAC,eAAe;QACjB,CAAC,CAAC,cAAc;YAChB,CAAC,CAAC,cAAc;YAChB,CAAC,CAAC,YAAY,CAAC;IAEnB,MAAM,WAAW,GACf,cAAc,KAAK,IAAI;QACrB,CAAC,CAAC,WAAW;QACb,CAAC,CAAC,cAAc;YAChB,CAAC,CAAC,WAAW;YACb,CAAC,CAAC,cAAc,CAAC;IAErB,OAAO,CACL,eAAK,SAAS,EAAC,oEAAoE,aACjF,eAAK,SAAS,EAAC,yBAAyB,aACtC,aAAI,SAAS,EAAC,sCAAsC,6BAAkB,EACtE,eAAM,SAAS,EAAC,uBAAuB,kBAAS,EAChD,eAAM,SAAS,EAAC,uBAAuB,YACpC,OAAO,CAAC,GAAG,CAAC,kCAAkC,IAAI,YAAY,GAC1D,IACH,EAEN,eAAK,SAAS,EAAC,yBAAyB,aACtC,eAAM,SAAS,EAAE,4BAA4B,WAAW,EAAE,GAAI,EAC9D,eAAM,SAAS,EAAC,uBAAuB,YAAE,WAAW,GAAQ,IACxD,IACF,CACP,CAAC;AACJ,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { BreadcrumbItem } from "../types";
2
+ interface BreadcrumbsProps {
3
+ items: BreadcrumbItem[];
4
+ onNavigate: (path: string) => void;
5
+ }
6
+ export default function Breadcrumbs({ items, onNavigate }: BreadcrumbsProps): import("react/jsx-runtime").JSX.Element;
7
+ export {};
8
+ //# sourceMappingURL=Breadcrumbs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Breadcrumbs.d.ts","sourceRoot":"","sources":["../../components/Breadcrumbs.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE1C,UAAU,gBAAgB;IACxB,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACpC;AAED,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,gBAAgB,2CAoB1E"}
@@ -0,0 +1,6 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ export default function Breadcrumbs({ items, onNavigate }) {
4
+ return (_jsx("nav", { className: "flex items-center gap-1 text-sm text-gray-600 py-3 px-1 overflow-x-auto", children: items.map((item, index) => (_jsxs("span", { className: "flex items-center gap-1 whitespace-nowrap", children: [index > 0 && _jsx("span", { className: "text-gray-400 mx-1", children: "/" }), index === items.length - 1 ? (_jsx("span", { className: "font-medium text-gray-900", children: item.name })) : (_jsx("button", { onClick: () => onNavigate(item.path), className: "text-blue-600 hover:text-blue-800 hover:underline transition-colors", children: item.name }))] }, item.path))) }));
5
+ }
6
+ //# sourceMappingURL=Breadcrumbs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Breadcrumbs.js","sourceRoot":"","sources":["../../components/Breadcrumbs.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AASb,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,EAAE,KAAK,EAAE,UAAU,EAAoB;IACzE,OAAO,CACL,cAAK,SAAS,EAAC,yEAAyE,YACrF,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,CAC1B,gBAAsB,SAAS,EAAC,2CAA2C,aACxE,KAAK,GAAG,CAAC,IAAI,eAAM,SAAS,EAAC,oBAAoB,kBAAS,EAC1D,KAAK,KAAK,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAC5B,eAAM,SAAS,EAAC,2BAA2B,YAAE,IAAI,CAAC,IAAI,GAAQ,CAC/D,CAAC,CAAC,CAAC,CACF,iBACE,OAAO,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EACpC,SAAS,EAAC,qEAAqE,YAE9E,IAAI,CAAC,IAAI,GACH,CACV,KAXQ,IAAI,CAAC,IAAI,CAYb,CACR,CAAC,GACE,CACP,CAAC;AACJ,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { UseFilesReturn } from "../hooks/useFiles";
2
+ interface FileBrowserProps {
3
+ fileState: UseFilesReturn;
4
+ }
5
+ export default function FileBrowser({ fileState }: FileBrowserProps): import("react/jsx-runtime").JSX.Element;
6
+ export {};
7
+ //# sourceMappingURL=FileBrowser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FileBrowser.d.ts","sourceRoot":"","sources":["../../components/FileBrowser.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAOnD,UAAU,gBAAgB;IACxB,SAAS,EAAE,cAAc,CAAC;CAC3B;AAED,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,EAAE,SAAS,EAAE,EAAE,gBAAgB,2CA4IlE"}
@@ -0,0 +1,47 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useState, useCallback } from "react";
4
+ import { buildBreadcrumbs } from "../lib/utils";
5
+ import Breadcrumbs from "./Breadcrumbs";
6
+ import SearchBar from "./SearchBar";
7
+ import FileList from "./FileList";
8
+ import UploadZone from "./UploadZone";
9
+ export default function FileBrowser({ fileState }) {
10
+ const { files, loading, currentPath, proxyConnected, fetchFiles, uploadFile, createNewFolder, deleteFile, downloadFile, search, } = fileState;
11
+ const [uploading, setUploading] = useState(false);
12
+ const [showNewFolder, setShowNewFolder] = useState(false);
13
+ const [newFolderName, setNewFolderName] = useState("");
14
+ const handleFolderClick = useCallback((folderName) => {
15
+ const newPath = currentPath ? `${currentPath}/${folderName}` : folderName;
16
+ fetchFiles(newPath);
17
+ }, [currentPath, fetchFiles]);
18
+ const handleBreadcrumbNavigate = useCallback((path) => {
19
+ fetchFiles(path);
20
+ }, [fetchFiles]);
21
+ const handleUpload = useCallback(async (uploadedFiles) => {
22
+ setUploading(true);
23
+ for (const file of uploadedFiles) {
24
+ await uploadFile(file, currentPath);
25
+ }
26
+ setUploading(false);
27
+ }, [uploadFile, currentPath]);
28
+ const handleCreateFolder = useCallback(async () => {
29
+ if (!newFolderName.trim())
30
+ return;
31
+ await createNewFolder(newFolderName.trim(), currentPath);
32
+ setNewFolderName("");
33
+ setShowNewFolder(false);
34
+ }, [newFolderName, createNewFolder, currentPath]);
35
+ const handleSearchClear = useCallback(() => {
36
+ fetchFiles(currentPath);
37
+ }, [fetchFiles, currentPath]);
38
+ if (proxyConnected === false) {
39
+ return (_jsxs("div", { className: "flex flex-col items-center justify-center py-24 text-gray-500", children: [_jsx("svg", { className: "w-16 h-16 mb-4 text-gray-300", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 1.5, d: "M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z" }) }), _jsx("h2", { className: "text-xl font-semibold text-gray-700", children: "Proxy not connected" }), _jsxs("p", { className: "mt-2 text-sm max-w-md text-center", children: ["Start the Go proxy first:", _jsx("code", { className: "block mt-2 px-3 py-1 bg-gray-100 rounded text-xs text-gray-700 font-mono", children: "cd proxy && ./team-connect-proxy" })] })] }));
40
+ }
41
+ const breadcrumbs = buildBreadcrumbs(currentPath);
42
+ return (_jsxs("div", { className: "space-y-4", children: [_jsxs("div", { className: "flex flex-col sm:flex-row gap-3 items-start sm:items-center justify-between", children: [_jsx(Breadcrumbs, { items: breadcrumbs, onNavigate: handleBreadcrumbNavigate }), _jsxs("div", { className: "flex items-center gap-2 w-full sm:w-auto", children: [_jsx("div", { className: "flex-1 sm:w-64", children: _jsx(SearchBar, { onSearch: search, onClear: handleSearchClear }) }), _jsx("button", { onClick: () => setShowNewFolder(!showNewFolder), className: "px-3 py-2 text-sm bg-gray-100 hover:bg-gray-200 rounded-lg transition-colors whitespace-nowrap", children: "+ Folder" })] })] }), showNewFolder && (_jsxs("div", { className: "flex items-center gap-2 p-3 bg-gray-50 rounded-lg", children: [_jsx("input", { type: "text", value: newFolderName, onChange: (e) => setNewFolderName(e.target.value), onKeyDown: (e) => e.key === "Enter" && handleCreateFolder(), placeholder: "Folder name...", className: "flex-1 px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500", autoFocus: true }), _jsx("button", { onClick: handleCreateFolder, className: "px-3 py-1.5 text-sm bg-blue-600 text-white rounded-md hover:bg-blue-500 transition-colors", children: "Create" }), _jsx("button", { onClick: () => {
43
+ setShowNewFolder(false);
44
+ setNewFolderName("");
45
+ }, className: "px-3 py-1.5 text-sm text-gray-600 hover:text-gray-800 transition-colors", children: "Cancel" })] })), _jsx(UploadZone, { onUpload: handleUpload, uploading: uploading }), _jsx(FileList, { files: files, loading: loading, onFolderClick: handleFolderClick, onDownload: downloadFile, onDelete: deleteFile })] }));
46
+ }
47
+ //# sourceMappingURL=FileBrowser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FileBrowser.js","sourceRoot":"","sources":["../../components/FileBrowser.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import { FileItem } from "../types";
2
+ interface FileListProps {
3
+ files: FileItem[];
4
+ loading: boolean;
5
+ onFolderClick: (folderName: string) => void;
6
+ onDownload: (serverRelativeUrl: string, fileName: string) => void;
7
+ onDelete: (serverRelativeUrl: string, itemName: string, isFolder: boolean) => void;
8
+ }
9
+ export default function FileList({ files, loading, onFolderClick, onDownload, onDelete, }: FileListProps): import("react/jsx-runtime").JSX.Element;
10
+ export {};
11
+ //# sourceMappingURL=FileList.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FileList.d.ts","sourceRoot":"","sources":["../../components/FileList.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAGpC,UAAU,aAAa;IACrB,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,UAAU,EAAE,CAAC,iBAAiB,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAClE,QAAQ,EAAE,CAAC,iBAAiB,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;CACpF;AAED,MAAM,CAAC,OAAO,UAAU,QAAQ,CAAC,EAC/B,KAAK,EACL,OAAO,EACP,aAAa,EACb,UAAU,EACV,QAAQ,GACT,EAAE,aAAa,2CAkIf"}
@@ -0,0 +1,25 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { formatFileSize, formatDate, getFileIcon } from "../lib/utils";
4
+ export default function FileList({ files, loading, onFolderClick, onDownload, onDelete, }) {
5
+ if (loading) {
6
+ return (_jsx("div", { className: "flex items-center justify-center py-12", children: _jsxs("svg", { className: "animate-spin w-8 h-8 text-blue-500", fill: "none", viewBox: "0 0 24 24", children: [_jsx("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }), _jsx("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z" })] }) }));
7
+ }
8
+ if (files.length === 0) {
9
+ return (_jsxs("div", { className: "text-center py-12 text-gray-500", children: [_jsx("p", { className: "text-lg", children: "No files found" }), _jsx("p", { className: "text-sm mt-1", children: "Upload files or create a folder to get started" })] }));
10
+ }
11
+ // Sort folders first, then files
12
+ const sorted = [...files].sort((a, b) => {
13
+ if (a.isFolder && !b.isFolder)
14
+ return -1;
15
+ if (!a.isFolder && b.isFolder)
16
+ return 1;
17
+ return a.name.localeCompare(b.name);
18
+ });
19
+ return (_jsx("div", { className: "overflow-x-auto", children: _jsxs("table", { className: "w-full text-sm", children: [_jsx("thead", { children: _jsxs("tr", { className: "border-b border-gray-200 text-left text-gray-500", children: [_jsx("th", { className: "py-2 px-3 font-medium", children: "Name" }), _jsx("th", { className: "py-2 px-3 font-medium w-24", children: "Size" }), _jsx("th", { className: "py-2 px-3 font-medium w-44", children: "Modified" }), _jsx("th", { className: "py-2 px-3 font-medium w-36", children: "Modified by" }), _jsx("th", { className: "py-2 px-3 font-medium w-24 text-right", children: "Actions" })] }) }), _jsx("tbody", { children: sorted.map((file) => (_jsxs("tr", { className: "border-b border-gray-100 hover:bg-gray-50 transition-colors", children: [_jsx("td", { className: "py-2.5 px-3", children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "text-base", children: getFileIcon(file.name, file.isFolder) }), file.isFolder ? (_jsx("button", { onClick: () => onFolderClick(file.name), className: "text-blue-600 hover:text-blue-800 hover:underline font-medium", children: file.name })) : (_jsx("button", { onClick: () => onDownload(file.serverRelativeUrl, file.name), className: "text-gray-900 hover:text-blue-600 hover:underline", children: file.name }))] }) }), _jsx("td", { className: "py-2.5 px-3 text-gray-500", children: file.isFolder ? "—" : formatFileSize(file.size) }), _jsx("td", { className: "py-2.5 px-3 text-gray-500", children: formatDate(file.lastModifiedDateTime) }), _jsx("td", { className: "py-2.5 px-3 text-gray-500 truncate max-w-[140px]", children: file.lastModifiedBy.displayName }), _jsx("td", { className: "py-2.5 px-3 text-right", children: _jsxs("div", { className: "flex items-center justify-end gap-1", children: [!file.isFolder && (_jsx("button", { onClick: () => onDownload(file.serverRelativeUrl, file.name), className: "p-1.5 text-gray-400 hover:text-blue-600 rounded transition-colors", title: "Download", children: _jsx("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" }) }) })), _jsx("button", { onClick: () => {
20
+ if (confirm(`Delete "${file.name}"?`)) {
21
+ onDelete(file.serverRelativeUrl, file.name, file.isFolder);
22
+ }
23
+ }, className: "p-1.5 text-gray-400 hover:text-red-600 rounded transition-colors", title: "Delete", children: _jsx("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" }) }) })] }) })] }, file.id))) })] }) }));
24
+ }
25
+ //# sourceMappingURL=FileList.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FileList.js","sourceRoot":"","sources":["../../components/FileList.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ interface SearchBarProps {
2
+ onSearch: (query: string) => void;
3
+ onClear: () => void;
4
+ }
5
+ export default function SearchBar({ onSearch, onClear }: SearchBarProps): import("react/jsx-runtime").JSX.Element;
6
+ export {};
7
+ //# sourceMappingURL=SearchBar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SearchBar.d.ts","sourceRoot":"","sources":["../../components/SearchBar.tsx"],"names":[],"mappings":"AAIA,UAAU,cAAc;IACtB,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,MAAM,CAAC,OAAO,UAAU,SAAS,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,cAAc,2CA4DtE"}
@@ -0,0 +1,29 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useState, useRef } from "react";
4
+ export default function SearchBar({ onSearch, onClear }) {
5
+ const [query, setQuery] = useState("");
6
+ const debounceRef = useRef(null);
7
+ const handleChange = (value) => {
8
+ setQuery(value);
9
+ if (debounceRef.current)
10
+ clearTimeout(debounceRef.current);
11
+ if (!value.trim()) {
12
+ onClear();
13
+ return;
14
+ }
15
+ debounceRef.current = setTimeout(() => {
16
+ onSearch(value);
17
+ }, 400);
18
+ };
19
+ const handleSubmit = (e) => {
20
+ e.preventDefault();
21
+ if (query.trim())
22
+ onSearch(query);
23
+ };
24
+ return (_jsxs("form", { onSubmit: handleSubmit, className: "relative", children: [_jsx("input", { type: "text", value: query, onChange: (e) => handleChange(e.target.value), placeholder: "Search files...", className: "w-full pl-10 pr-4 py-2 border border-gray-300 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent" }), _jsx("svg", { className: "absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-gray-400", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" }) }), query && (_jsx("button", { type: "button", onClick: () => {
25
+ setQuery("");
26
+ onClear();
27
+ }, className: "absolute right-3 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600", children: "\u2715" }))] }));
28
+ }
29
+ //# sourceMappingURL=SearchBar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SearchBar.js","sourceRoot":"","sources":["../../components/SearchBar.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAOzC,MAAM,CAAC,OAAO,UAAU,SAAS,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAkB;IACrE,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IACvC,MAAM,WAAW,GAAG,MAAM,CAAwB,IAAI,CAAC,CAAC;IAExD,MAAM,YAAY,GAAG,CAAC,KAAa,EAAE,EAAE;QACrC,QAAQ,CAAC,KAAK,CAAC,CAAC;QAEhB,IAAI,WAAW,CAAC,OAAO;YAAE,YAAY,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;QAE3D,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC;YAClB,OAAO,EAAE,CAAC;YACV,OAAO;QACT,CAAC;QAED,WAAW,CAAC,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE;YACpC,QAAQ,CAAC,KAAK,CAAC,CAAC;QAClB,CAAC,EAAE,GAAG,CAAC,CAAC;IACV,CAAC,CAAC;IAEF,MAAM,YAAY,GAAG,CAAC,CAAkB,EAAE,EAAE;QAC1C,CAAC,CAAC,cAAc,EAAE,CAAC;QACnB,IAAI,KAAK,CAAC,IAAI,EAAE;YAAE,QAAQ,CAAC,KAAK,CAAC,CAAC;IACpC,CAAC,CAAC;IAEF,OAAO,CACL,gBAAM,QAAQ,EAAE,YAAY,EAAE,SAAS,EAAC,UAAU,aAChD,gBACE,IAAI,EAAC,MAAM,EACX,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAC7C,WAAW,EAAC,iBAAiB,EAC7B,SAAS,EAAC,+IAA+I,GACzJ,EACF,cACE,SAAS,EAAC,gEAAgE,EAC1E,IAAI,EAAC,MAAM,EACX,MAAM,EAAC,cAAc,EACrB,OAAO,EAAC,WAAW,YAEnB,eACE,aAAa,EAAC,OAAO,EACrB,cAAc,EAAC,OAAO,EACtB,WAAW,EAAE,CAAC,EACd,CAAC,EAAC,6CAA6C,GAC/C,GACE,EACL,KAAK,IAAI,CACR,iBACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,GAAG,EAAE;oBACZ,QAAQ,CAAC,EAAE,CAAC,CAAC;oBACb,OAAO,EAAE,CAAC;gBACZ,CAAC,EACD,SAAS,EAAC,6EAA6E,uBAGhF,CACV,IACI,CACR,CAAC;AACJ,CAAC"}
@@ -0,0 +1,7 @@
1
+ interface UploadZoneProps {
2
+ onUpload: (files: File[]) => void;
3
+ uploading?: boolean;
4
+ }
5
+ export default function UploadZone({ onUpload, uploading }: UploadZoneProps): import("react/jsx-runtime").JSX.Element;
6
+ export {};
7
+ //# sourceMappingURL=UploadZone.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UploadZone.d.ts","sourceRoot":"","sources":["../../components/UploadZone.tsx"],"names":[],"mappings":"AAKA,UAAU,eAAe;IACvB,QAAQ,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,IAAI,CAAC;IAClC,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,CAAC,OAAO,UAAU,UAAU,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,eAAe,2CAyD1E"}
@@ -0,0 +1,19 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useCallback } from "react";
4
+ import { useDropzone } from "react-dropzone";
5
+ export default function UploadZone({ onUpload, uploading }) {
6
+ const onDrop = useCallback((acceptedFiles) => {
7
+ onUpload(acceptedFiles);
8
+ }, [onUpload]);
9
+ const { getRootProps, getInputProps, isDragActive } = useDropzone({
10
+ onDrop,
11
+ disabled: uploading,
12
+ });
13
+ return (_jsxs("div", Object.assign({}, getRootProps(), { className: `border-2 border-dashed rounded-lg p-6 text-center cursor-pointer transition-colors ${isDragActive
14
+ ? "border-blue-500 bg-blue-50"
15
+ : uploading
16
+ ? "border-gray-200 bg-gray-50 cursor-not-allowed"
17
+ : "border-gray-300 hover:border-blue-400 hover:bg-gray-50"}`, children: [_jsx("input", Object.assign({}, getInputProps())), uploading ? (_jsxs("div", { className: "flex items-center justify-center gap-2 text-gray-500", children: [_jsxs("svg", { className: "animate-spin w-5 h-5", fill: "none", viewBox: "0 0 24 24", children: [_jsx("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }), _jsx("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z" })] }), _jsx("span", { className: "text-sm", children: "Uploading..." })] })) : isDragActive ? (_jsx("p", { className: "text-sm text-blue-600 font-medium", children: "Drop files here..." })) : (_jsxs("div", { children: [_jsxs("p", { className: "text-sm text-gray-600", children: ["Drag & drop files here, or", " ", _jsx("span", { className: "text-blue-600 font-medium", children: "browse" })] }), _jsx("p", { className: "text-xs text-gray-400 mt-1", children: "Any file type supported" })] }))] })));
18
+ }
19
+ //# sourceMappingURL=UploadZone.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UploadZone.js","sourceRoot":"","sources":["../../components/UploadZone.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAO7C,MAAM,CAAC,OAAO,UAAU,UAAU,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAmB;IACzE,MAAM,MAAM,GAAG,WAAW,CACxB,CAAC,aAAqB,EAAE,EAAE;QACxB,QAAQ,CAAC,aAAa,CAAC,CAAC;IAC1B,CAAC,EACD,CAAC,QAAQ,CAAC,CACX,CAAC;IAEF,MAAM,EAAE,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,GAAG,WAAW,CAAC;QAChE,MAAM;QACN,QAAQ,EAAE,SAAS;KACpB,CAAC,CAAC;IAEH,OAAO,CACL,+BACM,YAAY,EAAE,IAClB,SAAS,EAAE,sFACT,YAAY;YACV,CAAC,CAAC,4BAA4B;YAC9B,CAAC,CAAC,SAAS;gBACX,CAAC,CAAC,+CAA+C;gBACjD,CAAC,CAAC,wDACN,EAAE,aAEF,gCAAW,aAAa,EAAE,EAAI,EAC7B,SAAS,CAAC,CAAC,CAAC,CACX,eAAK,SAAS,EAAC,sDAAsD,aACnE,eAAK,SAAS,EAAC,sBAAsB,EAAC,IAAI,EAAC,MAAM,EAAC,OAAO,EAAC,WAAW,aACnE,iBACE,SAAS,EAAC,YAAY,EACtB,EAAE,EAAC,IAAI,EACP,EAAE,EAAC,IAAI,EACP,CAAC,EAAC,IAAI,EACN,MAAM,EAAC,cAAc,EACrB,WAAW,EAAC,GAAG,GACf,EACF,eACE,SAAS,EAAC,YAAY,EACtB,IAAI,EAAC,cAAc,EACnB,CAAC,EAAC,6CAA6C,GAC/C,IACE,EACN,eAAM,SAAS,EAAC,SAAS,6BAAoB,IACzC,CACP,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CACjB,YAAG,SAAS,EAAC,mCAAmC,mCAAuB,CACxE,CAAC,CAAC,CAAC,CACF,0BACE,aAAG,SAAS,EAAC,uBAAuB,2CACP,GAAG,EAC9B,eAAM,SAAS,EAAC,2BAA2B,uBAAc,IACvD,EACJ,YAAG,SAAS,EAAC,4BAA4B,wCAA4B,IACjE,CACP,KACG,CACP,CAAC;AACJ,CAAC"}
@@ -0,0 +1,16 @@
1
+ import { FileItem } from "../types";
2
+ export declare function useFiles(): {
3
+ files: FileItem[];
4
+ loading: boolean;
5
+ currentPath: string;
6
+ proxyConnected: boolean | null;
7
+ checkConnection: () => Promise<boolean>;
8
+ fetchFiles: (path?: string) => Promise<void>;
9
+ uploadFile: (file: File, path: string) => Promise<void>;
10
+ createNewFolder: (folderName: string, path: string) => Promise<void>;
11
+ deleteFile: (serverRelativeUrl: string, itemName: string, isFolder: boolean) => Promise<void>;
12
+ downloadFile: (serverRelativeUrl: string, fileName: string) => Promise<void>;
13
+ search: (query: string) => Promise<void>;
14
+ };
15
+ export type UseFilesReturn = ReturnType<typeof useFiles>;
16
+ //# sourceMappingURL=useFiles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useFiles.d.ts","sourceRoot":"","sources":["../../hooks/useFiles.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAYpC,wBAAgB,QAAQ;;;;;2BAMwB,OAAO,CAAC,OAAO,CAAC;wBAMlB,MAAM;uBAcnC,IAAI,QAAQ,MAAM;kCAaZ,MAAM,QAAQ,MAAM;oCAeb,MAAM,YAAY,MAAM,YAAY,OAAO;sCAa3C,MAAM,YAAY,MAAM;oBAYpC,MAAM;EA+BvB;AAED,MAAM,MAAM,cAAc,GAAG,UAAU,CAAC,OAAO,QAAQ,CAAC,CAAC"}