@fluid-app/rep-sdk 0.1.9 → 0.1.11

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 (85) hide show
  1. package/dist/ContactsScreen-CB6l0Lf1.mjs +24 -0
  2. package/dist/ContactsScreen-CB6l0Lf1.mjs.map +1 -0
  3. package/dist/ContactsScreen-UfrdOORn.cjs +41 -0
  4. package/dist/ContactsScreen-UfrdOORn.cjs.map +1 -0
  5. package/dist/CoreScreenPlaceholder-D93ZYKt2.mjs +32 -0
  6. package/dist/CoreScreenPlaceholder-D93ZYKt2.mjs.map +1 -0
  7. package/dist/CoreScreenPlaceholder-DBZqxDsK.cjs +38 -0
  8. package/dist/CoreScreenPlaceholder-DBZqxDsK.cjs.map +1 -0
  9. package/dist/CustomersScreen-BEar6Leg.mjs +24 -0
  10. package/dist/CustomersScreen-BEar6Leg.mjs.map +1 -0
  11. package/dist/CustomersScreen-DXXPpWZW.cjs +41 -0
  12. package/dist/CustomersScreen-DXXPpWZW.cjs.map +1 -0
  13. package/dist/MessagingScreen-CsDvKkLC.cjs +1458 -0
  14. package/dist/MessagingScreen-CsDvKkLC.cjs.map +1 -0
  15. package/dist/MessagingScreen-xO9YudMx.mjs +1285 -0
  16. package/dist/MessagingScreen-xO9YudMx.mjs.map +1 -0
  17. package/dist/OrdersScreen-DB1v051q.mjs +24 -0
  18. package/dist/OrdersScreen-DB1v051q.mjs.map +1 -0
  19. package/dist/OrdersScreen-fcxcnpNU.cjs +41 -0
  20. package/dist/OrdersScreen-fcxcnpNU.cjs.map +1 -0
  21. package/dist/ProductsScreen-BaEng3LB.cjs +41 -0
  22. package/dist/ProductsScreen-BaEng3LB.cjs.map +1 -0
  23. package/dist/ProductsScreen-nVDsY6kf.mjs +24 -0
  24. package/dist/ProductsScreen-nVDsY6kf.mjs.map +1 -0
  25. package/dist/chunk-D1SwGrFN.mjs +27 -0
  26. package/dist/index.cjs +3397 -2850
  27. package/dist/index.cjs.map +1 -1
  28. package/dist/index.d.cts +1026 -955
  29. package/dist/index.d.cts.map +1 -0
  30. package/dist/index.d.mts +2207 -0
  31. package/dist/index.d.mts.map +1 -0
  32. package/dist/index.mjs +2921 -0
  33. package/dist/index.mjs.map +1 -0
  34. package/package.json +8 -8
  35. package/dist/ContactsScreen-7RGAMMGN.cjs +0 -18
  36. package/dist/ContactsScreen-7RGAMMGN.cjs.map +0 -1
  37. package/dist/ContactsScreen-XKZE5HTP.js +0 -5
  38. package/dist/ContactsScreen-XKZE5HTP.js.map +0 -1
  39. package/dist/CustomersScreen-BBQ3YHI4.js +0 -5
  40. package/dist/CustomersScreen-BBQ3YHI4.js.map +0 -1
  41. package/dist/CustomersScreen-EMGCQ2PV.cjs +0 -18
  42. package/dist/CustomersScreen-EMGCQ2PV.cjs.map +0 -1
  43. package/dist/MessagingScreen-I3GVOGKY.js +0 -4
  44. package/dist/MessagingScreen-I3GVOGKY.js.map +0 -1
  45. package/dist/MessagingScreen-ZRD4WEOE.cjs +0 -17
  46. package/dist/MessagingScreen-ZRD4WEOE.cjs.map +0 -1
  47. package/dist/OrdersScreen-ANDGND6F.js +0 -5
  48. package/dist/OrdersScreen-ANDGND6F.js.map +0 -1
  49. package/dist/OrdersScreen-NNE6OSRS.cjs +0 -18
  50. package/dist/OrdersScreen-NNE6OSRS.cjs.map +0 -1
  51. package/dist/ProductsScreen-5PMFLPWS.js +0 -5
  52. package/dist/ProductsScreen-5PMFLPWS.js.map +0 -1
  53. package/dist/ProductsScreen-ALQYD7ID.cjs +0 -18
  54. package/dist/ProductsScreen-ALQYD7ID.cjs.map +0 -1
  55. package/dist/chunk-2RIDFKS3.cjs +0 -19
  56. package/dist/chunk-2RIDFKS3.cjs.map +0 -1
  57. package/dist/chunk-424PT5DM.js +0 -21
  58. package/dist/chunk-424PT5DM.js.map +0 -1
  59. package/dist/chunk-4LTH3NNT.js +0 -16
  60. package/dist/chunk-4LTH3NNT.js.map +0 -1
  61. package/dist/chunk-4PHR2M6A.js +0 -14
  62. package/dist/chunk-4PHR2M6A.js.map +0 -1
  63. package/dist/chunk-EKMZ4NIA.cjs +0 -19
  64. package/dist/chunk-EKMZ4NIA.cjs.map +0 -1
  65. package/dist/chunk-HDQ2JUQT.cjs +0 -24
  66. package/dist/chunk-HDQ2JUQT.cjs.map +0 -1
  67. package/dist/chunk-HFPPHLOO.cjs +0 -19
  68. package/dist/chunk-HFPPHLOO.cjs.map +0 -1
  69. package/dist/chunk-HMOWQQDX.cjs +0 -19
  70. package/dist/chunk-HMOWQQDX.cjs.map +0 -1
  71. package/dist/chunk-JXEED3FK.js +0 -16
  72. package/dist/chunk-JXEED3FK.js.map +0 -1
  73. package/dist/chunk-LU42Y4H3.cjs +0 -1597
  74. package/dist/chunk-LU42Y4H3.cjs.map +0 -1
  75. package/dist/chunk-NGOEPTWZ.js +0 -16
  76. package/dist/chunk-NGOEPTWZ.js.map +0 -1
  77. package/dist/chunk-NNZKBXNB.cjs +0 -16
  78. package/dist/chunk-NNZKBXNB.cjs.map +0 -1
  79. package/dist/chunk-SYZUEL6B.js +0 -1538
  80. package/dist/chunk-SYZUEL6B.js.map +0 -1
  81. package/dist/chunk-TB6OK3WH.js +0 -16
  82. package/dist/chunk-TB6OK3WH.js.map +0 -1
  83. package/dist/index.d.ts +0 -2138
  84. package/dist/index.js +0 -2536
  85. package/dist/index.js.map +0 -1
