@elevasis/ui 2.20.0 → 2.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/dist/api/index.js +2 -2
  2. package/dist/app/index.js +4 -4
  3. package/dist/charts/index.js +3 -3
  4. package/dist/{chunk-FMFX4K6E.js → chunk-7GG6OSD7.js} +34 -9
  5. package/dist/{chunk-GTYUP7MB.js → chunk-ATEHYDL3.js} +5 -21
  6. package/dist/{chunk-AL23U6C3.js → chunk-BIWHHWCJ.js} +1 -2
  7. package/dist/{chunk-JR5WNTLA.js → chunk-BJWIKEQG.js} +6 -11
  8. package/dist/{chunk-GP3AFJYG.js → chunk-CZK67OHH.js} +6 -11
  9. package/dist/{chunk-TO7QXDBX.js → chunk-DMYELNGA.js} +2 -2
  10. package/dist/{chunk-2CFOFSSG.js → chunk-EDX6WIN3.js} +6 -11
  11. package/dist/{chunk-PJVG3ISO.js → chunk-EGKNRM6P.js} +6 -8
  12. package/dist/{chunk-ZE2KQSHL.js → chunk-I5WRKH25.js} +4 -4
  13. package/dist/chunk-KVW56ERD.js +24 -0
  14. package/dist/{chunk-YP6T426C.js → chunk-LQU62KHD.js} +144 -432
  15. package/dist/{chunk-OUYH2SBS.js → chunk-LVUCBY7X.js} +2 -2
  16. package/dist/chunk-S7RL77QS.js +48 -0
  17. package/dist/{chunk-OD7GWIZS.js → chunk-SGXXJE52.js} +1 -121
  18. package/dist/{chunk-R7OJCNL3.js → chunk-T6INEVX6.js} +1 -1
  19. package/dist/{chunk-CTTY6FUT.js → chunk-TSSKOQBX.js} +2 -2
  20. package/dist/{chunk-Q4QJOSVS.js → chunk-ULZ2B3NC.js} +1 -1
  21. package/dist/chunk-VQESMHQV.js +336 -0
  22. package/dist/{chunk-MZFJWCPH.js → chunk-XLZZOFGM.js} +5 -19
  23. package/dist/{chunk-BHR7IV72.js → chunk-XUYBOO32.js} +1 -1
  24. package/dist/{chunk-M7W7CGPL.js → chunk-Z6FAH4XV.js} +1 -1
  25. package/dist/components/index.d.ts +46 -87
  26. package/dist/components/index.js +27 -26
  27. package/dist/components/navigation/index.d.ts +1 -13
  28. package/dist/components/navigation/index.js +11 -1
  29. package/dist/execution/index.d.ts +27 -0
  30. package/dist/features/crm/index.d.ts +12 -35
  31. package/dist/features/crm/index.js +11 -10
  32. package/dist/features/dashboard/index.d.ts +25 -27
  33. package/dist/features/dashboard/index.js +12 -11
  34. package/dist/features/delivery/index.d.ts +12 -35
  35. package/dist/features/delivery/index.js +11 -10
  36. package/dist/features/lead-gen/index.d.ts +14 -37
  37. package/dist/features/lead-gen/index.js +11 -10
  38. package/dist/features/monitoring/index.d.ts +12 -35
  39. package/dist/features/monitoring/index.js +13 -12
  40. package/dist/features/monitoring/requests/index.d.ts +13 -36
  41. package/dist/features/monitoring/requests/index.js +11 -10
  42. package/dist/features/operations/index.d.ts +44 -65
  43. package/dist/features/operations/index.js +14 -13
  44. package/dist/features/seo/index.d.ts +12 -35
  45. package/dist/features/seo/index.js +1 -1
  46. package/dist/features/settings/index.d.ts +12 -35
  47. package/dist/features/settings/index.js +11 -10
  48. package/dist/hooks/delivery/index.js +2 -2
  49. package/dist/hooks/index.d.ts +46 -66
  50. package/dist/hooks/index.js +10 -9
  51. package/dist/hooks/operations/command-view/utils/transformCommandViewData.d.ts +92 -121
  52. package/dist/hooks/published.d.ts +46 -66
  53. package/dist/hooks/published.js +10 -9
  54. package/dist/index.d.ts +365 -452
  55. package/dist/index.js +10 -9
  56. package/dist/provider/index.d.ts +62 -125
  57. package/dist/provider/index.js +8 -7
  58. package/dist/provider/published.d.ts +62 -125
  59. package/dist/provider/published.js +6 -5
  60. package/dist/test-utils/index.js +2 -2
  61. package/dist/types/index.d.ts +108 -135
  62. package/dist/utils/index.d.ts +26 -59
  63. package/dist/utils/index.js +1 -1
  64. package/package.json +4 -4
  65. package/dist/chunk-LR5CRY5A.js +0 -514
  66. package/dist/chunk-MG3NF7QL.js +0 -63
