blixify-ui-web-mcp 0.1.19 → 0.1.21

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 (47) hide show
  1. package/lib/components/action/iconButton/iconButton.stories.tsx +11 -2
  2. package/lib/components/auth/signUp/signUp.stories.tsx +39 -1
  3. package/lib/components/chart/statsCard/README.md +24 -0
  4. package/lib/components/chart/statsCard/statsCard.stories.tsx +68 -0
  5. package/lib/components/chat/chatBase/chatBase.stories.tsx +1 -1
  6. package/lib/components/data/dataGraph/dataGraph.stories.tsx +5 -5
  7. package/lib/components/data/dataTemplate/README.md +204 -85
  8. package/lib/components/data/dataTemplate/dataTemplate.stories.tsx +307 -295
  9. package/lib/components/data/dataTemplate/drive.stories.tsx +197 -0
  10. package/lib/components/data/dataWrapper/README.md +109 -22
  11. package/lib/components/data/dataWrapper/dataWrapper.bareHooks.stories.tsx +951 -0
  12. package/lib/components/data/dataWrapper/dataWrapper.edit.stories.tsx +356 -5
  13. package/lib/components/data/dataWrapper/dataWrapper.view.stories.tsx +79 -5
  14. package/lib/components/display/calendar/calendar.stories.tsx +1 -1
  15. package/lib/components/display/detailList/README.md +11 -10
  16. package/lib/components/display/detailList/detailList.stories.tsx +16 -3
  17. package/lib/components/display/feeds/README.md +3 -3
  18. package/lib/components/display/feeds/feeds.stories.tsx +3 -3
  19. package/lib/components/display/filePreview/filePreview.stories.tsx +111 -0
  20. package/lib/components/display/modal/README.md +3 -0
  21. package/lib/components/display/modal/modal.stories.tsx +50 -1
  22. package/lib/components/display/newCalendar/README.md +0 -6
  23. package/lib/components/display/newCalendar/newCalendar.stories.tsx +1 -1
  24. package/lib/components/display/newFeeds/README.md +1 -5
  25. package/lib/components/display/newFeeds/newFeeds.stories.tsx +3 -3
  26. package/lib/components/display/newKanban/README.md +0 -7
  27. package/lib/components/display/newList/README.md +1 -4
  28. package/lib/components/display/newTable/README.md +29 -9
  29. package/lib/components/display/newTable/newTable.stories.tsx +120 -9
  30. package/lib/components/display/tag/README.md +1 -1
  31. package/lib/components/display/tag/tag.stories.tsx +7 -0
  32. package/lib/components/input/markdown/markdown.stories.tsx +3 -1
  33. package/lib/components/input/uploadInput/uploadInput.stories.tsx +41 -0
  34. package/lib/components/navigation/leftNav/leftNav.stories.tsx +175 -0
  35. package/lib/components/navigation/tabs/tabs.stories.tsx +23 -0
  36. package/lib/components/template/calendarView/calendarView.stories.tsx +4 -4
  37. package/lib/components/template/chatDashboard/chatDashboard.stories.tsx +2 -2
  38. package/lib/mcp/tools/getBackendComponent.d.ts.map +1 -1
  39. package/lib/mcp/tools/getBackendComponent.js +7 -3
  40. package/lib/mcp/tools/getBackendComponent.js.map +1 -1
  41. package/lib/mcp/tools/suggestTemplate.js +3 -3
  42. package/lib/mcp/tools/suggestTemplate.js.map +1 -1
  43. package/package.json +1 -1
  44. package/lib/components/data/dataTemplate/dataModule.stories.tsx +0 -191
  45. package/lib/components/data/dataWrapper/dataWrapper.consumer.stories.tsx +0 -2125
  46. package/lib/components/data/dataWrapper/dataWrapper.utils.stories.tsx +0 -576
  47. package/lib/components/data/flexFilter/flexFilter.stories.tsx +0 -171
