blixify-ui-web-mcp 0.1.21 → 0.1.23
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/lib/components/chat/chatAnchor/README.md +13 -3
- package/lib/components/chat/chatAnchor/chatAnchor.stories.tsx +50 -0
- package/lib/components/data/dataTemplate/README.md +0 -63
- package/lib/components/data/driveTemplate/README.md +90 -0
- package/lib/components/data/{dataTemplate/drive.stories.tsx → driveTemplate/driveTemplate.stories.tsx} +39 -59
- package/lib/mcp/tools/getBackendComponent.d.ts.map +1 -1
- package/lib/mcp/tools/getBackendComponent.js +4 -0
- package/lib/mcp/tools/getBackendComponent.js.map +1 -1
- package/package.json +1 -1
|
@@ -8,10 +8,20 @@ A floating chat button fixed to the viewport. Clicking it toggles the `ChatBase`
|
|
|
8
8
|
|
|
9
9
|
The button can be dragged out of the way on desktop and touch, and where it is dropped is kept in `localStorage` so it stays there on the next visit. A short drag is still treated as a click, so tapping always opens the chat. A saved position is clamped back into view when it is restored on a smaller screen or the window is resized under it, and dragging is disabled while the panel is full screen on mobile.
|
|
10
10
|
|
|
11
|
+
With `resizableWidth`, an open panel gains a grab handle on its left edge — dragging it left or right resizes the panel to any width. The only bounds are physical: it cannot be dragged wider than the viewport, nor narrower than 280px, below which the header, messages and input stop being usable. The chosen width is kept in `localStorage`, re-clamped to the viewport on window resize, and the handle is hidden while the panel is full screen on mobile.
|
|
12
|
+
|
|
13
|
+
`resizableHeight` works the same way on the vertical axis: an open panel gains a grab handle on its top edge, and dragging it up or down resizes the panel to any height. Because the panel grows upward from the bottom-right anchor, the cap is the distance from its bottom edge to the top of the viewport, and the floor keeps the header and input row usable. The default height is three quarters of the viewport (matching the panel's `sm:h-[75vh]`). Width and height are independent — turn on either or both. The chosen height is kept in `localStorage` and re-clamped on window resize.
|
|
14
|
+
|
|
11
15
|
| Prop | Type | Default | Description |
|
|
12
16
|
| -------------------- | --------- | -------------------------------- | ------------------------------------------------------------------------------------------- |
|
|
13
17
|
| `draggable` | `boolean` | `true` | Set `false` to pin the button to `positionOffset` and ignore any saved position |
|
|
14
18
|
| `positionStorageKey` | `string` | `"blixify-chat-anchor-position"` | `localStorage` key holding `{ right, bottom }` in px, measured from the bottom-right corner |
|
|
19
|
+
| `resizableWidth` | `boolean` | `false` | Set `true` to show a left-edge handle that drags the open panel to any width |
|
|
20
|
+
| `defaultWidth` | `number` | `384` | Width (px) the panel opens at before the user has dragged (matches `sm:w-96`) |
|
|
21
|
+
| `widthStorageKey` | `string` | `"blixify-chat-anchor-width"` | `localStorage` key holding the panel width in px |
|
|
22
|
+
| `resizableHeight` | `boolean` | `false` | Set `true` to show a top-edge handle that drags the open panel to any height |
|
|
23
|
+
| `defaultHeight` | `number` | `75% of viewport` | Height (px) the panel opens at before the user has dragged (matches `sm:h-[75vh]`) |
|
|
24
|
+
| `heightStorageKey` | `string` | `"blixify-chat-anchor-height"` | `localStorage` key holding the panel height in px |
|
|
15
25
|
|
|
16
26
|
##### Import
|
|
17
27
|
|
|
@@ -70,11 +80,11 @@ return (
|
|
|
70
80
|
|
|
71
81
|
| Name | Type | Default | Description |
|
|
72
82
|
| ---------------- | ----------------------------- | -------------------------------------- | ----------------------------------------------------------------------------------------------- |
|
|
73
|
-
| `positionOffset` | `string` | `"bottom-
|
|
83
|
+
| `positionOffset` | `string` | `"bottom-6 right-6"` | Tailwind classes that control the fixed position of the anchor. Ignored on mobile when open. |
|
|
74
84
|
| `greetingCard` | `boolean` | `false` | When `true`, shows a greeting bubble next to the anchor button while the chat is closed. |
|
|
75
85
|
| `greetingText` | `string` | `"Welcome! How can I help you today?"` | Text displayed inside the greeting card bubble. |
|
|
76
|
-
| `openIcon` | `React.ReactNode` \| `string` | `ChatBubbleOvalLeftIcon` | Icon shown when the chat is closed. A string is treated as an image URL (
|
|
77
|
-
| `closeIcon` | `React.ReactNode` \| `string` | `XMarkIcon` | Icon shown when the chat is open. A string is treated as an image URL (
|
|
86
|
+
| `openIcon` | `React.ReactNode` \| `string` | `ChatBubbleOvalLeftIcon` | Icon shown when the chat is closed. A string is treated as an image URL (56×56 rounded circle). |
|
|
87
|
+
| `closeIcon` | `React.ReactNode` \| `string` | `XMarkIcon` | Icon shown when the chat is open. A string is treated as an image URL (56×56 rounded circle). |
|
|
78
88
|
|
|
79
89
|
##### Optional props — inherited from ChatBase
|
|
80
90
|
|
|
@@ -148,3 +148,53 @@ export const ChatAnchor = () => {
|
|
|
148
148
|
</div>
|
|
149
149
|
);
|
|
150
150
|
}
|
|
151
|
+
|
|
152
|
+
export const Resizable = () => {
|
|
153
|
+
const botUser = { id: "1", name: "Bot" };
|
|
154
|
+
const currentUser = { id: "2", name: "Guest" };
|
|
155
|
+
|
|
156
|
+
const [openChatBase, setOpenChatBase] = useState<boolean>(true);
|
|
157
|
+
const [message, setMessage] = useState("");
|
|
158
|
+
|
|
159
|
+
const [conversation, setConversation] = useState<Conversation>({
|
|
160
|
+
id: "1",
|
|
161
|
+
members: [currentUser, botUser],
|
|
162
|
+
messageList: [
|
|
163
|
+
{
|
|
164
|
+
sender: botUser,
|
|
165
|
+
messageBody:
|
|
166
|
+
"Drag my left edge to resize the width and my top edge to resize the height. Both are remembered independently.",
|
|
167
|
+
createdAt: dayjs(
|
|
168
|
+
"Fri Nov 03 2023 12:21:14 GMT+0800 (Malaysia Time)"
|
|
169
|
+
).toDate(),
|
|
170
|
+
},
|
|
171
|
+
],
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
const handleOnClick = () => setOpenChatBase(!openChatBase);
|
|
175
|
+
|
|
176
|
+
const handleOnSendMessage = (conversation: Conversation) => {
|
|
177
|
+
setConversation(conversation);
|
|
178
|
+
setMessage("");
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
return (
|
|
182
|
+
<div className="h-96 w-full relative">
|
|
183
|
+
<ChatAnchorImpl
|
|
184
|
+
open={openChatBase}
|
|
185
|
+
value={message}
|
|
186
|
+
currentUser={currentUser}
|
|
187
|
+
conversation={conversation}
|
|
188
|
+
onSendMessage={handleOnSendMessage}
|
|
189
|
+
onChangeMessage={(e) => setMessage(e.target.value)}
|
|
190
|
+
onClose={handleOnClick}
|
|
191
|
+
onClick={handleOnClick}
|
|
192
|
+
className="shadow-lg border border-gray-200"
|
|
193
|
+
resizableWidth
|
|
194
|
+
defaultWidth={384}
|
|
195
|
+
resizableHeight
|
|
196
|
+
defaultHeight={384}
|
|
197
|
+
/>
|
|
198
|
+
</div>
|
|
199
|
+
);
|
|
200
|
+
};
|
|
@@ -563,58 +563,6 @@ Set `viewType="kanban"` on an `extendedTabs` entry and configure `kanbanSettings
|
|
|
563
563
|
|
|
564
564
|
---
|
|
565
565
|
|
|
566
|
-
### Drive view
|
|
567
|
-
|
|
568
|
-
A Google Drive-style folder browser. Every row in the collection is a file or a folder, so a folder is a row, and moving something only changes one column. Set `viewType="drive"` on an `extendedTabs` entry and name the four columns in `driveSettings`.
|
|
569
|
-
|
|
570
|
-
- **Browse:** the open folder's rows load as one unpaged list, with folders first and then files, sorted A–Z. A path above the list goes back up. While the DTW search has text, the view searches the whole drive and shows each result's folder.
|
|
571
|
-
- **Folder id:** pass `organise.folderId` and `organise.onChangeFolder` to keep the open folder in the url. Without them the view keeps its own state.
|
|
572
|
-
- **Actions:** New folder, and Upload (one row per file, stored in that row's own storage folder). Files dragged over the drive show a "Drop to upload to <folder>" overlay, and a drop starts uploading straight away. The record Create button is hidden on a drive tab. Each item's menu has Details (the record's read view), Rename, Move to… and Delete. Deleting a folder deletes everything inside it, rows and storage.
|
|
573
|
-
- **Permissions:** `allEditable` or `createBtn` shows New folder and Upload. `canUpdateRecord` or `canInlineUpdate` allows Rename and Move. `deleteBtn` allows Delete. Without them the drive can be browsed but not changed.
|
|
574
|
-
- **Layout:** grid or list. The choice is remembered per browser, and phones start in the list layout.
|
|
575
|
-
|
|
576
|
-
```tsx
|
|
577
|
-
<DataTemplate
|
|
578
|
-
title="Documents"
|
|
579
|
-
description=""
|
|
580
|
-
type="list"
|
|
581
|
-
collectionId="documents"
|
|
582
|
-
model={[
|
|
583
|
-
{ id: "name", name: "Name", type: "string" },
|
|
584
|
-
{ id: "kind", name: "Kind", type: "list", listSelection: ["folder", "file"] },
|
|
585
|
-
{ id: "parentId", name: "Folder", type: "string" },
|
|
586
|
-
{ id: "file", name: "File", type: "multipleFile" },
|
|
587
|
-
{ id: "size", name: "Size", type: "number" },
|
|
588
|
-
]}
|
|
589
|
-
localURLEndpoint=""
|
|
590
|
-
devSettings={devSettings}
|
|
591
|
-
lib={{ axios, Menu, Transition }}
|
|
592
|
-
edit={{ allEditable: true, listEditable: true, deleteBtn: true }}
|
|
593
|
-
organise={{
|
|
594
|
-
handleNavigate,
|
|
595
|
-
folderId,
|
|
596
|
-
onChangeFolder: setFolderId,
|
|
597
|
-
extendedTabs: [
|
|
598
|
-
{
|
|
599
|
-
name: "Drive",
|
|
600
|
-
type: "list",
|
|
601
|
-
viewType: "drive",
|
|
602
|
-
defaultTab: true,
|
|
603
|
-
driveSettings: {
|
|
604
|
-
nameColumnId: "name",
|
|
605
|
-
kindColumnId: "kind",
|
|
606
|
-
parentColumnId: "parentId",
|
|
607
|
-
fileColumnId: "file",
|
|
608
|
-
sizeColumnId: "size",
|
|
609
|
-
},
|
|
610
|
-
},
|
|
611
|
-
],
|
|
612
|
-
}}
|
|
613
|
-
/>
|
|
614
|
-
```
|
|
615
|
-
|
|
616
|
-
---
|
|
617
|
-
|
|
618
566
|
### With search and filter
|
|
619
567
|
|
|
620
568
|
Use `organise.additionalQuery` to add filter controls above the list. Each entry maps to a filter UI control.
|
|
@@ -1302,17 +1250,6 @@ Under `bareNewDTW` the feeds tab renders `NewFeeds` (timeline card that matches
|
|
|
1302
1250
|
| `useColumnName` | `boolean` | Shows column name instead of column ID on cards |
|
|
1303
1251
|
| `query` | `Query[]` | Additional queries to filter and organise kanban cards |
|
|
1304
1252
|
|
|
1305
|
-
### Drive Settings
|
|
1306
|
-
|
|
1307
|
-
| Name | Type | Description |
|
|
1308
|
-
| ------------------ | -------- | ------------------------------------------------------------------------------------------------------------ |
|
|
1309
|
-
| `nameColumnId` | `string` | A string column holding the file or folder name |
|
|
1310
|
-
| `kindColumnId` | `string` | A list column whose value is `folder` or `file` |
|
|
1311
|
-
| `parentColumnId` | `string` | The containing folder's row id. Missing, null or `""` means the top level |
|
|
1312
|
-
| `fileColumnId` | `string` | A `multipleFile` column holding the one uploaded file as `{ token, fileName }`, so the original name is kept |
|
|
1313
|
-
| `sizeColumnId` | `string` | Optional. A number column written with the file size in bytes on upload |
|
|
1314
|
-
| `mimeTypeColumnId` | `string` | Optional. A string column written with the file type on upload |
|
|
1315
|
-
|
|
1316
1253
|
### Map Settings
|
|
1317
1254
|
|
|
1318
1255
|
| Name | Type | Description |
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# Drive Template
|
|
2
|
+
|
|
3
|
+
<!-- STORY -->
|
|
4
|
+
|
|
5
|
+
<hr>
|
|
6
|
+
|
|
7
|
+
A Google Drive-style folder browser over a collection whose rows are files and folders. It is a standalone template, not a DataTemplate view: a drive has one fixed data structure (`DriveSchema`), no tabs, no table and no column editing.
|
|
8
|
+
|
|
9
|
+
- **Header:** the same row DataTemplate draws above a list — `title` and `description` on the left (`text-xl font-medium` / `text-sm text-gray-500`), then a labelled Search box, the grid/list toggle, New folder and Upload as icon buttons.
|
|
10
|
+
- **Browse:** the open folder loads as one unpaged list, folders first and then files, sorted A–Z. A path above the list goes back up. Grid or list layout, remembered per collection; phones start in list.
|
|
11
|
+
- **Search:** the header Search box (debounced 400ms) searches names across the whole drive and shows each result's folder. Opening a folder from the results clears the search.
|
|
12
|
+
- **New folder:** Enter and a phone keyboard's Done both create it. An empty name, or a name already used by a folder in the same place, is refused.
|
|
13
|
+
- **Upload:** pick files with Upload, or drop files onto the drive. A drop starts uploading at once. Each file is stored at `<collectionId>/<newRowId>/<uuid>-<name>`, then its row is created with `file: [{ token, fileName }]`, `size` and `mimeType`. One failed file does not stop the rest, and the dialog cannot be closed until every file has finished.
|
|
14
|
+
- **Item menu:** Rename and Move to… (`permissions.update`), and Delete (`permissions.delete`). Move never offers the item itself or a folder inside it. Deleting a folder counts its subtree one level at a time (by `parentId`, id and folder columns only), then deletes every row below it and their storage folders. With `additionalQuery` set, a folder that holds rows outside that slice, or whose full contents cannot be read, is refused, so no row is left under a folder that no longer exists.
|
|
15
|
+
- **Preview:** images, PDFs and videos open inline with size and type; every file has Download.
|
|
16
|
+
- **Backend:** reads and writes go through `ReadQuery` / `WriteQuery` built from `devSettings`. The top level is queried as `parentId in [null, ""]`, which relies on Mongo matching a missing field against `null`.
|
|
17
|
+
|
|
18
|
+
##### Import
|
|
19
|
+
|
|
20
|
+
```js
|
|
21
|
+
import {
|
|
22
|
+
DriveTemplate,
|
|
23
|
+
DriveSchema,
|
|
24
|
+
} from "blixify-ui-web/lib/components/data/driveTemplate";
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
##### Usage
|
|
28
|
+
|
|
29
|
+
```jsx
|
|
30
|
+
const [folderId, setFolderId] = useState("");
|
|
31
|
+
|
|
32
|
+
<DriveTemplate
|
|
33
|
+
title="Team Documents"
|
|
34
|
+
description="Contracts, invoices and handbooks"
|
|
35
|
+
collectionId="team-documents"
|
|
36
|
+
devSettings={{
|
|
37
|
+
server: "mongoServer",
|
|
38
|
+
dbEndpoint: "https://api.example.com/api/data",
|
|
39
|
+
dbAPIToken: "",
|
|
40
|
+
dbUserToken: "",
|
|
41
|
+
schemaEndpoint: "",
|
|
42
|
+
imageEndpoint:
|
|
43
|
+
"https://firebasestorage.googleapis.com/v0/b/demo-bucket.firebasestorage.app/o/",
|
|
44
|
+
uploadEndpoint: "https://api.example.com/api/asset",
|
|
45
|
+
}}
|
|
46
|
+
lib={{ axios }}
|
|
47
|
+
permissions={{ create: true, update: true, delete: true }}
|
|
48
|
+
folderId={folderId}
|
|
49
|
+
onChangeFolder={setFolderId}
|
|
50
|
+
/>;
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
A member limited to a slice of the drive:
|
|
54
|
+
|
|
55
|
+
```jsx
|
|
56
|
+
<DriveTemplate
|
|
57
|
+
{...driveProps}
|
|
58
|
+
additionalQuery={[{ type: "=", queryId: "teamId", value: "team-a" }]}
|
|
59
|
+
createPrefill={[{ key: "teamId", value: "team-a" }]}
|
|
60
|
+
/>
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
##### Data structure
|
|
64
|
+
|
|
65
|
+
Every drive collection stores rows in this shape. `DriveSchema` is exported as a `DataStructure[]`, and `DRIVE_COLUMNS` holds the ids.
|
|
66
|
+
|
|
67
|
+
| Column | Type | Description |
|
|
68
|
+
| ---------- | ------------ | ------------------------------------------------------------------------ |
|
|
69
|
+
| `name` | string | The file or folder name shown in the drive |
|
|
70
|
+
| `kind` | list | `folder` or `file` |
|
|
71
|
+
| `parentId` | string | The containing folder's row id; missing, `null` or `""` is the top level |
|
|
72
|
+
| `file` | multipleFile | The one upload as `[{ token, fileName }]`; empty for a folder |
|
|
73
|
+
| `size` | number | File size in bytes, written on upload |
|
|
74
|
+
| `mimeType` | string | File type, written on upload |
|
|
75
|
+
|
|
76
|
+
##### Props
|
|
77
|
+
|
|
78
|
+
| Name | Type | Description |
|
|
79
|
+
| ----------------- | ---------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
|
|
80
|
+
| `title` | string | Heading drawn like DataTemplate's list title |
|
|
81
|
+
| `description` | string | Sub heading under the title |
|
|
82
|
+
| `collectionId` | string | The collection holding the drive's rows. Also the storage folder name for uploads |
|
|
83
|
+
| `devSettings` | `DevSettings` | Connection settings, as DataTemplate takes them: `server`, `dbEndpoint`, tokens, `imageEndpoint`, `uploadEndpoint`, `bucketName` |
|
|
84
|
+
| `lib` | `{ axios }` | The axios instance used for reads, writes, uploads and storage deletes |
|
|
85
|
+
| `additionalQuery` | `Query[]` | Added to every read, so a scoped member stays in their slice. A folder holding rows outside the slice cannot be deleted |
|
|
86
|
+
| `createPrefill` | `{ key: string; value: any }[]` | Values written onto every folder and file the drive creates |
|
|
87
|
+
| `permissions` | `{ create?: boolean; update?: boolean; delete?: boolean }` | `create` shows New folder, Upload and drop; `update` allows Rename and Move; `delete` allows Delete. All default to off |
|
|
88
|
+
| `folderId` | string | The open folder. Pass with `onChangeFolder` to keep it in the url |
|
|
89
|
+
| `onChangeFolder` | `(folderId: string) => void` | Called when a folder is opened or the path is used. Without it the drive keeps its own state |
|
|
90
|
+
| `darkMode` | boolean | Dark text, surfaces, menus and dialogs throughout the drive, as DataTemplate's `organise.darkMode` |
|
|
@@ -1,15 +1,14 @@
|
|
|
1
|
-
// INFO: the drive
|
|
2
|
-
//
|
|
1
|
+
// INFO: the drive over an in-memory collection. The story mocks its own API,
|
|
2
|
+
// so it opens without a server and the e2e spec drives it as it is.
|
|
3
3
|
|
|
4
4
|
import React, { useEffect, useRef, useState } from "react";
|
|
5
5
|
import MockAdapter from "axios-mock-adapter";
|
|
6
6
|
import axios from "axios";
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import { ExtendedTabs } from "./spaceModel";
|
|
7
|
+
import { DevSettings } from "../dataTemplate/model";
|
|
8
|
+
import { DriveTemplate } from ".";
|
|
10
9
|
|
|
11
10
|
const meta = {
|
|
12
|
-
title: "Data/
|
|
11
|
+
title: "Data/Drive Template",
|
|
13
12
|
decorators: [
|
|
14
13
|
(Story: () => React.ReactElement) => (
|
|
15
14
|
<div className="bg-gray-50 min-h-screen p-4">
|
|
@@ -24,29 +23,16 @@ const DRIVE_ENDPOINT = "http://localhost:3000/api/data";
|
|
|
24
23
|
const DRIVE_UPLOAD = "http://localhost:3000/api/asset";
|
|
25
24
|
const DRIVE_COLLECTION = "demo-drive";
|
|
26
25
|
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
name: "Drive",
|
|
38
|
-
type: "list",
|
|
39
|
-
viewType: "drive",
|
|
40
|
-
defaultTab: true,
|
|
41
|
-
driveSettings: {
|
|
42
|
-
nameColumnId: "name",
|
|
43
|
-
kindColumnId: "kind",
|
|
44
|
-
parentColumnId: "parentId",
|
|
45
|
-
fileColumnId: "file",
|
|
46
|
-
sizeColumnId: "size",
|
|
47
|
-
},
|
|
48
|
-
},
|
|
49
|
-
];
|
|
26
|
+
const DRIVE_DEV_SETTINGS: DevSettings = {
|
|
27
|
+
server: "mongoServer",
|
|
28
|
+
dbEndpoint: DRIVE_ENDPOINT,
|
|
29
|
+
dbAPIToken: "",
|
|
30
|
+
dbUserToken: "",
|
|
31
|
+
schemaEndpoint: "",
|
|
32
|
+
imageEndpoint:
|
|
33
|
+
"https://firebasestorage.googleapis.com/v0/b/demo-bucket.firebasestorage.app/o/",
|
|
34
|
+
uploadEndpoint: DRIVE_UPLOAD,
|
|
35
|
+
};
|
|
50
36
|
|
|
51
37
|
const handleBuildDriveStore = () => [
|
|
52
38
|
{ _id: "f-contracts", name: "Contracts", kind: "folder", parentId: "" },
|
|
@@ -105,7 +91,7 @@ const handleMatchQuery = (row: any, query: any[]) =>
|
|
|
105
91
|
return true;
|
|
106
92
|
});
|
|
107
93
|
|
|
108
|
-
|
|
94
|
+
const DriveStory = (storyProps: { darkMode?: boolean }) => {
|
|
109
95
|
const [folderId, setFolderId] = useState("");
|
|
110
96
|
const [mounted, setMounted] = useState(false);
|
|
111
97
|
const storeRef = useRef<any[]>(handleBuildDriveStore());
|
|
@@ -157,41 +143,35 @@ export const Drive = () => {
|
|
|
157
143
|
if (!mounted) return null;
|
|
158
144
|
|
|
159
145
|
return (
|
|
160
|
-
<div
|
|
161
|
-
|
|
146
|
+
<div
|
|
147
|
+
className={`w-full ${storyProps.darkMode ? "rounded-lg bg-gray-900 p-4" : ""}`}
|
|
148
|
+
>
|
|
149
|
+
<div
|
|
150
|
+
className={`font-semibold mb-1 ${storyProps.darkMode ? "text-white" : "text-gray-900"}`}
|
|
151
|
+
>
|
|
152
|
+
Drive
|
|
153
|
+
</div>
|
|
162
154
|
<div className="text-sm font-light mb-4 text-gray-500">
|
|
163
155
|
A folder browser over a collection where every row is a file or a
|
|
164
|
-
folder. Open folders, use the path to go
|
|
165
|
-
move and delete. Deleting a folder
|
|
156
|
+
folder, in the fixed DriveSchema shape. Open folders, use the path to go
|
|
157
|
+
back, search, create, upload, rename, move and delete. Deleting a folder
|
|
158
|
+
takes everything inside it.
|
|
166
159
|
</div>
|
|
167
|
-
<
|
|
160
|
+
<DriveTemplate
|
|
168
161
|
title="Documents"
|
|
169
|
-
|
|
162
|
+
description="Team contracts, invoices and handbooks"
|
|
170
163
|
collectionId={DRIVE_COLLECTION}
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
assetEndpoint:
|
|
178
|
-
"https://firebasestorage.googleapis.com/v0/b/demo-bucket.firebasestorage.app/o/",
|
|
179
|
-
assetUploadEndpoint: DRIVE_UPLOAD,
|
|
180
|
-
}}
|
|
181
|
-
edit={{
|
|
182
|
-
allEditable: true,
|
|
183
|
-
listEditable: true,
|
|
184
|
-
disabledUpdate: false,
|
|
185
|
-
deleteBtn: true,
|
|
186
|
-
}}
|
|
187
|
-
bareSettings={{ bareNewDTW: true, bareCompactMode: true }}
|
|
188
|
-
organise={{
|
|
189
|
-
extendedTabs: DriveTabs,
|
|
190
|
-
folderId,
|
|
191
|
-
onChangeFolder: setFolderId,
|
|
192
|
-
}}
|
|
193
|
-
handleNavigate={() => {}}
|
|
164
|
+
devSettings={DRIVE_DEV_SETTINGS}
|
|
165
|
+
lib={{ axios }}
|
|
166
|
+
permissions={{ create: true, update: true, delete: true }}
|
|
167
|
+
folderId={folderId}
|
|
168
|
+
onChangeFolder={setFolderId}
|
|
169
|
+
darkMode={storyProps.darkMode}
|
|
194
170
|
/>
|
|
195
171
|
</div>
|
|
196
172
|
);
|
|
197
173
|
};
|
|
174
|
+
|
|
175
|
+
export const Drive = () => <DriveStory />;
|
|
176
|
+
|
|
177
|
+
export const DriveDarkMode = () => <DriveStory darkMode={true} />;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getBackendComponent.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/getBackendComponent.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"getBackendComponent.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/getBackendComponent.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AA6DxB,eAAO,MAAM,uBAAuB;;;;;;;;;;CA6DnC,CAAC"}
|
|
@@ -43,6 +43,10 @@ const BACKEND_COMPONENTS = {
|
|
|
43
43
|
dir: path.join(DATA_DIR, "dataTemplate"),
|
|
44
44
|
description: "Lower-level data component driven by a Space object from the Blixify backend. Use dataWrapper instead for custom integrations.",
|
|
45
45
|
},
|
|
46
|
+
driveTemplate: {
|
|
47
|
+
dir: path.join(DATA_DIR, "driveTemplate"),
|
|
48
|
+
description: "Standalone Google Drive-style folder browser over a collection of files and folders with a fixed DriveSchema — browse, search, upload, rename, move and delete.",
|
|
49
|
+
},
|
|
46
50
|
queryForm: {
|
|
47
51
|
dir: path.join(DATA_DIR, "queryForm"),
|
|
48
52
|
description: "Standalone filter/query form component for building custom search UIs.",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getBackendComponent.js","sourceRoot":"","sources":["../../../src/mcp/tools/getBackendComponent.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"getBackendComponent.js","sourceRoot":"","sources":["../../../src/mcp/tools/getBackendComponent.ts"],"names":[],"mappings":"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"}
|