@@ -1,6 +1,6 @@
1
- import { ApiClientProvider, useApiClient } from './chunk-R7OJCNL3.js';
1
+ import { ApiClientProvider, useApiClient } from './chunk-T6INEVX6.js';
2
2
  import { OrganizationProvider } from './chunk-6IA2OMAE.js';
3
- import { getErrorInfo, getErrorTitle, formatErrorMessage } from './chunk-OD7GWIZS.js';
3
+ import { getErrorInfo, getErrorTitle, formatErrorMessage } from './chunk-SGXXJE52.js';
4
4
  import { InitializationProvider } from './chunk-DK2HVHCY.js';
5
5
  import { useOrganization } from './chunk-DD3CCMCZ.js';
6
6
  import { ProfileProvider } from './chunk-QHSW4WHM.js';
@@ -0,0 +1,48 @@
1
+ import { useOptionalElevasisFeatures } from './chunk-VQESMHQV.js';
2
+ import { useRouterContext } from './chunk-Q7DJKLEN.js';
3
+ import { useMemo } from 'react';
4
+
5
+ var useBreadcrumbs = (options = {}) => {
6
+ const { currentPath } = useRouterContext();
7
+ const featureContext = useOptionalElevasisFeatures();
8
+ const { labelsByPath = {} } = options;
9
+ return useMemo(() => {
10
+ const shellModel = featureContext?.shellModel;
11
+ const overriddenLabel = labelsByPath[currentPath];
12
+ if (overriddenLabel) {
13
+ return [{ label: overriddenLabel, isActive: true }];
14
+ }
15
+ if (shellModel) {
16
+ const matchedNode = shellModel.findByPath(currentPath);
17
+ if (matchedNode) {
18
+ return shellModel.ancestorsOf(matchedNode.id).map((node, index, items) => ({
19
+ label: labelsByPath[node.path ?? ""] ?? node.label,
20
+ path: index === items.length - 1 ? void 0 : node.path,
21
+ isActive: index === items.length - 1
22
+ }));
23
+ }
24
+ }
25
+ const segments = currentPath.split("/").filter(Boolean);
26
+ if (segments.length === 0) {
27
+ return [{ label: "Dashboard", isActive: true }];
28
+ }
29
+ const breadcrumbs = [{ label: "Dashboard", path: "/" }];
30
+ let currentSegmentPath = "";
31
+ for (let i = 0; i < segments.length; i++) {
32
+ currentSegmentPath += `/${segments[i]}`;
33
+ const isLast = i === segments.length - 1;
34
+ const label = labelsByPath[currentSegmentPath] ?? formatSegmentLabel(segments[i]);
35
+ breadcrumbs.push({
36
+ label,
37
+ path: isLast ? void 0 : currentSegmentPath,
38
+ isActive: isLast
39
+ });
40
+ }
41
+ return breadcrumbs;
42
+ }, [currentPath, featureContext, labelsByPath]);
43
+ };
44
+ function formatSegmentLabel(segment) {
45
+ return segment.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
46
+ }
47
+
48
+ export { useBreadcrumbs };
@@ -191,126 +191,6 @@ z.object({
191
191
  endDate: z.string().datetime()
192
192
  });
193
193
 