@@ -1,576 +0,0 @@
1
- // INFO: DTW plumbing — flex filters, hidden columns, persisted view state and
2
- // SSE live updates.
3
-
4
- import React, { useEffect, useRef, useState } from "react";
5
- import { Button } from "../../action/button";
6
- import { Loading } from "../../display/loading";
7
- import { MeraqueWorkOrderSchema, meraqueDevSettings } from "../testSchema";
8
- import { DataTemplateWrapper } from "./index";
9
-
10
- const meta = {
11
- title: "Data/Data Wrapper/Utils",
12
- decorators: [
13
- (Story: () => React.ReactElement) => (
14
- <div className="bg-white min-h-screen p-4">
15
- <Story />
16
- </div>
17
- ),
18
- ],
19
- };
20
-
21
- export default meta;
22
-
23
- // INFO: SSE live-update smoke test.
24
- // Requires a local SocketWrapper SSE endpoint at http://localhost:3000/api/live.
25
- // bareSocketName="dtw-test-collection" → list room.
26
- // bareSocketName="dtw-test-collection-{id}" → document room (wired automatically
27
- // when the consumer passes the room in bareSettings on the read/update DTW).
28
- //
29
- // Expected behaviour:
30
- // List view — insert prepends a row; update patches in-place; delete removes.
31
- // Read view — update pushes new data into the form; delete navigates back to list.
32
- // isLive indicator (green dot) appears when EventSource connects.
33
- // isLiveOffline indicator (yellow dot) appears when navigator goes offline.
34
- const DTW_SSE_BASE_URL = "http://localhost:3000";
35
-
36
- const DTW_SSE_COLLECTION = "dtw-test-collection";
37
-
38
- const DTWSseLiveSchema = [
39
- { id: "clientName", name: "Client Name", type: "string" as const },
40
- {
41
- id: "status",
42
- name: "Status",
43
- type: "list" as const,
44
- listSelection: ["Draft", "Active", "Closed"],
45
- optional: true,
46
- },
47
- {
48
- id: "createdAt",
49
- name: "Created At",
50
- type: "date" as const,
51
- optional: true,
52
- },
53
- ];
54
-
55
- // ═══════════════════════════════════════════════════════════════════════════════
56
- // INFO: Standalone story — renders NewTable, NewList, NewKanban directly with
57
- // inline mock data. No backend required. Uses a simple "Tasks" schema that
58
- // exercises list/date/number types to show off the new components.
59
- // ═══════════════════════════════════════════════════════════════════════════════
60
-
61
- export const DTWSseLive = () => {
62
- const [mount, setMount] = useState(false);
63
- const dataRefreshRef: any = useRef(null);
64
- const [viewType, setViewType] = useState<"list" | "read" | "update">("list");
65
- const [selectedId, setSelectedId] = useState<string | undefined>(undefined);
66
-
67
- useEffect(() => {
68
- setMount(true);
69
- }, []);
70
-
71
- const handleNavigate = (type: any, id: any) => {
72
- setViewType(type);
73
- setSelectedId(id);
74
- };
75
-
76
- if (!mount) return <Loading />;
77
-
78
- // INFO: room name follows SocketWrapper convention —
79
- // list view → "{collection}"
80
- // read/update view → "{collection}-{id}"
81
- const bareSocketName =
82
- viewType === "list"
83
- ? DTW_SSE_COLLECTION
84
- : `${DTW_SSE_COLLECTION}-${selectedId}`;
85
-
86
- return (
87
- <div className="w-full">
88
- <div className="font-semibold mb-1 text-gray-900">
89
- DTW — SSE Live Updates
90
- </div>
91
- <div className="text-sm font-light mb-4 text-gray-500">
92
- Smoke test for <code>bareSocketName</code> +{" "}
93
- <code>workspace.sseEndpoint</code>. Requires a local SocketWrapper SSE
94
- endpoint at <code>{DTW_SSE_BASE_URL}/api/live</code>. The green dot in
95
- the table header appears when the EventSource connects. Open a second
96
- tab and mutate a record — the change should arrive in real-time without
97
- a refresh.
98
- </div>
99
- <DataTemplateWrapper
100
- ref={dataRefreshRef}
101
- title="Live Collection"
102
- type={viewType}
103
- id={selectedId}
104
- collectionId={DTW_SSE_COLLECTION}
105
- schema={DTWSseLiveSchema}
106
- workspace={{
107
- apiEndpointType: "mongoDB",
108
- apiEndpoint: `${DTW_SSE_BASE_URL}/api/data`,
109
- apiEndpointToken: "",
110
- apiUserToken: "",
111
- assetEndpoint: "",
112
- assetUploadEndpoint: `${DTW_SSE_BASE_URL}/api/asset`,
113
- // INFO: sseEndpoint flows through parseWorkspaceSettings →
114
- // devSettings.sseEndpoint → buildSSEUrl → EventSource
115
- sseEndpoint: `${DTW_SSE_BASE_URL}/api/live`,
116
- }}
117
- edit={{
118
- allEditable: true,
119
- disabledUpdate: false,
120
- disableBatchUpdate: false,
121
- deleteBtn: true,
122
- }}
123
- bareSettings={{
124
- bareCompactMode: true,
125
- bareNewDTW: true,
126
- // INFO: room switches between list room and document room depending on view type
127
- bareSocketName,
128
- bareUpdateActionComponent:
129
- viewType === "read"
130
- ? (data) => (
131
- <Button
132
- type="normal"
133
- text="Update"
134
- onClick={() => {
135
- setSelectedId(data._id);
136
- setViewType("update");
137
- }}
138
- />
139
- )
140
- : undefined,
141
- }}
142
- organise={{
143
- sort: { sortId: "createdAt", type: "desc" as const },
144
- breadcrumbType: "button",
145
- }}
146
- handleNavigate={handleNavigate}
147
- limit={10}
148
- />
149
- </div>
150
- );
151
- };
152
- DTWSseLive.storyName = "DTW SSE Live";
153
-
154
- export const DTWFlexFilters = () => {
155
- const [mount, setMount] = useState(false);
156
- const dataRef = useRef<any>(null);
157
- const [viewType, setViewType] = useState<"list" | "read" | "update">("list");
158
- const [selectedId, setSelectedId] = useState<string | undefined>(undefined);
159
- const [listMobileView, setListMobileView] = useState(false);
160
-
161
- useEffect(() => {
162
- setMount(true);
163
- }, []);
164
-
165
- // INFO: set mobile view when browser width is smaller than 640px
166
- useEffect(() => {
167
- const handleResize = () => {
168
- setListMobileView(window.innerWidth < 640);
169
- };
170
- handleResize();
171
- window.addEventListener("resize", handleResize);
172
- return () => window.removeEventListener("resize", handleResize);
173
- }, []);
174
-
175
- const handleNavigate = (type: any, id: any) => {
176
- setViewType(type);
177
- setSelectedId(id);
178
- };
179
-
180
- if (!mount) return <Loading />;
181
-
182
- return (
183
- <div className="w-full min-h-screen">
184
- <div className="font-semibold mb-1 text-gray-900">
185
- DTW - With Flex Filters & Floating Action
186
- </div>
187
- <DataTemplateWrapper
188
- ref={dataRef}
189
- title="Flex Filters"
190
- description=""
191
- type={viewType}
192
- id={selectedId}
193
- collectionId={"meraque-order"}
194
- schema={MeraqueWorkOrderSchema}
195
- workspace={meraqueDevSettings}
196
- edit={{
197
- allEditable: true,
198
- disabledUpdate: false,
199
- disableBatchUpdate: false,
200
- deleteBtn: true,
201
- }}
202
- organise={{
203
- breadcrumbType: "button",
204
- }}
205
- bareSettings={{
206
- bareCompactMode: true,
207
- bareNewDTW: true,
208
- bareListMobileView: listMobileView,
209
- bareFlexFilters: true,
210
- bareListMobileFloatingSearch: true,
211
- bareListTablePinColumns: { left: ["title"] },
212
- }}
213
- handleNavigate={handleNavigate}
214
- limit={10}
215
- />
216
- </div>
217
- );
218
- };
219
- DTWFlexFilters.storyName = "DTW Flex Filters";
220
-
221
- // INFO: Story used exclusively by the hide-columns e2e block. Shares the
222
- // dtw-test-collection alias so the spec's existing API mocks apply, and adds
223
- // one developer-hidden column to prove users can never toggle it back on.
224
- const DataWrapperHideColumnSchema = [
225
- {
226
- id: "clientName",
227
- name: "Client Name",
228
- type: "string" as const,
229
- optional: true,
230
- },
231
- {
232
- id: "clientPhone",
233
- name: "Client Phone",
234
- type: "string" as const,
235
- optional: true,
236
- },
237
- { id: "address", name: "Address", type: "string" as const, optional: true },
238
- {
239
- id: "internalRef",
240
- name: "Internal Ref",
241
- type: "string" as const,
242
- optional: true,
243
- hide: true,
244
- },
245
- ];
246
-
247
- // INFO: a deliberately wide schema — the view settings panel has to stay usable
248
- // on a collection with dozens of fields (Space runs to 24+), so the column list
249
- // scrolls and the search box earns its place
250
- const DataWrapperWideSchema = [
251
- ...DataWrapperHideColumnSchema,
252
- { id: "email", name: "Email", type: "email" as const, optional: true },
253
- { id: "city", name: "City", type: "string" as const, optional: true },
254
- { id: "state", name: "State", type: "string" as const, optional: true },
255
- { id: "postcode", name: "Postcode", type: "string" as const, optional: true },
256
- { id: "country", name: "Country", type: "string" as const, optional: true },
257
- {
258
- id: "status",
259
- name: "Status",
260
- type: "list" as const,
261
- listSelection: ["New", "Active", "On Hold", "Closed"],
262
- listSelectionColour: ["blue", "green", "yellow", "red"],
263
- optional: true,
264
- },
265
- {
266
- id: "priority",
267
- name: "Priority",
268
- type: "list" as const,
269
- listSelection: ["Low", "Medium", "High"],
270
- listSelectionColour: ["green", "yellow", "red"],
271
- optional: true,
272
- },
273
- { id: "owner", name: "Owner", type: "string" as const, optional: true },
274
- { id: "team", name: "Team", type: "string" as const, optional: true },
275
- { id: "source", name: "Source", type: "string" as const, optional: true },
276
- {
277
- id: "contractValue",
278
- name: "Contract Value",
279
- type: "number" as const,
280
- optional: true,
281
- },
282
- {
283
- id: "outstanding",
284
- name: "Outstanding Amount",
285
- type: "number" as const,
286
- optional: true,
287
- },
288
- {
289
- id: "startDate",
290
- name: "Start Date",
291
- type: "date" as const,
292
- optional: true,
293
- },
294
- { id: "endDate", name: "End Date", type: "date" as const, optional: true },
295
- {
296
- id: "lastContact",
297
- name: "Last Contact",
298
- type: "date" as const,
299
- optional: true,
300
- },
301
- {
302
- id: "followUpDate",
303
- name: "Follow Up Date",
304
- type: "date" as const,
305
- optional: true,
306
- },
307
- {
308
- id: "verified",
309
- name: "Verified",
310
- type: "boolean" as const,
311
- optional: true,
312
- },
313
- {
314
- id: "subscribed",
315
- name: "Subscribed",
316
- type: "boolean" as const,
317
- optional: true,
318
- },
319
- { id: "remarks", name: "Remarks", type: "textArea" as const, optional: true },
320
- {
321
- id: "internalNotes",
322
- name: "Internal Notes",
323
- type: "textArea" as const,
324
- optional: true,
325
- },
326
- ];
327
-
328
- export const DataWrapperHideColumnTest = () => {
329
- const [mount, setMount] = useState<boolean>(false);
330
- const dataRefreshRef: any = useRef(null);
331
- const [viewType, setViewType] = useState<"list" | "read" | "update">("list");
332
- const [selectedId, setSelectedId] = useState<string | undefined>(undefined);
333
- const dtwBaseUrl = "http://localhost:3000";
334
-
335
- useEffect(() => {
336
- setMount(true);
337
- }, []);
338
-
339
- const handleNavigate = (type: any, id: any) => {
340
- setViewType(type);
341
- setSelectedId(id);
342
- };
343
-
344
- if (!mount) {
345
- return <Loading />;
346
- }
347
-
348
- return (
349
- <div className="w-full">
350
- <div className="font-semibold mb-1 text-gray-900">
351
- DTW Hide Column Test
352
- </div>
353
- <div className="text-sm font-light mb-4 text-gray-500">
354
- Exercises bareSettings.bareViewSettings — the client-only column hiding
355
- control for bare DTWs. Internal Ref is hidden by the schema and must
356
- never appear in the toggle list.
357
- </div>
358
- <DataTemplateWrapper
359
- ref={dataRefreshRef}
360
- title="Checklist"
361
- type={viewType}
362
- id={selectedId}
363
- collectionId={"dtw-test-collection"}
364
- schema={DataWrapperHideColumnSchema}
365
- workspace={{
366
- apiEndpointType: "mongoDB",
367
- apiEndpoint: `${dtwBaseUrl}/api/data`,
368
- apiEndpointToken: "",
369
- apiUserToken: "",
370
- assetEndpoint:
371
- "https://firebasestorage.googleapis.com/v0/b/verdant-dev.firebasestorage.app/o/",
372
- assetUploadEndpoint: `${dtwBaseUrl}/api/asset`,
373
- }}
374
- edit={{
375
- allEditable: true,
376
- disabledUpdate: false,
377
- disableBatchUpdate: false,
378
- deleteBtn: true,
379
- }}
380
- bareSettings={{
381
- bareCompactMode: true,
382
- bareNewDTW: true,
383
- bareOffline: false,
384
- bareViewSettings: true,
385
- bareFlexFilters: true,
386
- }}
387
- organise={{
388
- breadcrumbType: "button",
389
- persistViewState: "session",
390
- }}
391
- handleNavigate={handleNavigate}
392
- limit={10}
393
- />
394
- </div>
395
- );
396
- };
397
- DataWrapperHideColumnTest.storyName = "DTW Hide Column Test";
398
-
399
- // INFO: Real-data smoke test for scroll pagination. Points the storybook DTW
400
- // at an external dev API (defaults to localhost:3000) and pulls real rows so
401
- // we can manually verify scroll pagination across all view types. Configure
402
- // SCROLL_TEST_API + SCROLL_TEST_COLLECTION below for whichever live backend
403
- // is running locally.
404
-
405
- export const DTWPersistView = () => {
406
- const [mount, setMount] = useState(false);
407
- const dataRef = useRef<any>(null);
408
- const [viewType, setViewType] = useState<"list" | "read" | "update">("list");
409
- const [selectedId, setSelectedId] = useState<string | undefined>(undefined);
410
-
411
- useEffect(() => {
412
- setMount(true);
413
- }, []);
414
-
415
- const handleNavigate = (type: any, id: any) => {
416
- setViewType(type);
417
- setSelectedId(id);
418
- };
419
-
420
- if (!mount) return <Loading />;
421
-
422
- return (
423
- <div className="w-full min-h-screen">
424
- <div className="font-semibold mb-1 text-gray-900">
425
- DTW - Persisted View
426
- </div>
427
- <p className="text-sm text-gray-500">
428
- Persist filters, sort, page index, searched value and user hidden
429
- columns in session storage / local storage
430
- </p>
431
- <DataTemplateWrapper
432
- ref={dataRef}
433
- title="Persisted View"
434
- description=""
435
- type={viewType}
436
- id={selectedId}
437
- collectionId={"meraque-order"}
438
- schema={MeraqueWorkOrderSchema}
439
- workspace={meraqueDevSettings}
440
- edit={{
441
- allEditable: true,
442
- disabledUpdate: false,
443
- disableBatchUpdate: false,
444
- deleteBtn: true,
445
- }}
446
- organise={{
447
- breadcrumbType: "button",
448
- persistViewState: "session",
449
- paginationType: "scroll",
450
- }}
451
- bareSettings={{
452
- bareCompactMode: true,
453
- bareNewDTW: true,
454
- bareViewSettings: true,
455
- bareFlexFilters: true,
456
- bareListMobileFloatingSearch: true,
457
- }}
458
- handleNavigate={handleNavigate}
459
- limit={10}
460
- />
461
- </div>
462
- );
463
- };
464
- DTWPersistView.storyName = "DTW Persisted View";
465
-
466
- export const DataWrapperViewSettingsWide = () => {
467
- const [mount, setMount] = useState<boolean>(false);
468
- const dataRefreshRef: any = useRef(null);
469
- const [viewType, setViewType] = useState<"list" | "read" | "update">("list");
470
- const [selectedId, setSelectedId] = useState<string | undefined>(undefined);
471
- // INFO: the same panel behaves two ways — per user by default, or schema level
472
- // once onChangeHide / onChangeDrag are wired (Space, Sun Luan)
473
- const [schemaMode, setSchemaMode] = useState<boolean>(false);
474
- const [model, setModel] = useState<any[]>(DataWrapperWideSchema);
475
- const [lastChange, setLastChange] = useState<string>("none");
476
- const dtwBaseUrl = "http://localhost:3000";
477
-
478
- useEffect(() => {
479
- setMount(true);
480
- }, []);
481
-
482
- const handleNavigate = (type: any, id: any) => {
483
- setViewType(type);
484
- setSelectedId(id);
485
- };
486
-
487
- const handleChangeHide = (updatedModel: any[]) => {
488
- setModel(updatedModel);
489
- setLastChange(
490
- `hide → ${
491
- updatedModel
492
- .filter((eachColumn) => eachColumn.hide)
493
- .map((eachColumn) => eachColumn.id)
494
- .join(", ") || "(none)"
495
- }`,
496
- );
497
- };
498
-
499
- const handleChangeDrag = (dragId: string, dropId: string) => {
500
- setLastChange(`order → ${dragId} before ${dropId}`);
501
- };
502
-
503
- const handleToggleMode = () => {
504
- setModel(DataWrapperWideSchema);
505
- setLastChange("none");
506
- setSchemaMode((previous) => !previous);
507
- };
508
-
509
- if (!mount) return <Loading />;
510
-
511
- return (
512
- <div className="w-full">
513
- <div className="font-semibold mb-1 text-gray-900">
514
- DTW View Settings — 23 columns
515
- </div>
516
- <div className="text-sm font-light mb-3 text-gray-500">
517
- The shape a Space collection actually has. Open the sliders icon: the
518
- column list scrolls with a shade on the cut edge, the search box narrows
519
- it, the handle reorders, and Sort and Rows per page stay pinned below.
520
- On a phone the same panel opens as a modal.
521
- </div>
522
- <div className="mb-4 flex flex-row items-center gap-x-3">
523
- <Button
524
- type={schemaMode ? "normal" : "light"}
525
- size="small"
526
- text={schemaMode ? "Schema mode" : "Per user mode"}
527
- onClick={handleToggleMode}
528
- />
529
- <span className="text-xs text-gray-500">
530
- {schemaMode
531
- ? "onChangeHide / onChangeDrag are wired — the change is handed back to write to the schema for everyone"
532
- : "no callbacks — the hide and the order stay in this user's persisted view state"}
533
- </span>
534
- </div>
535
- {schemaMode && (
536
- <div className="mb-4 text-xs text-primary-600">
537
- last change: {lastChange}
538
- </div>
539
- )}
540
- <DataTemplateWrapper
541
- // INFO: a fresh instance per mode so the panel re-reads the model
542
- key={schemaMode ? "schema" : "user"}
543
- ref={dataRefreshRef}
544
- title="Wide Collection"
545
- type={viewType}
546
- id={selectedId}
547
- collectionId={"dtw-test-collection"}
548
- schema={schemaMode ? model : DataWrapperWideSchema}
549
- workspace={{
550
- apiEndpointType: "mongoDB",
551
- apiEndpoint: `${dtwBaseUrl}/api/data`,
552
- apiEndpointToken: "",
553
- apiUserToken: "",
554
- assetEndpoint: "",
555
- assetUploadEndpoint: `${dtwBaseUrl}/api/asset`,
556
- }}
557
- edit={{ allEditable: true, deleteBtn: true }}
558
- bareSettings={{
559
- bareCompactMode: true,
560
- bareNewDTW: true,
561
- bareFlexFilters: true,
562
- }}
563
- organise={{
564
- breadcrumbType: "button",
565
- persistViewState: "session",
566
- ...(schemaMode
567
- ? { onChangeHide: handleChangeHide, onChangeDrag: handleChangeDrag }
568
- : {}),
569
- }}
570
- handleNavigate={handleNavigate}
571
- limit={10}
572
- />
573
- </div>
574
- );
575
- };
576
- DataWrapperViewSettingsWide.storyName = "DTW View Settings";