blixify-ui-web-mcp 0.1.26 → 0.1.27

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.
@@ -22,11 +22,17 @@ import {
22
22
  } from "../dataTemplate/spaceModel";
23
23
  import {
24
24
  DataWrapperTestSchema,
25
- SCROLL_TEST_API,
26
25
  SCROLL_TEST_COLLECTION,
27
26
  ServiceChecklistSchema,
28
27
  } from "./dataWrapper.fixtures";
29
28
  import { DataTemplateWrapper } from "./index";
29
+ import {
30
+ STORY_API_HOST,
31
+ STORY_NAMES,
32
+ handleBuildStoryRecords,
33
+ storyWorkspace,
34
+ useStoryBackend,
35
+ } from "./storyBackend.fixtures";
30
36
  import { StarIcon } from "@heroicons/react/24/outline";
31
37
  import {
32
38
  CheckCircleIcon,
@@ -46,18 +52,48 @@ const meta = {
46
52
 
47
53
  export default meta;
48
54
 
55
+ // INFO: served from /api/mongoData rather than /api/data, the endpoint shape
56
+ // this story has always used
57
+ const CHECKLIST_ENDPOINT = `${STORY_API_HOST}/api/mongoData`;
58
+
59
+ const handleBuildChecklistRecord = (index: number) => ({
60
+ _id: `checklist-${index}`,
61
+ clientName: STORY_NAMES[index % STORY_NAMES.length],
62
+ clientPhone: `01${2000000 + index * 1379}`,
63
+ address: `${index} Jalan Contoh, 50450 Kuala Lumpur`,
64
+ date: dayjs()
65
+ .add(index - 15, "day")
66
+ .toISOString(),
67
+ installerName: STORY_NAMES[(index + 4) % STORY_NAMES.length],
68
+ numberOfModules: 8 + (index % 12),
69
+ typeOfInverter: index % 2 === 0 ? "String Inverter" : "Microinverter",
70
+ numberOfInverters: 1 + (index % 3),
71
+ status: index % 3 === 0 ? "Approved" : "Pending",
72
+ panelsCleaned: index % 2 === 0,
73
+ cablingInspected: index % 4 !== 0,
74
+ // INFO: left empty — an image value is a file name resolved against the asset
75
+ // endpoint, and the story asset endpoint serves nothing
76
+ flowDiagramAppendix: "",
77
+ notes: index % 5 === 0 ? "Access via the rear gate." : "",
78
+ });
79
+
80
+ // INFO: the e2e CRUD spec answers this story's requests with page.route
49
81
  export const DataWrapper = () => {
50
- const [mount, setMount] = useState<boolean>(false);
82
+ const mount = useStoryBackend({
83
+ endpoint: CHECKLIST_ENDPOINT,
84
+ collections: {
85
+ "dtw-test-collection": handleBuildStoryRecords(
86
+ 30,
87
+ handleBuildChecklistRecord,
88
+ ),
89
+ },
90
+ yieldToE2E: true,
91
+ });
51
92
  const dataRefreshRef: any = useRef(null);
52
93
  const [statusFilter] = useState<string>("all");
53
94
  const [viewType, setViewType] = useState<"list" | "read" | "update">("list");
54
95
  const [selectedId, setSelectedId] = useState<string | undefined>(undefined);
55
96
  const [listLayout, setListLayout] = useState("table");
56
- const dtwBaseUrl = "http://localhost:3000";
57
-
58
- useEffect(() => {
59
- setMount(true);
60
- }, []);
61
97
 
62
98
  useEffect(() => {
63
99
  if (mount && dataRefreshRef.current) {
@@ -158,15 +194,7 @@ export const DataWrapper = () => {
158
194
  id={selectedId}
159
195
  collectionId={"dtw-test-collection"}
160
196
  schema={ServiceChecklistSchema}
161
- workspace={{
162
- apiEndpointType: "mongoDB",
163
- apiEndpoint: `${dtwBaseUrl}/api/mongoData`,
164
- apiEndpointToken: "",
165
- apiUserToken: "",
166
- assetEndpoint:
167
- "https://firebasestorage.googleapis.com/v0/b/demo-bucket.appspot.com/o/",
168
- assetUploadEndpoint: `${dtwBaseUrl}/api/asset`,
169
- }}
197
+ workspace={storyWorkspace(CHECKLIST_ENDPOINT)}
170
198
  edit={{
171
199
  allEditable: true,
172
200
  disabledUpdate: false,
@@ -608,22 +636,42 @@ const DTWGroupTestSchema = [
608
636
  },
609
637
  ];
610
638
 
611
- // ═══════════════════════════════════════════════════════════════════════════════
612
- // INFO: Standalone story — renders NewTable, NewList, NewKanban directly with
613
- // inline mock data. No backend required. Uses a simple "Tasks" schema that
614
- // exercises list/date/number types to show off the new components.
615
- // ═══════════════════════════════════════════════════════════════════════════════
639
+ const WORK_ORDER_STATUSES = [
640
+ "Not Completed",
641
+ "Completed",
642
+ "In Progress",
643
+ "Cancelled",
644
+ ];
645
+
646
+ const handleBuildWorkOrderRecord = (index: number) => {
647
+ const start = dayjs().subtract(index, "day");
648
+ return {
649
+ _id: `work-order-${index}`,
650
+ title: `Work Order ${String(index).padStart(3, "0")}`,
651
+ status: WORK_ORDER_STATUSES[index % WORK_ORDER_STATUSES.length],
652
+ operationDay: (index % 4) + 1,
653
+ startDate: start.toISOString(),
654
+ endDate: start.add(6, "hour").toISOString(),
655
+ totalFlight: 2 + (index % 6),
656
+ totalHours: 3 + (index % 5),
657
+ };
658
+ };
616
659
 
660
+ // INFO: the e2e CRUD spec answers this story's requests with page.route
617
661
  export const DTWGroupTest = () => {
618
- const [mount, setMount] = useState(false);
662
+ const mount = useStoryBackend({
663
+ collections: {
664
+ [SCROLL_TEST_COLLECTION]: handleBuildStoryRecords(
665
+ 24,
666
+ handleBuildWorkOrderRecord,
667
+ ),
668
+ },
669
+ yieldToE2E: true,
670
+ });
619
671
  const dataRefreshRef: any = useRef(null);
620
672
  const [viewType, setViewType] = useState<"list" | "read" | "update">("list");
621
673
  const [selectedId, setSelectedId] = useState<string | undefined>(undefined);
622
674
 
623
- useEffect(() => {
624
- setMount(true);
625
- }, []);
626
-
627
675
  if (!mount) return <Loading />;
628
676
 
629
677
  return (
@@ -631,8 +679,8 @@ export const DTWGroupTest = () => {
631
679
  <div className="font-semibold mb-1 text-gray-900">DTW Group Test</div>
632
680
  <div className="text-sm font-light mb-4 text-gray-500">
633
681
  Multi-tab + multi-group schema demo. List + read view renders sections
634
- by tabId / groupId; Create / Update / Delete write to the configured
635
- backend.
682
+ by tabId / groupId; Create / Update / Delete write to the in-memory
683
+ story backend.
636
684
  </div>
637
685
  <DataTemplateWrapper
638
686
  ref={dataRefreshRef}
@@ -641,14 +689,7 @@ export const DTWGroupTest = () => {
641
689
  id={selectedId}
642
690
  collectionId={SCROLL_TEST_COLLECTION}
643
691
  schema={DTWGroupTestSchema}
644
- workspace={{
645
- apiEndpointType: "mongoDB",
646
- apiEndpoint: SCROLL_TEST_API,
647
- apiEndpointToken: "",
648
- apiUserToken: "",
649
- assetEndpoint: "",
650
- assetUploadEndpoint: SCROLL_TEST_API.replace("/data", "/asset"),
651
- }}
692
+ workspace={storyWorkspace()}
652
693
  edit={{
653
694
  allEditable: true,
654
695
  disabledUpdate: false,
@@ -702,13 +743,9 @@ DTWGroupTest.storyName = "DTW Group Test";
702
743
  // SECTION: Offline demo — DTW with no backend required
703
744
  // ===================================================================================
704
745
 
705
- // INFO: every other DTW story points at a localhost dev API, so opening Storybook without
706
- // that server running shows an empty skeleton table. This story instead serves DTW from an
707
- // in-memory array via axios-mock-adapter, installed on the shared axios instance that
708
- // DataTemplateWrapper passes down as lib.axios. Nothing here reaches the network, so the
709
- // story is the reference for reviewing DTW behaviour (including viewSettings.readDrawer) without
710
- // any setup. The .invalid TLD is reserved by RFC 2606 and can never resolve, so a missed
711
- // mock fails loudly instead of silently hitting a real host.
746
+ // INFO: serves DTW from an in-memory array via axios-mock-adapter, installed on the shared
747
+ // axios instance that DataTemplateWrapper passes down as lib.axios. Its own mock rather than
748
+ // the story backend, because it numbers new records (refNo) the way this demo shows them.
712
749
  const DRAWER_DEMO_COLLECTION = "dtw-drawer-demo";
713
750
 
714
751
  const DRAWER_DEMO_ENDPOINT = "https://demo.blixify.invalid/api/data";
@@ -937,15 +974,20 @@ const handleInstallDrawerDemoMock = (store: any[]) => {
937
974
  // state wiring is identical — handleNavigate still just sets type + id, and the wrapper
938
975
  // decides whether a read means "swap the page" or "open the panel".
939
976
  export const DataWrapperDrawerTest = () => {
940
- const [mount, setMount] = useState<boolean>(false);
977
+ const mount = useStoryBackend({
978
+ collections: {
979
+ "dtw-test-collection": handleBuildStoryRecords(12, (index) => ({
980
+ _id: `checklist-${index}`,
981
+ clientName: STORY_NAMES[index % STORY_NAMES.length],
982
+ clientPhone: `01${2000000 + index * 1379}`,
983
+ address: `${index} Jalan Contoh, 50450 Kuala Lumpur`,
984
+ })),
985
+ },
986
+ yieldToE2E: true,
987
+ });
941
988
  const dataRefreshRef: any = useRef(null);
942
989
  const [viewType, setViewType] = useState<"list" | "read" | "update">("list");
943
990
  const [selectedId, setSelectedId] = useState<string | undefined>(undefined);
944
- const dtwBaseUrl = "http://localhost:3000";
945
-
946
- useEffect(() => {
947
- setMount(true);
948
- }, []);
949
991
 
950
992
  const handleNavigate = (type: any, id: any) => {
951
993
  setViewType(type);
@@ -973,15 +1015,7 @@ export const DataWrapperDrawerTest = () => {
973
1015
  collectionId={"dtw-test-collection"}
974
1016
  schema={DataWrapperTestSchema}
975
1017
  viewSettings={{ readDrawer: {} }}
976
- workspace={{
977
- apiEndpointType: "mongoDB",
978
- apiEndpoint: `${dtwBaseUrl}/api/data`,
979
- apiEndpointToken: "",
980
- apiUserToken: "",
981
- assetEndpoint:
982
- "https://firebasestorage.googleapis.com/v0/b/demo-bucket.firebasestorage.app/o/",
983
- assetUploadEndpoint: `${dtwBaseUrl}/api/asset`,
984
- }}
1018
+ workspace={storyWorkspace()}
985
1019
  edit={{
986
1020
  allEditable: true,
987
1021
  disabledUpdate: false,
@@ -1009,13 +1043,9 @@ DataWrapperDrawerTest.storyName = "DTW Drawer Test";
1009
1043
  // SECTION: Offline demo — DTW with no backend required
1010
1044
  // ===================================================================================
1011
1045
 
1012
- // INFO: every other DTW story points at a localhost dev API, so opening Storybook without
1013
- // that server running shows an empty skeleton table. This story instead serves DTW from an
1014
- // in-memory array via axios-mock-adapter, installed on the shared axios instance that
1015
- // DataTemplateWrapper passes down as lib.axios. Nothing here reaches the network, so the
1016
- // story is the reference for reviewing DTW behaviour (including viewSettings.readDrawer) without
1017
- // any setup. The .invalid TLD is reserved by RFC 2606 and can never resolve, so a missed
1018
- // mock fails loudly instead of silently hitting a real host.
1046
+ // INFO: serves DTW from an in-memory array via axios-mock-adapter, installed on the shared
1047
+ // axios instance that DataTemplateWrapper passes down as lib.axios. Its own mock rather than
1048
+ // the story backend, because it numbers new records (refNo) the way this demo shows them.
1019
1049
 
1020
1050
  export const DTWDrawerDemo = () => {
1021
1051
  const [mount, setMount] = useState<boolean>(false);
@@ -1167,16 +1197,20 @@ const DTWScrollTestSchema = [
1167
1197
  ];
1168
1198
 
1169
1199
  export const DTWScrollTest = () => {
1170
- const [mount, setMount] = useState(false);
1200
+ // INFO: enough rows for several scroll pages in every view type
1201
+ const mount = useStoryBackend({
1202
+ collections: {
1203
+ [SCROLL_TEST_COLLECTION]: handleBuildStoryRecords(
1204
+ 120,
1205
+ handleBuildWorkOrderRecord,
1206
+ ),
1207
+ },
1208
+ });
1171
1209
  const dataRefreshRef: any = useRef(null);
1172
1210
  const [viewType, setViewType] = useState<"list" | "read" | "update">("list");
1173
1211
  const [selectedId, setSelectedId] = useState<string | undefined>(undefined);
1174
1212
  const [viewId, setViewId] = useState<string>("scroll_list");
1175
1213
 
1176
- useEffect(() => {
1177
- setMount(true);
1178
- }, []);
1179
-
1180
1214
  // INFO: no second handleRefresh effect — ReadQueryHoc auto-fetches on mount,
1181
1215
  // a manual refresh here would only cause a visible double-loading flash.
1182
1216
 
@@ -1205,9 +1239,8 @@ export const DTWScrollTest = () => {
1205
1239
  <div className="w-full">
1206
1240
  <div className="font-semibold mb-1 text-gray-900">DTW Scroll Test</div>
1207
1241
  <div className="text-sm font-light mb-4 text-gray-500">
1208
- Scroll pagination smoke test against a local dev API. Requires the
1209
- matching dev server to be running so DTW can pull real rows across list,
1210
- feeds, and bare view types.
1242
+ Scroll pagination across list, feeds and bare view types, over 120 rows
1243
+ from the in-memory story backend.
1211
1244
  </div>
1212
1245
  <DataTemplateWrapper
1213
1246
  ref={dataRefreshRef}
@@ -1216,14 +1249,7 @@ export const DTWScrollTest = () => {
1216
1249
  id={selectedId}
1217
1250
  collectionId={SCROLL_TEST_COLLECTION}
1218
1251
  schema={DTWScrollTestSchema}
1219
- workspace={{
1220
- apiEndpointType: "mongoDB",
1221
- apiEndpoint: SCROLL_TEST_API,
1222
- apiEndpointToken: "",
1223
- apiUserToken: "",
1224
- assetEndpoint: "",
1225
- assetUploadEndpoint: SCROLL_TEST_API.replace("/data", "/asset"),
1226
- }}
1252
+ workspace={storyWorkspace()}
1227
1253
  edit={{ allEditable: false }}
1228
1254
  bareSettings={{
1229
1255
  bareCompactMode: true,
@@ -0,0 +1,223 @@
1
+ import { Transition } from "@headlessui/react";
2
+ import axios from "axios";
3
+ import React, { useState } from "react";
4
+ import { Button } from "../../action/button";
5
+ import { StorySection } from "../../storyUtils";
6
+ import { DataStructure } from "../dataTemplate/model";
7
+ import {
8
+ FlexFilter as FlexFilterComponent,
9
+ renderFlexFilterConditions,
10
+ } from ".";
11
+ import { FlexFilterData } from "./model";
12
+ import { Toggle } from "../../action/toggle";
13
+ import { DevSettings } from "../dataTemplate/model";
14
+ import { Loading } from "../../display/loading";
15
+ import {
16
+ STORY_API_ENDPOINT,
17
+ STORY_NAMES,
18
+ useStoryBackend,
19
+ } from "../dataWrapper/storyBackend.fixtures";
20
+
21
+ const meta = { title: "Data/Flex Filter" };
22
+ export default meta;
23
+
24
+ const CREW_COLLECTION = "demo-crew";
25
+
26
+ // INFO: one column per filter type, including a reference column whose options
27
+ // load from the story backend
28
+ const sampleSchema: DataStructure[] = [
29
+ { id: "title", name: "Title", type: "string" },
30
+ { id: "verified", name: "Verified", type: "boolean" },
31
+ {
32
+ id: "status",
33
+ name: "Status",
34
+ type: "list",
35
+ listSelection: ["Not Completed", "In Progress", "Completed", "Cancelled"],
36
+ },
37
+ {
38
+ id: "tags",
39
+ name: "Tags",
40
+ type: "multipleList",
41
+ listSelection: ["Urgent", "Follow Up", "Warranty", "Inspection"],
42
+ },
43
+ { id: "startDate", name: "Clock In", type: "date" },
44
+ { id: "operationDay", name: "Operation Day", type: "number" },
45
+ {
46
+ id: "crewId",
47
+ name: "Crew Lead",
48
+ type: "reference",
49
+ referenceLabel: "name",
50
+ referenceSpaceId: CREW_COLLECTION,
51
+ },
52
+ ];
53
+
54
+ const devSettings: DevSettings = {
55
+ server: "mongoServer",
56
+ dbEndpoint: STORY_API_ENDPOINT,
57
+ imageEndpoint: "",
58
+ uploadEndpoint: "",
59
+ dbAPIToken: "",
60
+ dbUserToken: "",
61
+ schemaEndpoint: "",
62
+ bucketName: "",
63
+ organisationMembers: [],
64
+ };
65
+
66
+ export const FlexFilter = () => {
67
+ const mount = useStoryBackend({
68
+ collections: {
69
+ [CREW_COLLECTION]: STORY_NAMES.map((name, index) => ({
70
+ _id: `crew-${index + 1}`,
71
+ name,
72
+ })),
73
+ },
74
+ });
75
+ const [bareFilters, setBareFilters] = useState<FlexFilterData[]>([
76
+ { id: "bare-init", columnId: "", operator: "=", value: undefined },
77
+ ]);
78
+
79
+ const [autoFilters, setAutoFilters] = useState<FlexFilterData[]>([
80
+ { id: "auto-init", columnId: "", operator: "=", value: undefined },
81
+ ]);
82
+
83
+ const [modalFilters, setModalFilters] = useState<FlexFilterData[]>([
84
+ { id: "modal-init", columnId: "", operator: "=", value: undefined },
85
+ ]);
86
+
87
+ const [addCompFilters, setAddCompFilters] = useState<FlexFilterData[]>([
88
+ { id: "addcomp-init", columnId: "", operator: "=", value: undefined },
89
+ ]);
90
+
91
+ const bareQueryConditions = renderFlexFilterConditions(
92
+ bareFilters,
93
+ sampleSchema,
94
+ );
95
+ const autoQueryConditions = renderFlexFilterConditions(
96
+ autoFilters,
97
+ sampleSchema,
98
+ );
99
+ const modalQueryConditions = renderFlexFilterConditions(
100
+ modalFilters,
101
+ sampleSchema,
102
+ );
103
+ const addCompQueryConditions = renderFlexFilterConditions(
104
+ addCompFilters,
105
+ sampleSchema,
106
+ );
107
+
108
+ if (!mount) return <Loading />;
109
+
110
+ return (
111
+ <div className="flex flex-col space-y-12">
112
+ <StorySection
113
+ title="Variant: bare"
114
+ description="Raw filter panel with no wrapper. Consumer renders their own container."
115
+ >
116
+ <div className="flex flex-col">
117
+ <div className="max-w-[700px]">
118
+ <FlexFilterComponent
119
+ structure={sampleSchema}
120
+ filters={bareFilters}
121
+ onChange={setBareFilters}
122
+ devSettings={devSettings}
123
+ dbModule={axios}
124
+ variant="bare"
125
+ lib={{ Transition }}
126
+ />
127
+ </div>
128
+ <div className="mt-4 p-4 bg-gray-50 rounded-lg border">
129
+ <p className="text-sm font-semibold mb-2">
130
+ Generated Query Conditions ({bareQueryConditions.length})
131
+ </p>
132
+ <pre className="text-xs whitespace-pre-wrap">
133
+ {JSON.stringify(bareQueryConditions, null, 2)}
134
+ </pre>
135
+ </div>
136
+ </div>
137
+ </StorySection>
138
+
139
+ <StorySection
140
+ title="Variant: auto (PopUp on desktop, Modal on mobile)"
141
+ description="Uses PopUp on md+ screens and Modal on mobile. Click the funnel icon to open."
142
+ >
143
+ <div className="flex flex-col w-96 max-w-96">
144
+ <div className="flex gap-x-3 w-ful">
145
+ <div className="h-12 bg-gray-100 rounded-lg flex-1"></div>
146
+ <FlexFilterComponent
147
+ structure={sampleSchema}
148
+ filters={autoFilters}
149
+ onChange={setAutoFilters}
150
+ devSettings={devSettings}
151
+ dbModule={axios}
152
+ variant="auto"
153
+ lib={{ Transition }}
154
+ />
155
+ </div>
156
+ <div className="mt-4 p-4 bg-gray-50 rounded-lg border">
157
+ <p className="text-sm font-semibold mb-2">
158
+ Generated Query Conditions ({autoQueryConditions.length})
159
+ </p>
160
+ <pre className="text-xs whitespace-pre-wrap">
161
+ {JSON.stringify(autoQueryConditions, null, 2)}
162
+ </pre>
163
+ </div>
164
+ </div>
165
+ </StorySection>
166
+ <StorySection
167
+ title="Variant: modal with custom CTA"
168
+ description="Modal variant triggered by a custom button instead of the default funnel icon."
169
+ >
170
+ <div className="flex flex-col">
171
+ <FlexFilterComponent
172
+ structure={sampleSchema}
173
+ filters={modalFilters}
174
+ onChange={setModalFilters}
175
+ devSettings={devSettings}
176
+ dbModule={axios}
177
+ variant="modal"
178
+ lib={{ Transition }}
179
+ ctaComp={<Button text="Filters" type="normal" size="small" />}
180
+ />
181
+ <div className="mt-4 p-4 bg-gray-50 rounded-lg border">
182
+ <p className="text-sm font-semibold mb-2">
183
+ Generated Query Conditions ({modalQueryConditions.length})
184
+ </p>
185
+ <pre className="text-xs whitespace-pre-wrap">
186
+ {JSON.stringify(modalQueryConditions, null, 2)}
187
+ </pre>
188
+ </div>
189
+ </div>
190
+ </StorySection>
191
+
192
+ <StorySection
193
+ title="Variant: bare with additional filter components"
194
+ description="bareListFilterAddComponent renders extra filter inputs above the flex filter rows."
195
+ >
196
+ <div className="flex flex-col">
197
+ <div className="max-w-[700px]">
198
+ <FlexFilterComponent
199
+ structure={sampleSchema}
200
+ filters={addCompFilters}
201
+ onChange={setAddCompFilters}
202
+ devSettings={devSettings}
203
+ dbModule={axios}
204
+ variant="bare"
205
+ lib={{ Transition }}
206
+ bareListFilterAddComponent={[
207
+ <Toggle text="Show all events" value={true} direction="left" />,
208
+ ]}
209
+ />
210
+ </div>
211
+ <div className="mt-4 p-4 bg-gray-50 rounded-lg border">
212
+ <p className="text-sm font-semibold mb-2">
213
+ Generated Query Conditions ({addCompQueryConditions.length})
214
+ </p>
215
+ <pre className="text-xs whitespace-pre-wrap">
216
+ {JSON.stringify(addCompQueryConditions, null, 2)}
217
+ </pre>
218
+ </div>
219
+ </div>
220
+ </StorySection>
221
+ </div>
222
+ );
223
+ };
@@ -3,6 +3,10 @@ import { CheckCircleIcon } from "@heroicons/react/24/outline";
3
3
  import React, { useState } from "react";
4
4
  import { Modal as ModalImpl } from ".";
5
5
  import { DataTemplateWrapper } from "../../data/dataWrapper";
6
+ import {
7
+ storyWorkspace,
8
+ useStoryBackend,
9
+ } from "../../data/dataWrapper/storyBackend.fixtures";
6
10
  import { Notification } from "../notification";
7
11
 
8
12
  const meta = { title: "Display/Modal" };
@@ -10,6 +14,7 @@ export default meta;
10
14
 
11
15
  export const Modal = () => {
12
16
  const [open, setOpen] = useState(true);
17
+ const mount = useStoryBackend({ collections: { "modal-updates": [] } });
13
18
  const notification = (
14
19
  <Notification
15
20
  icon={<CheckCircleIcon className="w-10 h-10 text-primary-600" />}
@@ -24,6 +29,8 @@ export const Modal = () => {
24
29
  />
25
30
  );
26
31
 
32
+ if (!mount) return null;
33
+
27
34
  return (
28
35
  <ModalImpl
29
36
  title="Modal Title"
@@ -46,11 +53,7 @@ export const Modal = () => {
46
53
  },
47
54
  { id: "startDate", type: "date", name: "Clock In" },
48
55
  ]}
49
- workspace={{
50
- apiEndpoint: "http://localhost:3000/api/data",
51
- assetEndpoint:
52
- "https://firebasestorage.googleapis.com/v0/b/demo-bucket.appspot.com/o/",
53
- }}
56
+ workspace={storyWorkspace()}
54
57
  additionalQuery={[]}
55
58
  organise={{
56
59
  breadcrumbType: "button",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blixify-ui-web-mcp",
3
- "version": "0.1.26",
3
+ "version": "0.1.27",
4
4
  "license": "MIT",
5
5
  "main": "lib/mcp/server.js",
6
6
  "bin": {