194
- // ../core/src/platform/registry/domains.ts
195
- var DOMAINS = {
196
- // Business domains
197
- INBOUND_PIPELINE: "inbound-pipeline",
198
- LEAD_GEN_PIPELINE: "lead-gen-pipeline",
199
- SUPPORT: "support",
200
- CLIENT_SUPPORT: "client-support",
201
- DELIVERY: "delivery",
202
- OPERATIONS: "operations",
203
- FINANCE: "finance",
204
- EXECUTIVE: "executive",
205
- INSTANTLY: "instantly",
206
- // Technical domains
207
- TESTING: "testing",
208
- INTERNAL: "internal",
209
- INTEGRATION: "integration",
210
- UTILITY: "utility",
211
- DIAGNOSTIC: "diagnostic"
212
- };
213
- var INBOUND_PIPELINE_DOMAIN = {
214
- id: DOMAINS.INBOUND_PIPELINE,
215
- name: "Inbound Pipeline",
216
- description: "End-to-end inbound client acquisition from first reply to onboarding",
217
- color: "blue"
218
- };
219
- var LEAD_GEN_PIPELINE_DOMAIN = {
220
- id: DOMAINS.LEAD_GEN_PIPELINE,
221
- name: "Lead Gen Pipeline",
222
- description: "Lead scraping, enrichment, qualification, and personalization",
223
- color: "cyan"
224
- };
225
- var SUPPORT_DOMAIN = {
226
- id: DOMAINS.SUPPORT,
227
- name: "Customer Support",
228
- description: "Ticket triage, knowledge base, escalations",
229
- color: "green"
230
- };
231
- var CLIENT_SUPPORT_DOMAIN = {
232
- id: DOMAINS.CLIENT_SUPPORT,
233
- name: "Client Support",
234
- description: "Client change requests, bug reports, and feature requests",
235
- color: "teal"
236
- };
237
- var DELIVERY_DOMAIN = {
238
- id: DOMAINS.DELIVERY,
239
- name: "Client Delivery",
240
- description: "Project execution and milestone tracking",
241
- color: "orange"
242
- };
243
- var OPERATIONS_DOMAIN = {
244
- id: DOMAINS.OPERATIONS,
245
- name: "Operations",
246
- description: "Internal business operations and administration",
247
- color: "violet"
248
- };
249
- var FINANCE_DOMAIN = {
250
- id: DOMAINS.FINANCE,
251
- name: "Finance",
252
- description: "Billing, invoicing, and financial operations",
253
- color: "pink"
254
- };
255
- var EXECUTIVE_DOMAIN = {
256
- id: DOMAINS.EXECUTIVE,
257
- name: "Executive Operations",
258
- description: "High-level business orchestration and decision-making",
259
- color: "indigo"
260
- };
261
- var TESTING_DOMAIN = {
262
- id: DOMAINS.TESTING,
263
- name: "Testing",
264
- description: "Test resources and development workflows",
265
- color: "gray"
266
- };
267
- var INTERNAL_DOMAIN = {
268
- id: DOMAINS.INTERNAL,
269
- name: "Internal",
270
- description: "Internal platform resources",
271
- color: "dark"
272
- };
273
- var INTEGRATION_DOMAIN = {
274
- id: DOMAINS.INTEGRATION,
275
- name: "Integration",
276
- description: "External service integrations",
277
- color: "teal"
278
- };
279
- var INSTANTLY_DOMAIN = {
280
- id: DOMAINS.INSTANTLY,
281
- name: "Instantly Toolkit",
282
- description: "Instantly campaign creation, analytics, and optimization",
283
- color: "lime"
284
- };
285
- var UTILITY_DOMAIN = {
286
- id: DOMAINS.UTILITY,
287
- name: "Utility",
288
- description: "Utility workflows for maintenance and diagnostics",
289
- color: "grape"
290
- };
291
- var DIAGNOSTIC_DOMAIN = {
292
- id: DOMAINS.DIAGNOSTIC,
293
- name: "Diagnostic",
294
- description: "Diagnostic workflows for testing integrations and services",
295
- color: "yellow"
296
- };
297
- var DOMAIN_MAP = {
298
- [DOMAINS.INBOUND_PIPELINE]: INBOUND_PIPELINE_DOMAIN,
299
- [DOMAINS.LEAD_GEN_PIPELINE]: LEAD_GEN_PIPELINE_DOMAIN,
300
- [DOMAINS.SUPPORT]: SUPPORT_DOMAIN,
301
- [DOMAINS.CLIENT_SUPPORT]: CLIENT_SUPPORT_DOMAIN,
302
- [DOMAINS.DELIVERY]: DELIVERY_DOMAIN,
303
- [DOMAINS.OPERATIONS]: OPERATIONS_DOMAIN,
304
- [DOMAINS.FINANCE]: FINANCE_DOMAIN,
305
- [DOMAINS.EXECUTIVE]: EXECUTIVE_DOMAIN,
306
- [DOMAINS.TESTING]: TESTING_DOMAIN,
307
- [DOMAINS.INTERNAL]: INTERNAL_DOMAIN,
308
- [DOMAINS.INSTANTLY]: INSTANTLY_DOMAIN,
309
- [DOMAINS.INTEGRATION]: INTEGRATION_DOMAIN,
310
- [DOMAINS.UTILITY]: UTILITY_DOMAIN,
311
- [DOMAINS.DIAGNOSTIC]: DIAGNOSTIC_DOMAIN
312
- };
313
-
314
194
  // ../core/src/platform/registry/command-view.ts