package/dist/index.js DELETED
@@ -1,2536 +0,0 @@
1
- import { themes_exports, useFluidApi, transformManifestToRepAppData, useThemeContext, useFluidAuthContext, MessagingScreen } from './chunk-SYZUEL6B.js';
2
- export { ApiError, DEFAULT_AUTH_URL, DEFAULT_SDK_WIDGET_REGISTRY, FluidAuthProvider, FluidProvider, FluidThemeProvider, MessagingScreen, buildThemeDefinition, createDefaultAuthRedirect, createFluidClient, createFluidFileUploader, getActiveThemeId, isApiError, messagingScreenPropertySchema, normalizeComponentTree, toNavigationItem, toScreenDefinition, transformManifestToRepAppData, transformThemes, useFluidApi, useFluidAuthContext, useFluidContext, useMessagingAuth, useMessagingConfig, useThemeContext } from './chunk-SYZUEL6B.js';
3
- import { ContactsScreen } from './chunk-NGOEPTWZ.js';
4
- export { ContactsScreen, contactsScreenPropertySchema } from './chunk-NGOEPTWZ.js';
5
- import { OrdersScreen } from './chunk-TB6OK3WH.js';
6
- export { OrdersScreen, ordersScreenPropertySchema } from './chunk-TB6OK3WH.js';
7
- import { CustomersScreen } from './chunk-JXEED3FK.js';
8
- export { CustomersScreen, customersScreenPropertySchema } from './chunk-JXEED3FK.js';
9
- import { ProductsScreen } from './chunk-4LTH3NNT.js';
10
- export { ProductsScreen, productsScreenPropertySchema } from './chunk-4LTH3NNT.js';
11
- import { CoreScreenPlaceholder } from './chunk-4PHR2M6A.js';
12
- import './chunk-424PT5DM.js';
13
- import * as React2 from 'react';
14
- import { createContext, memo, forwardRef, useContext, useRef, useEffect, useMemo, useState, useCallback } from 'react';
15
- import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
16
- import { useQuery } from '@tanstack/react-query';
17
- export { AUTH_CONSTANTS, STORAGE_KEYS, URL_PARAMS, USER_TYPES, cleanTokenFromUrl, clearTokens, decodeToken, extractAllTokensFromUrl, extractCompanyTokenFromUrl, extractTokenFromUrl, getStoredToken, getTokenExpiration, getTokenTimeRemaining, hasStoredToken, hasTokenInUrl, isTokenExpired, isUserType, isValidToken, storeToken, validateToken } from '@fluid-app/auth';
18
- export { WIDGET_TYPE_NAMES, assertDefined, assertNever, isWidgetType, isWidgetTypeName, sectionLayoutConfig } from '@fluid-app/rep-core/types';
19
- export { AlertWidget, CalendarWidget, CarouselWidget, CatchUpWidget, ChartWidget, ContainerWidget, EmbedWidget, ImageWidget, LayoutWidget, ListWidget, MySiteWidget, NestedWidget, QuickShareWidget, RecentActivityWidget, SpacerWidget, TableWidget, TextWidget, ToDoWidget, VideoWidget, alertWidgetPropertySchema, calendarWidgetPropertySchema, carouselWidgetPropertySchema, catchUpWidgetPropertySchema, chartWidgetPropertySchema, containerWidgetPropertySchema, embedWidgetPropertySchema, imageWidgetPropertySchema, layoutWidgetPropertySchema, listWidgetPropertySchema, mySiteWidgetPropertySchema, nestedWidgetPropertySchema, quickShareWidgetPropertySchema, recentActivityWidgetPropertySchema, spacerWidgetPropertySchema, tableWidgetPropertySchema, textWidgetPropertySchema, toDoWidgetPropertySchema, videoWidgetPropertySchema, widgetPropertySchemas } from '@fluid-app/rep-widgets/widgets';
20
- export { createScreen, createWidgetFromShareable, createWidgetRegistry, groupChildrenByColumn } from '@fluid-app/rep-core/widget-utils';
21
- export { PROPERTY_FIELD_TYPES, gapValues, isPropertyFieldType } from '@fluid-app/rep-core/registries';
22
- import { AppShellLayout } from '@fluid-app/rep-core/shell/AppShellLayout';
23
- import { useThemeMode, ThemeModeProvider } from '@fluid-app/rep-core/shell/ThemeModeContext';
24
- export { ThemeModeProvider, getThemeModeAttribute, useThemeMode } from '@fluid-app/rep-core/shell/ThemeModeContext';
25
- import { normalizeSlug, getSystemNavigationBySection, isSystemNavigationItem } from '@fluid-app/rep-core/navigation/system-navigation-items';
26
- import { ScreenHeader } from '@fluid-app/rep-core/shell/ScreenHeader';
27
- import { ScreenHeaderProvider } from '@fluid-app/rep-core/shell/ScreenHeaderContext';
28
- import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
29
- import { faEllipsis } from '@fortawesome/pro-regular-svg-icons/faEllipsis';
30
- import { faXmark } from '@fortawesome/pro-regular-svg-icons/faXmark';
31
- import { RepIcon } from '@fluid-app/rep-core/components/RepIcon';
32
- import { SidebarMenu, SidebarGroupLabel, SidebarMenuItem, SidebarMenuButton, useSidebar } from '@fluid-app/rep-core/shell/sidebar';
33
- import { resolveTheme, applyTheme, removeAllThemes } from '@fluid-app/rep-core/theme';
34
- import { faBars } from '@fortawesome/pro-regular-svg-icons/faBars';
35
- import { faSun } from '@fortawesome/pro-regular-svg-icons/faSun';
36
- import { faMoon } from '@fortawesome/pro-regular-svg-icons/faMoon';
37
- import { faTableCellsLarge } from '@fortawesome/pro-regular-svg-icons/faTableCellsLarge';
38
- import { DataAwareWidget } from '@fluid-app/rep-core/data-sources/DataAwareWidget';
39
- import { useRegistry } from '@fluid-app/rep-widgets/contexts';
40
-
41
- // src/types/page-template.ts
42
- var PAGE_CATEGORIES = {
43
- CORE: "core",
44
- COMMERCE: "commerce",
45
- COMMUNICATION: "communication",
46
- DATA: "data",
47
- CUSTOM: "custom"
48
- };
49
-
50
- // src/registries/page-template-registry.ts
51
- var PageTemplateRegistryImpl = class {
52
- templates = /* @__PURE__ */ new Map();
53
- categories = [];
54
- constructor() {
55
- this.categories = [
56
- { id: PAGE_CATEGORIES.CORE, label: "Core Features", icon: "star" },
57
- {
58
- id: PAGE_CATEGORIES.COMMERCE,
59
- label: "Commerce",
60
- icon: "shopping-cart"
61
- },
62
- {
63
- id: PAGE_CATEGORIES.COMMUNICATION,
64
- label: "Communication",
65
- icon: "message-circle"
66
- },
67
- {
68
- id: PAGE_CATEGORIES.DATA,
69
- label: "Data & Analytics",
70
- icon: "bar-chart"
71
- },
72
- { id: PAGE_CATEGORIES.CUSTOM, label: "Custom", icon: "puzzle" }
73
- ];
74
- }
75
- /**
76
- * Register a new page template.
77
- * @throws Error if a template with the same ID already exists
78
- */
79
- register(template) {
80
- if (this.templates.has(template.id)) {
81
- throw new Error(
82
- `Page template with ID "${template.id}" is already registered`
83
- );
84
- }
85
- this.templates.set(template.id, template);
86
- }
87
- /**
88
- * Unregister a page template by ID.
89
- * Core templates cannot be unregistered.
90
- * @returns true if the template was removed, false if it didn't exist or is a core template
91
- */
92
- unregister(id) {
93
- const template = this.templates.get(id);
94
- if (!template) {
95
- return false;
96
- }
97
- if (template.isCore) {
98
- console.warn(
99
- `Cannot unregister core page template "${id}". Core templates are required.`
100
- );
101
- return false;
102
- }
103
- return this.templates.delete(id);
104
- }
105
- /**
106
- * Get a page template by ID.
107
- */
108
- get(id) {
109
- return this.templates.get(id);
110
- }
111
- /**
112
- * Get all page templates in a specific category.
113
- */
114
- getByCategory(category) {
115
- return Array.from(this.templates.values()).filter(
116
- (t) => t.category === category
117
- );
118
- }
119
- /**
120
- * List all registered page templates.
121
- */
122
- listAll() {
123
- return Array.from(this.templates.values());
124
- }
125
- /**
126
- * List all core page templates (isCore: true).
127
- */
128
- listCore() {
129
- return Array.from(this.templates.values()).filter((t) => t.isCore);
130
- }
131
- /**
132
- * List all non-core page templates.
133
- */
134
- listOptional() {
135
- return Array.from(this.templates.values()).filter((t) => !t.isCore);
136
- }
137
- /**
138
- * List all registered categories.
139
- */
140
- listCategories() {
141
- return [...this.categories];
142
- }
143
- /**
144
- * Add a custom category.
145
- */
146
- addCategory(category) {
147
- if (this.categories.some((c) => c.id === category.id)) {
148
- console.warn(`Category with ID "${category.id}" already exists`);
149
- return;
150
- }
151
- this.categories.push(category);
152
- }
153
- /**
154
- * Check if a template exists by ID.
155
- */
156
- has(id) {
157
- return this.templates.has(id);
158
- }
159
- /**
160
- * Get the count of registered templates.
161
- */
162
- get size() {
163
- return this.templates.size;
164
- }
165
- /**
166
- * Clear all non-core templates.
167
- * Useful for testing or resetting the registry.
168
- */
169
- clearNonCore() {
170
- for (const [id, template] of this.templates) {
171
- if (!template.isCore) {
172
- this.templates.delete(id);
173
- }
174
- }
175
- }
176
- };
177
- var PageTemplateRegistry = new PageTemplateRegistryImpl();
178
-
179
- // src/core/resolve-pages.ts
180
- function applyOverrides(componentTree, overrides) {
181
- if (!overrides.length) {
182
- return [...componentTree];
183
- }
184
- const overrideMap = new Map(overrides.map((o) => [o.widget_id, o.props]));
185
- return componentTree.map(
186
- (widget) => applyWidgetOverrides(widget, overrideMap)
187
- );
188
- }
189
- function applyWidgetOverrides(widget, overrideMap) {
190
- const override = widget.id ? overrideMap.get(widget.id) : void 0;
191
- const children = widget.props.children;
192
- const hasChildren = Array.isArray(children) && children.length > 0;
193
- if (!override && !hasChildren) {
194
- return widget;
195
- }
196
- const newProps = override ? { ...widget.props, ...override } : { ...widget.props };
197
- if (hasChildren) {
198
- newProps.children = children.map(
199
- (child) => applyWidgetOverrides(child, overrideMap)
200
- );
201
- }
202
- return { ...widget, props: newProps };
203
- }
204
- function resolvePageReference(ref) {
205
- const template = PageTemplateRegistry.get(ref.page_template_id);
206
- if (!template) {
207
- console.warn(
208
- `Page template "${ref.page_template_id}" not found in registry`
209
- );
210
- return void 0;
211
- }
212
- const componentTree = ref.overrides ? applyOverrides(template.component_tree, ref.overrides) : [...template.component_tree];
213
- return {
214
- id: ref.screen_id,
215
- slug: template.slug,
216
- name: template.name,
217
- component_tree: componentTree
218
- };
219
- }
220
- function resolveNavigationPages(navigation) {
221
- const localScreenIds = new Set(navigation.screens.map((s) => s.id));
222
- const result = [...navigation.screens];
223
- if (navigation.page_refs) {
224
- for (const ref of navigation.page_refs) {
225
- if (localScreenIds.has(ref.screen_id)) {
226
- continue;
227
- }
228
- const screen = resolvePageReference(ref);
229
- if (screen) {
230
- result.push(screen);
231
- }
232
- }
233
- }
234
- return result;
235
- }
236
- function getAvailablePageTemplates() {
237
- return PageTemplateRegistry.listAll();
238
- }
239
- function getCorePageTemplates() {
240
- return PageTemplateRegistry.listCore();
241
- }
242
- function getOptionalPageTemplates() {
243
- return PageTemplateRegistry.listOptional();
244
- }
245
- function validateNavigationPages(navigation) {
246
- const corePages = PageTemplateRegistry.listCore();
247
- const referencedTemplateIds = new Set(
248
- navigation.page_refs?.map((ref) => ref.page_template_id) ?? []
249
- );
250
- const missingCorePages = corePages.filter((page) => !referencedTemplateIds.has(page.id)).map((page) => page.id);
251
- return {
252
- valid: missingCorePages.length === 0,
253
- missingCorePages
254
- };
255
- }
256
- var EMPTY_TEMPLATES = [];
257
- var PageTemplateContext = createContext(
258
- null
259
- );
260
- function PageTemplateProvider({
261
- children,
262
- templates = EMPTY_TEMPLATES
263
- }) {
264
- const registeredIds = useRef([]);
265
- const templateKey = templates.map((t) => t.id).join(",");
266
- useEffect(() => {
267
- const registered = [];
268
- for (const template of templates) {
269
- if (!PageTemplateRegistry.has(template.id)) {
270
- try {
271
- PageTemplateRegistry.register(template);
272
- registered.push(template.id);
273
- } catch (error) {
274
- console.warn(
275
- `Failed to register page template "${template.id}":`,
276
- error
277
- );
278
- }
279
- }
280
- }
281
- registeredIds.current = registered;
282
- return () => {
283
- for (const id of registeredIds.current) {
284
- PageTemplateRegistry.unregister(id);
285
- }
286
- registeredIds.current = [];
287
- };
288
- }, [templateKey]);
289
- const contextValue = useMemo(
290
- () => ({
291
- resolvePages: resolveNavigationPages,
292
- listTemplates: () => PageTemplateRegistry.listAll(),
293
- getTemplate: (id) => PageTemplateRegistry.get(id),
294
- hasTemplate: (id) => PageTemplateRegistry.has(id)
295
- }),
296
- []
297
- );
298
- return /* @__PURE__ */ jsx(PageTemplateContext.Provider, { value: contextValue, children });
299
- }
300
- function usePageTemplates() {
301
- const context = useContext(PageTemplateContext);
302
- if (!context) {
303
- throw new Error(
304
- "usePageTemplates must be used within a PageTemplateProvider"
305
- );
306
- }
307
- return context;
308
- }
309
- function useResolvedPages(navigation) {
310
- const { resolvePages } = usePageTemplates();
311
- return useMemo(() => resolvePages(navigation), [resolvePages, navigation]);
312
- }
313
- var PROFILE_QUERY_KEY = ["fluid", "profile"];
314
- function useFluidProfile() {
315
- const api = useFluidApi();
316
- return useQuery({
317
- queryKey: PROFILE_QUERY_KEY,
318
- queryFn: () => api.profile.get()
319
- });
320
- }
321
- function systemSetTimeoutZero(callback) {
322
- setTimeout(callback, 0);
323
- }
324
- function matchQuery(filters, query) {
325
- const {
326
- type = "all",
327
- exact,
328
- fetchStatus,
329
- predicate,
330
- queryKey,
331
- stale
332
- } = filters;
333
- if (queryKey) {
334
- if (exact) {
335
- if (query.queryHash !== hashQueryKeyByOptions(queryKey, query.options)) {
336
- return false;
337
- }
338
- } else if (!partialMatchKey(query.queryKey, queryKey)) {
339
- return false;
340
- }
341
- }
342
- if (type !== "all") {
343
- const isActive = query.isActive();
344
- if (type === "active" && !isActive) {
345
- return false;
346
- }
347
- if (type === "inactive" && isActive) {
348
- return false;
349
- }
350
- }
351
- if (typeof stale === "boolean" && query.isStale() !== stale) {
352
- return false;
353
- }
354
- if (fetchStatus && fetchStatus !== query.state.fetchStatus) {
355
- return false;
356
- }
357
- if (predicate && !predicate(query)) {
358
- return false;
359
- }
360
- return true;
361
- }
362
- function hashQueryKeyByOptions(queryKey, options) {
363
- const hashFn = options?.queryKeyHashFn || hashKey;
364
- return hashFn(queryKey);
365
- }
366
- function hashKey(queryKey) {
367
- return JSON.stringify(
368
- queryKey,
369
- (_, val) => isPlainObject(val) ? Object.keys(val).sort().reduce((result, key) => {
370
- result[key] = val[key];
371
- return result;
372
- }, {}) : val
373
- );
374
- }
375
- function partialMatchKey(a, b) {
376
- if (a === b) {
377
- return true;
378
- }
379
- if (typeof a !== typeof b) {
380
- return false;
381
- }
382
- if (a && b && typeof a === "object" && typeof b === "object") {
383
- return Object.keys(b).every((key) => partialMatchKey(a[key], b[key]));
384
- }
385
- return false;
386
- }
387
- function isPlainObject(o) {
388
- if (!hasObjectPrototype(o)) {
389
- return false;
390
- }
391
- const ctor = o.constructor;
392
- if (ctor === void 0) {
393
- return true;
394
- }
395
- const prot = ctor.prototype;
396
- if (!hasObjectPrototype(prot)) {
397
- return false;
398
- }
399
- if (!prot.hasOwnProperty("isPrototypeOf")) {
400
- return false;
401
- }
402
- if (Object.getPrototypeOf(o) !== Object.prototype) {
403
- return false;
404
- }
405
- return true;
406
- }
407
- function hasObjectPrototype(o) {
408
- return Object.prototype.toString.call(o) === "[object Object]";
409
- }
410
-
411
- // ../../../node_modules/.pnpm/@tanstack+query-core@5.90.12/node_modules/@tanstack/query-core/build/modern/notifyManager.js
412
- var defaultScheduler = systemSetTimeoutZero;
413
- function createNotifyManager() {
414
- let queue = [];
415
- let transactions = 0;
416
- let notifyFn = (callback) => {
417
- callback();
418
- };
419
- let batchNotifyFn = (callback) => {
420
- callback();
421
- };
422
- let scheduleFn = defaultScheduler;
423
- const schedule = (callback) => {
424
- if (transactions) {
425
- queue.push(callback);
426
- } else {
427
- scheduleFn(() => {
428
- notifyFn(callback);
429
- });
430
- }
431
- };
432
- const flush = () => {
433
- const originalQueue = queue;
434
- queue = [];
435
- if (originalQueue.length) {
436
- scheduleFn(() => {
437
- batchNotifyFn(() => {
438
- originalQueue.forEach((callback) => {
439
- notifyFn(callback);
440
- });
441
- });
442
- });
443
- }
444
- };
445
- return {
446
- batch: (callback) => {
447
- let result;
448
- transactions++;
449
- try {
450
- result = callback();
451
- } finally {
452
- transactions--;
453
- if (!transactions) {
454
- flush();
455
- }
456
- }
457
- return result;
458
- },
459
- /**
460
- * All calls to the wrapped function will be batched.
461
- */
462
- batchCalls: (callback) => {
463
- return (...args) => {
464
- schedule(() => {
465
- callback(...args);
466
- });
467
- };
468
- },
469
- schedule,
470
- /**
471
- * Use this method to set a custom notify function.
472
- * This can be used to for example wrap notifications with `React.act` while running tests.
473
- */
474
- setNotifyFunction: (fn) => {
475
- notifyFn = fn;
476
- },
477
- /**
478
- * Use this method to set a custom function to batch notifications together into a single tick.
479
- * By default React Query will use the batch function provided by ReactDOM or React Native.
480
- */
481
- setBatchNotifyFunction: (fn) => {
482
- batchNotifyFn = fn;
483
- },
484
- setScheduler: (fn) => {
485
- scheduleFn = fn;
486
- }
487
- };
488
- }
489
- var notifyManager = createNotifyManager();
490
-
491
- // ../../../node_modules/.pnpm/@tanstack+query-persist-client-core@5.91.11/node_modules/@tanstack/query-persist-client-core/build/modern/createPersister.js
492
- var PERSISTER_KEY_PREFIX = "tanstack-query";
493
- function experimental_createQueryPersister({
494
- storage: storage2,
495
- buster = "",
496
- maxAge = 1e3 * 60 * 60 * 24,
497
- serialize = JSON.stringify,
498
- deserialize = JSON.parse,
499
- prefix = PERSISTER_KEY_PREFIX,
500
- refetchOnRestore = true,
501
- filters
502
- }) {
503
- function isExpiredOrBusted(persistedQuery) {
504
- if (persistedQuery.state.dataUpdatedAt) {
505
- const queryAge = Date.now() - persistedQuery.state.dataUpdatedAt;
506
- const expired = queryAge > maxAge;
507
- const busted = persistedQuery.buster !== buster;
508
- if (expired || busted) {
509
- return true;
510
- }
511
- return false;
512
- }
513
- return true;
514
- }
515
- async function retrieveQuery(queryHash, afterRestoreMacroTask) {
516
- if (storage2 != null) {
517
- const storageKey = `${prefix}-${queryHash}`;
518
- try {
519
- const storedData = await storage2.getItem(storageKey);
520
- if (storedData) {
521
- const persistedQuery = await deserialize(storedData);
522
- if (isExpiredOrBusted(persistedQuery)) {
523
- await storage2.removeItem(storageKey);
524
- } else {
525
- if (afterRestoreMacroTask) {
526
- notifyManager.schedule(
527
- () => afterRestoreMacroTask(persistedQuery)
528
- );
529
- }
530
- return persistedQuery.state.data;
531
- }
532
- }
533
- } catch (err) {
534
- if (process.env.NODE_ENV === "development") {
535
- console.error(err);
536
- console.warn(
537
- "Encountered an error attempting to restore query cache from persisted location."
538
- );
539
- }
540
- await storage2.removeItem(storageKey);
541
- }
542
- }
543
- return;
544
- }
545
- async function persistQueryByKey(queryKey, queryClient) {
546
- if (storage2 != null) {
547
- const query = queryClient.getQueryCache().find({ queryKey });
548
- if (query) {
549
- await persistQuery(query);
550
- } else {
551
- if (process.env.NODE_ENV === "development") {
552
- console.warn(
553
- "Could not find query to be persisted. QueryKey:",
554
- JSON.stringify(queryKey)
555
- );
556
- }
557
- }
558
- }
559
- }
560
- async function persistQuery(query) {
561
- if (storage2 != null) {
562
- const storageKey = `${prefix}-${query.queryHash}`;
563
- storage2.setItem(
564
- storageKey,
565
- await serialize({
566
- state: query.state,
567
- queryKey: query.queryKey,
568
- queryHash: query.queryHash,
569
- buster
570
- })
571
- );
572
- }
573
- }
574
- async function persisterFn(queryFn, ctx, query) {
575
- const matchesFilter = filters ? matchQuery(filters, query) : true;
576
- if (matchesFilter && query.state.data === void 0 && storage2 != null) {
577
- const restoredData = await retrieveQuery(
578
- query.queryHash,
579
- (persistedQuery) => {
580
- query.setState({
581
- dataUpdatedAt: persistedQuery.state.dataUpdatedAt,
582
- errorUpdatedAt: persistedQuery.state.errorUpdatedAt
583
- });
584
- if (refetchOnRestore === "always" || refetchOnRestore === true && query.isStale()) {
585
- query.fetch();
586
- }
587
- }
588
- );
589
- if (restoredData !== void 0) {
590
- return Promise.resolve(restoredData);
591
- }
592
- }
593
- const queryFnResult = await queryFn(ctx);
594
- if (matchesFilter && storage2 != null) {
595
- notifyManager.schedule(() => {
596
- persistQuery(query);
597
- });
598
- }
599
- return Promise.resolve(queryFnResult);
600
- }
601
- async function persisterGc() {
602
- if (storage2?.entries) {
603
- const entries = await storage2.entries();
604
- for (const [key, value] of entries) {
605
- if (key.startsWith(prefix)) {
606
- const persistedQuery = await deserialize(value);
607
- if (isExpiredOrBusted(persistedQuery)) {
608
- await storage2.removeItem(key);
609
- }
610
- }
611
- }
612
- } else if (process.env.NODE_ENV === "development") {
613
- throw new Error(
614
- "Provided storage does not implement `entries` method. Garbage collection is not possible without ability to iterate over storage items."
615
- );
616
- }
617
- }
618
- async function restoreQueries(queryClient, filters2 = {}) {
619
- const { exact, queryKey } = filters2;
620
- if (storage2?.entries) {
621
- const entries = await storage2.entries();
622
- for (const [key, value] of entries) {
623
- if (key.startsWith(prefix)) {
624
- const persistedQuery = await deserialize(value);
625
- if (isExpiredOrBusted(persistedQuery)) {
626
- await storage2.removeItem(key);
627
- continue;
628
- }
629
- if (queryKey) {
630
- if (exact) {
631
- if (persistedQuery.queryHash !== hashKey(queryKey)) {
632
- continue;
633
- }
634
- } else if (!partialMatchKey(persistedQuery.queryKey, queryKey)) {
635
- continue;
636
- }
637
- }
638
- queryClient.setQueryData(
639
- persistedQuery.queryKey,
640
- persistedQuery.state.data,
641
- {
642
- updatedAt: persistedQuery.state.dataUpdatedAt
643
- }
644
- );
645
- }
646
- }
647
- } else if (process.env.NODE_ENV === "development") {
648
- throw new Error(
649
- "Provided storage does not implement `entries` method. Restoration of all stored entries is not possible without ability to iterate over storage items."
650
- );
651
- }
652
- }
653
- return {
654
- persisterFn,
655
- persistQuery,
656
- persistQueryByKey,
657
- retrieveQuery,
658
- persisterGc,
659
- restoreQueries
660
- };
661
- }
662
-
663
- // ../../platform/query-persister/src/persister.ts
664
- var DB_NAME = "fluid_tanstack_query_cache";
665
- var STORE_NAME = "fluid_queries";
666
- var VERSION = 1;
667
- var dbPromise = null;
668
- async function deleteDatabase() {
669
- return new Promise((resolve, reject) => {
670
- console.warn("[IDB] Deleting database due to error");
671
- const req = indexedDB.deleteDatabase(DB_NAME);
672
- req.onsuccess = () => {
673
- console.log("[IDB] Database deleted successfully");
674
- resolve();
675
- };
676
- req.onerror = () => {
677
- console.error("[IDB] Failed to delete database:", req.error);
678
- reject(req.error ?? new Error("deleteDatabase failed"));
679
- };
680
- req.onblocked = () => {
681
- console.warn("[IDB] Delete blocked: close all tabs using this database");
682
- };
683
- });
684
- }
685
- function openDatabase() {
686
- return new Promise((resolve, reject) => {
687
- const req = indexedDB.open(DB_NAME, VERSION);
688
- req.onupgradeneeded = () => {
689
- const upgradeDb = req.result;
690
- if (!upgradeDb.objectStoreNames.contains(STORE_NAME)) {
691
- upgradeDb.createObjectStore(STORE_NAME);
692
- }
693
- };
694
- req.onsuccess = () => {
695
- const conn = req.result;
696
- conn.onversionchange = () => {
697
- console.trace("[IDB] version change \u2013 closing connection");
698
- conn.close();
699
- dbPromise = null;
700
- };
701
- resolve(conn);
702
- };
703
- req.onblocked = () => {
704
- console.warn("[IDB] open blocked: another connection is holding the DB");
705
- };
706
- req.onerror = () => {
707
- reject(
708
- req.error instanceof Error ? req.error : new Error(`IndexedDB open failed: ${String(req.error)}`)
709
- );
710
- };
711
- });
712
- }
713
- async function getDbWithRecovery() {
714
- try {
715
- return await openDatabase();
716
- } catch (err) {
717
- console.warn("[IDB] Initial open failed, attempting recovery:", err);
718
- try {
719
- await deleteDatabase();
720
- console.log("[IDB] Retrying database open after deletion");
721
- return await openDatabase();
722
- } catch (retryErr) {
723
- console.error("[IDB] Recovery failed:", retryErr);
724
- throw retryErr;
725
- }
726
- }
727
- }
728
- function getDb() {
729
- if (dbPromise) return dbPromise;
730
- dbPromise = getDbWithRecovery().catch((err) => {
731
- dbPromise = null;
732
- throw err;
733
- });
734
- return dbPromise;
735
- }
736
- var storage = {
737
- async getItem(key) {
738
- try {
739
- const db = await getDb();
740
- return new Promise((res) => {
741
- try {
742
- const r = db.transaction(STORE_NAME, "readonly").objectStore(STORE_NAME).get(key);
743
- r.onsuccess = () => res(r.result);
744
- r.onerror = () => {
745
- console.trace("[IDB] getItem error:", r.error);
746
- res(void 0);
747
- };
748
- } catch (txErr) {
749
- console.trace("[IDB] getItem transaction error:", txErr);
750
- res(void 0);
751
- }
752
- });
753
- } catch (err) {
754
- console.trace("[IDB] getItem getDb error:", err);
755
- try {
756
- const db = await getDb();
757
- return new Promise((res) => {
758
- try {
759
- const r = db.transaction(STORE_NAME, "readonly").objectStore(STORE_NAME).get(key);
760
- r.onsuccess = () => res(r.result);
761
- r.onerror = () => {
762
- console.trace("[IDB] getItem retry error:", r.error);
763
- res(void 0);
764
- };
765
- } catch (txErr) {
766
- console.trace("[IDB] getItem retry transaction error:", txErr);
767
- res(void 0);
768
- }
769
- });
770
- } catch (recoveryErr) {
771
- console.trace("[IDB] getItem recovery failed:", recoveryErr);
772
- }
773
- return void 0;
774
- }
775
- },
776
- async setItem(key, value) {
777
- const cloneableValue = JSON.parse(JSON.stringify(value));
778
- try {
779
- const db = await getDb();
780
- if (!db) return;
781
- await new Promise((resolve) => {
782
- try {
783
- const req = db.transaction(STORE_NAME, "readwrite").objectStore(STORE_NAME).put(cloneableValue, key);
784
- req.onsuccess = () => resolve();
785
- req.onerror = () => {
786
- console.trace("[IDB] setItem error:", req.error);
787
- resolve();
788
- };
789
- } catch (txErr) {
790
- console.trace("[IDB] setItem transaction error:", txErr);
791
- resolve();
792
- }
793
- });
794
- } catch (err) {
795
- console.trace("[IDB] setItem getDb error:", err);
796
- try {
797
- const db = await getDb();
798
- await new Promise((resolve) => {
799
- try {
800
- const req = db.transaction(STORE_NAME, "readwrite").objectStore(STORE_NAME).put(cloneableValue, key);
801
- req.onsuccess = () => resolve();
802
- req.onerror = () => {
803
- console.trace("[IDB] setItem retry error:", req.error);
804
- resolve();
805
- };
806
- } catch (txErr) {
807
- console.trace("[IDB] setItem retry transaction error:", txErr);
808
- resolve();
809
- }
810
- });
811
- } catch (recoveryErr) {
812
- console.trace("[IDB] setItem recovery failed:", recoveryErr);
813
- }
814
- }
815
- },
816
- async removeItem(key) {
817
- try {
818
- const db = await getDb();
819
- if (!db) return;
820
- await new Promise((resolve) => {
821
- try {
822
- const req = db.transaction(STORE_NAME, "readwrite").objectStore(STORE_NAME).delete(key);
823
- req.onsuccess = () => resolve();
824
- req.onerror = () => {
825
- console.trace("[IDB] removeItem error:", req.error);
826
- resolve();
827
- };
828
- } catch (txErr) {
829
- console.trace("[IDB] removeItem transaction error:", txErr);
830
- resolve();
831
- }
832
- });
833
- } catch (err) {
834
- console.trace("[IDB] removeItem getDb error:", err);
835
- try {
836
- const db = await getDb();
837
- await new Promise((resolve) => {
838
- try {
839
- const req = db.transaction(STORE_NAME, "readwrite").objectStore(STORE_NAME).delete(key);
840
- req.onsuccess = () => resolve();
841
- req.onerror = () => {
842
- console.trace("[IDB] removeItem retry error:", req.error);
843
- resolve();
844
- };
845
- } catch (txErr) {
846
- console.trace("[IDB] removeItem retry transaction error:", txErr);
847
- resolve();
848
- }
849
- });
850
- } catch (recoveryErr) {
851
- console.trace("[IDB] removeItem recovery failed:", recoveryErr);
852
- }
853
- }
854
- }
855
- };
856
- function createPersister() {
857
- return experimental_createQueryPersister({
858
- storage,
859
- serialize: (persistedQuery) => persistedQuery,
860
- deserialize: (cached) => cached
861
- });
862
- }
863
-
864
- // src/hooks/use-fluid-app.ts
865
- var APP_DATA_QUERY_KEY = ["fluid", "app"];
866
- var appDataPersister = typeof window !== "undefined" ? createPersister() : void 0;
867
- function useFluidApp(options) {
868
- const api = useFluidApi();
869
- return useQuery({
870
- queryKey: APP_DATA_QUERY_KEY,
871
- queryFn: () => api.app.getRaw(),
872
- select: transformManifestToRepAppData,
873
- ...appDataPersister && { persister: appDataPersister.persisterFn },
874
- ...options?.enabled !== void 0 && { enabled: options.enabled }
875
- });
876
- }
877
- var PERMISSIONS_QUERY_KEY = ["fluid", "permissions"];
878
- function useFluidPermissions() {
879
- const api = useFluidApi();
880
- const query = useQuery({
881
- queryKey: PERMISSIONS_QUERY_KEY,
882
- queryFn: () => api.permissions.get()
883
- });
884
- const permissions = query.data;
885
- const can = useMemo(() => {
886
- return (resource, action = "view") => {
887
- if (!permissions) {
888
- return false;
889
- }
890
- if (permissions.is_super_admin) {
891
- return true;
892
- }
893
- const resourcePermissions = permissions.permissions[resource];
894
- if (!resourcePermissions) {
895
- return false;
896
- }
897
- return resourcePermissions[action] ?? false;
898
- };
899
- }, [permissions]);
900
- const isSuperAdmin = permissions?.is_super_admin ?? false;
901
- return {
902
- query,
903
- permissions,
904
- can,
905
- isSuperAdmin
906
- };
907
- }
908
-
909
- // src/hooks/use-fluid-theme.ts
910
- function useFluidTheme() {
911
- const { currentTheme, setTheme, setThemeMode, mode } = useThemeContext();
912
- return {
913
- currentTheme,
914
- setTheme,
915
- setThemeMode,
916
- mode
917
- };
918
- }
919
- var CURRENT_REP_QUERY_KEY = ["fluid", "currentRep"];
920
- function useCurrentRep() {
921
- const api = useFluidApi();
922
- return useQuery({
923
- queryKey: CURRENT_REP_QUERY_KEY,
924
- queryFn: () => api.reps.current()
925
- });
926
- }
927
-
928
- // src/hooks/use-fluid-auth.ts
929
- function useFluidAuth() {
930
- return useFluidAuthContext();
931
- }
932
-
933
- // src/hooks/demo-data/calendar-events.ts
934
- var now = /* @__PURE__ */ new Date();
935
- function daysFromNow(days, hour, minute = 0) {
936
- const d = new Date(now);
937
- d.setDate(d.getDate() + days);
938
- d.setHours(hour, minute, 0, 0);
939
- return d;
940
- }
941
- var DEMO_CALENDAR_EVENTS = [
942
- {
943
- id: 1,
944
- title: "Team Standup",
945
- description: { body: "Daily sync with the sales team" },
946
- color: "#4f46e5",
947
- start: daysFromNow(0, 9, 0).toISOString(),
948
- end: daysFromNow(0, 9, 30).toISOString(),
949
- active: true,
950
- status: "confirmed"
951
- },
952
- {
953
- id: 2,
954
- title: "Client Review - Acme Corp",
955
- description: { body: "Quarterly business review with key accounts" },
956
- color: "#059669",
957
- start: daysFromNow(2, 14, 0).toISOString(),
958
- end: daysFromNow(2, 15, 0).toISOString(),
959
- active: true,
960
- status: "confirmed",
961
- venue: "Conference Room B"
962
- },
963
- {
964
- id: 3,
965
- title: "Product Training Webinar",
966
- description: { body: "New product line training for the field" },
967
- color: "#d97706",
968
- start: daysFromNow(4, 11, 0).toISOString(),
969
- end: daysFromNow(4, 12, 30).toISOString(),
970
- active: true,
971
- status: "confirmed",
972
- url: "https://example.com/webinar"
973
- },
974
- {
975
- id: 4,
976
- title: "Regional Conference",
977
- description: { body: "Annual West Coast regional conference" },
978
- color: "#dc2626",
979
- start: daysFromNow(10, 8, 0).toISOString(),
980
- end: daysFromNow(12, 17, 0).toISOString(),
981
- active: true,
982
- status: "confirmed",
983
- venue: "San Diego Convention Center",
984
- isAllDay: true
985
- }
986
- ];
987
-
988
- // src/hooks/use-calendar-events.ts
989
- function useCalendarEvents() {
990
- return {
991
- data: [...DEMO_CALENDAR_EVENTS],
992
- isLoading: false,
993
- isError: false
994
- };
995
- }
996
-
997
- // src/hooks/demo-data/todos.ts
998
- var now2 = /* @__PURE__ */ new Date();
999
- function daysFromNow2(days) {
1000
- const d = new Date(now2);
1001
- d.setDate(d.getDate() + days);
1002
- return d.toISOString();
1003
- }
1004
- var DEMO_TODOS = [
1005
- {
1006
- id: 1,
1007
- body: "Follow up with Sarah about Q2 order",
1008
- dueAt: daysFromNow2(1),
1009
- completedAt: null,
1010
- createdAt: daysFromNow2(-2),
1011
- contactName: "Sarah Johnson"
1012
- },
1013
- {
1014
- id: 2,
1015
- body: "Send pricing proposal to Acme Corp",
1016
- dueAt: daysFromNow2(7),
1017
- completedAt: null,
1018
- createdAt: daysFromNow2(-1),
1019
- contactName: "Mike Chen"
1020
- },
1021
- {
1022
- id: 3,
1023
- body: "Schedule onboarding call with new team member",
1024
- dueAt: daysFromNow2(3),
1025
- completedAt: null,
1026
- createdAt: daysFromNow2(0),
1027
- contactName: "Emily Rodriguez"
1028
- },
1029
- {
1030
- id: 4,
1031
- body: "Review and approve Q1 expense report",
1032
- dueAt: daysFromNow2(-1),
1033
- completedAt: daysFromNow2(-1),
1034
- createdAt: daysFromNow2(-5),
1035
- contactName: null
1036
- },
1037
- {
1038
- id: 5,
1039
- body: "Prepare presentation for Friday team meeting",
1040
- dueAt: daysFromNow2(4),
1041
- completedAt: daysFromNow2(0),
1042
- createdAt: daysFromNow2(-3),
1043
- contactName: null
1044
- }
1045
- ];
1046
-
1047
- // src/hooks/use-todos.ts
1048
- function useTodos() {
1049
- return {
1050
- data: [...DEMO_TODOS],
1051
- isLoading: false,
1052
- isError: false
1053
- };
1054
- }
1055
-
1056
- // src/hooks/hook-types.ts
1057
- function hasData(result) {
1058
- return result.data != null && !result.isLoading && !result.isError;
1059
- }
1060
- function isLoading(result) {
1061
- return result.isLoading;
1062
- }
1063
- function isErrorResult(result) {
1064
- return result.isError && result.error !== void 0;
1065
- }
1066
- function isIdle(result) {
1067
- return !result.isLoading && !result.isError;
1068
- }
1069
- function selectProperty(items, key) {
1070
- return items.map((item) => item[key]);
1071
- }
1072
- function getProperty(item, key) {
1073
- return item?.[key];
1074
- }
1075
- var ACTIVITY_SLUGS = {
1076
- abandonedCart: "abandoned_cart",
1077
- announcements: "announcements",
1078
- cartItemsAdded: "cart_items_added",
1079
- commentReply: "comment_reply",
1080
- directMessage: "direct_message",
1081
- fantasyPoint: "fantasy_point",
1082
- newLead: "new_lead",
1083
- orderPlaced: "order_placed",
1084
- pageViews: "page_views",
1085
- pageViewsContact: "page_views_contact",
1086
- tasks: "tasks",
1087
- upcomingEvent: "upcoming_event",
1088
- video: "video",
1089
- videoComplete: "video_complete",
1090
- videoCompleteContact: "video_complete_contact",
1091
- videoContact: "video_contact",
1092
- messageReceived: "message_received",
1093
- messageSent: "message_sent",
1094
- newCartItemsAdded: "new_cart_items_added",
1095
- smartLinkClicked: "smart_link_clicked",
1096
- reviewLeft: "review_left"
1097
- };
1098
- function isActivitySlug(value) {
1099
- return Object.values(ACTIVITY_SLUGS).includes(value);
1100
- }
1101
-
1102
- // src/hooks/demo-data/activities.ts
1103
- var now3 = /* @__PURE__ */ new Date();
1104
- function hoursAgo(hours) {
1105
- const d = new Date(now3);
1106
- d.setHours(d.getHours() - hours);
1107
- return d.toISOString();
1108
- }
1109
- var DEMO_ACTIVITIES = [
1110
- {
1111
- id: 1,
1112
- userName: "Sarah Johnson",
1113
- avatarUrl: null,
1114
- activityType: "New Order",
1115
- targetName: "Wellness Starter Kit",
1116
- timestamp: hoursAgo(1),
1117
- slug: "order_placed"
1118
- },
1119
- {
1120
- id: 2,
1121
- userName: "Mike Chen",
1122
- avatarUrl: null,
1123
- activityType: "New Lead",
1124
- targetName: "Referral from LinkedIn campaign",
1125
- timestamp: hoursAgo(3),
1126
- slug: "new_lead"
1127
- },
1128
- {
1129
- id: 3,
1130
- userName: "Emily Rodriguez",
1131
- avatarUrl: null,
1132
- activityType: "Page View",
1133
- targetName: "Product Catalog",
1134
- timestamp: hoursAgo(5),
1135
- slug: "page_views"
1136
- },
1137
- {
1138
- id: 4,
1139
- userName: "David Park",
1140
- avatarUrl: null,
1141
- activityType: "Cart Items Added",
1142
- targetName: "Premium Bundle (3 items)",
1143
- timestamp: hoursAgo(8),
1144
- slug: "cart_items_added"
1145
- },
1146
- {
1147
- id: 5,
1148
- userName: "Lisa Thompson",
1149
- avatarUrl: null,
1150
- activityType: "Video Watched",
1151
- targetName: "Getting Started Tutorial",
1152
- timestamp: hoursAgo(12),
1153
- slug: "video_complete"
1154
- },
1155
- {
1156
- id: 6,
1157
- userName: "James Wilson",
1158
- avatarUrl: null,
1159
- activityType: "Message Received",
1160
- targetName: "Question about shipping",
1161
- timestamp: hoursAgo(18),
1162
- slug: "message_received"
1163
- },
1164
- {
1165
- id: 7,
1166
- userName: "Rachel Kim",
1167
- avatarUrl: null,
1168
- activityType: "Smart Link Clicked",
1169
- targetName: "Holiday Promo Link",
1170
- timestamp: hoursAgo(24),
1171
- slug: "smart_link_clicked"
1172
- },
1173
- {
1174
- id: 8,
1175
- userName: "Tom Martinez",
1176
- avatarUrl: null,
1177
- activityType: "Review Left",
1178
- targetName: "Essential Oil Set - 5 stars",
1179
- timestamp: hoursAgo(36),
1180
- slug: "review_left"
1181
- }
1182
- ];
1183
-
1184
- // src/hooks/use-activities.ts
1185
- function useActivities() {
1186
- return {
1187
- data: [...DEMO_ACTIVITIES],
1188
- isLoading: false,
1189
- isError: false
1190
- };
1191
- }
1192
-
1193
- // src/hooks/demo-data/catchups.ts
1194
- var DEMO_CATCHUPS = [
1195
- {
1196
- id: 1,
1197
- suggestion_title: "Sarah Johnson hasn't ordered in 30 days"
1198
- },
1199
- {
1200
- id: 2,
1201
- suggestion_title: "Mike Chen's subscription is expiring soon"
1202
- },
1203
- {
1204
- id: 3,
1205
- suggestion_title: "Emily Rodriguez left a cart with 3 items"
1206
- }
1207
- ];
1208
-
1209
- // src/hooks/use-catchups.ts
1210
- function useCatchUps() {
1211
- return {
1212
- data: [...DEMO_CATCHUPS],
1213
- isLoading: false,
1214
- isError: false
1215
- };
1216
- }
1217
-
1218
- // src/hooks/demo-data/mysite.ts
1219
- var DEMO_MYSITE = {
1220
- url: "https://my-portal.example.com",
1221
- views: 1243,
1222
- leads: 37,
1223
- userName: "Demo User"
1224
- };
1225
-
1226
- // src/hooks/use-mysite.ts
1227
- function useMySite() {
1228
- return {
1229
- data: DEMO_MYSITE,
1230
- isLoading: false,
1231
- isError: false
1232
- };
1233
- }
1234
-
1235
- // src/hooks/demo-data/conversations.ts
1236
- var now4 = /* @__PURE__ */ new Date();
1237
- function hoursAgo2(hours) {
1238
- const d = new Date(now4);
1239
- d.setHours(d.getHours() - hours);
1240
- return d.toISOString();
1241
- }
1242
- function daysAgo(days) {
1243
- const d = new Date(now4);
1244
- d.setDate(d.getDate() - days);
1245
- return d.toISOString();
1246
- }
1247
- var DEMO_CONVERSATIONS = [
1248
- {
1249
- id: "conv-1",
1250
- title: "Sarah Johnson",
1251
- participants: [
1252
- { id: "user-1", name: "You", email: "me@example.com", isOnline: true },
1253
- {
1254
- id: "user-2",
1255
- name: "Sarah Johnson",
1256
- email: "sarah.johnson@example.com",
1257
- isOnline: true
1258
- }
1259
- ],
1260
- lastMessage: {
1261
- id: "msg-1-3",
1262
- conversationId: "conv-1",
1263
- senderId: "user-2",
1264
- senderName: "Sarah Johnson",
1265
- type: "text",
1266
- content: "Sounds great! I'll place the order by end of day.",
1267
- timestamp: hoursAgo2(1),
1268
- isRead: false
1269
- },
1270
- unreadCount: 1,
1271
- status: "active",
1272
- createdAt: daysAgo(30),
1273
- updatedAt: hoursAgo2(1)
1274
- },
1275
- {
1276
- id: "conv-2",
1277
- title: "Mike Chen",
1278
- participants: [
1279
- { id: "user-1", name: "You", email: "me@example.com", isOnline: true },
1280
- {
1281
- id: "user-3",
1282
- name: "Mike Chen",
1283
- email: "mike.chen@acmecorp.com",
1284
- isOnline: false
1285
- }
1286
- ],
1287
- lastMessage: {
1288
- id: "msg-2-2",
1289
- conversationId: "conv-2",
1290
- senderId: "user-1",
1291
- senderName: "You",
1292
- type: "text",
1293
- content: "I've attached the updated pricing sheet. Let me know if you have any questions!",
1294
- timestamp: hoursAgo2(5),
1295
- isRead: true
1296
- },
1297
- unreadCount: 0,
1298
- status: "active",
1299
- createdAt: daysAgo(14),
1300
- updatedAt: hoursAgo2(5)
1301
- },
1302
- {
1303
- id: "conv-3",
1304
- title: "Team Updates",
1305
- participants: [
1306
- { id: "user-1", name: "You", email: "me@example.com", isOnline: true },
1307
- {
1308
- id: "user-4",
1309
- name: "Emily Rodriguez",
1310
- email: "emily.r@healthfirst.io"
1311
- },
1312
- { id: "user-5", name: "David Park", email: "david.park@email.com" }
1313
- ],
1314
- lastMessage: {
1315
- id: "msg-3-4",
1316
- conversationId: "conv-3",
1317
- senderId: "user-4",
1318
- senderName: "Emily Rodriguez",
1319
- type: "text",
1320
- content: "The new product samples arrived today. Will distribute to the team tomorrow.",
1321
- timestamp: daysAgo(1),
1322
- isRead: true
1323
- },
1324
- unreadCount: 0,
1325
- status: "active",
1326
- createdAt: daysAgo(60),
1327
- updatedAt: daysAgo(1)
1328
- }
1329
- ];
1330
- var DEMO_MESSAGES = [
1331
- {
1332
- id: "msg-1-1",
1333
- conversationId: "conv-1",
1334
- senderId: "user-1",
1335
- senderName: "You",
1336
- type: "text",
1337
- content: "Hi Sarah! I wanted to follow up on the Wellness Starter Kit. We have a special promotion running this month.",
1338
- timestamp: hoursAgo2(3),
1339
- isRead: true
1340
- },
1341
- {
1342
- id: "msg-1-2",
1343
- conversationId: "conv-1",
1344
- senderId: "user-2",
1345
- senderName: "Sarah Johnson",
1346
- type: "text",
1347
- content: "That's perfect timing! I was just thinking about reordering. What's the promo?",
1348
- timestamp: hoursAgo2(2),
1349
- isRead: true
1350
- },
1351
- {
1352
- id: "msg-1-3",
1353
- conversationId: "conv-1",
1354
- senderId: "user-2",
1355
- senderName: "Sarah Johnson",
1356
- type: "text",
1357
- content: "Sounds great! I'll place the order by end of day.",
1358
- timestamp: hoursAgo2(1),
1359
- isRead: false
1360
- }
1361
- ];
1362
-
1363
- // src/hooks/use-conversations.ts
1364
- function useConversations() {
1365
- return {
1366
- data: [...DEMO_CONVERSATIONS],
1367
- isLoading: false,
1368
- isError: false
1369
- };
1370
- }
1371
- function useConversationMessages(_conversationId) {
1372
- return {
1373
- data: [...DEMO_MESSAGES],
1374
- isLoading: false,
1375
- isError: false
1376
- };
1377
- }
1378
-
1379
- // src/types/screen-types.ts
1380
- var CONTACT_STATUSES = {
1381
- active: "active",
1382
- inactive: "inactive",
1383
- lead: "lead",
1384
- prospect: "prospect"
1385
- };
1386
-
1387
- // src/hooks/demo-data/contacts.ts
1388
- var now5 = /* @__PURE__ */ new Date();
1389
- function daysAgo2(days) {
1390
- const d = new Date(now5);
1391
- d.setDate(d.getDate() - days);
1392
- return d.toISOString();
1393
- }
1394
- var DEMO_CONTACTS = [
1395
- {
1396
- id: "contact-1",
1397
- firstName: "Sarah",
1398
- lastName: "Johnson",
1399
- email: "sarah.johnson@example.com",
1400
- phone: "+1 (555) 123-4567",
1401
- company: "Wellness Works Inc.",
1402
- jobTitle: "Purchasing Manager",
1403
- status: "active",
1404
- type: "individual",
1405
- tags: ["VIP", "Repeat Buyer"],
1406
- createdAt: daysAgo2(90),
1407
- updatedAt: daysAgo2(2)
1408
- },
1409
- {
1410
- id: "contact-2",
1411
- firstName: "Mike",
1412
- lastName: "Chen",
1413
- email: "mike.chen@acmecorp.com",
1414
- phone: "+1 (555) 234-5678",
1415
- company: "Acme Corp",
1416
- jobTitle: "Director of Operations",
1417
- status: "active",
1418
- type: "individual",
1419
- tags: ["Enterprise"],
1420
- createdAt: daysAgo2(60),
1421
- updatedAt: daysAgo2(5)
1422
- },
1423
- {
1424
- id: "contact-3",
1425
- firstName: "Emily",
1426
- lastName: "Rodriguez",
1427
- email: "emily.r@healthfirst.io",
1428
- company: "HealthFirst",
1429
- status: "lead",
1430
- type: "individual",
1431
- notes: "Interested in bulk pricing for team orders",
1432
- createdAt: daysAgo2(7),
1433
- updatedAt: daysAgo2(1)
1434
- },
1435
- {
1436
- id: "contact-4",
1437
- firstName: "David",
1438
- lastName: "Park",
1439
- email: "david.park@email.com",
1440
- phone: "+1 (555) 345-6789",
1441
- status: "prospect",
1442
- type: "individual",
1443
- tags: ["Referral"],
1444
- createdAt: daysAgo2(14),
1445
- updatedAt: daysAgo2(10)
1446
- },
1447
- {
1448
- id: "contact-5",
1449
- firstName: "Lisa",
1450
- lastName: "Thompson",
1451
- email: "lisa.t@globalfit.com",
1452
- company: "Global Fitness",
1453
- jobTitle: "CEO",
1454
- status: "active",
1455
- type: "individual",
1456
- address: {
1457
- city: "Los Angeles",
1458
- state: "CA",
1459
- country: "US"
1460
- },
1461
- createdAt: daysAgo2(120),
1462
- updatedAt: daysAgo2(15)
1463
- },
1464
- {
1465
- id: "contact-6",
1466
- firstName: "James",
1467
- lastName: "Wilson",
1468
- email: "jwilson@retired.net",
1469
- status: "inactive",
1470
- type: "individual",
1471
- notes: "Moved out of area, no longer purchasing",
1472
- createdAt: daysAgo2(200),
1473
- updatedAt: daysAgo2(45)
1474
- }
1475
- ];
1476
- var DEMO_CONTACT = DEMO_CONTACTS[0];
1477
-
1478
- // src/hooks/use-contacts.ts
1479
- function isContactStatus(value) {
1480
- return Object.values(CONTACT_STATUSES).includes(value);
1481
- }
1482
- function useContacts(_params) {
1483
- return {
1484
- data: [...DEMO_CONTACTS],
1485
- isLoading: false,
1486
- isError: false,
1487
- totalCount: DEMO_CONTACTS.length
1488
- };
1489
- }
1490
- function useContact(_contactId) {
1491
- return {
1492
- data: DEMO_CONTACT,
1493
- isLoading: false,
1494
- isError: false
1495
- };
1496
- }
1497
- function AuthError({
1498
- message = "You need to be authenticated to view this content.",
1499
- title = "Authentication Required",
1500
- children
1501
- }) {
1502
- return /* @__PURE__ */ jsx(
1503
- "div",
1504
- {
1505
- style: {
1506
- display: "flex",
1507
- flexDirection: "column",
1508
- alignItems: "center",
1509
- justifyContent: "center",
1510
- minHeight: "100vh",
1511
- padding: "2rem",
1512
- fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif',
1513
- backgroundColor: "#f9fafb",
1514
- color: "#111827"
1515
- },
1516
- children: /* @__PURE__ */ jsxs(
1517
- "div",
1518
- {
1519
- style: {
1520
- maxWidth: "400px",
1521
- textAlign: "center",
1522
- padding: "2rem",
1523
- backgroundColor: "#ffffff",
1524
- borderRadius: "0.75rem",
1525
- boxShadow: "0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06)"
1526
- },
1527
- children: [
1528
- /* @__PURE__ */ jsx(
1529
- "div",
1530
- {
1531
- style: {
1532
- width: "64px",
1533
- height: "64px",
1534
- margin: "0 auto 1.5rem",
1535
- backgroundColor: "#fee2e2",
1536
- borderRadius: "50%",
1537
- display: "flex",
1538
- alignItems: "center",
1539
- justifyContent: "center"
1540
- },
1541
- children: /* @__PURE__ */ jsxs(
1542
- "svg",
1543
- {
1544
- width: "32",
1545
- height: "32",
1546
- viewBox: "0 0 24 24",
1547
- fill: "none",
1548
- stroke: "#dc2626",
1549
- strokeWidth: "2",
1550
- strokeLinecap: "round",
1551
- strokeLinejoin: "round",
1552
- children: [
1553
- /* @__PURE__ */ jsx("rect", { x: "3", y: "11", width: "18", height: "11", rx: "2", ry: "2" }),
1554
- /* @__PURE__ */ jsx("path", { d: "M7 11V7a5 5 0 0 1 10 0v4" })
1555
- ]
1556
- }
1557
- )
1558
- }
1559
- ),
1560
- /* @__PURE__ */ jsx(
1561
- "h1",
1562
- {
1563
- style: {
1564
- fontSize: "1.5rem",
1565
- fontWeight: "600",
1566
- marginBottom: "0.75rem",
1567
- color: "#111827"
1568
- },
1569
- children: title
1570
- }
1571
- ),
1572
- /* @__PURE__ */ jsx(
1573
- "p",
1574
- {
1575
- style: {
1576
- fontSize: "1rem",
1577
- color: "#6b7280",
1578
- marginBottom: children ? "1.5rem" : "0",
1579
- lineHeight: "1.5"
1580
- },
1581
- children: message
1582
- }
1583
- ),
1584
- children
1585
- ]
1586
- }
1587
- )
1588
- }
1589
- );
1590
- }
1591
- var SPIN_STYLE_ID = "fluid-auth-loading-spin";
1592
- function ensureSpinStyle() {
1593
- if (typeof document === "undefined") return;
1594
- if (document.getElementById(SPIN_STYLE_ID)) return;
1595
- const style = document.createElement("style");
1596
- style.id = SPIN_STYLE_ID;
1597
- style.textContent = `@keyframes spin { to { transform: rotate(360deg); } }`;
1598
- document.head.appendChild(style);
1599
- }
1600
- function AuthLoading() {
1601
- useEffect(() => {
1602
- ensureSpinStyle();
1603
- }, []);
1604
- return /* @__PURE__ */ jsxs(
1605
- "div",
1606
- {
1607
- style: {
1608
- display: "flex",
1609
- flexDirection: "column",
1610
- alignItems: "center",
1611
- justifyContent: "center",
1612
- minHeight: "100vh",
1613
- fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif',
1614
- backgroundColor: "#f9fafb"
1615
- },
1616
- children: [
1617
- /* @__PURE__ */ jsx(
1618
- "div",
1619
- {
1620
- style: {
1621
- width: "40px",
1622
- height: "40px",
1623
- border: "3px solid #e5e7eb",
1624
- borderTopColor: "#3b82f6",
1625
- borderRadius: "50%",
1626
- animation: "spin 1s linear infinite"
1627
- }
1628
- }
1629
- ),
1630
- /* @__PURE__ */ jsx(
1631
- "p",
1632
- {
1633
- style: {
1634
- marginTop: "1rem",
1635
- color: "#6b7280",
1636
- fontSize: "0.875rem"
1637
- },
1638
- children: "Authenticating..."
1639
- }
1640
- )
1641
- ]
1642
- }
1643
- );
1644
- }
1645
- function RequireAuth({
1646
- children,
1647
- fallback = /* @__PURE__ */ jsx(AuthLoading, {}),
1648
- errorComponent = /* @__PURE__ */ jsx(AuthError, {})
1649
- }) {
1650
- const { isAuthenticated, isLoading: isLoading2, error } = useFluidAuth();
1651
- if (isLoading2) {
1652
- return /* @__PURE__ */ jsx(Fragment, { children: fallback });
1653
- }
1654
- if (!isAuthenticated || error) {
1655
- return /* @__PURE__ */ jsx(Fragment, { children: errorComponent });
1656
- }
1657
- return /* @__PURE__ */ jsx(Fragment, { children });
1658
- }
1659
-
1660
- // src/screens/index.ts
1661
- var screenPropertySchemas = {
1662
- MessagingScreen: () => import('./MessagingScreen-I3GVOGKY.js').then((m) => m.messagingScreenPropertySchema),
1663
- ContactsScreen: () => import('./ContactsScreen-XKZE5HTP.js').then((m) => m.contactsScreenPropertySchema),
1664
- OrdersScreen: () => import('./OrdersScreen-ANDGND6F.js').then((m) => m.ordersScreenPropertySchema),
1665
- CustomersScreen: () => import('./CustomersScreen-BBQ3YHI4.js').then((m) => m.customersScreenPropertySchema),
1666
- ProductsScreen: () => import('./ProductsScreen-5PMFLPWS.js').then((m) => m.productsScreenPropertySchema)
1667
- };
1668
- var CORE_PAGE_IDS = {
1669
- MESSAGING: "core-messaging",
1670
- CONTACTS: "core-contacts",
1671
- ORDERS: "core-orders",
1672
- CUSTOMERS: "core-customers",
1673
- PRODUCTS: "core-products"
1674
- };
1675
- function registerCorePageTemplates() {
1676
- PageTemplateRegistry.register({
1677
- id: CORE_PAGE_IDS.MESSAGING,
1678
- slug: "messaging",
1679
- name: "Messaging",
1680
- description: "Messaging interface provided by Fluid Commerce",
1681
- category: PAGE_CATEGORIES.COMMUNICATION,
1682
- tags: ["messaging", "chat", "conversations", "communication"],
1683
- version: "1.0.0",
1684
- isCore: true,
1685
- component_tree: [
1686
- {
1687
- type: "MessagingScreen",
1688
- id: "messaging-screen-root",
1689
- props: {}
1690
- }
1691
- ],
1692
- defaultProps: {}
1693
- });
1694
- PageTemplateRegistry.register({
1695
- id: CORE_PAGE_IDS.CONTACTS,
1696
- slug: "contacts",
1697
- name: "Contacts",
1698
- description: "Contact management provided by Fluid Commerce",
1699
- category: PAGE_CATEGORIES.CORE,
1700
- tags: ["contacts", "people", "address-book"],
1701
- version: "1.0.0",
1702
- isCore: true,
1703
- component_tree: [
1704
- {
1705
- type: "ContactsScreen",
1706
- id: "contacts-screen-root",
1707
- props: {}
1708
- }
1709
- ],
1710
- defaultProps: {}
1711
- });
1712
- PageTemplateRegistry.register({
1713
- id: CORE_PAGE_IDS.ORDERS,
1714
- slug: "orders",
1715
- name: "Orders",
1716
- description: "Order management provided by Fluid Commerce",
1717
- category: PAGE_CATEGORIES.CORE,
1718
- tags: ["orders", "commerce", "sales"],
1719
- version: "1.0.0",
1720
- isCore: true,
1721
- component_tree: [
1722
- {
1723
- type: "OrdersScreen",
1724
- id: "orders-screen-root",
1725
- props: {}
1726
- }
1727
- ],
1728
- defaultProps: {}
1729
- });
1730
- PageTemplateRegistry.register({
1731
- id: CORE_PAGE_IDS.CUSTOMERS,
1732
- slug: "customers",
1733
- name: "Customers",
1734
- description: "Customer management provided by Fluid Commerce",
1735
- category: PAGE_CATEGORIES.CORE,
1736
- tags: ["customers", "people", "commerce"],
1737
- version: "1.0.0",
1738
- isCore: true,
1739
- component_tree: [
1740
- {
1741
- type: "CustomersScreen",
1742
- id: "customers-screen-root",
1743
- props: {}
1744
- }
1745
- ],
1746
- defaultProps: {}
1747
- });
1748
- PageTemplateRegistry.register({
1749
- id: CORE_PAGE_IDS.PRODUCTS,
1750
- slug: "products",
1751
- name: "Products",
1752
- description: "Product catalog provided by Fluid Commerce",
1753
- category: PAGE_CATEGORIES.CORE,
1754
- tags: ["products", "catalog", "commerce"],
1755
- version: "1.0.0",
1756
- isCore: true,
1757
- component_tree: [
1758
- {
1759
- type: "ProductsScreen",
1760
- id: "products-screen-root",
1761
- props: {}
1762
- }
1763
- ],
1764
- defaultProps: {}
1765
- });
1766
- }
1767
- registerCorePageTemplates();
1768
- function isInSection(item, currentSlug) {
1769
- const normalized = normalizeSlug(currentSlug);
1770
- if (normalizeSlug(item.slug) === normalized) return true;
1771
- return item.children?.some((child) => normalizeSlug(child.slug) === normalized) ?? false;
1772
- }
1773
- function getNavTarget(item) {
1774
- if (item.slug && (!item.children || item.children.length === 0)) {
1775
- return normalizeSlug(item.slug);
1776
- }
1777
- if (item.children && item.children.length > 0) {
1778
- const firstChild = item.children[0];
1779
- if (firstChild?.slug) return normalizeSlug(firstChild.slug);
1780
- }
1781
- return null;
1782
- }
1783
- function SdkBottomNav({
1784
- navItems,
1785
- currentSlug,
1786
- onNavigate,
1787
- maxVisibleItems = 5
1788
- }) {
1789
- const { isMobile, useBottomNav } = useSidebar();
1790
- const [moreOpen, setMoreOpen] = React2.useState(false);
1791
- if (!isMobile || !useBottomNav) return null;
1792
- const navigableItems = navItems.filter((item) => !item.parent_id).filter((item) => item.slug || item.children && item.children.length > 0);
1793
- const hasOverflow = navigableItems.length > maxVisibleItems;
1794
- const visibleItems = hasOverflow ? navigableItems.slice(0, maxVisibleItems - 1) : navigableItems;
1795
- const overflowItems = hasOverflow ? navigableItems.slice(maxVisibleItems - 1) : [];
1796
- const handleItemClick = (item) => {
1797
- const target = getNavTarget(item);
1798
- if (target) onNavigate(target);
1799
- setMoreOpen(false);
1800
- };
1801
- return /* @__PURE__ */ jsxs(Fragment, { children: [
1802
- /* @__PURE__ */ jsxs("nav", { className: "border-border bg-sidebar fixed right-0 bottom-0 left-0 z-40 flex h-16 items-end justify-around border-t pb-[env(safe-area-inset-bottom)]", children: [
1803
- visibleItems.map((item) => {
1804
- const isActive = isInSection(item, currentSlug);
1805
- return /* @__PURE__ */ jsxs(
1806
- "button",
1807
- {
1808
- type: "button",
1809
- onClick: () => handleItemClick(item),
1810
- className: `flex flex-1 flex-col items-center justify-center gap-0.5 py-2 text-[10px] font-medium transition-colors ${isActive ? "text-primary" : "text-muted-foreground"}`,
1811
- children: [
1812
- item.icon ? /* @__PURE__ */ jsx(RepIcon, { name: item.icon, className: "size-5" }) : /* @__PURE__ */ jsx("span", { className: "size-5" }),
1813
- /* @__PURE__ */ jsx("span", { className: "max-w-[72px] truncate", children: item.label })
1814
- ]
1815
- },
1816
- item.id ?? item.slug ?? item.label
1817
- );
1818
- }),
1819
- hasOverflow && /* @__PURE__ */ jsxs(
1820
- "button",
1821
- {
1822
- type: "button",
1823
- onClick: () => setMoreOpen(true),
1824
- className: `flex flex-1 flex-col items-center justify-center gap-0.5 py-2 text-[10px] font-medium transition-colors ${overflowItems.some((item) => isInSection(item, currentSlug)) ? "text-primary" : "text-muted-foreground"}`,
1825
- children: [
1826
- /* @__PURE__ */ jsx(FontAwesomeIcon, { icon: faEllipsis, className: "size-5" }),
1827
- /* @__PURE__ */ jsx("span", { children: "More" })
1828
- ]
1829
- }
1830
- )
1831
- ] }),
1832
- moreOpen && /* @__PURE__ */ jsxs("div", { className: "fixed inset-0 z-50 flex flex-col", children: [
1833
- /* @__PURE__ */ jsx(
1834
- "div",
1835
- {
1836
- className: "flex-1 bg-black/50",
1837
- onClick: () => setMoreOpen(false),
1838
- "aria-hidden": "true"
1839
- }
1840
- ),
1841
- /* @__PURE__ */ jsxs("div", { className: "bg-sidebar rounded-t-2xl pb-[env(safe-area-inset-bottom)]", children: [
1842
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-4 pt-4 pb-2", children: [
1843
- /* @__PURE__ */ jsx("span", { className: "text-foreground text-sm font-semibold", children: "More" }),
1844
- /* @__PURE__ */ jsx(
1845
- "button",
1846
- {
1847
- type: "button",
1848
- onClick: () => setMoreOpen(false),
1849
- className: "text-muted-foreground hover:bg-sidebar-accent flex items-center justify-center rounded-full p-1",
1850
- "aria-label": "Close",
1851
- children: /* @__PURE__ */ jsx(FontAwesomeIcon, { icon: faXmark, className: "size-5" })
1852
- }
1853
- )
1854
- ] }),
1855
- /* @__PURE__ */ jsx("div", { className: "px-2 pb-4", children: overflowItems.map((item) => {
1856
- const isActive = isInSection(item, currentSlug);
1857
- return /* @__PURE__ */ jsxs(
1858
- "button",
1859
- {
1860
- type: "button",
1861
- onClick: () => handleItemClick(item),
1862
- className: `flex w-full items-center gap-3 rounded-lg px-3 py-2.5 text-sm font-medium transition-colors ${isActive ? "bg-sidebar-primary text-sidebar-primary-foreground" : "text-sidebar-foreground hover:bg-sidebar-accent"}`,
1863
- children: [
1864
- item.icon && /* @__PURE__ */ jsx(RepIcon, { name: item.icon, className: "size-5" }),
1865
- /* @__PURE__ */ jsx("span", { children: item.label })
1866
- ]
1867
- },
1868
- item.id ?? item.slug ?? item.label
1869
- );
1870
- }) })
1871
- ] })
1872
- ] })
1873
- ] });
1874
- }
1875
- var SPIN_STYLE_ID2 = "fluid-app-shell-loading-spin";
1876
- function ensureSpinStyle2() {
1877
- if (typeof document === "undefined") return;
1878
- if (document.getElementById(SPIN_STYLE_ID2)) return;
1879
- const style = document.createElement("style");
1880
- style.id = SPIN_STYLE_ID2;
1881
- style.textContent = `@keyframes spin { to { transform: rotate(360deg); } }`;
1882
- document.head.appendChild(style);
1883
- }
1884
- function AppShellLoading() {
1885
- useEffect(() => {
1886
- ensureSpinStyle2();
1887
- }, []);
1888
- return /* @__PURE__ */ jsxs(
1889
- "div",
1890
- {
1891
- style: {
1892
- display: "flex",
1893
- flexDirection: "column",
1894
- alignItems: "center",
1895
- justifyContent: "center",
1896
- minHeight: "100vh",
1897
- fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif',
1898
- backgroundColor: "#f9fafb"
1899
- },
1900
- children: [
1901
- /* @__PURE__ */ jsx(
1902
- "div",
1903
- {
1904
- style: {
1905
- width: "40px",
1906
- height: "40px",
1907
- border: "3px solid #e5e7eb",
1908
- borderTopColor: "#3b82f6",
1909
- borderRadius: "50%",
1910
- animation: "spin 1s linear infinite"
1911
- }
1912
- }
1913
- ),
1914
- /* @__PURE__ */ jsx(
1915
- "p",
1916
- {
1917
- style: {
1918
- marginTop: "1rem",
1919
- color: "#6b7280",
1920
- fontSize: "0.875rem"
1921
- },
1922
- children: "Loading..."
1923
- }
1924
- )
1925
- ]
1926
- }
1927
- );
1928
- }
1929
- function collectNavSlugs(items) {
1930
- const slugs = [];
1931
- for (const item of items) {
1932
- if (item.slug) slugs.push(normalizeSlug(item.slug));
1933
- for (const child of item.children ?? []) {
1934
- if (child.slug) slugs.push(normalizeSlug(child.slug));
1935
- }
1936
- }
1937
- return [...slugs].sort((a, b) => b.split("/").length - a.split("/").length);
1938
- }
1939
- function matchSlugPrefix(fullSlug, navSlugs) {
1940
- const normalized = normalizeSlug(fullSlug);
1941
- if (!normalized) return void 0;
1942
- for (const navSlug of navSlugs) {
1943
- if (normalized === navSlug) {
1944
- return { matchedSlug: navSlug, rest: "" };
1945
- }
1946
- if (normalized.startsWith(navSlug + "/")) {
1947
- return {
1948
- matchedSlug: navSlug,
1949
- rest: normalized.slice(navSlug.length + 1)
1950
- };
1951
- }
1952
- }
1953
- return void 0;
1954
- }
1955
- function extractSlugFromPathname(pathname, basePath) {
1956
- if (basePath === "/") {
1957
- return pathname.replace(/^\//, "");
1958
- }
1959
- if (pathname.startsWith(basePath)) {
1960
- return pathname.slice(basePath.length).replace(/^\//, "");
1961
- }
1962
- return pathname.replace(/^\//, "");
1963
- }
1964
- function isSlugInSection(item, currentSlug, navSlugs) {
1965
- const match = matchSlugPrefix(currentSlug, navSlugs);
1966
- const baseSlug = match?.matchedSlug ?? normalizeSlug(currentSlug);
1967
- if (normalizeSlug(item.slug) === baseSlug) return true;
1968
- return item.children?.some((child) => normalizeSlug(child.slug) === baseSlug) ?? false;
1969
- }
1970
- function SdkNavigation({
1971
- navItems,
1972
- currentSlug,
1973
- onNavigate,
1974
- navSlugs
1975
- }) {
1976
- return /* @__PURE__ */ jsx(SidebarMenu, { children: navItems.map((item, index) => {
1977
- if (!item.slug && !item.label) return null;
1978
- if (!item.slug) {
1979
- return /* @__PURE__ */ jsx(SidebarGroupLabel, { children: item.label }, item.id ?? `section-${index}`);
1980
- }
1981
- const itemSlug = normalizeSlug(item.slug);
1982
- const isActive = isSlugInSection(item, currentSlug, navSlugs);
1983
- return /* @__PURE__ */ jsx(SidebarMenuItem, { children: /* @__PURE__ */ jsxs(
1984
- SidebarMenuButton,
1985
- {
1986
- isActive,
1987
- onClick: () => onNavigate(itemSlug),
1988
- children: [
1989
- item.icon && /* @__PURE__ */ jsx(RepIcon, { name: item.icon }),
1990
- /* @__PURE__ */ jsx("span", { className: "truncate", children: item.label })
1991
- ]
1992
- }
1993
- ) }, item.id ?? itemSlug);
1994
- }) });
1995
- }
1996
- function QuickLinksDropdown({ onNavigate }) {
1997
- const [open, setOpen] = useState(false);
1998
- const panelRef = useRef(null);
1999
- const buttonRef = useRef(null);
2000
- const close = useCallback(() => setOpen(false), []);
2001
- useEffect(() => {
2002
- if (!open) return;
2003
- const handleMouseDown = (e) => {
2004
- if (panelRef.current && !panelRef.current.contains(e.target) && buttonRef.current && !buttonRef.current.contains(e.target)) {
2005
- close();
2006
- }
2007
- };
2008
- const handleKeyDown = (e) => {
2009
- if (e.key === "Escape") close();
2010
- };
2011
- document.addEventListener("mousedown", handleMouseDown);
2012
- document.addEventListener("keydown", handleKeyDown);
2013
- return () => {
2014
- document.removeEventListener("mousedown", handleMouseDown);
2015
- document.removeEventListener("keydown", handleKeyDown);
2016
- };
2017
- }, [open, close]);
2018
- const sections = getSystemNavigationBySection();
2019
- const handleItemClick = (slug) => {
2020
- onNavigate(slug);
2021
- close();
2022
- };
2023
- return /* @__PURE__ */ jsxs("div", { className: "relative", children: [
2024
- /* @__PURE__ */ jsx(
2025
- "button",
2026
- {
2027
- ref: buttonRef,
2028
- type: "button",
2029
- onClick: () => setOpen((prev) => !prev),
2030
- className: "text-sidebar-foreground hover:bg-sidebar-accent hover:text-sidebar-accent-foreground flex shrink-0 items-center justify-center rounded-md p-2",
2031
- "aria-label": "Quick links",
2032
- "aria-expanded": open,
2033
- children: /* @__PURE__ */ jsx(FontAwesomeIcon, { icon: faTableCellsLarge, className: "h-4 w-4" })
2034
- }
2035
- ),
2036
- open && /* @__PURE__ */ jsx(
2037
- "div",
2038
- {
2039
- ref: panelRef,
2040
- className: "border-border bg-background absolute top-full right-0 z-50 mt-1 w-[700px] max-w-[90vw] overflow-hidden rounded-lg border shadow-lg",
2041
- children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
2042
- /* @__PURE__ */ jsxs("div", { className: "bg-background flex items-center gap-2 border-b p-4", children: [
2043
- /* @__PURE__ */ jsx(
2044
- FontAwesomeIcon,
2045
- {
2046
- icon: faTableCellsLarge,
2047
- className: "text-muted-foreground h-5 w-5"
2048
- }
2049
- ),
2050
- /* @__PURE__ */ jsx("h3", { className: "text-foreground text-sm font-semibold", children: "Shortcuts" })
2051
- ] }),
2052
- /* @__PURE__ */ jsx("div", { className: "bg-muted space-y-6 p-6", children: Object.entries(sections).map(([sectionName, items]) => /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
2053
- /* @__PURE__ */ jsx("h3", { className: "text-foreground text-sm font-semibold", children: sectionName }),
2054
- /* @__PURE__ */ jsx("div", { className: "grid grid-cols-4 gap-2", children: items.map((item) => /* @__PURE__ */ jsxs(
2055
- "button",
2056
- {
2057
- type: "button",
2058
- onClick: () => handleItemClick(item.slug),
2059
- className: "text-sidebar-foreground hover:bg-sidebar-primary hover:text-sidebar-primary-foreground flex items-center gap-2 rounded-lg px-3 py-2 text-sm transition-colors",
2060
- children: [
2061
- item.icon && /* @__PURE__ */ jsx(
2062
- RepIcon,
2063
- {
2064
- name: item.icon,
2065
- className: "text-muted-foreground h-4 w-4 shrink-0"
2066
- }
2067
- ),
2068
- /* @__PURE__ */ jsx("span", { className: "truncate", children: item.label })
2069
- ]
2070
- },
2071
- item.slug
2072
- )) })
2073
- ] }, sectionName)) })
2074
- ] })
2075
- }
2076
- )
2077
- ] });
2078
- }
2079
- function SdkHeader({
2080
- tabs,
2081
- mobileTabs,
2082
- currentSlug,
2083
- onNavigate,
2084
- navSlugs
2085
- }) {
2086
- const sidebar = useSidebar();
2087
- const themeMode = useThemeMode();
2088
- const match = matchSlugPrefix(currentSlug, navSlugs);
2089
- const baseSlug = match?.matchedSlug ?? normalizeSlug(currentSlug);
2090
- const themeIcon = themeMode.mode === "dark" ? faMoon : faSun;
2091
- const activeTabs = sidebar.isMobile && sidebar.useBottomNav && mobileTabs ? mobileTabs : tabs;
2092
- return /* @__PURE__ */ jsxs("header", { className: "bg-sidebar flex h-[52px] shrink-0 items-center gap-2 px-6", children: [
2093
- sidebar.isMobile && !sidebar.useBottomNav && /* @__PURE__ */ jsx(
2094
- "button",
2095
- {
2096
- type: "button",
2097
- onClick: sidebar.toggleSidebar,
2098
- className: "text-sidebar-foreground hover:bg-sidebar-accent hover:text-sidebar-accent-foreground mr-2 flex shrink-0 items-center justify-center rounded-md p-2",
2099
- "aria-label": "Toggle sidebar",
2100
- children: /* @__PURE__ */ jsx(FontAwesomeIcon, { icon: faBars, className: "size-5" })
2101
- }
2102
- ),
2103
- /* @__PURE__ */ jsx("nav", { className: "scrollbar-none flex flex-1 items-center gap-1 overflow-x-auto", children: activeTabs.map((tab) => {
2104
- const tabSlug = normalizeSlug(tab.slug);
2105
- if (!tabSlug) return null;
2106
- const isActive = tabSlug === baseSlug;
2107
- return /* @__PURE__ */ jsx(
2108
- "button",
2109
- {
2110
- type: "button",
2111
- onClick: () => onNavigate(tabSlug),
2112
- className: `border-b-2 px-4 py-3 text-sm font-medium whitespace-nowrap transition-colors ${isActive ? "border-primary text-foreground" : "text-muted-foreground hover:border-border hover:text-foreground border-transparent"}`,
2113
- children: tab.label
2114
- },
2115
- tab.id ?? tabSlug
2116
- );
2117
- }) }),
2118
- /* @__PURE__ */ jsx(QuickLinksDropdown, { onNavigate }),
2119
- /* @__PURE__ */ jsx(
2120
- "button",
2121
- {
2122
- type: "button",
2123
- onClick: themeMode.cycleMode,
2124
- className: "text-sidebar-foreground hover:bg-sidebar-accent hover:text-sidebar-accent-foreground ml-2 flex shrink-0 items-center justify-center rounded-md p-2",
2125
- "aria-label": `Switch theme (current: ${themeMode.mode})`,
2126
- children: /* @__PURE__ */ jsx(FontAwesomeIcon, { icon: themeIcon, className: "size-3" })
2127
- }
2128
- )
2129
- ] });
2130
- }
2131
- function WidgetRenderer({ widget, index }) {
2132
- const registry = useRegistry();
2133
- const Component = registry[widget.type];
2134
- if (!Component) {
2135
- console.warn(
2136
- `[BuilderScreenView] Widget type "${String(widget.type)}" not found in registry`
2137
- );
2138
- return null;
2139
- }
2140
- if (widget.dataSource) {
2141
- return /* @__PURE__ */ jsx("div", { className: "h-full w-full overflow-x-hidden", children: /* @__PURE__ */ jsx(DataAwareWidget, { widget, Component }) }, widget.id ?? index);
2142
- }
2143
- return /* @__PURE__ */ jsx("div", { className: "h-full w-full overflow-x-hidden", children: /* @__PURE__ */ jsx(Component, { ...widget.props }) }, widget.id ?? index);
2144
- }
2145
- function BuilderScreenViewImpl({ screen, className }) {
2146
- const widgets = screen.component_tree;
2147
- if (!widgets || widgets.length === 0) {
2148
- return /* @__PURE__ */ jsx("div", { className: className ?? "h-full w-full", children: /* @__PURE__ */ jsx("div", { className: "text-muted-foreground flex h-full items-center justify-center", children: /* @__PURE__ */ jsx("p", { children: "This screen has no content yet." }) }) });
2149
- }
2150
- return /* @__PURE__ */ jsx("div", { className: className ?? "h-full w-full", children: widgets.map((widget, index) => {
2151
- if (!widget) return null;
2152
- return /* @__PURE__ */ jsx(
2153
- WidgetRenderer,
2154
- {
2155
- widget,
2156
- index
2157
- },
2158
- widget.id ?? index
2159
- );
2160
- }) });
2161
- }
2162
- var BuilderScreenView = memo(BuilderScreenViewImpl);
2163
- var SYSTEM_SLUG_SCREEN_MAP = {
2164
- messages: MessagingScreen,
2165
- contacts: ContactsScreen,
2166
- shop: OrdersScreen,
2167
- customers: CustomersScreen,
2168
- products: ProductsScreen
2169
- };
2170
- function PageRouter({
2171
- currentSlug,
2172
- currentNavItem,
2173
- customPages,
2174
- screens,
2175
- baseSlug,
2176
- restParams
2177
- }) {
2178
- const screenById = useMemo(() => {
2179
- if (!screens || screens.length === 0) return void 0;
2180
- return new Map(screens.map((s) => [s.id, s]));
2181
- }, [screens]);
2182
- const screenBySlug = useMemo(() => {
2183
- if (!screens || screens.length === 0) return void 0;
2184
- return new Map(screens.filter((s) => s.slug).map((s) => [s.slug, s]));
2185
- }, [screens]);
2186
- const builderScreen = useMemo(() => {
2187
- if (currentNavItem?.screen_id && screenById) {
2188
- const byId = screenById.get(currentNavItem.screen_id);
2189
- if (byId) return byId;
2190
- }
2191
- if (screenBySlug) {
2192
- return screenBySlug.get(currentSlug) ?? screenBySlug.get(baseSlug) ?? void 0;
2193
- }
2194
- return void 0;
2195
- }, [
2196
- currentNavItem?.screen_id,
2197
- screenById,
2198
- screenBySlug,
2199
- currentSlug,
2200
- baseSlug
2201
- ]);
2202
- const SystemScreen = SYSTEM_SLUG_SCREEN_MAP[baseSlug];
2203
- if (SystemScreen) {
2204
- return /* @__PURE__ */ jsx(SystemScreen, {});
2205
- }
2206
- if (isSystemNavigationItem(baseSlug)) {
2207
- return /* @__PURE__ */ jsx(CoreScreenPlaceholder, { name: currentNavItem?.label ?? baseSlug });
2208
- }
2209
- const ExactCustomPage = customPages?.[currentSlug];
2210
- if (ExactCustomPage) {
2211
- return /* @__PURE__ */ jsx(ExactCustomPage, { slug: currentSlug, params: restParams });
2212
- }
2213
- if (baseSlug !== currentSlug) {
2214
- const PrefixCustomPage = customPages?.[baseSlug];
2215
- if (PrefixCustomPage) {
2216
- return /* @__PURE__ */ jsx(PrefixCustomPage, { slug: currentSlug, params: restParams });
2217
- }
2218
- }
2219
- if (builderScreen) {
2220
- return /* @__PURE__ */ jsx(BuilderScreenView, { screen: builderScreen });
2221
- }
2222
- return /* @__PURE__ */ jsx(CoreScreenPlaceholder, { name: currentNavItem?.label ?? currentSlug });
2223
- }
2224
- var AppNavigationContext = createContext(
2225
- null
2226
- );
2227
- function AppNavigationProvider({
2228
- currentSlug,
2229
- basePath,
2230
- navigate,
2231
- children
2232
- }) {
2233
- const buildHref = useMemo(() => {
2234
- return (slug) => {
2235
- if (basePath === "/") return `/${slug}`;
2236
- return `${basePath}/${slug}`;
2237
- };
2238
- }, [basePath]);
2239
- const value = useMemo(
2240
- () => ({ currentSlug, basePath, navigate, buildHref }),
2241
- [currentSlug, basePath, navigate, buildHref]
2242
- );
2243
- return /* @__PURE__ */ jsx(AppNavigationContext.Provider, { value, children });
2244
- }
2245
- function useAppNavigation() {
2246
- const ctx = useContext(AppNavigationContext);
2247
- if (!ctx) {
2248
- throw new Error(
2249
- "useAppNavigation must be used within an <AppShell> or <AppNavigationProvider>"
2250
- );
2251
- }
2252
- return ctx;
2253
- }
2254
- var THEME_STORAGE_KEY = "rep-theme-mode";
2255
- var DEFAULT_NAVIGATION = [
2256
- { label: "We Commerce", children: [] },
2257
- { slug: "shop", label: "Shop", icon: "store", children: [] },
2258
- { slug: "account", label: "Account", icon: "user-gear", children: [] },
2259
- { slug: "messages", label: "Messaging", icon: "comment", children: [] },
2260
- { label: "Marketing Assets", children: [] },
2261
- {
2262
- slug: "share/products",
2263
- label: "Products",
2264
- icon: "boxes-stacked",
2265
- children: []
2266
- }
2267
- ];
2268
- function getInitialThemeMode() {
2269
- if (typeof window === "undefined") return "light";
2270
- const stored = localStorage.getItem(THEME_STORAGE_KEY);
2271
- if (stored === "light" || stored === "dark") return stored;
2272
- return "light";
2273
- }
2274
- function findFirstNavigableSlug(items) {
2275
- for (const item of items) {
2276
- if (item.slug) return normalizeSlug(item.slug);
2277
- for (const child of item.children ?? []) {
2278
- if (child.slug) return normalizeSlug(child.slug);
2279
- }
2280
- }
2281
- return "";
2282
- }
2283
- function findCurrentSection(items, slug) {
2284
- const normalized = normalizeSlug(slug);
2285
- for (const item of items) {
2286
- if (normalizeSlug(item.slug) === normalized) return item;
2287
- if (item.children?.some((child) => normalizeSlug(child.slug) === normalized)) {
2288
- return item;
2289
- }
2290
- }
2291
- return void 0;
2292
- }
2293
- function findNavItem(items, slug) {
2294
- const normalized = normalizeSlug(slug);
2295
- for (const item of items) {
2296
- if (normalizeSlug(item.slug) === normalized) return item;
2297
- for (const child of item.children ?? []) {
2298
- if (normalizeSlug(child.slug) === normalized) return child;
2299
- }
2300
- }
2301
- return void 0;
2302
- }
2303
- function AppShell({
2304
- appData: appDataProp,
2305
- navigation: navigationProp,
2306
- customPages,
2307
- basePath = "/",
2308
- currentSlug: controlledSlug,
2309
- onNavigate: onNavigateProp,
2310
- sidebarHeader,
2311
- sidebarFooter,
2312
- children
2313
- }) {
2314
- const normalizedBasePath = useMemo(() => {
2315
- const stripped = basePath.replace(/^\/|\/$/g, "");
2316
- return stripped ? `/${stripped}` : "/";
2317
- }, [basePath]);
2318
- const { data: fetchedAppData, isLoading: isLoading2 } = useFluidApp({
2319
- enabled: !appDataProp
2320
- });
2321
- const appData = appDataProp ?? fetchedAppData;
2322
- const activeTheme = useMemo(() => {
2323
- if (!appData?.profile?.themes?.length) return void 0;
2324
- const themes = appData.profile.themes;
2325
- const activeId = appData.profile.activeThemeId;
2326
- return activeId ? themes.find((t) => t.id === activeId) ?? themes[0] : themes[0];
2327
- }, [appData?.profile?.themes, appData?.profile?.activeThemeId]);
2328
- useEffect(() => {
2329
- if (!activeTheme) return;
2330
- const resolved = resolveTheme(activeTheme);
2331
- applyTheme(resolved);
2332
- return () => {
2333
- removeAllThemes();
2334
- };
2335
- }, [activeTheme]);
2336
- const navItems = useMemo(() => {
2337
- if (navigationProp) return navigationProp;
2338
- const profileNav = appData?.profile?.navigation?.navigation_items;
2339
- if (profileNav && profileNav.length > 0) return profileNav;
2340
- return DEFAULT_NAVIGATION;
2341
- }, [navigationProp, appData?.profile?.navigation?.navigation_items]);
2342
- const mobileNavItems = useMemo(() => {
2343
- const mobileNav = appData?.profile?.mobile_navigation?.navigation_items;
2344
- if (mobileNav && mobileNav.length > 0) return mobileNav;
2345
- return navItems;
2346
- }, [appData?.profile?.mobile_navigation?.navigation_items, navItems]);
2347
- const screens = appData?.screens;
2348
- const navSlugs = useMemo(() => collectNavSlugs(navItems), [navItems]);
2349
- const [themeMode, setThemeMode] = useState(getInitialThemeMode);
2350
- const handleThemeModeChange = useCallback((mode) => {
2351
- setThemeMode(mode);
2352
- if (typeof window !== "undefined") {
2353
- localStorage.setItem(THEME_STORAGE_KEY, mode);
2354
- }
2355
- }, []);
2356
- const [pathSlug, setPathSlug] = useState(() => {
2357
- if (typeof window === "undefined") return "";
2358
- return extractSlugFromPathname(
2359
- window.location.pathname,
2360
- normalizedBasePath
2361
- );
2362
- });
2363
- useEffect(() => {
2364
- if (controlledSlug !== void 0) return;
2365
- if (typeof window === "undefined") return;
2366
- const currentPath = extractSlugFromPathname(
2367
- window.location.pathname,
2368
- normalizedBasePath
2369
- );
2370
- if (!currentPath) {
2371
- const firstSlug = findFirstNavigableSlug(navItems);
2372
- if (firstSlug) {
2373
- const targetPath = normalizedBasePath === "/" ? `/${firstSlug}` : `${normalizedBasePath}/${firstSlug}`;
2374
- history.replaceState(null, "", targetPath);
2375
- setPathSlug(firstSlug);
2376
- }
2377
- }
2378
- }, [navItems, controlledSlug, normalizedBasePath]);
2379
- useEffect(() => {
2380
- if (controlledSlug !== void 0) return;
2381
- const handlePopState = () => {
2382
- const slug = extractSlugFromPathname(
2383
- window.location.pathname,
2384
- normalizedBasePath
2385
- );
2386
- setPathSlug(slug);
2387
- };
2388
- window.addEventListener("popstate", handlePopState);
2389
- return () => window.removeEventListener("popstate", handlePopState);
2390
- }, [controlledSlug, normalizedBasePath]);
2391
- const activeSlug = controlledSlug ?? pathSlug;
2392
- const handleNavigate = useCallback(
2393
- (slug) => {
2394
- if (onNavigateProp) {
2395
- onNavigateProp(slug);
2396
- return;
2397
- }
2398
- const targetPath = normalizedBasePath === "/" ? `/${slug}` : `${normalizedBasePath}/${slug}`;
2399
- history.pushState(null, "", targetPath);
2400
- setPathSlug(slug);
2401
- },
2402
- [onNavigateProp, normalizedBasePath]
2403
- );
2404
- const slugMatch = useMemo(
2405
- () => matchSlugPrefix(activeSlug, navSlugs),
2406
- [activeSlug, navSlugs]
2407
- );
2408
- const baseSlug = slugMatch?.matchedSlug ?? normalizeSlug(activeSlug);
2409
- const restParams = slugMatch?.rest ?? "";
2410
- const currentSection = findCurrentSection(navItems, baseSlug);
2411
- const secondLevelTabs = currentSection?.children ?? [];
2412
- const mobileCurrentSection = findCurrentSection(mobileNavItems, baseSlug);
2413
- const mobileSecondLevelTabs = mobileCurrentSection?.children ?? [];
2414
- const currentNavItem = findNavItem(navItems, baseSlug);
2415
- const screenTitle = currentNavItem?.label || screens?.find((s) => s.id === currentNavItem?.screen_id)?.name || void 0;
2416
- const content = typeof children === "function" ? children({ currentSlug: activeSlug, currentNavItem }) : children ?? /* @__PURE__ */ jsxs(ScreenHeaderProvider, { children: [
2417
- /* @__PURE__ */ jsx(ScreenHeader, { title: screenTitle }),
2418
- /* @__PURE__ */ jsx(
2419
- PageRouter,
2420
- {
2421
- currentSlug: activeSlug,
2422
- currentNavItem,
2423
- customPages,
2424
- screens,
2425
- baseSlug,
2426
- restParams
2427
- }
2428
- )
2429
- ] });
2430
- if (isLoading2 && !appData) {
2431
- return /* @__PURE__ */ jsx(AppShellLoading, {});
2432
- }
2433
- return /* @__PURE__ */ jsx(
2434
- ThemeModeProvider,
2435
- {
2436
- mode: themeMode,
2437
- onModeChange: handleThemeModeChange,
2438
- autoModeEnabled: false,
2439
- children: /* @__PURE__ */ jsx(
2440
- AppNavigationProvider,
2441
- {
2442
- currentSlug: activeSlug,
2443
- basePath: normalizedBasePath,
2444
- navigate: handleNavigate,
2445
- children: /* @__PURE__ */ jsx(
2446
- "div",
2447
- {
2448
- "data-theme": activeTheme?.id,
2449
- "data-theme-mode": themeMode === "auto" ? void 0 : themeMode,
2450
- children: /* @__PURE__ */ jsx(
2451
- AppShellLayout,
2452
- {
2453
- sidebarContent: /* @__PURE__ */ jsx(
2454
- SdkNavigation,
2455
- {
2456
- navItems,
2457
- currentSlug: activeSlug,
2458
- onNavigate: handleNavigate,
2459
- navSlugs
2460
- }
2461
- ),
2462
- headerContent: /* @__PURE__ */ jsx(
2463
- SdkHeader,
2464
- {
2465
- tabs: secondLevelTabs,
2466
- mobileTabs: mobileSecondLevelTabs,
2467
- currentSlug: activeSlug,
2468
- onNavigate: handleNavigate,
2469
- navSlugs
2470
- }
2471
- ),
2472
- sidebarHeader,
2473
- sidebarFooter,
2474
- useBottomNav: true,
2475
- afterContent: /* @__PURE__ */ jsx(
2476
- SdkBottomNav,
2477
- {
2478
- navItems: mobileNavItems,
2479
- currentSlug: activeSlug,
2480
- onNavigate: handleNavigate
2481
- }
2482
- ),
2483
- children: content
2484
- }
2485
- )
2486
- }
2487
- )
2488
- }
2489
- )
2490
- }
2491
- );
2492
- }
2493
- var AppLink = forwardRef(
2494
- function AppLink2({ to, onClick, children, ...rest }, ref) {
2495
- const { navigate, buildHref } = useAppNavigation();
2496
- const handleClick = (e) => {
2497
- onClick?.(e);
2498
- if (e.defaultPrevented) return;
2499
- if (e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return;
2500
- if (e.button !== 0) return;
2501
- if (rest.target && rest.target !== "_self") return;
2502
- e.preventDefault();
2503
- navigate(to);
2504
- };
2505
- return /* @__PURE__ */ jsx("a", { ref, href: buildHref(to), onClick: handleClick, ...rest, children });
2506
- }
2507
- );
2508
- var export_DEFAULT_COLORS = themes_exports.DEFAULT_COLORS;
2509
- var export_DEFAULT_FONT_FAMILIES = themes_exports.DEFAULT_FONT_FAMILIES;
2510
- var export_DEFAULT_FONT_SIZES = themes_exports.DEFAULT_FONT_SIZES;
2511
- var export_DEFAULT_RADII = themes_exports.DEFAULT_RADII;
2512
- var export_DEFAULT_SPACING = themes_exports.DEFAULT_SPACING;
2513
- var export_DEFAULT_THEME_ID = themes_exports.DEFAULT_THEME_ID;
2514
- var export_DEFAULT_THEME_NAME = themes_exports.DEFAULT_THEME_NAME;
2515
- var export_FONT_FAMILY_KEYS = themes_exports.FONT_FAMILY_KEYS;
2516
- var export_FONT_SIZE_KEYS = themes_exports.FONT_SIZE_KEYS;
2517
- var export_RADIUS_KEYS = themes_exports.RADIUS_KEYS;
2518
- var export_SEMANTIC_COLOR_NAMES = themes_exports.SEMANTIC_COLOR_NAMES;
2519
- var export_SHADE_STEPS = themes_exports.SHADE_STEPS;
2520
- var export_applyTheme = themes_exports.applyTheme;
2521
- var export_deriveDarkVariant = themes_exports.deriveDarkVariant;
2522
- var export_deserialiseTheme = themes_exports.deserialiseTheme;
2523
- var export_generateShades = themes_exports.generateShades;
2524
- var export_generateThemeCSS = themes_exports.generateThemeCSS;
2525
- var export_getDefaultThemeDefinition = themes_exports.getDefaultThemeDefinition;
2526
- var export_getForegroundColor = themes_exports.getForegroundColor;
2527
- var export_mergeDarkOverrides = themes_exports.mergeDarkOverrides;
2528
- var export_parseColor = themes_exports.parseColor;
2529
- var export_removeAllThemes = themes_exports.removeAllThemes;
2530
- var export_removeTheme = themes_exports.removeTheme;
2531
- var export_resolveTheme = themes_exports.resolveTheme;
2532
- var export_serialiseTheme = themes_exports.serialiseTheme;
2533
-
2534
- export { ACTIVITY_SLUGS, APP_DATA_QUERY_KEY, AppLink, AppNavigationProvider, AppShell, AuthError, AuthLoading, BuilderScreenView, CORE_PAGE_IDS, CURRENT_REP_QUERY_KEY, export_DEFAULT_COLORS as DEFAULT_COLORS, export_DEFAULT_FONT_FAMILIES as DEFAULT_FONT_FAMILIES, export_DEFAULT_FONT_SIZES as DEFAULT_FONT_SIZES, export_DEFAULT_RADII as DEFAULT_RADII, export_DEFAULT_SPACING as DEFAULT_SPACING, export_DEFAULT_THEME_ID as DEFAULT_THEME_ID, export_DEFAULT_THEME_NAME as DEFAULT_THEME_NAME, export_FONT_FAMILY_KEYS as FONT_FAMILY_KEYS, export_FONT_SIZE_KEYS as FONT_SIZE_KEYS, PAGE_CATEGORIES, PERMISSIONS_QUERY_KEY, PROFILE_QUERY_KEY, PageRouter, PageTemplateProvider, PageTemplateRegistry, QuickLinksDropdown, export_RADIUS_KEYS as RADIUS_KEYS, RequireAuth, export_SEMANTIC_COLOR_NAMES as SEMANTIC_COLOR_NAMES, export_SHADE_STEPS as SHADE_STEPS, SdkHeader, SdkNavigation, export_applyTheme as applyTheme, collectNavSlugs, export_deriveDarkVariant as deriveDarkVariant, export_deserialiseTheme as deserialiseTheme, extractSlugFromPathname, export_generateShades as generateShades, export_generateThemeCSS as generateThemeCSS, getAvailablePageTemplates, getCorePageTemplates, export_getDefaultThemeDefinition as getDefaultThemeDefinition, export_getForegroundColor as getForegroundColor, getOptionalPageTemplates, getProperty, hasData, isActivitySlug, isContactStatus, isErrorResult, isIdle, isLoading, isSlugInSection, matchSlugPrefix, export_mergeDarkOverrides as mergeDarkOverrides, export_parseColor as parseColor, export_removeAllThemes as removeAllThemes, export_removeTheme as removeTheme, resolveNavigationPages, export_resolveTheme as resolveTheme, screenPropertySchemas, selectProperty, export_serialiseTheme as serialiseTheme, useActivities, useAppNavigation, useCalendarEvents, useCatchUps, useContact, useContacts, useConversationMessages, useConversations, useCurrentRep, useFluidApp, useFluidAuth, useFluidPermissions, useFluidProfile, useFluidTheme, useMySite, usePageTemplates, useResolvedPages, useTodos, validateNavigationPages };
2535
- //# sourceMappingURL=index.js.map
2536
- //# sourceMappingURL=index.js.map