315
195
  function getNodeId(node) {
316
196
  return node.resourceId;
@@ -504,4 +384,4 @@ function setupBrowserMocks() {
504
384
  setupResizeObserver();
505
385
  }
506
386
 
507
- export { APIClientError, API_URL, CredentialNameSchema, DEBOUNCE_FILTER, DEBOUNCE_SLIDER, DOMAIN_MAP, GC_TIME_LONG, GC_TIME_MEDIUM, GC_TIME_SHORT, LIMIT_ACTIVITY_FEED, NonEmptyStringSchema, OAUTH_FLOW_TIMEOUT, OAUTH_POPUP_CHECK_INTERVAL, OriginResourceTypeSchema, PAGE_SIZE_DEFAULT, REFETCH_INTERVAL_DASHBOARD, REFETCH_INTERVAL_REALTIME, REFETCH_INTERVAL_RUNNING, REFETCH_INTERVAL_RUNNING_FAST, ResourceTypeSchema, SSE_CLOSE_GRACE_PERIOD, SSE_TOKEN_REFRESH_DELAY, STALE_TIME_ADMIN, STALE_TIME_DEFAULT, STALE_TIME_MONITORING, UuidSchema, WS_MAX_RETRIES_BEFORE_ERROR, WS_RECONNECT_BASE_DELAY, WS_RECONNECT_MAX_DELAY, debounce, formatBucketTime, formatChartAxisDate, formatDate, formatDateTime, formatErrorMessage, formatRelativeTime, formatTimeAgo, getErrorInfo, getErrorTitle, getNodeId, getResourceColor, getResourceIcon, getTimeRangeDates, getTimeRangeLabel, isAPIClientError, restoreConsole, setupBrowserMocks, suppressKnownWarnings, validateEmail };
387
+ export { APIClientError, API_URL, CredentialNameSchema, DEBOUNCE_FILTER, DEBOUNCE_SLIDER, GC_TIME_LONG, GC_TIME_MEDIUM, GC_TIME_SHORT, LIMIT_ACTIVITY_FEED, NonEmptyStringSchema, OAUTH_FLOW_TIMEOUT, OAUTH_POPUP_CHECK_INTERVAL, OriginResourceTypeSchema, PAGE_SIZE_DEFAULT, REFETCH_INTERVAL_DASHBOARD, REFETCH_INTERVAL_REALTIME, REFETCH_INTERVAL_RUNNING, REFETCH_INTERVAL_RUNNING_FAST, ResourceTypeSchema, SSE_CLOSE_GRACE_PERIOD, SSE_TOKEN_REFRESH_DELAY, STALE_TIME_ADMIN, STALE_TIME_DEFAULT, STALE_TIME_MONITORING, UuidSchema, WS_MAX_RETRIES_BEFORE_ERROR, WS_RECONNECT_BASE_DELAY, WS_RECONNECT_MAX_DELAY, debounce, formatBucketTime, formatChartAxisDate, formatDate, formatDateTime, formatErrorMessage, formatRelativeTime, formatTimeAgo, getErrorInfo, getErrorTitle, getNodeId, getResourceColor, getResourceIcon, getTimeRangeDates, getTimeRangeLabel, isAPIClientError, restoreConsole, setupBrowserMocks, suppressKnownWarnings, validateEmail };
@@ -1,4 +1,4 @@
1
- import { APIClientError } from './chunk-OD7GWIZS.js';
1
+ import { APIClientError } from './chunk-SGXXJE52.js';
2
2
  import { OrganizationContext } from './chunk-DD3CCMCZ.js';
3
3
  import { createContext, useContext, useMemo, useCallback } from 'react';
4
4
  import { jsx } from 'react/jsx-runtime';
@@ -1,6 +1,6 @@
1
1
  import { useErrorTrends } from './chunk-QSTH6T77.js';
2
- import { CardHeader, CenteredErrorState, TrendIndicator, EmptyState, StatCard } from './chunk-BHR7IV72.js';
3
- import { getTimeRangeLabel, getTimeRangeDates, formatBucketTime } from './chunk-OD7GWIZS.js';
2
+ import { CardHeader, CenteredErrorState, TrendIndicator, EmptyState, StatCard } from './chunk-XUYBOO32.js';
3
+ import { getTimeRangeLabel, getTimeRangeDates, formatBucketTime } from './chunk-SGXXJE52.js';
4
4
  import { useRef, useState, useLayoutEffect, useEffect, useMemo, useCallback } from 'react';
5
5
  import { jsx, jsxs } from 'react/jsx-runtime';
6
6
  import { useComputedColorScheme, Group, Text, Box, Stack, Center, Loader, Paper, Button, NumberFormatter, Badge, Space, Tooltip as Tooltip$1, SimpleGrid, Alert, SegmentedControl } from '@mantine/core';
@@ -1,4 +1,4 @@
1
- import { ElevasisFeaturesProvider } from './chunk-LR5CRY5A.js';
1
+ import { ElevasisFeaturesProvider } from './chunk-VQESMHQV.js';
2
2
  import { jsx } from 'react/jsx-runtime';
3
3
 
4
4
  function createTestFeaturesProvider({
@@ -0,0 +1,336 @@
1
+ import { useInitialization } from './chunk-DK2HVHCY.js';
2
+ import { useOrganization } from './chunk-DD3CCMCZ.js';
3
+ import { createContext, useMemo, useCallback, useContext } from 'react';
4
+ import { jsx } from 'react/jsx-runtime';
5
+
6
+ function createFeatureAccessHook({
7
+ useInitialization: useInitialization2,
8
+ useOrganization: useOrganization2
9
+ }) {
10
+ return function useFeatureAccess2() {
11
+ const { profile, organizationReady } = useInitialization2();
12
+ const { currentMembership } = useOrganization2();
13
+ const { orgConfig, membershipConfig } = useMemo(() => {
14
+ const organizationConfig = currentMembership?.organization?.config;
15
+ const memberConfig = currentMembership?.config;
16
+ return { orgConfig: organizationConfig, membershipConfig: memberConfig };
17
+ }, [currentMembership]);
18
+ const userConfig = profile?.config;
19
+ const checkFeature = useCallback(
20
+ (featureKey) => {
21
+ if (profile?.is_platform_admin) {
22
+ return { allowed: true, restrictedBy: null };
23
+ }
24
+ const membershipValue = membershipConfig?.features?.[featureKey];
25
+ if (membershipValue === false) return { allowed: false, restrictedBy: "membership" };
26
+ return { allowed: true, restrictedBy: null };
27
+ },
28
+ [profile?.is_platform_admin, membershipConfig]
29
+ );
30
+ const hasFeature = useCallback((featureKey) => checkFeature(featureKey).allowed, [checkFeature]);
31
+ return {
32
+ orgConfig,
33
+ membershipConfig,
34
+ userConfig,
35
+ hasFeature,
36
+ checkFeature,
37
+ isReady: organizationReady
38
+ };
39
+ };
40
+ }
41
+ var createUseFeatureAccess = createFeatureAccessHook;
42
+
43
+ // ../core/src/organization-model/helpers.ts
44
+ function defaultPathFor(id) {
45
+ return `/${id.replaceAll(".", "/")}`;
46
+ }
47
+ function parentIdOf(id) {
48
+ const index = id.lastIndexOf(".");
49
+ return index === -1 ? void 0 : id.slice(0, index);
50
+ }
51
+ function findById(features, id) {
52
+ return features.find((feature) => feature.id === id);
53
+ }
54
+ function findByPath(features, path) {
55
+ return features.find((feature) => (feature.path ?? defaultPathFor(feature.id)) === path);
56
+ }
57
+ function childrenOf(features, id) {
58
+ const prefix = `${id}.`;
59
+ return features.filter((feature) => feature.id.startsWith(prefix) && !feature.id.slice(prefix.length).includes("."));
60
+ }
61
+ function topLevel(features) {
62
+ return features.filter((feature) => !feature.id.includes("."));
63
+ }
64
+ function ancestorsOf(features, id) {
65
+ const segments = id.split(".");
66
+ const ids = segments.map((_, index) => segments.slice(0, index + 1).join("."));
67
+ return ids.map((ancestorId) => findById(features, ancestorId)).filter((feature) => Boolean(feature));
68
+ }
69
+ function parentOf(features, id) {
70
+ const parentId = parentIdOf(id);
71
+ return parentId ? findById(features, parentId) : void 0;
72
+ }
73
+ function inheritedValue(features, id, getValue) {
74
+ return ancestorsOf(features, id).slice().reverse().map(getValue).find((value) => value !== void 0);
75
+ }
76
+ function uiPositionFor(features, id) {
77
+ return inheritedValue(features, id, (feature) => feature.uiPosition);
78
+ }
79
+ function requiresAdminFor(features, id) {
80
+ return inheritedValue(features, id, (feature) => feature.requiresAdmin) ?? false;
81
+ }
82
+ function devOnlyFor(features, id) {
83
+ return inheritedValue(features, id, (feature) => feature.devOnly) ?? false;
84
+ }
85
+
86
+ // src/provider/resolvers/RouteResolver.ts
87
+ function normalizeRoutePath(path) {
88
+ const trimmedPath = path.trim();
89
+ if (!trimmedPath || trimmedPath === "/") {
90
+ return "/";
91
+ }
92
+ return trimmedPath.replace(/\/+$/, "") || "/";
93
+ }
94
+ function isRouteMatch(currentPath, route) {
95
+ const normalizedCurrentPath = normalizeRoutePath(currentPath);
96
+ const normalizedRoute = normalizeRoutePath(route);
97
+ return normalizedCurrentPath === normalizedRoute || normalizedCurrentPath.startsWith(`${normalizedRoute}/`);
98
+ }
99
+
100
+ // src/provider/resolvers/NavResolver.ts
101
+ function uniqueIds(ids) {
102
+ return ids ? [...new Set(ids)] : [];
103
+ }
104
+
105
+ // src/provider/validateManifests.ts
106
+ function validateManifests(manifests, organizationModel) {
107
+ if (!organizationModel) {
108
+ return;
109
+ }
110
+ const validFeatureIds = new Set(organizationModel.features.map((f) => f.id));
111
+ const errors = [];
112
+ for (const manifest of manifests) {
113
+ const key = manifest.key;
114
+ if (!validFeatureIds.has(manifest.featureId)) {
115
+ errors.push(
116
+ `Manifest "${key}": featureId "${manifest.featureId}" is not a known feature id. Valid values: ${[...validFeatureIds].sort().join(", ")}`
117
+ );
118
+ }
119
+ }
120
+ if (errors.length > 0) {
121
+ throw new Error(
122
+ `Feature manifest validation failed with ${errors.length} error(s):
123
+ ` + errors.map((e, i) => ` ${i + 1}. ${e}`).join("\n")
124
+ );
125
+ }
126
+ }
127
+ var useFeatureAccess = createFeatureAccessHook({
128
+ useInitialization,
129
+ useOrganization
130
+ });
131
+ var ElevasisFeaturesContext = createContext(null);
132
+ function useElevasisFeatures() {
133
+ const context = useContext(ElevasisFeaturesContext);
134
+ if (!context) {
135
+ throw new Error(
136
+ "useElevasisFeatures must be used within an ElevasisFeaturesProvider. Wrap your app (or the relevant subtree) with <ElevasisFeaturesProvider>."
137
+ );
138
+ }
139
+ return context;
140
+ }
141
+ function useOptionalElevasisFeatures() {
142
+ return useContext(ElevasisFeaturesContext);
143
+ }
144
+ function defaultFeatures(organizationModel) {
145
+ return organizationModel?.features ?? [];
146
+ }
147
+ function featurePath(feature) {
148
+ return feature.path ?? defaultPathFor(feature.id);
149
+ }
150
+ function isOrganizationModelFeatureEnabled(organizationModel, featureId) {
151
+ const feature = organizationModel?.features.find((f) => f.id === featureId);
152
+ return feature?.enabled;
153
+ }
154
+ function resolveFeatureModules(features, isFeatureEnabled) {
155
+ return features.map((feature) => {
156
+ const featureId = feature.featureId;
157
+ return {
158
+ ...feature,
159
+ access: {
160
+ featureId,
161
+ enabled: isFeatureEnabled(featureId)
162
+ },
163
+ semantics: {
164
+ capabilityIds: uniqueIds(feature.capabilityIds ?? [])
165
+ }
166
+ };
167
+ });
168
+ }
169
+ function buildShellFeatures(organizationModel, modules) {
170
+ const iconByFeatureId = new Map(modules.map((module) => [module.featureId, module.icon]));
171
+ return defaultFeatures(organizationModel).map((feature) => ({
172
+ ...feature,
173
+ iconComponent: iconByFeatureId.get(feature.id)
174
+ }));
175
+ }
176
+ function createShellModel(features) {
177
+ return {
178
+ features,
179
+ findByPath: (path) => findByPath(features, normalizeRoutePath(path)),
180
+ findById: (id) => findById(features, id),
181
+ childrenOf: (id) => childrenOf(features, id),
182
+ ancestorsOf: (id) => ancestorsOf(features, id),
183
+ parentOf: (id) => parentOf(features, id),
184
+ topLevel: () => topLevel(features),
185
+ uiPositionFor: (id) => uiPositionFor(features, id),
186
+ requiresAdminFor: (id) => requiresAdminFor(features, id),
187
+ devOnlyFor: (id) => devOnlyFor(features, id)
188
+ };
189
+ }
190
+ function resolveOrganizationGraphFeature(features, shellModel) {
191
+ for (const feature of features) {
192
+ const graphBridge = feature.organizationGraph;
193
+ if (!graphBridge) continue;
194
+ const node = shellModel.findById(graphBridge.featureId);
195
+ return {
196
+ available: Boolean(node),
197
+ featureId: graphBridge.featureId,
198
+ featurePath: node ? featurePath(node) : void 0
199
+ };
200
+ }
201
+ return {
202
+ available: false
203
+ };
204
+ }
205
+ function findMatchingNode(shellModel, currentPath) {
206
+ const normalizedPath = normalizeRoutePath(currentPath);
207
+ const exact = shellModel.findByPath(normalizedPath);
208
+ if (exact) return exact;
209
+ return [...shellModel.features].filter((feature) => {
210
+ const path = normalizeRoutePath(featurePath(feature));
211
+ return path !== "/" && isRouteMatch(normalizedPath, path);
212
+ }).sort((a, b) => featurePath(b).length - featurePath(a).length)[0];
213
+ }
214
+ function ownsNode(module, node) {
215
+ if (!node) return false;
216
+ return node.id === module.featureId || node.id.startsWith(`${module.featureId}.`);
217
+ }
218
+ function resolveRoute(features, shellModel, currentPath, disabledSubsectionPaths) {
219
+ const node = findMatchingNode(shellModel, currentPath);
220
+ const normalizedPath = normalizeRoutePath(currentPath);
221
+ if (disabledSubsectionPaths.some((disabledPath) => isRouteMatch(normalizedPath, disabledPath))) {
222
+ return {
223
+ status: "hidden",
224
+ path: currentPath,
225
+ node
226
+ };
227
+ }
228
+ const feature = features.find((candidate) => ownsNode(candidate, node));
229
+ if (!feature) {
230
+ return {
231
+ status: "unmatched",
232
+ path: currentPath,
233
+ node
234
+ };
235
+ }
236
+ return {
237
+ status: "matched",
238
+ path: currentPath,
239
+ feature,
240
+ node
241
+ };
242
+ }
243
+ function ElevasisFeaturesProvider({
244
+ features,
245
+ organizationModel,
246
+ timeRange,
247
+ operationsApiUrl,
248
+ operationsSSEManager,
249
+ deliveryApiUrl,
250
+ deliverySSEManager,
251
+ disabledSubsectionPaths = [],
252
+ children
253
+ }) {
254
+ useMemo(() => validateManifests(features, organizationModel), [features, organizationModel]);
255
+ const { hasFeature } = useFeatureAccess();
256
+ const hasResolvedFeature = useCallback(
257
+ (key) => {
258
+ if (!hasFeature(key)) {
259
+ return false;
260
+ }
261
+ const organizationModelFeatureEnabled = isOrganizationModelFeatureEnabled(organizationModel, key);
262
+ return organizationModelFeatureEnabled ?? true;
263
+ },
264
+ [hasFeature, organizationModel]
265
+ );
266
+ const shellFeatures = useMemo(() => buildShellFeatures(organizationModel, features), [organizationModel, features]);
267
+ const shellModel = useMemo(() => createShellModel(shellFeatures), [shellFeatures]);
268
+ const normalizedDisabledSubsectionPaths = useMemo(
269
+ () => [...new Set(disabledSubsectionPaths.map((path) => normalizeRoutePath(path)))],
270
+ [disabledSubsectionPaths]
271
+ );
272
+ const resolvedFeatures = useMemo(
273
+ () => resolveFeatureModules(features, hasResolvedFeature),
274
+ [features, hasResolvedFeature]
275
+ );
276
+ const enabledResolvedFeatures = useMemo(
277
+ () => resolvedFeatures.filter((feature) => feature.access.enabled),
278
+ [resolvedFeatures]
279
+ );
280
+ const organizationGraph = useMemo(
281
+ () => resolveOrganizationGraphFeature(enabledResolvedFeatures, shellModel),
282
+ [enabledResolvedFeatures, shellModel]
283
+ );
284
+ const getResolvedFeature = useCallback(
285
+ (key) => resolvedFeatures.find((feature) => feature.key === key),
286
+ [resolvedFeatures]
287
+ );
288
+ const isFeatureEnabled = useCallback((key) => hasResolvedFeature(key), [hasResolvedFeature]);
289
+ const resolveRouteByPath = useCallback(
290
+ (path) => resolveRoute(enabledResolvedFeatures, shellModel, path, normalizedDisabledSubsectionPaths),
291
+ [enabledResolvedFeatures, shellModel, normalizedDisabledSubsectionPaths]
292
+ );
293
+ const shellRuntime = useMemo(
294
+ () => ({
295
+ resolveRoute: resolveRouteByPath
296
+ }),
297
+ [resolveRouteByPath]
298
+ );
299
+ const value = useMemo(
300
+ () => ({
301
+ shellModel,
302
+ shellRuntime,
303
+ enabledResolvedFeatures,
304
+ resolvedFeatures,
305
+ organizationGraph,
306
+ organizationModel,
307
+ timeRange,
308
+ operationsApiUrl,
309
+ operationsSSEManager,
310
+ deliveryApiUrl,
311
+ deliverySSEManager,
312
+ disabledSubsectionPaths: normalizedDisabledSubsectionPaths,
313
+ isFeatureEnabled,
314
+ getResolvedFeature
315
+ }),
316
+ [
317
+ shellModel,
318
+ shellRuntime,
319
+ enabledResolvedFeatures,
320
+ resolvedFeatures,
321
+ organizationGraph,
322
+ organizationModel,
323
+ timeRange,
324
+ operationsApiUrl,
325
+ operationsSSEManager,
326
+ deliveryApiUrl,
327
+ deliverySSEManager,
328
+ normalizedDisabledSubsectionPaths,
329
+ isFeatureEnabled,
330
+ getResolvedFeature
331
+ ]
332
+ );
333
+ return /* @__PURE__ */ jsx(ElevasisFeaturesContext.Provider, { value, children });
334
+ }
335
+
336
+ export { ElevasisFeaturesProvider, createFeatureAccessHook, createUseFeatureAccess, useElevasisFeatures, useOptionalElevasisFeatures };
@@ -2,10 +2,10 @@ import { AppShellLoader } from './chunk-M25JL54Z.js';
2
2
  import { FilterBar } from './chunk-PDHTXPSF.js';
3
3
  import { CustomModal } from './chunk-GBMNCNHX.js';
4
4
  import { useAvailablePresets } from './chunk-TIIPYB2Z.js';
5
- import { useDeleteCredential, useCreateCredential, useCredentials, MEMBERSHIP_STATUS_COLORS, transformMembershipToTableRow, useUserMemberships, useUpdateWebhookEndpoint, useResources, useDeleteWebhookEndpoint, useCreateWebhookEndpoint, useListWebhookEndpoints, useUpdateMemberConfig, useOrganizationMembers, useUpdateCredential, CredentialSchemas } from './chunk-FMFX4K6E.js';
6
- import { showErrorNotification } from './chunk-M7W7CGPL.js';
7
- import { ListSkeleton, EmptyState, PageTitleCaption, CardHeader, APIErrorAlert, StatCard } from './chunk-BHR7IV72.js';
8
- import { formatDateTime, OAUTH_POPUP_CHECK_INTERVAL, OAUTH_FLOW_TIMEOUT } from './chunk-OD7GWIZS.js';
5
+ import { useDeleteCredential, useCreateCredential, useCredentials, MEMBERSHIP_STATUS_COLORS, transformMembershipToTableRow, useUserMemberships, useUpdateWebhookEndpoint, useResources, useDeleteWebhookEndpoint, useCreateWebhookEndpoint, useListWebhookEndpoints, useUpdateMemberConfig, useOrganizationMembers, useUpdateCredential, CredentialSchemas } from './chunk-7GG6OSD7.js';
6
+ import { showErrorNotification } from './chunk-Z6FAH4XV.js';
7
+ import { ListSkeleton, EmptyState, PageTitleCaption, CardHeader, APIErrorAlert, StatCard } from './chunk-XUYBOO32.js';
8
+ import { formatDateTime, OAUTH_POPUP_CHECK_INTERVAL, OAUTH_FLOW_TIMEOUT } from './chunk-SGXXJE52.js';
9
9
  import { useInitialization } from './chunk-DK2HVHCY.js';
10
10
  import { useElevasisServices } from './chunk-IRW7JMQ4.js';
11
11
  import { Table, Group, Text, Tooltip, ActionIcon, Stack, Title, Button, Select, TextInput, Alert, PasswordInput, Anchor, Paper, Card, Switch, Badge, Center, Loader, Box, Code, CopyButton, ThemeIcon, SimpleGrid, UnstyledButton, Divider, Textarea } from '@mantine/core';
@@ -1980,21 +1980,7 @@ function OAuthIntegrationsCard({ apiUrl }) {
1980
1980
  var settingsManifest = {
1981
1981
  key: "settings",
1982
1982
  featureId: "settings",
1983
- navEntry: {
1984
- label: "Settings",
1985
- icon: IconSettings,
1986
- link: "/settings/account",
1987
- dataOnboardingTourId: "settings-gear",
1988
- links: [
1989
- { label: "Account", link: "/settings/account" },
1990
- { label: "Appearance", link: "/settings/appearance" },
1991
- { label: "Organization", link: "/settings/organization" },
1992
- { label: "Credentials", link: "/settings/credentials" },
1993
- { label: "API Keys", link: "/settings/api-keys" },
1994
- { label: "Webhooks", link: "/settings/webhooks" },
1995
- { label: "Deployments", link: "/settings/deployments" }
1996
- ]
1997
- }
1983
+ icon: IconSettings
1998
1984
  };
1999
1985
 
2000
1986
  export { AccountSettings, AppearanceSettings, CreateCredentialModal, CreateWebhookEndpointModal, CredentialList, CredentialSettings, EditCredentialModal, EditWebhookEndpointModal, MemberConfigModal, MembershipFeaturePanel, MembershipStatusBadge, OAuthConnectModal, OAuthIntegrationsCard, OrgMembersList, OrganizationMembershipsList, OrganizationSettings, WebhookEndpointList, WebhookEndpointSettings, WebhookUrlDisplayModal, settingsManifest };
@@ -1,6 +1,6 @@
1
1
  import { StyledMarkdown } from './chunk-3KMDHCAR.js';
2
2
  import { useRouterContext } from './chunk-Q7DJKLEN.js';
3
- import { getErrorInfo, getErrorTitle, getResourceIcon, formatTimeAgo } from './chunk-OD7GWIZS.js';
3
+ import { getErrorInfo, getErrorTitle, getResourceIcon, formatTimeAgo } from './chunk-SGXXJE52.js';
4
4
  import { ResourceStatusColors } from './chunk-KRWALB24.js';
5
5
  import { useAuthContext } from './chunk-BRJ3QZ4E.js';
6
6
  import { Center, Stack, Title, Text, Button, Box, Loader, Badge, Group, Collapse, ScrollArea, Card, Select, Alert, Code, ThemeIcon, Paper, Grid, Timeline, Space } from '@mantine/core';
@@ -1,4 +1,4 @@
1
- import { getErrorInfo, formatErrorMessage, getErrorTitle } from './chunk-OD7GWIZS.js';
1
+ import { getErrorInfo, formatErrorMessage, getErrorTitle } from './chunk-SGXXJE52.js';
2
2
  import { useElevasisServices } from './chunk-IRW7JMQ4.js';
3
3
  import { useQuery, useQueryClient, useMutation } from '@tanstack/react-query';
4
4
  import { notifications } from '@mantine/notifications';